diff options
Diffstat (limited to 'servers')
175 files changed, 20739 insertions, 16005 deletions
diff --git a/servers/SCsub b/servers/SCsub index d861847101..eefa6278c4 100644 --- a/servers/SCsub +++ b/servers/SCsub @@ -1,17 +1,19 @@ +#!/usr/bin/env python + Import('env') -env.servers_sources=[] -env.add_source_files(env.servers_sources,"*.cpp") +env.servers_sources = [] +env.add_source_files(env.servers_sources, "*.cpp") Export('env') -SConscript('physics/SCsub'); -SConscript('physics_2d/SCsub'); -SConscript('visual/SCsub'); -SConscript('audio/SCsub'); -SConscript('spatial_sound/SCsub'); -SConscript('spatial_sound_2d/SCsub'); +SConscript('physics/SCsub') +SConscript('physics_2d/SCsub') +SConscript('visual/SCsub') +SConscript('audio/SCsub') +SConscript('spatial_sound/SCsub') +SConscript('spatial_sound_2d/SCsub') -lib = env.Library("servers",env.servers_sources) +lib = env.Library("servers", env.servers_sources) env.Prepend(LIBS=[lib]) diff --git a/servers/audio/SCsub b/servers/audio/SCsub index d31af2c1c4..afaffcfe93 100644 --- a/servers/audio/SCsub +++ b/servers/audio/SCsub @@ -1,5 +1,9 @@ +#!/usr/bin/env python + Import('env') -env.add_source_files(env.servers_sources,"*.cpp") +env.add_source_files(env.servers_sources, "*.cpp") Export('env') + +SConscript("effects/SCsub") diff --git a/servers/audio/audio_driver_dummy.cpp b/servers/audio/audio_driver_dummy.cpp index d0695451b9..6c12957851 100644 --- a/servers/audio/audio_driver_dummy.cpp +++ b/servers/audio/audio_driver_dummy.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -28,7 +28,7 @@ /*************************************************************************/ #include "audio_driver_dummy.h" -#include "globals.h" +#include "global_config.h" #include "os/os.h" @@ -43,7 +43,7 @@ Error AudioDriverDummy::init() { mix_rate = 44100; - output_format = OUTPUT_STEREO; + speaker_mode = SPEAKER_MODE_STEREO; channels = 2; int latency = GLOBAL_DEF("audio/output_latency",25); @@ -97,16 +97,18 @@ int AudioDriverDummy::get_mix_rate() const { return mix_rate; }; -AudioDriverSW::OutputFormat AudioDriverDummy::get_output_format() const { +AudioDriver::SpeakerMode AudioDriverDummy::get_speaker_mode() const { - return output_format; + return speaker_mode; }; + void AudioDriverDummy::lock() { if (!thread || !mutex) return; mutex->lock(); }; + void AudioDriverDummy::unlock() { if (!thread || !mutex) diff --git a/servers/audio/audio_driver_dummy.h b/servers/audio/audio_driver_dummy.h index 9421574f93..78ec41ea09 100644 --- a/servers/audio/audio_driver_dummy.h +++ b/servers/audio/audio_driver_dummy.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -29,13 +29,13 @@ #ifndef AUDIO_DRIVER_DUMMY_H #define AUDIO_DRIVER_DUMMY_H -#include "servers/audio/audio_server_sw.h" +#include "servers/audio_server.h" #include "core/os/thread.h" #include "core/os/mutex.h" -class AudioDriverDummy : public AudioDriverSW { +class AudioDriverDummy : public AudioDriver { Thread* thread; Mutex* mutex; @@ -46,7 +46,7 @@ class AudioDriverDummy : public AudioDriverSW { int buffer_size; unsigned int mix_rate; - OutputFormat output_format; + SpeakerMode speaker_mode; int channels; @@ -64,7 +64,7 @@ public: virtual Error init(); virtual void start(); virtual int get_mix_rate() const; - virtual OutputFormat get_output_format() const; + virtual SpeakerMode get_speaker_mode() const; virtual void lock(); virtual void unlock(); virtual void finish(); diff --git a/servers/audio/audio_effect.cpp b/servers/audio/audio_effect.cpp new file mode 100644 index 0000000000..372c0cbc13 --- /dev/null +++ b/servers/audio/audio_effect.cpp @@ -0,0 +1,6 @@ +#include "audio_effect.h" + +AudioEffect::AudioEffect() +{ + +} diff --git a/servers/audio/audio_effect.h b/servers/audio/audio_effect.h new file mode 100644 index 0000000000..02eb258f99 --- /dev/null +++ b/servers/audio/audio_effect.h @@ -0,0 +1,26 @@ +#ifndef AUDIOEFFECT_H +#define AUDIOEFFECT_H + +#include "audio_frame.h" +#include "resource.h" + + +class AudioEffectInstance : public Reference { + GDCLASS(AudioEffectInstance,Reference) + +public: + + virtual void process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count)=0; + +}; + + +class AudioEffect : public Resource { + GDCLASS(AudioEffect,Resource) +public: + + virtual Ref<AudioEffectInstance> instance()=0; + AudioEffect(); +}; + +#endif // AUDIOEFFECT_H diff --git a/servers/audio/audio_filter_sw.cpp b/servers/audio/audio_filter_sw.cpp index 3fb8e8f734..e97eb75d04 100644 --- a/servers/audio/audio_filter_sw.cpp +++ b/servers/audio/audio_filter_sw.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -142,9 +142,9 @@ void AudioFilterSW::prepare_coefficients(Coeffs *p_coeffs) { //this one is extra tricky double hicutoff=resonance; double centercutoff = (cutoff+resonance)/2.0; - double bandwidth=(Math::log(centercutoff)-Math::log(hicutoff))/Math::log(2); + double bandwidth=(Math::log(centercutoff)-Math::log(hicutoff))/Math::log((double)2); omega=2.0*Math_PI*centercutoff/sampling_rate; - alpha = Math::sin(omega)*Math::sinh( Math::log(2)/2 * bandwidth * omega/Math::sin(omega) ); + alpha = Math::sin(omega)*Math::sinh( Math::log((double)2)/2 * bandwidth * omega/Math::sin(omega) ); a0=1+alpha; p_coeffs->b0 = alpha; diff --git a/servers/audio/audio_filter_sw.h b/servers/audio/audio_filter_sw.h index d4d225ce29..b711944ca8 100644 --- a/servers/audio/audio_filter_sw.h +++ b/servers/audio/audio_filter_sw.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -65,7 +65,7 @@ public: void set_filter(AudioFilterSW * p_filter); void process(float *p_samples,int p_amount, int p_stride=1); void update_coeffs(); - inline void process_one(float& p_sample); + _ALWAYS_INLINE_ void process_one(float& p_sample); Processor(); }; diff --git a/servers/audio/audio_mixer_sw.cpp b/servers/audio/audio_mixer_sw.cpp deleted file mode 100644 index 17f8c36c9a..0000000000 --- a/servers/audio/audio_mixer_sw.cpp +++ /dev/null @@ -1,1222 +0,0 @@ -/*************************************************************************/ -/* audio_mixer_sw.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "audio_mixer_sw.h" -#include "print_string.h" -#include "os/os.h" -//TODO implement FAST_AUDIO macro - -#ifdef FAST_AUDIO -#define NO_REVERB -#endif - -template<class Depth,bool is_stereo,bool is_ima_adpcm,bool use_filter,bool use_fx,AudioMixerSW::InterpolationType type,AudioMixerSW::MixChannels mix_mode> -void AudioMixerSW::do_resample(const Depth* p_src, int32_t *p_dst, ResamplerState *p_state) { - - // this function will be compiled branchless by any decent compiler - - int32_t final,final_r,next,next_r; - int32_t *reverb_dst = p_state->reverb_buffer; - while (p_state->amount--) { - - int32_t pos=p_state->pos >> MIX_FRAC_BITS; - if (is_stereo && !is_ima_adpcm) - pos<<=1; - - if (is_ima_adpcm) { - - int sample_pos = pos + p_state->ima_adpcm[0].window_ofs; - - while(sample_pos>p_state->ima_adpcm[0].last_nibble) { - - - static const int16_t _ima_adpcm_step_table[89] = { - 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, - 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, - 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, - 130, 143, 157, 173, 190, 209, 230, 253, 279, 307, - 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, - 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, - 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358, - 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, - 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767 - }; - - static const int8_t _ima_adpcm_index_table[16] = { - -1, -1, -1, -1, 2, 4, 6, 8, - -1, -1, -1, -1, 2, 4, 6, 8 - }; - - for(int i=0;i<(is_stereo?2:1);i++) { - - - int16_t nibble,diff,step; - - p_state->ima_adpcm[i].last_nibble++; - const uint8_t *src_ptr=p_state->ima_adpcm[i].ptr; - - - uint8_t nbb = src_ptr[ (p_state->ima_adpcm[i].last_nibble>>1) * (is_stereo?2:1) + i ]; - nibble = (p_state->ima_adpcm[i].last_nibble&1)?(nbb>>4):(nbb&0xF); - step=_ima_adpcm_step_table[p_state->ima_adpcm[i].step_index]; - - - p_state->ima_adpcm[i].step_index += _ima_adpcm_index_table[nibble]; - if (p_state->ima_adpcm[i].step_index<0) - p_state->ima_adpcm[i].step_index=0; - if (p_state->ima_adpcm[i].step_index>88) - p_state->ima_adpcm[i].step_index=88; - - diff = step >> 3 ; - if (nibble & 1) - diff += step >> 2 ; - if (nibble & 2) - diff += step >> 1 ; - if (nibble & 4) - diff += step ; - if (nibble & 8) - diff = -diff ; - - p_state->ima_adpcm[i].predictor+=diff; - if (p_state->ima_adpcm[i].predictor<-0x8000) - p_state->ima_adpcm[i].predictor=-0x8000; - else if (p_state->ima_adpcm[i].predictor>0x7FFF) - p_state->ima_adpcm[i].predictor=0x7FFF; - - - /* store loop if there */ - if (p_state->ima_adpcm[i].last_nibble==p_state->ima_adpcm[i].loop_pos) { - - p_state->ima_adpcm[i].loop_step_index = p_state->ima_adpcm[i].step_index; - p_state->ima_adpcm[i].loop_predictor = p_state->ima_adpcm[i].predictor; - } - - //printf("%i - %i - pred %i\n",int(p_state->ima_adpcm[i].last_nibble),int(nibble),int(p_state->ima_adpcm[i].predictor)); - - } - - } - - final=p_state->ima_adpcm[0].predictor; - if (is_stereo) { - final_r=p_state->ima_adpcm[1].predictor; - } - - } else { - final=p_src[pos]; - if (is_stereo) - final_r=p_src[pos+1]; - - if (sizeof(Depth)==1) { /* conditions will not exist anymore when compiled! */ - final<<=8; - if (is_stereo) - final_r<<=8; - } - - if (type==INTERPOLATION_LINEAR) { - - if (is_stereo) { - - next=p_src[pos+2]; - next_r=p_src[pos+3]; - } else { - next=p_src[pos+1]; - } - - if (sizeof(Depth)==1) { - next<<=8; - if (is_stereo) - next_r<<=8; - } - - int32_t frac=int32_t(p_state->pos&MIX_FRAC_MASK); - - final=final+((next-final)*frac >> MIX_FRAC_BITS); - if (is_stereo) - final_r=final_r+((next_r-final_r)*frac >> MIX_FRAC_BITS); - } - } - - if (use_filter) { - - Channel::Mix::Filter *f = p_state->filter_l; - float finalf=final; - float pre = finalf; - finalf = ((finalf*p_state->coefs.b0) + (f->hb[0]*p_state->coefs.b1) + (f->hb[1]*p_state->coefs.b2) + (f->ha[0]*p_state->coefs.a1) + (f->ha[1]*p_state->coefs.a2) - ); - - f->ha[1]=f->ha[0]; - f->hb[1]=f->hb[0]; - f->hb[0]=pre; - f->ha[0]=finalf; - - final=Math::fast_ftoi(finalf); - - if (is_stereo) { - - f = p_state->filter_r; - finalf=final_r; - pre = finalf; - finalf = ((finalf*p_state->coefs.b0) + (f->hb[0]*p_state->coefs.b1) + (f->hb[1]*p_state->coefs.b2) + (f->ha[0]*p_state->coefs.a1) + (f->ha[1]*p_state->coefs.a2) - ); - f->ha[1]=f->ha[0]; - f->hb[1]=f->hb[0]; - f->hb[0]=pre; - f->ha[0]=finalf; - - final_r=Math::fast_ftoi(finalf); - - } - - p_state->coefs.b0+=p_state->coefs_inc.b0; - p_state->coefs.b1+=p_state->coefs_inc.b1; - p_state->coefs.b2+=p_state->coefs_inc.b2; - p_state->coefs.a1+=p_state->coefs_inc.a1; - p_state->coefs.a2+=p_state->coefs_inc.a2; - } - - if (!is_stereo) { - final_r=final; //copy to right channel if stereo - } - - //convert back to 24 bits and mix to buffers - - if (mix_mode==MIX_STEREO) { - *p_dst++ +=(final*(p_state->vol[0]>>MIX_VOLRAMP_FRAC_BITS))>>MIX_VOL_MOVE_TO_24; - *p_dst++ +=(final_r*(p_state->vol[1]>>MIX_VOLRAMP_FRAC_BITS))>>MIX_VOL_MOVE_TO_24; - - p_state->vol[0]+=p_state->vol_inc[0]; - p_state->vol[1]+=p_state->vol_inc[1]; - - if (use_fx) { - *reverb_dst++ +=(final*(p_state->reverb_vol[0]>>MIX_VOLRAMP_FRAC_BITS))>>MIX_VOL_MOVE_TO_24; - *reverb_dst++ +=(final_r*(p_state->reverb_vol[1]>>MIX_VOLRAMP_FRAC_BITS))>>MIX_VOL_MOVE_TO_24; - p_state->reverb_vol[0]+=p_state->reverb_vol_inc[0]; - p_state->reverb_vol[1]+=p_state->reverb_vol_inc[1]; - } - - - } else if (mix_mode==MIX_QUAD) { - - *p_dst++ +=(final*(p_state->vol[0]>>MIX_VOLRAMP_FRAC_BITS))>>MIX_VOL_MOVE_TO_24; - *p_dst++ +=(final_r*(p_state->vol[1]>>MIX_VOLRAMP_FRAC_BITS))>>MIX_VOL_MOVE_TO_24; - - *p_dst++ +=(final*(p_state->vol[2]>>MIX_VOLRAMP_FRAC_BITS))>>MIX_VOL_MOVE_TO_24; - *p_dst++ +=(final_r*(p_state->vol[3]>>MIX_VOLRAMP_FRAC_BITS))>>MIX_VOL_MOVE_TO_24; - - p_state->vol[0]+=p_state->vol_inc[0]; - p_state->vol[1]+=p_state->vol_inc[1]; - p_state->vol[2]+=p_state->vol_inc[2]; - p_state->vol[3]+=p_state->vol_inc[3]; - - if (use_fx) { - *reverb_dst++ +=(final*(p_state->reverb_vol[0]>>MIX_VOLRAMP_FRAC_BITS))>>MIX_VOL_MOVE_TO_24; - *reverb_dst++ +=(final_r*(p_state->reverb_vol[1]>>MIX_VOLRAMP_FRAC_BITS))>>MIX_VOL_MOVE_TO_24; - *reverb_dst++ +=(final*(p_state->reverb_vol[2]>>MIX_VOLRAMP_FRAC_BITS))>>MIX_VOL_MOVE_TO_24; - *reverb_dst++ +=(final_r*(p_state->reverb_vol[3]>>MIX_VOLRAMP_FRAC_BITS))>>MIX_VOL_MOVE_TO_24; - p_state->reverb_vol[0]+=p_state->reverb_vol_inc[0]; - p_state->reverb_vol[1]+=p_state->reverb_vol_inc[1]; - p_state->reverb_vol[2]+=p_state->reverb_vol_inc[2]; - p_state->reverb_vol[3]+=p_state->reverb_vol_inc[3]; - } - } - - p_state->pos+=p_state->increment; - } -} - - -void AudioMixerSW::mix_channel(Channel& c) { - - - if (!sample_manager->is_sample(c.sample)) { - // sample is gone! - c.active=false; - return; - } - - - /* some 64-bit fixed point precaches */ - - int64_t loop_begin_fp=((int64_t)sample_manager->sample_get_loop_begin(c.sample) << MIX_FRAC_BITS); - int64_t loop_end_fp=((int64_t)sample_manager->sample_get_loop_end(c.sample) << MIX_FRAC_BITS); - int64_t length_fp=((int64_t)sample_manager->sample_get_length(c.sample) << MIX_FRAC_BITS); - int64_t begin_limit=(sample_manager->sample_get_loop_format(c.sample)!=AS::SAMPLE_LOOP_NONE)?loop_begin_fp:0; - int64_t end_limit=(sample_manager->sample_get_loop_format(c.sample)!=AS::SAMPLE_LOOP_NONE)?loop_end_fp:length_fp; - bool is_stereo=sample_manager->sample_is_stereo(c.sample); - - int32_t todo=mix_chunk_size; -// int mixed=0; - bool use_filter=false; - - ResamplerState rstate; - - /* compute voume ramps, increment, etc */ - - - - for(int i=0;i<mix_channels;i++) { - c.mix.old_vol[i]=c.mix.vol[i]; - c.mix.old_reverb_vol[i]=c.mix.reverb_vol[i]; - c.mix.old_chorus_vol[i]=c.mix.chorus_vol[i]; - } - - float vol = c.vol*channel_nrg; - - float reverb_vol = c.reverb_send*channel_nrg; - float chorus_vol = c.chorus_send*channel_nrg; - - if (mix_channels==2) { - //stereo pan - float pan = c.pan * 0.5 + 0.5; - float panv[2]={ - (1.0 - pan)*(1<<MIX_VOL_FRAC_BITS), - (pan)*(1<<MIX_VOL_FRAC_BITS) - }; - - for(int i=0;i<2;i++) { - - c.mix.vol[i]=Math::fast_ftoi(vol*panv[i]); - c.mix.reverb_vol[i]=Math::fast_ftoi(reverb_vol*panv[i]); - c.mix.chorus_vol[i]=Math::fast_ftoi(chorus_vol*panv[i]); - } - - } else { - //qudra pan - float panx = c.pan * 0.5 + 0.5; - float pany = c.depth * 0.5 + 0.5; - // with this model every speaker plays at 0.25 energy at the center.. i'm not sure if it's correct but it seems to be balanced - float panv[4]={ - (1.0-pany)*(1.0-panx)*(1<<MIX_VOL_FRAC_BITS), - (1.0-pany)*( panx)*(1<<MIX_VOL_FRAC_BITS), - ( pany)*(1.0-panx)*(1<<MIX_VOL_FRAC_BITS), - ( pany)*( panx)*(1<<MIX_VOL_FRAC_BITS) - }; - - for(int i=0;i<4;i++) { - - c.mix.vol[i]=Math::fast_ftoi(vol*panv[i]); - c.mix.reverb_vol[i]=Math::fast_ftoi(reverb_vol*panv[i]); - c.mix.chorus_vol[i]=Math::fast_ftoi(chorus_vol*panv[i]); - } - - } - - if (c.first_mix) { // avoid ramp up - - for(int i=0;i<mix_channels;i++) { - c.mix.old_vol[i]=c.mix.vol[i]; - c.mix.old_reverb_vol[i]=c.mix.reverb_vol[i]; - c.mix.old_chorus_vol[i]=c.mix.chorus_vol[i]; - } - - c.first_mix=false; - } - - - - Channel::Filter::Coefs filter_coefs; - Channel::Filter::Coefs filter_inc; - - if (c.filter.type!=AudioMixer::FILTER_NONE) { - - filter_coefs=c.filter.old_coefs; - filter_inc.b0=(c.filter.coefs.b0-filter_coefs.b0)/(1<<mix_chunk_bits); - filter_inc.b1=(c.filter.coefs.b1-filter_coefs.b1)/(1<<mix_chunk_bits); - filter_inc.b2=(c.filter.coefs.b2-filter_coefs.b2)/(1<<mix_chunk_bits); - filter_inc.a1=(c.filter.coefs.a1-filter_coefs.a1)/(1<<mix_chunk_bits); - filter_inc.a2=(c.filter.coefs.a2-filter_coefs.a2)/(1<<mix_chunk_bits); - use_filter=true; - } - - if (c.mix.increment>0) - c.mix.increment=((int64_t)c.speed<<MIX_FRAC_BITS)/mix_rate; - else - c.mix.increment=-((int64_t)c.speed<<MIX_FRAC_BITS)/mix_rate; - - //volume ramp - - - for(int i=0;i<mix_channels;i++) { - rstate.vol_inc[i]=((c.mix.vol[i]-c.mix.old_vol[i])<<MIX_VOLRAMP_FRAC_BITS)>>mix_chunk_bits; - rstate.vol[i]=c.mix.old_vol[i]<<MIX_VOLRAMP_FRAC_BITS; - rstate.reverb_vol_inc[i]=((c.mix.reverb_vol[i]-c.mix.old_reverb_vol[i])<<MIX_VOLRAMP_FRAC_BITS)>>mix_chunk_bits; - rstate.reverb_vol[i]=c.mix.old_reverb_vol[i]<<MIX_VOLRAMP_FRAC_BITS; - rstate.chorus_vol_inc[i]=((c.mix.chorus_vol[i]-c.mix.old_chorus_vol[i])<<MIX_VOLRAMP_FRAC_BITS)>>mix_chunk_bits; - rstate.chorus_vol[i]=c.mix.old_chorus_vol[i]<<MIX_VOLRAMP_FRAC_BITS; - } - - - //looping - - AS::SampleLoopFormat loop_format=sample_manager->sample_get_loop_format(c.sample); - AS::SampleFormat format=sample_manager->sample_get_format(c.sample); - - bool use_fx=false; - - if (fx_enabled) { - - for(int i=0;i<mix_channels;i++) { - if (c.mix.old_reverb_vol[i] || c.mix.reverb_vol[i] || c.mix.old_chorus_vol[i] || c.mix.chorus_vol[i] ) { - use_fx=true; - break; - } - } - } - - /* audio data */ - - const void *data=sample_manager->sample_get_data_ptr(c.sample); - int32_t *dst_buff=mix_buffer; - -#ifndef NO_REVERB - rstate.reverb_buffer=reverb_state[c.reverb_room].buffer; -#endif - - /* @TODO validar loops al registrar? */ - - rstate.coefs=filter_coefs; - rstate.coefs_inc=filter_inc; - rstate.filter_l=&c.mix.filter_l; - rstate.filter_r=&c.mix.filter_r; - - if (format==AS::SAMPLE_FORMAT_IMA_ADPCM) { - - rstate.ima_adpcm=c.mix.ima_adpcm; - if (loop_format!=AS::SAMPLE_LOOP_NONE) { - c.mix.ima_adpcm[0].loop_pos=loop_begin_fp>>MIX_FRAC_BITS; - c.mix.ima_adpcm[1].loop_pos=loop_begin_fp>>MIX_FRAC_BITS; - loop_format=AS::SAMPLE_LOOP_FORWARD; - } - } - - while (todo>0) { - - int64_t limit=0; - int32_t target=0,aux=0; - - /** LOOP CHECKING **/ - - if ( c.mix.increment < 0 ) { - /* going backwards */ - - if ( loop_format!=AS::SAMPLE_LOOP_NONE && c.mix.offset < loop_begin_fp ) { - /* loopstart reached */ - if ( loop_format==AS::SAMPLE_LOOP_PING_PONG ) { - /* bounce ping pong */ - c.mix.offset= loop_begin_fp + ( loop_begin_fp-c.mix.offset ); - c.mix.increment=-c.mix.increment; - } else { - /* go to loop-end */ - c.mix.offset=loop_end_fp-(loop_begin_fp-c.mix.offset); - } - } else { - /* check for sample not reaching begining */ - if(c.mix.offset < 0) { - - c.active=false; - break; - } - } - } else { - /* going forward */ - if( loop_format!=AS::SAMPLE_LOOP_NONE && c.mix.offset >= loop_end_fp ) { - /* loopend reached */ - - if ( loop_format==AS::SAMPLE_LOOP_PING_PONG ) { - /* bounce ping pong */ - c.mix.offset=loop_end_fp-(c.mix.offset-loop_end_fp); - c.mix.increment=-c.mix.increment; - } else { - /* go to loop-begin */ - - if (format==AS::SAMPLE_FORMAT_IMA_ADPCM) { - for(int i=0;i<2;i++) { - c.mix.ima_adpcm[i].step_index=c.mix.ima_adpcm[i].loop_step_index; - c.mix.ima_adpcm[i].predictor=c.mix.ima_adpcm[i].loop_predictor; - c.mix.ima_adpcm[i].last_nibble=loop_begin_fp>>MIX_FRAC_BITS; - } - c.mix.offset=loop_begin_fp; - } else { - c.mix.offset=loop_begin_fp+(c.mix.offset-loop_end_fp); - } - - } - } else { - /* no loop, check for end of sample */ - if(c.mix.offset >= length_fp) { - - c.active=false; - break; - } - } - } - - /** MIXCOUNT COMPUTING **/ - - /* next possible limit (looppoints or sample begin/end */ - limit=(c.mix.increment < 0) ?begin_limit:end_limit; - - /* compute what is shorter, the todo or the limit? */ - aux=(limit-c.mix.offset)/c.mix.increment+1; - target=(aux<todo)?aux:todo; /* mix target is the shorter buffer */ - - /* check just in case */ - if ( target<=0 ) { - c.active=false; - break; - } - - todo-=target; - - int32_t offset=c.mix.offset&mix_chunk_mask; /* strip integer */ - c.mix.offset-=offset; - - rstate.increment=c.mix.increment; - rstate.amount=target; - rstate.pos=offset; - -/* Macros to call the resample function for all possibilities, creating a dedicated-non branchy function call for each thanks to template magic*/ - -#define CALL_RESAMPLE_FUNC( m_depth, m_stereo, m_ima_adpcm, m_use_filter, m_use_fx, m_interp, m_mode)\ - do_resample<m_depth,m_stereo,m_ima_adpcm, m_use_filter,m_use_fx,m_interp, m_mode>(\ - src_ptr,\ - dst_buff,&rstate); - - -#define CALL_RESAMPLE_INTERP( m_depth, m_stereo, m_ima_adpcm, m_use_filter, m_use_fx, m_interp, m_mode)\ - if(m_interp==INTERPOLATION_RAW) {\ - CALL_RESAMPLE_FUNC(m_depth,m_stereo, m_ima_adpcm,m_use_filter,m_use_fx,INTERPOLATION_RAW,m_mode);\ - } else if(m_interp==INTERPOLATION_LINEAR) {\ - CALL_RESAMPLE_FUNC(m_depth,m_stereo, m_ima_adpcm,m_use_filter,m_use_fx,INTERPOLATION_LINEAR,m_mode);\ - } else if(m_interp==INTERPOLATION_CUBIC) {\ - CALL_RESAMPLE_FUNC(m_depth,m_stereo, m_ima_adpcm,m_use_filter,m_use_fx,INTERPOLATION_CUBIC,m_mode);\ - }\ - -#define CALL_RESAMPLE_FX( m_depth, m_stereo, m_ima_adpcm, m_use_filter, m_use_fx, m_interp, m_mode)\ - if(m_use_fx) {\ - CALL_RESAMPLE_INTERP(m_depth,m_stereo, m_ima_adpcm,m_use_filter,true,m_interp, m_mode);\ - } else {\ - CALL_RESAMPLE_INTERP(m_depth,m_stereo, m_ima_adpcm,m_use_filter,false,m_interp, m_mode);\ - }\ - - -#define CALL_RESAMPLE_FILTER( m_depth, m_stereo, m_ima_adpcm, m_use_filter, m_use_fx, m_interp, m_mode)\ - if(m_use_filter) {\ - CALL_RESAMPLE_FX(m_depth,m_stereo, m_ima_adpcm,true,m_use_fx,m_interp, m_mode);\ - } else {\ - CALL_RESAMPLE_FX(m_depth,m_stereo, m_ima_adpcm,false,m_use_fx,m_interp, m_mode);\ - }\ - -#define CALL_RESAMPLE_STEREO( m_depth, m_stereo, m_ima_adpcm, m_use_filter, m_use_fx, m_interp, m_mode)\ - if(m_stereo) {\ - CALL_RESAMPLE_FILTER(m_depth,true,m_ima_adpcm, m_use_filter,m_use_fx,m_interp, m_mode);\ - } else {\ - CALL_RESAMPLE_FILTER(m_depth,false,m_ima_adpcm,m_use_filter,m_use_fx,m_interp, m_mode);\ - }\ - -#define CALL_RESAMPLE_MODE( m_depth, m_stereo, m_ima_adpcm, m_use_filter, m_use_fx, m_interp, m_mode)\ - if(m_mode==MIX_STEREO) {\ - CALL_RESAMPLE_STEREO(m_depth,m_stereo, m_ima_adpcm,m_use_filter,m_use_fx,m_interp, MIX_STEREO);\ - } else {\ - CALL_RESAMPLE_STEREO(m_depth,m_stereo, m_ima_adpcm,m_use_filter,m_use_fx,m_interp, MIX_QUAD);\ - }\ - - - - - if (format==AS::SAMPLE_FORMAT_PCM8) { - - int8_t *src_ptr = &((int8_t*)data)[(c.mix.offset >> MIX_FRAC_BITS)<<(is_stereo?1:0) ]; - CALL_RESAMPLE_MODE(int8_t,is_stereo,false,use_filter,use_fx,interpolation_type,mix_channels); - - } else if (format==AS::SAMPLE_FORMAT_PCM16) { - int16_t *src_ptr = &((int16_t*)data)[(c.mix.offset >> MIX_FRAC_BITS)<<(is_stereo?1:0) ]; - CALL_RESAMPLE_MODE(int16_t,is_stereo,false,use_filter,use_fx,interpolation_type,mix_channels); - - } else if (format==AS::SAMPLE_FORMAT_IMA_ADPCM) { - for(int i=0;i<2;i++) { - c.mix.ima_adpcm[i].window_ofs=c.mix.offset>>MIX_FRAC_BITS; - c.mix.ima_adpcm[i].ptr=(const uint8_t*)data; - } - int8_t *src_ptr = NULL; - CALL_RESAMPLE_MODE(int8_t,is_stereo,true,use_filter,use_fx,interpolation_type,mix_channels); - - } - - c.mix.offset+=rstate.pos; - dst_buff+=target*mix_channels; - rstate.reverb_buffer+=target*mix_channels; - } - - c.filter.old_coefs=c.filter.coefs; -} - -void AudioMixerSW::mix_chunk() { - - ERR_FAIL_COND(mix_chunk_left); - - inside_mix=true; - - // emit tick in usecs - for (int i=0;i<mix_chunk_size*mix_channels;i++) { - - mix_buffer[i]=0; - } -#ifndef NO_REVERB - for(int i=0;i<max_reverbs;i++) - reverb_state[i].used_in_chunk=false; -#endif - - - audio_mixer_chunk_call(mix_chunk_size); - - int ac=0; - for (int i=0;i<MAX_CHANNELS;i++) { - - if (!channels[i].active) - continue; - ac++; - - /* process volume */ - Channel&c=channels[i]; -#ifndef NO_REVERB - bool has_reverb = c.reverb_send>CMP_EPSILON && fx_enabled; - if (has_reverb || c.had_prev_reverb) { - - if (!reverb_state[c.reverb_room].used_in_chunk) { - //zero the room - int32_t *buff = reverb_state[c.reverb_room].buffer; - int len = mix_chunk_size*mix_channels; - for (int j=0;j<len;j++) { - - buff[j]=0; // buffer in use, clear it for appending - } - reverb_state[c.reverb_room].used_in_chunk=true; - } - } -#else - bool has_reverb = false; -#endif - bool has_chorus = c.chorus_send>CMP_EPSILON && fx_enabled; - - - mix_channel(c); - - c.had_prev_reverb=has_reverb; - c.had_prev_chorus=has_chorus; - - } - - //process reverb -#ifndef NO_REVERB - if (fx_enabled) { - - - for(int i=0;i<max_reverbs;i++) { - - if (!reverb_state[i].enabled && !reverb_state[i].used_in_chunk) - continue; //this reverb is not in use - - int32_t *src=NULL; - - if (reverb_state[i].used_in_chunk) - src=reverb_state[i].buffer; - else - src=zero_buffer; - - bool in_use=false; - - int passes=mix_channels/2; - - for(int j=0;j<passes;j++) { - - if (reverb_state[i].reverb[j].process((int*)&src[j*2],(int*)&mix_buffer[j*2],mix_chunk_size,passes)) - in_use=true; - } - - if (in_use) { - reverb_state[i].enabled=true; - reverb_state[i].frames_idle=0; - //copy data over - - } else { - reverb_state[i].frames_idle+=mix_chunk_size; - if (false) { // go idle because too many frames passed - //disable this reverb, as nothing important happened on it - reverb_state[i].enabled=false; - reverb_state[i].frames_idle=0; - } - } - - } - } -#endif - mix_chunk_left=mix_chunk_size; - inside_mix=false; -} - -int AudioMixerSW::mix(int32_t *p_buffer,int p_frames) { - - int todo=p_frames; - int mixes=0; - - while(todo) { - - - if (!mix_chunk_left) { - - if (step_callback) - step_callback(step_udata); - mix_chunk(); - mixes++; - } - - int to_mix=MIN(mix_chunk_left,todo); - int from=mix_chunk_size-mix_chunk_left; - - for (int i=0;i<to_mix*2;i++) { - - (*p_buffer++)=mix_buffer[from*2+i]; - } - - mix_chunk_left-=to_mix; - todo-=to_mix; - } - - return mixes; -} - -uint64_t AudioMixerSW::get_step_usecs() const { - - double mct = (1<<mix_chunk_bits)/double(mix_rate); - return mct*1000000.0; -} - -int AudioMixerSW::_get_channel(ChannelID p_channel) const { - - if (p_channel<0) { - return -1; - } - - int idx=p_channel%MAX_CHANNELS; - int check=p_channel/MAX_CHANNELS; - ERR_FAIL_INDEX_V(idx,MAX_CHANNELS,-1); - if (channels[idx].check!=check) { - return -1; - } - if (!channels[idx].active) { - return -1; - } - - return idx; -} - -AudioMixer::ChannelID AudioMixerSW::channel_alloc(RID p_sample) { - - ERR_FAIL_COND_V( !sample_manager->is_sample(p_sample), INVALID_CHANNEL ); - - - int index=-1; - for (int i=0;i<MAX_CHANNELS;i++) { - - if (!channels[i].active) { - index=i; - break; - } - } - - if (index==-1) - return INVALID_CHANNEL; - - Channel &c=channels[index]; - - // init variables - c.sample=p_sample; - c.vol=1; - c.pan=0; - c.depth=0; - c.height=0; - c.chorus_send=0; - c.reverb_send=0; - c.reverb_room=REVERB_HALL; - c.positional=false; - c.filter.type=FILTER_NONE; - c.speed=sample_manager->sample_get_mix_rate(p_sample); - c.active=true; - c.check=channel_id_count++; - c.first_mix=true; - - // init mix variables - - c.mix.offset=0; - c.mix.increment=1; - //zero everything when this errors - for(int i=0;i<4;i++) { - c.mix.vol[i]=0; - c.mix.reverb_vol[i]=0; - c.mix.chorus_vol[i]=0; - - c.mix.old_vol[i]=0; - c.mix.old_reverb_vol[i]=0; - c.mix.old_chorus_vol[i]=0; - } - - c.had_prev_chorus=false; - c.had_prev_reverb=false; - c.had_prev_vol=false; - - - if (sample_manager->sample_get_format(c.sample)==AudioServer::SAMPLE_FORMAT_IMA_ADPCM) { - - for(int i=0;i<2;i++) { - c.mix.ima_adpcm[i].step_index=0; - c.mix.ima_adpcm[i].predictor=0; - c.mix.ima_adpcm[i].loop_step_index=0; - c.mix.ima_adpcm[i].loop_predictor=0; - c.mix.ima_adpcm[i].last_nibble=-1; - c.mix.ima_adpcm[i].loop_pos=0x7FFFFFFF; - c.mix.ima_adpcm[i].window_ofs=0; - c.mix.ima_adpcm[i].ptr=NULL; - } - } - - ChannelID ret_id = index+c.check*MAX_CHANNELS; - - return ret_id; - -} - -void AudioMixerSW::channel_set_volume(ChannelID p_channel, float p_gain) { - - if (p_gain>3) // avoid gain going too high - p_gain=3; - if (p_gain<0) - p_gain=0; - - int chan = _get_channel(p_channel); - if (chan<0 || chan >=MAX_CHANNELS) - return; - Channel &c = channels[chan]; - - //Math::exp( p_db * 0.11512925464970228420089957273422 ); - c.vol=p_gain; - -} - -void AudioMixerSW::channel_set_pan(ChannelID p_channel, float p_pan, float p_depth,float p_height) { - - int chan = _get_channel(p_channel); - if (chan<0 || chan >=MAX_CHANNELS) - return; - Channel &c = channels[chan]; - - c.pan=p_pan; - c.depth=p_depth; - c.height=p_height; - -} -void AudioMixerSW::channel_set_filter(ChannelID p_channel, FilterType p_type, float p_cutoff, float p_resonance, float p_gain) { - - int chan = _get_channel(p_channel); - if (chan<0 || chan >=MAX_CHANNELS) - return; - - Channel &c = channels[chan]; - - if (c.filter.type==p_type && c.filter.cutoff==p_cutoff && c.filter.resonance==p_resonance && c.filter.gain==p_gain) - return; //bye - - - bool type_changed = p_type!=c.filter.type; - - c.filter.type=p_type; - c.filter.cutoff=p_cutoff; - c.filter.resonance=p_resonance; - c.filter.gain=p_gain; - - - AudioFilterSW filter; - switch(p_type) { - case FILTER_NONE: { - - return; //do nothing else - } break; - case FILTER_LOWPASS: { - filter.set_mode(AudioFilterSW::LOWPASS); - } break; - case FILTER_BANDPASS: { - filter.set_mode(AudioFilterSW::BANDPASS); - } break; - case FILTER_HIPASS: { - filter.set_mode(AudioFilterSW::HIGHPASS); - } break; - case FILTER_NOTCH: { - filter.set_mode(AudioFilterSW::NOTCH); - } break; - case FILTER_PEAK: { - filter.set_mode(AudioFilterSW::PEAK); - } break; - case FILTER_BANDLIMIT: { - filter.set_mode(AudioFilterSW::BANDLIMIT); - } break; - case FILTER_LOW_SHELF: { - filter.set_mode(AudioFilterSW::LOWSHELF); - } break; - case FILTER_HIGH_SHELF: { - filter.set_mode(AudioFilterSW::HIGHSHELF); - } break; - } - - filter.set_cutoff(p_cutoff); - filter.set_resonance(p_resonance); - filter.set_gain(p_gain); - filter.set_sampling_rate(mix_rate); - filter.set_stages(1); - - AudioFilterSW::Coeffs coefs; - filter.prepare_coefficients(&coefs); - - if (!type_changed) - c.filter.old_coefs=c.filter.coefs; - - c.filter.coefs.b0=coefs.b0; - c.filter.coefs.b1=coefs.b1; - c.filter.coefs.b2=coefs.b2; - c.filter.coefs.a1=coefs.a1; - c.filter.coefs.a2=coefs.a2; - - - if (type_changed) { - //type changed reset filter - c.filter.old_coefs=c.filter.coefs; - c.mix.filter_l.ha[0]=0; - c.mix.filter_l.ha[1]=0; - c.mix.filter_l.hb[0]=0; - c.mix.filter_l.hb[1]=0; - c.mix.filter_r.ha[0]=0; - c.mix.filter_r.ha[1]=0; - c.mix.filter_r.hb[0]=0; - c.mix.filter_r.hb[1]=0; - } - - -} -void AudioMixerSW::channel_set_chorus(ChannelID p_channel, float p_chorus ) { - - int chan = _get_channel(p_channel); - if (chan<0 || chan >=MAX_CHANNELS) - return; - - Channel &c = channels[chan]; - c.chorus_send=p_chorus; - -} -void AudioMixerSW::channel_set_reverb(ChannelID p_channel, ReverbRoomType p_room_type, float p_reverb) { - - ERR_FAIL_INDEX(p_room_type,MAX_REVERBS); - int chan = _get_channel(p_channel); - if (chan<0 || chan >=MAX_CHANNELS) - return; - - Channel &c = channels[chan]; - c.reverb_room=p_room_type; - c.reverb_send=p_reverb; - -} - -void AudioMixerSW::channel_set_mix_rate(ChannelID p_channel, int p_mix_rate) { - - int chan = _get_channel(p_channel); - if (chan<0 || chan >=MAX_CHANNELS) - return; - - Channel &c = channels[chan]; - c.speed=p_mix_rate; - -} -void AudioMixerSW::channel_set_positional(ChannelID p_channel, bool p_positional) { - - int chan = _get_channel(p_channel); - if (chan<0 || chan >=MAX_CHANNELS) - return; - - Channel &c = channels[chan]; - c.positional=p_positional; -} - -float AudioMixerSW::channel_get_volume(ChannelID p_channel) const { - - int chan = _get_channel(p_channel); - if (chan<0 || chan >=MAX_CHANNELS) - return 0; - - const Channel &c = channels[chan]; - //Math::log( c.vol ) * 8.6858896380650365530225783783321; - return c.vol; -} - -float AudioMixerSW::channel_get_pan(ChannelID p_channel) const { - - int chan = _get_channel(p_channel); - if (chan<0 || chan >=MAX_CHANNELS) - return 0; - - const Channel &c = channels[chan]; - return c.pan; -} -float AudioMixerSW::channel_get_pan_depth(ChannelID p_channel) const { - - int chan = _get_channel(p_channel); - if (chan<0 || chan >=MAX_CHANNELS) - return 0; - - const Channel &c = channels[chan]; - return c.depth; -} -float AudioMixerSW::channel_get_pan_height(ChannelID p_channel) const { - - int chan = _get_channel(p_channel); - if (chan<0 || chan >=MAX_CHANNELS) - return 0; - - const Channel &c = channels[chan]; - return c.height; - -} -AudioMixer::FilterType AudioMixerSW::channel_get_filter_type(ChannelID p_channel) const { - - int chan = _get_channel(p_channel); - if (chan<0 || chan >=MAX_CHANNELS) - return FILTER_NONE; - - const Channel &c = channels[chan]; - return c.filter.type; -} -float AudioMixerSW::channel_get_filter_cutoff(ChannelID p_channel) const { - - - int chan = _get_channel(p_channel); - if (chan<0 || chan >=MAX_CHANNELS) - return 0; - - const Channel &c = channels[chan]; - return c.filter.cutoff; - -} -float AudioMixerSW::channel_get_filter_resonance(ChannelID p_channel) const { - - int chan = _get_channel(p_channel); - if (chan<0 || chan >=MAX_CHANNELS) - return 0; - - const Channel &c = channels[chan]; - return c.filter.resonance; - -} - -float AudioMixerSW::channel_get_filter_gain(ChannelID p_channel) const { - - int chan = _get_channel(p_channel); - if (chan<0 || chan >=MAX_CHANNELS) - return 0; - - const Channel &c = channels[chan]; - return c.filter.gain; -} - - -float AudioMixerSW::channel_get_chorus(ChannelID p_channel) const { - - int chan = _get_channel(p_channel); - if (chan<0 || chan >=MAX_CHANNELS) - return 0; - - const Channel &c = channels[chan]; - return c.chorus_send; - -} -AudioMixer::ReverbRoomType AudioMixerSW::channel_get_reverb_type(ChannelID p_channel) const { - - int chan = _get_channel(p_channel); - if (chan<0 || chan >=MAX_CHANNELS) - return REVERB_HALL; - - const Channel &c = channels[chan]; - return c.reverb_room; - -} -float AudioMixerSW::channel_get_reverb(ChannelID p_channel) const { - - int chan = _get_channel(p_channel); - if (chan<0 || chan >=MAX_CHANNELS) - return 0; - - const Channel &c = channels[chan]; - return c.reverb_send; -} - -int AudioMixerSW::channel_get_mix_rate(ChannelID p_channel) const { - - int chan = _get_channel(p_channel); - if (chan<0 || chan >=MAX_CHANNELS) - return 0; - - const Channel &c = channels[chan]; - return c.speed; -} -bool AudioMixerSW::channel_is_positional(ChannelID p_channel) const { - - int chan = _get_channel(p_channel); - if (chan<0 || chan >=MAX_CHANNELS) - return false; - - const Channel &c = channels[chan]; - return c.positional; -} - -bool AudioMixerSW::channel_is_valid(ChannelID p_channel) const { - - int chan = _get_channel(p_channel); - if (chan<0 || chan >=MAX_CHANNELS) - return false; - return channels[chan].active; -} - - -void AudioMixerSW::channel_free(ChannelID p_channel) { - - int chan = _get_channel(p_channel); - if (chan<0 || chan >=MAX_CHANNELS) - return; - - Channel &c=channels[chan]; - - if (!c.active) - return; - - bool has_vol=false; - - for(int i=0;i<mix_channels;i++) { - - if (c.mix.vol[i]) - has_vol=true; - if (c.mix.reverb_vol[i]) - has_vol=true; - if (c.mix.chorus_vol[i]) - has_vol=true; - } - if (c.active && has_vol && inside_mix) { - // drive voice to zero, and run a chunk, the VRAMP will fade it good - c.vol=0; - c.reverb_send=0; - c.chorus_send=0; - mix_channel(c); - } - /* @TODO RAMP DOWN ON STOP */ - c.active=false; -} - - - -AudioMixerSW::AudioMixerSW(SampleManagerSW *p_sample_manager,int p_desired_latency_ms,int p_mix_rate,MixChannels p_mix_channels,bool p_use_fx,InterpolationType p_interp,MixStepCallback p_step_callback,void *p_step_udata) { - - if (OS::get_singleton()->is_stdout_verbose()) { - print_line("AudioServerSW Params: "); - print_line(" -mix chans: "+itos(p_mix_channels)); - print_line(" -mix rate: "+itos(p_mix_rate)); - print_line(" -latency: "+itos(p_desired_latency_ms)); - print_line(" -fx: "+itos(p_use_fx)); - print_line(" -interp: "+itos(p_interp)); - } - sample_manager=p_sample_manager; - mix_channels=p_mix_channels; - mix_rate=p_mix_rate; - step_callback=p_step_callback; - step_udata=p_step_udata; - - - mix_chunk_bits=nearest_shift( p_desired_latency_ms * p_mix_rate / 1000 ); - - mix_chunk_size=(1<<mix_chunk_bits); - mix_chunk_mask=mix_chunk_size-1; - mix_buffer = memnew_arr(int32_t,mix_chunk_size*mix_channels); -#ifndef NO_REVERB - zero_buffer = memnew_arr(int32_t,mix_chunk_size*mix_channels); - for(int i=0;i<mix_chunk_size*mix_channels;i++) - zero_buffer[i]=0; //zero buffer is zero... - - max_reverbs=MAX_REVERBS; - int reverberators=mix_channels/2; - - reverb_state = memnew_arr(ReverbState,max_reverbs); - for(int i=0;i<max_reverbs;i++) { - reverb_state[i].enabled=false; - reverb_state[i].reverb = memnew_arr(ReverbSW,reverberators); - reverb_state[i].buffer = memnew_arr(int32_t,mix_chunk_size*mix_channels); - reverb_state[i].frames_idle=0; - for(int j=0;j<reverberators;j++) { - static ReverbSW::ReverbMode modes[MAX_REVERBS]={ReverbSW::REVERB_MODE_STUDIO_SMALL,ReverbSW::REVERB_MODE_STUDIO_MEDIUM,ReverbSW::REVERB_MODE_STUDIO_LARGE,ReverbSW::REVERB_MODE_HALL}; - reverb_state[i].reverb[j].set_mix_rate(p_mix_rate); - reverb_state[i].reverb[j].set_mode(modes[i]); - } - - } - fx_enabled=p_use_fx; -#else - fx_enabled=false; -#endif - mix_chunk_left=0; - - interpolation_type=p_interp; - channel_id_count=1; - inside_mix=false; - channel_nrg=1.0; - -} - -void AudioMixerSW::set_mixer_volume(float p_volume) { - - channel_nrg=p_volume; -} - -AudioMixerSW::~AudioMixerSW() { - - memdelete_arr(mix_buffer); - -#ifndef NO_REVERB - memdelete_arr(zero_buffer); - for(int i=0;i<max_reverbs;i++) { - memdelete_arr(reverb_state[i].reverb); - memdelete_arr(reverb_state[i].buffer); - } - memdelete_arr(reverb_state); -#endif - - -} diff --git a/servers/audio/audio_mixer_sw.h b/servers/audio/audio_mixer_sw.h deleted file mode 100644 index e924b518cc..0000000000 --- a/servers/audio/audio_mixer_sw.h +++ /dev/null @@ -1,264 +0,0 @@ -/*************************************************************************/ -/* audio_mixer_sw.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#ifndef AUDIO_MIXER_SW_H -#define AUDIO_MIXER_SW_H - -#include "servers/audio_server.h" -#include "servers/audio/sample_manager_sw.h" -#include "servers/audio/audio_filter_sw.h" -#include "servers/audio/reverb_sw.h" - -class AudioMixerSW : public AudioMixer { -public: - - enum InterpolationType { - - INTERPOLATION_RAW, - INTERPOLATION_LINEAR, - INTERPOLATION_CUBIC - }; - - enum MixChannels { - - MIX_STEREO=2, - MIX_QUAD=4 - }; - - typedef void (*MixStepCallback)(void*); - -private: - SampleManagerSW *sample_manager; - - enum { - - MAX_CHANNELS=64, - // fixed point defs - - MIX_FRAC_BITS=13, - MIX_FRAC_LEN=(1<<MIX_FRAC_BITS), - MIX_FRAC_MASK=MIX_FRAC_LEN-1, - MIX_VOL_FRAC_BITS=12, - MIX_VOLRAMP_FRAC_BITS=16, - MIX_VOLRAMP_FRAC_LEN=(1<<MIX_VOLRAMP_FRAC_BITS), - MIX_VOLRAMP_FRAC_MASK=MIX_VOLRAMP_FRAC_LEN-1, - MIX_FILTER_FRAC_BITS=16, - MIX_FILTER_RAMP_FRAC_BITS=8, - MIX_VOL_MOVE_TO_24=4 - }; - - - struct Channel { - - RID sample; - struct Mix { - int64_t offset; - int32_t increment; - - int32_t vol[4]; - int32_t reverb_vol[4]; - int32_t chorus_vol[4]; - - int32_t old_vol[4]; - int32_t old_reverb_vol[4]; - int32_t old_chorus_vol[4]; - - - struct Filter { //history (stereo) - float ha[2],hb[2]; - } filter_l,filter_r; - - struct IMA_ADPCM_State { - - int16_t step_index; - int32_t predictor; - /* values at loop point */ - int16_t loop_step_index; - int32_t loop_predictor; - int32_t last_nibble; - int32_t loop_pos; - int32_t window_ofs; - const uint8_t *ptr; - } ima_adpcm[2]; - - } mix; - - float vol; - float pan; - float depth; - float height; - - float chorus_send; - ReverbRoomType reverb_room; - float reverb_send; - int speed; - int check; - bool positional; - - bool had_prev_reverb; - bool had_prev_chorus; - bool had_prev_vol; - - struct Filter { - - bool dirty; - - FilterType type; - float cutoff; - float resonance; - float gain; - - struct Coefs { - - float a1,a2,b0,b1,b2; // fixed point coefficients - } coefs,old_coefs; - - } filter; - - bool first_mix; - bool active; - Channel() { active=false; check=-1; first_mix=false; filter.dirty=true; filter.type=FILTER_NONE; filter.cutoff=8000; filter.resonance=0; filter.gain=0; } - }; - - Channel channels[MAX_CHANNELS]; - - uint32_t mix_rate; - bool fx_enabled; - InterpolationType interpolation_type; - - int mix_chunk_bits; - int mix_chunk_size; - int mix_chunk_mask; - - int32_t *mix_buffer; - int32_t *zero_buffer; // fx feed when no input was mixed - - struct ResamplerState { - - uint32_t amount; - int32_t increment; - - - int32_t pos; - - - int32_t vol[4]; - int32_t reverb_vol[4]; - int32_t chorus_vol[4]; - - int32_t vol_inc[4]; - int32_t reverb_vol_inc[4]; - int32_t chorus_vol_inc[4]; - - - - Channel::Mix::Filter *filter_l; - Channel::Mix::Filter *filter_r; - Channel::Filter::Coefs coefs; - Channel::Filter::Coefs coefs_inc; - - Channel::Mix::IMA_ADPCM_State *ima_adpcm; - - int32_t *reverb_buffer; - }; - - - - template<class Depth,bool is_stereo,bool use_filter,bool is_ima_adpcm,bool use_fx,InterpolationType type,MixChannels> - _FORCE_INLINE_ void do_resample(const Depth* p_src, int32_t *p_dst, ResamplerState *p_state); - - MixChannels mix_channels; - - void mix_channel(Channel& p_channel); - int mix_chunk_left; - void mix_chunk(); - - float channel_nrg; - int channel_id_count; - bool inside_mix; - MixStepCallback step_callback; - void *step_udata; - _FORCE_INLINE_ int _get_channel(ChannelID p_channel) const; - - int max_reverbs; - struct ReverbState { - - bool used_in_chunk; - bool enabled; - ReverbSW *reverb; - int frames_idle; - int32_t *buffer; //reverb is sent here - ReverbState() { enabled=false; frames_idle=0; used_in_chunk=false; } - }; - - ReverbState *reverb_state; - - -public: - - - virtual ChannelID channel_alloc(RID p_sample); - - virtual void channel_set_volume(ChannelID p_channel, float p_gain); - virtual void channel_set_pan(ChannelID p_channel, float p_pan, float p_depth=0,float height=0); //pan and depth go from -1 to 1 - virtual void channel_set_filter(ChannelID p_channel, FilterType p_type, float p_cutoff, float p_resonance, float p_gain=1.0); - virtual void channel_set_chorus(ChannelID p_channel, float p_chorus ); - virtual void channel_set_reverb(ChannelID p_channel, ReverbRoomType p_room_type, float p_reverb); - virtual void channel_set_mix_rate(ChannelID p_channel, int p_mix_rate); - virtual void channel_set_positional(ChannelID p_channel, bool p_positional); - - virtual float channel_get_volume(ChannelID p_channel) const; - virtual float channel_get_pan(ChannelID p_channel) const; //pan and depth go from -1 to 1 - virtual float channel_get_pan_depth(ChannelID p_channel) const; //pan and depth go from -1 to 1 - virtual float channel_get_pan_height(ChannelID p_channel) const; //pan and depth go from -1 to 1 - virtual FilterType channel_get_filter_type(ChannelID p_channel) const; - virtual float channel_get_filter_cutoff(ChannelID p_channel) const; - virtual float channel_get_filter_resonance(ChannelID p_channel) const; - virtual float channel_get_filter_gain(ChannelID p_channel) const; - - virtual float channel_get_chorus(ChannelID p_channel) const; - virtual ReverbRoomType channel_get_reverb_type(ChannelID p_channel) const; - virtual float channel_get_reverb(ChannelID p_channel) const; - - virtual int channel_get_mix_rate(ChannelID p_channel) const; - virtual bool channel_is_positional(ChannelID p_channel) const; - - virtual bool channel_is_valid(ChannelID p_channel) const; - - virtual void channel_free(ChannelID p_channel); - - int mix(int32_t *p_buffer,int p_frames); //return amount of mixsteps - uint64_t get_step_usecs() const; - - virtual void set_mixer_volume(float p_volume); - - AudioMixerSW(SampleManagerSW *p_sample_manager,int p_desired_latency_ms,int p_mix_rate,MixChannels p_mix_channels,bool p_use_fx=true,InterpolationType p_interp=INTERPOLATION_LINEAR,MixStepCallback p_step_callback=NULL,void *p_callback_udata=NULL); - ~AudioMixerSW(); -}; - -#endif // AUDIO_MIXER_SW_H diff --git a/servers/audio/audio_rb_resampler.cpp b/servers/audio/audio_rb_resampler.cpp index aa4fca3a62..28f0007b5b 100644 --- a/servers/audio/audio_rb_resampler.cpp +++ b/servers/audio/audio_rb_resampler.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/servers/audio/audio_rb_resampler.h b/servers/audio/audio_rb_resampler.h index 22643e4e82..e97e275b68 100644 --- a/servers/audio/audio_rb_resampler.h +++ b/servers/audio/audio_rb_resampler.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/servers/audio/audio_server_sw.cpp b/servers/audio/audio_server_sw.cpp deleted file mode 100644 index 853714be2a..0000000000 --- a/servers/audio/audio_server_sw.cpp +++ /dev/null @@ -1,1028 +0,0 @@ -/*************************************************************************/ -/* audio_server_sw.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "audio_server_sw.h" -#include "globals.h" -#include "os/os.h" - -struct _AudioDriverLock { - - _AudioDriverLock() { if (AudioDriverSW::get_singleton()) AudioDriverSW::get_singleton()->lock(); } - ~_AudioDriverLock() { if (AudioDriverSW::get_singleton()) AudioDriverSW::get_singleton()->unlock(); } - -}; - -#define AUDIO_LOCK _AudioDriverLock _adlock; - -AudioMixer *AudioServerSW::get_mixer() { - - return mixer; -} - -/* CALLBACKS */ - -void AudioServerSW::audio_mixer_chunk_callback(int p_frames) { -/* - for(List<Stream*>::Element *E=event_streams.front();E;E=E->next()) { - - if (E->get()->active) - E->get()->audio_stream->mix(NULL,p_frames); - } -*/ -} - -void AudioServerSW::_mixer_callback(void *p_udata) { - - AudioServerSW *self = (AudioServerSW*)p_udata; - for(List<Stream*>::Element *E=self->active_audio_streams.front();E;E=E->next()) { - - if (!E->get()->active) - continue; - - EventStream *es=E->get()->event_stream; - if (!es) - continue; - - es->update(self->mixer_step_usecs); - } - -} - -void AudioServerSW::driver_process_chunk(int p_frames,int32_t *p_buffer) { - - - - int samples=p_frames*internal_buffer_channels; - - for(int i=0;i<samples;i++) { - internal_buffer[i]=0; - } - - while(voice_rb.commands_left()) { - - VoiceRBSW::Command cmd = voice_rb.pop_command(); - - if (cmd.type==VoiceRBSW::Command::CMD_CHANGE_ALL_FX_VOLUMES) { - - SelfList<Voice>*al = active_list.first(); - while(al) { - - Voice *v=al->self(); - if (v->channel!=AudioMixer::INVALID_CHANNEL) { - mixer->channel_set_volume(v->channel,v->volume*fx_volume_scale); - } - al=al->next(); - } - - continue; - } - if (!voice_owner.owns(cmd.voice)) - continue; - - - Voice *v = voice_owner.get(cmd.voice); - - switch(cmd.type) { - case VoiceRBSW::Command::CMD_NONE: { - - - } break; - case VoiceRBSW::Command::CMD_PLAY: { - - if (v->channel!=AudioMixer::INVALID_CHANNEL) - mixer->channel_free(v->channel); - - RID sample = cmd.play.sample; - if (!sample_manager->is_sample(sample)) - continue; - - v->channel=mixer->channel_alloc(sample); - v->volume=1.0; - mixer->channel_set_volume(v->channel,fx_volume_scale); - if (v->channel==AudioMixer::INVALID_CHANNEL) { -#ifdef AUDIO_DEBUG - WARN_PRINT("AUDIO: all channels used, failed to allocate voice"); -#endif - v->active=false; - break; // no voices left? - } - - v->active=true; // this kind of ensures it works - if (!v->active_item.in_list()) - active_list.add(&v->active_item); - - } break; - case VoiceRBSW::Command::CMD_STOP: { - - if (v->channel!=AudioMixer::INVALID_CHANNEL) { - mixer->channel_free(v->channel); - if (v->active_item.in_list()) { - active_list.remove(&v->active_item); - } - } - v->active=false; - } break; - case VoiceRBSW::Command::CMD_SET_VOLUME: { - - - if (v->channel!=AudioMixer::INVALID_CHANNEL) { - v->volume=cmd.volume.volume; - mixer->channel_set_volume(v->channel,cmd.volume.volume*fx_volume_scale); - } - - } break; - case VoiceRBSW::Command::CMD_SET_PAN: { - - if (v->channel!=AudioMixer::INVALID_CHANNEL) - mixer->channel_set_pan(v->channel,cmd.pan.pan,cmd.pan.depth,cmd.pan.height); - - } break; - case VoiceRBSW::Command::CMD_SET_FILTER: { - - - if (v->channel!=AudioMixer::INVALID_CHANNEL) - mixer->channel_set_filter(v->channel,(AudioMixer::FilterType)cmd.filter.type,cmd.filter.cutoff,cmd.filter.resonance,cmd.filter.gain); - } break; - case VoiceRBSW::Command::CMD_SET_CHORUS: { - - if (v->channel!=AudioMixer::INVALID_CHANNEL) - mixer->channel_set_chorus(v->channel,cmd.chorus.send); - - } break; - case VoiceRBSW::Command::CMD_SET_REVERB: { - - if (v->channel!=AudioMixer::INVALID_CHANNEL) - mixer->channel_set_reverb(v->channel,(AudioMixer::ReverbRoomType)cmd.reverb.room,cmd.reverb.send); - - } break; - case VoiceRBSW::Command::CMD_SET_MIX_RATE: { - - if (v->channel!=AudioMixer::INVALID_CHANNEL) - mixer->channel_set_mix_rate(v->channel,cmd.mix_rate.mix_rate); - - } break; - case VoiceRBSW::Command::CMD_SET_POSITIONAL: { - - if (v->channel!=AudioMixer::INVALID_CHANNEL) - mixer->channel_set_positional(v->channel,cmd.positional.positional); - - } break; - default: {} - - } - } - - mixer->mix(internal_buffer,p_frames); - //uint64_t stepsize=mixer->get_step_usecs(); - - - for(List<Stream*>::Element *E=active_audio_streams.front();E;E=E->next()) { - - ERR_CONTINUE(!E->get()->active); // bug? - - - AudioStream *as=E->get()->audio_stream; - if (!as) - continue; - - int channels=as->get_channel_count(); - if (channels==0) - continue; // does not want mix - if (!as->mix(stream_buffer,p_frames)) - continue; //nothing was mixed!! - - int32_t stream_vol_scale=(stream_volume*stream_volume_scale*E->get()->volume_scale)*(1<<STREAM_SCALE_BITS); - -#define STRSCALE(m_val) (((m_val>>STREAM_SCALE_BITS)*stream_vol_scale)>>8) - switch(internal_buffer_channels) { - - case 2: { - - switch(channels) { - case 1: { - - for(int i=0;i<p_frames;i++) { - - internal_buffer[(i<<1)+0]+=STRSCALE(stream_buffer[i]); - internal_buffer[(i<<1)+1]+=STRSCALE(stream_buffer[i]); - } - } break; - case 2: { - - for(int i=0;i<p_frames*2;i++) { - - internal_buffer[i]+=STRSCALE(stream_buffer[i]); - } - } break; - case 4: { - - for(int i=0;i<p_frames;i++) { - - internal_buffer[(i<<2)+0]+=STRSCALE((stream_buffer[(i<<2)+0]+stream_buffer[(i<<2)+2])>>1); - internal_buffer[(i<<2)+1]+=STRSCALE((stream_buffer[(i<<2)+1]+stream_buffer[(i<<2)+3])>>1); - } - } break; - - } break; - - } break; - case 4: { - - switch(channels) { - case 1: { - - for(int i=0;i<p_frames;i++) { - - internal_buffer[(i<<2)+0]+=STRSCALE(stream_buffer[i]); - internal_buffer[(i<<2)+1]+=STRSCALE(stream_buffer[i]); - internal_buffer[(i<<2)+2]+=STRSCALE(stream_buffer[i]); - internal_buffer[(i<<2)+3]+=STRSCALE(stream_buffer[i]); - } - } break; - case 2: { - - for(int i=0;i<p_frames*2;i++) { - - internal_buffer[(i<<2)+0]+=STRSCALE(stream_buffer[(i<<1)+0]); - internal_buffer[(i<<2)+1]+=STRSCALE(stream_buffer[(i<<1)+1]); - internal_buffer[(i<<2)+2]+=STRSCALE(stream_buffer[(i<<1)+0]); - internal_buffer[(i<<2)+3]+=STRSCALE(stream_buffer[(i<<1)+1]); - } - } break; - case 4: { - - for(int i=0;i<p_frames*4;i++) { - internal_buffer[i]+=STRSCALE(stream_buffer[i]); - } - } break; - - } break; - - } break; - case 6: { - - - } break; - } - -#undef STRSCALE - } - - SelfList<Voice> *activeE=active_list.first(); - while(activeE) { - - SelfList<Voice> *activeN=activeE->next(); - if (activeE->self()->channel==AudioMixer::INVALID_CHANNEL || !mixer->channel_is_valid(activeE->self()->channel)) { - - active_list.remove(activeE); - activeE->self()->active=false; - - } - activeE=activeN; - } - - uint32_t peak=0; - for(int i=0;i<samples;i++) { - //clamp to (1<<24) using branchless code - int32_t in = internal_buffer[i]; -#ifdef DEBUG_ENABLED - { - int mask = (in >> (32 - 1)); - uint32_t p = (in + mask) ^ mask; - if (p>peak) - peak=p; - } -#endif - int32_t lo = -0x800000, hi=0x7FFFFF; - lo-=in; - hi-=in; - in += (lo & ((lo < 0) - 1)) + (hi & ((hi > 0) - 1)); - p_buffer[i]=in<<8; - } - - if (peak>max_peak) - max_peak=peak; -} - -void AudioServerSW::driver_process(int p_frames,int32_t *p_buffer) { - - - _output_delay=p_frames/double(AudioDriverSW::get_singleton()->get_mix_rate()); - //process in chunks to make sure to never process more than INTERNAL_BUFFER_SIZE - int todo=p_frames; - while(todo) { - - int tomix=MIN(todo,INTERNAL_BUFFER_SIZE); - driver_process_chunk(tomix,p_buffer); - p_buffer+=tomix; - todo-=tomix; - } - - -} - -/* SAMPLE API */ - -RID AudioServerSW::sample_create(SampleFormat p_format, bool p_stereo, int p_length) { - - AUDIO_LOCK - - return sample_manager->sample_create(p_format,p_stereo,p_length); -} - -void AudioServerSW::sample_set_description(RID p_sample, const String& p_description) { - - AUDIO_LOCK - sample_manager->sample_set_description(p_sample,p_description); -} -String AudioServerSW::sample_get_description(RID p_sample) const { - - AUDIO_LOCK - return sample_manager->sample_get_description(p_sample); -} - -AS::SampleFormat AudioServerSW::sample_get_format(RID p_sample) const { - //AUDIO_LOCK - return sample_manager->sample_get_format(p_sample); -} -bool AudioServerSW::sample_is_stereo(RID p_sample) const { - //AUDIO_LOCK - return sample_manager->sample_is_stereo(p_sample); -} -int AudioServerSW::sample_get_length(RID p_sample) const { - ///AUDIO_LOCK - return sample_manager->sample_get_length(p_sample); -} - -const void* AudioServerSW::sample_get_data_ptr(RID p_sample) const { - ///AUDIO_LOCK - return sample_manager->sample_get_data_ptr(p_sample); -} - -void AudioServerSW::sample_set_data(RID p_sample, const DVector<uint8_t>& p_buffer) { - AUDIO_LOCK - sample_manager->sample_set_data(p_sample,p_buffer); -} -DVector<uint8_t> AudioServerSW::sample_get_data(RID p_sample) const { - AUDIO_LOCK - return sample_manager->sample_get_data(p_sample); -} - -void AudioServerSW::sample_set_mix_rate(RID p_sample,int p_rate) { - AUDIO_LOCK - sample_manager->sample_set_mix_rate(p_sample,p_rate); -} -int AudioServerSW::sample_get_mix_rate(RID p_sample) const { - AUDIO_LOCK - return sample_manager->sample_get_mix_rate(p_sample); -} - -void AudioServerSW::sample_set_loop_format(RID p_sample,SampleLoopFormat p_format) { - AUDIO_LOCK - sample_manager->sample_set_loop_format(p_sample,p_format); -} -AS::SampleLoopFormat AudioServerSW::sample_get_loop_format(RID p_sample) const { - AUDIO_LOCK - return sample_manager->sample_get_loop_format(p_sample); -} - -void AudioServerSW::sample_set_loop_begin(RID p_sample,int p_pos) { - AUDIO_LOCK - sample_manager->sample_set_loop_begin(p_sample,p_pos); -} -int AudioServerSW::sample_get_loop_begin(RID p_sample) const { - AUDIO_LOCK - return sample_manager->sample_get_loop_begin(p_sample); -} - -void AudioServerSW::sample_set_loop_end(RID p_sample,int p_pos) { - AUDIO_LOCK - sample_manager->sample_set_loop_end(p_sample,p_pos); -} -int AudioServerSW::sample_get_loop_end(RID p_sample) const { - AUDIO_LOCK - return sample_manager->sample_get_loop_end(p_sample); -} - -/* VOICE API */ - -RID AudioServerSW::voice_create() { - - Voice * v = memnew( Voice ); - v->channel=AudioMixer::INVALID_CHANNEL; - - AUDIO_LOCK - return voice_owner.make_rid(v); - -} -void AudioServerSW::voice_play(RID p_voice, RID p_sample) { - - Voice *v = voice_owner.get( p_voice ); - ERR_FAIL_COND(!v); - v->active=true; // force actvive (will be disabled later i gues..) - - //stop old, start new - VoiceRBSW::Command cmd; - cmd.type=VoiceRBSW::Command::CMD_PLAY; - cmd.voice=p_voice; - cmd.play.sample=p_sample; - voice_rb.push_command(cmd); - -} - -void AudioServerSW::voice_set_volume(RID p_voice, float p_volume) { - - VoiceRBSW::Command cmd; - cmd.type=VoiceRBSW::Command::CMD_SET_VOLUME; - cmd.voice=p_voice; - cmd.volume.volume=p_volume; - voice_rb.push_command(cmd); - -} -void AudioServerSW::voice_set_pan(RID p_voice, float p_pan, float p_depth,float p_height) { - - VoiceRBSW::Command cmd; - cmd.type=VoiceRBSW::Command::CMD_SET_PAN; - cmd.voice=p_voice; - cmd.pan.pan=p_pan; - cmd.pan.depth=p_depth; - cmd.pan.height=p_height; - voice_rb.push_command(cmd); - -} -void AudioServerSW::voice_set_filter(RID p_voice, FilterType p_type, float p_cutoff, float p_resonance,float p_gain) { - - VoiceRBSW::Command cmd; - cmd.type=VoiceRBSW::Command::CMD_SET_FILTER; - cmd.voice=p_voice; - cmd.filter.type=p_type; - cmd.filter.cutoff=p_cutoff; - cmd.filter.resonance=p_resonance; - cmd.filter.gain=p_gain; - voice_rb.push_command(cmd); - -} -void AudioServerSW::voice_set_chorus(RID p_voice, float p_chorus ) { - - VoiceRBSW::Command cmd; - cmd.type=VoiceRBSW::Command::CMD_SET_CHORUS; - cmd.voice=p_voice; - cmd.chorus.send=p_chorus; - voice_rb.push_command(cmd); - -} -void AudioServerSW::voice_set_reverb(RID p_voice, ReverbRoomType p_room_type, float p_reverb) { - - VoiceRBSW::Command cmd; - cmd.type=VoiceRBSW::Command::CMD_SET_REVERB; - cmd.voice=p_voice; - cmd.reverb.room=p_room_type; - cmd.reverb.send=p_reverb; - - voice_rb.push_command(cmd); - -} -void AudioServerSW::voice_set_mix_rate(RID p_voice, int p_mix_rate) { - - VoiceRBSW::Command cmd; - cmd.type=VoiceRBSW::Command::CMD_SET_MIX_RATE; - cmd.voice=p_voice; - cmd.mix_rate.mix_rate=p_mix_rate; - voice_rb.push_command(cmd); - -} -void AudioServerSW::voice_set_positional(RID p_voice, bool p_positional) { - - VoiceRBSW::Command cmd; - cmd.type=VoiceRBSW::Command::CMD_SET_POSITIONAL; - cmd.voice=p_voice; - cmd.positional.positional=p_positional; - voice_rb.push_command(cmd); - -} - -float AudioServerSW::voice_get_volume(RID p_voice) const { - - AUDIO_LOCK - Voice *v = voice_owner.get( p_voice ); - ERR_FAIL_COND_V(!v, 0); - - return mixer->channel_get_volume( v->channel ); - -} -float AudioServerSW::voice_get_pan(RID p_voice) const { - - AUDIO_LOCK - Voice *v = voice_owner.get( p_voice ); - ERR_FAIL_COND_V(!v, 0); - - return mixer->channel_get_pan( v->channel ); - -} -float AudioServerSW::voice_get_pan_depth(RID p_voice) const { - - AUDIO_LOCK - Voice *v = voice_owner.get( p_voice ); - ERR_FAIL_COND_V(!v, 0); - - return mixer->channel_get_pan_depth( v->channel ); - -} -float AudioServerSW::voice_get_pan_height(RID p_voice) const { - - AUDIO_LOCK - Voice *v = voice_owner.get( p_voice ); - ERR_FAIL_COND_V(!v, 0); - - return mixer->channel_get_pan_height( v->channel ); - -} -AS::FilterType AudioServerSW::voice_get_filter_type(RID p_voice) const { - - AUDIO_LOCK - Voice *v = voice_owner.get( p_voice ); - ERR_FAIL_COND_V(!v, AS::FILTER_NONE); - - return (AS::FilterType)mixer->channel_get_filter_type(v->channel); - -} -float AudioServerSW::voice_get_filter_cutoff(RID p_voice) const { - - AUDIO_LOCK - Voice *v = voice_owner.get( p_voice ); - ERR_FAIL_COND_V(!v, 0); - - return mixer->channel_get_filter_cutoff( v->channel ); - -} -float AudioServerSW::voice_get_filter_resonance(RID p_voice) const { - - AUDIO_LOCK - Voice *v = voice_owner.get( p_voice ); - ERR_FAIL_COND_V(!v, 0); - - return mixer->channel_get_filter_resonance( v->channel ); - -} -float AudioServerSW::voice_get_chorus(RID p_voice) const { - - AUDIO_LOCK - Voice *v = voice_owner.get( p_voice ); - ERR_FAIL_COND_V(!v, 0); - - return mixer->channel_get_chorus( v->channel ); - -} -AS::ReverbRoomType AudioServerSW::voice_get_reverb_type(RID p_voice) const { - - AUDIO_LOCK - Voice *v = voice_owner.get( p_voice ); - ERR_FAIL_COND_V(!v, REVERB_SMALL); - - return (AS::ReverbRoomType)mixer->channel_get_reverb_type( v->channel ); - -} -float AudioServerSW::voice_get_reverb(RID p_voice) const { - - AUDIO_LOCK - Voice *v = voice_owner.get( p_voice ); - ERR_FAIL_COND_V(!v, 0); - - return mixer->channel_get_reverb( v->channel ); - -} - -int AudioServerSW::voice_get_mix_rate(RID p_voice) const { - - AUDIO_LOCK - Voice *v = voice_owner.get( p_voice ); - ERR_FAIL_COND_V(!v, 0); - - return mixer->channel_get_mix_rate( v->channel ); - -} -bool AudioServerSW::voice_is_positional(RID p_voice) const { - - AUDIO_LOCK - Voice *v = voice_owner.get( p_voice ); - ERR_FAIL_COND_V(!v, 0); - - return mixer->channel_is_positional( v->channel ); - -} - -void AudioServerSW::voice_stop(RID p_voice) { - - VoiceRBSW::Command cmd; - cmd.type=VoiceRBSW::Command::CMD_STOP; - cmd.voice=p_voice; - voice_rb.push_command(cmd); - - //return mixer->channel_free( v->channel ); - -} - -bool AudioServerSW::voice_is_active(RID p_voice) const { - - Voice *v = voice_owner.get(p_voice); - ERR_FAIL_COND_V(!v,false); - return v->active; - -} - -/* STREAM API */ - -RID AudioServerSW::audio_stream_create(AudioStream *p_stream) { - - AUDIO_LOCK - Stream *s = memnew(Stream); - s->audio_stream=p_stream; - s->event_stream=NULL; - s->active=false; - s->E=NULL; - s->volume_scale=1.0; - p_stream->set_mix_rate(AudioDriverSW::get_singleton()->get_mix_rate()); - - return stream_owner.make_rid(s); -} - -RID AudioServerSW::event_stream_create(EventStream *p_stream) { - - AUDIO_LOCK - Stream *s = memnew(Stream); - s->audio_stream=NULL; - s->event_stream=p_stream; - s->active=false; - s->E=NULL; - s->volume_scale=1.0; - //p_stream->set_mix_rate(AudioDriverSW::get_singleton()->get_mix_rate()); - - return stream_owner.make_rid(s); - - -} - - -void AudioServerSW::stream_set_active(RID p_stream, bool p_active) { - - - Stream *s = stream_owner.get(p_stream); - ERR_FAIL_COND(!s); - _THREAD_SAFE_METHOD_ - - if (s->active==p_active) - return; - AUDIO_LOCK; - s->active=p_active; - if (p_active) - s->E=active_audio_streams.push_back(s); - else { - active_audio_streams.erase(s->E); - s->E=NULL; - } - - -} - -bool AudioServerSW::stream_is_active(RID p_stream) const { - - Stream *s = stream_owner.get(p_stream); - ERR_FAIL_COND_V(!s,false); - return s->active; -} - -void AudioServerSW::stream_set_volume_scale(RID p_stream, float p_scale) { - - Stream *s = stream_owner.get(p_stream); - ERR_FAIL_COND(!s); - s->volume_scale=p_scale; - -} - -float AudioServerSW::stream_set_volume_scale(RID p_stream) const { - - Stream *s = stream_owner.get(p_stream); - ERR_FAIL_COND_V(!s,0); - return s->volume_scale; - -} - - -void AudioServerSW::free(RID p_id) { - - if(voice_owner.owns(p_id)) { - - Voice *v = voice_owner.get(p_id); - AUDIO_LOCK - mixer->channel_free( v->channel ); - voice_owner.free(p_id); - memdelete(v); - - } else if (stream_owner.owns(p_id)) { - - - Stream *s=stream_owner.get(p_id); - - if (s->active) { - stream_set_active(p_id,false); - } - - memdelete(s); - stream_owner.free(p_id); - - } else if (sample_manager->is_sample(p_id)) { - - AUDIO_LOCK - sample_manager->free(p_id); - } - -} - -void AudioServerSW::_thread_func(void *self) { - - Thread::set_name("AudioServerSW"); - - AudioServerSW *as=(AudioServerSW *)self; - - while (!as->exit_update_thread) { - as->_update_streams(true); - OS::get_singleton()->delay_usec(5000); - } - -} - -void AudioServerSW::init() { - - int latency = GLOBAL_DEF("audio/mixer_latency",10); - internal_buffer_channels=2; // read from driver - internal_buffer = memnew_arr(int32_t,INTERNAL_BUFFER_SIZE*internal_buffer_channels); - stream_buffer = memnew_arr(int32_t,INTERNAL_BUFFER_SIZE*4); //max 4 channels - AudioMixerSW::MixChannels mix_chans = AudioMixerSW::MIX_STEREO; - - switch(AudioDriverSW::get_singleton()->get_output_format()) { - - case AudioDriverSW::OUTPUT_MONO: - case AudioDriverSW::OUTPUT_STEREO: - mix_chans=AudioMixerSW::MIX_STEREO; - break; - case AudioDriverSW::OUTPUT_QUAD: - case AudioDriverSW::OUTPUT_5_1: - mix_chans=AudioMixerSW::MIX_QUAD; - break; - } - - mixer = memnew( AudioMixerSW( sample_manager, latency, AudioDriverSW::get_singleton()->get_mix_rate(),mix_chans,mixer_use_fx,mixer_interp,_mixer_callback,this ) ); - mixer_step_usecs=mixer->get_step_usecs(); - - _output_delay=0; - - stream_volume=0.3; - // start the audio driver - if (AudioDriverSW::get_singleton()) - AudioDriverSW::get_singleton()->start(); - -#ifndef NO_THREADS - exit_update_thread=false; - thread = Thread::create(_thread_func,this); -#endif - -} - -void AudioServerSW::finish() { - -#ifndef NO_THREADS - exit_update_thread=true; - Thread::wait_to_finish(thread); - memdelete(thread); -#endif - - if (AudioDriverSW::get_singleton()) - AudioDriverSW::get_singleton()->finish(); - - memdelete_arr(internal_buffer); - memdelete_arr(stream_buffer); - memdelete(mixer); - -} - -void AudioServerSW::_update_streams(bool p_thread) { - - _THREAD_SAFE_METHOD_ - for(List<Stream*>::Element *E=active_audio_streams.front();E;) { //stream might be removed durnig this callback - - List<Stream*>::Element *N=E->next(); - - if (E->get()->audio_stream && p_thread == E->get()->audio_stream->can_update_mt()) - E->get()->audio_stream->update(); - - E=N; - } - -} - -void AudioServerSW::update() { - - _update_streams(false); -#ifdef NO_THREADS - - _update_streams(true); -#endif -} - - -void AudioServerSW::lock() { - - AudioDriverSW::get_singleton()->lock(); -} - -void AudioServerSW::unlock() { - AudioDriverSW::get_singleton()->unlock(); - -} - -int AudioServerSW::get_default_mix_rate() const { - - return AudioDriverSW::get_singleton()->get_mix_rate(); -} -int AudioServerSW::get_default_channel_count() const { - return internal_buffer_channels; -} - -void AudioServerSW::set_mixer_params(AudioMixerSW::InterpolationType p_interp, bool p_use_fx) { - - mixer_interp=p_interp; - mixer_use_fx=p_use_fx; -} - -void AudioServerSW::set_stream_global_volume_scale(float p_volume) { - - stream_volume_scale=p_volume; -} - -float AudioServerSW::get_stream_global_volume_scale() const { - - return stream_volume_scale; - - -} - -void AudioServerSW::set_fx_global_volume_scale(float p_volume) { - - fx_volume_scale=p_volume; - //mixer->set_mixer_volume(fx_volume_scale); - VoiceRBSW::Command cmd; - cmd.type=VoiceRBSW::Command::CMD_CHANGE_ALL_FX_VOLUMES; - cmd.voice=RID(); - cmd.volume.volume=p_volume; - voice_rb.push_command(cmd); - -} - - -float AudioServerSW::get_fx_global_volume_scale() const { - - return fx_volume_scale; -} - -void AudioServerSW::set_event_voice_global_volume_scale(float p_volume) { - - event_voice_volume_scale=p_volume; - //mixer->set_mixer_volume(event_voice_volume_scale); -} - - -float AudioServerSW::get_event_voice_global_volume_scale() const { - - return event_voice_volume_scale; -} - -double AudioServerSW::get_output_delay() const { - - return _output_delay+AudioDriverSW::get_singleton()->get_latency(); -} - -double AudioServerSW::get_mix_time() const { - - return AudioDriverSW::get_singleton()->get_mix_time(); -} - -uint32_t AudioServerSW::read_output_peak() const { - - uint32_t val = max_peak; - uint32_t *p = (uint32_t*)&max_peak; - *p=0; - return val; -} - -AudioServerSW::AudioServerSW(SampleManagerSW *p_sample_manager) { - - sample_manager=p_sample_manager; - String interp = GLOBAL_DEF("audio/mixer_interp","linear"); - Globals::get_singleton()->set_custom_property_info("audio/mixer_interp",PropertyInfo(Variant::STRING,"audio/mixer_interp",PROPERTY_HINT_ENUM,"raw,linear,cubic")); - if (interp=="raw") - mixer_interp=AudioMixerSW::INTERPOLATION_RAW; - else if (interp=="cubic") - mixer_interp=AudioMixerSW::INTERPOLATION_CUBIC; - else - mixer_interp=AudioMixerSW::INTERPOLATION_LINEAR; - mixer_use_fx = GLOBAL_DEF("audio/use_chorus_reverb",true); - stream_volume_scale=GLOBAL_DEF("audio/stream_volume_scale",1.0); - fx_volume_scale=GLOBAL_DEF("audio/fx_volume_scale",1.0); - event_voice_volume_scale=GLOBAL_DEF("audio/event_voice_volume_scale",0.5); - max_peak=0; - - -} - -AudioServerSW::~AudioServerSW() { - -} - - -AudioDriverSW *AudioDriverSW::singleton=NULL; -AudioDriverSW *AudioDriverSW::get_singleton() { - - return singleton; -} - -void AudioDriverSW::set_singleton() { - - singleton=this; -} - -void AudioDriverSW::audio_server_process(int p_frames,int32_t *p_buffer,bool p_update_mix_time) { - - AudioServerSW * audio_server = static_cast<AudioServerSW*>(AudioServer::get_singleton()); - if (p_update_mix_time) - update_mix_time(p_frames); - audio_server->driver_process(p_frames,p_buffer); -} - -void AudioDriverSW::update_mix_time(int p_frames) { - - _mix_amount+=p_frames; - _last_mix_time=OS::get_singleton()->get_ticks_usec(); -} - -double AudioDriverSW::get_mix_time() const { - - double total = (OS::get_singleton()->get_ticks_usec() - _last_mix_time) / 1000000.0; - total+=_mix_amount/(double)get_mix_rate(); - return total; - -} - - -AudioDriverSW::AudioDriverSW() { - - _last_mix_time=0; - _mix_amount=0; -} - - -AudioDriverSW *AudioDriverManagerSW::drivers[MAX_DRIVERS]; -int AudioDriverManagerSW::driver_count=0; - - - -void AudioDriverManagerSW::add_driver(AudioDriverSW *p_driver) { - - ERR_FAIL_COND(driver_count>=MAX_DRIVERS); - drivers[driver_count++]=p_driver; -} - -int AudioDriverManagerSW::get_driver_count() { - - return driver_count; -} -AudioDriverSW *AudioDriverManagerSW::get_driver(int p_driver) { - - ERR_FAIL_INDEX_V(p_driver,driver_count,NULL); - return drivers[p_driver]; -} - diff --git a/servers/audio/audio_server_sw.h b/servers/audio/audio_server_sw.h deleted file mode 100644 index fda952fa94..0000000000 --- a/servers/audio/audio_server_sw.h +++ /dev/null @@ -1,286 +0,0 @@ -/*************************************************************************/ -/* audio_server_sw.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#ifndef AUDIO_SERVER_SW_H -#define AUDIO_SERVER_SW_H - -#include "servers/audio_server.h" -#include "servers/audio/audio_mixer_sw.h" -#include "servers/audio/voice_rb_sw.h" -#include "self_list.h" -#include "os/thread_safe.h" -#include "os/thread.h" -class AudioServerSW : public AudioServer { - - OBJ_TYPE( AudioServerSW, AudioServer ); - - _THREAD_SAFE_CLASS_ - - enum { - INTERNAL_BUFFER_SIZE=4096, - STREAM_SCALE_BITS=12 - - }; - - SampleManagerSW *sample_manager; - AudioMixerSW *mixer; - - virtual AudioMixer *get_mixer(); - virtual void audio_mixer_chunk_callback(int p_frames); - - struct Voice { - - float volume; - volatile bool active; - SelfList<Voice> active_item; - AudioMixer::ChannelID channel; - - - Voice () : active_item(this) { channel=AudioMixer::INVALID_CHANNEL; active=false;} - }; - - mutable RID_Owner<Voice> voice_owner; - SelfList<Voice>::List active_list; - - struct Stream { - bool active; - List<Stream*>::Element *E; - AudioStream *audio_stream; - EventStream *event_stream; - float volume_scale; - }; - - List<Stream*> active_audio_streams; - - //List<Stream*> event_streams; - - int32_t * internal_buffer; - int internal_buffer_channels; - int32_t * stream_buffer; - - mutable RID_Owner<Stream> stream_owner; - - float stream_volume; - float stream_volume_scale; - float fx_volume_scale; - float event_voice_volume_scale; - float peak_left,peak_right; - uint32_t max_peak; - - double _output_delay; - - VoiceRBSW voice_rb; - - bool exit_update_thread; - Thread *thread; - static void _thread_func(void *self); - - void _update_streams(bool p_thread); - void driver_process_chunk(int p_frames,int32_t *p_buffer); - - AudioMixerSW::InterpolationType mixer_interp; - bool mixer_use_fx; - uint64_t mixer_step_usecs; - - static void _mixer_callback(void *p_udata); -friend class AudioDriverSW; - void driver_process(int p_frames,int32_t *p_buffer); -public: - - - /* SAMPLE API */ - - virtual RID sample_create(SampleFormat p_format, bool p_stereo, int p_length); - - virtual void sample_set_description(RID p_sample, const String& p_description); - virtual String sample_get_description(RID p_sample) const; - - virtual SampleFormat sample_get_format(RID p_sample) const; - virtual bool sample_is_stereo(RID p_sample) const; - virtual int sample_get_length(RID p_sample) const; - const void* sample_get_data_ptr(RID p_sample) const; - - virtual void sample_set_data(RID p_sample, const DVector<uint8_t>& p_buffer); - virtual DVector<uint8_t> sample_get_data(RID p_sample) const; - - virtual void sample_set_mix_rate(RID p_sample,int p_rate); - virtual int sample_get_mix_rate(RID p_sample) const; - - virtual void sample_set_loop_format(RID p_sample,SampleLoopFormat p_format); - virtual SampleLoopFormat sample_get_loop_format(RID p_sample) const; - - virtual void sample_set_loop_begin(RID p_sample,int p_pos); - virtual int sample_get_loop_begin(RID p_sample) const; - - virtual void sample_set_loop_end(RID p_sample,int p_pos); - virtual int sample_get_loop_end(RID p_sample) const; - - /* VOICE API */ - - virtual RID voice_create(); - - virtual void voice_play(RID p_voice, RID p_sample); - - virtual void voice_set_volume(RID p_voice, float p_volume); - virtual void voice_set_pan(RID p_voice, float p_pan, float p_depth=0,float height=0); //pan and depth go from -1 to 1 - virtual void voice_set_filter(RID p_voice, FilterType p_type, float p_cutoff, float p_resonance,float p_gain=0); - virtual void voice_set_chorus(RID p_voice, float p_chorus ); - virtual void voice_set_reverb(RID p_voice, ReverbRoomType p_room_type, float p_reverb); - virtual void voice_set_mix_rate(RID p_voice, int p_mix_rate); - virtual void voice_set_positional(RID p_voice, bool p_positional); - - virtual float voice_get_volume(RID p_voice) const; - virtual float voice_get_pan(RID p_voice) const; //pan and depth go from -1 to 1 - virtual float voice_get_pan_depth(RID p_voice) const; //pan and depth go from -1 to 1 - virtual float voice_get_pan_height(RID p_voice) const; //pan and depth go from -1 to 1 - virtual FilterType voice_get_filter_type(RID p_voice) const; - virtual float voice_get_filter_cutoff(RID p_voice) const; - virtual float voice_get_filter_resonance(RID p_voice) const; - virtual float voice_get_chorus(RID p_voice) const; - virtual ReverbRoomType voice_get_reverb_type(RID p_voice) const; - virtual float voice_get_reverb(RID p_voice) const; - - virtual int voice_get_mix_rate(RID p_voice) const; - virtual bool voice_is_positional(RID p_voice) const; - - virtual void voice_stop(RID p_voice); - virtual bool voice_is_active(RID p_voice) const; - - /* STREAM API */ - - virtual RID audio_stream_create(AudioStream *p_stream); - virtual RID event_stream_create(EventStream *p_stream); - - virtual void stream_set_active(RID p_stream, bool p_active); - virtual bool stream_is_active(RID p_stream) const; - - virtual void stream_set_volume_scale(RID p_stream, float p_scale); - virtual float stream_set_volume_scale(RID p_stream) const; - - virtual void free(RID p_id); - - virtual void init(); - virtual void finish(); - virtual void update(); - - virtual void lock(); - virtual void unlock(); - virtual int get_default_channel_count() const; - virtual int get_default_mix_rate() const; - - void set_mixer_params(AudioMixerSW::InterpolationType p_interp, bool p_use_fx); - - virtual void set_stream_global_volume_scale(float p_volume); - virtual void set_fx_global_volume_scale(float p_volume); - virtual void set_event_voice_global_volume_scale(float p_volume); - - - virtual float get_stream_global_volume_scale() const; - virtual float get_fx_global_volume_scale() const; - virtual float get_event_voice_global_volume_scale() const; - - virtual uint32_t read_output_peak() const; - - virtual double get_mix_time() const; //useful for video -> audio sync - - virtual double get_output_delay() const; - - - AudioServerSW(SampleManagerSW *p_sample_manager); - ~AudioServerSW(); - -}; - - -class AudioDriverSW { - - - static AudioDriverSW *singleton; - uint64_t _last_mix_time; - uint64_t _mix_amount; - - -protected: - - void audio_server_process(int p_frames,int32_t *p_buffer,bool p_update_mix_time=true); - void update_mix_time(int p_frames); - -public: - - - double get_mix_time() const; //useful for video -> audio sync - - enum OutputFormat { - - OUTPUT_MONO, - OUTPUT_STEREO, - OUTPUT_QUAD, - OUTPUT_5_1 - }; - - static AudioDriverSW *get_singleton(); - void set_singleton(); - - virtual const char* get_name() const=0; - - virtual Error init()=0; - virtual void start()=0; - virtual int get_mix_rate() const =0; - virtual OutputFormat get_output_format() const=0; - virtual void lock()=0; - virtual void unlock()=0; - virtual void finish()=0; - - virtual float get_latency() { return 0; } - - - - - AudioDriverSW(); - virtual ~AudioDriverSW() {}; -}; - - - -class AudioDriverManagerSW { - - enum { - - MAX_DRIVERS=10 - }; - - static AudioDriverSW *drivers[MAX_DRIVERS]; - static int driver_count; -public: - - static void add_driver(AudioDriverSW *p_driver); - static int get_driver_count(); - static AudioDriverSW *get_driver(int p_driver); -}; - -#endif // AUDIO_SERVER_SW_H diff --git a/servers/spatial_sound_server.cpp b/servers/audio/audio_stream.cpp index 5f93c55a91..f4214838a1 100644 --- a/servers/spatial_sound_server.cpp +++ b/servers/audio/audio_stream.cpp @@ -1,11 +1,11 @@ /*************************************************************************/ -/* spatial_sound_server.cpp */ +/* audio_stream.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -26,19 +26,61 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "spatial_sound_server.h" +#include "audio_stream.h" -SpatialSoundServer *SpatialSoundServer::singleton=NULL; +////////////////////////////// -SpatialSoundServer *SpatialSoundServer::get_singleton() { - return singleton; +void AudioStreamPlaybackResampled::_begin_resample() { + + //clear cubic interpolation history + internal_buffer[0]=AudioFrame(0.0,0.0); + internal_buffer[1]=AudioFrame(0.0,0.0); + internal_buffer[2]=AudioFrame(0.0,0.0); + internal_buffer[3]=AudioFrame(0.0,0.0); + //mix buffer + _mix_internal(internal_buffer+4,INTERNAL_BUFFER_LEN); + mix_offset=0; } +void AudioStreamPlaybackResampled::mix(AudioFrame* p_buffer,float p_rate_scale,int p_frames) { + + float target_rate = AudioServer::get_singleton()->get_mix_rate() * p_rate_scale; + + uint64_t mix_increment = uint64_t((get_stream_sampling_rate() / double(target_rate)) * double( FP_LEN )); + + for(int i=0;i<p_frames;i++) { + + + + uint32_t idx = CUBIC_INTERP_HISTORY + uint32_t(mix_offset >> FP_BITS); + //standard cubic interpolation (great quality/performance ratio) + //this used to be moved to a LUT for greater performance, but nowadays CPU speed is generally faster than memory. + float mu = (mix_offset&FP_MASK)/float(FP_LEN); + AudioFrame y0 = internal_buffer[idx-3]; + AudioFrame y1 = internal_buffer[idx-2]; + AudioFrame y2 = internal_buffer[idx-1]; + AudioFrame y3 = internal_buffer[idx-0]; + + float mu2 = mu*mu; + AudioFrame a0 = y3 - y2 - y0 + y1; + AudioFrame a1 = y0 - y1 - a0; + AudioFrame a2 = y2 - y0; + AudioFrame a3 = y1; + + p_buffer[i] = (a0*mu*mu2 + a1*mu2 + a2*mu + a3); + + mix_offset+=mix_increment; -SpatialSoundServer::SpatialSoundServer() { + while ( (mix_offset >> FP_BITS) >= INTERNAL_BUFFER_LEN ) { - ERR_FAIL_COND(singleton!=NULL); - singleton=this; + internal_buffer[0]=internal_buffer[INTERNAL_BUFFER_LEN+0]; + internal_buffer[1]=internal_buffer[INTERNAL_BUFFER_LEN+1]; + internal_buffer[2]=internal_buffer[INTERNAL_BUFFER_LEN+2]; + internal_buffer[3]=internal_buffer[INTERNAL_BUFFER_LEN+3]; + _mix_internal(internal_buffer+4,INTERNAL_BUFFER_LEN); + mix_offset-=(INTERNAL_BUFFER_LEN<<FP_BITS); + } + } } diff --git a/servers/spatial_sound_2d_server.cpp b/servers/audio/audio_stream.h index cfe40a0937..d08fedb084 100644 --- a/servers/spatial_sound_2d_server.cpp +++ b/servers/audio/audio_stream.h @@ -1,11 +1,11 @@ /*************************************************************************/ -/* spatial_sound_2d_server.cpp */ +/* audio_stream.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -26,19 +26,76 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "spatial_sound_2d_server.h" +#ifndef AUDIO_STREAM_H +#define AUDIO_STREAM_H -SpatialSound2DServer *SpatialSound2DServer::singleton=NULL; +#include "resource.h" +#include "servers/audio_server.h" +class AudioStreamPlayback : public Reference { -SpatialSound2DServer *SpatialSound2DServer::get_singleton() { + GDCLASS( AudioStreamPlayback, Reference ) - return singleton; -} +public: + virtual void start(float p_from_pos=0.0)=0; + virtual void stop()=0; + virtual bool is_playing() const=0; -SpatialSound2DServer::SpatialSound2DServer() { + virtual int get_loop_count() const=0; //times it looped - ERR_FAIL_COND(singleton!=NULL); - singleton=this; -} + virtual float get_pos() const=0; + virtual void seek_pos(float p_time)=0; + + virtual void mix(AudioFrame* p_bufer,float p_rate_scale,int p_frames)=0; + + virtual float get_length() const=0; //if supported, otherwise return 0 + + +}; + +class AudioStreamPlaybackResampled : public AudioStreamPlayback { + + GDCLASS( AudioStreamPlaybackResampled, AudioStreamPlayback ) + + + + enum { + FP_BITS=16, //fixed point used for resampling + FP_LEN=(1<<FP_BITS), + FP_MASK=FP_LEN-1, + INTERNAL_BUFFER_LEN=256, + CUBIC_INTERP_HISTORY=4 + }; + + AudioFrame internal_buffer[INTERNAL_BUFFER_LEN+CUBIC_INTERP_HISTORY]; + uint64_t mix_offset; + +protected: + void _begin_resample(); + virtual void _mix_internal(AudioFrame* p_bufer,int p_frames)=0; + virtual float get_stream_sampling_rate()=0; + +public: + + virtual void mix(AudioFrame* p_bufer,float p_rate_scale,int p_frames); + + AudioStreamPlaybackResampled() { mix_offset=0; } +}; + +class AudioStream : public Resource { + + GDCLASS( AudioStream, Resource ) + OBJ_SAVE_TYPE( AudioStream ) //children are all saved as AudioStream, so they can be exchanged + + +public: + + virtual Ref<AudioStreamPlayback> instance_playback()=0; + virtual String get_stream_name() const=0; + + +}; + + +#endif // AUDIO_STREAM_H diff --git a/servers/audio/effects/SCsub b/servers/audio/effects/SCsub new file mode 100644 index 0000000000..ccc76e823f --- /dev/null +++ b/servers/audio/effects/SCsub @@ -0,0 +1,7 @@ +#!/usr/bin/env python + +Import('env') + +env.add_source_files(env.servers_sources, "*.cpp") + +Export('env') diff --git a/servers/audio/effects/audio_effect_amplify.cpp b/servers/audio/effects/audio_effect_amplify.cpp new file mode 100644 index 0000000000..fde33dfe63 --- /dev/null +++ b/servers/audio/effects/audio_effect_amplify.cpp @@ -0,0 +1,50 @@ +#include "audio_effect_amplify.h" + + +void AudioEffectAmplifyInstance::process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count) { + + + //multiply volume interpolating to avoid clicks if this changes + float volume_db = base->volume_db; + float vol = Math::db2linear(mix_volume_db); + float vol_inc = (Math::db2linear(volume_db) - vol)/float(p_frame_count); + + for(int i=0;i<p_frame_count;i++) { + p_dst_frames[i]=p_src_frames[i]*vol; + vol+=vol_inc; + } + //set volume for next mix + mix_volume_db = volume_db; + +} + + +Ref<AudioEffectInstance> AudioEffectAmplify::instance() { + Ref<AudioEffectAmplifyInstance> ins; + ins.instance(); + ins->base=Ref<AudioEffectAmplify>(this); + ins->mix_volume_db=volume_db; + return ins; +} + +void AudioEffectAmplify::set_volume_db(float p_volume) { + volume_db=p_volume; +} + +float AudioEffectAmplify::get_volume_db() const { + + return volume_db; +} + +void AudioEffectAmplify::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_volume_db","volume"),&AudioEffectAmplify::set_volume_db); + ClassDB::bind_method(D_METHOD("get_volume_db"),&AudioEffectAmplify::get_volume_db); + + ADD_PROPERTY(PropertyInfo(Variant::REAL,"volume_db",PROPERTY_HINT_RANGE,"-80,24,0.01"),"set_volume_db","get_volume_db"); +} + +AudioEffectAmplify::AudioEffectAmplify() +{ + volume_db=0; +} diff --git a/servers/audio/effects/audio_effect_amplify.h b/servers/audio/effects/audio_effect_amplify.h new file mode 100644 index 0000000000..921054e2cd --- /dev/null +++ b/servers/audio/effects/audio_effect_amplify.h @@ -0,0 +1,40 @@ +#ifndef AUDIOEFFECTAMPLIFY_H +#define AUDIOEFFECTAMPLIFY_H + +#include "servers/audio/audio_effect.h" + +class AudioEffectAmplify; + +class AudioEffectAmplifyInstance : public AudioEffectInstance { + GDCLASS(AudioEffectAmplifyInstance,AudioEffectInstance) +friend class AudioEffectAmplify; + Ref<AudioEffectAmplify> base; + + float mix_volume_db; +public: + + virtual void process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count); + +}; + + +class AudioEffectAmplify : public AudioEffect { + GDCLASS(AudioEffectAmplify,AudioEffect) + +friend class AudioEffectAmplifyInstance; + float volume_db; + +protected: + + static void _bind_methods(); +public: + + + Ref<AudioEffectInstance> instance(); + void set_volume_db(float p_volume); + float get_volume_db() const; + + AudioEffectAmplify(); +}; + +#endif // AUDIOEFFECTAMPLIFY_H diff --git a/servers/audio/effects/audio_effect_chorus.cpp b/servers/audio/effects/audio_effect_chorus.cpp new file mode 100644 index 0000000000..b33aabf24b --- /dev/null +++ b/servers/audio/effects/audio_effect_chorus.cpp @@ -0,0 +1,365 @@ +#include "audio_effect_chorus.h" +#include "servers/audio_server.h" +#include "math_funcs.h" + +void AudioEffectChorusInstance::process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count) { + + int todo = p_frame_count; + + while(todo) { + + int to_mix = MIN(todo,256); //can't mix too much + + _process_chunk(p_src_frames,p_dst_frames,to_mix); + + p_src_frames+=to_mix; + p_dst_frames+=to_mix; + + todo-=to_mix; + } +} + +void AudioEffectChorusInstance::_process_chunk(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count) { + + + //fill ringbuffer + for(int i=0;i<p_frame_count;i++) { + audio_buffer[(buffer_pos+i)&buffer_mask]=p_src_frames[i]; + p_dst_frames[i]=p_src_frames[i]*base->dry; + } + + float mix_rate = AudioServer::get_singleton()->get_mix_rate(); + + /* process voices */ + for (int vc=0;vc<base->voice_count;vc++) { + + AudioEffectChorus::Voice &v=base->voice[vc]; + + + double time_to_mix=(float)p_frame_count/mix_rate; + double cycles_to_mix=time_to_mix*v.rate; + + unsigned int local_rb_pos=buffer_pos; + AudioFrame *dst_buff=p_dst_frames; + AudioFrame *rb_buff=audio_buffer.ptr(); + + double delay_msec=v.delay; + unsigned int delay_frames=Math::fast_ftoi((delay_msec/1000.0)*mix_rate); + float max_depth_frames=(v.depth/1000.0)*mix_rate; + + uint64_t local_cycles=cycles[vc]; + uint64_t increment=llrint(cycles_to_mix/(double)p_frame_count*(double)(1<<AudioEffectChorus::CYCLES_FRAC)); + + //check the LFO doesnt read ahead of the write pos + if ((((int)max_depth_frames)+10)>delay_frames) { //10 as some threshold to avoid precision stuff + delay_frames+=(int)max_depth_frames-delay_frames; + delay_frames+=10; //threshold to avoid precision stuff + + } + + + + //low pass filter + if (v.cutoff==0) + continue; + float auxlp=expf(-2.0*Math_PI*v.cutoff/mix_rate); + float c1=1.0-auxlp; + float c2=auxlp; + AudioFrame h=filter_h[vc]; + if (v.cutoff>=AudioEffectChorus::MS_CUTOFF_MAX) { + c1=1.0; c2=0.0; + } + + //vol modifier + + AudioFrame vol_modifier=AudioFrame(base->wet,base->wet) * Math::db2linear(v.level); + vol_modifier.l*=CLAMP( 1.0 - v.pan, 0, 1); + vol_modifier.r*=CLAMP( 1.0 + v.pan, 0, 1); + + + + for (int i=0;i<p_frame_count;i++) { + + /** COMPUTE WAVEFORM **/ + + float phase=(float)(local_cycles&AudioEffectChorus::CYCLES_MASK)/(float)(1<<AudioEffectChorus::CYCLES_FRAC); + + float wave_delay=sinf(phase*2.0*Math_PI)*max_depth_frames; + + int wave_delay_frames=lrint(floor(wave_delay)); + float wave_delay_frac=wave_delay-(float)wave_delay_frames; + + /** COMPUTE RINGBUFFER POS**/ + + unsigned int rb_source=local_rb_pos; + rb_source-=delay_frames; + + rb_source-=wave_delay_frames; + + /** READ FROM RINGBUFFER, LINEARLY INTERPOLATE */ + + AudioFrame val=rb_buff[rb_source&buffer_mask]; + AudioFrame val_next=rb_buff[(rb_source-1)&buffer_mask]; + + val+=(val_next-val)*wave_delay_frac; + + val=val*c1+h*c2; + h=val; + + /** MIX VALUE TO OUTPUT **/ + + dst_buff[i]+=val*vol_modifier; + + local_cycles+=increment; + local_rb_pos++; + + } + + filter_h[vc]=h; + cycles[vc]+=Math::fast_ftoi(cycles_to_mix*(double)(1<<AudioEffectChorus::CYCLES_FRAC)); + } + + buffer_pos+=p_frame_count; +} + + +Ref<AudioEffectInstance> AudioEffectChorus::instance() { + + Ref<AudioEffectChorusInstance> ins; + ins.instance(); + ins->base=Ref<AudioEffectChorus>(this); + for(int i=0;i<4;i++) { + ins->filter_h[i]=AudioFrame(0,0); + ins->cycles[i]=0; + } + + float ring_buffer_max_size=AudioEffectChorus::MAX_DELAY_MS+AudioEffectChorus::MAX_DEPTH_MS+AudioEffectChorus::MAX_WIDTH_MS; + + ring_buffer_max_size*=2; //just to avoid complications + ring_buffer_max_size/=1000.0;//convert to seconds + ring_buffer_max_size*=AudioServer::get_singleton()->get_mix_rate(); + + int ringbuff_size=ring_buffer_max_size; + + int bits=0; + + while(ringbuff_size>0) { + bits++; + ringbuff_size/=2; + } + + ringbuff_size=1<<bits; + ins->buffer_mask=ringbuff_size-1; + ins->buffer_pos=0; + ins->audio_buffer.resize(ringbuff_size); + for(int i=0;i<ringbuff_size;i++) { + ins->audio_buffer[i]=AudioFrame(0,0); + } + + return ins; +} + +void AudioEffectChorus::set_voice_count(int p_voices) { + + ERR_FAIL_COND(p_voices<1 || p_voices>=MAX_VOICES); + voice_count=p_voices; + _change_notify(); +} + + +int AudioEffectChorus::get_voice_count() const{ + + return voice_count; +} + +void AudioEffectChorus::set_voice_delay_ms(int p_voice,float p_delay_ms){ + + ERR_FAIL_INDEX(p_voice,MAX_VOICES); + + voice[p_voice].delay=p_delay_ms; + +} +float AudioEffectChorus::get_voice_delay_ms(int p_voice) const{ + + ERR_FAIL_INDEX_V(p_voice,MAX_VOICES,0); + return voice[p_voice].delay; +} + +void AudioEffectChorus::set_voice_rate_hz(int p_voice,float p_rate_hz){ + ERR_FAIL_INDEX(p_voice,MAX_VOICES); + + voice[p_voice].rate=p_rate_hz; +} +float AudioEffectChorus::get_voice_rate_hz(int p_voice) const{ + + ERR_FAIL_INDEX_V(p_voice,MAX_VOICES,0); + + return voice[p_voice].rate; +} + +void AudioEffectChorus::set_voice_depth_ms(int p_voice,float p_depth_ms){ + + ERR_FAIL_INDEX(p_voice,MAX_VOICES); + + voice[p_voice].depth=p_depth_ms; +} +float AudioEffectChorus::get_voice_depth_ms(int p_voice) const{ + + ERR_FAIL_INDEX_V(p_voice,MAX_VOICES,0); + + return voice[p_voice].depth; +} + +void AudioEffectChorus::set_voice_level_db(int p_voice,float p_level_db){ + + ERR_FAIL_INDEX(p_voice,MAX_VOICES); + + voice[p_voice].level=p_level_db; +} +float AudioEffectChorus::get_voice_level_db(int p_voice) const{ + + ERR_FAIL_INDEX_V(p_voice,MAX_VOICES,0); + + return voice[p_voice].level; +} + + +void AudioEffectChorus::set_voice_cutoff_hz(int p_voice,float p_cutoff_hz){ + + ERR_FAIL_INDEX(p_voice,MAX_VOICES); + + voice[p_voice].cutoff=p_cutoff_hz; +} +float AudioEffectChorus::get_voice_cutoff_hz(int p_voice) const{ + + ERR_FAIL_INDEX_V(p_voice,MAX_VOICES,0); + + return voice[p_voice].cutoff; +} + +void AudioEffectChorus::set_voice_pan(int p_voice,float p_pan){ + + ERR_FAIL_INDEX(p_voice,MAX_VOICES); + + voice[p_voice].pan=p_pan; +} +float AudioEffectChorus::get_voice_pan(int p_voice) const{ + + ERR_FAIL_INDEX_V(p_voice,MAX_VOICES,0); + + return voice[p_voice].pan; +} + + +void AudioEffectChorus::set_wet(float amount){ + + + wet=amount; +} +float AudioEffectChorus::get_wet() const{ + + return wet; +} + +void AudioEffectChorus::set_dry(float amount){ + + dry=amount; + +} +float AudioEffectChorus::get_dry() const{ + + return dry; +} + +void AudioEffectChorus::_validate_property(PropertyInfo& property) const { + + if (property.name.begins_with("voice/")) { + int voice_idx = property.name.get_slice("/",1).to_int(); + if (voice_idx>voice_count) { + property.usage=0; + } + } +} + + +void AudioEffectChorus::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_voice_count","voices"),&AudioEffectChorus::set_voice_count); + ClassDB::bind_method(D_METHOD("get_voice_count"),&AudioEffectChorus::get_voice_count); + + + ClassDB::bind_method(D_METHOD("set_voice_delay_ms","voice_idx","delay_ms"),&AudioEffectChorus::set_voice_delay_ms); + ClassDB::bind_method(D_METHOD("get_voice_delay_ms","voice_idx"),&AudioEffectChorus::get_voice_delay_ms); + + ClassDB::bind_method(D_METHOD("set_voice_rate_hz","voice_idx","rate_hz"),&AudioEffectChorus::set_voice_rate_hz); + ClassDB::bind_method(D_METHOD("get_voice_rate_hz","voice_idx"),&AudioEffectChorus::get_voice_rate_hz); + + ClassDB::bind_method(D_METHOD("set_voice_depth_ms","voice_idx","depth_ms"),&AudioEffectChorus::set_voice_depth_ms); + ClassDB::bind_method(D_METHOD("get_voice_depth_ms","voice_idx"),&AudioEffectChorus::get_voice_depth_ms); + + ClassDB::bind_method(D_METHOD("set_voice_level_db","voice_idx","level_db"),&AudioEffectChorus::set_voice_level_db); + ClassDB::bind_method(D_METHOD("get_voice_level_db","voice_idx"),&AudioEffectChorus::get_voice_level_db); + + ClassDB::bind_method(D_METHOD("set_voice_cutoff_hz","voice_idx","cutoff_hz"),&AudioEffectChorus::set_voice_cutoff_hz); + ClassDB::bind_method(D_METHOD("get_voice_cutoff_hz","voice_idx"),&AudioEffectChorus::get_voice_cutoff_hz); + + ClassDB::bind_method(D_METHOD("set_voice_pan","voice_idx","pan"),&AudioEffectChorus::set_voice_pan); + ClassDB::bind_method(D_METHOD("get_voice_pan","voice_idx"),&AudioEffectChorus::get_voice_pan); + + ClassDB::bind_method(D_METHOD("set_wet","amount"),&AudioEffectChorus::set_wet); + ClassDB::bind_method(D_METHOD("get_wet"),&AudioEffectChorus::get_wet); + + ClassDB::bind_method(D_METHOD("set_dry","amount"),&AudioEffectChorus::set_dry); + ClassDB::bind_method(D_METHOD("get_dry"),&AudioEffectChorus::get_dry); + + ADD_PROPERTY(PropertyInfo(Variant::INT,"voice_count",PROPERTY_HINT_RANGE,"1,4,1"),"set_voice_count","get_voice_count"); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"dry",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_dry","get_dry"); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"wet",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_wet","get_wet"); + + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/1/delay_ms",PROPERTY_HINT_RANGE,"0,50,0.01"),"set_voice_delay_ms","get_voice_delay_ms",0); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/1/rate_hz",PROPERTY_HINT_RANGE,"0.1,20,0.1"),"set_voice_rate_hz","get_voice_rate_hz",0); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/1/depth_ms",PROPERTY_HINT_RANGE,"0,20,0.01"),"set_voice_depth_ms","get_voice_depth_ms",0); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/1/level_db",PROPERTY_HINT_RANGE,"-60,24,0.1"),"set_voice_level_db","get_voice_level_db",0); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/1/cutoff_hz",PROPERTY_HINT_RANGE,"1,16000,1"),"set_voice_cutoff_hz","get_voice_cutoff_hz",0); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/1/pan",PROPERTY_HINT_RANGE,"-1,1,0.01"),"set_voice_pan","get_voice_pan",0); + + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/2/delay_ms",PROPERTY_HINT_RANGE,"0,50,0.01"),"set_voice_delay_ms","get_voice_delay_ms",1); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/2/rate_hz",PROPERTY_HINT_RANGE,"0.1,20,0.1"),"set_voice_rate_hz","get_voice_rate_hz",1); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/2/depth_ms",PROPERTY_HINT_RANGE,"0,20,0.01"),"set_voice_depth_ms","get_voice_depth_ms",1); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/2/level_db",PROPERTY_HINT_RANGE,"-60,24,0.1"),"set_voice_level_db","get_voice_level_db",1); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/2/cutoff_hz",PROPERTY_HINT_RANGE,"1,16000,1"),"set_voice_cutoff_hz","get_voice_cutoff_hz",1); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/2/pan",PROPERTY_HINT_RANGE,"-1,1,0.01"),"set_voice_pan","get_voice_pan",1); + + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/3/delay_ms",PROPERTY_HINT_RANGE,"0,50,0.01"),"set_voice_delay_ms","get_voice_delay_ms",2); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/3/rate_hz",PROPERTY_HINT_RANGE,"0.1,20,0.1"),"set_voice_rate_hz","get_voice_rate_hz",2); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/3/depth_ms",PROPERTY_HINT_RANGE,"0,20,0.01"),"set_voice_depth_ms","get_voice_depth_ms",2); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/3/level_db",PROPERTY_HINT_RANGE,"-60,24,0.1"),"set_voice_level_db","get_voice_level_db",2); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/3/cutoff_hz",PROPERTY_HINT_RANGE,"1,16000,1"),"set_voice_cutoff_hz","get_voice_cutoff_hz",2); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/3/pan",PROPERTY_HINT_RANGE,"-1,1,0.01"),"set_voice_pan","get_voice_pan",2); + + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/4/delay_ms",PROPERTY_HINT_RANGE,"0,50,0.01"),"set_voice_delay_ms","get_voice_delay_ms",3); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/4/rate_hz",PROPERTY_HINT_RANGE,"0.1,20,0.1"),"set_voice_rate_hz","get_voice_rate_hz",3); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/4/depth_ms",PROPERTY_HINT_RANGE,"0,20,0.01"),"set_voice_depth_ms","get_voice_depth_ms",3); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/4/level_db",PROPERTY_HINT_RANGE,"-60,24,0.1"),"set_voice_level_db","get_voice_level_db",3); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/4/cutoff_hz",PROPERTY_HINT_RANGE,"1,16000,1"),"set_voice_cutoff_hz","get_voice_cutoff_hz",3); + ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/4/pan",PROPERTY_HINT_RANGE,"-1,1,0.01"),"set_voice_pan","get_voice_pan",3); + +} + +AudioEffectChorus::AudioEffectChorus() +{ + voice_count=2; + voice[0].delay=15; + voice[1].delay=20; + voice[0].rate=0.8; + voice[1].rate=1.2; + voice[0].depth=2; + voice[1].depth=3; + voice[0].cutoff=8000; + voice[1].cutoff=8000; + voice[0].pan=-0.5; + voice[1].pan=0.5; + + wet=0.5; + dry=1.0; +} diff --git a/servers/audio/effects/audio_effect_chorus.h b/servers/audio/effects/audio_effect_chorus.h new file mode 100644 index 0000000000..4cfba5d61a --- /dev/null +++ b/servers/audio/effects/audio_effect_chorus.h @@ -0,0 +1,115 @@ +#ifndef AUDIOEFFECTCHORUS_H +#define AUDIOEFFECTCHORUS_H + + +#include "servers/audio/audio_effect.h" + +class AudioEffectChorus; + +class AudioEffectChorusInstance : public AudioEffectInstance { + GDCLASS(AudioEffectChorusInstance,AudioEffectInstance) +friend class AudioEffectChorus; + Ref<AudioEffectChorus> base; + + Vector<AudioFrame> audio_buffer; + unsigned int buffer_pos; + unsigned int buffer_mask; + + AudioFrame filter_h[4]; + uint64_t cycles[4]; + + void _process_chunk(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count); + +public: + + virtual void process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count); + +}; + + +class AudioEffectChorus : public AudioEffect { + GDCLASS(AudioEffectChorus,AudioEffect) + +friend class AudioEffectChorusInstance; +public: + enum { + + MAX_DELAY_MS=50, + MAX_DEPTH_MS=20, + MAX_WIDTH_MS=50, + MAX_VOICES=4, + CYCLES_FRAC=16, + CYCLES_MASK=(1<<CYCLES_FRAC)-1, + MAX_CHANNELS=4, + MS_CUTOFF_MAX=16000 + }; + +private: + + struct Voice { + + float delay; + float rate; + float depth; + float level; + float cutoff; + float pan; + + Voice() { + + delay=12.0; + rate=1; + depth=0; + level=0; + cutoff=MS_CUTOFF_MAX; + pan=0; + + } + + } voice[MAX_VOICES]; + + int voice_count; + + float wet; + float dry; + + +protected: + void _validate_property(PropertyInfo& property) const; + + static void _bind_methods(); +public: + + void set_voice_count(int p_voices); + int get_voice_count() const; + + void set_voice_delay_ms(int p_voice,float p_delay_ms); + float get_voice_delay_ms(int p_voice) const; + + void set_voice_rate_hz(int p_voice,float p_rate_hz); + float get_voice_rate_hz(int p_voice) const; + + void set_voice_depth_ms(int p_voice,float p_depth_ms); + float get_voice_depth_ms(int p_voice) const; + + void set_voice_level_db(int p_voice,float p_level_db); + float get_voice_level_db(int p_voice) const; + + void set_voice_cutoff_hz(int p_voice,float p_cutoff_hz); + float get_voice_cutoff_hz(int p_voice) const; + + void set_voice_pan(int p_voice,float p_pan); + float get_voice_pan(int p_voice) const; + + void set_wet(float amount); + float get_wet() const; + + void set_dry(float amount); + float get_dry() const; + + Ref<AudioEffectInstance> instance(); + + AudioEffectChorus(); +}; + +#endif // AUDIOEFFECTCHORUS_H diff --git a/servers/audio/effects/audio_effect_compressor.cpp b/servers/audio/effects/audio_effect_compressor.cpp new file mode 100644 index 0000000000..d20c5bb4bd --- /dev/null +++ b/servers/audio/effects/audio_effect_compressor.cpp @@ -0,0 +1,227 @@ +#include "audio_effect_compressor.h" +#include "servers/audio_server.h" + +void AudioEffectCompressorInstance::process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count) { + + + float treshold = Math::db2linear(base->treshold); + float sample_rate=AudioServer::get_singleton()->get_mix_rate(); + + float ratatcoef = exp(-1 / (0.00001f * sample_rate)); + float ratrelcoef = exp(-1 / (0.5f * sample_rate)); + float attime = base->attack_us / 1000000.0; + float reltime = base->release_ms / 1000.0; + float atcoef = exp(-1 / (attime * sample_rate)); + float relcoef = exp(-1 / (reltime * sample_rate)); + + float makeup = Math::db2linear(base->gain); + + float mix = base->mix; + float gr_meter_decay = exp(1 / (1 * sample_rate)); + + const AudioFrame *src = p_src_frames; + + if (base->sidechain!=StringName() && current_channel!=-1) { + + int bus = AudioServer::get_singleton()->thread_find_bus_index(base->sidechain); + if (bus>=0) { + src = AudioServer::get_singleton()->thread_get_channel_mix_buffer(bus,current_channel); + } + } + + for(int i=0;i<p_frame_count;i++) { + + AudioFrame s = src[i]; + //convert to positive + s.l = Math::abs(s.l); + s.r = Math::abs(s.r); + + float peak = MAX(s.l,s.r); + + float overdb = 2.08136898f * Math::linear2db(peak/treshold); + + if (overdb<0.0) //we only care about what goes over to compress + overdb=0.0; + + if(overdb-rundb>5) // diffeence is too large + averatio = 4; + + if(overdb > rundb) { + rundb = overdb + atcoef * (rundb - overdb); + runratio = averatio + ratatcoef * (runratio - averatio); + } else { + rundb = overdb + relcoef * (rundb - overdb); + runratio = averatio + ratrelcoef * (runratio - averatio); + } + + overdb = rundb; + averatio = runratio; + + float cratio; + + if(false) { //rato all-in + cratio = 12 + averatio; + } else { + cratio = base->ratio; + } + + float gr = -overdb * (cratio-1)/cratio; + float grv = Math::db2linear(gr); + + runmax = maxover + relcoef * (runmax - maxover); // highest peak for setting att/rel decays in reltime + maxover = runmax; + + if (grv < gr_meter) { + gr_meter=grv; + } else { + gr_meter*=gr_meter_decay; + if(gr_meter>1) + gr_meter=1; + } + + + p_dst_frames[i] = p_src_frames[i] * grv * makeup * mix + p_src_frames[i] * (1.0-mix); + + } + +} + + +Ref<AudioEffectInstance> AudioEffectCompressor::instance() { + Ref<AudioEffectCompressorInstance> ins; + ins.instance(); + ins->base=Ref<AudioEffectCompressor>(this); + ins->rundb=0; + ins->runratio=0; + ins->averatio=0; + ins->runmax=0; + ins->maxover=0; + ins->gr_meter=1.0; + ins->current_channel=-1; + return ins; +} + + +void AudioEffectCompressor::set_treshold(float p_treshold) { + + treshold=p_treshold; +} + +float AudioEffectCompressor::get_treshold() const { + + return treshold; +} + +void AudioEffectCompressor::set_ratio(float p_ratio) { + + ratio=p_ratio; +} +float AudioEffectCompressor::get_ratio() const { + + return ratio; +} + +void AudioEffectCompressor::set_gain(float p_gain) { + + gain=p_gain; +} +float AudioEffectCompressor::get_gain() const { + + return gain; +} + +void AudioEffectCompressor::set_attack_us(float p_attack_us) { + + attack_us=p_attack_us; +} +float AudioEffectCompressor::get_attack_us() const { + + return attack_us; +} + +void AudioEffectCompressor::set_release_ms(float p_release_ms) { + + release_ms=p_release_ms; +} +float AudioEffectCompressor::get_release_ms() const { + + return release_ms; +} + +void AudioEffectCompressor::set_mix(float p_mix) { + + mix=p_mix; +} +float AudioEffectCompressor::get_mix() const { + + return mix; +} + +void AudioEffectCompressor::set_sidechain(const StringName& p_sidechain) { + + AudioServer::get_singleton()->lock(); + sidechain=p_sidechain; + AudioServer::get_singleton()->unlock(); +} + +StringName AudioEffectCompressor::get_sidechain() const { + + return sidechain; +} + +void AudioEffectCompressor::_validate_property(PropertyInfo& property) const { + + if (property.name=="sidechain") { + + String buses=""; + for(int i=0;i<AudioServer::get_singleton()->get_bus_count();i++) { + buses+=","; + buses+=AudioServer::get_singleton()->get_bus_name(i); + } + + property.hint_string=buses; + } +} + +void AudioEffectCompressor::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_treshold","treshold"),&AudioEffectCompressor::set_treshold); + ClassDB::bind_method(D_METHOD("get_treshold"),&AudioEffectCompressor::get_treshold); + + ClassDB::bind_method(D_METHOD("set_ratio","ratio"),&AudioEffectCompressor::set_ratio); + ClassDB::bind_method(D_METHOD("get_ratio"),&AudioEffectCompressor::get_ratio); + + ClassDB::bind_method(D_METHOD("set_gain","gain"),&AudioEffectCompressor::set_gain); + ClassDB::bind_method(D_METHOD("get_gain"),&AudioEffectCompressor::get_gain); + + ClassDB::bind_method(D_METHOD("set_attack_us","attack_us"),&AudioEffectCompressor::set_attack_us); + ClassDB::bind_method(D_METHOD("get_attack_us"),&AudioEffectCompressor::get_attack_us); + + ClassDB::bind_method(D_METHOD("set_release_ms","release_ms"),&AudioEffectCompressor::set_release_ms); + ClassDB::bind_method(D_METHOD("get_release_ms"),&AudioEffectCompressor::get_release_ms); + + ClassDB::bind_method(D_METHOD("set_mix","mix"),&AudioEffectCompressor::set_mix); + ClassDB::bind_method(D_METHOD("get_mix"),&AudioEffectCompressor::get_mix); + + ClassDB::bind_method(D_METHOD("set_sidechain","sidechain"),&AudioEffectCompressor::set_sidechain); + ClassDB::bind_method(D_METHOD("get_sidechain"),&AudioEffectCompressor::get_sidechain); + + ADD_PROPERTY(PropertyInfo(Variant::REAL,"treshold",PROPERTY_HINT_RANGE,"-60,0,0.1"),"set_treshold","get_treshold"); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"ratio",PROPERTY_HINT_RANGE,"1,48,0.1"),"set_ratio","get_ratio"); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"gain",PROPERTY_HINT_RANGE,"-20,20,0.1"),"set_gain","get_gain"); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"attack_us",PROPERTY_HINT_RANGE,"20,2000,1"),"set_attack_us","get_attack_us"); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"release_ms",PROPERTY_HINT_RANGE,"20,2000,1"),"set_release_ms","get_release_ms"); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"mix",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_mix","get_mix"); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"sidechain",PROPERTY_HINT_ENUM),"set_sidechain","get_sidechain"); + +} + +AudioEffectCompressor::AudioEffectCompressor() +{ + treshold=0; + ratio=4; + gain=0; + attack_us=20; + release_ms=250; + mix=1; +} diff --git a/servers/audio/effects/audio_effect_compressor.h b/servers/audio/effects/audio_effect_compressor.h new file mode 100644 index 0000000000..eb06b3db77 --- /dev/null +++ b/servers/audio/effects/audio_effect_compressor.h @@ -0,0 +1,70 @@ +#ifndef AUDIOEFFECTCOMPRESSOR_H +#define AUDIOEFFECTCOMPRESSOR_H + + +#include "servers/audio/audio_effect.h" + +class AudioEffectCompressor; + +class AudioEffectCompressorInstance : public AudioEffectInstance { + GDCLASS(AudioEffectCompressorInstance,AudioEffectInstance) +friend class AudioEffectCompressor; + Ref<AudioEffectCompressor> base; + + float rundb,averatio,runratio,runmax,maxover,gr_meter; + int current_channel; +public: + + void set_current_channel(int p_channel) { current_channel=p_channel; } + virtual void process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count); + +}; + + +class AudioEffectCompressor : public AudioEffect { + GDCLASS(AudioEffectCompressor,AudioEffect) + +friend class AudioEffectCompressorInstance; + float treshold; + float ratio; + float gain; + float attack_us; + float release_ms; + float mix; + StringName sidechain; + + +protected: + void _validate_property(PropertyInfo& property) const; + static void _bind_methods(); +public: + + + Ref<AudioEffectInstance> instance(); + + + void set_treshold(float p_treshold); + float get_treshold() const; + + void set_ratio(float p_ratio); + float get_ratio() const; + + void set_gain(float p_gain); + float get_gain() const; + + void set_attack_us(float p_attack_us); + float get_attack_us() const; + + void set_release_ms(float p_release_ms); + float get_release_ms() const; + + void set_mix(float p_mix); + float get_mix() const; + + void set_sidechain(const StringName& p_sidechain); + StringName get_sidechain() const; + + AudioEffectCompressor(); +}; + +#endif // AUDIOEFFECTCOMPRESSOR_H diff --git a/servers/audio/effects/audio_effect_delay.cpp b/servers/audio/effects/audio_effect_delay.cpp new file mode 100644 index 0000000000..3d3a956b92 --- /dev/null +++ b/servers/audio/effects/audio_effect_delay.cpp @@ -0,0 +1,326 @@ +#include "audio_effect_delay.h" +#include "servers/audio_server.h" +#include "math_funcs.h" + +void AudioEffectDelayInstance::process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count) { + + int todo = p_frame_count; + + while(todo) { + + int to_mix = MIN(todo,256); //can't mix too much + + _process_chunk(p_src_frames,p_dst_frames,to_mix); + + p_src_frames+=to_mix; + p_dst_frames+=to_mix; + + todo-=to_mix; + } +} + +void AudioEffectDelayInstance::_process_chunk(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count) { + + + + float main_level_f=base->dry; + + + float mix_rate = AudioServer::get_singleton()->get_mix_rate(); + + float tap_1_level_f=base->tap_1_active?Math::db2linear(base->tap_1_level):0.0; + int tap_1_delay_frames=int((base->tap_1_delay_ms/1000.0)*mix_rate);; + + float tap_2_level_f=base->tap_2_active?Math::db2linear(base->tap_2_level):0.0; + int tap_2_delay_frames=int((base->tap_2_delay_ms/1000.0)*mix_rate);; + + float feedback_level_f=base->feedback_active?Math::db2linear(base->feedback_level):0.0; + unsigned int feedback_delay_frames=int((base->feedback_delay_ms/1000.0)*mix_rate);; + + + AudioFrame tap1_vol=AudioFrame(tap_1_level_f,tap_1_level_f); + + tap1_vol.l*=CLAMP( 1.0 - base->tap_1_pan, 0, 1); + tap1_vol.r*=CLAMP( 1.0 + base->tap_1_pan, 0, 1); + + AudioFrame tap2_vol=AudioFrame(tap_2_level_f,tap_2_level_f); + + tap2_vol.l*=CLAMP( 1.0 - base->tap_2_pan, 0, 1); + tap2_vol.r*=CLAMP( 1.0 + base->tap_2_pan, 0, 1); + + // feedback lowpass here + float lpf_c=expf(-2.0*Math_PI*base->feedback_lowpass/mix_rate); // 0 .. 10khz + float lpf_ic=1.0-lpf_c; + + const AudioFrame *src=p_src_frames; + AudioFrame *dst=p_dst_frames; + AudioFrame *rb_buf=ring_buffer.ptr(); + AudioFrame *fb_buf=feedback_buffer.ptr(); + + + for (int i=0;i<p_frame_count;i++) { + + + rb_buf[ring_buffer_pos&ring_buffer_mask]=src[i]; + + AudioFrame main_val=src[i]*main_level_f; + AudioFrame tap_1_val=rb_buf[(ring_buffer_pos-tap_1_delay_frames)&ring_buffer_mask]*tap1_vol; + AudioFrame tap_2_val=rb_buf[(ring_buffer_pos-tap_2_delay_frames)&ring_buffer_mask]*tap2_vol; + + AudioFrame out=main_val+tap_1_val+tap_2_val; + + out+=fb_buf[ feedback_buffer_pos ]; + + //apply lowpass and feedback gain + AudioFrame fb_in=out*feedback_level_f*lpf_ic+h*lpf_c; + fb_in.undenormalise(); //avoid denormals + + h=fb_in; + fb_buf[ feedback_buffer_pos ]=fb_in; + + dst[i]=out; + + ring_buffer_pos++; + + if ( (++feedback_buffer_pos) >= feedback_delay_frames ) + feedback_buffer_pos=0; + } +} + + + +Ref<AudioEffectInstance> AudioEffectDelay::instance() { + Ref<AudioEffectDelayInstance> ins; + ins.instance(); + ins->base=Ref<AudioEffectDelay>(this); + + float ring_buffer_max_size=MAX_DELAY_MS+100; //add 100ms of extra room, just in case + ring_buffer_max_size/=1000.0;//convert to seconds + ring_buffer_max_size*=AudioServer::get_singleton()->get_mix_rate(); + + int ringbuff_size=ring_buffer_max_size; + + int bits=0; + + while(ringbuff_size>0) { + bits++; + ringbuff_size/=2; + } + + ringbuff_size=1<<bits; + ins->ring_buffer_mask=ringbuff_size-1; + ins->ring_buffer_pos=0; + + ins->ring_buffer.resize( ringbuff_size ); + ins->feedback_buffer.resize( ringbuff_size ); + + ins->feedback_buffer_pos=0; + + ins->h=AudioFrame(0,0); + + return ins; +} + + +void AudioEffectDelay::set_dry(float p_dry) { + + dry=p_dry; +} + +float AudioEffectDelay::get_dry(){ + + return dry; +} + +void AudioEffectDelay::set_tap1_active(bool p_active){ + + tap_1_active=p_active; +} +bool AudioEffectDelay::is_tap1_active() const{ + + return tap_1_active; +} + +void AudioEffectDelay::set_tap1_delay_ms(float p_delay_ms){ + + tap_1_delay_ms=p_delay_ms; +} +float AudioEffectDelay::get_tap1_delay_ms() const{ + + return tap_1_delay_ms; +} + +void AudioEffectDelay::set_tap1_level_db(float p_level_db){ + + tap_1_level=p_level_db; +} +float AudioEffectDelay::get_tap1_level_db() const{ + + return tap_1_level; +} + +void AudioEffectDelay::set_tap1_pan(float p_pan){ + + tap_1_pan=p_pan; +} +float AudioEffectDelay::get_tap1_pan() const{ + + return tap_1_pan; +} + + +void AudioEffectDelay::set_tap2_active(bool p_active){ + + tap_2_active=p_active; +} +bool AudioEffectDelay::is_tap2_active() const{ + + return tap_2_active; +} + +void AudioEffectDelay::set_tap2_delay_ms(float p_delay_ms){ + + tap_2_delay_ms=p_delay_ms; +} +float AudioEffectDelay::get_tap2_delay_ms() const{ + + return tap_2_delay_ms; +} + +void AudioEffectDelay::set_tap2_level_db(float p_level_db){ + + tap_2_level=p_level_db; +} +float AudioEffectDelay::get_tap2_level_db() const{ + + return tap_2_level; +} + +void AudioEffectDelay::set_tap2_pan(float p_pan){ + + tap_2_pan=p_pan; +} +float AudioEffectDelay::get_tap2_pan() const{ + + return tap_2_pan; +} + +void AudioEffectDelay::set_feedback_active(bool p_active){ + + feedback_active=p_active; +} +bool AudioEffectDelay::is_feedback_active() const{ + + return feedback_active; +} + +void AudioEffectDelay::set_feedback_delay_ms(float p_delay_ms){ + + feedback_delay_ms=p_delay_ms; +} +float AudioEffectDelay::get_feedback_delay_ms() const{ + + return feedback_delay_ms; +} + +void AudioEffectDelay::set_feedback_level_db(float p_level_db){ + + feedback_level=p_level_db; +} +float AudioEffectDelay::get_feedback_level_db() const{ + + return feedback_level; +} + +void AudioEffectDelay::set_feedback_lowpass(float p_lowpass){ + + feedback_lowpass=p_lowpass; +} +float AudioEffectDelay::get_feedback_lowpass() const{ + + return feedback_lowpass; +} + + +void AudioEffectDelay::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_dry","amount"),&AudioEffectDelay::set_dry); + ClassDB::bind_method(D_METHOD("get_dry"),&AudioEffectDelay::get_dry); + + ClassDB::bind_method(D_METHOD("set_tap1_active","amount"),&AudioEffectDelay::set_tap1_active); + ClassDB::bind_method(D_METHOD("is_tap1_active"),&AudioEffectDelay::is_tap1_active); + + ClassDB::bind_method(D_METHOD("set_tap1_delay_ms","amount"),&AudioEffectDelay::set_tap1_delay_ms); + ClassDB::bind_method(D_METHOD("get_tap1_delay_ms"),&AudioEffectDelay::get_tap1_delay_ms); + + ClassDB::bind_method(D_METHOD("set_tap1_level_db","amount"),&AudioEffectDelay::set_tap1_level_db); + ClassDB::bind_method(D_METHOD("get_tap1_level_db"),&AudioEffectDelay::get_tap1_level_db); + + ClassDB::bind_method(D_METHOD("set_tap1_pan","amount"),&AudioEffectDelay::set_tap1_pan); + ClassDB::bind_method(D_METHOD("get_tap1_pan"),&AudioEffectDelay::get_tap1_pan); + + ClassDB::bind_method(D_METHOD("set_tap2_active","amount"),&AudioEffectDelay::set_tap2_active); + ClassDB::bind_method(D_METHOD("is_tap2_active"),&AudioEffectDelay::is_tap2_active); + + ClassDB::bind_method(D_METHOD("set_tap2_delay_ms","amount"),&AudioEffectDelay::set_tap2_delay_ms); + ClassDB::bind_method(D_METHOD("get_tap2_delay_ms"),&AudioEffectDelay::get_tap2_delay_ms); + + ClassDB::bind_method(D_METHOD("set_tap2_level_db","amount"),&AudioEffectDelay::set_tap2_level_db); + ClassDB::bind_method(D_METHOD("get_tap2_level_db"),&AudioEffectDelay::get_tap2_level_db); + + ClassDB::bind_method(D_METHOD("set_tap2_pan","amount"),&AudioEffectDelay::set_tap2_pan); + ClassDB::bind_method(D_METHOD("get_tap2_pan"),&AudioEffectDelay::get_tap2_pan); + + + ClassDB::bind_method(D_METHOD("set_feedback_active","amount"),&AudioEffectDelay::set_feedback_active); + ClassDB::bind_method(D_METHOD("is_feedback_active"),&AudioEffectDelay::is_feedback_active); + + ClassDB::bind_method(D_METHOD("set_feedback_delay_ms","amount"),&AudioEffectDelay::set_feedback_delay_ms); + ClassDB::bind_method(D_METHOD("get_feedback_delay_ms"),&AudioEffectDelay::get_feedback_delay_ms); + + ClassDB::bind_method(D_METHOD("set_feedback_level_db","amount"),&AudioEffectDelay::set_feedback_level_db); + ClassDB::bind_method(D_METHOD("get_feedback_level_db"),&AudioEffectDelay::get_feedback_level_db); + + ClassDB::bind_method(D_METHOD("set_feedback_lowpass","amount"),&AudioEffectDelay::set_feedback_lowpass); + ClassDB::bind_method(D_METHOD("get_feedback_lowpass"),&AudioEffectDelay::get_feedback_lowpass); + + ADD_PROPERTY(PropertyInfo(Variant::REAL,"dry",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_dry","get_dry"); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL,"tap1/active"),"set_tap1_active","is_tap1_active"); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"tap1/delay_ms",PROPERTY_HINT_RANGE,"0,1500,1"),"set_tap1_delay_ms","get_tap1_delay_ms"); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"tap1/level_db",PROPERTY_HINT_RANGE,"-60,0,0.01"),"set_tap1_level_db","get_tap1_level_db"); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"tap1/pan",PROPERTY_HINT_RANGE,"-1,1,0.01"),"set_tap1_pan","get_tap1_pan"); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL,"tap2/active"),"set_tap2_active","is_tap2_active"); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"tap2/delay_ms",PROPERTY_HINT_RANGE,"0,1500,1"),"set_tap2_delay_ms","get_tap2_delay_ms"); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"tap2/level_db",PROPERTY_HINT_RANGE,"-60,0,0.01"),"set_tap2_level_db","get_tap2_level_db"); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"tap2/pan",PROPERTY_HINT_RANGE,"-1,1,0.01"),"set_tap2_pan","get_tap2_pan"); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL,"feedback/active"),"set_feedback_active","is_feedback_active"); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"feedback/delay_ms",PROPERTY_HINT_RANGE,"0,1500,1"),"set_feedback_delay_ms","get_feedback_delay_ms"); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"feedback/level_db",PROPERTY_HINT_RANGE,"-60,0,0.01"),"set_feedback_level_db","get_feedback_level_db"); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"feedback/lowpass",PROPERTY_HINT_RANGE,"1,16000,1"),"set_feedback_lowpass","get_feedback_lowpass"); + + +} + +AudioEffectDelay::AudioEffectDelay() +{ + tap_1_active=true; + tap_1_delay_ms=250; + tap_1_level=-6; + tap_1_pan=0.2; + + tap_2_active=true; + tap_2_delay_ms=500; + tap_2_level=-12; + tap_2_pan=-0.4; + + feedback_active=false; + feedback_delay_ms=340; + feedback_level=-6; + feedback_lowpass=16000; + + dry=1.0; + +} diff --git a/servers/audio/effects/audio_effect_delay.h b/servers/audio/effects/audio_effect_delay.h new file mode 100644 index 0000000000..645561138b --- /dev/null +++ b/servers/audio/effects/audio_effect_delay.h @@ -0,0 +1,112 @@ +#ifndef AUDIOEFFECTECHO_H +#define AUDIOEFFECTECHO_H + +#include "servers/audio/audio_effect.h" + +class AudioEffectDelay; + +class AudioEffectDelayInstance : public AudioEffectInstance { + GDCLASS(AudioEffectDelayInstance,AudioEffectInstance) +friend class AudioEffectDelay; + Ref<AudioEffectDelay> base; + + Vector<AudioFrame> ring_buffer; + + unsigned int ring_buffer_pos; + unsigned int ring_buffer_mask; + + /* feedback buffer */ + Vector<AudioFrame> feedback_buffer; + + unsigned int feedback_buffer_pos; + + AudioFrame h; + void _process_chunk(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count); + +public: + + virtual void process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count); + +}; + + +class AudioEffectDelay : public AudioEffect { + GDCLASS(AudioEffectDelay,AudioEffect) + +friend class AudioEffectDelayInstance; + enum { + + MAX_DELAY_MS=3000, + MAX_TAPS=2 + }; + + float dry; + + bool tap_1_active; + float tap_1_delay_ms; + float tap_1_level; + float tap_1_pan; + + bool tap_2_active; + float tap_2_delay_ms; + float tap_2_level; + float tap_2_pan; + + bool feedback_active; + float feedback_delay_ms; + float feedback_level; + float feedback_lowpass; + + + +protected: + + static void _bind_methods(); +public: + + void set_dry(float p_dry); + float get_dry(); + + void set_tap1_active(bool p_active); + bool is_tap1_active() const; + + void set_tap1_delay_ms(float p_delay_ms); + float get_tap1_delay_ms() const; + + void set_tap1_level_db(float p_level_db); + float get_tap1_level_db() const; + + void set_tap1_pan(float p_pan); + float get_tap1_pan() const; + + void set_tap2_active(bool p_active); + bool is_tap2_active() const; + + void set_tap2_delay_ms(float p_delay_ms); + float get_tap2_delay_ms() const; + + void set_tap2_level_db(float p_level_db); + float get_tap2_level_db() const; + + void set_tap2_pan(float p_pan); + float get_tap2_pan() const; + + void set_feedback_active(bool p_active); + bool is_feedback_active() const; + + void set_feedback_delay_ms(float p_delay_ms); + float get_feedback_delay_ms() const; + + void set_feedback_level_db(float p_level_db); + float get_feedback_level_db() const; + + void set_feedback_lowpass(float p_lowpass); + float get_feedback_lowpass() const; + + Ref<AudioEffectInstance> instance(); + + AudioEffectDelay(); +}; + + +#endif // AUDIOEFFECTECHO_H diff --git a/servers/audio/effects/audio_effect_distortion.cpp b/servers/audio/effects/audio_effect_distortion.cpp new file mode 100644 index 0000000000..d0f526fe24 --- /dev/null +++ b/servers/audio/effects/audio_effect_distortion.cpp @@ -0,0 +1,171 @@ +#include "audio_effect_distortion.h" +#include "servers/audio_server.h" +#include "math_funcs.h" + + + +void AudioEffectDistortionInstance::process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count) { + + const float *src = (const float*)p_src_frames; + float *dst = (float*)p_dst_frames; + + //float lpf_c=expf(-2.0*Math_PI*keep_hf_hz.get()/(mix_rate*(float)OVERSAMPLE)); + float lpf_c=expf(-2.0*Math_PI*base->keep_hf_hz/(AudioServer::get_singleton()->get_mix_rate())); + float lpf_ic=1.0-lpf_c; + + float drive_f=base->drive; + float pregain_f=Math::db2linear(base->pre_gain); + float postgain_f=Math::db2linear(base->post_gain); + + float atan_mult=pow(10,drive_f*drive_f*3.0)-1.0+0.001; + float atan_div=1.0/(atanf(atan_mult)*(1.0+drive_f*8)); + + float lofi_mult=powf(2.0,2.0+(1.0-drive_f)*14); //goes from 16 to 2 bits + + for (int i=0;i<p_frame_count*2;i++) { + + float out=undenormalise(src[i]*lpf_ic+lpf_c*h[i&1]); + h[i&1]=out; + float a=out; + float ha=src[i]-out; //high freqs + a*=pregain_f; + + switch (base->mode) { + + case AudioEffectDistortion::MODE_CLIP: { + + a=powf(a,1.0001-drive_f); + if (a>1.0) + a=1.0; + else if (a<(-1.0)) + a=-1.0; + + } break; + case AudioEffectDistortion::MODE_ATAN: { + + + a=atanf(a*atan_mult)*atan_div; + + } break; + case AudioEffectDistortion::MODE_LOFI: { + + a = floorf(a*lofi_mult+0.5)/lofi_mult; + + } break; + case AudioEffectDistortion::MODE_OVERDRIVE: { + + + const double x = a * 0.686306; + const double z = 1 + exp (sqrt (fabs (x)) * -0.75); + a = (expf(x) - expf(-x * z)) / (expf(x) + expf(-x)); + } break; + case AudioEffectDistortion::MODE_WAVESHAPE: { + float x = a; + float k= 2*drive_f/(1.00001-drive_f); + + a = (1.0+k)*x/(1.0+k*fabsf(x)); + + + } break; + } + + dst[i]=a*postgain_f+ha; + + } + + +} + + +Ref<AudioEffectInstance> AudioEffectDistortion::instance() { + Ref<AudioEffectDistortionInstance> ins; + ins.instance(); + ins->base=Ref<AudioEffectDistortion>(this); + ins->h[0]=0; + ins->h[1]=0; + + return ins; +} + + +void AudioEffectDistortion::set_mode(Mode p_mode) { + + mode=p_mode; +} + +AudioEffectDistortion::Mode AudioEffectDistortion::get_mode() const{ + + return mode; +} + +void AudioEffectDistortion::set_pre_gain(float p_pre_gain){ + + pre_gain=p_pre_gain; +} +float AudioEffectDistortion::get_pre_gain() const{ + + return pre_gain; +} + +void AudioEffectDistortion::set_keep_hf_hz(float p_keep_hf_hz){ + + keep_hf_hz=p_keep_hf_hz; +} +float AudioEffectDistortion::get_keep_hf_hz() const{ + + return keep_hf_hz; +} + +void AudioEffectDistortion::set_drive(float p_drive){ + + drive=p_drive; +} +float AudioEffectDistortion::get_drive() const{ + + return drive; +} + +void AudioEffectDistortion::set_post_gain(float p_post_gain){ + + post_gain=p_post_gain; +} +float AudioEffectDistortion::get_post_gain() const{ + + return post_gain; +} + + +void AudioEffectDistortion::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_mode","mode"),&AudioEffectDistortion::set_mode); + ClassDB::bind_method(D_METHOD("get_mode"),&AudioEffectDistortion::get_mode); + + ClassDB::bind_method(D_METHOD("set_pre_gain","pre_gain"),&AudioEffectDistortion::set_pre_gain); + ClassDB::bind_method(D_METHOD("get_pre_gain"),&AudioEffectDistortion::get_pre_gain); + + ClassDB::bind_method(D_METHOD("set_keep_hf_hz","keep_hf_hz"),&AudioEffectDistortion::set_keep_hf_hz); + ClassDB::bind_method(D_METHOD("get_keep_hf_hz"),&AudioEffectDistortion::get_keep_hf_hz); + + ClassDB::bind_method(D_METHOD("set_drive","drive"),&AudioEffectDistortion::set_drive); + ClassDB::bind_method(D_METHOD("get_drive"),&AudioEffectDistortion::get_drive); + + + ClassDB::bind_method(D_METHOD("set_post_gain","post_gain"),&AudioEffectDistortion::set_post_gain); + ClassDB::bind_method(D_METHOD("get_post_gain"),&AudioEffectDistortion::get_post_gain); + + ADD_PROPERTY(PropertyInfo(Variant::INT,"mode",PROPERTY_HINT_ENUM,"Clip,ATan,LoFi,Overdrive,WaveShape"),"set_mode","get_mode"); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"pre_gain",PROPERTY_HINT_RANGE,"-60,60,0.01"),"set_pre_gain","get_pre_gain"); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"keep_hf_hz",PROPERTY_HINT_RANGE,"1,20000,1"),"set_keep_hf_hz","get_keep_hf_hz"); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"drive",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_drive","get_drive"); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"post_gain",PROPERTY_HINT_RANGE,"-80,24,0.01"),"set_post_gain","get_post_gain"); +} + +AudioEffectDistortion::AudioEffectDistortion() +{ + mode=MODE_CLIP; + pre_gain=0; + post_gain=0; + keep_hf_hz=16000; + drive=0; +} + diff --git a/servers/audio/effects/audio_effect_distortion.h b/servers/audio/effects/audio_effect_distortion.h new file mode 100644 index 0000000000..1d2433faeb --- /dev/null +++ b/servers/audio/effects/audio_effect_distortion.h @@ -0,0 +1,69 @@ +#ifndef AUDIOEFFECTDISTORTION_H +#define AUDIOEFFECTDISTORTION_H + +#include "servers/audio/audio_effect.h" + +class AudioEffectDistortion; + +class AudioEffectDistortionInstance : public AudioEffectInstance { + GDCLASS(AudioEffectDistortionInstance,AudioEffectInstance) +friend class AudioEffectDistortion; + Ref<AudioEffectDistortion> base; + float h[2]; +public: + + virtual void process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count); + +}; + + +class AudioEffectDistortion : public AudioEffect { + GDCLASS(AudioEffectDistortion,AudioEffect) +public: + enum Mode { + MODE_CLIP, + MODE_ATAN, + MODE_LOFI, + MODE_OVERDRIVE, + MODE_WAVESHAPE, + }; + +friend class AudioEffectDistortionInstance; + Mode mode; + float pre_gain; + float post_gain; + float keep_hf_hz; + float drive; + +protected: + + static void _bind_methods(); +public: + + + Ref<AudioEffectInstance> instance(); + + + void set_mode(Mode p_mode); + Mode get_mode() const; + + void set_pre_gain(float pre_gain); + float get_pre_gain() const; + + void set_keep_hf_hz(float keep_hf_hz); + float get_keep_hf_hz() const; + + void set_drive(float drive); + float get_drive() const; + + void set_post_gain(float post_gain); + float get_post_gain() const; + + + + AudioEffectDistortion(); +}; + +VARIANT_ENUM_CAST( AudioEffectDistortion::Mode ) + +#endif // AUDIOEFFECTDISTORTION_H diff --git a/servers/audio/effects/audio_effect_eq.cpp b/servers/audio/effects/audio_effect_eq.cpp new file mode 100644 index 0000000000..5f42f2826f --- /dev/null +++ b/servers/audio/effects/audio_effect_eq.cpp @@ -0,0 +1,122 @@ +#include "audio_effect_eq.h" +#include "servers/audio_server.h" + + +void AudioEffectEQInstance::process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count) { + + int band_count = bands[0].size(); + EQ::BandProcess *proc_l = bands[0].ptr(); + EQ::BandProcess *proc_r = bands[1].ptr(); + float *bgain = gains.ptr(); + for(int i=0;i<band_count;i++) { + bgain[i]=Math::db2linear(base->gain[i]); + } + + + for(int i=0;i<p_frame_count;i++) { + + AudioFrame src = p_src_frames[i]; + AudioFrame dst = AudioFrame(0,0); + + for(int j=0;j<band_count;j++) { + + float l = src.l; + float r = src.r; + + proc_l[j].process_one(l); + proc_r[j].process_one(r); + + dst.l+=l * bgain[j]; + dst.r+=r * bgain[j]; + } + + p_dst_frames[i]=dst; + } + +} + + +Ref<AudioEffectInstance> AudioEffectEQ::instance() { + Ref<AudioEffectEQInstance> ins; + ins.instance(); + ins->base=Ref<AudioEffectEQ>(this); + ins->gains.resize(eq.get_band_count()); + for(int i=0;i<2;i++) { + ins->bands[i].resize(eq.get_band_count()); + for(int j=0;j<ins->bands[i].size();j++) { + ins->bands[i][j]=eq.get_band_processor(j); + } + } + + return ins; +} + +void AudioEffectEQ::set_band_gain_db(int p_band,float p_volume) { + ERR_FAIL_INDEX(p_band,gain.size()); + gain[p_band]=p_volume; +} + +float AudioEffectEQ::get_band_gain_db(int p_band) const { + ERR_FAIL_INDEX_V(p_band,gain.size(),0); + + return gain[p_band]; +} +int AudioEffectEQ::get_band_count() const { + return gain.size(); +} + +bool AudioEffectEQ::_set(const StringName& p_name, const Variant& p_value) { + + const Map<StringName,int>::Element *E=prop_band_map.find(p_name); + if (E) { + set_band_gain_db(E->get(),p_value); + return true; + } + + return false; +} + +bool AudioEffectEQ::_get(const StringName& p_name,Variant &r_ret) const{ + + const Map<StringName,int>::Element *E=prop_band_map.find(p_name); + if (E) { + r_ret=get_band_gain_db(E->get()); + return true; + } + + return false; + +} + +void AudioEffectEQ::_get_property_list( List<PropertyInfo> *p_list) const{ + + for(int i=0;i<band_names.size();i++) { + + p_list->push_back(PropertyInfo(Variant::REAL,band_names[i],PROPERTY_HINT_RANGE,"-60,24,0.1")); + } +} + + + +void AudioEffectEQ::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_band_gain_db","band_idx","volume_db"),&AudioEffectEQ::set_band_gain_db); + ClassDB::bind_method(D_METHOD("get_band_gain_db","band_idx"),&AudioEffectEQ::get_band_gain_db); + ClassDB::bind_method(D_METHOD("get_band_count"),&AudioEffectEQ::get_band_count); + +} + +AudioEffectEQ::AudioEffectEQ(EQ::Preset p_preset) +{ + + + eq.set_mix_rate(AudioServer::get_singleton()->get_mix_rate()); + eq.set_preset_band_mode(p_preset); + gain.resize(eq.get_band_count()); + for(int i=0;i<gain.size();i++) { + gain[i]=0.0; + String name = "band_db/"+itos(eq.get_band_frequency(i))+"_hz"; + prop_band_map[name]=i; + band_names.push_back(name); + } +} diff --git a/servers/audio/effects/audio_effect_eq.h b/servers/audio/effects/audio_effect_eq.h new file mode 100644 index 0000000000..3fcc2c0056 --- /dev/null +++ b/servers/audio/effects/audio_effect_eq.h @@ -0,0 +1,72 @@ +#ifndef AUDIOEFFECTEQ_H +#define AUDIOEFFECTEQ_H + + +#include "servers/audio/audio_effect.h" +#include "servers/audio/effects/eq.h" + +class AudioEffectEQ; + +class AudioEffectEQInstance : public AudioEffectInstance { + GDCLASS(AudioEffectEQInstance,AudioEffectInstance) +friend class AudioEffectEQ; + Ref<AudioEffectEQ> base; + + Vector<EQ::BandProcess> bands[2]; + Vector<float> gains; +public: + + virtual void process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count); + +}; + + +class AudioEffectEQ : public AudioEffect { + GDCLASS(AudioEffectEQ,AudioEffect) + +friend class AudioEffectEQInstance; + + EQ eq; + Vector<float> gain; + Map<StringName,int> prop_band_map; + Vector<String> band_names; + +protected: + bool _set(const StringName& p_name, const Variant& p_value); + bool _get(const StringName& p_name,Variant &r_ret) const; + void _get_property_list( List<PropertyInfo> *p_list) const; + + + + static void _bind_methods(); +public: + + + Ref<AudioEffectInstance> instance(); + void set_band_gain_db(int p_band,float p_volume); + float get_band_gain_db(int p_band) const; + int get_band_count() const; + + AudioEffectEQ(EQ::Preset p_preset=EQ::PRESET_6_BANDS); +}; + + +class AudioEffectEQ6 : public AudioEffectEQ { + GDCLASS(AudioEffectEQ6,AudioEffectEQ) +public: + AudioEffectEQ6() : AudioEffectEQ(EQ::PRESET_6_BANDS) {} +}; + +class AudioEffectEQ10 : public AudioEffectEQ { + GDCLASS(AudioEffectEQ10,AudioEffectEQ) +public: + AudioEffectEQ10() : AudioEffectEQ(EQ::PRESET_10_BANDS) {} +}; + +class AudioEffectEQ21 : public AudioEffectEQ { + GDCLASS(AudioEffectEQ21,AudioEffectEQ) +public: + AudioEffectEQ21() : AudioEffectEQ(EQ::PRESET_21_BANDS) {} +}; + +#endif // AUDIOEFFECTEQ_H diff --git a/servers/audio/effects/audio_effect_filter.cpp b/servers/audio/effects/audio_effect_filter.cpp new file mode 100644 index 0000000000..e7af7ca9c0 --- /dev/null +++ b/servers/audio/effects/audio_effect_filter.cpp @@ -0,0 +1,151 @@ +#include "audio_effect_filter.h" +#include "servers/audio_server.h" + +template<int S> +void AudioEffectFilterInstance::_process_filter(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count) { + + for(int i=0;i<p_frame_count;i++) { + float f = p_src_frames[i].l; + filter_process[0][0].process_one(f); + if (S>1) + filter_process[0][1].process_one(f); + if (S>2) + filter_process[0][2].process_one(f); + if (S>3) + filter_process[0][3].process_one(f); + + p_dst_frames[i].l=f; + } + + for(int i=0;i<p_frame_count;i++) { + float f = p_src_frames[i].r; + filter_process[1][0].process_one(f); + if (S>1) + filter_process[1][1].process_one(f); + if (S>2) + filter_process[1][2].process_one(f); + if (S>3) + filter_process[1][3].process_one(f); + + p_dst_frames[i].r=f; + } + +} + +void AudioEffectFilterInstance::process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count) { + + filter.set_cutoff(base->cutoff); + filter.set_gain(base->gain); + filter.set_resonance(base->resonance); + filter.set_mode(base->mode); + int stages = int(base->db)+1; + filter.set_stages(stages); + filter.set_sampling_rate(AudioServer::get_singleton()->get_mix_rate()); + + for(int i=0;i<2;i++) { + for(int j=0;j<4;j++) { + filter_process[i][j].update_coeffs(); + } + } + + + if (stages==1) { + _process_filter<1>(p_src_frames,p_dst_frames,p_frame_count); + } else if (stages==2) { + _process_filter<2>(p_src_frames,p_dst_frames,p_frame_count); + } else if (stages==3) { + _process_filter<3>(p_src_frames,p_dst_frames,p_frame_count); + } else if (stages==4) { + _process_filter<4>(p_src_frames,p_dst_frames,p_frame_count); + } + +} + + +AudioEffectFilterInstance::AudioEffectFilterInstance() { + + for(int i=0;i<2;i++) { + for(int j=0;j<4;j++) { + filter_process[i][j].set_filter(&filter); + } + } + +} + + +Ref<AudioEffectInstance> AudioEffectFilter::instance() { + Ref<AudioEffectFilterInstance> ins; + ins.instance(); + ins->base=Ref<AudioEffectFilter>(this); + + return ins; +} + +void AudioEffectFilter::set_cutoff(float p_freq) { + + cutoff=p_freq; +} + +float AudioEffectFilter::get_cutoff() const{ + + return cutoff; +} + +void AudioEffectFilter::set_resonance(float p_amount){ + + resonance=p_amount; +} +float AudioEffectFilter::get_resonance() const{ + + return resonance; +} + +void AudioEffectFilter::set_gain(float p_amount){ + + gain=p_amount; +} +float AudioEffectFilter::get_gain() const { + + return gain; +} + + + +void AudioEffectFilter::set_db(FilterDB p_db) { + db=p_db; +} + +AudioEffectFilter::FilterDB AudioEffectFilter::get_db() const { + + return db; +} + +void AudioEffectFilter::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_cutoff","freq"),&AudioEffectFilter::set_cutoff); + ClassDB::bind_method(D_METHOD("get_cutoff"),&AudioEffectFilter::get_cutoff); + + ClassDB::bind_method(D_METHOD("set_resonance","amount"),&AudioEffectFilter::set_resonance); + ClassDB::bind_method(D_METHOD("get_resonance"),&AudioEffectFilter::get_resonance); + + ClassDB::bind_method(D_METHOD("set_gain","amount"),&AudioEffectFilter::set_gain); + ClassDB::bind_method(D_METHOD("get_gain"),&AudioEffectFilter::get_gain); + + ClassDB::bind_method(D_METHOD("set_db","amount"),&AudioEffectFilter::set_db); + ClassDB::bind_method(D_METHOD("get_db"),&AudioEffectFilter::get_db); + + ADD_PROPERTY(PropertyInfo(Variant::REAL,"cutoff_hz",PROPERTY_HINT_RANGE,"1,40000,0.1"),"set_cutoff","get_cutoff"); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"resonance",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_resonance","get_resonance"); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"gain",PROPERTY_HINT_RANGE,"0,4,0.01"),"set_gain","get_gain"); + ADD_PROPERTY(PropertyInfo(Variant::INT,"dB",PROPERTY_HINT_ENUM,"6db,12db,18db,24db"),"set_db","get_db"); +} + +AudioEffectFilter::AudioEffectFilter(AudioFilterSW::Mode p_mode) +{ + + mode=p_mode; + cutoff=2000; + resonance=0.5; + gain=1.0; + db=FILTER_6DB; +} diff --git a/servers/audio/effects/audio_effect_filter.h b/servers/audio/effects/audio_effect_filter.h new file mode 100644 index 0000000000..d0bc7a446a --- /dev/null +++ b/servers/audio/effects/audio_effect_filter.h @@ -0,0 +1,125 @@ +#ifndef AUDIOEFFECTFILTER_H +#define AUDIOEFFECTFILTER_H + +#include "servers/audio/audio_effect.h" +#include "servers/audio/audio_filter_sw.h" + +class AudioEffectFilter; + +class AudioEffectFilterInstance : public AudioEffectInstance { + GDCLASS(AudioEffectFilterInstance,AudioEffectInstance) +friend class AudioEffectFilter; + + Ref<AudioEffectFilter> base; + + AudioFilterSW filter; + AudioFilterSW::Processor filter_process[2][4]; + + template<int S> + void _process_filter(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count); +public: + + virtual void process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count); + + AudioEffectFilterInstance(); +}; + + +class AudioEffectFilter : public AudioEffect { + GDCLASS(AudioEffectFilter,AudioEffect) +public: + + enum FilterDB { + FILTER_6DB, + FILTER_12DB, + FILTER_18DB, + FILTER_24DB, + }; + friend class AudioEffectFilterInstance; + + AudioFilterSW::Mode mode; + float cutoff; + float resonance; + float gain; + FilterDB db; + + +protected: + + + static void _bind_methods(); +public: + + void set_cutoff(float p_freq); + float get_cutoff() const; + + void set_resonance(float p_amount); + float get_resonance() const; + + void set_gain(float p_amount); + float get_gain() const; + + void set_db(FilterDB p_db); + FilterDB get_db() const; + + Ref<AudioEffectInstance> instance(); + + AudioEffectFilter(AudioFilterSW::Mode p_mode=AudioFilterSW::LOWPASS); +}; + +VARIANT_ENUM_CAST(AudioEffectFilter::FilterDB) + +class AudioEffectLowPassFilter : public AudioEffectFilter { + GDCLASS(AudioEffectLowPassFilter,AudioEffectFilter) +public: + + AudioEffectLowPassFilter() : AudioEffectFilter(AudioFilterSW::LOWPASS) {} +}; + +class AudioEffectHighPassFilter : public AudioEffectFilter { + GDCLASS(AudioEffectHighPassFilter,AudioEffectFilter) +public: + + AudioEffectHighPassFilter() : AudioEffectFilter(AudioFilterSW::HIGHPASS) {} +}; + +class AudioEffectBandPassFilter : public AudioEffectFilter { + GDCLASS(AudioEffectBandPassFilter,AudioEffectFilter) +public: + + AudioEffectBandPassFilter() : AudioEffectFilter(AudioFilterSW::BANDPASS) {} +}; + +class AudioEffectNotchFilter : public AudioEffectFilter { + GDCLASS(AudioEffectNotchFilter,AudioEffectFilter) +public: + + AudioEffectNotchFilter() : AudioEffectFilter(AudioFilterSW::NOTCH) {} +}; + +class AudioEffectBandLimitFilter : public AudioEffectFilter { + GDCLASS(AudioEffectBandLimitFilter,AudioEffectFilter) +public: + + AudioEffectBandLimitFilter() : AudioEffectFilter(AudioFilterSW::BANDLIMIT) {} +}; + + +class AudioEffectLowShelfFilter : public AudioEffectFilter { + GDCLASS(AudioEffectLowShelfFilter,AudioEffectFilter) +public: + + AudioEffectLowShelfFilter() : AudioEffectFilter(AudioFilterSW::LOWSHELF) {} +}; + + +class AudioEffectHighShelfFilter : public AudioEffectFilter { + GDCLASS(AudioEffectHighShelfFilter,AudioEffectFilter) +public: + + AudioEffectHighShelfFilter() : AudioEffectFilter(AudioFilterSW::HIGHSHELF) {} +}; + + + +#endif // AUDIOEFFECTFILTER_H diff --git a/servers/audio/effects/audio_effect_limiter.cpp b/servers/audio/effects/audio_effect_limiter.cpp new file mode 100644 index 0000000000..bce1e0a0df --- /dev/null +++ b/servers/audio/effects/audio_effect_limiter.cpp @@ -0,0 +1,124 @@ +#include "audio_effect_limiter.h" + +void AudioEffectLimiterInstance::process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count) { + + float thresh = Math::db2linear(base->treshold); + float threshdb = base->treshold; + float ceiling = Math::db2linear(base->ceiling); + float ceildb = base->ceiling; + float makeup = Math::db2linear(ceildb - threshdb); + float makeupdb = ceildb - threshdb; + float sc = -base->soft_clip; + float scv = Math::db2linear(sc); + float sccomp = Math::db2linear(-sc); + float peakdb = ceildb + 25; + float peaklvl = Math::db2linear(peakdb); + float scratio = base->soft_clip_ratio; + float scmult = Math::abs((ceildb - sc) / (peakdb - sc)); + + for(int i=0;i<p_frame_count;i++) { + + float spl0 = p_src_frames[i].l; + float spl1 = p_src_frames[i].r; + spl0 = spl0 * makeup; + spl1 = spl1 * makeup; + float sign0 = (spl0 < 0.0 ? -1.0 : 1.0 ); + float sign1 = (spl1 < 0.0 ? -1.0 : 1.0 ); + float abs0 = Math::abs(spl0); + float abs1 = Math::abs(spl1); + float overdb0 = Math::linear2db(abs0) - ceildb; + float overdb1 = Math::linear2db(abs1) - ceildb; + + if (abs0 > scv) + { + spl0 = sign0 * (scv + Math::db2linear(overdb0 * scmult)); + } + if (abs1 > scv) + { + spl1 = sign1 * (scv + Math::db2linear(overdb1 * scmult)); + } + + spl0 = MIN(ceiling, Math::abs(spl0)) * (spl0 < 0.0 ? -1.0 : 1.0); + spl1 = MIN(ceiling, Math::abs(spl1)) * (spl1 < 0.0 ? -1.0 : 1.0); + + p_dst_frames[i].l = spl0; + p_dst_frames[i].r = spl1; + } + +} + + +Ref<AudioEffectInstance> AudioEffectLimiter::instance() { + Ref<AudioEffectLimiterInstance> ins; + ins.instance(); + ins->base=Ref<AudioEffectLimiter>(this); + + return ins; +} + + +void AudioEffectLimiter::set_treshold_db(float p_treshold) { + + treshold=p_treshold; +} + +float AudioEffectLimiter::get_treshold_db() const{ + + return treshold; +} + +void AudioEffectLimiter::set_ceiling_db(float p_ceiling){ + + ceiling=p_ceiling; +} +float AudioEffectLimiter::get_ceiling_db() const{ + + return ceiling; +} + +void AudioEffectLimiter::set_soft_clip_db(float p_soft_clip){ + + soft_clip=p_soft_clip; +} +float AudioEffectLimiter::get_soft_clip_db() const{ + + return soft_clip; +} + +void AudioEffectLimiter::set_soft_clip_ratio(float p_soft_clip){ + + soft_clip_ratio=p_soft_clip; +} +float AudioEffectLimiter::get_soft_clip_ratio() const{ + + return soft_clip; +} + + +void AudioEffectLimiter::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_ceiling_db","ceiling"),&AudioEffectLimiter::set_ceiling_db); + ClassDB::bind_method(D_METHOD("get_ceiling_db"),&AudioEffectLimiter::get_ceiling_db); + + ClassDB::bind_method(D_METHOD("set_treshold_db","treshold"),&AudioEffectLimiter::set_treshold_db); + ClassDB::bind_method(D_METHOD("get_treshold_db"),&AudioEffectLimiter::get_treshold_db); + + ClassDB::bind_method(D_METHOD("set_soft_clip_db","soft_clip"),&AudioEffectLimiter::set_soft_clip_db); + ClassDB::bind_method(D_METHOD("get_soft_clip_db"),&AudioEffectLimiter::get_soft_clip_db); + + ClassDB::bind_method(D_METHOD("set_soft_clip_ratio","soft_clip"),&AudioEffectLimiter::set_soft_clip_ratio); + ClassDB::bind_method(D_METHOD("get_soft_clip_ratio"),&AudioEffectLimiter::get_soft_clip_ratio); + + ADD_PROPERTY(PropertyInfo(Variant::REAL,"ceiling_db",PROPERTY_HINT_RANGE,"-20,-0.1,0.1"),"set_ceiling_db","get_ceiling_db"); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"treshold_db",PROPERTY_HINT_RANGE,"-30,0,0.1"),"set_treshold_db","get_treshold_db"); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"soft_clip_db",PROPERTY_HINT_RANGE,"0,6,0.1"),"set_soft_clip_db","get_soft_clip_db"); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"soft_clip_ratio",PROPERTY_HINT_RANGE,"3,20,0.1"),"set_soft_clip_ratio","get_soft_clip_ratio"); +} + +AudioEffectLimiter::AudioEffectLimiter() +{ + treshold=0; + ceiling=-0.1; + soft_clip=2; + soft_clip_ratio=10; +} diff --git a/servers/audio/effects/audio_effect_limiter.h b/servers/audio/effects/audio_effect_limiter.h new file mode 100644 index 0000000000..b0d7321205 --- /dev/null +++ b/servers/audio/effects/audio_effect_limiter.h @@ -0,0 +1,58 @@ +#ifndef AUDIO_EFFECT_LIMITER_H +#define AUDIO_EFFECT_LIMITER_H + + +#include "servers/audio/audio_effect.h" + +class AudioEffectLimiter; + +class AudioEffectLimiterInstance : public AudioEffectInstance { + GDCLASS(AudioEffectLimiterInstance,AudioEffectInstance) +friend class AudioEffectLimiter; + Ref<AudioEffectLimiter> base; + + float mix_volume_db; +public: + + virtual void process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count); + +}; + + +class AudioEffectLimiter : public AudioEffect { + GDCLASS(AudioEffectLimiter,AudioEffect) + +friend class AudioEffectLimiterInstance; + float treshold; + float ceiling; + float soft_clip; + float soft_clip_ratio; + +protected: + + static void _bind_methods(); +public: + + + void set_treshold_db(float p_treshold); + float get_treshold_db() const; + + void set_ceiling_db(float p_ceiling); + float get_ceiling_db() const; + + void set_soft_clip_db(float p_soft_clip); + float get_soft_clip_db() const; + + void set_soft_clip_ratio(float p_soft_clip); + float get_soft_clip_ratio() const; + + + Ref<AudioEffectInstance> instance(); + void set_volume_db(float p_volume); + float get_volume_db() const; + + AudioEffectLimiter(); +}; + + +#endif // AUDIO_EFFECT_LIMITER_H diff --git a/servers/audio/effects/audio_effect_panner.cpp b/servers/audio/effects/audio_effect_panner.cpp new file mode 100644 index 0000000000..75ef9c3e3a --- /dev/null +++ b/servers/audio/effects/audio_effect_panner.cpp @@ -0,0 +1,47 @@ +#include "audio_effect_panner.h" + + +void AudioEffectPannerInstance::process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count) { + + + float lvol = CLAMP( 1.0 - base->pan, 0, 1); + float rvol = CLAMP( 1.0 + base->pan, 0, 1); + + for(int i=0;i<p_frame_count;i++) { + + p_dst_frames[i].l = p_src_frames[i].l * lvol + p_src_frames[i].r * (1.0 - rvol); + p_dst_frames[i].r = p_src_frames[i].r * rvol + p_src_frames[i].l * (1.0 - lvol); + + } + +} + + +Ref<AudioEffectInstance> AudioEffectPanner::instance() { + Ref<AudioEffectPannerInstance> ins; + ins.instance(); + ins->base=Ref<AudioEffectPanner>(this); + return ins; +} + +void AudioEffectPanner::set_pan(float p_cpanume) { + pan=p_cpanume; +} + +float AudioEffectPanner::get_pan() const { + + return pan; +} + +void AudioEffectPanner::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_pan","cpanume"),&AudioEffectPanner::set_pan); + ClassDB::bind_method(D_METHOD("get_pan"),&AudioEffectPanner::get_pan); + + ADD_PROPERTY(PropertyInfo(Variant::REAL,"pan",PROPERTY_HINT_RANGE,"-1,1,0.01"),"set_pan","get_pan"); +} + +AudioEffectPanner::AudioEffectPanner() +{ + pan=0; +} diff --git a/servers/audio/effects/audio_effect_panner.h b/servers/audio/effects/audio_effect_panner.h new file mode 100644 index 0000000000..bc1bb00815 --- /dev/null +++ b/servers/audio/effects/audio_effect_panner.h @@ -0,0 +1,40 @@ +#ifndef AUDIOEFFECTPANNER_H +#define AUDIOEFFECTPANNER_H + +#include "servers/audio/audio_effect.h" + +class AudioEffectPanner; + +class AudioEffectPannerInstance : public AudioEffectInstance { + GDCLASS(AudioEffectPannerInstance,AudioEffectInstance) +friend class AudioEffectPanner; + Ref<AudioEffectPanner> base; + +public: + + virtual void process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count); + +}; + + +class AudioEffectPanner : public AudioEffect { + GDCLASS(AudioEffectPanner,AudioEffect) + +friend class AudioEffectPannerInstance; + float pan; + +protected: + + static void _bind_methods(); +public: + + + Ref<AudioEffectInstance> instance(); + void set_pan(float p_volume); + float get_pan() const; + + AudioEffectPanner(); +}; + + +#endif // AUDIOEFFECTPANNER_H diff --git a/servers/audio/effects/audio_effect_phaser.cpp b/servers/audio/effects/audio_effect_phaser.cpp new file mode 100644 index 0000000000..c5e49e6cc6 --- /dev/null +++ b/servers/audio/effects/audio_effect_phaser.cpp @@ -0,0 +1,148 @@ +#include "audio_effect_phaser.h" +#include "servers/audio_server.h" +#include "math_funcs.h" + +void AudioEffectPhaserInstance::process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count) { + + float sampling_rate = AudioServer::get_singleton()->get_mix_rate(); + + float dmin = base->range_min / (sampling_rate/2.0); + float dmax = base->range_max / (sampling_rate/2.0); + + float increment = 2.f * Math_PI * (base->rate / sampling_rate); + + for(int i=0;i<p_frame_count;i++) { + + phase += increment; + + while ( phase >= Math_PI * 2.f ) { + phase -= Math_PI * 2.f; + } + + float d = dmin + (dmax-dmin) * ((sin( phase ) + 1.f)/2.f); + + + //update filter coeffs + for( int j=0; j<6; j++ ) { + allpass[0][j].delay( d ); + allpass[1][j].delay( d ); + } + + //calculate output + float y = allpass[0][0].update( + allpass[0][1].update( + allpass[0][2].update( + allpass[0][3].update( + allpass[0][4].update( + allpass[0][5].update( p_src_frames[i].l + h.l * base->feedback )))))); + h.l=y; + + p_dst_frames[i].l = p_src_frames[i].l + y * base->depth; + + y = allpass[1][0].update( + allpass[1][1].update( + allpass[1][2].update( + allpass[1][3].update( + allpass[1][4].update( + allpass[1][5].update( p_src_frames[i].r + h.r * base->feedback )))))); + h.r=y; + + p_dst_frames[i].r = p_src_frames[i].r + y * base->depth; + + + } + +} + + +Ref<AudioEffectInstance> AudioEffectPhaser::instance() { + Ref<AudioEffectPhaserInstance> ins; + ins.instance(); + ins->base=Ref<AudioEffectPhaser>(this); + ins->phase=0; + ins->h=AudioFrame(0,0); + + return ins; +} + + +void AudioEffectPhaser::set_range_min_hz(float p_hz) { + + range_min=p_hz; +} + +float AudioEffectPhaser::get_range_min_hz() const{ + + return range_min; +} + +void AudioEffectPhaser::set_range_max_hz(float p_hz){ + + range_max=p_hz; +} +float AudioEffectPhaser::get_range_max_hz() const{ + + return range_max; +} + +void AudioEffectPhaser::set_rate_hz(float p_hz){ + + rate=p_hz; +} +float AudioEffectPhaser::get_rate_hz() const{ + + return rate; +} + +void AudioEffectPhaser::set_feedback(float p_fbk){ + + feedback=p_fbk; +} +float AudioEffectPhaser::get_feedback() const{ + + return feedback; +} + +void AudioEffectPhaser::set_depth(float p_depth) { + + depth=p_depth; +} + +float AudioEffectPhaser::get_depth() const { + + return depth; +} + +void AudioEffectPhaser::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_range_min_hz","hz"),&AudioEffectPhaser::set_range_min_hz); + ClassDB::bind_method(D_METHOD("get_range_min_hz"),&AudioEffectPhaser::get_range_min_hz); + + ClassDB::bind_method(D_METHOD("set_range_max_hz","hz"),&AudioEffectPhaser::set_range_max_hz); + ClassDB::bind_method(D_METHOD("get_range_max_hz"),&AudioEffectPhaser::get_range_max_hz); + + ClassDB::bind_method(D_METHOD("set_rate_hz","hz"),&AudioEffectPhaser::set_rate_hz); + ClassDB::bind_method(D_METHOD("get_rate_hz"),&AudioEffectPhaser::get_rate_hz); + + ClassDB::bind_method(D_METHOD("set_feedback","fbk"),&AudioEffectPhaser::set_feedback); + ClassDB::bind_method(D_METHOD("get_feedback"),&AudioEffectPhaser::get_feedback); + + ClassDB::bind_method(D_METHOD("set_depth","depth"),&AudioEffectPhaser::set_depth); + ClassDB::bind_method(D_METHOD("get_depth"),&AudioEffectPhaser::get_depth); + + ADD_PROPERTY(PropertyInfo(Variant::REAL,"range_min_hz",PROPERTY_HINT_RANGE,"10,10000"),"set_range_min_hz","get_range_min_hz"); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"range_max_hz",PROPERTY_HINT_RANGE,"10,10000"),"set_range_max_hz","get_range_max_hz"); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"rate_hz",PROPERTY_HINT_RANGE,"0.01,20"),"set_rate_hz","get_rate_hz"); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"feedback",PROPERTY_HINT_RANGE,"0.1,0.9,0.1"),"set_feedback","get_feedback"); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"depth",PROPERTY_HINT_RANGE,"0.1,4,0.1"),"set_depth","get_depth"); + +} + +AudioEffectPhaser::AudioEffectPhaser() +{ + range_min=440; + range_max=1600; + rate=0.5; + feedback=0.7; + depth=1; +} diff --git a/servers/audio/effects/audio_effect_phaser.h b/servers/audio/effects/audio_effect_phaser.h new file mode 100644 index 0000000000..53a8ab8bd8 --- /dev/null +++ b/servers/audio/effects/audio_effect_phaser.h @@ -0,0 +1,81 @@ +#ifndef AUDIO_EFFECT_PHASER_H +#define AUDIO_EFFECT_PHASER_H + + + +#include "servers/audio/audio_effect.h" + +class AudioEffectPhaser; + +class AudioEffectPhaserInstance : public AudioEffectInstance { + GDCLASS(AudioEffectPhaserInstance,AudioEffectInstance) +friend class AudioEffectPhaser; + Ref<AudioEffectPhaser> base; + + float phase; + AudioFrame h; + + class AllpassDelay{ + float a, h; + public: + + _ALWAYS_INLINE_ void delay( float d ) { + a = (1.f - d) / (1.f + d); + } + + _ALWAYS_INLINE_ float update( float s ){ + float y = s * -a + h; + h = y * a + s; + return y; + } + + AllpassDelay() { a =0; h = 0;} + + }; + + AllpassDelay allpass[2][6]; +public: + + virtual void process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count); + +}; + + +class AudioEffectPhaser : public AudioEffect { + GDCLASS(AudioEffectPhaser,AudioEffect) + +friend class AudioEffectPhaserInstance; + float range_min; + float range_max; + float rate; + float feedback; + float depth; + +protected: + + static void _bind_methods(); +public: + + + Ref<AudioEffectInstance> instance(); + + void set_range_min_hz(float p_hz); + float get_range_min_hz() const; + + void set_range_max_hz(float p_hz); + float get_range_max_hz() const; + + void set_rate_hz(float p_hz); + float get_rate_hz() const; + + void set_feedback(float p_fbk); + float get_feedback() const; + + void set_depth(float p_depth); + float get_depth() const; + + AudioEffectPhaser(); +}; + + +#endif // AUDIO_EFFECT_PHASER_H diff --git a/servers/audio/effects/audio_effect_pitch_shift.cpp b/servers/audio/effects/audio_effect_pitch_shift.cpp new file mode 100644 index 0000000000..1222c7b1b2 --- /dev/null +++ b/servers/audio/effects/audio_effect_pitch_shift.cpp @@ -0,0 +1,298 @@ +#include "audio_effect_pitch_shift.h" +#include "servers/audio_server.h" +#include "math_funcs.h" +/**************************************************************************** +* +* NAME: smbPitchShift.cpp +* VERSION: 1.2 +* HOME URL: http://blogs.zynaptiq.com/bernsee +* KNOWN BUGS: none +* +* SYNOPSIS: Routine for doing pitch shifting while maintaining +* duration using the Short Time Fourier Transform. +* +* DESCRIPTION: The routine takes a pitchShift factor value which is between 0.5 +* (one octave down) and 2. (one octave up). A value of exactly 1 does not change +* the pitch. numSampsToProcess tells the routine how many samples in indata[0... +* numSampsToProcess-1] should be pitch shifted and moved to outdata[0 ... +* numSampsToProcess-1]. The two buffers can be identical (ie. it can process the +* data in-place). fftFrameSize defines the FFT frame size used for the +* processing. Typical values are 1024, 2048 and 4096. It may be any value <= +* MAX_FRAME_LENGTH but it MUST be a power of 2. osamp is the STFT +* oversampling factor which also determines the overlap between adjacent STFT +* frames. It should at least be 4 for moderate scaling ratios. A value of 32 is +* recommended for best quality. sampleRate takes the sample rate for the signal +* in unit Hz, ie. 44100 for 44.1 kHz audio. The data passed to the routine in +* indata[] should be in the range [-1.0, 1.0), which is also the output range +* for the data, make sure you scale the data accordingly (for 16bit signed integers +* you would have to divide (and multiply) by 32768). +* +* COPYRIGHT 1999-2015 Stephan M. Bernsee <s.bernsee [AT] zynaptiq [DOT] com> +* +* The Wide Open License (WOL) +* +* Permission to use, copy, modify, distribute and sell this software and its +* documentation for any purpose is hereby granted without fee, provided that +* the above copyright notice and this license appear in all source copies. +* THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY OF +* ANY KIND. See http://www.dspguru.com/wol.htm for more information. +* +*****************************************************************************/ + + +void SMBPitchShift::PitchShift(float pitchShift, long numSampsToProcess, long fftFrameSize, long osamp, float sampleRate, float *indata, float *outdata,int stride) { + + + /* + Routine smbPitchShift(). See top of file for explanation + Purpose: doing pitch shifting while maintaining duration using the Short + Time Fourier Transform. + Author: (c)1999-2015 Stephan M. Bernsee <s.bernsee [AT] zynaptiq [DOT] com> + */ + + double magn, phase, tmp, window, real, imag; + double freqPerBin, expct; + long i,k, qpd, index, inFifoLatency, stepSize, fftFrameSize2; + + /* set up some handy variables */ + fftFrameSize2 = fftFrameSize/2; + stepSize = fftFrameSize/osamp; + freqPerBin = sampleRate/(double)fftFrameSize; + expct = 2.*Math_PI*(double)stepSize/(double)fftFrameSize; + inFifoLatency = fftFrameSize-stepSize; + if (gRover == 0) gRover = inFifoLatency; + + /* initialize our static arrays */ + + /* main processing loop */ + for (i = 0; i < numSampsToProcess; i++){ + + /* As long as we have not yet collected enough data just read in */ + gInFIFO[gRover] = indata[i*stride]; + outdata[i*stride] = gOutFIFO[gRover-inFifoLatency]; + gRover++; + + /* now we have enough data for processing */ + if (gRover >= fftFrameSize) { + gRover = inFifoLatency; + + /* do windowing and re,im interleave */ + for (k = 0; k < fftFrameSize;k++) { + window = -.5*cos(2.*Math_PI*(double)k/(double)fftFrameSize)+.5; + gFFTworksp[2*k] = gInFIFO[k] * window; + gFFTworksp[2*k+1] = 0.; + } + + + /* ***************** ANALYSIS ******************* */ + /* do transform */ + smbFft(gFFTworksp, fftFrameSize, -1); + + /* this is the analysis step */ + for (k = 0; k <= fftFrameSize2; k++) { + + /* de-interlace FFT buffer */ + real = gFFTworksp[2*k]; + imag = gFFTworksp[2*k+1]; + + /* compute magnitude and phase */ + magn = 2.*sqrt(real*real + imag*imag); + phase = atan2(imag,real); + + /* compute phase difference */ + tmp = phase - gLastPhase[k]; + gLastPhase[k] = phase; + + /* subtract expected phase difference */ + tmp -= (double)k*expct; + + /* map delta phase into +/- Pi interval */ + qpd = tmp/Math_PI; + if (qpd >= 0) qpd += qpd&1; + else qpd -= qpd&1; + tmp -= Math_PI*(double)qpd; + + /* get deviation from bin frequency from the +/- Pi interval */ + tmp = osamp*tmp/(2.*Math_PI); + + /* compute the k-th partials' true frequency */ + tmp = (double)k*freqPerBin + tmp*freqPerBin; + + /* store magnitude and true frequency in analysis arrays */ + gAnaMagn[k] = magn; + gAnaFreq[k] = tmp; + + } + + /* ***************** PROCESSING ******************* */ + /* this does the actual pitch shifting */ + memset(gSynMagn, 0, fftFrameSize*sizeof(float)); + memset(gSynFreq, 0, fftFrameSize*sizeof(float)); + for (k = 0; k <= fftFrameSize2; k++) { + index = k*pitchShift; + if (index <= fftFrameSize2) { + gSynMagn[index] += gAnaMagn[k]; + gSynFreq[index] = gAnaFreq[k] * pitchShift; + } + } + + /* ***************** SYNTHESIS ******************* */ + /* this is the synthesis step */ + for (k = 0; k <= fftFrameSize2; k++) { + + /* get magnitude and true frequency from synthesis arrays */ + magn = gSynMagn[k]; + tmp = gSynFreq[k]; + + /* subtract bin mid frequency */ + tmp -= (double)k*freqPerBin; + + /* get bin deviation from freq deviation */ + tmp /= freqPerBin; + + /* take osamp into account */ + tmp = 2.*Math_PI*tmp/osamp; + + /* add the overlap phase advance back in */ + tmp += (double)k*expct; + + /* accumulate delta phase to get bin phase */ + gSumPhase[k] += tmp; + phase = gSumPhase[k]; + + /* get real and imag part and re-interleave */ + gFFTworksp[2*k] = magn*cos(phase); + gFFTworksp[2*k+1] = magn*sin(phase); + } + + /* zero negative frequencies */ + for (k = fftFrameSize+2; k < 2*fftFrameSize; k++) gFFTworksp[k] = 0.; + + /* do inverse transform */ + smbFft(gFFTworksp, fftFrameSize, 1); + + /* do windowing and add to output accumulator */ + for(k=0; k < fftFrameSize; k++) { + window = -.5*cos(2.*Math_PI*(double)k/(double)fftFrameSize)+.5; + gOutputAccum[k] += 2.*window*gFFTworksp[2*k]/(fftFrameSize2*osamp); + } + for (k = 0; k < stepSize; k++) gOutFIFO[k] = gOutputAccum[k]; + + /* shift accumulator */ + memmove(gOutputAccum, gOutputAccum+stepSize, fftFrameSize*sizeof(float)); + + /* move input FIFO */ + for (k = 0; k < inFifoLatency; k++) gInFIFO[k] = gInFIFO[k+stepSize]; + } + } + + + +} + + +void SMBPitchShift::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 AudioEffectPitchShiftInstance::process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count) { + + float sample_rate = AudioServer::get_singleton()->get_mix_rate(); + + float *in_l = (float*)p_src_frames; + float *in_r = in_l + 1; + + float *out_l = (float*)p_dst_frames; + float *out_r = out_l + 1; + + shift_l.PitchShift(base->pitch_scale,p_frame_count,2048,4,sample_rate,in_l,out_l,2); + shift_r.PitchShift(base->pitch_scale,p_frame_count,2048,4,sample_rate,in_r,out_r,2); + +} + + +Ref<AudioEffectInstance> AudioEffectPitchShift::instance() { + Ref<AudioEffectPitchShiftInstance> ins; + ins.instance(); + ins->base=Ref<AudioEffectPitchShift>(this); + + + return ins; +} + +void AudioEffectPitchShift::set_pitch_scale(float p_adjust) { + + pitch_scale=p_adjust; +} + +float AudioEffectPitchShift::get_pitch_scale() const { + + return pitch_scale; +} + + +void AudioEffectPitchShift::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_pitch_scale","rate"),&AudioEffectPitchShift::set_pitch_scale); + ClassDB::bind_method(D_METHOD("get_pitch_scale"),&AudioEffectPitchShift::get_pitch_scale); + + ADD_PROPERTY(PropertyInfo(Variant::REAL,"pitch_scale",PROPERTY_HINT_RANGE,"0.01,16,0.01"),"set_pitch_scale","get_pitch_scale"); + +} + +AudioEffectPitchShift::AudioEffectPitchShift() { + pitch_scale=1.0; + +} diff --git a/servers/audio/effects/audio_effect_pitch_shift.h b/servers/audio/effects/audio_effect_pitch_shift.h new file mode 100644 index 0000000000..d1343a0745 --- /dev/null +++ b/servers/audio/effects/audio_effect_pitch_shift.h @@ -0,0 +1,89 @@ +#ifndef AUDIO_EFFECT_PITCH_SHIFT_H +#define AUDIO_EFFECT_PITCH_SHIFT_H + + +#include "servers/audio/audio_effect.h" + +class SMBPitchShift { + + enum { + MAX_FRAME_LENGTH=8192 + }; + + float gInFIFO[MAX_FRAME_LENGTH]; + float gOutFIFO[MAX_FRAME_LENGTH]; + float gFFTworksp[2*MAX_FRAME_LENGTH]; + float gLastPhase[MAX_FRAME_LENGTH/2+1]; + float gSumPhase[MAX_FRAME_LENGTH/2+1]; + float gOutputAccum[2*MAX_FRAME_LENGTH]; + float gAnaFreq[MAX_FRAME_LENGTH]; + float gAnaMagn[MAX_FRAME_LENGTH]; + float gSynFreq[MAX_FRAME_LENGTH]; + float gSynMagn[MAX_FRAME_LENGTH]; + long gRover; + + void smbFft(float *fftBuffer, long fftFrameSize, long sign); +public: + void PitchShift(float pitchShift, long numSampsToProcess, long fftFrameSize, long osamp, float sampleRate, float *indata, float *outdata, int stride); + + SMBPitchShift() { + gRover=0; + memset(gInFIFO, 0, MAX_FRAME_LENGTH*sizeof(float)); + memset(gOutFIFO, 0, MAX_FRAME_LENGTH*sizeof(float)); + memset(gFFTworksp, 0, 2*MAX_FRAME_LENGTH*sizeof(float)); + memset(gLastPhase, 0, (MAX_FRAME_LENGTH/2+1)*sizeof(float)); + memset(gSumPhase, 0, (MAX_FRAME_LENGTH/2+1)*sizeof(float)); + memset(gOutputAccum, 0, 2*MAX_FRAME_LENGTH*sizeof(float)); + memset(gAnaFreq, 0, MAX_FRAME_LENGTH*sizeof(float)); + memset(gAnaMagn, 0, MAX_FRAME_LENGTH*sizeof(float)); + } + + +}; + + +class AudioEffectPitchShift; + +class AudioEffectPitchShiftInstance : public AudioEffectInstance { + GDCLASS(AudioEffectPitchShiftInstance,AudioEffectInstance) +friend class AudioEffectPitchShift; + Ref<AudioEffectPitchShift> base; + + SMBPitchShift shift_l; + SMBPitchShift shift_r; + + +public: + + virtual void process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count); + +}; + + +class AudioEffectPitchShift : public AudioEffect { + GDCLASS(AudioEffectPitchShift,AudioEffect) + +friend class AudioEffectPitchShiftInstance; + + float pitch_scale; + int window_size; + float wet; + float dry; + bool filter; + +protected: + + static void _bind_methods(); +public: + + + Ref<AudioEffectInstance> instance(); + + void set_pitch_scale(float p_adjust); + float get_pitch_scale() const; + + AudioEffectPitchShift(); +}; + + +#endif // AUDIO_EFFECT_PITCH_SHIFT_H diff --git a/servers/audio/effects/audio_effect_reverb.cpp b/servers/audio/effects/audio_effect_reverb.cpp new file mode 100644 index 0000000000..f84dffdd36 --- /dev/null +++ b/servers/audio/effects/audio_effect_reverb.cpp @@ -0,0 +1,182 @@ +#include "audio_effect_reverb.h" +#include "servers/audio_server.h" +void AudioEffectReverbInstance::process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count) { + + for(int i=0;i<2;i++) { + Reverb &r=reverb[i]; + + r.set_predelay( base->predelay); + r.set_predelay_feedback( base->predelay_fb ); + r.set_highpass( base->hpf ); + r.set_room_size( base->room_size ); + r.set_damp( base->damping ); + r.set_extra_spread( base->spread ); + r.set_wet( base->wet ); + r.set_dry( base->dry ); + } + + int todo = p_frame_count; + int offset=0; + + while(todo) { + + int to_mix = MIN(todo,Reverb::INPUT_BUFFER_MAX_SIZE); + + for(int j=0;j<to_mix;j++) { + tmp_src[j]=p_src_frames[offset+j].l; + } + + reverb[0].process(tmp_src,tmp_dst,to_mix); + + for(int j=0;j<to_mix;j++) { + p_dst_frames[offset+j].l=tmp_dst[j]; + tmp_src[j]=p_src_frames[offset+j].r; + } + + reverb[1].process(tmp_src,tmp_dst,to_mix); + + for(int j=0;j<to_mix;j++) { + p_dst_frames[offset+j].r=tmp_dst[j]; + } + + offset+=to_mix; + todo-=to_mix; + } +} + +AudioEffectReverbInstance::AudioEffectReverbInstance() { + + reverb[0].set_mix_rate( AudioServer::get_singleton()->get_mix_rate() ); + reverb[0].set_extra_spread_base(0); + reverb[1].set_mix_rate( AudioServer::get_singleton()->get_mix_rate() ); + reverb[1].set_extra_spread_base(0.000521); //for stereo effect + +} + +Ref<AudioEffectInstance> AudioEffectReverb::instance() { + Ref<AudioEffectReverbInstance> ins; + ins.instance(); + ins->base=Ref<AudioEffectReverb>(this); + return ins; +} + +void AudioEffectReverb::set_predelay_msec(float p_msec) { + + predelay=p_msec; +} + +void AudioEffectReverb::set_predelay_feedback(float p_feedback){ + + predelay_fb=p_feedback; +} +void AudioEffectReverb::set_room_size(float p_size){ + + room_size=p_size; +} +void AudioEffectReverb::set_damping(float p_damping){ + + damping=p_damping; +} +void AudioEffectReverb::set_spread(float p_spread){ + + spread=p_spread; +} + +void AudioEffectReverb::set_dry(float p_dry){ + + dry=p_dry; +} +void AudioEffectReverb::set_wet(float p_wet){ + + wet=p_wet; +} +void AudioEffectReverb::set_hpf(float p_hpf) { + + hpf=p_hpf; +} + +float AudioEffectReverb::get_predelay_msec() const { + + return predelay; +} +float AudioEffectReverb::get_predelay_feedback() const { + + return predelay_fb; +} +float AudioEffectReverb::get_room_size() const { + + return room_size; +} +float AudioEffectReverb::get_damping() const { + + return damping; +} +float AudioEffectReverb::get_spread() const { + + return spread; +} +float AudioEffectReverb::get_dry() const { + + return dry; +} +float AudioEffectReverb::get_wet() const { + + return wet; +} +float AudioEffectReverb::get_hpf() const { + + return hpf; +} + + +void AudioEffectReverb::_bind_methods() { + + + ClassDB::bind_method(D_METHOD("set_predelay_msec","msec"),&AudioEffectReverb::set_predelay_msec); + ClassDB::bind_method(D_METHOD("get_predelay_msec"),&AudioEffectReverb::get_predelay_msec); + + ClassDB::bind_method(D_METHOD("set_predelay_feedback","feedback"),&AudioEffectReverb::set_predelay_feedback); + ClassDB::bind_method(D_METHOD("get_predelay_feedback"),&AudioEffectReverb::get_predelay_feedback); + + ClassDB::bind_method(D_METHOD("set_room_size","size"),&AudioEffectReverb::set_room_size); + ClassDB::bind_method(D_METHOD("get_room_size"),&AudioEffectReverb::get_room_size); + + ClassDB::bind_method(D_METHOD("set_damping","amount"),&AudioEffectReverb::set_damping); + ClassDB::bind_method(D_METHOD("get_damping"),&AudioEffectReverb::get_damping); + + ClassDB::bind_method(D_METHOD("set_spread","amount"),&AudioEffectReverb::set_spread); + ClassDB::bind_method(D_METHOD("get_spread"),&AudioEffectReverb::get_spread); + + ClassDB::bind_method(D_METHOD("set_dry","amount"),&AudioEffectReverb::set_dry); + ClassDB::bind_method(D_METHOD("get_dry"),&AudioEffectReverb::get_dry); + + ClassDB::bind_method(D_METHOD("set_wet","amount"),&AudioEffectReverb::set_wet); + ClassDB::bind_method(D_METHOD("get_wet"),&AudioEffectReverb::get_wet); + + ClassDB::bind_method(D_METHOD("set_hpf","amount"),&AudioEffectReverb::set_hpf); + ClassDB::bind_method(D_METHOD("get_hpf"),&AudioEffectReverb::get_hpf); + + + ADD_GROUP("Predelay","predelay_"); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"predelay_msec",PROPERTY_HINT_RANGE,"20,500,1"),"set_predelay_msec","get_predelay_msec"); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"predelay_feedback",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_predelay_msec","get_predelay_msec"); + ADD_GROUP("",""); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"room_size",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_room_size","get_room_size"); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"damping",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_damping","get_damping"); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"spread",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_spread","get_spread"); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"hipass",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_hpf","get_hpf"); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"dry",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_dry","get_dry"); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"wet",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_wet","get_wet"); +} + +AudioEffectReverb::AudioEffectReverb() { + predelay=150; + predelay_fb=0.4; + hpf=0; + room_size=0.8; + damping=0.5; + spread=1.0; + dry=1.0; + wet=0.5; + +} diff --git a/servers/audio/effects/audio_effect_reverb.h b/servers/audio/effects/audio_effect_reverb.h new file mode 100644 index 0000000000..e05ffe422f --- /dev/null +++ b/servers/audio/effects/audio_effect_reverb.h @@ -0,0 +1,76 @@ +#ifndef AUDIOEFFECTREVERB_H +#define AUDIOEFFECTREVERB_H + + +#include "servers/audio/audio_effect.h" +#include "servers/audio/effects/reverb.h" + +class AudioEffectReverb; + +class AudioEffectReverbInstance : public AudioEffectInstance { + GDCLASS(AudioEffectReverbInstance,AudioEffectInstance) + + Ref<AudioEffectReverb> base; + + float tmp_src[Reverb::INPUT_BUFFER_MAX_SIZE]; + float tmp_dst[Reverb::INPUT_BUFFER_MAX_SIZE]; + +friend class AudioEffectReverb; + + Reverb reverb[2]; + + +public: + + virtual void process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count); + AudioEffectReverbInstance(); +}; + + +class AudioEffectReverb : public AudioEffect { + GDCLASS(AudioEffectReverb,AudioEffect) + +friend class AudioEffectReverbInstance; + + float predelay; + float predelay_fb; + float hpf; + float room_size; + float damping; + float spread; + float dry; + float wet; + +protected: + + static void _bind_methods(); +public: + + + void set_predelay_msec(float p_msec); + void set_predelay_feedback(float p_feedback); + void set_room_size(float p_size); + void set_damping(float p_damping); + void set_spread(float p_spread); + void set_dry(float p_dry); + void set_wet(float p_wet); + void set_hpf(float p_hpf); + + float get_predelay_msec() const; + float get_predelay_feedback() const; + float get_room_size() const; + float get_damping() const; + float get_spread() const; + float get_dry() const; + float get_wet() const; + float get_hpf() const; + + Ref<AudioEffectInstance> instance(); + void set_volume_db(float p_volume); + float get_volume_db() const; + + AudioEffectReverb(); +}; + + +#endif // AUDIOEFFECTREVERB_H diff --git a/servers/audio/effects/audio_effect_stereo_enhance.cpp b/servers/audio/effects/audio_effect_stereo_enhance.cpp new file mode 100644 index 0000000000..0afabc8f3d --- /dev/null +++ b/servers/audio/effects/audio_effect_stereo_enhance.cpp @@ -0,0 +1,135 @@ +#include "audio_effect_stereo_enhance.h" +#include "servers/audio_server.h" +void AudioEffectStereoEnhanceInstance::process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count) { + + + float intensity=base->pan_pullout; + bool surround_mode=base->surround>0; + float surround_amount=base->surround; + unsigned int delay_frames=(base->time_pullout/1000.0)*AudioServer::get_singleton()->get_mix_rate(); + + for (int i=0;i<p_frame_count;i++) { + + float l=p_src_frames[i].l; + float r=p_src_frames[i].r; + + float center=(l+r)/2.0f; + + l=( center+(l-center)*intensity ); + r=( center+(r-center)*intensity ); + + if (surround_mode) { + + float val=(l+r)/2.0; + + delay_ringbuff[ringbuff_pos&ringbuff_mask]=val; + + float out=delay_ringbuff[(ringbuff_pos-delay_frames)&ringbuff_mask]*surround_amount; + + l+=out; + r+=-out; + } else { + + float val=r; + + delay_ringbuff[ringbuff_pos&ringbuff_mask]=val; + + //r is delayed + r=delay_ringbuff[(ringbuff_pos-delay_frames)&ringbuff_mask];; + + + } + + p_dst_frames[i].l=l; + p_dst_frames[i].r=r; + ringbuff_pos++; + + } + +} + + +AudioEffectStereoEnhanceInstance::~AudioEffectStereoEnhanceInstance() { + + memdelete_arr(delay_ringbuff); +} + +Ref<AudioEffectInstance> AudioEffectStereoEnhance::instance() { + Ref<AudioEffectStereoEnhanceInstance> ins; + ins.instance(); + + ins->base=Ref<AudioEffectStereoEnhance>(this); + + + float ring_buffer_max_size=AudioEffectStereoEnhanceInstance::MAX_DELAY_MS+2; + ring_buffer_max_size/=1000.0;//convert to seconds + ring_buffer_max_size*=AudioServer::get_singleton()->get_mix_rate(); + + int ringbuff_size=(int)ring_buffer_max_size; + + int bits=0; + + while(ringbuff_size>0) { + bits++; + ringbuff_size/=2; + } + + ringbuff_size=1<<bits; + ins->ringbuff_mask=ringbuff_size-1; + ins->ringbuff_pos=0; + + ins->delay_ringbuff = memnew_arr(float,ringbuff_size ); + + return ins; +} + +void AudioEffectStereoEnhance::set_pan_pullout(float p_amount) { + + pan_pullout=p_amount; +} + +float AudioEffectStereoEnhance::get_pan_pullout() const { + + return pan_pullout; +} + +void AudioEffectStereoEnhance::set_time_pullout(float p_amount) { + + time_pullout=p_amount; +} +float AudioEffectStereoEnhance::get_time_pullout() const { + + return time_pullout; +} + +void AudioEffectStereoEnhance::set_surround(float p_amount) { + + surround=p_amount; +} +float AudioEffectStereoEnhance::get_surround() const { + + return surround; +} + +void AudioEffectStereoEnhance::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_pan_pullout","amount"),&AudioEffectStereoEnhance::set_pan_pullout); + ClassDB::bind_method(D_METHOD("get_pan_pullout"),&AudioEffectStereoEnhance::get_pan_pullout); + + ClassDB::bind_method(D_METHOD("set_time_pullout","amount"),&AudioEffectStereoEnhance::set_time_pullout); + ClassDB::bind_method(D_METHOD("get_time_pullout"),&AudioEffectStereoEnhance::get_time_pullout); + + ClassDB::bind_method(D_METHOD("set_surround","amount"),&AudioEffectStereoEnhance::set_surround); + ClassDB::bind_method(D_METHOD("get_surround"),&AudioEffectStereoEnhance::get_surround); + + ADD_PROPERTY(PropertyInfo(Variant::REAL,"pan_pullout",PROPERTY_HINT_RANGE,"0,4,0.01"),"set_pan_pullout","get_pan_pullout"); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"time_pullout_ms",PROPERTY_HINT_RANGE,"0,50,0.01"),"set_time_pullout","get_time_pullout"); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"surround",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_surround","get_surround"); +} + +AudioEffectStereoEnhance::AudioEffectStereoEnhance() +{ + pan_pullout=1; + time_pullout=0; + surround=0; +} diff --git a/servers/audio/effects/audio_effect_stereo_enhance.h b/servers/audio/effects/audio_effect_stereo_enhance.h new file mode 100644 index 0000000000..06762acbf3 --- /dev/null +++ b/servers/audio/effects/audio_effect_stereo_enhance.h @@ -0,0 +1,62 @@ +#ifndef AUDIOEFFECTSTEREOENHANCE_H +#define AUDIOEFFECTSTEREOENHANCE_H + + +#include "servers/audio/audio_effect.h" + +class AudioEffectStereoEnhance; + +class AudioEffectStereoEnhanceInstance : public AudioEffectInstance { + GDCLASS(AudioEffectStereoEnhanceInstance,AudioEffectInstance) +friend class AudioEffectStereoEnhance; + Ref<AudioEffectStereoEnhance> base; + + enum { + + MAX_DELAY_MS=50 + }; + + float *delay_ringbuff; + unsigned int ringbuff_pos; + unsigned int ringbuff_mask; + + +public: + + virtual void process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count); + + ~AudioEffectStereoEnhanceInstance(); +}; + + +class AudioEffectStereoEnhance : public AudioEffect { + GDCLASS(AudioEffectStereoEnhance,AudioEffect) + +friend class AudioEffectStereoEnhanceInstance; + float volume_db; + + float pan_pullout; + float time_pullout; + float surround; + +protected: + + static void _bind_methods(); +public: + + + Ref<AudioEffectInstance> instance(); + + void set_pan_pullout(float p_amount); + float get_pan_pullout() const; + + void set_time_pullout(float p_amount); + float get_time_pullout() const; + + void set_surround(float p_amount); + float get_surround() const; + + AudioEffectStereoEnhance(); +}; + +#endif // AUDIOEFFECTSTEREOENHANCE_H diff --git a/servers/audio/effects/eq.cpp b/servers/audio/effects/eq.cpp new file mode 100644 index 0000000000..5aab60a558 --- /dev/null +++ b/servers/audio/effects/eq.cpp @@ -0,0 +1,219 @@ +// +// C++ Interface: eq +// +// Description: +// +// +// Author: reduzio@gmail.com (C) 2006 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#include "eq.h" +#include <math.h> +#include "error_macros.h" +#include "math_funcs.h" + +#define POW2(v) ((v)*(v)) + +/* Helper */ + static int solve_quadratic(double a,double b,double c,double *r1, double *r2) { +//solves quadractic and returns number of roots + + double base=2*a; + if (base == 0.0f) + return 0; + + double squared=b*b-4*a*c; + if (squared<0.0) + return 0; + + squared=sqrt(squared); + + *r1=(-b+squared)/base; + *r2=(-b-squared)/base; + + if (*r1==*r2) + return 1; + else + return 2; + } + +EQ::BandProcess::BandProcess() { + + c1=c2=c3=history.a1=history.a2=history.a3=0; + history.b1=history.b2=history.b3=0; +} + +void EQ::recalculate_band_coefficients() { + +#define BAND_LOG( m_f ) ( log((m_f)) / log(2.) ) + + for (int i=0;i<band.size();i++) { + + double octave_size; + + double frq=band[i].freq; + + if (i==0) { + + octave_size=BAND_LOG(band[1].freq)-BAND_LOG(frq); + } else if (i==(band.size()-1)) { + + octave_size=BAND_LOG(frq)-BAND_LOG(band[i-1].freq); + } else { + + double next=BAND_LOG(band[i+1].freq)-BAND_LOG(frq); + double prev=BAND_LOG(frq)-BAND_LOG(band[i-1].freq); + octave_size=(next+prev)/2.0; + } + + + + double frq_l=round(frq/pow(2.0,octave_size/2.0)); + + + + double side_gain2=POW2(Math_SQRT12); + double th=2.0*Math_PI*frq/mix_rate; + double th_l=2.0*Math_PI*frq_l/mix_rate; + + double c2a=side_gain2 * POW2(cos(th)) + - 2.0 * side_gain2 * cos(th_l) * cos(th) + + side_gain2 + - POW2(sin(th_l)); + + double c2b=2.0 * side_gain2 * POW2(cos(th_l)) + + side_gain2 * POW2(cos(th)) + - 2.0 * side_gain2 * cos(th_l) * cos(th) + - side_gain2 + + POW2(sin(th_l)); + + double c2c=0.25 * side_gain2 * POW2(cos(th)) + - 0.5 * side_gain2 * cos(th_l) * cos(th) + + 0.25 * side_gain2 + - 0.25 * POW2(sin(th_l)); + + //printf("band %i, precoefs = %f,%f,%f\n",i,c2a,c2b,c2c); + + double r1,r2; //roots + int roots=solve_quadratic(c2a,c2b,c2c,&r1,&r2); + + ERR_CONTINUE( roots==0 ); + + band[i].c1=2.0 * ((0.5-r1)/2.0); + band[i].c2=2.0 * r1; + band[i].c3=2.0 * (0.5+r1) * cos(th); + //printf("band %i, coefs = %f,%f,%f\n",i,(float)bands[i].c1,(float)bands[i].c2,(float)bands[i].c3); + + } +} + +void EQ::set_preset_band_mode(Preset p_preset) { + + + band.clear(); + +#define PUSH_BANDS(m_bands) \ + for (int i=0;i<m_bands;i++) { \ + Band b; \ + b.freq=bands[i];\ + band.push_back(b);\ + } + + switch (p_preset) { + + case PRESET_6_BANDS: { + + static const double bands[] = { 32 , 100 , 320 , 1e3, 3200, 10e3 }; + PUSH_BANDS(6); + + } break; + + case PRESET_8_BANDS: { + + static const double bands[] = { 32,72,192,512,1200,3000,7500,16e3 }; + + PUSH_BANDS(8); + } break; + + case PRESET_10_BANDS: { + static const double bands[] = { 31.25, 62.5, 125 , 250 , 500 , 1e3, 2e3, 4e3, 8e3, 16e3 }; + + PUSH_BANDS(10); + + } break; + + case PRESET_21_BANDS: { + + static const double bands[] = { 22 , 32 , 44 , 63 , 90 , 125 , 175 , 250 , 350 , 500 , 700 , 1e3, 1400 , 2e3, 2800 , 4e3, 5600 , 8e3, 11e3, 16e3, 22e3 }; + PUSH_BANDS(21); + + } break; + + case PRESET_31_BANDS: { + + static const double bands[] = { 20, 25, 31.5, 40 , 50 , 63 , 80 , 100 , 125 , 160 , 200 , 250 , 315 , 400 , 500 , 630 , 800 , 1e3 , 1250 , 1600 , 2e3, 2500 , 3150 , 4e3, 5e3, 6300 , 8e3, 10e3, 12500 , 16e3, 20e3 }; + PUSH_BANDS(31); + } break; + + }; + + recalculate_band_coefficients(); +} + +int EQ::get_band_count() const { + + return band.size(); +} +float EQ::get_band_frequency(int p_band) { + + ERR_FAIL_INDEX_V(p_band,band.size(),0); + return band[p_band].freq; +} +void EQ::set_bands(const Vector<float>& p_bands) { + + band.resize(p_bands.size()); + for (int i=0;i<p_bands.size();i++) { + + band[i].freq=p_bands[i]; + } + + recalculate_band_coefficients(); + +} + +void EQ::set_mix_rate(float p_mix_rate) { + + mix_rate=p_mix_rate; + recalculate_band_coefficients(); +} + +EQ::BandProcess EQ::get_band_processor(int p_band) const { + + + EQ::BandProcess band_proc; + + ERR_FAIL_INDEX_V(p_band,band.size(),band_proc); + + band_proc.c1=band[p_band].c1; + band_proc.c2=band[p_band].c2; + band_proc.c3=band[p_band].c3; + + return band_proc; + + +} + + +EQ::EQ() +{ + mix_rate=44100; +} + + +EQ::~EQ() +{ +} + + diff --git a/servers/audio/effects/eq.h b/servers/audio/effects/eq.h new file mode 100644 index 0000000000..2c4668cd0b --- /dev/null +++ b/servers/audio/effects/eq.h @@ -0,0 +1,106 @@ +// +// C++ Interface: eq +// +// Description: +// +// +// Author: reduzio@gmail.com (C) 2006 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#ifndef EQ_FILTER_H +#define EQ_FILTER_H + + +#include "typedefs.h" +#include "vector.h" + + +/** +@author Juan Linietsky +*/ + +class EQ { +public: + + enum Preset { + + PRESET_6_BANDS, + PRESET_8_BANDS, + PRESET_10_BANDS, + PRESET_21_BANDS, + PRESET_31_BANDS + }; + + + + class BandProcess { + + friend class EQ; + float c1,c2,c3; + struct History { + float a1,a2,a3; + float b1,b2,b3; + + } history; + + public: + + inline void process_one(float & p_data); + + BandProcess(); + }; + +private: + struct Band { + + float freq; + float c1,c2,c3; + }; + + Vector<Band> band; + + float mix_rate; + + void recalculate_band_coefficients(); + +public: + + + void set_mix_rate(float p_mix_rate); + + int get_band_count() const; + void set_preset_band_mode(Preset p_preset); + void set_bands(const Vector<float>& p_bands); + BandProcess get_band_processor(int p_band) const; + float get_band_frequency(int p_band); + + EQ(); + ~EQ(); + +}; + + +/* Inline Function */ + +inline void EQ::BandProcess::process_one(float & p_data) { + + + history.a1=p_data; + + history.b1= c1 * ( history.a1 - history.a3 ) + + c3 * history.b2 + - c2 * history.b3; + + p_data = history.b1; + + history.a3=history.a2; + history.a2=history.a1; + history.b3=history.b2; + history.b2=history.b1; + +} + + +#endif diff --git a/servers/audio/effects/reverb.cpp b/servers/audio/effects/reverb.cpp new file mode 100644 index 0000000000..43ea0edb3a --- /dev/null +++ b/servers/audio/effects/reverb.cpp @@ -0,0 +1,364 @@ +// +// C++ Interface: reverb +// +// Description: +// +// +// Author: Juan Linietsky <reduzio@gmail.com>, (C) 2006 +// +// Copyright: See COPYING file that comes with this distribution +// +// + +#include "reverb.h" +#include <math.h> +#include "math_funcs.h" + + +const float Reverb::comb_tunings[MAX_COMBS]={ + //freeverb comb tunings + 0.025306122448979593, + 0.026938775510204082, + 0.028956916099773241, + 0.03074829931972789, + 0.032244897959183672, + 0.03380952380952381, + 0.035306122448979592, + 0.036666666666666667 +}; + +const float Reverb::allpass_tunings[MAX_ALLPASS]={ + //freeverb allpass tunings + 0.0051020408163265302, + 0.007732426303854875, + 0.01, + 0.012607709750566893 +}; + + + +void Reverb::process(float *p_src,float *p_dst,int p_frames) { + + if (p_frames>INPUT_BUFFER_MAX_SIZE) + p_frames=INPUT_BUFFER_MAX_SIZE; + + int predelay_frames=lrint((params.predelay/1000.0)*params.mix_rate); + if (predelay_frames<10) + predelay_frames=10; + if (predelay_frames>=echo_buffer_size) + predelay_frames=echo_buffer_size-1; + + for (int i=0;i<p_frames;i++) { + + if (echo_buffer_pos>=echo_buffer_size) + echo_buffer_pos=0; + + int read_pos=echo_buffer_pos-predelay_frames; + while (read_pos<0) + read_pos+=echo_buffer_size; + + float in=undenormalise(echo_buffer[read_pos]*params.predelay_fb+p_src[i]); + + echo_buffer[echo_buffer_pos]=in; + + input_buffer[i]=in; + + p_dst[i]=0; //take the chance and clear this + + echo_buffer_pos++; + } + + if (params.hpf>0) { + float hpaux=expf(-2.0*Math_PI*params.hpf*6000/params.mix_rate); + float hp_a1=(1.0+hpaux)/2.0; + float hp_a2=-(1.0+hpaux)/2.0; + float hp_b1=hpaux; + + for (int i=0;i<p_frames;i++) { + + float in=input_buffer[i]; + input_buffer[i]=in*hp_a1+hpf_h1*hp_a2+hpf_h2*hp_b1; + hpf_h2=input_buffer[i]; + hpf_h1=in; + } + } + + for (int i=0;i<MAX_COMBS;i++) { + + Comb &c=comb[i]; + + int size_limit=c.size-lrintf((float)c.extra_spread_frames*(1.0-params.extra_spread)); + for (int j=0;j<p_frames;j++) { + + if (c.pos>=size_limit) //reset this now just in case + c.pos=0; + + float out=undenormalise(c.buffer[c.pos]*c.feedback); + out=out*(1.0-c.damp)+c.damp_h*c.damp; //lowpass + c.damp_h=out; + c.buffer[c.pos]=input_buffer[j]+out; + p_dst[j]+=out; + c.pos++; + } + + } + + + static const float allpass_feedback=0.7; + /* this one works, but the other version is just nicer.... + int ap_size_limit[MAX_ALLPASS]; + + for (int i=0;i<MAX_ALLPASS;i++) { + + AllPass &a=allpass[i]; + ap_size_limit[i]=a.size-lrintf((float)a.extra_spread_frames*(1.0-params.extra_spread)); + } + + for (int i=0;i<p_frames;i++) { + + float sample=p_dst[i]; + float aux,in; + float AllPass*ap; + +#define PROCESS_ALLPASS(m_ap) \ + ap=&allpass[m_ap]; \ + if (ap->pos>=ap_size_limit[m_ap]) \ + ap->pos=0; \ + aux=undenormalise(ap->buffer[ap->pos]); \ + in=sample; \ + sample=-in+aux; \ + ap->pos++; + + + PROCESS_ALLPASS(0); + PROCESS_ALLPASS(1); + PROCESS_ALLPASS(2); + PROCESS_ALLPASS(3); + + p_dst[i]=sample; + } + */ + + for (int i=0;i<MAX_ALLPASS;i++) { + + AllPass &a=allpass[i]; + int size_limit=a.size-lrintf((float)a.extra_spread_frames*(1.0-params.extra_spread)); + + for (int j=0;j<p_frames;j++) { + + if (a.pos>=size_limit) + a.pos=0; + + float aux=a.buffer[a.pos]; + a.buffer[a.pos]=undenormalise(allpass_feedback*aux+p_dst[j]); + p_dst[j]=aux-allpass_feedback*a.buffer[a.pos]; + a.pos++; + + } + } + + static const float wet_scale=0.6; + + for (int i=0;i<p_frames;i++) { + + + p_dst[i]=p_dst[i]*params.wet*wet_scale+p_src[i]*params.dry; + } + +} + + +void Reverb::set_room_size(float p_size) { + + params.room_size=p_size; + update_parameters(); + +} +void Reverb::set_damp(float p_damp) { + + params.damp=p_damp; + update_parameters(); + +} +void Reverb::set_wet(float p_wet) { + + params.wet=p_wet; + +} + +void Reverb::set_dry(float p_dry) { + + params.dry=p_dry; + +} + +void Reverb::set_predelay(float p_predelay) { + + params.predelay=p_predelay; +} +void Reverb::set_predelay_feedback(float p_predelay_fb) { + + params.predelay_fb=p_predelay_fb; + +} + +void Reverb::set_highpass(float p_frq) { + + if (p_frq>1) + p_frq=1; + if (p_frq<0) + p_frq=0; + params.hpf=p_frq; +} + +void Reverb::set_extra_spread(float p_spread) { + + params.extra_spread=p_spread; + +} + + +void Reverb::set_mix_rate(float p_mix_rate) { + + params.mix_rate=p_mix_rate; + configure_buffers(); +} + +void Reverb::set_extra_spread_base(float p_sec) { + + params.extra_spread_base=p_sec; + configure_buffers(); +} + + +void Reverb::configure_buffers() { + + clear_buffers(); //clear if necesary + + for (int i=0;i<MAX_COMBS;i++) { + + Comb &c=comb[i]; + + + c.extra_spread_frames=lrint(params.extra_spread_base*params.mix_rate); + + int len=lrint(comb_tunings[i]*params.mix_rate)+c.extra_spread_frames; + if (len<5) + len=5; //may this happen? + + c.buffer = memnew_arr(float,len); + c.pos=0; + for (int j=0;j<len;j++) + c.buffer[j]=0; + c.size=len; + + } + + for (int i=0;i<MAX_ALLPASS;i++) { + + AllPass &a=allpass[i]; + + a.extra_spread_frames=lrint(params.extra_spread_base*params.mix_rate); + + int len=lrint(allpass_tunings[i]*params.mix_rate)+a.extra_spread_frames; + if (len<5) + len=5; //may this happen? + + a.buffer = memnew_arr(float,len); + a.pos=0; + for (int j=0;j<len;j++) + a.buffer[j]=0; + a.size=len; + } + + echo_buffer_size=(int)(((float)MAX_ECHO_MS/1000.0)*params.mix_rate+1.0); + echo_buffer = memnew_arr(float,echo_buffer_size); + for (int i=0;i<echo_buffer_size;i++) { + + echo_buffer[i]=0; + } + + echo_buffer_pos=0; +} + + +void Reverb::update_parameters() { + + //more freeverb derived constants + static const float room_scale = 0.28f; + static const float room_offset = 0.7f; + + for (int i=0;i<MAX_COMBS;i++) { + + Comb &c=comb[i]; + c.feedback=room_offset+params.room_size*room_scale; + if (c.feedback<room_offset) + c.feedback=room_offset; + else if (c.feedback>(room_offset+room_scale)) + c.feedback=(room_offset+room_scale); + + float auxdmp=params.damp/2.0+0.5; //only half the range (0.5 .. 1.0 is enough) + auxdmp*=auxdmp; + + c.damp=expf(-2.0*Math_PI*auxdmp*10000/params.mix_rate); // 0 .. 10khz + } + +} + +void Reverb::clear_buffers() { + + if (echo_buffer) + memdelete_arr(echo_buffer); + + for (int i=0;i<MAX_COMBS;i++) { + + if (comb[i].buffer) + memdelete_arr(comb[i].buffer); + + comb[i].buffer=0; + + } + + for (int i=0;i<MAX_ALLPASS;i++) { + + if (allpass[i].buffer) + memdelete_arr(allpass[i].buffer); + + allpass[i].buffer=0; + } + +} + +Reverb::Reverb() { + + params.room_size=0.8; + params.damp=0.5; + params.dry=1.0; + params.wet=0.0; + params.mix_rate=44100; + params.extra_spread_base=0; + params.extra_spread=1.0; + params.predelay=150; + params.predelay_fb=0.4; + params.hpf=0; + hpf_h1=0; + hpf_h2=0; + + + input_buffer=memnew_arr(float,INPUT_BUFFER_MAX_SIZE); + echo_buffer=0; + + configure_buffers(); + update_parameters(); + + +} + + +Reverb::~Reverb() { + + memdelete_arr(input_buffer); + clear_buffers(); +} + + diff --git a/servers/audio/effects/reverb.h b/servers/audio/effects/reverb.h new file mode 100644 index 0000000000..2c82be9156 --- /dev/null +++ b/servers/audio/effects/reverb.h @@ -0,0 +1,111 @@ +// +// C++ Interface: reverb +// +// Description: +// +// +// Author: Juan Linietsky <reduzio@gmail.com>, (C) 2006 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#ifndef REVERB_H +#define REVERB_H + +#include "typedefs.h" +#include "os/memory.h" +#include "audio_frame.h" + +class Reverb { +public: + enum { + INPUT_BUFFER_MAX_SIZE=1024, + + }; +private: + enum { + + MAX_COMBS=8, + MAX_ALLPASS=4, + MAX_ECHO_MS=500 + + }; + + + + static const float comb_tunings[MAX_COMBS]; + static const float allpass_tunings[MAX_ALLPASS]; + + struct Comb { + + int size; + float *buffer; + float feedback; + float damp; //lowpass + float damp_h; //history + int pos; + int extra_spread_frames; + + Comb() { size=0; buffer=0; feedback=0; damp_h=0; pos=0; } + }; + + struct AllPass { + + int size; + float *buffer; + int pos; + int extra_spread_frames; + AllPass() { size=0; buffer=0; pos=0; } + }; + + Comb comb[MAX_COMBS]; + AllPass allpass[MAX_ALLPASS]; + float *input_buffer; + float *echo_buffer; + int echo_buffer_size; + int echo_buffer_pos; + + float hpf_h1,hpf_h2; + + + struct Parameters { + + float room_size; + float damp; + float wet; + float dry; + float mix_rate; + float extra_spread_base; + float extra_spread; + float predelay; + float predelay_fb; + float hpf; + } params; + + void configure_buffers(); + void update_parameters(); + void clear_buffers(); +public: + + void set_room_size(float p_size); + void set_damp(float p_damp); + void set_wet(float p_wet); + void set_dry(float p_dry); + void set_predelay(float p_predelay); // in ms + void set_predelay_feedback(float p_predelay_fb); // in ms + void set_highpass(float p_frq); + void set_mix_rate(float p_mix_rate); + void set_extra_spread(float p_spread); + void set_extra_spread_base(float p_sec); + + void process(float *p_src,float *p_dst,int p_frames); + + Reverb(); + + ~Reverb(); + +}; + + + +#endif diff --git a/servers/audio/reverb_sw.cpp b/servers/audio/reverb_sw.cpp index 5721403ba3..5e02f37679 100644 --- a/servers/audio/reverb_sw.cpp +++ b/servers/audio/reverb_sw.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -100,145 +100,145 @@ struct ReverbParamsSW { static ReverbParamsSW reverb_params_Room = { 0x26C0/2, -// gLPF gEcho0 gEcho1 gEcho2 gEcho3 gWall + //gLPF gEcho0 gEcho1 gEcho2 gEcho3 gWall 0x6D80, 0x54B8, -0x4130, 0x0000, 0x0000, -0x4580, -// gReva gRevb gInputL gInputR + //gReva gRevb gInputL gInputR 0x5800, 0x5300, -0x8000, -0x8000, -// nRevaOldL nRevaOldR nRevbOldL nRevbOldR + //nRevaOldL nRevaOldR nRevbOldL nRevbOldR 0x01B4 - 0x007D, 0x0136 - 0x007D, 0x00B8 - 0x005B, 0x005C - 0x005B, -// nLwlNew nRwrNew nEcho0L nEcho0R nEcho1L nEcho1R + //nLwlNew nRwrNew nEcho0L nEcho0R nEcho1L nEcho1R 0x04D6, 0x0333, 0x03F0, 0x0227, 0x0374, 0x01EF, -// nLwlOld nRwrOld nLwrNew nRwlNew nEcho2L nEcho2R nEcho3L nEcho3R + //nLwlOld nRwrOld nLwrNew nRwlNew nEcho2L nEcho2R nEcho3L nEcho3R 0x0334, 0x01B5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, -// nLwrOld nRwlOld nRevaNewL nRevaNewR nRevbNewL nRevbNewR + //nLwrOld nRwlOld nRevaNewL nRevaNewR nRevbNewL nRevbNewR 0x0000, 0x0000, 0x01B4, 0x0136, 0x00B8, 0x005C }; static ReverbParamsSW reverb_params_StudioSmall = { 0x1F40/2, -// gLPF gEcho0 gEcho1 gEcho2 gEcho3 gWall + //gLPF gEcho0 gEcho1 gEcho2 gEcho3 gWall 0x70F0, 0x4FA8, -0x4320, 0x4410, -0x3F10, -0x6400, -// gReva gRevb gInputL gInputR + //gReva gRevb gInputL gInputR 0x5280, 0x4EC0, -0x8000, -0x8000, -// nRevaOldL nRevaOldR nRevbOldL nRevbOldR + //nRevaOldL nRevaOldR nRevbOldL nRevbOldR 0x00B4 - 0x0033, 0x0080 - 0x0033, 0x004C - 0x0025, 0x0026 - 0x0025, -// nLwlNew nRwrNew nEcho0L nEcho0R nEcho1L nEcho1R + //nLwlNew nRwrNew nEcho0L nEcho0R nEcho1L nEcho1R 0x03E4, 0x031B, 0x03A4, 0x02AF, 0x0372, 0x0266, -// nLwlOld nRwrOld nLwrNew nRwlNew nEcho2L nEcho2R nEcho3L nEcho3R + //nLwlOld nRwrOld nLwrNew nRwlNew nEcho2L nEcho2R nEcho3L nEcho3R 0x031C, 0x025D, 0x025C, 0x018E, 0x022F, 0x0135, 0x01D2, 0x00B7, -// nLwrOld nRwlOld nRevaNewL nRevaNewR nRevbNewL nRevbNewR + //nLwrOld nRwlOld nRevaNewL nRevaNewR nRevbNewL nRevbNewR 0x018F, 0x00B5, 0x00B4, 0x0080, 0x004C, 0x0026 }; static ReverbParamsSW reverb_params_StudioMedium = { 0x4840/2, -// gLPF gEcho0 gEcho1 gEcho2 gEcho3 gWall + //gLPF gEcho0 gEcho1 gEcho2 gEcho3 gWall 0x70F0, 0x4FA8, -0x4320, 0x4510, -0x4110, -0x4B40, -// gReva gRevb gInputL gInputR + //gReva gRevb gInputL gInputR 0x5280, 0x4EC0, -0x8000, -0x8000, -// nRevaOldL nRevaOldR nRevbOldL nRevbOldR + //nRevaOldL nRevaOldR nRevbOldL nRevbOldR 0x0264 - 0x00B1, 0x01B2 - 0x00B1, 0x0100 - 0x007F, 0x0080 - 0x007F, -// nLwlNew nRwrNew nEcho0L nEcho0R nEcho1L nEcho1R + //nLwlNew nRwrNew nEcho0L nEcho0R nEcho1L nEcho1R 0x0904, 0x076B, 0x0824, 0x065F, 0x07A2, 0x0616, -// nLwlOld nRwrOld nLwrNew nRwlNew nEcho2L nEcho2R nEcho3L nEcho3R + //nLwlOld nRwrOld nLwrNew nRwlNew nEcho2L nEcho2R nEcho3L nEcho3R 0x076C, 0x05ED, 0x05EC, 0x042E, 0x050F, 0x0305, 0x0462, 0x02B7, -// nLwrOld nRwlOld nRevaNewL nRevaNewR nRevbNewL nRevbNewR + //nLwrOld nRwlOld nRevaNewL nRevaNewR nRevbNewL nRevbNewR 0x042F, 0x0265, 0x0264, 0x01B2, 0x0100, 0x0080 }; static ReverbParamsSW reverb_params_StudioLarge = { 0x6FE0/2, -// gLPF gEcho0 gEcho1 gEcho2 gEcho3 gWall + //gLPF gEcho0 gEcho1 gEcho2 gEcho3 gWall 0x6F60, 0x4FA8, -0x4320, 0x4510, -0x4110, -0x5980, -// gReva gRevb gInputL gInputR + //gReva gRevb gInputL gInputR 0x5680, 0x52C0, -0x8000, -0x8000, -// nRevaOldL nRevaOldR nRevbOldL nRevbOldR + //nRevaOldL nRevaOldR nRevbOldL nRevbOldR 0x031C - 0x00E3, 0x0238 - 0x00E3, 0x0154 - 0x00A9, 0x00AA - 0x00A9, -// nLwlNew nRwrNew nEcho0L nEcho0R nEcho1L nEcho1R + //nLwlNew nRwrNew nEcho0L nEcho0R nEcho1L nEcho1R 0x0DFB, 0x0B58, 0x0D09, 0x0A3C, 0x0BD9, 0x0973, -// nLwlOld nRwrOld nLwrNew nRwlNew nEcho2L nEcho2R nEcho3L nEcho3R + //nLwlOld nRwrOld nLwrNew nRwlNew nEcho2L nEcho2R nEcho3L nEcho3R 0x0B59, 0x08DA, 0x08D9, 0x05E9, 0x07EC, 0x04B0, 0x06EF, 0x03D2, -// nLwrOld nRwlOld nRevaNewL nRevaNewR nRevbNewL nRevbNewR + //nLwrOld nRwlOld nRevaNewL nRevaNewR nRevbNewL nRevbNewR 0x05EA, 0x031D, 0x031C, 0x0238, 0x0154, 0x00AA }; static ReverbParamsSW reverb_params_Hall = { 0xADE0/2, -// gLPF gEcho0 gEcho1 gEcho2 gEcho3 gWall + //gLPF gEcho0 gEcho1 gEcho2 gEcho3 gWall 0x6000, 0x5000, 0x4C00, -0x4800, -0x4400, -0x4000, -// gReva gRevb gInputL gInputR + //gReva gRevb gInputL gInputR 0x6000, 0x5C00, -0x8000, -0x8000, -// nRevaOldL nRevaOldR nRevbOldL nRevbOldR + //nRevaOldL nRevaOldR nRevbOldL nRevbOldR 0x05C0 - 0x01A5, 0x041A - 0x01A5, 0x0274 - 0x0139, 0x013A - 0x0139, -// nLwlNew nRwrNew nEcho0L nEcho0R nEcho1L nEcho1R + //nLwlNew nRwrNew nEcho0L nEcho0R nEcho1L nEcho1R 0x15BA, 0x11BB, 0x14C2, 0x10BD, 0x11BC, 0x0DC1, -// nLwlOld nRwrOld nLwrNew nRwlNew nEcho2L nEcho2R nEcho3L nEcho3R + //nLwlOld nRwrOld nLwrNew nRwlNew nEcho2L nEcho2R nEcho3L nEcho3R 0x11C0, 0x0DC3, 0x0DC0, 0x09C1, 0x0BC4, 0x07C1, 0x0A00, 0x06CD, -// nLwrOld nRwlOld nRevaNewL nRevaNewR nRevbNewL nRevbNewR + //nLwrOld nRwlOld nRevaNewL nRevaNewR nRevbNewL nRevbNewR 0x09C2, 0x05C1, 0x05C0, 0x041A, 0x0274, 0x013A }; static ReverbParamsSW reverb_params_SpaceEcho = { 0xF6C0/2, -// gLPF gEcho0 gEcho1 gEcho2 gEcho3 gWall + //gLPF gEcho0 gEcho1 gEcho2 gEcho3 gWall 0x7E00, 0x5000, -0x4C00, -0x5000, 0x4C00, -0x5000, -// gReva gRevb gInputL gInputR + //gReva gRevb gInputL gInputR 0x6000, 0x5400, -0x8000, -0x8000, -// nRevaOldL nRevaOldR nRevbOldL nRevbOldR + //nRevaOldL nRevaOldR nRevbOldL nRevbOldR 0x0AE0 - 0x033D, 0x07A2 - 0x033D, 0x0464 - 0x0231, 0x0232 - 0x0231, -// nLwlNew nRwrNew nEcho0L nEcho0R nEcho1L nEcho1R + //nLwlNew nRwrNew nEcho0L nEcho0R nEcho1L nEcho1R 0x1ED6, 0x1A31, 0x1D14, 0x183B, 0x1BC2, 0x16B2, -// nLwlOld nRwrOld nLwrNew nRwlNew nEcho2L nEcho2R nEcho3L nEcho3R + //nLwlOld nRwrOld nLwrNew nRwlNew nEcho2L nEcho2R nEcho3L nEcho3R 0x1A32, 0x15EF, 0x15EE, 0x1055, 0x1334, 0x0F2D, 0x11F6, 0x0C5D, -// nLwrOld nRwlOld nRevaNewL nRevaNewR nRevbNewL nRevbNewR + //nLwrOld nRwlOld nRevaNewL nRevaNewR nRevbNewL nRevbNewR 0x1056, 0x0AE1, 0x0AE0, 0x07A2, 0x0464, 0x0232 }; static ReverbParamsSW reverb_params_Echo = { 0x18040/2, -// gLPF gEcho0 gEcho1 gEcho2 gEcho3 gWall + //gLPF gEcho0 gEcho1 gEcho2 gEcho3 gWall 0x7FFF, 0x7FFF, 0x0000, 0x0000, 0x0000, -0x7F00, -// gReva gRevb gInputL gInputR + //gReva gRevb gInputL gInputR 0x0000, 0x0000, -0x8000, -0x8000, -// nRevaOldL nRevaOldR nRevbOldL nRevbOldR + //nRevaOldL nRevaOldR nRevbOldL nRevbOldR 0x1004 - 0x0001, 0x1002 - 0x0001, 0x0004 - 0x0001, 0x0002 - 0x0001, -// nLwlNew nRwrNew nEcho0L nEcho0R nEcho1L nEcho1R + //nLwlNew nRwrNew nEcho0L nEcho0R nEcho1L nEcho1R 0x1FFF, 0x0FFF, 0x1005, 0x0005, 0x0000, 0x0000, -// nLwlOld nRwrOld nLwrNew nRwlNew nEcho2L nEcho2R nEcho3L nEcho3R + //nLwlOld nRwrOld nLwrNew nRwlNew nEcho2L nEcho2R nEcho3L nEcho3R 0x1005, 0x0005, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, -// nLwrOld nRwlOld nRevaNewL nRevaNewR nRevbNewL nRevbNewR + //nLwrOld nRwlOld nRevaNewL nRevaNewR nRevbNewL nRevbNewR 0x0000, 0x0000, 0x1004, 0x1002, 0x0004, 0x0002 }; static ReverbParamsSW reverb_params_Delay = { 0x18040/2, -// gLPF gEcho0 gEcho1 gEcho2 gEcho3 gWall + //gLPF gEcho0 gEcho1 gEcho2 gEcho3 gWall 0x7FFF, 0x7FFF, 0x0000, 0x0000, 0x0000, 0x0000, -// gReva gRevb gInputL gInputR + //gReva gRevb gInputL gInputR 0x0000, 0x0000, -0x8000, -0x8000, -// nRevaOldL nRevaOldR nRevbOldL nRevbOldR + //nRevaOldL nRevaOldR nRevbOldL nRevbOldR 0x1004 - 0x0001, 0x1002 - 0x0001, 0x0004 - 0x0001, 0x0002 - 0x0001, -// nLwlNew nRwrNew nEcho0L nEcho0R nEcho1L nEcho1R + //nLwlNew nRwrNew nEcho0L nEcho0R nEcho1L nEcho1R 0x1FFF, 0x0FFF, 0x1005, 0x0005, 0x0000, 0x0000, -// nLwlOld nRwrOld nLwrNew nRwlNew nEcho2L nEcho2R nEcho3L nEcho3R + //nLwlOld nRwrOld nLwrNew nRwlNew nEcho2L nEcho2R nEcho3L nEcho3R 0x1005, 0x0005, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, -// nLwrOld nRwlOld nRevaNewL nRevaNewR nRevbNewL nRevbNewR + //nLwrOld nRwlOld nRevaNewL nRevaNewR nRevbNewL nRevbNewR 0x0000, 0x0000, 0x1004, 0x1002, 0x0004, 0x0002 }; static ReverbParamsSW reverb_params_HalfEcho = { 0x3C00/2, -// gLPF gEcho0 gEcho1 gEcho2 gEcho3 gWall + //gLPF gEcho0 gEcho1 gEcho2 gEcho3 gWall 0x70F0, 0x4FA8, -0x4320, 0x4510, -0x4110, -0x7B00, -// gReva gRevb gInputL gInputR + //gReva gRevb gInputL gInputR 0x5F80, 0x54C0, -0x8000, -0x8000, -// nRevaOldL nRevaOldR nRevbOldL nRevbOldR + //nRevaOldL nRevaOldR nRevbOldL nRevbOldR 0x0058 - 0x0017, 0x0040 - 0x0017, 0x0028 - 0x0013, 0x0014 - 0x0013, -// nLwlNew nRwrNew nEcho0L nEcho0R nEcho1L nEcho1R + //nLwlNew nRwrNew nEcho0L nEcho0R nEcho1L nEcho1R 0x0371, 0x02AF, 0x02E5, 0x01DF, 0x02B0, 0x01D7, -// nLwlOld nRwrOld nLwrNew nRwlNew nEcho2L nEcho2R nEcho3L nEcho3R + //nLwlOld nRwrOld nLwrNew nRwlNew nEcho2L nEcho2R nEcho3L nEcho3R 0x0358, 0x026A, 0x01D6, 0x011E, 0x012D, 0x00B1, 0x011F, 0x0059, -// nLwrOld nRwlOld nRevaNewL nRevaNewR nRevbNewL nRevbNewR + //nLwrOld nRwlOld nRevaNewL nRevaNewR nRevbNewL nRevbNewR 0x01A0, 0x00E3, 0x0058, 0x0040, 0x0028, 0x0014 }; @@ -265,7 +265,7 @@ bool ReverbSW::process(int *p_input,int *p_output,int p_frames,int p_stereo_stri // p_input must point to a non-looping buffer. // BOTH p_input and p_output must be touched (use ClearModuleBuffer). - // �������LOCAL MACROS ������۲ + // LOCAL MACROS #undef LM_SETSRCOFFSET #define LM_SETSRCOFFSET(x) \ @@ -296,14 +296,14 @@ MULSHIFT_S32 ( x, current_params->y, 15 ) #undef LM_REVERB #define LM_REVERB(x) reverb_buffer[ (x) + cSample ] - // �������LOCAL VARIABLES ������۲ + // LOCAL VARIABLES unsigned int Offset; int lwl, lwr, rwl, rwr; -// unsigned char HZShift; + //unsigned char HZShift; - // �������CODE ������۲ + // CODE lwl = state.lwl; diff --git a/servers/audio/reverb_sw.h b/servers/audio/reverb_sw.h index b028a245c8..d9f16a5fbb 100644 --- a/servers/audio/reverb_sw.h +++ b/servers/audio/reverb_sw.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/servers/audio/sample_manager_sw.cpp b/servers/audio/sample_manager_sw.cpp deleted file mode 100644 index 60f4d16659..0000000000 --- a/servers/audio/sample_manager_sw.cpp +++ /dev/null @@ -1,320 +0,0 @@ -/*************************************************************************/ -/* sample_manager_sw.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "sample_manager_sw.h" - -#include "print_string.h" - -SampleManagerSW::~SampleManagerSW() -{ -} - - - -RID SampleManagerMallocSW::sample_create(AS::SampleFormat p_format, bool p_stereo, int p_length) { - - Sample *s = memnew( Sample ); - int datalen = p_length; - if (p_format==AS::SAMPLE_FORMAT_PCM16) - datalen*=2; - else if (p_format==AS::SAMPLE_FORMAT_IMA_ADPCM) { - if (datalen&1) { - datalen++; - } - datalen/=2; - datalen+=4; - } - - if (p_stereo) - datalen*=2; - -#define SAMPLE_EXTRA 16 - - s->data = memalloc(datalen+SAMPLE_EXTRA); //help the interpolator by allocating a little more.. - for(int i=0;i<SAMPLE_EXTRA;i++) { - - uint8_t *data = (uint8_t*)s->data; - data[datalen+i]=0; - } - if (!s->data) { - - memdelete(s); - ERR_EXPLAIN("Cannot allocate sample of requested size."); - ERR_FAIL_V(RID()); - } - - s->format=p_format; - s->length=p_length; - s->length_bytes=datalen; - s->stereo=p_stereo; - s->loop_begin=0; - s->loop_end=0; - s->loop_format=AS::SAMPLE_LOOP_NONE; - s->mix_rate=44100; - - AudioServer::get_singleton()->lock(); - RID rid = sample_owner.make_rid(s); - AudioServer::get_singleton()->unlock(); - - return rid; -} - -void SampleManagerMallocSW::sample_set_description(RID p_sample, const String& p_description) { - - Sample *s = sample_owner.get(p_sample); - ERR_FAIL_COND(!s); - - s->description=p_description; -} - -String SampleManagerMallocSW::sample_get_description(RID p_sample) const { - - const Sample *s = sample_owner.get(p_sample); - ERR_FAIL_COND_V(!s,String()); - - return s->description; -} - - -AS::SampleFormat SampleManagerMallocSW::sample_get_format(RID p_sample) const { - - const Sample *s = sample_owner.get(p_sample); - ERR_FAIL_COND_V(!s,AS::SAMPLE_FORMAT_PCM8); - - return s->format; -} - -bool SampleManagerMallocSW::sample_is_stereo(RID p_sample) const { - - const Sample *s = sample_owner.get(p_sample); - ERR_FAIL_COND_V(!s,false); - - return s->stereo; - -} -int SampleManagerMallocSW::sample_get_length(RID p_sample) const { - - const Sample *s = sample_owner.get(p_sample); - ERR_FAIL_COND_V(!s,-1); - - return s->length; -} - -void SampleManagerMallocSW::sample_set_data(RID p_sample, const DVector<uint8_t>& p_buffer) { - - Sample *s = sample_owner.get(p_sample); - ERR_FAIL_COND(!s); - - int buff_size=p_buffer.size(); - ERR_FAIL_COND(buff_size==0); - - - ERR_EXPLAIN("Sample buffer size does not match sample size."); - //print_line("len bytes: "+itos(s->length_bytes)+" bufsize: "+itos(buff_size)); - ERR_FAIL_COND(s->length_bytes!=buff_size); - DVector<uint8_t>::Read buffer_r=p_buffer.read(); - const uint8_t *src = buffer_r.ptr(); - uint8_t *dst = (uint8_t*)s->data; - //print_line("set data: "+itos(s->length_bytes)); - - for(int i=0;i<s->length_bytes;i++) { - - dst[i]=src[i]; - } - - switch(s->format) { - - case AS::SAMPLE_FORMAT_PCM8: { - - if (s->stereo) { - dst[s->length]=dst[s->length-2]; - dst[s->length+1]=dst[s->length-1]; - } else { - - dst[s->length]=dst[s->length-1]; - } - - } break; - case AS::SAMPLE_FORMAT_PCM16: { - - if (s->stereo) { - dst[s->length]=dst[s->length-4]; - dst[s->length+1]=dst[s->length-3]; - dst[s->length+2]=dst[s->length-2]; - dst[s->length+3]=dst[s->length-1]; - } else { - - dst[s->length]=dst[s->length-2]; - dst[s->length+1]=dst[s->length-1]; - } - - } break; - - } - - - -} - -const DVector<uint8_t> SampleManagerMallocSW::sample_get_data(RID p_sample) const { - - Sample *s = sample_owner.get(p_sample); - ERR_FAIL_COND_V(!s,DVector<uint8_t>()); - - DVector<uint8_t> ret_buffer; - ret_buffer.resize(s->length_bytes); - DVector<uint8_t>::Write buffer_w=ret_buffer.write(); - uint8_t *dst = buffer_w.ptr(); - const uint8_t *src = (const uint8_t*)s->data; - - for(int i=0;i<s->length_bytes;i++) { - - dst[i]=src[i]; - } - - buffer_w = DVector<uint8_t>::Write(); //unlock - - return ret_buffer; -} - -void *SampleManagerMallocSW::sample_get_data_ptr(RID p_sample) const { - - const Sample *s = sample_owner.get(p_sample); - ERR_FAIL_COND_V(!s,NULL); - - return s->data; - -} - -void SampleManagerMallocSW::sample_set_mix_rate(RID p_sample,int p_rate) { - - ERR_FAIL_COND(p_rate<1); - - Sample *s = sample_owner.get(p_sample); - ERR_FAIL_COND(!s); - - s->mix_rate=p_rate; - - -} -int SampleManagerMallocSW::sample_get_mix_rate(RID p_sample) const { - - const Sample *s = sample_owner.get(p_sample); - ERR_FAIL_COND_V(!s,-1); - - return s->mix_rate; - -} -void SampleManagerMallocSW::sample_set_loop_format(RID p_sample,AS::SampleLoopFormat p_format) { - - Sample *s = sample_owner.get(p_sample); - ERR_FAIL_COND(!s); - - s->loop_format=p_format; - -} -AS::SampleLoopFormat SampleManagerMallocSW::sample_get_loop_format(RID p_sample) const { - - const Sample *s = sample_owner.get(p_sample); - ERR_FAIL_COND_V(!s,AS::SAMPLE_LOOP_NONE); - - return s->loop_format; -} - -void SampleManagerMallocSW::sample_set_loop_begin(RID p_sample,int p_pos) { - - Sample *s = sample_owner.get(p_sample); - ERR_FAIL_COND(!s); - ERR_FAIL_INDEX(p_pos,s->length); - - s->loop_begin=p_pos; -} -int SampleManagerMallocSW::sample_get_loop_begin(RID p_sample) const { - - const Sample *s = sample_owner.get(p_sample); - ERR_FAIL_COND_V(!s,-1); - - return s->loop_begin; -} - -void SampleManagerMallocSW::sample_set_loop_end(RID p_sample,int p_pos) { - - Sample *s = sample_owner.get(p_sample); - ERR_FAIL_COND(!s); - if (p_pos>s->length) - p_pos=s->length; - s->loop_end=p_pos; - -} -int SampleManagerMallocSW::sample_get_loop_end(RID p_sample) const { - - const Sample *s = sample_owner.get(p_sample); - ERR_FAIL_COND_V(!s,-1); - - return s->loop_end; -} - -bool SampleManagerMallocSW::is_sample(RID p_sample) const { - - return sample_owner.owns(p_sample); - -} -void SampleManagerMallocSW::free(RID p_sample) { - - Sample *s = sample_owner.get(p_sample); - ERR_FAIL_COND(!s); - AudioServer::get_singleton()->lock(); - sample_owner.free(p_sample); - AudioServer::get_singleton()->unlock(); - - memfree(s->data); - memdelete(s); - -} - -SampleManagerMallocSW::SampleManagerMallocSW() { - - -} - -SampleManagerMallocSW::~SampleManagerMallocSW() { - - // check for sample leakage - List<RID> owned_list; - sample_owner.get_owned_list(&owned_list); - - while(owned_list.size()) { - - Sample *s = sample_owner.get(owned_list.front()->get()); - String err="Leaked sample of size: "+itos(s->length_bytes)+" description: "+s->description; - ERR_PRINT(err.utf8().get_data()); - free(owned_list.front()->get()); - owned_list.pop_front(); - } - -} diff --git a/servers/audio/sample_manager_sw.h b/servers/audio/sample_manager_sw.h deleted file mode 100644 index bd7a11a3d2..0000000000 --- a/servers/audio/sample_manager_sw.h +++ /dev/null @@ -1,129 +0,0 @@ -/*************************************************************************/ -/* sample_manager_sw.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#ifndef SAMPLE_MANAGER_SW_H -#define SAMPLE_MANAGER_SW_H - -#include "servers/audio_server.h" - -class SampleManagerSW { -public: - - /* SAMPLE API */ - - virtual RID sample_create(AS::SampleFormat p_format, bool p_stereo, int p_length)=0; - - virtual void sample_set_description(RID p_sample, const String& p_description)=0; - virtual String sample_get_description(RID p_sample) const=0; - - virtual AS::SampleFormat sample_get_format(RID p_sample) const=0; - virtual bool sample_is_stereo(RID p_sample) const=0; - virtual int sample_get_length(RID p_sample) const=0; - - virtual void sample_set_data(RID p_sample, const DVector<uint8_t>& p_buffer)=0; - virtual const DVector<uint8_t> sample_get_data(RID p_sample) const=0; - - virtual void *sample_get_data_ptr(RID p_sample) const=0; - - virtual void sample_set_mix_rate(RID p_sample,int p_rate)=0; - virtual int sample_get_mix_rate(RID p_sample) const=0; - - virtual void sample_set_loop_format(RID p_sample,AS::SampleLoopFormat p_format)=0; - virtual AS::SampleLoopFormat sample_get_loop_format(RID p_sample) const=0; - - virtual void sample_set_loop_begin(RID p_sample,int p_pos)=0; - virtual int sample_get_loop_begin(RID p_sample) const=0; - - virtual void sample_set_loop_end(RID p_sample,int p_pos)=0; - virtual int sample_get_loop_end(RID p_sample) const=0; - - virtual bool is_sample(RID) const=0; - virtual void free(RID p_sample)=0; - - - - virtual ~SampleManagerSW(); -}; - - -class SampleManagerMallocSW : public SampleManagerSW { - - - struct Sample { - - void *data; - int length; - int length_bytes; - AS::SampleFormat format; - bool stereo; - AS::SampleLoopFormat loop_format; - int loop_begin; - int loop_end; - int mix_rate; - String description; - }; - - mutable RID_Owner<Sample> sample_owner; -public: - - /* SAMPLE API */ - - virtual RID sample_create(AS::SampleFormat p_format, bool p_stereo, int p_length); - - virtual void sample_set_description(RID p_sample, const String& p_description); - virtual String sample_get_description(RID p_sample) const; - - virtual AS::SampleFormat sample_get_format(RID p_sample) const; - virtual bool sample_is_stereo(RID p_sample) const; - virtual int sample_get_length(RID p_sample) const; - - virtual void sample_set_data(RID p_sample, const DVector<uint8_t>& p_buffer); - virtual const DVector<uint8_t> sample_get_data(RID p_sample) const; - - virtual void *sample_get_data_ptr(RID p_sample) const; - - virtual void sample_set_mix_rate(RID p_sample,int p_rate); - virtual int sample_get_mix_rate(RID p_sample) const; - - virtual void sample_set_loop_format(RID p_sample,AS::SampleLoopFormat p_format); - virtual AS::SampleLoopFormat sample_get_loop_format(RID p_sample) const; - - virtual void sample_set_loop_begin(RID p_sample,int p_pos); - virtual int sample_get_loop_begin(RID p_sample) const; - - virtual void sample_set_loop_end(RID p_sample,int p_pos); - virtual int sample_get_loop_end(RID p_sample) const; - - virtual bool is_sample(RID) const; - virtual void free(RID p_sample); - - SampleManagerMallocSW(); - virtual ~SampleManagerMallocSW(); -}; - -#endif // SAMPLE_MANAGER_SW_H diff --git a/servers/audio/voice_rb_sw.h b/servers/audio/voice_rb_sw.h index f785646577..cbf1392482 100644 --- a/servers/audio/voice_rb_sw.h +++ b/servers/audio/voice_rb_sw.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp index 1f0a2e403a..192d958a64 100644 --- a/servers/audio_server.cpp +++ b/servers/audio_server.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -27,178 +27,1195 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "audio_server.h" -#include "globals.h" +#include "global_config.h" +#include "os/os.h" +#include "servers/audio/effects/audio_effect_compressor.h" +#include "io/resource_loader.h" +#include "os/file_access.h" +#ifdef TOOLS_ENABLED -void AudioMixer::audio_mixer_chunk_call(int p_frames) { +#define MARK_EDITED set_edited(true); - AudioServer::get_singleton()->audio_mixer_chunk_callback(p_frames); +#else + +#define MARK_EDITED + +#endif + +AudioDriver *AudioDriver::singleton=NULL; +AudioDriver *AudioDriver::get_singleton() { + + return singleton; } -AudioMixer *AudioServer::EventStream::get_mixer() const { +void AudioDriver::set_singleton() { - return AudioServer::get_singleton()->get_mixer(); + singleton=this; } -AudioServer *AudioServer::singleton=NULL; +void AudioDriver::audio_server_process(int p_frames,int32_t *p_buffer,bool p_update_mix_time) { -AudioServer *AudioServer::get_singleton() { - return singleton; + if (p_update_mix_time) + update_mix_time(p_frames); + + if (AudioServer::get_singleton()) + AudioServer::get_singleton()->_driver_process(p_frames,p_buffer); +} + + + +void AudioDriver::update_mix_time(int p_frames) { + + _mix_amount+=p_frames; + _last_mix_time=OS::get_singleton()->get_ticks_usec(); +} + +double AudioDriver::get_mix_time() const { + + double total = (OS::get_singleton()->get_ticks_usec() - _last_mix_time) / 1000000.0; + total+=_mix_amount/(double)get_mix_rate(); + return total; + +} + + +AudioDriver::AudioDriver() { + + _last_mix_time=0; + _mix_amount=0; +} + + +AudioDriver *AudioDriverManager::drivers[MAX_DRIVERS]; +int AudioDriverManager::driver_count=0; + + +void AudioDriverManager::add_driver(AudioDriver *p_driver) { + + ERR_FAIL_COND(driver_count>=MAX_DRIVERS); + drivers[driver_count++]=p_driver; } -void AudioServer::sample_set_signed_data(RID p_sample, const DVector<float>& p_buffer) { +int AudioDriverManager::get_driver_count() { - SampleFormat format = sample_get_format(p_sample); + return driver_count; +} +AudioDriver *AudioDriverManager::get_driver(int p_driver) { + + ERR_FAIL_INDEX_V(p_driver,driver_count,NULL); + return drivers[p_driver]; +} + + +////////////////////////////////////////////// +////////////////////////////////////////////// +////////////////////////////////////////////// +////////////////////////////////////////////// + +void AudioServer::_driver_process(int p_frames,int32_t* p_buffer) { + + int todo=p_frames; - ERR_EXPLAIN("IMA ADPCM is not supported."); - ERR_FAIL_COND(format==SAMPLE_FORMAT_IMA_ADPCM); + while(todo) { - int len = p_buffer.size(); - ERR_FAIL_COND( len == 0 ); + if (to_mix==0) { + _mix_step(); + } - DVector<uint8_t> data; - DVector<uint8_t>::Write w; - DVector<float>::Read r = p_buffer.read(); + int to_copy = MIN(to_mix,todo); - switch(format) { - case SAMPLE_FORMAT_PCM8: { - data.resize(len); - w=data.write(); + Bus *master = buses[0]; - int8_t *samples8 = (int8_t*)w.ptr(); + int from = buffer_size-to_mix; + int from_buf=p_frames-todo; - for(int i=0;i<len;i++) { + //master master, send to output + int cs = master->channels.size(); + for(int k=0;k<cs;k++) { - float sample = Math::floor( r[i] * (1<<8) ); - if (sample<-128) - sample=-128; - else if (sample>127) - sample=127; - samples8[i]=sample; + if (master->channels[k].active) { + + AudioFrame *buf = master->channels[k].buffer.ptr(); + + for(int j=0;j<to_copy;j++) { + + float l = CLAMP(buf[from+j].l,-1.0,1.0); + int32_t vl = l*((1<<20)-1); + p_buffer[(from_buf+j)*(cs*2)+k*2+0]=vl<<11; + + float r = CLAMP(buf[from+j].r,-1.0,1.0); + int32_t vr = r*((1<<20)-1); + p_buffer[(from_buf+j)*(cs*2)+k*2+1]=vr<<11; + } + + } else { + for(int j=0;j<to_copy;j++) { + + p_buffer[(from_buf+j)*(cs*2)+k*2+0]=0; + p_buffer[(from_buf+j)*(cs*2)+k*2+1]=0; + } } - } break; - case SAMPLE_FORMAT_PCM16: { - data.resize(len*2); - w=data.write(); - int16_t *samples16 = (int16_t*)w.ptr(); + } + + todo-=to_copy; + to_mix-=to_copy; + + } + +} + +void AudioServer::_mix_step() { + + for(int i=0;i<buses.size();i++) { + Bus *bus = buses[i]; + bus->index_cache=i; //might be moved around by editor, so.. + for(int k=0;k<bus->channels.size();k++) { + + bus->channels[k].used=false; + } + } + + //make callbacks for mixing the audio + for (Set<CallbackItem>::Element *E=callbacks.front();E;E=E->next()) { + + E->get().callback(E->get().userdata); + } + + for(int i=buses.size()-1;i>=0;i--) { + //go bus by bus + Bus *bus = buses[i]; + + + for(int k=0;k<bus->channels.size();k++) { + + if (bus->channels[k].active && !bus->channels[k].used) { + //buffer was not used, but it's still active, so it must be cleaned + AudioFrame *buf = bus->channels[k].buffer.ptr(); + + for(uint32_t j=0;j<buffer_size;j++) { + + buf[j]=AudioFrame(0,0); + } + } + + } + + + //process effects + for(int j=0;j<bus->effects.size();j++) { + + if (!bus->effects[j].enabled) + continue; + + for(int k=0;k<bus->channels.size();k++) { + + if (!bus->channels[k].active) + continue; + bus->channels[k].effect_instances[j]->process(bus->channels[k].buffer.ptr(),temp_buffer[k].ptr(),buffer_size); + } + + //swap buffers, so internal buffer always has the right data + for(int k=0;k<bus->channels.size();k++) { + + if (!buses[i]->channels[k].active) + continue; + SWAP(bus->channels[k].buffer,temp_buffer[k]); + } + } + + //process send + + Bus *send=NULL; + + if (i>0) { + //everything has a send save for master bus + if (!bus_map.has(bus->send)) { + send=buses[0]; + } else { + send=bus_map[bus->send]; + if (send->index_cache>=bus->index_cache) { //invalid, send to master + send=buses[0]; + } + } + } + + + for(int k=0;k<bus->channels.size();k++) { + + if (!bus->channels[k].active) + continue; + + AudioFrame *buf = bus->channels[k].buffer.ptr(); + + + AudioFrame peak = AudioFrame(0,0); + for(uint32_t j=0;j<buffer_size;j++) { + float l = ABS(buf[j].l); + if (l>peak.l) { + peak.l=l; + } + float r = ABS(buf[j].r); + if (r>peak.r) { + peak.r=r; + } + } + + bus->channels[k].peak_volume=AudioFrame(Math::linear2db(peak.l+0.0000000001),Math::linear2db(peak.r+0.0000000001)); + + + if (!bus->channels[k].used) { + //see if any audio is contained, because channel was not used + + + if (MAX(peak.r,peak.l) > Math::db2linear(channel_disable_treshold_db)) { + bus->channels[k].last_mix_with_audio=mix_frames; + } else if (mix_frames-bus->channels[k].last_mix_with_audio > channel_disable_frames ) { + bus->channels[k].active=false; + continue; //went inactive, dont mix. + } + } + + if (send) { + //if not master bus, send + AudioFrame *target_buf = thread_get_channel_mix_buffer(send->index_cache,k); + + for(uint32_t j=0;j<buffer_size;j++) { + target_buf[j]+=buf[j]; + } + } + + } + + } + + + mix_frames+=buffer_size; + to_mix=buffer_size; + +} + +AudioFrame *AudioServer::thread_get_channel_mix_buffer(int p_bus,int p_buffer) { + + ERR_FAIL_INDEX_V(p_bus,buses.size(),NULL); + ERR_FAIL_INDEX_V(p_buffer,buses[p_bus]->channels.size(),NULL); + + AudioFrame *data = buses[p_bus]->channels[p_buffer].buffer.ptr(); + + + if (!buses[p_bus]->channels[p_buffer].used) { + buses[p_bus]->channels[p_buffer].used=true; + buses[p_bus]->channels[p_buffer].active=true; + buses[p_bus]->channels[p_buffer].last_mix_with_audio=mix_frames; + for(uint32_t i=0;i<buffer_size;i++) { + data[i]=AudioFrame(0,0); + } + } + + return data; +} + +int AudioServer::thread_get_mix_buffer_size() const { + + return buffer_size; +} + +int AudioServer::thread_find_bus_index(const StringName& p_name) { + + if (bus_map.has(p_name)) { + return bus_map[p_name]->index_cache; + } else { + return 0; + } + +} + +void AudioServer::set_bus_count(int p_count) { + + ERR_FAIL_COND(p_count<1); + ERR_FAIL_INDEX(p_count,256); + + MARK_EDITED + + lock(); + int cb = buses.size(); + + if (p_count<buses.size()) { + for(int i=p_count;i<buses.size();i++) { + bus_map.erase(buses[i]->name); + memdelete(buses[i]); + } + } + + buses.resize(p_count); + + for(int i=cb;i<buses.size();i++) { + + String attempt="New Bus"; + int attempts=1; + while(true) { + + bool name_free=true; + for(int j=0;j<i;j++) { + + if (buses[j]->name==attempt) { + name_free=false; + break; + } + } + + if (!name_free) { + attempts++; + attempt="New Bus " +itos(attempts); + } else { + break; + } + + } + + + buses[i]=memnew(Bus); + buses[i]->channels.resize(_get_channel_count()); + for(int j=0;j<_get_channel_count();j++) { + buses[i]->channels[j].buffer.resize(buffer_size); + } + buses[i]->name=attempt; + buses[i]->solo=false; + buses[i]->mute=false; + buses[i]->bypass=false; + buses[i]->volume_db=0; + if (i>0) { + buses[i]->send="Master"; + } + + bus_map[attempt]=buses[i]; + + } + + unlock(); + + emit_signal("bus_layout_changed"); +} + + +void AudioServer::remove_bus(int p_index) { - for(int i=0;i<len;i++) { + ERR_FAIL_INDEX(p_index,buses.size()); + ERR_FAIL_COND(p_index==0); - float sample = Math::floor( r[i] * (1<<16) ); - if (sample<-32768) - sample=-32768; - else if (sample>32767) - sample=32767; - samples16[i]=sample; + MARK_EDITED + + lock(); + bus_map.erase(buses[p_index]->name); + memdelete(buses[p_index]); + buses.remove(p_index); + unlock(); +} + +void AudioServer::add_bus(int p_at_pos) { + + MARK_EDITED + + if (p_at_pos>=buses.size()) { + p_at_pos=-1; + } else if (p_at_pos==0) { + if (buses.size()>1) + p_at_pos=1; + else + p_at_pos=-1; + } + + String attempt="New Bus"; + int attempts=1; + while(true) { + + bool name_free=true; + for(int j=0;j<buses.size();j++) { + + if (buses[j]->name==attempt) { + name_free=false; + break; } + } + + if (!name_free) { + attempts++; + attempt="New Bus " +itos(attempts); + } else { + break; + } + + } + + Bus* bus =memnew(Bus); + bus->channels.resize(_get_channel_count()); + for(int j=0;j<_get_channel_count();j++) { + bus->channels[j].buffer.resize(buffer_size); + } + bus->name=attempt; + bus->solo=false; + bus->mute=false; + bus->bypass=false; + bus->volume_db=0; + + bus_map[attempt]=bus; + + if (p_at_pos==-1) + buses.push_back(bus); + else + buses.insert(p_at_pos,bus); + +} + +void AudioServer::move_bus(int p_bus,int p_to_pos) { + + ERR_FAIL_COND(p_bus<1 || p_bus>=buses.size()); + ERR_FAIL_COND(p_to_pos!=-1 && (p_to_pos<1 || p_to_pos>buses.size())); + + MARK_EDITED + + if (p_bus==p_to_pos) + return; + + Bus *bus = buses[p_bus]; + buses.remove(p_bus); + + if (p_to_pos==-1) { + buses.push_back(bus); + } else if (p_to_pos<p_bus) { + buses.insert(p_to_pos,bus); + } else { + buses.insert(p_to_pos-1,bus); + } +} + +int AudioServer::get_bus_count() const { + + return buses.size(); +} + + +void AudioServer::set_bus_name(int p_bus,const String& p_name) { + + ERR_FAIL_INDEX(p_bus,buses.size()); + if (p_bus==0 && p_name!="Master") + return; //bus 0 is always master + + MARK_EDITED + + lock(); + + if (buses[p_bus]->name==p_name) { + unlock(); + return; + } + + String attempt=p_name; + int attempts=1; + + while(true) { + + bool name_free=true; + for(int i=0;i<buses.size();i++) { + + if (buses[i]->name==attempt) { + name_free=false; + break; + } + } + + if (name_free) { + break; + } + + attempts++; + attempt=p_name+" "+itos(attempts); + } + bus_map.erase(buses[p_bus]->name); + buses[p_bus]->name=attempt; + bus_map[attempt]=buses[p_bus]; + unlock(); + + emit_signal("bus_layout_changed"); + +} +String AudioServer::get_bus_name(int p_bus) const { + + ERR_FAIL_INDEX_V(p_bus,buses.size(),String()); + return buses[p_bus]->name; +} + +void AudioServer::set_bus_volume_db(int p_bus,float p_volume_db) { + + ERR_FAIL_INDEX(p_bus,buses.size()); + + MARK_EDITED + + buses[p_bus]->volume_db=p_volume_db; + +} +float AudioServer::get_bus_volume_db(int p_bus) const { + + ERR_FAIL_INDEX_V(p_bus,buses.size(),0); + return buses[p_bus]->volume_db; + +} + +void AudioServer::set_bus_send(int p_bus,const StringName& p_send) { + + ERR_FAIL_INDEX(p_bus,buses.size()); + + MARK_EDITED + + buses[p_bus]->send=p_send; + +} + +StringName AudioServer::get_bus_send(int p_bus) const { + + ERR_FAIL_INDEX_V(p_bus,buses.size(),StringName()); + return buses[p_bus]->send; + +} + + +void AudioServer::set_bus_solo(int p_bus,bool p_enable) { + + ERR_FAIL_INDEX(p_bus,buses.size()); + + MARK_EDITED + + buses[p_bus]->solo=p_enable; + +} + +bool AudioServer::is_bus_solo(int p_bus) const{ + + ERR_FAIL_INDEX_V(p_bus,buses.size(),false); + + return buses[p_bus]->solo; + +} + +void AudioServer::set_bus_mute(int p_bus,bool p_enable){ + + ERR_FAIL_INDEX(p_bus,buses.size()); + + MARK_EDITED + + buses[p_bus]->mute=p_enable; +} +bool AudioServer::is_bus_mute(int p_bus) const{ + + ERR_FAIL_INDEX_V(p_bus,buses.size(),false); + + return buses[p_bus]->mute; + +} + +void AudioServer::set_bus_bypass_effects(int p_bus,bool p_enable){ + + ERR_FAIL_INDEX(p_bus,buses.size()); + + MARK_EDITED + + buses[p_bus]->bypass=p_enable; +} +bool AudioServer::is_bus_bypassing_effects(int p_bus) const{ + + ERR_FAIL_INDEX_V(p_bus,buses.size(),false); + + return buses[p_bus]->bypass; + +} + + +void AudioServer::_update_bus_effects(int p_bus) { + + for(int i=0;i<buses[p_bus]->channels.size();i++) { + buses[p_bus]->channels[i].effect_instances.resize(buses[p_bus]->effects.size()); + for(int j=0;j<buses[p_bus]->effects.size();j++) { + Ref<AudioEffectInstance> fx = buses[p_bus]->effects[j].effect->instance(); + if (fx->cast_to<AudioEffectCompressorInstance>()) { + fx->cast_to<AudioEffectCompressorInstance>()->set_current_channel(i); + } + buses[p_bus]->channels[i].effect_instances[j]=fx; + + } + } +} + + +void AudioServer::add_bus_effect(int p_bus,const Ref<AudioEffect>& p_effect,int p_at_pos) { + + ERR_FAIL_COND(p_effect.is_null()); + ERR_FAIL_INDEX(p_bus,buses.size()); + + MARK_EDITED + + + lock(); + + Bus::Effect fx; + fx.effect=p_effect; + //fx.instance=p_effect->instance(); + fx.enabled=true; + + if (p_at_pos>=buses[p_bus]->effects.size() || p_at_pos<0) { + buses[p_bus]->effects.push_back(fx); + } else { + buses[p_bus]->effects.insert(p_at_pos,fx); + } + + _update_bus_effects(p_bus); + + unlock(); +} + + +void AudioServer::remove_bus_effect(int p_bus,int p_effect) { + + ERR_FAIL_INDEX(p_bus,buses.size()); + + MARK_EDITED + + + lock(); + + buses[p_bus]->effects.remove(p_effect); + _update_bus_effects(p_bus); + + unlock(); +} + +int AudioServer::get_bus_effect_count(int p_bus) { + + ERR_FAIL_INDEX_V(p_bus,buses.size(),0); + + return buses[p_bus]->effects.size(); + +} + +Ref<AudioEffect> AudioServer::get_bus_effect(int p_bus,int p_effect) { + + ERR_FAIL_INDEX_V(p_bus,buses.size(),Ref<AudioEffect>()); + ERR_FAIL_INDEX_V(p_effect,buses[p_bus]->effects.size(),Ref<AudioEffect>()); + + return buses[p_bus]->effects[p_effect].effect; + +} + +void AudioServer::swap_bus_effects(int p_bus,int p_effect,int p_by_effect) { + + ERR_FAIL_INDEX(p_bus,buses.size()); + ERR_FAIL_INDEX(p_effect,buses[p_bus]->effects.size()); + ERR_FAIL_INDEX(p_by_effect,buses[p_bus]->effects.size()); + + MARK_EDITED + + + lock(); + SWAP( buses[p_bus]->effects[p_effect], buses[p_bus]->effects[p_by_effect] ); + _update_bus_effects(p_bus); + unlock(); +} + +void AudioServer::set_bus_effect_enabled(int p_bus,int p_effect,bool p_enabled) { + + ERR_FAIL_INDEX(p_bus,buses.size()); + ERR_FAIL_INDEX(p_effect,buses[p_bus]->effects.size()); + + MARK_EDITED + + + buses[p_bus]->effects[p_effect].enabled=p_enabled; + +} +bool AudioServer::is_bus_effect_enabled(int p_bus,int p_effect) const { + + ERR_FAIL_INDEX_V(p_bus,buses.size(),false); + ERR_FAIL_INDEX_V(p_effect,buses[p_bus]->effects.size(),false); + return buses[p_bus]->effects[p_effect].enabled; + +} + + +float AudioServer::get_bus_peak_volume_left_db(int p_bus,int p_channel) const { + + ERR_FAIL_INDEX_V(p_bus,buses.size(),0); + ERR_FAIL_INDEX_V(p_channel,buses[p_bus]->channels.size(),0); + + return buses[p_bus]->channels[p_channel].peak_volume.l; + +} +float AudioServer::get_bus_peak_volume_right_db(int p_bus,int p_channel) const { + + ERR_FAIL_INDEX_V(p_bus,buses.size(),0); + ERR_FAIL_INDEX_V(p_channel,buses[p_bus]->channels.size(),0); + + return buses[p_bus]->channels[p_channel].peak_volume.r; + +} + +bool AudioServer::is_bus_channel_active(int p_bus,int p_channel) const { + + ERR_FAIL_INDEX_V(p_bus,buses.size(),false); + ERR_FAIL_INDEX_V(p_channel,buses[p_bus]->channels.size(),false); + + return buses[p_bus]->channels[p_channel].active; + +} + +void AudioServer::init() { + + channel_disable_treshold_db=GLOBAL_DEF("audio/channel_disable_treshold_db",-60.0); + channel_disable_frames=float(GLOBAL_DEF("audio/channel_disable_time",2.0))*get_mix_rate(); + buffer_size=1024; //harcoded for now + switch( get_speaker_mode() ) { + case SPEAKER_MODE_STEREO: { + temp_buffer.resize(1); + } break; + case SPEAKER_SURROUND_51: { + temp_buffer.resize(3); + } break; + case SPEAKER_SURROUND_71: { + temp_buffer.resize(4); } break; } - w = DVector<uint8_t>::Write(); + for(int i=0;i<temp_buffer.size();i++) { + temp_buffer[i].resize(buffer_size); + } + + mix_count=0; + set_bus_count(1);; + set_bus_name(0,"Master"); - sample_set_data(p_sample,data); + if (AudioDriver::get_singleton()) + AudioDriver::get_singleton()->start(); +#ifdef TOOLS_ENABLED + set_edited(false); //avoid editors from thinking this was edited +#endif } -void AudioServer::_bind_methods() { +void AudioServer::load_default_bus_layout() { - ObjectTypeDB::bind_method(_MD("sample_create","format","stereo","length"), &AudioServer::sample_create ); - ObjectTypeDB::bind_method(_MD("sample_set_description","sample","description"), &AudioServer::sample_set_description ); - ObjectTypeDB::bind_method(_MD("sample_get_description","sample"), &AudioServer::sample_get_description ); + if (FileAccess::exists("res://default_bus_layout.tres")) { + Ref<AudioBusLayout> default_layout = ResourceLoader::load("res://default_bus_layout.tres"); + if (default_layout.is_valid()) { + set_bus_layout(default_layout); + } + } - ObjectTypeDB::bind_method(_MD("sample_get_format","sample"), &AudioServer::sample_get_format ); - ObjectTypeDB::bind_method(_MD("sample_is_stereo","sample"), &AudioServer::sample_is_stereo ); - ObjectTypeDB::bind_method(_MD("sample_get_length","sample"), &AudioServer::sample_get_length ); +} - ObjectTypeDB::bind_method(_MD("sample_set_signed_data","sample","data"), &AudioServer::sample_set_signed_data ); - ObjectTypeDB::bind_method(_MD("sample_set_data","sample","data"), &AudioServer::sample_set_data ); - ObjectTypeDB::bind_method(_MD("sample_get_data","sample"), &AudioServer::sample_get_data ); +void AudioServer::finish() { - ObjectTypeDB::bind_method(_MD("sample_set_mix_rate","sample","mix_rate"), &AudioServer::sample_set_mix_rate ); - ObjectTypeDB::bind_method(_MD("sample_get_mix_rate","sample"), &AudioServer::sample_get_mix_rate ); + for(int i=0;i<buses.size();i++) { + memdelete(buses[i]); + } - ObjectTypeDB::bind_method(_MD("sample_set_loop_format","sample","loop_format"), &AudioServer::sample_set_loop_format ); - ObjectTypeDB::bind_method(_MD("sample_get_loop_format","sample"), &AudioServer::sample_get_loop_format ); + buses.clear(); +} +void AudioServer::update() { - ObjectTypeDB::bind_method(_MD("sample_set_loop_begin","sample","pos"), &AudioServer::sample_set_loop_begin ); - ObjectTypeDB::bind_method(_MD("sample_get_loop_begin","sample"), &AudioServer::sample_get_loop_begin ); +} - ObjectTypeDB::bind_method(_MD("sample_set_loop_end","sample","pos"), &AudioServer::sample_set_loop_end ); - ObjectTypeDB::bind_method(_MD("sample_get_loop_end","sample"), &AudioServer::sample_get_loop_end ); +/* MISC config */ +void AudioServer::lock() { + AudioDriver::get_singleton()->lock(); +} +void AudioServer::unlock() { - ObjectTypeDB::bind_method(_MD("voice_create"), &AudioServer::voice_create ); - ObjectTypeDB::bind_method(_MD("voice_play","voice","sample"), &AudioServer::voice_play ); - ObjectTypeDB::bind_method(_MD("voice_set_volume","voice","volume"), &AudioServer::voice_set_volume ); - ObjectTypeDB::bind_method(_MD("voice_set_pan","voice","pan","depth","height"), &AudioServer::voice_set_pan,DEFVAL(0),DEFVAL(0) ); - ObjectTypeDB::bind_method(_MD("voice_set_filter","voice","type","cutoff","resonance","gain"), &AudioServer::voice_set_filter,DEFVAL(0) ); - ObjectTypeDB::bind_method(_MD("voice_set_chorus","voice","chorus"), &AudioServer::voice_set_chorus ); - ObjectTypeDB::bind_method(_MD("voice_set_reverb","voice","room","reverb"), &AudioServer::voice_set_reverb ); - ObjectTypeDB::bind_method(_MD("voice_set_mix_rate","voice","rate"), &AudioServer::voice_set_mix_rate ); - ObjectTypeDB::bind_method(_MD("voice_set_positional","voice","enabled"), &AudioServer::voice_set_positional ); + AudioDriver::get_singleton()->unlock(); +} - ObjectTypeDB::bind_method(_MD("voice_get_volume","voice"), &AudioServer::voice_get_volume ); - ObjectTypeDB::bind_method(_MD("voice_get_pan","voice"), &AudioServer::voice_get_pan ); - ObjectTypeDB::bind_method(_MD("voice_get_pan_height","voice"), &AudioServer::voice_get_pan_height ); - ObjectTypeDB::bind_method(_MD("voice_get_pan_depth","voice"), &AudioServer::voice_get_pan_depth ); - ObjectTypeDB::bind_method(_MD("voice_get_filter_type","voice"), &AudioServer::voice_get_filter_type ); - ObjectTypeDB::bind_method(_MD("voice_get_filter_cutoff","voice"), &AudioServer::voice_get_filter_cutoff ); - ObjectTypeDB::bind_method(_MD("voice_get_filter_resonance","voice"), &AudioServer::voice_get_filter_resonance ); - ObjectTypeDB::bind_method(_MD("voice_get_chorus","voice"), &AudioServer::voice_get_chorus ); - ObjectTypeDB::bind_method(_MD("voice_get_reverb_type","voice"), &AudioServer::voice_get_reverb_type ); - ObjectTypeDB::bind_method(_MD("voice_get_reverb","voice"), &AudioServer::voice_get_reverb ); - ObjectTypeDB::bind_method(_MD("voice_get_mix_rate","voice"), &AudioServer::voice_get_mix_rate ); - ObjectTypeDB::bind_method(_MD("voice_is_positional","voice"), &AudioServer::voice_is_positional ); - ObjectTypeDB::bind_method(_MD("voice_stop","voice"), &AudioServer::voice_stop ); +AudioServer::SpeakerMode AudioServer::get_speaker_mode() const { - ObjectTypeDB::bind_method(_MD("free_rid","rid"), &AudioServer::free ); + return (AudioServer::SpeakerMode)AudioDriver::get_singleton()->get_speaker_mode(); +} +float AudioServer::get_mix_rate() const { + + return AudioDriver::get_singleton()->get_mix_rate(); +} - ObjectTypeDB::bind_method(_MD("set_stream_global_volume_scale","scale"), &AudioServer::set_stream_global_volume_scale ); - ObjectTypeDB::bind_method(_MD("get_stream_global_volume_scale"), &AudioServer::get_stream_global_volume_scale ); +float AudioServer::read_output_peak_db() const { - ObjectTypeDB::bind_method(_MD("set_fx_global_volume_scale","scale"), &AudioServer::set_fx_global_volume_scale ); - ObjectTypeDB::bind_method(_MD("get_fx_global_volume_scale"), &AudioServer::get_fx_global_volume_scale ); + return 0; +} - ObjectTypeDB::bind_method(_MD("set_event_voice_global_volume_scale","scale"), &AudioServer::set_event_voice_global_volume_scale ); - ObjectTypeDB::bind_method(_MD("get_event_voice_global_volume_scale"), &AudioServer::get_event_voice_global_volume_scale ); +AudioServer *AudioServer::get_singleton() { + + return singleton; +} + +double AudioServer::get_mix_time() const { + + return 0; +} +double AudioServer::get_output_delay() const { + + return 0; +} - BIND_CONSTANT( SAMPLE_FORMAT_PCM8 ); - BIND_CONSTANT( SAMPLE_FORMAT_PCM16 ); - BIND_CONSTANT( SAMPLE_FORMAT_IMA_ADPCM ); +AudioServer* AudioServer::singleton=NULL; - BIND_CONSTANT( SAMPLE_LOOP_NONE ); - BIND_CONSTANT( SAMPLE_LOOP_FORWARD ); - BIND_CONSTANT( SAMPLE_LOOP_PING_PONG ); - BIND_CONSTANT( FILTER_NONE ); - BIND_CONSTANT( FILTER_LOWPASS ); - BIND_CONSTANT( FILTER_BANDPASS ); - BIND_CONSTANT( FILTER_HIPASS ); - BIND_CONSTANT( FILTER_NOTCH ); - BIND_CONSTANT( FILTER_BANDLIMIT ); ///< cutoff is LP resonace is HP - BIND_CONSTANT( REVERB_SMALL ); - BIND_CONSTANT( REVERB_MEDIUM ); - BIND_CONSTANT( REVERB_LARGE ); - BIND_CONSTANT( REVERB_HALL ); - GLOBAL_DEF("audio/stream_buffering_ms",500); - GLOBAL_DEF("audio/video_delay_compensation_ms",300); +void* AudioServer::audio_data_alloc(uint32_t p_data_len,const uint8_t *p_from_data) { + void * ad = memalloc( p_data_len ); + ERR_FAIL_COND_V(!ad,NULL); + if (p_from_data) { + copymem(ad,p_from_data,p_data_len); + } + + audio_data_lock->lock(); + audio_data[ad]=p_data_len; + audio_data_total_mem+=p_data_len; + audio_data_max_mem=MAX(audio_data_total_mem,audio_data_max_mem); + audio_data_lock->unlock(); + + return ad; +} + +void AudioServer::audio_data_free(void* p_data) { + + audio_data_lock->lock(); + if (!audio_data.has(p_data)) { + audio_data_lock->unlock(); + ERR_FAIL(); + } + + audio_data_total_mem-=audio_data[p_data]; + audio_data.erase(p_data); + memfree(p_data); + audio_data_lock->unlock(); + + +} + +size_t AudioServer::audio_data_get_total_memory_usage() const{ + + return audio_data_total_mem; +} +size_t AudioServer::audio_data_get_max_memory_usage() const{ + + return audio_data_max_mem; + +} + +void AudioServer::add_callback(AudioCallback p_callback,void *p_userdata) { + lock(); + CallbackItem ci; + ci.callback=p_callback; + ci.userdata=p_userdata; + callbacks.insert(ci); + unlock(); +} + +void AudioServer::remove_callback(AudioCallback p_callback,void *p_userdata) { + + lock(); + CallbackItem ci; + ci.callback=p_callback; + ci.userdata=p_userdata; + callbacks.erase(ci); + unlock(); + +} + +void AudioServer::set_bus_layout(const Ref<AudioBusLayout> &p_state) { + + ERR_FAIL_COND(p_state.is_null() || p_state->buses.size()==0); + + lock(); + for(int i=0;i<buses.size();i++) { + memdelete(buses[i]); + } + buses.resize(p_state->buses.size()); + bus_map.clear(); + for(int i=0;i<p_state->buses.size();i++) { + Bus * bus = memnew(Bus); + if (i==0) { + bus->name="Master"; + } else { + bus->name=p_state->buses[i].name; + bus->send=p_state->buses[i].send; + } + + bus->solo=p_state->buses[i].solo; + bus->mute=p_state->buses[i].mute; + bus->bypass=p_state->buses[i].bypass; + bus->volume_db=p_state->buses[i].volume_db; + + for(int j=0;j<p_state->buses[i].effects.size();j++) { + + Ref<AudioEffect> fx = p_state->buses[i].effects[j].effect; + + if (fx.is_valid()) { + + Bus::Effect bfx; + bfx.effect=fx; + bfx.enabled=p_state->buses[i].effects[j].enabled; + bus->effects.push_back(bfx); + } + } + + bus_map[bus->name]=bus; + buses[i]=bus; + + buses[i]->channels.resize(_get_channel_count()); + for(int j=0;j<_get_channel_count();j++) { + buses[i]->channels[j].buffer.resize(buffer_size); + } + _update_bus_effects(i); + } +#ifdef TOOLS_ENABLED + set_edited(false); +#endif + unlock(); + +} + + +Ref<AudioBusLayout> AudioServer::generate_bus_layout() const { + + Ref<AudioBusLayout> state; + state.instance(); + + state->buses.resize( buses.size() ); + + for(int i=0;i<buses.size();i++) { + + state->buses[i].name=buses[i]->name; + state->buses[i].send=buses[i]->send; + state->buses[i].mute=buses[i]->mute; + state->buses[i].solo=buses[i]->solo; + state->buses[i].bypass=buses[i]->bypass; + state->buses[i].volume_db=buses[i]->volume_db; + for(int j=0;j<buses[i]->effects.size();j++) { + AudioBusLayout::Bus::Effect fx; + fx.effect=buses[i]->effects[j].effect; + fx.enabled=buses[i]->effects[j].enabled; + state->buses[i].effects.push_back(fx); + + } + } + + return state; +} + + +void AudioServer::_bind_methods() { + + + ClassDB::bind_method(D_METHOD("set_bus_count","amount"),&AudioServer::set_bus_count); + ClassDB::bind_method(D_METHOD("get_bus_count"),&AudioServer::get_bus_count); + + ClassDB::bind_method(D_METHOD("remove_bus","index"),&AudioServer::remove_bus); + ClassDB::bind_method(D_METHOD("add_bus","at_pos"),&AudioServer::add_bus,DEFVAL(-1)); + ClassDB::bind_method(D_METHOD("move_bus","index","to_index"),&AudioServer::move_bus); + + ClassDB::bind_method(D_METHOD("set_bus_name","bus_idx","name"),&AudioServer::set_bus_name); + ClassDB::bind_method(D_METHOD("get_bus_name","bus_idx"),&AudioServer::get_bus_name); + + ClassDB::bind_method(D_METHOD("set_bus_volume_db","bus_idx","volume_db"),&AudioServer::set_bus_volume_db); + ClassDB::bind_method(D_METHOD("get_bus_volume_db","bus_idx"),&AudioServer::get_bus_volume_db); + + ClassDB::bind_method(D_METHOD("set_bus_send","bus_idx","send"),&AudioServer::set_bus_send); + ClassDB::bind_method(D_METHOD("get_bus_send","bus_idx"),&AudioServer::get_bus_send); + + ClassDB::bind_method(D_METHOD("set_bus_solo","bus_idx","enable"),&AudioServer::set_bus_solo); + ClassDB::bind_method(D_METHOD("is_bus_solo","bus_idx"),&AudioServer::is_bus_solo); + + ClassDB::bind_method(D_METHOD("set_bus_mute","bus_idx","enable"),&AudioServer::set_bus_mute); + ClassDB::bind_method(D_METHOD("is_bus_mute","bus_idx"),&AudioServer::is_bus_mute); + + ClassDB::bind_method(D_METHOD("set_bus_bypass_effects","bus_idx","enable"),&AudioServer::set_bus_bypass_effects); + ClassDB::bind_method(D_METHOD("is_bus_bypassing_effects","bus_idx"),&AudioServer::is_bus_bypassing_effects); + + ClassDB::bind_method(D_METHOD("add_bus_effect","bus_idx","effect:AudioEffect"),&AudioServer::add_bus_effect,DEFVAL(-1)); + ClassDB::bind_method(D_METHOD("remove_bus_effect","bus_idx","effect_idx"),&AudioServer::remove_bus_effect); + + ClassDB::bind_method(D_METHOD("get_bus_effect_count","bus_idx"),&AudioServer::add_bus_effect); + ClassDB::bind_method(D_METHOD("get_bus_effect:AudioEffect","bus_idx","effect_idx"),&AudioServer::get_bus_effect); + 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); + ClassDB::bind_method(D_METHOD("is_bus_effect_enabled","bus_idx","effect_idx"),&AudioServer::is_bus_effect_enabled); + + ClassDB::bind_method(D_METHOD("get_bus_peak_volume_left_db","bus_idx","channel"),&AudioServer::get_bus_peak_volume_left_db); + ClassDB::bind_method(D_METHOD("get_bus_peak_volume_right_db","bus_idx","channel"),&AudioServer::get_bus_peak_volume_right_db); + + ClassDB::bind_method(D_METHOD("lock"),&AudioServer::lock); + ClassDB::bind_method(D_METHOD("unlock"),&AudioServer::unlock); + + ClassDB::bind_method(D_METHOD("get_speaker_mode"),&AudioServer::get_speaker_mode); + ClassDB::bind_method(D_METHOD("get_mix_rate"),&AudioServer::get_mix_rate); + + ClassDB::bind_method(D_METHOD("set_state","state:AudioServerState"),&AudioServer::set_bus_layout); + ClassDB::bind_method(D_METHOD("generate_state:AudioServerState"),&AudioServer::generate_bus_layout); + + ADD_SIGNAL(MethodInfo("bus_layout_changed") ); } AudioServer::AudioServer() { singleton=this; + audio_data_total_mem=0; + audio_data_max_mem=0; + audio_data_lock=Mutex::create(); + mix_frames=0; + to_mix=0; + } AudioServer::~AudioServer() { + memdelete(audio_data_lock); +} + +///////////////////////////////// + + + +bool AudioBusLayout::_set(const StringName& p_name, const Variant& p_value) { + + String s = p_name; + if (s.begins_with("bus/")) { + int index = s.get_slice("/",1).to_int(); + if (buses.size()<=index) { + buses.resize(index+1); + } + + Bus &bus = buses[index]; + + String what = s.get_slice("/",2); + + if (what=="name") { + bus.name=p_value; + } else if (what=="solo") { + bus.solo=p_value; + } else if (what=="mute") { + bus.mute=p_value; + } else if (what=="bypass_fx") { + bus.bypass=p_value; + } else if (what=="volume_db") { + bus.volume_db=p_value; + } else if (what=="send") { + bus.send=p_value; + } else if (what=="effect") { + int which = s.get_slice("/",3).to_int(); + if (bus.effects.size()<=which) { + bus.effects.resize(which+1); + } + + Bus::Effect &fx = bus.effects[which]; + + String fxwhat = s.get_slice("/",4); + if (fxwhat=="effect") { + fx.effect=p_value; + } else if (fxwhat=="enabled") { + fx.enabled=p_value; + } else { + return false; + } + + return true; + } else { + return false; + } + + return true; + } + + return false; + +} + +bool AudioBusLayout::_get(const StringName& p_name,Variant &r_ret) const{ + + String s = p_name; + if (s.begins_with("bus/")) { + + int index = s.get_slice("/",1).to_int(); + if (index<0 || index>=buses.size()) + return false; + + const Bus &bus = buses[index]; + + String what = s.get_slice("/",2); + + if (what=="name") { + r_ret=bus.name; + } else if (what=="solo") { + r_ret=bus.solo; + } else if (what=="mute") { + r_ret=bus.mute; + } else if (what=="bypass_fx") { + r_ret=bus.bypass; + } else if (what=="volume_db") { + r_ret=bus.volume_db; + } else if (what=="send") { + r_ret=bus.send; + } else if (what=="effect") { + int which = s.get_slice("/",3).to_int(); + if (which<0 || which>=bus.effects.size()) { + return false; + } + + const Bus::Effect &fx = bus.effects[which]; + + String fxwhat = s.get_slice("/",4); + if (fxwhat=="effect") { + r_ret=fx.effect; + } else if (fxwhat=="enabled") { + r_ret=fx.enabled; + } else { + return false; + } + + return true; + } else { + return false; + } + + return true; + } + + return false; + +} +void AudioBusLayout::_get_property_list( List<PropertyInfo> *p_list) const{ + + for(int i=0;i<buses.size();i++) { + p_list->push_back(PropertyInfo(Variant::STRING,"bus/"+itos(i)+"/name",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::BOOL,"bus/"+itos(i)+"/solo",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::BOOL,"bus/"+itos(i)+"/mute",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::BOOL,"bus/"+itos(i)+"/bypass_fx",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::REAL,"bus/"+itos(i)+"/volume_db",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::REAL,"bus/"+itos(i)+"/send",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR)); + + for(int j=0;j<buses[i].effects.size();j++) { + p_list->push_back(PropertyInfo(Variant::OBJECT,"bus/"+itos(i)+"/effect/"+itos(j)+"/effect",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::BOOL,"bus/"+itos(i)+"/effect/"+itos(j)+"/enabled",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR)); + } + } +} + + +AudioBusLayout::AudioBusLayout() { + buses.resize(1); + buses[0].name="Master"; } diff --git a/servers/audio_server.h b/servers/audio_server.h index 9e21e6b183..88849bb591 100644 --- a/servers/audio_server.h +++ b/servers/audio_server.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,261 +31,326 @@ #include "variant.h" #include "object.h" +#include "audio_frame.h" +#include "servers/audio/audio_effect.h" + + +class AudioDriver { + + + static AudioDriver *singleton; + uint64_t _last_mix_time; + uint64_t _mix_amount; + -class AudioMixer { protected: - void audio_mixer_chunk_call(int p_frames); + void audio_server_process(int p_frames,int32_t *p_buffer,bool p_update_mix_time=true); + void update_mix_time(int p_frames); + public: - enum { - INVALID_CHANNEL=0xFFFFFFFF + double get_mix_time() const; //useful for video -> audio sync + + enum SpeakerMode { + SPEAKER_MODE_STEREO, + SPEAKER_SURROUND_51, + SPEAKER_SURROUND_71, }; - typedef uint32_t ChannelID; + static AudioDriver *get_singleton(); + void set_singleton(); - /* CHANNEL API */ + virtual const char* get_name() const=0; - enum FilterType { - FILTER_NONE, - FILTER_LOWPASS, - FILTER_BANDPASS, - FILTER_HIPASS, - FILTER_NOTCH, - FILTER_PEAK, - FILTER_BANDLIMIT, ///< cutoff is LP resonace is HP - FILTER_LOW_SHELF, - FILTER_HIGH_SHELF + virtual Error init()=0; + virtual void start()=0; + virtual int get_mix_rate() const =0; + virtual SpeakerMode get_speaker_mode() const=0; + virtual void lock()=0; + virtual void unlock()=0; + virtual void finish()=0; - }; + virtual float get_latency() { return 0; } - enum ReverbRoomType { - REVERB_SMALL, - REVERB_MEDIUM, - REVERB_LARGE, - REVERB_HALL, - MAX_REVERBS - }; - virtual ChannelID channel_alloc(RID p_sample)=0; - virtual void channel_set_volume(ChannelID p_channel, float p_gain)=0; - virtual void channel_set_pan(ChannelID p_channel, float p_pan, float p_depth=0,float height=0)=0; //pan and depth go from -1 to 1 - virtual void channel_set_filter(ChannelID p_channel, FilterType p_type, float p_cutoff, float p_resonance, float p_gain=1.0)=0; - virtual void channel_set_chorus(ChannelID p_channel, float p_chorus )=0; - virtual void channel_set_reverb(ChannelID p_channel, ReverbRoomType p_room_type, float p_reverb)=0; - virtual void channel_set_mix_rate(ChannelID p_channel, int p_mix_rate)=0; - virtual void channel_set_positional(ChannelID p_channel, bool p_positional)=0; + AudioDriver(); + virtual ~AudioDriver() {} +}; - virtual float channel_get_volume(ChannelID p_channel) const=0; - virtual float channel_get_pan(ChannelID p_channel) const=0; //pan and depth go from -1 to 1 - virtual float channel_get_pan_depth(ChannelID p_channel) const=0; //pan and depth go from -1 to 1 - virtual float channel_get_pan_height(ChannelID p_channel) const=0; //pan and depth go from -1 to 1 - virtual FilterType channel_get_filter_type(ChannelID p_channel) const=0; - virtual float channel_get_filter_cutoff(ChannelID p_channel) const=0; - virtual float channel_get_filter_resonance(ChannelID p_channel) const=0; - virtual float channel_get_filter_gain(ChannelID p_channel) const=0; - virtual float channel_get_chorus(ChannelID p_channel) const=0; - virtual ReverbRoomType channel_get_reverb_type(ChannelID p_channel) const=0; - virtual float channel_get_reverb(ChannelID p_channel) const=0; - virtual int channel_get_mix_rate(ChannelID p_channel) const=0; - virtual bool channel_is_positional(ChannelID p_channel) const=0; - virtual bool channel_is_valid(ChannelID p_channel) const=0; +class AudioDriverManager { - virtual void channel_free(ChannelID p_channel)=0; + enum { - virtual void set_mixer_volume(float p_volume)=0; + MAX_DRIVERS=10 + }; + static AudioDriver *drivers[MAX_DRIVERS]; + static int driver_count; +public: - virtual ~AudioMixer() {} + static void add_driver(AudioDriver *p_driver); + static int get_driver_count(); + static AudioDriver *get_driver(int p_driver); }; +class AudioBusLayout; + class AudioServer : public Object { - OBJ_TYPE( AudioServer, Object ); + GDCLASS( AudioServer, Object ) +public: + //re-expose this her, as AudioDriver is not exposed to script + enum SpeakerMode { + SPEAKER_MODE_STEREO, + SPEAKER_SURROUND_51, + SPEAKER_SURROUND_71, + }; + + enum { + AUDIO_DATA_INVALID_ID=-1 + }; - static AudioServer *singleton; -protected: -friend class AudioStream; -friend class EventStream; -friend class AudioMixer; + typedef void (*AudioCallback)(void* p_userdata); - virtual AudioMixer *get_mixer()=0; - virtual void audio_mixer_chunk_callback(int p_frames)=0; +private: + uint32_t buffer_size; + uint64_t mix_count; + uint64_t mix_frames; - static void _bind_methods(); -public: + float channel_disable_treshold_db; + uint32_t channel_disable_frames; + int to_mix; - class EventStream { - protected: - AudioMixer *get_mixer() const; - public: - virtual void update(uint64_t p_usec)=0; + struct Bus { - virtual ~EventStream() {} - }; + StringName name; + bool solo; + bool mute; + bool bypass; - class AudioStream { - public: - virtual int get_channel_count() const=0; - virtual void set_mix_rate(int p_rate)=0; //notify the stream of the mix rate - virtual bool mix(int32_t *p_buffer,int p_frames)=0; - virtual void update()=0; - virtual bool can_update_mt() const { return true; } - virtual ~AudioStream() {} - }; + //Each channel is a stereo pair. + struct Channel { + bool used; + bool active; + AudioFrame peak_volume; + Vector<AudioFrame> buffer; + Vector<Ref<AudioEffectInstance> > effect_instances; + uint64_t last_mix_with_audio; + Channel() { last_mix_with_audio=0; used=false; active=false; peak_volume=AudioFrame(0,0); } + }; + + Vector<Channel> channels; - enum SampleFormat { + struct Effect { + Ref<AudioEffect> effect; + bool enabled; + }; - SAMPLE_FORMAT_PCM8, - SAMPLE_FORMAT_PCM16, - SAMPLE_FORMAT_IMA_ADPCM + Vector<Effect> effects; + float volume_db; + StringName send; + int index_cache; }; - enum SampleLoopFormat { - SAMPLE_LOOP_NONE, - SAMPLE_LOOP_FORWARD, - SAMPLE_LOOP_PING_PONG // not supported in every platform - }; + Vector< Vector<AudioFrame> >temp_buffer; //temp_buffer for each level + Vector<Bus*> buses; + Map<StringName,Bus*> bus_map; - /* SAMPLE API */ + _FORCE_INLINE_ int _get_channel_count() const { + switch (AudioDriver::get_singleton()->get_speaker_mode()) { + case AudioDriver::SPEAKER_MODE_STEREO: return 1; + case AudioDriver::SPEAKER_SURROUND_51: return 3; + case AudioDriver::SPEAKER_SURROUND_71: return 4; - virtual RID sample_create(SampleFormat p_format, bool p_stereo, int p_length)=0; + } + ERR_FAIL_V(1); + } - virtual void sample_set_description(RID p_sample, const String& p_description)=0; - virtual String sample_get_description(RID p_sample) const=0; - virtual SampleFormat sample_get_format(RID p_sample) const=0; - virtual bool sample_is_stereo(RID p_sample) const=0; - virtual int sample_get_length(RID p_sample) const=0; - virtual const void* sample_get_data_ptr(RID p_sample) const=0; + void _update_bus_effects(int p_bus); - virtual void sample_set_signed_data(RID p_sample, const DVector<float>& p_buffer); - virtual void sample_set_data(RID p_sample, const DVector<uint8_t>& p_buffer)=0; - virtual DVector<uint8_t> sample_get_data(RID p_sample) const=0; - virtual void sample_set_mix_rate(RID p_sample,int p_rate)=0; - virtual int sample_get_mix_rate(RID p_sample) const=0; + static AudioServer* singleton; - virtual void sample_set_loop_format(RID p_sample,SampleLoopFormat p_format)=0; - virtual SampleLoopFormat sample_get_loop_format(RID p_sample) const=0; + // TODO create an audiodata pool to optimize memory - virtual void sample_set_loop_begin(RID p_sample,int p_pos)=0; - virtual int sample_get_loop_begin(RID p_sample) const=0; - virtual void sample_set_loop_end(RID p_sample,int p_pos)=0; - virtual int sample_get_loop_end(RID p_sample) const=0; + Map<void*,uint32_t> audio_data; + size_t audio_data_total_mem; + size_t audio_data_max_mem; + Mutex *audio_data_lock; - /* VOICE API */ + void _mix_step(); - enum FilterType { - FILTER_NONE, - FILTER_LOWPASS, - FILTER_BANDPASS, - FILTER_HIPASS, - FILTER_NOTCH, - FILTER_PEAK, - FILTER_BANDLIMIT, ///< cutoff is LP resonace is HP - FILTER_LOW_SHELF, - FILTER_HIGH_SHELF - }; + struct CallbackItem { - enum ReverbRoomType { + AudioCallback callback; + void *userdata; - REVERB_SMALL, - REVERB_MEDIUM, - REVERB_LARGE, - REVERB_HALL + bool operator<(const CallbackItem& p_item) const { + return (callback==p_item.callback ? userdata < p_item.userdata : callback < p_item.callback); + } }; - virtual RID voice_create()=0; + Set<CallbackItem> callbacks; - virtual void voice_play(RID p_voice, RID p_sample)=0; +friend class AudioDriver; + void _driver_process(int p_frames, int32_t *p_buffer); +protected: - virtual void voice_set_volume(RID p_voice, float p_volume)=0; - virtual void voice_set_pan(RID p_voice, float p_pan, float p_depth=0,float height=0)=0; //pan and depth go from -1 to 1 - virtual void voice_set_filter(RID p_voice, FilterType p_type, float p_cutoff, float p_resonance, float p_gain=0)=0; - virtual void voice_set_chorus(RID p_voice, float p_chorus )=0; - virtual void voice_set_reverb(RID p_voice, ReverbRoomType p_room_type, float p_reverb)=0; - virtual void voice_set_mix_rate(RID p_voice, int p_mix_rate)=0; - virtual void voice_set_positional(RID p_voice, bool p_positional)=0; + static void _bind_methods(); +public: - virtual float voice_get_volume(RID p_voice) const=0; - virtual float voice_get_pan(RID p_voice) const=0; //pan and depth go from -1 to 1 - virtual float voice_get_pan_depth(RID p_voice) const=0; //pan and depth go from -1 to 1 - virtual float voice_get_pan_height(RID p_voice) const=0; //pan and depth go from -1 to 1 - virtual FilterType voice_get_filter_type(RID p_voice) const=0; - virtual float voice_get_filter_cutoff(RID p_voice) const=0; - virtual float voice_get_filter_resonance(RID p_voice) const=0; - virtual float voice_get_chorus(RID p_voice) const=0; - virtual ReverbRoomType voice_get_reverb_type(RID p_voice) const=0; - virtual float voice_get_reverb(RID p_voice) const=0; + //do not use from outside audio thread + AudioFrame *thread_get_channel_mix_buffer(int p_bus,int p_buffer); + int thread_get_mix_buffer_size() const; + int thread_find_bus_index(const StringName& p_name); - virtual int voice_get_mix_rate(RID p_voice) const=0; - virtual bool voice_is_positional(RID p_voice) const=0; - virtual void voice_stop(RID p_voice)=0; - virtual bool voice_is_active(RID p_voice) const=0; + void set_bus_count(int p_count); + int get_bus_count() const; - /* STREAM API */ + void remove_bus(int p_index); + void add_bus(int p_at_pos=-1); - virtual RID audio_stream_create(AudioStream *p_stream)=0; - virtual RID event_stream_create(EventStream *p_stream)=0; + void move_bus(int p_bus,int p_to_pos); - virtual void stream_set_active(RID p_stream, bool p_active)=0; - virtual bool stream_is_active(RID p_stream) const=0; + void set_bus_name(int p_bus,const String& p_name); + String get_bus_name(int p_bus) const; - virtual void stream_set_volume_scale(RID p_stream, float p_scale)=0; - virtual float stream_set_volume_scale(RID p_stream) const=0; + void set_bus_volume_db(int p_bus,float p_volume_db); + float get_bus_volume_db(int p_bus) const; - /* Audio Physics API */ - virtual void free(RID p_id)=0; + void set_bus_send(int p_bus,const StringName& p_send); + StringName get_bus_send(int p_bus) const; - virtual void init()=0; - virtual void finish()=0; - virtual void update()=0; + void set_bus_solo(int p_bus,bool p_enable); + bool is_bus_solo(int p_bus) const; + + void set_bus_mute(int p_bus,bool p_enable); + bool is_bus_mute(int p_bus) const; + + void set_bus_bypass_effects(int p_bus,bool p_enable); + bool is_bus_bypassing_effects(int p_bus) const; + + void add_bus_effect(int p_bus,const Ref<AudioEffect>& p_effect,int p_at_pos=-1); + void remove_bus_effect(int p_bus,int p_effect); + + int get_bus_effect_count(int p_bus); + Ref<AudioEffect> get_bus_effect(int p_bus,int p_effect); + + void swap_bus_effects(int p_bus,int p_effect,int p_by_effect); + + void set_bus_effect_enabled(int p_bus,int p_effect,bool p_enabled); + bool is_bus_effect_enabled(int p_bus,int p_effect) const; + + float get_bus_peak_volume_left_db(int p_bus,int p_channel) const; + float get_bus_peak_volume_right_db(int p_bus,int p_channel) const; + + bool is_bus_channel_active(int p_bus,int p_channel) const; + + virtual void init(); + virtual void finish(); + virtual void update(); + virtual void load_default_bus_layout(); /* MISC config */ - virtual void lock()=0; - virtual void unlock()=0; - virtual int get_default_channel_count() const=0; - virtual int get_default_mix_rate() const=0; + virtual void lock(); + virtual void unlock(); - virtual void set_stream_global_volume_scale(float p_volume)=0; - virtual void set_fx_global_volume_scale(float p_volume)=0; - virtual void set_event_voice_global_volume_scale(float p_volume)=0; - virtual float get_stream_global_volume_scale() const=0; - virtual float get_fx_global_volume_scale() const=0; - virtual float get_event_voice_global_volume_scale() const=0; + virtual SpeakerMode get_speaker_mode() const; + virtual float get_mix_rate() const; - virtual uint32_t read_output_peak() const=0; + virtual float read_output_peak_db() const; static AudioServer *get_singleton(); - virtual double get_mix_time() const=0; //useful for video -> audio sync - virtual double get_output_delay() const=0; + virtual double get_mix_time() const; //useful for video -> audio sync + virtual double get_output_delay() const; + + void* audio_data_alloc(uint32_t p_data_len, const uint8_t *p_from_data=NULL); + void audio_data_free(void* p_data); + + size_t audio_data_get_total_memory_usage() const; + size_t audio_data_get_max_memory_usage() const; + + + void add_callback(AudioCallback p_callback,void *p_userdata); + void remove_callback(AudioCallback p_callback,void *p_userdata); + + void set_bus_layout(const Ref<AudioBusLayout>& p_state); + Ref<AudioBusLayout> generate_bus_layout() const; AudioServer(); virtual ~AudioServer(); }; -VARIANT_ENUM_CAST( AudioServer::SampleFormat ); -VARIANT_ENUM_CAST( AudioServer::SampleLoopFormat ); -VARIANT_ENUM_CAST( AudioServer::FilterType ); -VARIANT_ENUM_CAST( AudioServer::ReverbRoomType ); +VARIANT_ENUM_CAST( AudioServer::SpeakerMode ) + +class AudioBusLayout : public Resource { + + GDCLASS(AudioBusLayout,Resource) + +friend class AudioServer; + + struct Bus { + + StringName name; + bool solo; + bool mute; + bool bypass; + + struct Effect { + Ref<AudioEffect> effect; + bool enabled; + }; + + Vector<Effect> effects; + + float volume_db; + StringName send; + + Bus() { + solo=false; + mute=false; + bypass=false; + volume_db=0; + } + }; + + Vector<Bus> buses; + +protected: + + bool _set(const StringName& p_name, const Variant& p_value); + bool _get(const StringName& p_name,Variant &r_ret) const; + void _get_property_list( List<PropertyInfo> *p_list) const; + +public: + + AudioBusLayout(); +}; + + + + + typedef AudioServer AS; + #endif // AUDIO_SERVER_H diff --git a/servers/physics/SCsub b/servers/physics/SCsub index 95296eadbe..c0ee2cc739 100644 --- a/servers/physics/SCsub +++ b/servers/physics/SCsub @@ -1,6 +1,8 @@ +#!/usr/bin/env python + Import('env') -env.add_source_files(env.servers_sources,"*.cpp") +env.add_source_files(env.servers_sources, "*.cpp") Export('env') diff --git a/servers/physics/area_pair_sw.cpp b/servers/physics/area_pair_sw.cpp index 24f3b75ca5..3aa0816b06 100644 --- a/servers/physics/area_pair_sw.cpp +++ b/servers/physics/area_pair_sw.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,7 +30,7 @@ #include "collision_solver_sw.h" -bool AreaPairSW::setup(float p_step) { +bool AreaPairSW::setup(real_t p_step) { if (!area->test_collision_mask(body)) { colliding = false; @@ -64,7 +64,7 @@ bool AreaPairSW::setup(float p_step) { return false; //never do any post solving } -void AreaPairSW::solve(float p_step) { +void AreaPairSW::solve(real_t p_step) { } @@ -103,14 +103,14 @@ AreaPairSW::~AreaPairSW() { -bool Area2PairSW::setup(float p_step) { +bool Area2PairSW::setup(real_t p_step) { if (!area_a->test_collision_mask(area_b)) { colliding = false; return false; } -// bool result = area_a->test_collision_mask(area_b) && CollisionSolverSW::solve(area_a->get_shape(shape_a),area_a->get_transform() * area_a->get_shape_transform(shape_a),Vector2(),area_b->get_shape(shape_b),area_b->get_transform() * area_b->get_shape_transform(shape_b),Vector2(),NULL,this); + //bool result = area_a->test_collision_mask(area_b) && CollisionSolverSW::solve(area_a->get_shape(shape_a),area_a->get_transform() * area_a->get_shape_transform(shape_a),Vector2(),area_b->get_shape(shape_b),area_b->get_transform() * area_b->get_shape_transform(shape_b),Vector2(),NULL,this); bool result = CollisionSolverSW::solve_static(area_a->get_shape(shape_a),area_a->get_transform() * area_a->get_shape_transform(shape_a),area_b->get_shape(shape_b),area_b->get_transform() * area_b->get_shape_transform(shape_b),NULL,this); if (result!=colliding) { @@ -139,7 +139,7 @@ bool Area2PairSW::setup(float p_step) { return false; //never do any post solving } -void Area2PairSW::solve(float p_step) { +void Area2PairSW::solve(real_t p_step) { } diff --git a/servers/physics/area_pair_sw.h b/servers/physics/area_pair_sw.h index 09a2934467..637976a095 100644 --- a/servers/physics/area_pair_sw.h +++ b/servers/physics/area_pair_sw.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -42,8 +42,8 @@ class AreaPairSW : public ConstraintSW { bool colliding; public: - bool setup(float p_step); - void solve(float p_step); + bool setup(real_t p_step); + void solve(real_t p_step); AreaPairSW(BodySW *p_body,int p_body_shape, AreaSW *p_area,int p_area_shape); ~AreaPairSW(); @@ -59,8 +59,8 @@ class Area2PairSW : public ConstraintSW { bool colliding; public: - bool setup(float p_step); - void solve(float p_step); + bool setup(real_t p_step); + void solve(real_t p_step); Area2PairSW(AreaSW *p_area_a,int p_shape_a, AreaSW *p_area_b,int p_shape_b); ~Area2PairSW(); diff --git a/servers/physics/area_sw.cpp b/servers/physics/area_sw.cpp index dbc82da316..8aed07d5e5 100644 --- a/servers/physics/area_sw.cpp +++ b/servers/physics/area_sw.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -126,14 +126,14 @@ void AreaSW::set_space_override_mode(PhysicsServer::AreaSpaceOverrideMode p_mode void AreaSW::set_param(PhysicsServer::AreaParameter p_param, const Variant& p_value) { switch(p_param) { - case PhysicsServer::AREA_PARAM_GRAVITY: gravity=p_value; ; break; - case PhysicsServer::AREA_PARAM_GRAVITY_VECTOR: gravity_vector=p_value; ; break; - case PhysicsServer::AREA_PARAM_GRAVITY_IS_POINT: gravity_is_point=p_value; ; break; - case PhysicsServer::AREA_PARAM_GRAVITY_DISTANCE_SCALE: gravity_distance_scale=p_value; ; break; - case PhysicsServer::AREA_PARAM_GRAVITY_POINT_ATTENUATION: point_attenuation=p_value; ; break; - case PhysicsServer::AREA_PARAM_LINEAR_DAMP: linear_damp=p_value; ; break; - case PhysicsServer::AREA_PARAM_ANGULAR_DAMP: angular_damp=p_value; ; break; - case PhysicsServer::AREA_PARAM_PRIORITY: priority=p_value; ; break; + case PhysicsServer::AREA_PARAM_GRAVITY: gravity=p_value; break; + case PhysicsServer::AREA_PARAM_GRAVITY_VECTOR: gravity_vector=p_value; break; + case PhysicsServer::AREA_PARAM_GRAVITY_IS_POINT: gravity_is_point=p_value; break; + case PhysicsServer::AREA_PARAM_GRAVITY_DISTANCE_SCALE: gravity_distance_scale=p_value; break; + case PhysicsServer::AREA_PARAM_GRAVITY_POINT_ATTENUATION: point_attenuation=p_value; break; + case PhysicsServer::AREA_PARAM_LINEAR_DAMP: linear_damp=p_value; break; + case PhysicsServer::AREA_PARAM_ANGULAR_DAMP: angular_damp=p_value; break; + case PhysicsServer::AREA_PARAM_PRIORITY: priority=p_value; break; } diff --git a/servers/physics/area_sw.h b/servers/physics/area_sw.h index 622eeb5e23..4e6f1c5a51 100644 --- a/servers/physics/area_sw.h +++ b/servers/physics/area_sw.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -42,13 +42,13 @@ class AreaSW : public CollisionObjectSW{ PhysicsServer::AreaSpaceOverrideMode space_override_mode; - float gravity; + real_t gravity; Vector3 gravity_vector; bool gravity_is_point; - float gravity_distance_scale; - float point_attenuation; - float linear_damp; - float angular_damp; + real_t gravity_distance_scale; + real_t point_attenuation; + real_t linear_damp; + real_t angular_damp; int priority; bool monitorable; @@ -131,8 +131,8 @@ public: void set_space_override_mode(PhysicsServer::AreaSpaceOverrideMode p_mode); PhysicsServer::AreaSpaceOverrideMode get_space_override_mode() const { return space_override_mode; } - _FORCE_INLINE_ void set_gravity(float p_gravity) { gravity=p_gravity; } - _FORCE_INLINE_ float get_gravity() const { return gravity; } + _FORCE_INLINE_ void set_gravity(real_t p_gravity) { gravity=p_gravity; } + _FORCE_INLINE_ real_t get_gravity() const { return gravity; } _FORCE_INLINE_ void set_gravity_vector(const Vector3& p_gravity) { gravity_vector=p_gravity; } _FORCE_INLINE_ Vector3 get_gravity_vector() const { return gravity_vector; } @@ -140,17 +140,17 @@ public: _FORCE_INLINE_ void set_gravity_as_point(bool p_enable) { gravity_is_point=p_enable; } _FORCE_INLINE_ bool is_gravity_point() const { return gravity_is_point; } - _FORCE_INLINE_ void set_gravity_distance_scale(float scale) { gravity_distance_scale=scale; } - _FORCE_INLINE_ float get_gravity_distance_scale() const { return gravity_distance_scale; } + _FORCE_INLINE_ void set_gravity_distance_scale(real_t scale) { gravity_distance_scale=scale; } + _FORCE_INLINE_ real_t get_gravity_distance_scale() const { return gravity_distance_scale; } - _FORCE_INLINE_ void set_point_attenuation(float p_point_attenuation) { point_attenuation=p_point_attenuation; } - _FORCE_INLINE_ float get_point_attenuation() const { return point_attenuation; } + _FORCE_INLINE_ void set_point_attenuation(real_t p_point_attenuation) { point_attenuation=p_point_attenuation; } + _FORCE_INLINE_ real_t get_point_attenuation() const { return point_attenuation; } - _FORCE_INLINE_ void set_linear_damp(float p_linear_damp) { linear_damp=p_linear_damp; } - _FORCE_INLINE_ float get_linear_damp() const { return linear_damp; } + _FORCE_INLINE_ void set_linear_damp(real_t p_linear_damp) { linear_damp=p_linear_damp; } + _FORCE_INLINE_ real_t get_linear_damp() const { return linear_damp; } - _FORCE_INLINE_ void set_angular_damp(float p_angular_damp) { angular_damp=p_angular_damp; } - _FORCE_INLINE_ float get_angular_damp() const { return angular_damp; } + _FORCE_INLINE_ void set_angular_damp(real_t p_angular_damp) { angular_damp=p_angular_damp; } + _FORCE_INLINE_ real_t get_angular_damp() const { return angular_damp; } _FORCE_INLINE_ void set_priority(int p_priority) { priority=p_priority; } _FORCE_INLINE_ int get_priority() const { return priority; } diff --git a/servers/physics/body_pair_sw.cpp b/servers/physics/body_pair_sw.cpp index 43e52f26e8..7fb3def387 100644 --- a/servers/physics/body_pair_sw.cpp +++ b/servers/physics/body_pair_sw.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -105,7 +105,7 @@ void BodyPairSW::contact_added_callback(const Vector3& p_point_A,const Vector3& // remove the contact with the minimum depth int least_deep=-1; - float min_depth=1e10; + real_t min_depth=1e10; for (int i=0;i<=contact_count;i++) { @@ -114,7 +114,7 @@ void BodyPairSW::contact_added_callback(const Vector3& p_point_A,const Vector3& Vector3 global_B = B->get_transform().basis.xform(c.local_B)+offset_B; Vector3 axis = global_A - global_B; - float depth = axis.dot( c.normal ); + real_t depth = axis.dot( c.normal ); if (depth<min_depth) { @@ -154,7 +154,7 @@ void BodyPairSW::validate_contacts() { Vector3 global_A = A->get_transform().basis.xform(c.local_A); Vector3 global_B = B->get_transform().basis.xform(c.local_B)+offset_B; Vector3 axis = global_A - global_B; - float depth = axis.dot( c.normal ); + real_t depth = axis.dot( c.normal ); if (depth < -contact_max_separation || (global_B + c.normal * depth - global_A).length() > contact_max_separation) { // contact no longer needed, remove @@ -173,7 +173,7 @@ void BodyPairSW::validate_contacts() { } -bool BodyPairSW::_test_ccd(float p_step,BodySW *p_A, int p_shape_A,const Transform& p_xform_A,BodySW *p_B, int p_shape_B,const Transform& p_xform_B) { +bool BodyPairSW::_test_ccd(real_t p_step,BodySW *p_A, int p_shape_A,const Transform& p_xform_A,BodySW *p_B, int p_shape_B,const Transform& p_xform_B) { @@ -211,14 +211,14 @@ bool BodyPairSW::_test_ccd(float p_step,BodySW *p_A, int p_shape_A,const Transfo //shorten the linear velocity so it does not hit, but gets close enough, next frame will hit softly or soft enough Vector3 hitpos = p_xform_B.xform(rpos); - float newlen = hitpos.distance_to(from)-(max-min)*0.01; + real_t newlen = hitpos.distance_to(from)-(max-min)*0.01; p_A->set_linear_velocity((mnormal*newlen)/p_step); return true; } -bool BodyPairSW::setup(float p_step) { +bool BodyPairSW::setup(real_t p_step) { //cannot collide if (!A->test_collision_mask(B) || A->has_exception(B->get_self()) || B->has_exception(A->get_self()) || (A->get_mode()<=PhysicsServer::BODY_MODE_KINEMATIC && B->get_mode()<=PhysicsServer::BODY_MODE_KINEMATIC && A->get_max_contacts_reported()==0 && B->get_max_contacts_reported()==0)) { @@ -264,7 +264,7 @@ bool BodyPairSW::setup(float p_step) { real_t max_penetration = space->get_contact_max_allowed_penetration(); - float bias = 0.3f; + real_t bias = (real_t)0.3; if (shape_A_ptr->get_custom_bias() || shape_B_ptr->get_custom_bias()) { @@ -307,8 +307,8 @@ bool BodyPairSW::setup(float p_step) { } #endif - c.rA = global_A; - c.rB = global_B-offset_B; + c.rA = global_A-A->get_center_of_mass(); + c.rB = global_B-B->get_center_of_mass()-offset_B; // contact query reporting... #if 0 @@ -356,7 +356,7 @@ bool BodyPairSW::setup(float p_step) { if (depth > max_penetration) { c.bias = (depth - max_penetration) * (1.0/(p_step*(1.0/RELAXATION_TIMESTEPS))); } else { - float approach = -0.1f * (depth - max_penetration) / (CMP_EPSILON + max_penetration); + real_t approach = -0.1 * (depth - max_penetration) / (CMP_EPSILON + max_penetration); approach = CLAMP( approach, CMP_EPSILON, 1.0 ); c.bias = approach * (depth - max_penetration) * (1.0/p_step); } @@ -364,12 +364,12 @@ bool BodyPairSW::setup(float p_step) { c.depth=depth; Vector3 j_vec = c.normal * c.acc_normal_impulse + c.acc_tangent_impulse; - A->apply_impulse( c.rA, -j_vec ); - B->apply_impulse( c.rB, j_vec ); + A->apply_impulse( c.rA+A->get_center_of_mass(), -j_vec ); + B->apply_impulse( c.rB+B->get_center_of_mass(), j_vec ); c.acc_bias_impulse=0; Vector3 jb_vec = c.normal * c.acc_bias_impulse; - A->apply_bias_impulse( c.rA, -jb_vec ); - B->apply_bias_impulse( c.rB, jb_vec ); + A->apply_bias_impulse( c.rA+A->get_center_of_mass(), -jb_vec ); + B->apply_bias_impulse( c.rB+B->get_center_of_mass(), jb_vec ); c.bounce = MAX(A->get_bounce(),B->get_bounce()); if (c.bounce) { @@ -387,7 +387,7 @@ bool BodyPairSW::setup(float p_step) { return true; } -void BodyPairSW::solve(float p_step) { +void BodyPairSW::solve(real_t p_step) { if (!collided) return; @@ -418,8 +418,8 @@ void BodyPairSW::solve(float p_step) { Vector3 jb = c.normal * (c.acc_bias_impulse - jbnOld); - A->apply_bias_impulse(c.rA,-jb); - B->apply_bias_impulse(c.rB, jb); + A->apply_bias_impulse(c.rA+A->get_center_of_mass(),-jb); + B->apply_bias_impulse(c.rB+B->get_center_of_mass(), jb); c.active=true; } @@ -442,8 +442,8 @@ void BodyPairSW::solve(float p_step) { Vector3 j =c.normal * (c.acc_normal_impulse - jnOld); - A->apply_impulse(c.rA,-j); - B->apply_impulse(c.rB, j); + A->apply_impulse(c.rA+A->get_center_of_mass(),-j); + B->apply_impulse(c.rB+B->get_center_of_mass(), j); c.active=true; } @@ -489,8 +489,8 @@ void BodyPairSW::solve(float p_step) { jt = c.acc_tangent_impulse - jtOld; - A->apply_impulse( c.rA, -jt ); - B->apply_impulse( c.rB, jt ); + A->apply_impulse( c.rA+A->get_center_of_mass(), -jt ); + B->apply_impulse( c.rB+B->get_center_of_mass(), jt ); c.active=true; diff --git a/servers/physics/body_pair_sw.h b/servers/physics/body_pair_sw.h index da637ade05..f282a56b9e 100644 --- a/servers/physics/body_pair_sw.h +++ b/servers/physics/body_pair_sw.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -65,7 +65,7 @@ class BodyPairSW : public ConstraintSW { real_t depth; bool active; - Vector3 rA,rB; + Vector3 rA,rB; // Offset in world orientation with respect to center of mass }; Vector3 offset_B; //use local A coordinates to avoid numerical issues on collision detection @@ -82,14 +82,14 @@ class BodyPairSW : public ConstraintSW { void contact_added_callback(const Vector3& p_point_A,const Vector3& p_point_B); void validate_contacts(); - bool _test_ccd(float p_step,BodySW *p_A, int p_shape_A,const Transform& p_xform_A,BodySW *p_B, int p_shape_B,const Transform& p_xform_B); + bool _test_ccd(real_t p_step,BodySW *p_A, int p_shape_A,const Transform& p_xform_A,BodySW *p_B, int p_shape_B,const Transform& p_xform_B); SpaceSW *space; public: - bool setup(float p_step); - void solve(float p_step); + bool setup(real_t p_step); + void solve(real_t p_step); BodyPairSW(BodySW *p_A, int p_shape_A,BodySW *p_B, int p_shape_B); ~BodyPairSW(); diff --git a/servers/physics/body_sw.cpp b/servers/physics/body_sw.cpp index b0ed99cb48..7fcd767268 100644 --- a/servers/physics/body_sw.cpp +++ b/servers/physics/body_sw.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -37,12 +37,16 @@ void BodySW::_update_inertia() { } +void BodySW::_update_transform_dependant() { + + center_of_mass = get_transform().basis.xform(center_of_mass_local); + principal_inertia_axes = get_transform().basis * principal_inertia_axes_local; -void BodySW::_update_inertia_tensor() { - - Matrix3 tb = get_transform().basis; + // update inertia tensor + Basis tb = principal_inertia_axes; + Basis tbt = tb.transposed(); tb.scale(_inv_inertia); - _inv_inertia_tensor = tb * get_transform().basis.transposed(); + _inv_inertia_tensor = tb * tbt; } @@ -54,33 +58,56 @@ void BodySW::update_inertias() { case PhysicsServer::BODY_MODE_RIGID: { - //update tensor for allshapes, not the best way but should be somehow OK. (inspired from bullet) - float total_area=0; + //update tensor for all shapes, not the best way but should be somehow OK. (inspired from bullet) + real_t total_area=0; for (int i=0;i<get_shape_count();i++) { - total_area+=get_shape_aabb(i).get_area(); + total_area+=get_shape_area(i); } - Vector3 _inertia; + // We have to recompute the center of mass + center_of_mass_local.zero(); + + for (int i=0; i<get_shape_count(); i++) { + real_t area=get_shape_area(i); + + real_t mass = area * this->mass / total_area; + + // NOTE: we assume that the shape origin is also its center of mass + center_of_mass_local += mass * get_shape_transform(i).origin; + } + center_of_mass_local /= mass; + + // Recompute the inertia tensor + Basis inertia_tensor; + inertia_tensor.set_zero(); for (int i=0;i<get_shape_count();i++) { const ShapeSW* shape=get_shape(i); - float area=get_shape_aabb(i).get_area(); + real_t area=get_shape_area(i); + + real_t mass = area * this->mass / total_area; + + Basis shape_inertia_tensor=shape->get_moment_of_inertia(mass).to_diagonal_matrix(); + Transform shape_transform=get_shape_transform(i); + Basis shape_basis = shape_transform.basis.orthonormalized(); + + // NOTE: we don't take the scale of collision shapes into account when computing the inertia tensor! + shape_inertia_tensor = shape_basis * shape_inertia_tensor * shape_basis.transposed(); - float mass = area * this->mass / total_area; + Vector3 shape_origin = shape_transform.origin - center_of_mass_local; + inertia_tensor += shape_inertia_tensor + (Basis()*shape_origin.dot(shape_origin)-shape_origin.outer(shape_origin))*mass; - _inertia += shape->get_moment_of_inertia(mass) + mass * get_shape_transform(i).get_origin(); } - if (_inertia!=Vector3()) - _inv_inertia=_inertia.inverse(); - else - _inv_inertia=Vector3(); + // Compute the principal axes of inertia + principal_inertia_axes_local = inertia_tensor.diagonalize().transposed(); + _inv_inertia = inertia_tensor.get_main_diagonal().inverse(); if (mass) _inv_mass=1.0/mass; @@ -92,20 +119,21 @@ void BodySW::update_inertias() { case PhysicsServer::BODY_MODE_KINEMATIC: case PhysicsServer::BODY_MODE_STATIC: { - _inv_inertia=Vector3(); + _inv_inertia_tensor.set_zero(); _inv_mass=0; } break; case PhysicsServer::BODY_MODE_CHARACTER: { - _inv_inertia=Vector3(); + _inv_inertia_tensor.set_zero(); _inv_mass=1.0/mass; } break; } - _update_inertia_tensor(); + //_update_shapes(); + _update_transform_dependant(); } @@ -142,7 +170,7 @@ void BodySW::set_active(bool p_active) { -void BodySW::set_param(PhysicsServer::BodyParameter p_param, float p_value) { +void BodySW::set_param(PhysicsServer::BodyParameter p_param, real_t p_value) { switch(p_param) { case PhysicsServer::BODY_PARAM_BOUNCE: { @@ -174,7 +202,7 @@ void BodySW::set_param(PhysicsServer::BodyParameter p_param, float p_value) { } } -float BodySW::get_param(PhysicsServer::BodyParameter p_param) const { +real_t BodySW::get_param(PhysicsServer::BodyParameter p_param) const { switch(p_param) { case PhysicsServer::BODY_PARAM_BOUNCE: { @@ -242,8 +270,10 @@ void BodySW::set_mode(PhysicsServer::BodyMode p_mode) { } _update_inertia(); - //if (get_space()) -// _update_queries(); + /* + if (get_space()) + _update_queries(); + */ } PhysicsServer::BodyMode BodySW::get_mode() const { @@ -291,14 +321,18 @@ void BodySW::set_state(PhysicsServer::BodyState p_state, const Variant& p_varian } break; case PhysicsServer::BODY_STATE_LINEAR_VELOCITY: { - //if (mode==PhysicsServer::BODY_MODE_STATIC) - // break; + /* + if (mode==PhysicsServer::BODY_MODE_STATIC) + break; + */ linear_velocity=p_variant; wakeup(); } break; case PhysicsServer::BODY_STATE_ANGULAR_VELOCITY: { - //if (mode!=PhysicsServer::BODY_MODE_RIGID) - // break; + /* + if (mode!=PhysicsServer::BODY_MODE_RIGID) + break; + */ angular_velocity=p_variant; wakeup(); @@ -372,11 +406,13 @@ void BodySW::set_space(SpaceSW *p_space){ _update_inertia(); if (active) get_space()->body_add_to_active_list(&active_list); -// _update_queries(); - //if (is_active()) { - // active=false; - // set_active(true); - //} + /* + _update_queries(); + if (is_active()) { + active=false; + set_active(true); + } + */ } @@ -451,13 +487,17 @@ void BodySW::integrate_forces(real_t p_step) { // If less than 0, override dampenings with that of the Body if (angular_damp>=0) area_angular_damp=angular_damp; - //else - // area_angular_damp=damp_area->get_angular_damp(); + /* + else + area_angular_damp=damp_area->get_angular_damp(); + */ if (linear_damp>=0) area_linear_damp=linear_damp; - //else - // area_linear_damp=damp_area->get_linear_damp(); + /* + else + area_linear_damp=damp_area->get_linear_damp(); + */ Vector3 motion; @@ -469,9 +509,9 @@ void BodySW::integrate_forces(real_t p_step) { linear_velocity = (new_transform.origin - get_transform().origin)/p_step; //compute a FAKE angular velocity, not so easy - Matrix3 rot=new_transform.basis.orthonormalized().transposed() * get_transform().basis.orthonormalized(); + Basis rot=new_transform.basis.orthonormalized().transposed() * get_transform().basis.orthonormalized(); Vector3 axis; - float angle; + real_t angle; rot.get_axis_and_angle(axis,angle); axis.normalize(); @@ -575,13 +615,15 @@ void BodySW::integrate_velocities(real_t p_step) { - float ang_vel = total_angular_velocity.length(); + real_t ang_vel = total_angular_velocity.length(); Transform transform = get_transform(); if (ang_vel!=0.0) { Vector3 ang_vel_axis = total_angular_velocity / ang_vel; - Matrix3 rot( ang_vel_axis, -ang_vel*p_step ); + Basis rot( ang_vel_axis, ang_vel*p_step ); + Basis identity3(1, 0, 0, 0, 1, 0, 0, 0, 1); + transform.origin += ((identity3 - rot) * transform.basis).xform(center_of_mass_local); transform.basis = rot * transform.basis; transform.orthonormalize(); } @@ -598,12 +640,12 @@ void BodySW::integrate_velocities(real_t p_step) { _set_transform(transform); _set_inv_transform(get_transform().inverse()); - _update_inertia_tensor(); - - //if (fi_callback) { + _update_transform_dependant(); - // get_space()->body_add_to_state_query_list(&direct_state_query_list); - // + /* + if (fi_callback) { + get_space()->body_add_to_state_query_list(&direct_state_query_list); + */ } /* @@ -624,7 +666,7 @@ void BodySW::simulate_motion(const Transform& p_xform,real_t p_step) { //compute a FAKE angular velocity, not so easy Matrix3 rot=get_transform().basis.orthonormalized().transposed() * p_xform.basis.orthonormalized(); Vector3 axis; - float angle; + real_t angle; rot.get_axis_and_angle(axis,angle); axis.normalize(); @@ -742,12 +784,12 @@ BodySW::BodySW() : CollisionObjectSW(TYPE_BODY), active_list(this), inertia_upda active=true; mass=1; -// _inv_inertia=Transform(); + //_inv_inertia=Transform(); _inv_mass=1; bounce=0; friction=1; omit_force_integration=false; -// applied_torque=0; + //applied_torque=0; island_step=0; island_next=NULL; island_list_next=NULL; diff --git a/servers/physics/body_sw.h b/servers/physics/body_sw.h index 870e8357f1..2383d2d688 100644 --- a/servers/physics/body_sw.h +++ b/servers/physics/body_sw.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -57,8 +57,16 @@ class BodySW : public CollisionObjectSW { PhysicsServer::BodyAxisLock axis_lock; real_t _inv_mass; - Vector3 _inv_inertia; - Matrix3 _inv_inertia_tensor; + Vector3 _inv_inertia; // Relative to the principal axes of inertia + + // Relative to the local frame of reference + Basis principal_inertia_axes_local; + Vector3 center_of_mass_local; + + // In world orientation with local origin + Basis _inv_inertia_tensor; + Basis principal_inertia_axes; + Vector3 center_of_mass; Vector3 gravity; @@ -67,8 +75,8 @@ class BodySW : public CollisionObjectSW { Vector3 applied_force; Vector3 applied_torque; - float area_angular_damp; - float area_linear_damp; + real_t area_angular_damp; + real_t area_linear_damp; SelfList<BodySW> active_list; @@ -107,7 +115,7 @@ class BodySW : public CollisionObjectSW { Vector3 local_pos; Vector3 local_normal; - float depth; + real_t depth; int local_shape; Vector3 collider_pos; int collider_shape; @@ -135,7 +143,7 @@ class BodySW : public CollisionObjectSW { _FORCE_INLINE_ void _compute_area_gravity_and_dampenings(const AreaSW *p_area); - _FORCE_INLINE_ void _update_inertia_tensor(); + _FORCE_INLINE_ void _update_transform_dependant(); friend class PhysicsDirectBodyStateSW; // i give up, too many functions to expose @@ -166,7 +174,7 @@ public: _FORCE_INLINE_ int get_max_contacts_reported() const { return contacts.size(); } _FORCE_INLINE_ bool can_report_contacts() const { return !contacts.empty(); } - _FORCE_INLINE_ void add_contact(const Vector3& p_local_pos,const Vector3& p_local_normal, float p_depth, int p_local_shape, const Vector3& p_collider_pos, int p_collider_shape, ObjectID p_collider_instance_id, const RID& p_collider,const Vector3& p_collider_velocity_at_pos); + _FORCE_INLINE_ void add_contact(const Vector3& p_local_pos,const Vector3& p_local_normal, real_t p_depth, int p_local_shape, const Vector3& p_collider_pos, int p_collider_shape, ObjectID p_collider_instance_id, const RID& p_collider,const Vector3& p_collider_velocity_at_pos); _FORCE_INLINE_ void add_exception(const RID& p_exception) { exceptions.insert(p_exception);} @@ -190,6 +198,10 @@ public: _FORCE_INLINE_ void set_omit_force_integration(bool p_omit_force_integration) { omit_force_integration=p_omit_force_integration; } _FORCE_INLINE_ bool get_omit_force_integration() const { return omit_force_integration; } + _FORCE_INLINE_ Basis get_principal_inertia_axes() const { return principal_inertia_axes; } + _FORCE_INLINE_ Vector3 get_center_of_mass() const { return center_of_mass; } + _FORCE_INLINE_ Vector3 xform_local_to_principal(const Vector3& p_pos) const { return principal_inertia_axes_local.xform(p_pos - center_of_mass_local); } + _FORCE_INLINE_ void set_linear_velocity(const Vector3& p_velocity) {linear_velocity=p_velocity; } _FORCE_INLINE_ Vector3 get_linear_velocity() const { return linear_velocity; } @@ -202,18 +214,23 @@ public: _FORCE_INLINE_ void apply_impulse(const Vector3& p_pos, const Vector3& p_j) { linear_velocity += p_j * _inv_mass; - angular_velocity += _inv_inertia_tensor.xform( p_pos.cross(p_j) ); + angular_velocity += _inv_inertia_tensor.xform( (p_pos-center_of_mass).cross(p_j) ); + } + + _FORCE_INLINE_ void apply_torque_impulse(const Vector3& p_j) { + + angular_velocity += _inv_inertia_tensor.xform(p_j); } _FORCE_INLINE_ void apply_bias_impulse(const Vector3& p_pos, const Vector3& p_j) { biased_linear_velocity += p_j * _inv_mass; - biased_angular_velocity += _inv_inertia_tensor.xform( p_pos.cross(p_j) ); + biased_angular_velocity += _inv_inertia_tensor.xform( (p_pos-center_of_mass).cross(p_j) ); } - _FORCE_INLINE_ void apply_torque_impulse(const Vector3& p_j) { + _FORCE_INLINE_ void apply_bias_torque_impulse(const Vector3& p_j) { - angular_velocity += _inv_inertia_tensor.xform(p_j); + biased_angular_velocity += _inv_inertia_tensor.xform(p_j); } _FORCE_INLINE_ void add_force(const Vector3& p_force, const Vector3& p_pos) { @@ -231,8 +248,8 @@ public: set_active(true); } - void set_param(PhysicsServer::BodyParameter p_param, float); - float get_param(PhysicsServer::BodyParameter p_param) const; + void set_param(PhysicsServer::BodyParameter p_param, real_t); + real_t get_param(PhysicsServer::BodyParameter p_param) const; void set_mode(PhysicsServer::BodyMode p_mode); PhysicsServer::BodyMode get_mode() const; @@ -255,7 +272,7 @@ public: _FORCE_INLINE_ real_t get_inv_mass() const { return _inv_mass; } _FORCE_INLINE_ Vector3 get_inv_inertia() const { return _inv_inertia; } - _FORCE_INLINE_ Matrix3 get_inv_inertia_tensor() const { return _inv_inertia_tensor; } + _FORCE_INLINE_ Basis get_inv_inertia_tensor() const { return _inv_inertia_tensor; } _FORCE_INLINE_ real_t get_friction() const { return friction; } _FORCE_INLINE_ Vector3 get_gravity() const { return gravity; } _FORCE_INLINE_ real_t get_bounce() const { return bounce; } @@ -268,12 +285,12 @@ public: _FORCE_INLINE_ Vector3 get_velocity_in_local_point(const Vector3& rel_pos) const { - return linear_velocity + angular_velocity.cross(rel_pos); + return linear_velocity + angular_velocity.cross(rel_pos-center_of_mass); } _FORCE_INLINE_ real_t compute_impulse_denominator(const Vector3& p_pos, const Vector3& p_normal) const { - Vector3 r0 = p_pos - get_transform().origin; + Vector3 r0 = p_pos - get_transform().origin - center_of_mass; Vector3 c0 = (r0).cross(p_normal); @@ -302,7 +319,7 @@ public: //add contact inline -void BodySW::add_contact(const Vector3& p_local_pos,const Vector3& p_local_normal, float p_depth, int p_local_shape, const Vector3& p_collider_pos, int p_collider_shape, ObjectID p_collider_instance_id, const RID& p_collider,const Vector3& p_collider_velocity_at_pos) { +void BodySW::add_contact(const Vector3& p_local_pos,const Vector3& p_local_normal, real_t p_depth, int p_local_shape, const Vector3& p_collider_pos, int p_collider_shape, ObjectID p_collider_instance_id, const RID& p_collider,const Vector3& p_collider_velocity_at_pos) { int c_max=contacts.size(); @@ -318,7 +335,7 @@ void BodySW::add_contact(const Vector3& p_local_pos,const Vector3& p_local_norma idx=contact_count++; } else { - float least_depth=1e20; + real_t least_depth=1e20; int least_deep=-1; for(int i=0;i<c_max;i++) { @@ -351,7 +368,7 @@ void BodySW::add_contact(const Vector3& p_local_pos,const Vector3& p_local_norma class PhysicsDirectBodyStateSW : public PhysicsDirectBodyState { - OBJ_TYPE( PhysicsDirectBodyStateSW, PhysicsDirectBodyState ); + GDCLASS( PhysicsDirectBodyStateSW, PhysicsDirectBodyState ); public: @@ -360,12 +377,15 @@ public: real_t step; virtual Vector3 get_total_gravity() const { return body->gravity; } // get gravity vector working on this body space/area - virtual float get_total_angular_damp() const { return body->area_angular_damp; } // get density of this body space/area - virtual float get_total_linear_damp() const { return body->area_linear_damp; } // get density of this body space/area + virtual real_t get_total_angular_damp() const { return body->area_angular_damp; } // get density of this body space/area + virtual real_t get_total_linear_damp() const { return body->area_linear_damp; } // get density of this body space/area + + virtual Vector3 get_center_of_mass() const { return body->get_center_of_mass(); } + virtual Basis get_principal_inertia_axes() const { return body->get_principal_inertia_axes(); } - virtual float get_inverse_mass() const { return body->get_inv_mass(); } // get the mass + virtual real_t get_inverse_mass() const { return body->get_inv_mass(); } // get the mass virtual Vector3 get_inverse_inertia() const { return body->get_inv_inertia(); } // get density of this body space - virtual Matrix3 get_inverse_inertia_tensor() const { return body->get_inv_inertia_tensor(); } // get density of this body space + virtual Basis get_inverse_inertia_tensor() const { return body->get_inv_inertia_tensor(); } // get density of this body space virtual void set_linear_velocity(const Vector3& p_velocity) { body->set_linear_velocity(p_velocity); } virtual Vector3 get_linear_velocity() const { return body->get_linear_velocity(); } @@ -378,6 +398,7 @@ public: virtual void add_force(const Vector3& p_force, const Vector3& p_pos) { body->add_force(p_force,p_pos); } virtual void apply_impulse(const Vector3& p_pos, const Vector3& p_j) { body->apply_impulse(p_pos,p_j); } + virtual void apply_torque_impulse(const Vector3& p_j) { body->apply_torque_impulse(p_j); } virtual void set_sleep_state(bool p_enable) { body->set_active(!p_enable); } virtual bool is_sleeping() const { return !body->is_active(); } diff --git a/servers/physics/broad_phase_basic.cpp b/servers/physics/broad_phase_basic.cpp index 0bed56d398..f1c22caae3 100644 --- a/servers/physics/broad_phase_basic.cpp +++ b/servers/physics/broad_phase_basic.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -47,7 +47,7 @@ BroadPhaseSW::ID BroadPhaseBasic::create(CollisionObjectSW *p_object_, int p_sub return current; } -void BroadPhaseBasic::move(ID p_id, const AABB& p_aabb) { +void BroadPhaseBasic::move(ID p_id, const Rect3& p_aabb) { Map<ID,Element>::Element *E=element_map.find(p_id); ERR_FAIL_COND(!E); @@ -115,7 +115,7 @@ int BroadPhaseBasic::cull_segment(const Vector3& p_from, const Vector3& p_to,Col for (Map<ID,Element>::Element *E=element_map.front();E;E=E->next()) { - const AABB aabb=E->get().aabb; + const Rect3 aabb=E->get().aabb; if (aabb.intersects_segment(p_from,p_to)) { p_results[rc]=E->get().owner; @@ -129,13 +129,13 @@ int BroadPhaseBasic::cull_segment(const Vector3& p_from, const Vector3& p_to,Col return rc; } -int BroadPhaseBasic::cull_aabb(const AABB& p_aabb,CollisionObjectSW** p_results,int p_max_results,int *p_result_indices) { +int BroadPhaseBasic::cull_aabb(const Rect3& p_aabb,CollisionObjectSW** p_results,int p_max_results,int *p_result_indices) { int rc=0; for (Map<ID,Element>::Element *E=element_map.front();E;E=E->next()) { - const AABB aabb=E->get().aabb; + const Rect3 aabb=E->get().aabb; if (aabb.intersects(p_aabb)) { p_results[rc]=E->get().owner; diff --git a/servers/physics/broad_phase_basic.h b/servers/physics/broad_phase_basic.h index 6bf024044e..9f07e896c4 100644 --- a/servers/physics/broad_phase_basic.h +++ b/servers/physics/broad_phase_basic.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -38,7 +38,7 @@ class BroadPhaseBasic : public BroadPhaseSW { CollisionObjectSW *owner; bool _static; - AABB aabb; + Rect3 aabb; int subindex; }; @@ -78,7 +78,7 @@ public: // 0 is an invalid ID virtual ID create(CollisionObjectSW *p_object_, int p_subindex=0); - virtual void move(ID p_id, const AABB& p_aabb); + virtual void move(ID p_id, const Rect3& p_aabb); virtual void set_static(ID p_id, bool p_static); virtual void remove(ID p_id); @@ -87,7 +87,7 @@ public: virtual int get_subindex(ID p_id) const; virtual int cull_segment(const Vector3& p_from, const Vector3& p_to,CollisionObjectSW** p_results,int p_max_results,int *p_result_indices=NULL); - virtual int cull_aabb(const AABB& p_aabb,CollisionObjectSW** p_results,int p_max_results,int *p_result_indices=NULL); + virtual int cull_aabb(const Rect3& p_aabb,CollisionObjectSW** p_results,int p_max_results,int *p_result_indices=NULL); virtual void set_pair_callback(PairCallback p_pair_callback,void *p_userdata); virtual void set_unpair_callback(UnpairCallback p_unpair_callback,void *p_userdata); diff --git a/servers/physics/broad_phase_octree.cpp b/servers/physics/broad_phase_octree.cpp index bfe41f8423..89581997a2 100644 --- a/servers/physics/broad_phase_octree.cpp +++ b/servers/physics/broad_phase_octree.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -29,13 +29,13 @@ #include "broad_phase_octree.h" #include "collision_object_sw.h" -ID BroadPhaseOctree::create(CollisionObjectSW *p_object, int p_subindex) { +BroadPhaseSW::ID BroadPhaseOctree::create(CollisionObjectSW *p_object, int p_subindex) { - ID oid = octree.create(p_object,AABB(),p_subindex,false,1<<p_object->get_type(),0); + ID oid = octree.create(p_object,Rect3(),p_subindex,false,1<<p_object->get_type(),0); return oid; } -void BroadPhaseOctree::move(ID p_id, const AABB& p_aabb){ +void BroadPhaseOctree::move(ID p_id, const Rect3& p_aabb){ octree.move(p_id,p_aabb); } @@ -71,7 +71,7 @@ int BroadPhaseOctree::cull_segment(const Vector3& p_from, const Vector3& p_to,Co return octree.cull_segment(p_from,p_to,p_results,p_max_results,p_result_indices); } -int BroadPhaseOctree::cull_aabb(const AABB& p_aabb,CollisionObjectSW** p_results,int p_max_results,int *p_result_indices) { +int BroadPhaseOctree::cull_aabb(const Rect3& p_aabb,CollisionObjectSW** p_results,int p_max_results,int *p_result_indices) { return octree.cull_AABB(p_aabb,p_results,p_max_results,p_result_indices); diff --git a/servers/physics/broad_phase_octree.h b/servers/physics/broad_phase_octree.h index b87996a58c..29f1123edf 100644 --- a/servers/physics/broad_phase_octree.h +++ b/servers/physics/broad_phase_octree.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -50,7 +50,7 @@ public: // 0 is an invalid ID virtual ID create(CollisionObjectSW *p_object_, int p_subindex=0); - virtual void move(ID p_id, const AABB& p_aabb); + virtual void move(ID p_id, const Rect3& p_aabb); virtual void set_static(ID p_id, bool p_static); virtual void remove(ID p_id); @@ -59,7 +59,7 @@ public: virtual int get_subindex(ID p_id) const; virtual int cull_segment(const Vector3& p_from, const Vector3& p_to,CollisionObjectSW** p_results,int p_max_results,int *p_result_indices=NULL); - virtual int cull_aabb(const AABB& p_aabb,CollisionObjectSW** p_results,int p_max_results,int *p_result_indices=NULL); + virtual int cull_aabb(const Rect3& p_aabb,CollisionObjectSW** p_results,int p_max_results,int *p_result_indices=NULL); virtual void set_pair_callback(PairCallback p_pair_callback,void *p_userdata); virtual void set_unpair_callback(UnpairCallback p_unpair_callback,void *p_userdata); diff --git a/servers/physics/broad_phase_sw.cpp b/servers/physics/broad_phase_sw.cpp index a382df6a46..2a897dea2b 100644 --- a/servers/physics/broad_phase_sw.cpp +++ b/servers/physics/broad_phase_sw.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/servers/physics/broad_phase_sw.h b/servers/physics/broad_phase_sw.h index 409c249865..20b3efc7fb 100644 --- a/servers/physics/broad_phase_sw.h +++ b/servers/physics/broad_phase_sw.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,7 +30,7 @@ #define BROAD_PHASE_SW_H #include "math_funcs.h" -#include "aabb.h" +#include "rect3.h" class CollisionObjectSW; @@ -50,7 +50,7 @@ public: // 0 is an invalid ID virtual ID create(CollisionObjectSW *p_object_, int p_subindex=0)=0; - virtual void move(ID p_id, const AABB& p_aabb)=0; + virtual void move(ID p_id, const Rect3& p_aabb)=0; virtual void set_static(ID p_id, bool p_static)=0; virtual void remove(ID p_id)=0; @@ -59,7 +59,7 @@ public: virtual int get_subindex(ID p_id) const=0; virtual int cull_segment(const Vector3& p_from, const Vector3& p_to,CollisionObjectSW** p_results,int p_max_results,int *p_result_indices=NULL)=0; - virtual int cull_aabb(const AABB& p_aabb,CollisionObjectSW** p_results,int p_max_results,int *p_result_indices=NULL)=0; + virtual int cull_aabb(const Rect3& p_aabb,CollisionObjectSW** p_results,int p_max_results,int *p_result_indices=NULL)=0; virtual void set_pair_callback(PairCallback p_pair_callback,void *p_userdata)=0; virtual void set_unpair_callback(UnpairCallback p_unpair_callback,void *p_userdata)=0; diff --git a/servers/physics/collision_object_sw.cpp b/servers/physics/collision_object_sw.cpp index f2864ee95e..88aa737579 100644 --- a/servers/physics/collision_object_sw.cpp +++ b/servers/physics/collision_object_sw.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -138,12 +138,14 @@ void CollisionObjectSW::_update_shapes() { } //not quite correct, should compute the next matrix.. - AABB shape_aabb=s.shape->get_aabb(); + Rect3 shape_aabb=s.shape->get_aabb(); Transform xform = transform * s.xform; shape_aabb=xform.xform(shape_aabb); s.aabb_cache=shape_aabb; s.aabb_cache=s.aabb_cache.grow( (s.aabb_cache.size.x + s.aabb_cache.size.y)*0.5*0.05 ); + Vector3 scale = xform.get_basis().get_scale(); + s.area_cache=s.shape->get_area()*scale.x*scale.y*scale.z; space->get_broadphase()->move(s.bpid,s.aabb_cache); } @@ -165,10 +167,10 @@ void CollisionObjectSW::_update_shapes_with_motion(const Vector3& p_motion) { } //not quite correct, should compute the next matrix.. - AABB shape_aabb=s.shape->get_aabb(); + Rect3 shape_aabb=s.shape->get_aabb(); Transform xform = transform * s.xform; shape_aabb=xform.xform(shape_aabb); - shape_aabb=shape_aabb.merge(AABB( shape_aabb.pos+p_motion,shape_aabb.size)); //use motion + shape_aabb=shape_aabb.merge(Rect3( shape_aabb.pos+p_motion,shape_aabb.size)); //use motion s.aabb_cache=shape_aabb; space->get_broadphase()->move(s.bpid,shape_aabb); diff --git a/servers/physics/collision_object_sw.h b/servers/physics/collision_object_sw.h index bc71c2709b..c46a7f4a5f 100644 --- a/servers/physics/collision_object_sw.h +++ b/servers/physics/collision_object_sw.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -60,7 +60,8 @@ private: Transform xform; Transform xform_inv; BroadPhaseSW::ID bpid; - AABB aabb_cache; //for rayqueries + Rect3 aabb_cache; //for rayqueries + real_t area_cache; ShapeSW *shape; bool trigger; @@ -122,7 +123,8 @@ public: _FORCE_INLINE_ ShapeSW *get_shape(int p_index) const { return shapes[p_index].shape; } _FORCE_INLINE_ const Transform& get_shape_transform(int p_index) const { return shapes[p_index].xform; } _FORCE_INLINE_ const Transform& get_shape_inv_transform(int p_index) const { return shapes[p_index].xform_inv; } - _FORCE_INLINE_ const AABB& get_shape_aabb(int p_index) const { return shapes[p_index].aabb_cache; } + _FORCE_INLINE_ const Rect3& get_shape_aabb(int p_index) const { return shapes[p_index].aabb_cache; } + _FORCE_INLINE_ const real_t get_shape_area(int p_index) const { return shapes[p_index].area_cache; } _FORCE_INLINE_ Transform get_transform() const { return transform; } _FORCE_INLINE_ Transform get_inv_transform() const { return inv_transform; } diff --git a/servers/physics/collision_solver_sat.cpp b/servers/physics/collision_solver_sat.cpp index 3e7719e5eb..9d3e1db47b 100644 --- a/servers/physics/collision_solver_sat.cpp +++ b/servers/physics/collision_solver_sat.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -42,9 +42,11 @@ struct _CollectorCallback { _FORCE_INLINE_ void call(const Vector3& p_point_A, const Vector3& p_point_B) { - //if (normal.dot(p_point_A) >= normal.dot(p_point_B)) - // return; -// print_line("** A: "+p_point_A+" B: "+p_point_B+" D: "+rtos(p_point_A.distance_to(p_point_B))); + /* + if (normal.dot(p_point_A) >= normal.dot(p_point_B)) + return; + print_line("** A: "+p_point_A+" B: "+p_point_B+" D: "+rtos(p_point_A.distance_to(p_point_B))); + */ if (swap) callback(p_point_B,p_point_A,userdata); @@ -108,7 +110,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) )<_EDGE_IS_VALID_SUPPORT_TRESHOLD ) { + //if ( Math::abs(rel_A.dot(c) )<_EDGE_IS_VALID_SUPPORT_TRESHOLD ) { if ( Math::abs(rel_A.dot(c) )<CMP_EPSILON ) { // should handle somehow.. @@ -120,9 +122,9 @@ static void _generate_contacts_edge_edge(const Vector3 * p_points_A,int p_point_ Vector3 base_B = p_points_B[0] - axis * axis.dot(p_points_B[0]); //sort all 4 points in axis - float dvec[4]={ axis.dot(p_points_A[0]), axis.dot(p_points_A[1]), axis.dot(p_points_B[0]), axis.dot(p_points_B[1]) }; + real_t dvec[4]={ axis.dot(p_points_A[0]), axis.dot(p_points_A[1]), axis.dot(p_points_B[0]), axis.dot(p_points_B[1]) }; - SortArray<float> sa; + SortArray<real_t> sa; sa.sort(dvec,4); //use the middle ones as contacts @@ -205,7 +207,7 @@ static void _generate_contacts_face_face(const Vector3 * p_points_A,int p_point_ // check for different sides and non coplanar -// if ( (dist0*dist1) < -CMP_EPSILON && !(edge && j)) { + //if ( (dist0*dist1) < -CMP_EPSILON && !(edge && j)) { if ( (dist0*dist1) < 0 && !(edge && j)) { // calculate intersection @@ -232,9 +234,11 @@ static void _generate_contacts_face_face(const Vector3 * p_points_A,int p_point_ for (int i=0;i<clipbuf_len;i++) { - float d = plane_B.distance_to(clipbuf_src[i]); - //if (d>CMP_EPSILON) - // continue; + real_t d = plane_B.distance_to(clipbuf_src[i]); + /* + if (d>CMP_EPSILON) + continue; + */ Vector3 closest_B=clipbuf_src[i] - plane_B.normal*d; @@ -472,11 +476,11 @@ public: /****** SAT TESTS *******/ -typedef void (*CollisionFunc)(const ShapeSW*,const Transform&,const ShapeSW*,const Transform&,_CollectorCallback *p_callback,float,float); +typedef void (*CollisionFunc)(const ShapeSW*,const Transform&,const ShapeSW*,const Transform&,_CollectorCallback *p_callback,real_t,real_t); template<bool withMargin> -static void _collision_sphere_sphere(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,float p_margin_a,float p_margin_b) { +static void _collision_sphere_sphere(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,real_t p_margin_a,real_t p_margin_b) { const SphereShapeSW *sphere_A = static_cast<const SphereShapeSW*>(p_a); @@ -496,7 +500,7 @@ static void _collision_sphere_sphere(const ShapeSW *p_a,const Transform &p_trans } template<bool withMargin> -static void _collision_sphere_box(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,float p_margin_a,float p_margin_b) { +static void _collision_sphere_box(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,real_t p_margin_a,real_t p_margin_b) { const SphereShapeSW *sphere_A = static_cast<const SphereShapeSW*>(p_a); @@ -551,7 +555,7 @@ static void _collision_sphere_box(const ShapeSW *p_a,const Transform &p_transfor } template<bool withMargin> -static void _collision_sphere_capsule(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,float p_margin_a,float p_margin_b) { +static void _collision_sphere_capsule(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,real_t p_margin_a,real_t p_margin_b) { const SphereShapeSW *sphere_A = static_cast<const SphereShapeSW*>(p_a); const CapsuleShapeSW *capsule_B = static_cast<const CapsuleShapeSW*>(p_b); @@ -591,7 +595,7 @@ static void _collision_sphere_capsule(const ShapeSW *p_a,const Transform &p_tran } template<bool withMargin> -static void _collision_sphere_convex_polygon(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,float p_margin_a,float p_margin_b) { +static void _collision_sphere_convex_polygon(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,real_t p_margin_a,real_t p_margin_b) { const SphereShapeSW *sphere_A = static_cast<const SphereShapeSW*>(p_a); @@ -635,7 +639,7 @@ static void _collision_sphere_convex_polygon(const ShapeSW *p_a,const Transform Vector3 n1=v2-v1; Vector3 n2=v2-v3; - Vector3 axis = n1.cross(n2).cross(n1).normalized();; + Vector3 axis = n1.cross(n2).cross(n1).normalized(); if (!separator.test_axis( axis )) return; @@ -662,7 +666,7 @@ static void _collision_sphere_convex_polygon(const ShapeSW *p_a,const Transform } template<bool withMargin> -static void _collision_sphere_face(const ShapeSW *p_a,const Transform &p_transform_a, const ShapeSW *p_b,const Transform& p_transform_b,_CollectorCallback *p_collector,float p_margin_a,float p_margin_b) { +static void _collision_sphere_face(const ShapeSW *p_a,const Transform &p_transform_a, const ShapeSW *p_b,const Transform& p_transform_b,_CollectorCallback *p_collector,real_t p_margin_a,real_t p_margin_b) { const SphereShapeSW *sphere_A = static_cast<const SphereShapeSW*>(p_a); const FaceShapeSW *face_B = static_cast<const FaceShapeSW*>(p_b); @@ -706,7 +710,7 @@ static void _collision_sphere_face(const ShapeSW *p_a,const Transform &p_transfo template<bool withMargin> -static void _collision_box_box(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,float p_margin_a,float p_margin_b) { +static void _collision_box_box(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,real_t p_margin_a,real_t p_margin_b) { const BoxShapeSW *box_A = static_cast<const BoxShapeSW*>(p_a); @@ -814,7 +818,7 @@ static void _collision_box_box(const ShapeSW *p_a,const Transform &p_transform_a } template<bool withMargin> -static void _collision_box_capsule(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,float p_margin_a,float p_margin_b) { +static void _collision_box_capsule(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,real_t p_margin_a,real_t p_margin_b) { const BoxShapeSW *box_A = static_cast<const BoxShapeSW*>(p_a); const CapsuleShapeSW *capsule_B = static_cast<const CapsuleShapeSW*>(p_b); @@ -914,7 +918,7 @@ static void _collision_box_capsule(const ShapeSW *p_a,const Transform &p_transfo } template<bool withMargin> -static void _collision_box_convex_polygon(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,float p_margin_a,float p_margin_b) { +static void _collision_box_convex_polygon(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,real_t p_margin_a,real_t p_margin_b) { @@ -1042,7 +1046,7 @@ static void _collision_box_convex_polygon(const ShapeSW *p_a,const Transform &p_ template<bool withMargin> -static void _collision_box_face(const ShapeSW *p_a,const Transform &p_transform_a, const ShapeSW *p_b,const Transform& p_transform_b,_CollectorCallback *p_collector,float p_margin_a,float p_margin_b) { +static void _collision_box_face(const ShapeSW *p_a,const Transform &p_transform_a, const ShapeSW *p_b,const Transform& p_transform_b,_CollectorCallback *p_collector,real_t p_margin_a,real_t p_margin_b) { const BoxShapeSW *box_A = static_cast<const BoxShapeSW*>(p_a); @@ -1154,7 +1158,7 @@ static void _collision_box_face(const ShapeSW *p_a,const Transform &p_transform_ template<bool withMargin> -static void _collision_capsule_capsule(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,float p_margin_a,float p_margin_b) { +static void _collision_capsule_capsule(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,real_t p_margin_a,real_t p_margin_b) { const CapsuleShapeSW *capsule_A = static_cast<const CapsuleShapeSW*>(p_a); const CapsuleShapeSW *capsule_B = static_cast<const CapsuleShapeSW*>(p_b); @@ -1212,7 +1216,7 @@ static void _collision_capsule_capsule(const ShapeSW *p_a,const Transform &p_tra } template<bool withMargin> -static void _collision_capsule_convex_polygon(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,float p_margin_a,float p_margin_b) { +static void _collision_capsule_convex_polygon(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,real_t p_margin_a,real_t p_margin_b) { const CapsuleShapeSW *capsule_A = static_cast<const CapsuleShapeSW*>(p_a); @@ -1283,7 +1287,7 @@ static void _collision_capsule_convex_polygon(const ShapeSW *p_a,const Transform template<bool withMargin> -static void _collision_capsule_face(const ShapeSW *p_a,const Transform &p_transform_a, const ShapeSW *p_b,const Transform& p_transform_b,_CollectorCallback *p_collector,float p_margin_a,float p_margin_b) { +static void _collision_capsule_face(const ShapeSW *p_a,const Transform &p_transform_a, const ShapeSW *p_b,const Transform& p_transform_b,_CollectorCallback *p_collector,real_t p_margin_a,real_t p_margin_b) { const CapsuleShapeSW *capsule_A = static_cast<const CapsuleShapeSW*>(p_a); const FaceShapeSW *face_B = static_cast<const FaceShapeSW*>(p_b); @@ -1346,7 +1350,7 @@ static void _collision_capsule_face(const ShapeSW *p_a,const Transform &p_transf template<bool withMargin> -static void _collision_convex_polygon_convex_polygon(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,float p_margin_a,float p_margin_b) { +static void _collision_convex_polygon_convex_polygon(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,real_t p_margin_a,real_t p_margin_b) { const ConvexPolygonShapeSW *convex_polygon_A = static_cast<const ConvexPolygonShapeSW*>(p_a); @@ -1379,7 +1383,7 @@ static void _collision_convex_polygon_convex_polygon(const ShapeSW *p_a,const Tr for (int i=0;i<face_count_A;i++) { Vector3 axis = p_transform_a.xform( faces_A[i].plane ).normal; -// Vector3 axis = p_transform_a.basis.xform( faces_A[i].plane.normal ).normalized(); + //Vector3 axis = p_transform_a.basis.xform( faces_A[i].plane.normal ).normalized(); if (!separator.test_axis( axis )) return; @@ -1389,7 +1393,7 @@ static void _collision_convex_polygon_convex_polygon(const ShapeSW *p_a,const Tr for (int i=0;i<face_count_B;i++) { Vector3 axis = p_transform_b.xform( faces_B[i].plane ).normal; -// Vector3 axis = p_transform_b.basis.xform( faces_B[i].plane.normal ).normalized(); + //Vector3 axis = p_transform_b.basis.xform( faces_B[i].plane.normal ).normalized(); if (!separator.test_axis( axis )) @@ -1470,7 +1474,7 @@ static void _collision_convex_polygon_convex_polygon(const ShapeSW *p_a,const Tr template<bool withMargin> -static void _collision_convex_polygon_face(const ShapeSW *p_a,const Transform &p_transform_a, const ShapeSW *p_b,const Transform& p_transform_b,_CollectorCallback *p_collector,float p_margin_a,float p_margin_b) { +static void _collision_convex_polygon_face(const ShapeSW *p_a,const Transform &p_transform_a, const ShapeSW *p_b,const Transform& p_transform_b,_CollectorCallback *p_collector,real_t p_margin_a,real_t p_margin_b) { const ConvexPolygonShapeSW *convex_polygon_A = static_cast<const ConvexPolygonShapeSW*>(p_a); @@ -1502,7 +1506,7 @@ static void _collision_convex_polygon_face(const ShapeSW *p_a,const Transform &p // faces of A for (int i=0;i<face_count;i++) { -// Vector3 axis = p_transform_a.xform( faces[i].plane ).normal; + //Vector3 axis = p_transform_a.xform( faces[i].plane ).normal; Vector3 axis = p_transform_a.basis.xform( faces[i].plane.normal ).normalized(); if (!separator.test_axis( axis )) @@ -1581,7 +1585,7 @@ static void _collision_convex_polygon_face(const ShapeSW *p_a,const Transform &p } -bool sat_calculate_penetration(const ShapeSW *p_shape_A, const Transform& p_transform_A, const ShapeSW *p_shape_B, const Transform& p_transform_B, CollisionSolverSW::CallbackResult p_result_callback,void *p_userdata,bool p_swap,Vector3* r_prev_axis,float p_margin_a,float p_margin_b) { +bool sat_calculate_penetration(const ShapeSW *p_shape_A, const Transform& p_transform_A, const ShapeSW *p_shape_B, const Transform& p_transform_B, CollisionSolverSW::CallbackResult p_result_callback,void *p_userdata,bool p_swap,Vector3* r_prev_axis,real_t p_margin_a,real_t p_margin_b) { PhysicsServer::ShapeType type_A=p_shape_A->get_type(); @@ -1663,8 +1667,8 @@ bool sat_calculate_penetration(const ShapeSW *p_shape_A, const Transform& p_tran const ShapeSW *B=p_shape_B; const Transform *transform_A=&p_transform_A; const Transform *transform_B=&p_transform_B; - float margin_A=p_margin_a; - float margin_B=p_margin_b; + real_t margin_A=p_margin_a; + real_t margin_B=p_margin_b; if (type_A > type_B) { SWAP(A,B); diff --git a/servers/physics/collision_solver_sat.h b/servers/physics/collision_solver_sat.h index 57f5bdbbc0..15fe7dc34a 100644 --- a/servers/physics/collision_solver_sat.h +++ b/servers/physics/collision_solver_sat.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,6 +32,6 @@ #include "collision_solver_sw.h" -bool sat_calculate_penetration(const ShapeSW *p_shape_A, const Transform& p_transform_A, const ShapeSW *p_shape_B, const Transform& p_transform_B, CollisionSolverSW::CallbackResult p_result_callback,void *p_userdata, bool p_swap=false,Vector3* r_prev_axis=NULL,float p_margin_a=0,float p_margin_b=0); +bool sat_calculate_penetration(const ShapeSW *p_shape_A, const Transform& p_transform_A, const ShapeSW *p_shape_B, const Transform& p_transform_B, CollisionSolverSW::CallbackResult p_result_callback,void *p_userdata, bool p_swap=false,Vector3* r_prev_axis=NULL,real_t p_margin_a=0,real_t p_margin_b=0); #endif // COLLISION_SOLVER_SAT_H diff --git a/servers/physics/collision_solver_sw.cpp b/servers/physics/collision_solver_sw.cpp index 716e724637..f0ddde3a76 100644 --- a/servers/physics/collision_solver_sw.cpp +++ b/servers/physics/collision_solver_sw.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -115,8 +115,8 @@ struct _ConcaveCollisionInfo { int aabb_tests; int collisions; bool tested; - float margin_A; - float margin_B; + real_t margin_A; + real_t margin_B; Vector3 close_A,close_B; }; @@ -136,7 +136,7 @@ void CollisionSolverSW::concave_callback(void *p_userdata, ShapeSW *p_convex) { } -bool CollisionSolverSW::solve_concave(const ShapeSW *p_shape_A,const Transform& p_transform_A,const ShapeSW *p_shape_B,const Transform& p_transform_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result,float p_margin_A,float p_margin_B) { +bool CollisionSolverSW::solve_concave(const ShapeSW *p_shape_A,const Transform& p_transform_A,const ShapeSW *p_shape_B,const Transform& p_transform_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result,real_t p_margin_A,real_t p_margin_B) { const ConcaveShapeSW *concave_B=static_cast<const ConcaveShapeSW*>(p_shape_B); @@ -160,14 +160,14 @@ bool CollisionSolverSW::solve_concave(const ShapeSW *p_shape_A,const Transform& //quickly compute a local AABB - AABB local_aabb; + Rect3 local_aabb; for(int i=0;i<3;i++) { Vector3 axis( p_transform_B.basis.get_axis(i) ); - float axis_scale = 1.0/axis.length(); + real_t axis_scale = 1.0/axis.length(); axis*=axis_scale; - float smin,smax; + real_t smin,smax; p_shape_A->project_range(axis,rel_transform,smin,smax); smin-=p_margin_A; smax+=p_margin_A; @@ -186,7 +186,7 @@ bool CollisionSolverSW::solve_concave(const ShapeSW *p_shape_A,const Transform& } -bool CollisionSolverSW::solve_static(const ShapeSW *p_shape_A,const Transform& p_transform_A,const ShapeSW *p_shape_B,const Transform& p_transform_B,CallbackResult p_result_callback,void *p_userdata,Vector3 *r_sep_axis,float p_margin_A,float p_margin_B) { +bool CollisionSolverSW::solve_static(const ShapeSW *p_shape_A,const Transform& p_transform_A,const ShapeSW *p_shape_B,const Transform& p_transform_B,CallbackResult p_result_callback,void *p_userdata,Vector3 *r_sep_axis,real_t p_margin_A,real_t p_margin_B) { PhysicsServer::ShapeType type_A=p_shape_A->get_type(); @@ -291,7 +291,7 @@ bool CollisionSolverSW::solve_distance_plane(const ShapeSW *p_shape_A,const Tran bool collided=false; Vector3 closest; - float closest_d; + real_t closest_d; for(int i=0;i<support_count;i++) { @@ -313,7 +313,7 @@ bool CollisionSolverSW::solve_distance_plane(const ShapeSW *p_shape_A,const Tran return collided; } -bool CollisionSolverSW::solve_distance(const ShapeSW *p_shape_A,const Transform& p_transform_A,const ShapeSW *p_shape_B,const Transform& p_transform_B,Vector3& r_point_A,Vector3& r_point_B,const AABB& p_concave_hint,Vector3 *r_sep_axis) { +bool CollisionSolverSW::solve_distance(const ShapeSW *p_shape_A,const Transform& p_transform_A,const ShapeSW *p_shape_B,const Transform& p_transform_B,Vector3& r_point_A,Vector3& r_point_B,const Rect3& p_concave_hint,Vector3 *r_sep_axis) { if (p_shape_A->is_concave()) return false; @@ -351,21 +351,21 @@ bool CollisionSolverSW::solve_distance(const ShapeSW *p_shape_A,const Transform& //quickly compute a local AABB - bool use_cc_hint=p_concave_hint!=AABB(); - AABB cc_hint_aabb; + bool use_cc_hint=p_concave_hint!=Rect3(); + Rect3 cc_hint_aabb; if (use_cc_hint) { cc_hint_aabb=p_concave_hint; cc_hint_aabb.pos-=p_transform_B.origin; } - AABB local_aabb; + Rect3 local_aabb; for(int i=0;i<3;i++) { Vector3 axis( p_transform_B.basis.get_axis(i) ); - float axis_scale = 1.0/axis.length(); + real_t axis_scale = ((real_t)1.0)/axis.length(); axis*=axis_scale; - float smin,smax; + real_t smin,smax; if (use_cc_hint) { cc_hint_aabb.project_range_in_plane(Plane(axis,0),smin,smax); @@ -383,7 +383,7 @@ bool CollisionSolverSW::solve_distance(const ShapeSW *p_shape_A,const Transform& concave_B->cull(local_aabb,concave_distance_callback,&cinfo); if (!cinfo.collided) { -// print_line(itos(cinfo.tested)); + //print_line(itos(cinfo.tested)); r_point_A=cinfo.close_A; r_point_B=cinfo.close_B; diff --git a/servers/physics/collision_solver_sw.h b/servers/physics/collision_solver_sw.h index abc50cae2c..b8d37a8a96 100644 --- a/servers/physics/collision_solver_sw.h +++ b/servers/physics/collision_solver_sw.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -40,15 +40,15 @@ private: static void concave_callback(void *p_userdata, ShapeSW *p_convex); static bool solve_static_plane(const ShapeSW *p_shape_A,const Transform& p_transform_A,const ShapeSW *p_shape_B,const Transform& p_transform_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result); static bool solve_ray(const ShapeSW *p_shape_A,const Transform& p_transform_A,const ShapeSW *p_shape_B,const Transform& p_transform_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result); - static bool solve_concave(const ShapeSW *p_shape_A,const Transform& p_transform_A,const ShapeSW *p_shape_B,const Transform& p_transform_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result,float p_margin_A=0,float p_margin_B=0); + static bool solve_concave(const ShapeSW *p_shape_A,const Transform& p_transform_A,const ShapeSW *p_shape_B,const Transform& p_transform_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result,real_t p_margin_A=0,real_t p_margin_B=0); static void concave_distance_callback(void *p_userdata, ShapeSW *p_convex); static bool solve_distance_plane(const ShapeSW *p_shape_A,const Transform& p_transform_A,const ShapeSW *p_shape_B,const Transform& p_transform_B,Vector3& r_point_A,Vector3& r_point_B); public: - static bool solve_static(const ShapeSW *p_shape_A,const Transform& p_transform_A,const ShapeSW *p_shape_B,const Transform& p_transform_B,CallbackResult p_result_callback,void *p_userdata,Vector3 *r_sep_axis=NULL,float p_margin_A=0,float p_margin_B=0); - static bool solve_distance(const ShapeSW *p_shape_A,const Transform& p_transform_A,const ShapeSW *p_shape_B,const Transform& p_transform_B,Vector3& r_point_A,Vector3& r_point_B,const AABB& p_concave_hint,Vector3 *r_sep_axis=NULL); + static bool solve_static(const ShapeSW *p_shape_A,const Transform& p_transform_A,const ShapeSW *p_shape_B,const Transform& p_transform_B,CallbackResult p_result_callback,void *p_userdata,Vector3 *r_sep_axis=NULL,real_t p_margin_A=0,real_t p_margin_B=0); + static bool solve_distance(const ShapeSW *p_shape_A,const Transform& p_transform_A,const ShapeSW *p_shape_B,const Transform& p_transform_B,Vector3& r_point_A,Vector3& r_point_B,const Rect3& p_concave_hint,Vector3 *r_sep_axis=NULL); }; diff --git a/servers/physics/constraint_sw.h b/servers/physics/constraint_sw.h index d61701ac07..f5bbe4bbd0 100644 --- a/servers/physics/constraint_sw.h +++ b/servers/physics/constraint_sw.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,7 +31,7 @@ #include "body_sw.h" -class ConstraintSW { +class ConstraintSW : public RID_Data { BodySW **_body_ptr; int _body_count; @@ -67,8 +67,8 @@ public: _FORCE_INLINE_ int get_priority() const { return priority; } - virtual bool setup(float p_step)=0; - virtual void solve(float p_step)=0; + virtual bool setup(real_t p_step)=0; + virtual void solve(real_t p_step)=0; virtual ~ConstraintSW() {} }; diff --git a/servers/physics/gjk_epa.cpp b/servers/physics/gjk_epa.cpp index 71d6fee2ab..92ca5ea8dd 100644 --- a/servers/physics/gjk_epa.cpp +++ b/servers/physics/gjk_epa.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/servers/physics/gjk_epa.h b/servers/physics/gjk_epa.h index 78afd3149f..58cf8f50ce 100644 --- a/servers/physics/gjk_epa.h +++ b/servers/physics/gjk_epa.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/servers/physics/joints/SCsub b/servers/physics/joints/SCsub index d31af2c1c4..ccc76e823f 100644 --- a/servers/physics/joints/SCsub +++ b/servers/physics/joints/SCsub @@ -1,5 +1,7 @@ +#!/usr/bin/env python + Import('env') -env.add_source_files(env.servers_sources,"*.cpp") +env.add_source_files(env.servers_sources, "*.cpp") Export('env') diff --git a/servers/physics/joints/cone_twist_joint_sw.cpp b/servers/physics/joints/cone_twist_joint_sw.cpp index 5f1dde4e20..d78bcbd16d 100644 --- a/servers/physics/joints/cone_twist_joint_sw.cpp +++ b/servers/physics/joints/cone_twist_joint_sw.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -96,7 +96,7 @@ ConeTwistJointSW::ConeTwistJointSW(BodySW* rbA,BodySW* rbB,const Transform& rbAF } -bool ConeTwistJointSW::setup(float p_step) { +bool ConeTwistJointSW::setup(real_t p_step) { m_appliedImpulse = real_t(0.); //set bias, sign, clear accumulator @@ -128,10 +128,10 @@ bool ConeTwistJointSW::setup(float p_step) { for (int i=0;i<3;i++) { memnew_placement(&m_jac[i], JacobianEntrySW( - A->get_transform().basis.transposed(), - B->get_transform().basis.transposed(), - pivotAInW - A->get_transform().origin, - pivotBInW - B->get_transform().origin, + A->get_principal_inertia_axes().transposed(), + B->get_principal_inertia_axes().transposed(), + pivotAInW - A->get_transform().origin - A->get_center_of_mass(), + pivotBInW - B->get_transform().origin - B->get_center_of_mass(), normal[i], A->get_inv_inertia(), A->get_inv_mass(), @@ -156,7 +156,7 @@ bool ConeTwistJointSW::setup(float p_step) { if (m_swingSpan1 >= real_t(0.05f)) { b1Axis2 = A->get_transform().basis.xform( this->m_rbAFrame.basis.get_axis(1) ); -// swing1 = btAtan2Fast( b2Axis1.dot(b1Axis2),b2Axis1.dot(b1Axis1) ); + //swing1 = btAtan2Fast( b2Axis1.dot(b1Axis2),b2Axis1.dot(b1Axis1) ); swx = b2Axis1.dot(b1Axis1); swy = b2Axis1.dot(b1Axis2); swing1 = atan2fast(swy, swx); @@ -169,7 +169,7 @@ bool ConeTwistJointSW::setup(float p_step) { if (m_swingSpan2 >= real_t(0.05f)) { b1Axis3 = A->get_transform().basis.xform( this->m_rbAFrame.basis.get_axis(2) ); -// swing2 = btAtan2Fast( b2Axis1.dot(b1Axis3),b2Axis1.dot(b1Axis1) ); + //swing2 = btAtan2Fast( b2Axis1.dot(b1Axis3),b2Axis1.dot(b1Axis1) ); swx = b2Axis1.dot(b1Axis1); swy = b2Axis1.dot(b1Axis3); swing2 = atan2fast(swy, swx); @@ -318,7 +318,7 @@ void ConeTwistJointSW::solve(real_t timeStep) } -void ConeTwistJointSW::set_param(PhysicsServer::ConeTwistJointParam p_param, float p_value) { +void ConeTwistJointSW::set_param(PhysicsServer::ConeTwistJointParam p_param, real_t p_value) { switch(p_param) { case PhysicsServer::CONE_TWIST_JOINT_SWING_SPAN: { @@ -345,7 +345,7 @@ void ConeTwistJointSW::set_param(PhysicsServer::ConeTwistJointParam p_param, flo } } -float ConeTwistJointSW::get_param(PhysicsServer::ConeTwistJointParam p_param) const{ +real_t ConeTwistJointSW::get_param(PhysicsServer::ConeTwistJointParam p_param) const{ switch(p_param) { case PhysicsServer::CONE_TWIST_JOINT_SWING_SPAN: { diff --git a/servers/physics/joints/cone_twist_joint_sw.h b/servers/physics/joints/cone_twist_joint_sw.h index 653259071d..eb7a5cd1b1 100644 --- a/servers/physics/joints/cone_twist_joint_sw.h +++ b/servers/physics/joints/cone_twist_joint_sw.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -109,8 +109,8 @@ public: virtual PhysicsServer::JointType get_type() const { return PhysicsServer::JOINT_CONE_TWIST; } - virtual bool setup(float p_step); - virtual void solve(float p_step); + virtual bool setup(real_t p_step); + virtual void solve(real_t p_step); ConeTwistJointSW(BodySW* rbA,BodySW* rbB,const Transform& rbAFrame, const Transform& rbBFrame); @@ -146,8 +146,8 @@ public: return m_twistLimitSign; } - void set_param(PhysicsServer::ConeTwistJointParam p_param, float p_value); - float get_param(PhysicsServer::ConeTwistJointParam p_param) const; + void set_param(PhysicsServer::ConeTwistJointParam p_param, real_t p_value); + real_t get_param(PhysicsServer::ConeTwistJointParam p_param) const; }; diff --git a/servers/physics/joints/generic_6dof_joint_sw.cpp b/servers/physics/joints/generic_6dof_joint_sw.cpp index 06015a5228..bd07f3122a 100644 --- a/servers/physics/joints/generic_6dof_joint_sw.cpp +++ b/servers/physics/joints/generic_6dof_joint_sw.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -38,55 +38,6 @@ See corresponding header file for licensing info. #define GENERIC_D6_DISABLE_WARMSTARTING 1 -real_t btGetMatrixElem(const Matrix3& mat, int index); -real_t btGetMatrixElem(const Matrix3& mat, int index) -{ - int i = index%3; - int j = index/3; - return mat[i][j]; -} - -///MatrixToEulerXYZ from http://www.geometrictools.com/LibFoundation/Mathematics/Wm4Matrix3.inl.html -bool matrixToEulerXYZ(const Matrix3& mat,Vector3& xyz); -bool matrixToEulerXYZ(const Matrix3& mat,Vector3& xyz) -{ -// // rot = cy*cz -cy*sz sy -// // cz*sx*sy+cx*sz cx*cz-sx*sy*sz -cy*sx -// // -cx*cz*sy+sx*sz cz*sx+cx*sy*sz cx*cy -// - - if (btGetMatrixElem(mat,2) < real_t(1.0)) - { - if (btGetMatrixElem(mat,2) > real_t(-1.0)) - { - xyz[0] = Math::atan2(-btGetMatrixElem(mat,5),btGetMatrixElem(mat,8)); - xyz[1] = Math::asin(btGetMatrixElem(mat,2)); - xyz[2] = Math::atan2(-btGetMatrixElem(mat,1),btGetMatrixElem(mat,0)); - return true; - } - else - { - // WARNING. Not unique. XA - ZA = -atan2(r10,r11) - xyz[0] = -Math::atan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,4)); - xyz[1] = -Math_PI*0.5; - xyz[2] = real_t(0.0); - return false; - } - } - else - { - // WARNING. Not unique. XAngle + ZAngle = atan2(r10,r11) - xyz[0] = Math::atan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,4)); - xyz[1] = Math_PI*0.5; - xyz[2] = 0.0; - - } - - - return false; -} - - //////////////////////////// G6DOFRotationalLimitMotorSW //////////////////////////////////// @@ -296,9 +247,9 @@ Generic6DOFJointSW::Generic6DOFJointSW(BodySW* rbA, BodySW* rbB, const Transform void Generic6DOFJointSW::calculateAngleInfo() { - Matrix3 relative_frame = m_calculatedTransformA.basis.inverse()*m_calculatedTransformB.basis; + Basis relative_frame = m_calculatedTransformA.basis.inverse()*m_calculatedTransformB.basis; - matrixToEulerXYZ(relative_frame,m_calculatedAxisAngleDiff); + m_calculatedAxisAngleDiff = relative_frame.get_euler(); @@ -325,16 +276,18 @@ void Generic6DOFJointSW::calculateAngleInfo() m_calculatedAxis[2] = axis0.cross(m_calculatedAxis[1]); -// if(m_debugDrawer) -// { -// -// char buff[300]; -// sprintf(buff,"\n X: %.2f ; Y: %.2f ; Z: %.2f ", -// m_calculatedAxisAngleDiff[0], -// m_calculatedAxisAngleDiff[1], -// m_calculatedAxisAngleDiff[2]); -// m_debugDrawer->reportErrorWarning(buff); -// } + /* + if(m_debugDrawer) + { + + char buff[300]; + sprintf(buff,"\n X: %.2f ; Y: %.2f ; Z: %.2f ", + m_calculatedAxisAngleDiff[0], + m_calculatedAxisAngleDiff[1], + m_calculatedAxisAngleDiff[2]); + m_debugDrawer->reportErrorWarning(buff); + } + */ } @@ -352,10 +305,10 @@ void Generic6DOFJointSW::buildLinearJacobian( const Vector3 & pivotAInW,const Vector3 & pivotBInW) { memnew_placement(&jacLinear, JacobianEntrySW( - A->get_transform().basis.transposed(), - B->get_transform().basis.transposed(), - pivotAInW - A->get_transform().origin, - pivotBInW - B->get_transform().origin, + A->get_principal_inertia_axes().transposed(), + B->get_principal_inertia_axes().transposed(), + pivotAInW - A->get_transform().origin - A->get_center_of_mass(), + pivotBInW - B->get_transform().origin - B->get_center_of_mass(), normalWorld, A->get_inv_inertia(), A->get_inv_mass(), @@ -368,8 +321,8 @@ void Generic6DOFJointSW::buildAngularJacobian( JacobianEntrySW & jacAngular,const Vector3 & jointAxisW) { memnew_placement(&jacAngular, JacobianEntrySW(jointAxisW, - A->get_transform().basis.transposed(), - B->get_transform().basis.transposed(), + A->get_principal_inertia_axes().transposed(), + B->get_principal_inertia_axes().transposed(), A->get_inv_inertia(), B->get_inv_inertia())); @@ -384,7 +337,7 @@ bool Generic6DOFJointSW::testAngularLimitMotor(int axis_index) return m_angularLimits[axis_index].needApplyTorques(); } -bool Generic6DOFJointSW::setup(float p_step) { +bool Generic6DOFJointSW::setup(real_t p_step) { // Clear accumulated impulses for the next simulation step m_linearLimits.m_accumulatedImpulse=Vector3(real_t(0.), real_t(0.), real_t(0.)); @@ -440,7 +393,7 @@ bool Generic6DOFJointSW::setup(float p_step) { } -void Generic6DOFJointSW::solve(real_t timeStep) +void Generic6DOFJointSW::solve(real_t timeStep) { m_timeStep = timeStep; @@ -530,7 +483,7 @@ void Generic6DOFJointSW::calcAnchorPos(void) } // Generic6DOFJointSW::calcAnchorPos() -void Generic6DOFJointSW::set_param(Vector3::Axis p_axis,PhysicsServer::G6DOFJointAxisParam p_param, float p_value) { +void Generic6DOFJointSW::set_param(Vector3::Axis p_axis,PhysicsServer::G6DOFJointAxisParam p_param, real_t p_value) { ERR_FAIL_INDEX(p_axis,3); switch(p_param) { @@ -606,7 +559,7 @@ void Generic6DOFJointSW::set_param(Vector3::Axis p_axis,PhysicsServer::G6DOFJoin } } -float Generic6DOFJointSW::get_param(Vector3::Axis p_axis,PhysicsServer::G6DOFJointAxisParam p_param) const{ +real_t Generic6DOFJointSW::get_param(Vector3::Axis p_axis,PhysicsServer::G6DOFJointAxisParam p_param) const{ ERR_FAIL_INDEX_V(p_axis,3,0); switch(p_param) { case PhysicsServer::G6DOF_JOINT_LINEAR_LOWER_LIMIT: { @@ -675,7 +628,7 @@ float Generic6DOFJointSW::get_param(Vector3::Axis p_axis,PhysicsServer::G6DOFJoi } break; case PhysicsServer::G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT: { - return m_angularLimits[p_axis].m_maxLimitForce; + return m_angularLimits[p_axis].m_maxMotorForce; } break; } diff --git a/servers/physics/joints/generic_6dof_joint_sw.h b/servers/physics/joints/generic_6dof_joint_sw.h index 47ef43156d..207ae85a45 100644 --- a/servers/physics/joints/generic_6dof_joint_sw.h +++ b/servers/physics/joints/generic_6dof_joint_sw.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -295,8 +295,8 @@ public: virtual PhysicsServer::JointType get_type() const { return PhysicsServer::JOINT_6DOF; } - virtual bool setup(float p_step); - virtual void solve(float p_step); + virtual bool setup(real_t p_step); + virtual void solve(real_t p_step); //! Calcs global transform of the offsets @@ -449,8 +449,8 @@ public: virtual void calcAnchorPos(void); // overridable - void set_param(Vector3::Axis p_axis,PhysicsServer::G6DOFJointAxisParam p_param, float p_value); - float get_param(Vector3::Axis p_axis,PhysicsServer::G6DOFJointAxisParam p_param) const; + void set_param(Vector3::Axis p_axis,PhysicsServer::G6DOFJointAxisParam p_param, real_t p_value); + real_t get_param(Vector3::Axis p_axis,PhysicsServer::G6DOFJointAxisParam p_param) const; void set_flag(Vector3::Axis p_axis,PhysicsServer::G6DOFJointAxisFlag p_flag, bool p_value); bool get_flag(Vector3::Axis p_axis,PhysicsServer::G6DOFJointAxisFlag p_flag) const; diff --git a/servers/physics/joints/hinge_joint_sw.cpp b/servers/physics/joints/hinge_joint_sw.cpp index 035407065c..9617eb8794 100644 --- a/servers/physics/joints/hinge_joint_sw.cpp +++ b/servers/physics/joints/hinge_joint_sw.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -112,7 +112,7 @@ HingeJointSW::HingeJointSW(BodySW* rbA,BodySW* rbB, const Vector3& pivotInA,cons rbAxisA1 = rbAxisA2.cross(axisInA); } - m_rbAFrame.basis=Matrix3( rbAxisA1.x,rbAxisA2.x,axisInA.x, + m_rbAFrame.basis=Basis( rbAxisA1.x,rbAxisA2.x,axisInA.x, rbAxisA1.y,rbAxisA2.y,axisInA.y, rbAxisA1.z,rbAxisA2.z,axisInA.z ); @@ -121,7 +121,7 @@ HingeJointSW::HingeJointSW(BodySW* rbA,BodySW* rbB, const Vector3& pivotInA,cons Vector3 rbAxisB2 = axisInB.cross(rbAxisB1); m_rbBFrame.origin = pivotInB; - m_rbBFrame.basis=Matrix3( rbAxisB1.x,rbAxisB2.x,-axisInB.x, + m_rbBFrame.basis=Basis( rbAxisB1.x,rbAxisB2.x,-axisInB.x, rbAxisB1.y,rbAxisB2.y,-axisInB.y, rbAxisB1.z,rbAxisB2.z,-axisInB.z ); @@ -148,7 +148,7 @@ HingeJointSW::HingeJointSW(BodySW* rbA,BodySW* rbB, const Vector3& pivotInA,cons -bool HingeJointSW::setup(float p_step) { +bool HingeJointSW::setup(real_t p_step) { m_appliedImpulse = real_t(0.); @@ -173,10 +173,10 @@ bool HingeJointSW::setup(float p_step) { for (int i=0;i<3;i++) { memnew_placement(&m_jac[i], JacobianEntrySW( - A->get_transform().basis.transposed(), - B->get_transform().basis.transposed(), - pivotAInW - A->get_transform().origin, - pivotBInW - B->get_transform().origin, + A->get_principal_inertia_axes().transposed(), + B->get_principal_inertia_axes().transposed(), + pivotAInW - A->get_transform().origin - A->get_center_of_mass(), + pivotBInW - B->get_transform().origin - B->get_center_of_mass(), normal[i], A->get_inv_inertia(), A->get_inv_mass(), @@ -200,20 +200,20 @@ bool HingeJointSW::setup(float p_step) { Vector3 hingeAxisWorld = A->get_transform().basis.xform( m_rbAFrame.basis.get_axis(2) ); memnew_placement(&m_jacAng[0], JacobianEntrySW(jointAxis0, - A->get_transform().basis.transposed(), - B->get_transform().basis.transposed(), + A->get_principal_inertia_axes().transposed(), + B->get_principal_inertia_axes().transposed(), A->get_inv_inertia(), B->get_inv_inertia())); memnew_placement(&m_jacAng[1], JacobianEntrySW(jointAxis1, - A->get_transform().basis.transposed(), - B->get_transform().basis.transposed(), + A->get_principal_inertia_axes().transposed(), + B->get_principal_inertia_axes().transposed(), A->get_inv_inertia(), B->get_inv_inertia())); memnew_placement(&m_jacAng[2], JacobianEntrySW(hingeAxisWorld, - A->get_transform().basis.transposed(), - B->get_transform().basis.transposed(), + A->get_principal_inertia_axes().transposed(), + B->get_principal_inertia_axes().transposed(), A->get_inv_inertia(), B->get_inv_inertia())); @@ -221,7 +221,7 @@ bool HingeJointSW::setup(float p_step) { // Compute limit information real_t hingeAngle = get_hinge_angle(); -// print_line("angle: "+rtos(hingeAngle)); + //print_line("angle: "+rtos(hingeAngle)); //set bias, sign, clear accumulator m_correction = real_t(0.); m_limitSign = real_t(0.); @@ -235,17 +235,17 @@ bool HingeJointSW::setup(float p_step) { print_line("hi: "+rtos(m_upperLimit)); }*/ -// if (m_lowerLimit < m_upperLimit) + //if (m_lowerLimit < m_upperLimit) if (m_useLimit && m_lowerLimit <= m_upperLimit) { -// if (hingeAngle <= m_lowerLimit*m_limitSoftness) + //if (hingeAngle <= m_lowerLimit*m_limitSoftness) if (hingeAngle <= m_lowerLimit) { m_correction = (m_lowerLimit - hingeAngle); m_limitSign = 1.0f; m_solveLimit = true; } -// else if (hingeAngle >= m_upperLimit*m_limitSoftness) + //else if (hingeAngle >= m_upperLimit*m_limitSoftness) else if (hingeAngle >= m_upperLimit) { m_correction = m_upperLimit - hingeAngle; @@ -262,7 +262,7 @@ bool HingeJointSW::setup(float p_step) { return true; } -void HingeJointSW::solve(float p_step) { +void HingeJointSW::solve(real_t p_step) { Vector3 pivotAInW = A->get_transform().xform(m_rbAFrame.origin); Vector3 pivotBInW = B->get_transform().xform(m_rbBFrame.origin); @@ -371,7 +371,7 @@ void HingeJointSW::solve(float p_step) { real_t desiredMotorVel = m_motorTargetVelocity; real_t motor_relvel = desiredMotorVel - projRelVel; - real_t unclippedMotorImpulse = m_kHinge * motor_relvel;; + real_t unclippedMotorImpulse = m_kHinge * motor_relvel; //todo: should clip against accumulated impulse real_t clippedMotorImpulse = unclippedMotorImpulse > m_maxMotorImpulse ? m_maxMotorImpulse : unclippedMotorImpulse; clippedMotorImpulse = clippedMotorImpulse < -m_maxMotorImpulse ? -m_maxMotorImpulse : clippedMotorImpulse; @@ -418,7 +418,7 @@ real_t HingeJointSW::get_hinge_angle() { } -void HingeJointSW::set_param(PhysicsServer::HingeJointParam p_param, float p_value) { +void HingeJointSW::set_param(PhysicsServer::HingeJointParam p_param, real_t p_value) { switch (p_param) { @@ -434,7 +434,7 @@ void HingeJointSW::set_param(PhysicsServer::HingeJointParam p_param, float p_val } } -float HingeJointSW::get_param(PhysicsServer::HingeJointParam p_param) const{ +real_t HingeJointSW::get_param(PhysicsServer::HingeJointParam p_param) const{ switch (p_param) { diff --git a/servers/physics/joints/hinge_joint_sw.h b/servers/physics/joints/hinge_joint_sw.h index f87c2ac4c5..8469fd1ca0 100644 --- a/servers/physics/joints/hinge_joint_sw.h +++ b/servers/physics/joints/hinge_joint_sw.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -103,13 +103,13 @@ public: virtual PhysicsServer::JointType get_type() const { return PhysicsServer::JOINT_HINGE; } - virtual bool setup(float p_step); - virtual void solve(float p_step); + virtual bool setup(real_t p_step); + virtual void solve(real_t p_step); real_t get_hinge_angle(); - void set_param(PhysicsServer::HingeJointParam p_param, float p_value); - float get_param(PhysicsServer::HingeJointParam p_param) const; + void set_param(PhysicsServer::HingeJointParam p_param, real_t p_value); + real_t get_param(PhysicsServer::HingeJointParam p_param) const; void set_flag(PhysicsServer::HingeJointFlag p_flag, bool p_value); bool get_flag(PhysicsServer::HingeJointFlag p_flag) const; diff --git a/servers/physics/joints/jacobian_entry_sw.h b/servers/physics/joints/jacobian_entry_sw.h index b7ab58f16b..cd85162ba5 100644 --- a/servers/physics/joints/jacobian_entry_sw.h +++ b/servers/physics/joints/jacobian_entry_sw.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -56,8 +56,8 @@ public: JacobianEntrySW() {}; //constraint between two different rigidbodies JacobianEntrySW( - const Matrix3& world2A, - const Matrix3& world2B, + const Basis& world2A, + const Basis& world2B, const Vector3& rel_pos1,const Vector3& rel_pos2, const Vector3& jointAxis, const Vector3& inertiaInvA, @@ -77,8 +77,8 @@ public: //angular constraint between two different rigidbodies JacobianEntrySW(const Vector3& jointAxis, - const Matrix3& world2A, - const Matrix3& world2B, + const Basis& world2A, + const Basis& world2B, const Vector3& inertiaInvA, const Vector3& inertiaInvB) :m_linearJointAxis(Vector3(real_t(0.),real_t(0.),real_t(0.))) @@ -110,7 +110,7 @@ public: //constraint on one rigidbody JacobianEntrySW( - const Matrix3& world2A, + const Basis& world2A, const Vector3& rel_pos1,const Vector3& rel_pos2, const Vector3& jointAxis, const Vector3& inertiaInvA, diff --git a/servers/physics/joints/pin_joint_sw.cpp b/servers/physics/joints/pin_joint_sw.cpp index 013d750b4f..b545ae630b 100644 --- a/servers/physics/joints/pin_joint_sw.cpp +++ b/servers/physics/joints/pin_joint_sw.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -34,7 +34,7 @@ See corresponding header file for licensing info. #include "pin_joint_sw.h" -bool PinJointSW::setup(float p_step) { +bool PinJointSW::setup(real_t p_step) { m_appliedImpulse = real_t(0.); @@ -44,10 +44,10 @@ bool PinJointSW::setup(float p_step) { { normal[i] = 1; memnew_placement(&m_jac[i],JacobianEntrySW( - A->get_transform().basis.transposed(), - B->get_transform().basis.transposed(), - A->get_transform().xform(m_pivotInA) - A->get_transform().origin, - B->get_transform().xform(m_pivotInB) - B->get_transform().origin, + A->get_principal_inertia_axes().transposed(), + B->get_principal_inertia_axes().transposed(), + A->get_transform().xform(m_pivotInA) - A->get_transform().origin - A->get_center_of_mass(), + B->get_transform().xform(m_pivotInB) - B->get_transform().origin - B->get_center_of_mass(), normal, A->get_inv_inertia(), A->get_inv_mass(), @@ -59,7 +59,7 @@ bool PinJointSW::setup(float p_step) { return true; } -void PinJointSW::solve(float p_step){ +void PinJointSW::solve(real_t p_step){ Vector3 pivotAInW = A->get_transform().xform(m_pivotInA); Vector3 pivotBInW = B->get_transform().xform(m_pivotInB); @@ -68,8 +68,8 @@ void PinJointSW::solve(float p_step){ Vector3 normal(0,0,0); -// Vector3 angvelA = A->get_transform().origin.getBasis().transpose() * A->getAngularVelocity(); -// Vector3 angvelB = B->get_transform().origin.getBasis().transpose() * B->getAngularVelocity(); + //Vector3 angvelA = A->get_transform().origin.getBasis().transpose() * A->getAngularVelocity(); + //Vector3 angvelB = B->get_transform().origin.getBasis().transpose() * B->getAngularVelocity(); for (int i=0;i<3;i++) { @@ -116,7 +116,7 @@ void PinJointSW::solve(float p_step){ } } -void PinJointSW::set_param(PhysicsServer::PinJointParam p_param,float p_value) { +void PinJointSW::set_param(PhysicsServer::PinJointParam p_param,real_t p_value) { switch(p_param) { case PhysicsServer::PIN_JOINT_BIAS: m_tau=p_value; break; @@ -125,7 +125,7 @@ void PinJointSW::set_param(PhysicsServer::PinJointParam p_param,float p_value) { } } -float PinJointSW::get_param(PhysicsServer::PinJointParam p_param) const{ +real_t PinJointSW::get_param(PhysicsServer::PinJointParam p_param) const{ switch(p_param) { case PhysicsServer::PIN_JOINT_BIAS: return m_tau; diff --git a/servers/physics/joints/pin_joint_sw.h b/servers/physics/joints/pin_joint_sw.h index 4ef134fe73..b72b21219d 100644 --- a/servers/physics/joints/pin_joint_sw.h +++ b/servers/physics/joints/pin_joint_sw.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -79,11 +79,11 @@ public: virtual PhysicsServer::JointType get_type() const { return PhysicsServer::JOINT_PIN; } - virtual bool setup(float p_step); - virtual void solve(float p_step); + virtual bool setup(real_t p_step); + virtual void solve(real_t p_step); - void set_param(PhysicsServer::PinJointParam p_param,float p_value); - float get_param(PhysicsServer::PinJointParam p_param) const; + void set_param(PhysicsServer::PinJointParam p_param,real_t p_value); + real_t get_param(PhysicsServer::PinJointParam p_param) const; void set_pos_A(const Vector3& p_pos) { m_pivotInA=p_pos; } void set_pos_B(const Vector3& p_pos) { m_pivotInB=p_pos; } diff --git a/servers/physics/joints/slider_joint_sw.cpp b/servers/physics/joints/slider_joint_sw.cpp index a9072e5de3..fc728ed0ba 100644 --- a/servers/physics/joints/slider_joint_sw.cpp +++ b/servers/physics/joints/slider_joint_sw.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -112,7 +112,7 @@ SliderJointSW::SliderJointSW(BodySW* rbA, BodySW* rbB, const Transform& frameInA //----------------------------------------------------------------------------- -bool SliderJointSW::setup(float p_step) +bool SliderJointSW::setup(real_t p_step) { //calculate transforms @@ -132,10 +132,10 @@ bool SliderJointSW::setup(float p_step) { normalWorld = m_calculatedTransformA.basis.get_axis(i); memnew_placement(&m_jacLin[i], JacobianEntrySW( - A->get_transform().basis.transposed(), - B->get_transform().basis.transposed(), - m_relPosA, - m_relPosB, + A->get_principal_inertia_axes().transposed(), + B->get_principal_inertia_axes().transposed(), + m_relPosA - A->get_center_of_mass(), + m_relPosB - B->get_center_of_mass(), normalWorld, A->get_inv_inertia(), A->get_inv_mass(), @@ -152,8 +152,8 @@ bool SliderJointSW::setup(float p_step) normalWorld = m_calculatedTransformA.basis.get_axis(i); memnew_placement(&m_jacAng[i], JacobianEntrySW( normalWorld, - A->get_transform().basis.transposed(), - B->get_transform().basis.transposed(), + A->get_principal_inertia_axes().transposed(), + B->get_principal_inertia_axes().transposed(), A->get_inv_inertia(), B->get_inv_inertia() )); @@ -406,7 +406,7 @@ Vector3 SliderJointSW::getAncorInB(void) return ancorInB; } // SliderJointSW::getAncorInB(); -void SliderJointSW::set_param(PhysicsServer::SliderJointParam p_param, float p_value) { +void SliderJointSW::set_param(PhysicsServer::SliderJointParam p_param, real_t p_value) { switch(p_param) { case PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_UPPER: m_upperLinLimit=p_value; break; @@ -437,7 +437,7 @@ void SliderJointSW::set_param(PhysicsServer::SliderJointParam p_param, float p_v } -float SliderJointSW::get_param(PhysicsServer::SliderJointParam p_param) const { +real_t SliderJointSW::get_param(PhysicsServer::SliderJointParam p_param) const { switch(p_param) { case PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_UPPER: return m_upperLinLimit; diff --git a/servers/physics/joints/slider_joint_sw.h b/servers/physics/joints/slider_joint_sw.h index 9ee6c83800..d01038df59 100644 --- a/servers/physics/joints/slider_joint_sw.h +++ b/servers/physics/joints/slider_joint_sw.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -237,11 +237,11 @@ public: Vector3 getAncorInA(void); Vector3 getAncorInB(void); - void set_param(PhysicsServer::SliderJointParam p_param, float p_value); - float get_param(PhysicsServer::SliderJointParam p_param) const; + void set_param(PhysicsServer::SliderJointParam p_param, real_t p_value); + real_t get_param(PhysicsServer::SliderJointParam p_param) const; - bool setup(float p_step); - void solve(float p_step); + bool setup(real_t p_step); + void solve(real_t p_step); virtual PhysicsServer::JointType get_type() const { return PhysicsServer::JOINT_SLIDER; } diff --git a/servers/physics/joints_sw.h b/servers/physics/joints_sw.h index b54c655ea1..c87c86b599 100644 --- a/servers/physics/joints_sw.h +++ b/servers/physics/joints_sw.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/servers/physics/physics_server_sw.cpp b/servers/physics/physics_server_sw.cpp index 6c098a6df2..67e3b27852 100644 --- a/servers/physics/physics_server_sw.cpp +++ b/servers/physics/physics_server_sw.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -727,7 +727,7 @@ uint32_t PhysicsServerSW::body_get_user_flags(RID p_body, uint32_t p_flags) cons return 0; }; -void PhysicsServerSW::body_set_param(RID p_body, BodyParameter p_param, float p_value) { +void PhysicsServerSW::body_set_param(RID p_body, BodyParameter p_param, real_t p_value) { BodySW *body = body_owner.get(p_body); ERR_FAIL_COND(!body); @@ -735,7 +735,7 @@ void PhysicsServerSW::body_set_param(RID p_body, BodyParameter p_param, float p_ body->set_param(p_param,p_value); }; -float PhysicsServerSW::body_get_param(RID p_body, BodyParameter p_param) const { +real_t PhysicsServerSW::body_get_param(RID p_body, BodyParameter p_param) const { BodySW *body = body_owner.get(p_body); ERR_FAIL_COND_V(!body,0); @@ -805,6 +805,15 @@ void PhysicsServerSW::body_apply_impulse(RID p_body, const Vector3& p_pos, const body->wakeup(); }; +void PhysicsServerSW::body_apply_torque_impulse(RID p_body, const Vector3& p_impulse) { + + BodySW *body = body_owner.get(p_body); + ERR_FAIL_COND(!body); + + body->apply_torque_impulse(p_impulse); + body->wakeup(); +}; + void PhysicsServerSW::body_set_axis_velocity(RID p_body, const Vector3& p_axis_velocity) { BodySW *body = body_owner.get(p_body); @@ -870,14 +879,14 @@ void PhysicsServerSW::body_get_collision_exceptions(RID p_body, List<RID> *p_exc }; -void PhysicsServerSW::body_set_contacts_reported_depth_treshold(RID p_body, float p_treshold) { +void PhysicsServerSW::body_set_contacts_reported_depth_treshold(RID p_body, real_t p_treshold) { BodySW *body = body_owner.get(p_body); ERR_FAIL_COND(!body); }; -float PhysicsServerSW::body_get_contacts_reported_depth_treshold(RID p_body) const { +real_t PhysicsServerSW::body_get_contacts_reported_depth_treshold(RID p_body) const { BodySW *body = body_owner.get(p_body); ERR_FAIL_COND_V(!body,0); @@ -962,7 +971,7 @@ RID PhysicsServerSW::joint_create_pin(RID p_body_A,const Vector3& p_local_A,RID return rid; } -void PhysicsServerSW::pin_joint_set_param(RID p_joint,PinJointParam p_param, float p_value){ +void PhysicsServerSW::pin_joint_set_param(RID p_joint,PinJointParam p_param, real_t p_value){ JointSW *joint = joint_owner.get(p_joint); ERR_FAIL_COND(!joint); @@ -971,7 +980,7 @@ void PhysicsServerSW::pin_joint_set_param(RID p_joint,PinJointParam p_param, flo pin_joint->set_param(p_param,p_value); } -float PhysicsServerSW::pin_joint_get_param(RID p_joint,PinJointParam p_param) const{ +real_t PhysicsServerSW::pin_joint_get_param(RID p_joint,PinJointParam p_param) const{ JointSW *joint = joint_owner.get(p_joint); ERR_FAIL_COND_V(!joint,0); @@ -1065,7 +1074,7 @@ RID PhysicsServerSW::joint_create_hinge_simple(RID p_body_A,const Vector3& p_piv } -void PhysicsServerSW::hinge_joint_set_param(RID p_joint,HingeJointParam p_param, float p_value){ +void PhysicsServerSW::hinge_joint_set_param(RID p_joint,HingeJointParam p_param, real_t p_value){ JointSW *joint = joint_owner.get(p_joint); ERR_FAIL_COND(!joint); @@ -1074,7 +1083,7 @@ void PhysicsServerSW::hinge_joint_set_param(RID p_joint,HingeJointParam p_param, hinge_joint->set_param(p_param,p_value); } -float PhysicsServerSW::hinge_joint_get_param(RID p_joint,HingeJointParam p_param) const{ +real_t PhysicsServerSW::hinge_joint_get_param(RID p_joint,HingeJointParam p_param) const{ JointSW *joint = joint_owner.get(p_joint); ERR_FAIL_COND_V(!joint,0); @@ -1145,7 +1154,7 @@ RID PhysicsServerSW::joint_create_slider(RID p_body_A,const Transform& p_local_f return rid; } -void PhysicsServerSW::slider_joint_set_param(RID p_joint,SliderJointParam p_param, float p_value){ +void PhysicsServerSW::slider_joint_set_param(RID p_joint,SliderJointParam p_param, real_t p_value){ JointSW *joint = joint_owner.get(p_joint); ERR_FAIL_COND(!joint); @@ -1153,7 +1162,7 @@ void PhysicsServerSW::slider_joint_set_param(RID p_joint,SliderJointParam p_para SliderJointSW *slider_joint = static_cast<SliderJointSW*>(joint); slider_joint->set_param(p_param,p_value); } -float PhysicsServerSW::slider_joint_get_param(RID p_joint,SliderJointParam p_param) const{ +real_t PhysicsServerSW::slider_joint_get_param(RID p_joint,SliderJointParam p_param) const{ JointSW *joint = joint_owner.get(p_joint); ERR_FAIL_COND_V(!joint,0); @@ -1184,7 +1193,7 @@ RID PhysicsServerSW::joint_create_cone_twist(RID p_body_A,const Transform& p_loc return rid; } -void PhysicsServerSW::cone_twist_joint_set_param(RID p_joint,ConeTwistJointParam p_param, float p_value) { +void PhysicsServerSW::cone_twist_joint_set_param(RID p_joint,ConeTwistJointParam p_param, real_t p_value) { JointSW *joint = joint_owner.get(p_joint); ERR_FAIL_COND(!joint); @@ -1192,7 +1201,7 @@ void PhysicsServerSW::cone_twist_joint_set_param(RID p_joint,ConeTwistJointParam ConeTwistJointSW *cone_twist_joint = static_cast<ConeTwistJointSW*>(joint); cone_twist_joint->set_param(p_param,p_value); } -float PhysicsServerSW::cone_twist_joint_get_param(RID p_joint,ConeTwistJointParam p_param) const { +real_t PhysicsServerSW::cone_twist_joint_get_param(RID p_joint,ConeTwistJointParam p_param) const { JointSW *joint = joint_owner.get(p_joint); ERR_FAIL_COND_V(!joint,0); @@ -1223,7 +1232,7 @@ RID PhysicsServerSW::joint_create_generic_6dof(RID p_body_A,const Transform& p_l return rid; } -void PhysicsServerSW::generic_6dof_joint_set_param(RID p_joint,Vector3::Axis p_axis,G6DOFJointAxisParam p_param, float p_value){ +void PhysicsServerSW::generic_6dof_joint_set_param(RID p_joint,Vector3::Axis p_axis,G6DOFJointAxisParam p_param, real_t p_value){ JointSW *joint = joint_owner.get(p_joint); ERR_FAIL_COND(!joint); @@ -1231,7 +1240,7 @@ void PhysicsServerSW::generic_6dof_joint_set_param(RID p_joint,Vector3::Axis p_a Generic6DOFJointSW *generic_6dof_joint = static_cast<Generic6DOFJointSW*>(joint); generic_6dof_joint->set_param(p_axis,p_param,p_value); } -float PhysicsServerSW::generic_6dof_joint_get_param(RID p_joint,Vector3::Axis p_axis,G6DOFJointAxisParam p_param){ +real_t PhysicsServerSW::generic_6dof_joint_get_param(RID p_joint,Vector3::Axis p_axis,G6DOFJointAxisParam p_param){ JointSW *joint = joint_owner.get(p_joint); ERR_FAIL_COND_V(!joint,0); @@ -1386,11 +1395,13 @@ void PhysicsServerSW::free(RID p_rid) { BodySW *body = body_owner.get(p_rid); -// if (body->get_state_query()) -// _clear_query(body->get_state_query()); + /* + if (body->get_state_query()) + _clear_query(body->get_state_query()); -// if (body->get_direct_state_query()) -// _clear_query(body->get_direct_state_query()); + if (body->get_direct_state_query()) + _clear_query(body->get_direct_state_query()); + */ body->set_space(NULL); @@ -1413,8 +1424,10 @@ void PhysicsServerSW::free(RID p_rid) { AreaSW *area = area_owner.get(p_rid); -// if (area->get_monitor_query()) -// _clear_query(area->get_monitor_query()); + /* + if (area->get_monitor_query()) + _clear_query(area->get_monitor_query()); + */ area->set_space(NULL); @@ -1475,7 +1488,7 @@ void PhysicsServerSW::init() { }; -void PhysicsServerSW::step(float p_step) { +void PhysicsServerSW::step(real_t p_step) { if (!active) @@ -1598,11 +1611,11 @@ void PhysicsServerSW::_shape_col_cbk(const Vector3& p_point_A,const Vector3& p_p if (cbk->amount == cbk->max) { //find least deep - float min_depth=1e20; + real_t min_depth=1e20; int min_depth_idx=0; for(int i=0;i<cbk->amount;i++) { - float d = cbk->ptr[i*2+0].distance_squared_to(cbk->ptr[i*2+1]); + real_t d = cbk->ptr[i*2+0].distance_squared_to(cbk->ptr[i*2+1]); if (d<min_depth) { min_depth=d; min_depth_idx=i; @@ -1610,7 +1623,7 @@ void PhysicsServerSW::_shape_col_cbk(const Vector3& p_point_A,const Vector3& p_p } - float d = p_point_A.distance_squared_to(p_point_B); + real_t d = p_point_A.distance_squared_to(p_point_B); if (d<min_depth) return; cbk->ptr[min_depth_idx*2+0]=p_point_A; diff --git a/servers/physics/physics_server_sw.h b/servers/physics/physics_server_sw.h index 59eeeb42a7..6e20474350 100644 --- a/servers/physics/physics_server_sw.h +++ b/servers/physics/physics_server_sw.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -39,7 +39,7 @@ class PhysicsServerSW : public PhysicsServer { - OBJ_TYPE( PhysicsServerSW, PhysicsServer ); + GDCLASS( PhysicsServerSW, PhysicsServer ); friend class PhysicsDirectSpaceStateSW; bool active; @@ -62,7 +62,7 @@ friend class PhysicsDirectSpaceStateSW; mutable RID_Owner<BodySW> body_owner; mutable RID_Owner<JointSW> joint_owner; -// void _clear_query(QuerySW *p_query); + //void _clear_query(QuerySW *p_query); public: struct CollCbkData { @@ -180,8 +180,8 @@ public: virtual void body_set_user_flags(RID p_body, uint32_t p_flags); virtual uint32_t body_get_user_flags(RID p_body, uint32_t p_flags) const; - virtual void body_set_param(RID p_body, BodyParameter p_param, float p_value); - virtual float body_get_param(RID p_body, BodyParameter p_param) const; + virtual void body_set_param(RID p_body, BodyParameter p_param, real_t p_value); + virtual real_t body_get_param(RID p_body, BodyParameter p_param) const; virtual void body_set_state(RID p_body, BodyState p_state, const Variant& p_variant); virtual Variant body_get_state(RID p_body, BodyState p_state) const; @@ -193,6 +193,7 @@ public: virtual Vector3 body_get_applied_torque(RID p_body) const; virtual void body_apply_impulse(RID p_body, const Vector3& p_pos, const Vector3& p_impulse); + virtual void body_apply_torque_impulse(RID p_body, const Vector3& p_impulse); virtual void body_set_axis_velocity(RID p_body, const Vector3& p_axis_velocity); virtual void body_set_axis_lock(RID p_body,BodyAxisLock p_lock); @@ -202,8 +203,8 @@ public: virtual void body_remove_collision_exception(RID p_body, RID p_body_b); virtual void body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions); - virtual void body_set_contacts_reported_depth_treshold(RID p_body, float p_treshold); - virtual float body_get_contacts_reported_depth_treshold(RID p_body) const; + virtual void body_set_contacts_reported_depth_treshold(RID p_body, real_t p_treshold); + virtual real_t body_get_contacts_reported_depth_treshold(RID p_body) const; virtual void body_set_omit_force_integration(RID p_body,bool p_omit); virtual bool body_is_omitting_force_integration(RID p_body) const; @@ -220,8 +221,8 @@ public: virtual RID joint_create_pin(RID p_body_A,const Vector3& p_local_A,RID p_body_B,const Vector3& p_local_B); - virtual void pin_joint_set_param(RID p_joint,PinJointParam p_param, float p_value); - virtual float pin_joint_get_param(RID p_joint,PinJointParam p_param) const; + virtual void pin_joint_set_param(RID p_joint,PinJointParam p_param, real_t p_value); + virtual real_t pin_joint_get_param(RID p_joint,PinJointParam p_param) const; virtual void pin_joint_set_local_A(RID p_joint, const Vector3& p_A); virtual Vector3 pin_joint_get_local_A(RID p_joint) const; @@ -232,8 +233,8 @@ public: virtual RID joint_create_hinge(RID p_body_A,const Transform& p_frame_A,RID p_body_B,const Transform& p_frame_B); virtual RID joint_create_hinge_simple(RID p_body_A,const Vector3& p_pivot_A,const Vector3& p_axis_A,RID p_body_B,const Vector3& p_pivot_B,const Vector3& p_axis_B); - virtual void hinge_joint_set_param(RID p_joint,HingeJointParam p_param, float p_value); - virtual float hinge_joint_get_param(RID p_joint,HingeJointParam p_param) const; + virtual void hinge_joint_set_param(RID p_joint,HingeJointParam p_param, real_t p_value); + virtual real_t hinge_joint_get_param(RID p_joint,HingeJointParam p_param) const; virtual void hinge_joint_set_flag(RID p_joint,HingeJointFlag p_flag, bool p_value); virtual bool hinge_joint_get_flag(RID p_joint,HingeJointFlag p_flag) const; @@ -241,18 +242,18 @@ public: virtual RID joint_create_slider(RID p_body_A,const Transform& p_local_frame_A,RID p_body_B,const Transform& p_local_frame_B); //reference frame is A - virtual void slider_joint_set_param(RID p_joint,SliderJointParam p_param, float p_value); - virtual float slider_joint_get_param(RID p_joint,SliderJointParam p_param) const; + virtual void slider_joint_set_param(RID p_joint,SliderJointParam p_param, real_t p_value); + virtual real_t slider_joint_get_param(RID p_joint,SliderJointParam p_param) const; virtual RID joint_create_cone_twist(RID p_body_A,const Transform& p_local_frame_A,RID p_body_B,const Transform& p_local_frame_B); //reference frame is A - virtual void cone_twist_joint_set_param(RID p_joint,ConeTwistJointParam p_param, float p_value); - virtual float cone_twist_joint_get_param(RID p_joint,ConeTwistJointParam p_param) const; + virtual void cone_twist_joint_set_param(RID p_joint,ConeTwistJointParam p_param, real_t p_value); + virtual real_t cone_twist_joint_get_param(RID p_joint,ConeTwistJointParam p_param) const; virtual RID joint_create_generic_6dof(RID p_body_A,const Transform& p_local_frame_A,RID p_body_B,const Transform& p_local_frame_B); //reference frame is A - virtual void generic_6dof_joint_set_param(RID p_joint,Vector3::Axis,G6DOFJointAxisParam p_param, float p_value); - virtual float generic_6dof_joint_get_param(RID p_joint,Vector3::Axis,G6DOFJointAxisParam p_param); + virtual void generic_6dof_joint_set_param(RID p_joint,Vector3::Axis,G6DOFJointAxisParam p_param, real_t p_value); + virtual real_t generic_6dof_joint_get_param(RID p_joint,Vector3::Axis,G6DOFJointAxisParam p_param); virtual void generic_6dof_joint_set_flag(RID p_joint,Vector3::Axis,G6DOFJointAxisFlag p_flag, bool p_enable); virtual bool generic_6dof_joint_get_flag(RID p_joint,Vector3::Axis,G6DOFJointAxisFlag p_flag); @@ -280,7 +281,7 @@ public: virtual void set_active(bool p_active); virtual void init(); - virtual void step(float p_step); + virtual void step(real_t p_step); virtual void sync(); virtual void flush_queries(); virtual void finish(); diff --git a/servers/physics/shape_sw.cpp b/servers/physics/shape_sw.cpp index 1d4914c945..10500a306f 100644 --- a/servers/physics/shape_sw.cpp +++ b/servers/physics/shape_sw.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -35,7 +35,7 @@ #define _FACE_IS_VALID_SUPPORT_TRESHOLD 0.9998 -void ShapeSW::configure(const AABB& p_aabb) { +void ShapeSW::configure(const Rect3& p_aabb) { aabb=p_aabb; configured=true; for (Map<ShapeOwnerSW*,int>::Element *E=owners.front();E;E=E->next()) { @@ -125,7 +125,7 @@ bool PlaneShapeSW::intersect_segment(const Vector3& p_begin,const Vector3& p_end return inters; } -Vector3 PlaneShapeSW::get_moment_of_inertia(float p_mass) const { +Vector3 PlaneShapeSW::get_moment_of_inertia(real_t p_mass) const { return Vector3(); //wtf } @@ -133,7 +133,7 @@ Vector3 PlaneShapeSW::get_moment_of_inertia(float p_mass) const { void PlaneShapeSW::_setup(const Plane& p_plane) { plane=p_plane; - configure(AABB(Vector3(-1e4,-1e4,-1e4),Vector3(1e4*2,1e4*2,1e4*2))); + configure(Rect3(Vector3(-1e4,-1e4,-1e4),Vector3(1e4*2,1e4*2,1e4*2))); } void PlaneShapeSW::set_data(const Variant& p_data) { @@ -154,7 +154,7 @@ PlaneShapeSW::PlaneShapeSW() { // -float RayShapeSW::get_length() const { +real_t RayShapeSW::get_length() const { return length; } @@ -196,15 +196,15 @@ bool RayShapeSW::intersect_segment(const Vector3& p_begin,const Vector3& p_end,V return false; //simply not possible } -Vector3 RayShapeSW::get_moment_of_inertia(float p_mass) const { +Vector3 RayShapeSW::get_moment_of_inertia(real_t p_mass) const { return Vector3(); } -void RayShapeSW::_setup(float p_length) { +void RayShapeSW::_setup(real_t p_length) { length=p_length; - configure(AABB(Vector3(0,0,0),Vector3(0.1,0.1,length))); + configure(Rect3(Vector3(0,0,0),Vector3(0.1,0.1,length))); } void RayShapeSW::set_data(const Variant& p_data) { @@ -234,11 +234,11 @@ real_t SphereShapeSW::get_radius() const { void SphereShapeSW::project_range(const Vector3& p_normal, const Transform& p_transform, real_t &r_min, real_t &r_max) const { - float d = p_normal.dot( p_transform.origin ); + real_t d = p_normal.dot( p_transform.origin ); // figure out scale at point Vector3 local_normal = p_transform.basis.xform_inv(p_normal); - float scale = local_normal.length(); + real_t scale = local_normal.length(); r_min = d - (radius) * scale; r_max = d + (radius) * scale; @@ -261,9 +261,9 @@ bool SphereShapeSW::intersect_segment(const Vector3& p_begin,const Vector3& p_en return Geometry::segment_intersects_sphere(p_begin,p_end,Vector3(),radius,&r_result,&r_normal); } -Vector3 SphereShapeSW::get_moment_of_inertia(float p_mass) const { +Vector3 SphereShapeSW::get_moment_of_inertia(real_t p_mass) const { - float s = 0.4 * p_mass * radius * radius; + real_t s = 0.4 * p_mass * radius * radius; return Vector3(s,s,s); } @@ -271,7 +271,7 @@ void SphereShapeSW::_setup(real_t p_radius) { radius=p_radius; - configure(AABB( Vector3(-radius,-radius,-radius), Vector3(radius*2.0,radius*2.0,radius*2.0))); + configure(Rect3( Vector3(-radius,-radius,-radius), Vector3(radius*2.0,radius*2.0,radius*2.0))); } @@ -299,8 +299,8 @@ void BoxShapeSW::project_range(const Vector3& p_normal, const Transform& p_trans // no matter the angle, the box is mirrored anyway Vector3 local_normal=p_transform.basis.xform_inv(p_normal); - float length = local_normal.abs().dot(half_extents); - float distance = p_normal.dot( p_transform.origin ); + real_t length = local_normal.abs().dot(half_extents); + real_t distance = p_normal.dot( p_transform.origin ); r_min = distance - length; r_max = distance + length; @@ -329,7 +329,7 @@ void BoxShapeSW::get_supports(const Vector3& p_normal,int p_max,Vector3 *r_suppo Vector3 axis; axis[i]=1.0; - float dot = p_normal.dot( axis ); + real_t dot = p_normal.dot( axis ); if ( Math::abs( dot ) > _FACE_IS_VALID_SUPPORT_TRESHOLD ) { //Vector3 axis_b; @@ -343,7 +343,7 @@ void BoxShapeSW::get_supports(const Vector3& p_normal,int p_max,Vector3 *r_suppo int i_n=next[i]; int i_n2=next2[i]; - static const float sign[4][2]={ + static const real_t sign[4][2]={ {-1.0, 1.0}, { 1.0, 1.0}, @@ -412,17 +412,17 @@ void BoxShapeSW::get_supports(const Vector3& p_normal,int p_max,Vector3 *r_suppo bool BoxShapeSW::intersect_segment(const Vector3& p_begin,const Vector3& p_end,Vector3 &r_result, Vector3 &r_normal) const { - AABB aabb(-half_extents,half_extents*2.0); + Rect3 aabb(-half_extents,half_extents*2.0); return aabb.intersects_segment(p_begin,p_end,&r_result,&r_normal); } -Vector3 BoxShapeSW::get_moment_of_inertia(float p_mass) const { +Vector3 BoxShapeSW::get_moment_of_inertia(real_t p_mass) const { - float lx=half_extents.x; - float ly=half_extents.y; - float lz=half_extents.z; + real_t lx=half_extents.x; + real_t ly=half_extents.y; + real_t lz=half_extents.z; return Vector3( (p_mass/3.0) * (ly*ly + lz*lz), (p_mass/3.0) * (lx*lx + lz*lz), (p_mass/3.0) * (lx*lx + ly*ly) ); @@ -432,7 +432,7 @@ void BoxShapeSW::_setup(const Vector3& p_half_extents) { half_extents=p_half_extents.abs(); - configure(AABB(-half_extents,half_extents*2)); + configure(Rect3(-half_extents,half_extents*2)); } @@ -460,7 +460,7 @@ BoxShapeSW::BoxShapeSW() { void CapsuleShapeSW::project_range(const Vector3& p_normal, const Transform& p_transform, real_t &r_min, real_t &r_max) const { Vector3 n=p_transform.basis.xform_inv(p_normal).normalized(); - float h = (n.z > 0) ? height : -height; + real_t h = (n.z > 0) ? height : -height; n *= radius; n.z += h * 0.5; @@ -471,8 +471,8 @@ void CapsuleShapeSW::project_range(const Vector3& p_normal, const Transform& p_t n = p_transform.basis.xform(n); - float distance = p_normal.dot( p_transform.origin ); - float length = Math::abs(p_normal.dot(n)); + real_t distance = p_normal.dot( p_transform.origin ); + real_t length = Math::abs(p_normal.dot(n)); r_min = distance - length; r_max = distance + length; @@ -484,7 +484,7 @@ Vector3 CapsuleShapeSW::get_support(const Vector3& p_normal) const { Vector3 n=p_normal; - float h = (n.z > 0) ? height : -height; + real_t h = (n.z > 0) ? height : -height; n*=radius; n.z += h*0.5; @@ -496,7 +496,7 @@ void CapsuleShapeSW::get_supports(const Vector3& p_normal,int p_max,Vector3 *r_s Vector3 n=p_normal; - float d = n.z; + real_t d = n.z; if (Math::abs( d )<_EDGE_IS_VALID_SUPPORT_TRESHOLD ) { @@ -513,7 +513,7 @@ void CapsuleShapeSW::get_supports(const Vector3& p_normal,int p_max,Vector3 *r_s } else { - float h = (d > 0) ? height : -height; + real_t h = (d > 0) ? height : -height; n*=radius; n.z += h*0.5; @@ -528,7 +528,7 @@ void CapsuleShapeSW::get_supports(const Vector3& p_normal,int p_max,Vector3 *r_s bool CapsuleShapeSW::intersect_segment(const Vector3& p_begin,const Vector3& p_end,Vector3 &r_result, Vector3 &r_normal) const { Vector3 norm=(p_end-p_begin).normalized(); - float min_d=1e20; + real_t min_d=1e20; Vector3 res,n; @@ -542,7 +542,7 @@ bool CapsuleShapeSW::intersect_segment(const Vector3& p_begin,const Vector3& p_e collided = Geometry::segment_intersects_cylinder(p_begin,p_end,height,radius,&auxres,&auxn); if (collided) { - float d=norm.dot(auxres); + real_t d=norm.dot(auxres); if (d<min_d) { min_d=d; res=auxres; @@ -554,7 +554,7 @@ bool CapsuleShapeSW::intersect_segment(const Vector3& p_begin,const Vector3& p_e collided = Geometry::segment_intersects_sphere(p_begin,p_end,Vector3(0,0,height*0.5),radius,&auxres,&auxn); if (collided) { - float d=norm.dot(auxres); + real_t d=norm.dot(auxres); if (d<min_d) { min_d=d; res=auxres; @@ -566,7 +566,7 @@ bool CapsuleShapeSW::intersect_segment(const Vector3& p_begin,const Vector3& p_e collided = Geometry::segment_intersects_sphere(p_begin,p_end,Vector3(0,0,height*-0.5),radius,&auxres,&auxn); if (collided) { - float d=norm.dot(auxres); + real_t d=norm.dot(auxres); if (d<min_d) { min_d=d; @@ -584,7 +584,7 @@ bool CapsuleShapeSW::intersect_segment(const Vector3& p_begin,const Vector3& p_e return collision; } -Vector3 CapsuleShapeSW::get_moment_of_inertia(float p_mass) const { +Vector3 CapsuleShapeSW::get_moment_of_inertia(real_t p_mass) const { // use crappy AABB approximation Vector3 extents=get_aabb().size*0.5; @@ -604,7 +604,7 @@ void CapsuleShapeSW::_setup(real_t p_height,real_t p_radius) { height=p_height; radius=p_radius; - configure(AABB(Vector3(-radius,-radius,-height*0.5-radius),Vector3(radius*2,radius*2,height+radius*2.0))); + configure(Rect3(Vector3(-radius,-radius,-height*0.5-radius),Vector3(radius*2,radius*2,height+radius*2.0))); } @@ -647,7 +647,7 @@ void ConvexPolygonShapeSW::project_range(const Vector3& p_normal, const Transfor for (int i=0;i<vertex_count;i++) { - float d=p_normal.dot( p_transform.xform( vrts[i] ) ); + real_t d=p_normal.dot( p_transform.xform( vrts[i] ) ); if (i==0 || d > r_max) r_max=d; @@ -661,7 +661,7 @@ Vector3 ConvexPolygonShapeSW::get_support(const Vector3& p_normal) const { Vector3 n=p_normal; int vert_support_idx=-1; - float support_max; + real_t support_max; int vertex_count=mesh.vertices.size(); if (vertex_count==0) @@ -671,7 +671,7 @@ Vector3 ConvexPolygonShapeSW::get_support(const Vector3& p_normal) const { for (int i=0;i<vertex_count;i++) { - float d=n.dot(vrts[i]); + real_t d=n.dot(vrts[i]); if (i==0 || d > support_max) { support_max=d; @@ -702,7 +702,7 @@ void ConvexPolygonShapeSW::get_supports(const Vector3& p_normal,int p_max,Vector for (int i=0;i<vc;i++) { - float d=p_normal.dot(vertices[i]); + real_t d=p_normal.dot(vertices[i]); if (i==0 || d > max) { max=d; @@ -742,7 +742,7 @@ void ConvexPolygonShapeSW::get_supports(const Vector3& p_normal,int p_max,Vector for(int i=0;i<ec;i++) { - float dot=(vertices[edges[i].a]-vertices[edges[i].b]).normalized().dot(p_normal); + real_t dot=(vertices[edges[i].a]-vertices[edges[i].b]).normalized().dot(p_normal); dot=ABS(dot); if (dot < _EDGE_IS_VALID_SUPPORT_TRESHOLD && (edges[i].a==vtx || edges[i].b==vtx)) { @@ -768,7 +768,7 @@ bool ConvexPolygonShapeSW::intersect_segment(const Vector3& p_begin,const Vector const Vector3 *vertices = mesh.vertices.ptr(); Vector3 n = p_end-p_begin; - float min = 1e20; + real_t min = 1e20; bool col=false; for(int i=0;i<fc;i++) { @@ -784,7 +784,7 @@ bool ConvexPolygonShapeSW::intersect_segment(const Vector3& p_begin,const Vector Face3 f(vertices[ind[0]],vertices[ind[j]],vertices[ind[j+1]]); Vector3 result; if (f.intersects_segment(p_begin,p_end,&result)) { - float d = n.dot(result); + real_t d = n.dot(result); if (d<min) { min=d; r_result=result; @@ -802,7 +802,7 @@ bool ConvexPolygonShapeSW::intersect_segment(const Vector3& p_begin,const Vector } -Vector3 ConvexPolygonShapeSW::get_moment_of_inertia(float p_mass) const { +Vector3 ConvexPolygonShapeSW::get_moment_of_inertia(real_t p_mass) const { // use crappy AABB approximation Vector3 extents=get_aabb().size*0.5; @@ -818,7 +818,7 @@ Vector3 ConvexPolygonShapeSW::get_moment_of_inertia(float p_mass) const { void ConvexPolygonShapeSW::_setup(const Vector<Vector3>& p_vertices) { Error err = QuickHull::build(p_vertices,mesh); - AABB _aabb; + Rect3 _aabb; for(int i=0;i<mesh.vertices.size();i++) { @@ -859,7 +859,7 @@ void FaceShapeSW::project_range(const Vector3& p_normal, const Transform& p_tran for (int i=0;i<3;i++) { Vector3 v=p_transform.xform(vertex[i]); - float d=p_normal.dot(v); + real_t d=p_normal.dot(v); if (i==0 || d > r_max) r_max=d; @@ -873,11 +873,11 @@ Vector3 FaceShapeSW::get_support(const Vector3& p_normal) const { int vert_support_idx=-1; - float support_max; + real_t support_max; for (int i=0;i<3;i++) { - float d=p_normal.dot(vertex[i]); + real_t d=p_normal.dot(vertex[i]); if (i==0 || d > support_max) { support_max=d; @@ -907,11 +907,11 @@ void FaceShapeSW::get_supports(const Vector3& p_normal,int p_max,Vector3 *r_supp /** FIND SUPPORT VERTEX **/ int vert_support_idx=-1; - float support_max; + real_t support_max; for (int i=0;i<3;i++) { - float d=n.dot(vertex[i]); + real_t d=n.dot(vertex[i]); if (i==0 || d > support_max) { support_max=d; @@ -928,7 +928,7 @@ void FaceShapeSW::get_supports(const Vector3& p_normal,int p_max,Vector3 *r_supp continue; // check if edge is valid as a support - float dot=(vertex[i]-vertex[nx]).normalized().dot(n); + real_t dot=(vertex[i]-vertex[nx]).normalized().dot(n); dot=ABS(dot); if (dot < _EDGE_IS_VALID_SUPPORT_TRESHOLD) { @@ -957,7 +957,7 @@ bool FaceShapeSW::intersect_segment(const Vector3& p_begin,const Vector3& p_end, return c; } -Vector3 FaceShapeSW::get_moment_of_inertia(float p_mass) const { +Vector3 FaceShapeSW::get_moment_of_inertia(real_t p_mass) const { return Vector3(); // Sorry, but i don't think anyone cares, FaceShape! @@ -965,16 +965,16 @@ Vector3 FaceShapeSW::get_moment_of_inertia(float p_mass) const { FaceShapeSW::FaceShapeSW() { - configure(AABB()); + configure(Rect3()); } -DVector<Vector3> ConcavePolygonShapeSW::get_faces() const { +PoolVector<Vector3> ConcavePolygonShapeSW::get_faces() const { - DVector<Vector3> rfaces; + PoolVector<Vector3> rfaces; rfaces.resize(faces.size()*3); for(int i=0;i<faces.size();i++) { @@ -998,12 +998,12 @@ void ConcavePolygonShapeSW::project_range(const Vector3& p_normal, const Transfo r_max=0; return; } - DVector<Vector3>::Read r=vertices.read(); + PoolVector<Vector3>::Read r=vertices.read(); const Vector3 *vptr=r.ptr(); for (int i=0;i<count;i++) { - float d=p_normal.dot( p_transform.xform( vptr[i] ) ); + real_t d=p_normal.dot( p_transform.xform( vptr[i] ) ); if (i==0 || d > r_max) r_max=d; @@ -1020,17 +1020,17 @@ Vector3 ConcavePolygonShapeSW::get_support(const Vector3& p_normal) const { if (count==0) return Vector3(); - DVector<Vector3>::Read r=vertices.read(); + PoolVector<Vector3>::Read r=vertices.read(); const Vector3 *vptr=r.ptr(); Vector3 n=p_normal; int vert_support_idx=-1; - float support_max; + real_t support_max; for (int i=0;i<count;i++) { - float d=n.dot(vptr[i]); + real_t d=n.dot(vptr[i]); if (i==0 || d > support_max) { support_max=d; @@ -1048,8 +1048,10 @@ void ConcavePolygonShapeSW::_cull_segment(int p_idx,_SegmentCullParams *p_params const BVH *bvh=&p_params->bvh[p_idx]; - //if (p_params->dir.dot(bvh->aabb.get_support(-p_params->dir))>p_params->min_d) - // return; //test against whole AABB, which isn't very costly + /* + if (p_params->dir.dot(bvh->aabb.get_support(-p_params->dir))>p_params->min_d) + return; //test against whole AABB, which isn't very costly + */ //printf("addr: %p\n",bvh); @@ -1078,7 +1080,7 @@ void ConcavePolygonShapeSW::_cull_segment(int p_idx,_SegmentCullParams *p_params &res)) { - float d=p_params->dir.dot(res) - p_params->dir.dot(p_params->from); + real_t d=p_params->dir.dot(res) - p_params->dir.dot(p_params->from); //TODO, seems segmen/triangle intersection is broken :( if (d>0 && d<p_params->min_d) { @@ -1111,9 +1113,9 @@ bool ConcavePolygonShapeSW::intersect_segment(const Vector3& p_begin,const Vecto return false; // unlock data - DVector<Face>::Read fr=faces.read(); - DVector<Vector3>::Read vr=vertices.read(); - DVector<BVH>::Read br=bvh.read(); + PoolVector<Face>::Read fr=faces.read(); + PoolVector<Vector3>::Read vr=vertices.read(); + PoolVector<BVH>::Read br=bvh.read(); _SegmentCullParams params; @@ -1175,18 +1177,18 @@ void ConcavePolygonShapeSW::_cull(int p_idx,_CullParams *p_params) const { } } -void ConcavePolygonShapeSW::cull(const AABB& p_local_aabb,Callback p_callback,void* p_userdata) const { +void ConcavePolygonShapeSW::cull(const Rect3& p_local_aabb,Callback p_callback,void* p_userdata) const { // make matrix local to concave if (faces.size()==0) return; - AABB local_aabb=p_local_aabb; + Rect3 local_aabb=p_local_aabb; // unlock data - DVector<Face>::Read fr=faces.read(); - DVector<Vector3>::Read vr=vertices.read(); - DVector<BVH>::Read br=bvh.read(); + PoolVector<Face>::Read fr=faces.read(); + PoolVector<Vector3>::Read vr=vertices.read(); + PoolVector<BVH>::Read br=bvh.read(); FaceShapeSW face; // use this to send in the callback @@ -1204,7 +1206,7 @@ void ConcavePolygonShapeSW::cull(const AABB& p_local_aabb,Callback p_callback,vo } -Vector3 ConcavePolygonShapeSW::get_moment_of_inertia(float p_mass) const { +Vector3 ConcavePolygonShapeSW::get_moment_of_inertia(real_t p_mass) const { // use crappy AABB approximation Vector3 extents=get_aabb().size*0.5; @@ -1219,7 +1221,7 @@ Vector3 ConcavePolygonShapeSW::get_moment_of_inertia(float p_mass) const { struct _VolumeSW_BVH_Element { - AABB aabb; + Rect3 aabb; Vector3 center; int face_index; }; @@ -1251,7 +1253,7 @@ struct _VolumeSW_BVH_CompareZ { struct _VolumeSW_BVH { - AABB aabb; + Rect3 aabb; _VolumeSW_BVH *left; _VolumeSW_BVH *right; @@ -1276,7 +1278,7 @@ _VolumeSW_BVH* _volume_sw_build_bvh(_VolumeSW_BVH_Element *p_elements,int p_size bvh->face_index=-1; } - AABB aabb; + Rect3 aabb; for(int i=0;i<p_size;i++) { if (i==0) @@ -1309,7 +1311,7 @@ _VolumeSW_BVH* _volume_sw_build_bvh(_VolumeSW_BVH_Element *p_elements,int p_size bvh->left=_volume_sw_build_bvh(p_elements,split,count); bvh->right=_volume_sw_build_bvh(&p_elements[split],p_size-split,count); -// printf("branch at %p - %i: %i\n",bvh,count,bvh->face_index); + //printf("branch at %p - %i: %i\n",bvh,count,bvh->face_index); count++; return bvh; } @@ -1322,7 +1324,7 @@ void ConcavePolygonShapeSW::_fill_bvh(_VolumeSW_BVH* p_bvh_tree,BVH* p_bvh_array p_bvh_array[idx].aabb=p_bvh_tree->aabb; p_bvh_array[idx].face_index=p_bvh_tree->face_index; -// printf("%p - %i: %i(%p) -- %p:%p\n",%p_bvh_array[idx],p_idx,p_bvh_array[i]->face_index,&p_bvh_tree->face_index,p_bvh_tree->left,p_bvh_tree->right); + //printf("%p - %i: %i(%p) -- %p:%p\n",%p_bvh_array[idx],p_idx,p_bvh_array[i]->face_index,&p_bvh_tree->face_index,p_bvh_tree->left,p_bvh_tree->right); if (p_bvh_tree->left) { @@ -1347,17 +1349,17 @@ void ConcavePolygonShapeSW::_fill_bvh(_VolumeSW_BVH* p_bvh_tree,BVH* p_bvh_array } -void ConcavePolygonShapeSW::_setup(DVector<Vector3> p_faces) { +void ConcavePolygonShapeSW::_setup(PoolVector<Vector3> p_faces) { int src_face_count=p_faces.size(); if (src_face_count==0) { - configure(AABB()); + configure(Rect3()); return; } ERR_FAIL_COND(src_face_count%3); src_face_count/=3; - DVector<Vector3>::Read r = p_faces.read(); + PoolVector<Vector3>::Read r = p_faces.read(); const Vector3 * facesr= r.ptr(); #if 0 @@ -1399,7 +1401,7 @@ void ConcavePolygonShapeSW::_setup(DVector<Vector3> p_faces) { vertices.resize( point_map.size() ); - DVector<Vector3>::Write vw = vertices.write(); + PoolVector<Vector3>::Write vw = vertices.write(); Vector3 *verticesw=vw.ptr(); AABB _aabb; @@ -1418,7 +1420,7 @@ void ConcavePolygonShapeSW::_setup(DVector<Vector3> p_faces) { point_map.clear(); // not needed anymore faces.resize(face_list.size()); - DVector<Face>::Write w = faces.write(); + PoolVector<Face>::Write w = faces.write(); Face *facesw=w.ptr(); int fc=0; @@ -1431,10 +1433,10 @@ void ConcavePolygonShapeSW::_setup(DVector<Vector3> p_faces) { face_list.clear(); - DVector<_VolumeSW_BVH_Element> bvh_array; + PoolVector<_VolumeSW_BVH_Element> bvh_array; bvh_array.resize( fc ); - DVector<_VolumeSW_BVH_Element>::Write bvhw = bvh_array.write(); + PoolVector<_VolumeSW_BVH_Element>::Write bvhw = bvh_array.write(); _VolumeSW_BVH_Element *bvh_arrayw=bvhw.ptr(); @@ -1451,8 +1453,8 @@ void ConcavePolygonShapeSW::_setup(DVector<Vector3> p_faces) { } - w=DVector<Face>::Write(); - vw=DVector<Vector3>::Write(); + w=PoolVector<Face>::Write(); + vw=PoolVector<Vector3>::Write(); int count=0; @@ -1460,11 +1462,11 @@ void ConcavePolygonShapeSW::_setup(DVector<Vector3> p_faces) { ERR_FAIL_COND(count==0); - bvhw=DVector<_VolumeSW_BVH_Element>::Write(); + bvhw=PoolVector<_VolumeSW_BVH_Element>::Write(); bvh.resize( count+1 ); - DVector<BVH>::Write bvhw2 = bvh.write(); + PoolVector<BVH>::Write bvhw2 = bvh.write(); BVH*bvh_arrayw2=bvhw2.ptr(); int idx=0; @@ -1473,22 +1475,22 @@ void ConcavePolygonShapeSW::_setup(DVector<Vector3> p_faces) { set_aabb(_aabb); #else - DVector<_VolumeSW_BVH_Element> bvh_array; + PoolVector<_VolumeSW_BVH_Element> bvh_array; bvh_array.resize( src_face_count ); - DVector<_VolumeSW_BVH_Element>::Write bvhw = bvh_array.write(); + PoolVector<_VolumeSW_BVH_Element>::Write bvhw = bvh_array.write(); _VolumeSW_BVH_Element *bvh_arrayw=bvhw.ptr(); faces.resize(src_face_count); - DVector<Face>::Write w = faces.write(); + PoolVector<Face>::Write w = faces.write(); Face *facesw=w.ptr(); vertices.resize( src_face_count*3 ); - DVector<Vector3>::Write vw = vertices.write(); + PoolVector<Vector3>::Write vw = vertices.write(); Vector3 *verticesw=vw.ptr(); - AABB _aabb; + Rect3 _aabb; for(int i=0;i<src_face_count;i++) { @@ -1512,15 +1514,15 @@ void ConcavePolygonShapeSW::_setup(DVector<Vector3> p_faces) { } - w=DVector<Face>::Write(); - vw=DVector<Vector3>::Write(); + w=PoolVector<Face>::Write(); + vw=PoolVector<Vector3>::Write(); int count=0; _VolumeSW_BVH *bvh_tree=_volume_sw_build_bvh(bvh_arrayw,src_face_count,count); bvh.resize( count+1 ); - DVector<BVH>::Write bvhw2 = bvh.write(); + PoolVector<BVH>::Write bvhw2 = bvh.write(); BVH*bvh_arrayw2=bvhw2.ptr(); int idx=0; @@ -1553,7 +1555,7 @@ ConcavePolygonShapeSW::ConcavePolygonShapeSW() { /* HEIGHT MAP SHAPE */ -DVector<float> HeightMapShapeSW::get_heights() const { +PoolVector<real_t> HeightMapShapeSW::get_heights() const { return heights; } @@ -1565,7 +1567,7 @@ int HeightMapShapeSW::get_depth() const { return depth; } -float HeightMapShapeSW::get_cell_size() const { +real_t HeightMapShapeSW::get_cell_size() const { return cell_size; } @@ -1593,14 +1595,14 @@ bool HeightMapShapeSW::intersect_segment(const Vector3& p_begin,const Vector3& p } -void HeightMapShapeSW::cull(const AABB& p_local_aabb,Callback p_callback,void* p_userdata) const { +void HeightMapShapeSW::cull(const Rect3& p_local_aabb,Callback p_callback,void* p_userdata) const { } -Vector3 HeightMapShapeSW::get_moment_of_inertia(float p_mass) const { +Vector3 HeightMapShapeSW::get_moment_of_inertia(real_t p_mass) const { // use crappy AABB approximation @@ -1614,22 +1616,22 @@ Vector3 HeightMapShapeSW::get_moment_of_inertia(float p_mass) const { } -void HeightMapShapeSW::_setup(DVector<real_t> p_heights,int p_width,int p_depth,real_t p_cell_size) { +void HeightMapShapeSW::_setup(PoolVector<real_t> p_heights,int p_width,int p_depth,real_t p_cell_size) { heights=p_heights; width=p_width; - depth=p_depth;; + depth=p_depth; cell_size=p_cell_size; - DVector<real_t>::Read r = heights. read(); + PoolVector<real_t>::Read r = heights. read(); - AABB aabb; + Rect3 aabb; for(int i=0;i<depth;i++) { for(int j=0;j<width;j++) { - float h = r[i*width+j]; + real_t h = r[i*width+j]; Vector3 pos( j*cell_size, h, i*cell_size ); if (i==0 || j==0) @@ -1655,8 +1657,8 @@ void HeightMapShapeSW::set_data(const Variant& p_data) { int width=d["width"]; int depth=d["depth"]; - float cell_size=d["cell_size"]; - DVector<float> heights=d["heights"]; + real_t cell_size=d["cell_size"]; + PoolVector<real_t> heights=d["heights"]; ERR_FAIL_COND( width<= 0); ERR_FAIL_COND( depth<= 0); diff --git a/servers/physics/shape_sw.h b/servers/physics/shape_sw.h index 39779bcda3..c8194ad755 100644 --- a/servers/physics/shape_sw.h +++ b/servers/physics/shape_sw.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -35,8 +35,8 @@ /* SHAPE_LINE, ///< plane:"plane" -SHAPE_SEGMENT, ///< float:"length" -SHAPE_CIRCLE, ///< float:"radius" +SHAPE_SEGMENT, ///< real_t:"length" +SHAPE_CIRCLE, ///< real_t:"radius" SHAPE_RECTANGLE, ///< vec3:"extents" SHAPE_CONVEX_POLYGON, ///< array of planes:"planes" SHAPE_CONCAVE_POLYGON, ///< Vector3 array:"triangles" , or Dictionary with "indices" (int array) and "triangles" (Vector3 array) @@ -46,7 +46,7 @@ SHAPE_CUSTOM, ///< Server-Implementation based custom shape, calling shape_creat class ShapeSW; -class ShapeOwnerSW { +class ShapeOwnerSW : public RID_Data { public: virtual void _shape_changed()=0; @@ -56,29 +56,31 @@ public: }; -class ShapeSW { +class ShapeSW : public RID_Data { RID self; - AABB aabb; + Rect3 aabb; bool configured; real_t custom_bias; Map<ShapeOwnerSW*,int> owners; protected: - void configure(const AABB& p_aabb); + void configure(const Rect3& p_aabb); public: enum { MAX_SUPPORTS=8 }; + virtual real_t get_area() const { return aabb.get_area();} + _FORCE_INLINE_ void set_self(const RID& p_self) { self=p_self; } _FORCE_INLINE_ RID get_self() const {return self; } virtual PhysicsServer::ShapeType get_type() const=0; - _FORCE_INLINE_ AABB get_aabb() const { return aabb; } + _FORCE_INLINE_ Rect3 get_aabb() const { return aabb; } _FORCE_INLINE_ bool is_configured() const { return configured; } virtual bool is_concave() const { return false; } @@ -88,7 +90,7 @@ public: virtual void get_supports(const Vector3& p_normal,int p_max,Vector3 *r_supports,int & r_amount) const=0; virtual bool intersect_segment(const Vector3& p_begin,const Vector3& p_end,Vector3 &r_point, Vector3 &r_normal) const=0; - virtual Vector3 get_moment_of_inertia(float p_mass) const=0; + virtual Vector3 get_moment_of_inertia(real_t p_mass) const=0; virtual void set_data(const Variant& p_data)=0; virtual Variant get_data() const=0; @@ -114,7 +116,7 @@ public: typedef void (*Callback)(void* p_userdata,ShapeSW *p_convex); virtual void get_supports(const Vector3& p_normal,int p_max,Vector3 *r_supports,int & r_amount) const { r_amount=0; } - virtual void cull(const AABB& p_local_aabb,Callback p_callback,void* p_userdata) const=0; + virtual void cull(const Rect3& p_local_aabb,Callback p_callback,void* p_userdata) const=0; ConcaveShapeSW() {} }; @@ -128,6 +130,7 @@ public: Plane get_plane() const; + virtual real_t get_area() const { return INFINITY; } virtual PhysicsServer::ShapeType get_type() const { return PhysicsServer::SHAPE_PLANE; } virtual void project_range(const Vector3& p_normal, const Transform& p_transform, real_t &r_min, real_t &r_max) const; virtual Vector3 get_support(const Vector3& p_normal) const; @@ -135,7 +138,7 @@ public: virtual bool intersect_segment(const Vector3& p_begin,const Vector3& p_end,Vector3 &r_result, Vector3 &r_normal) const; - virtual Vector3 get_moment_of_inertia(float p_mass) const; + virtual Vector3 get_moment_of_inertia(real_t p_mass) const; virtual void set_data(const Variant& p_data); virtual Variant get_data() const; @@ -145,13 +148,14 @@ public: class RayShapeSW : public ShapeSW { - float length; + real_t length; - void _setup(float p_length); + void _setup(real_t p_length); public: - float get_length() const; + real_t get_length() const; + virtual real_t get_area() const { return 0.0; } virtual PhysicsServer::ShapeType get_type() const { return PhysicsServer::SHAPE_RAY; } virtual void project_range(const Vector3& p_normal, const Transform& p_transform, real_t &r_min, real_t &r_max) const; virtual Vector3 get_support(const Vector3& p_normal) const; @@ -159,7 +163,7 @@ public: virtual bool intersect_segment(const Vector3& p_begin,const Vector3& p_end,Vector3 &r_result, Vector3 &r_normal) const; - virtual Vector3 get_moment_of_inertia(float p_mass) const; + virtual Vector3 get_moment_of_inertia(real_t p_mass) const; virtual void set_data(const Variant& p_data); virtual Variant get_data() const; @@ -176,6 +180,8 @@ public: real_t get_radius() const; + virtual real_t get_area() const { return 4.0/3.0 * Math_PI * radius * radius * radius; } + virtual PhysicsServer::ShapeType get_type() const { return PhysicsServer::SHAPE_SPHERE; } virtual void project_range(const Vector3& p_normal, const Transform& p_transform, real_t &r_min, real_t &r_max) const; @@ -183,7 +189,7 @@ public: virtual void get_supports(const Vector3& p_normal,int p_max,Vector3 *r_supports,int & r_amount) const; virtual bool intersect_segment(const Vector3& p_begin,const Vector3& p_end,Vector3 &r_result, Vector3 &r_normal) const; - virtual Vector3 get_moment_of_inertia(float p_mass) const; + virtual Vector3 get_moment_of_inertia(real_t p_mass) const; virtual void set_data(const Variant& p_data); virtual Variant get_data() const; @@ -198,6 +204,7 @@ class BoxShapeSW : public ShapeSW { public: _FORCE_INLINE_ Vector3 get_half_extents() const { return half_extents; } + virtual real_t get_area() const { return 8 * half_extents.x * half_extents.y * half_extents.z; } virtual PhysicsServer::ShapeType get_type() const { return PhysicsServer::SHAPE_BOX; } @@ -206,7 +213,7 @@ public: virtual void get_supports(const Vector3& p_normal,int p_max,Vector3 *r_supports,int & r_amount) const; virtual bool intersect_segment(const Vector3& p_begin,const Vector3& p_end,Vector3 &r_result, Vector3 &r_normal) const; - virtual Vector3 get_moment_of_inertia(float p_mass) const; + virtual Vector3 get_moment_of_inertia(real_t p_mass) const; virtual void set_data(const Variant& p_data); virtual Variant get_data() const; @@ -226,6 +233,8 @@ public: _FORCE_INLINE_ real_t get_height() const { return height; } _FORCE_INLINE_ real_t get_radius() const { return radius; } + virtual real_t get_area() { return 4.0/3.0 * Math_PI * radius * radius * radius + height * Math_PI * radius * radius; } + virtual PhysicsServer::ShapeType get_type() const { return PhysicsServer::SHAPE_CAPSULE; } virtual void project_range(const Vector3& p_normal, const Transform& p_transform, real_t &r_min, real_t &r_max) const; @@ -233,7 +242,7 @@ public: virtual void get_supports(const Vector3& p_normal,int p_max,Vector3 *r_supports,int & r_amount) const; virtual bool intersect_segment(const Vector3& p_begin,const Vector3& p_end,Vector3 &r_result, Vector3 &r_normal) const; - virtual Vector3 get_moment_of_inertia(float p_mass) const; + virtual Vector3 get_moment_of_inertia(real_t p_mass) const; virtual void set_data(const Variant& p_data); virtual Variant get_data() const; @@ -257,7 +266,7 @@ public: virtual void get_supports(const Vector3& p_normal,int p_max,Vector3 *r_supports,int & r_amount) const; virtual bool intersect_segment(const Vector3& p_begin,const Vector3& p_end,Vector3 &r_result, Vector3 &r_normal) const; - virtual Vector3 get_moment_of_inertia(float p_mass) const; + virtual Vector3 get_moment_of_inertia(real_t p_mass) const; virtual void set_data(const Variant& p_data); virtual Variant get_data() const; @@ -279,23 +288,23 @@ struct ConcavePolygonShapeSW : public ConcaveShapeSW { int indices[3]; }; - DVector<Face> faces; - DVector<Vector3> vertices; + PoolVector<Face> faces; + PoolVector<Vector3> vertices; struct BVH { - AABB aabb; + Rect3 aabb; int left; int right; int face_index; }; - DVector<BVH> bvh; + PoolVector<BVH> bvh; struct _CullParams { - AABB aabb; + Rect3 aabb; Callback callback; void *userdata; const Face *faces; @@ -326,10 +335,10 @@ struct ConcavePolygonShapeSW : public ConcaveShapeSW { void _fill_bvh(_VolumeSW_BVH* p_bvh_tree,BVH* p_bvh_array,int& p_idx); - void _setup(DVector<Vector3> p_faces); + void _setup(PoolVector<Vector3> p_faces); public: - DVector<Vector3> get_faces() const; + PoolVector<Vector3> get_faces() const; virtual PhysicsServer::ShapeType get_type() const { return PhysicsServer::SHAPE_CONCAVE_POLYGON; } @@ -338,9 +347,9 @@ public: virtual bool intersect_segment(const Vector3& p_begin,const Vector3& p_end,Vector3 &r_result, Vector3 &r_normal) const; - virtual void cull(const AABB& p_local_aabb,Callback p_callback,void* p_userdata) const; + virtual void cull(const Rect3& p_local_aabb,Callback p_callback,void* p_userdata) const; - virtual Vector3 get_moment_of_inertia(float p_mass) const; + virtual Vector3 get_moment_of_inertia(real_t p_mass) const; virtual void set_data(const Variant& p_data); virtual Variant get_data() const; @@ -352,21 +361,21 @@ public: struct HeightMapShapeSW : public ConcaveShapeSW { - DVector<real_t> heights; + PoolVector<real_t> heights; int width; int depth; - float cell_size; + real_t cell_size; -// void _cull_segment(int p_idx,_SegmentCullParams *p_params) const; -// void _cull(int p_idx,_CullParams *p_params) const; + //void _cull_segment(int p_idx,_SegmentCullParams *p_params) const; + //void _cull(int p_idx,_CullParams *p_params) const; - void _setup(DVector<float> p_heights,int p_width,int p_depth,float p_cell_size); + void _setup(PoolVector<real_t> p_heights,int p_width,int p_depth,real_t p_cell_size); public: - DVector<real_t> get_heights() const; + PoolVector<real_t> get_heights() const; int get_width() const; int get_depth() const; - float get_cell_size() const; + real_t get_cell_size() const; virtual PhysicsServer::ShapeType get_type() const { return PhysicsServer::SHAPE_HEIGHTMAP; } @@ -374,9 +383,9 @@ public: virtual Vector3 get_support(const Vector3& p_normal) const; virtual bool intersect_segment(const Vector3& p_begin,const Vector3& p_end,Vector3 &r_result, Vector3 &r_normal) const; - virtual void cull(const AABB& p_local_aabb,Callback p_callback,void* p_userdata) const; + virtual void cull(const Rect3& p_local_aabb,Callback p_callback,void* p_userdata) const; - virtual Vector3 get_moment_of_inertia(float p_mass) const; + virtual Vector3 get_moment_of_inertia(real_t p_mass) const; virtual void set_data(const Variant& p_data); virtual Variant get_data() const; @@ -400,7 +409,7 @@ struct FaceShapeSW : public ShapeSW { virtual void get_supports(const Vector3& p_normal,int p_max,Vector3 *r_supports,int & r_amount) const; bool intersect_segment(const Vector3& p_begin,const Vector3& p_end,Vector3 &r_result, Vector3 &r_normal) const; - Vector3 get_moment_of_inertia(float p_mass) const; + Vector3 get_moment_of_inertia(real_t p_mass) const; virtual void set_data(const Variant& p_data) {} virtual Variant get_data() const { return Variant(); } @@ -441,12 +450,12 @@ struct MotionShapeSW : public ShapeSW { virtual void get_supports(const Vector3& p_normal,int p_max,Vector3 *r_supports,int & r_amount) const { r_amount=0; } bool intersect_segment(const Vector3& p_begin,const Vector3& p_end,Vector3 &r_result, Vector3 &r_normal) const { return false; } - Vector3 get_moment_of_inertia(float p_mass) const { return Vector3(); } + Vector3 get_moment_of_inertia(real_t p_mass) const { return Vector3(); } virtual void set_data(const Variant& p_data) {} virtual Variant get_data() const { return Variant(); } - MotionShapeSW() { configure(AABB()); } + MotionShapeSW() { configure(Rect3()); } }; diff --git a/servers/physics/space_sw.cpp b/servers/physics/space_sw.cpp index 7077146420..0bc11041de 100644 --- a/servers/physics/space_sw.cpp +++ b/servers/physics/space_sw.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -26,7 +26,7 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "globals.h" +#include "global_config.h" #include "space_sw.h" #include "collision_solver_sw.h" #include "physics_server_sw.h" @@ -138,7 +138,7 @@ bool PhysicsDirectSpaceStateSW::intersect_ray(const Vector3& p_from, const Vecto } -int PhysicsDirectSpaceStateSW::intersect_shape(const RID& p_shape, const Transform& p_xform,float p_margin,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) { +int PhysicsDirectSpaceStateSW::intersect_shape(const RID& p_shape, const Transform& p_xform,real_t p_margin,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) { if (p_result_max<=0) return 0; @@ -146,7 +146,7 @@ int PhysicsDirectSpaceStateSW::intersect_shape(const RID& p_shape, const Transfo ShapeSW *shape = static_cast<PhysicsServerSW*>(PhysicsServer::get_singleton())->shape_owner.get(p_shape); ERR_FAIL_COND_V(!shape,0); - AABB aabb = p_xform.xform(shape->get_aabb()); + Rect3 aabb = p_xform.xform(shape->get_aabb()); int amount = space->broadphase->cull_aabb(aabb,space->intersection_query_results,SpaceSW::INTERSECTION_QUERY_MAX,space->intersection_query_subindex_results); @@ -193,24 +193,26 @@ int PhysicsDirectSpaceStateSW::intersect_shape(const RID& p_shape, const Transfo } -bool PhysicsDirectSpaceStateSW::cast_motion(const RID& p_shape, const Transform& p_xform,const Vector3& p_motion,float p_margin,float &p_closest_safe,float &p_closest_unsafe, const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask,ShapeRestInfo *r_info) { +bool PhysicsDirectSpaceStateSW::cast_motion(const RID& p_shape, const Transform& p_xform,const Vector3& p_motion,real_t p_margin,real_t &p_closest_safe,real_t &p_closest_unsafe, const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask,ShapeRestInfo *r_info) { ShapeSW *shape = static_cast<PhysicsServerSW*>(PhysicsServer::get_singleton())->shape_owner.get(p_shape); ERR_FAIL_COND_V(!shape,false); - AABB aabb = p_xform.xform(shape->get_aabb()); - aabb=aabb.merge(AABB(aabb.pos+p_motion,aabb.size)); //motion + Rect3 aabb = p_xform.xform(shape->get_aabb()); + aabb=aabb.merge(Rect3(aabb.pos+p_motion,aabb.size)); //motion aabb=aabb.grow(p_margin); - //if (p_motion!=Vector3()) - // print_line(p_motion); + /* + if (p_motion!=Vector3()) + print_line(p_motion); + */ int amount = space->broadphase->cull_aabb(aabb,space->intersection_query_results,SpaceSW::INTERSECTION_QUERY_MAX,space->intersection_query_subindex_results); - float best_safe=1; - float best_unsafe=1; + real_t best_safe=1; + real_t best_unsafe=1; Transform xform_inv = p_xform.affine_inverse(); MotionShapeSW mshape; @@ -262,13 +264,13 @@ bool PhysicsDirectSpaceStateSW::cast_motion(const RID& p_shape, const Transform& //just do kinematic solving - float low=0; - float hi=1; + real_t low=0; + real_t hi=1; Vector3 mnormal=p_motion.normalized(); for(int i=0;i<8;i++) { //steps should be customizable.. - float ofs = (low+hi)*0.5; + real_t ofs = (low+hi)*0.5; Vector3 sep=mnormal; //important optimization for this to work fast enough @@ -321,7 +323,7 @@ bool PhysicsDirectSpaceStateSW::cast_motion(const RID& p_shape, const Transform& return true; } -bool PhysicsDirectSpaceStateSW::collide_shape(RID p_shape, const Transform& p_shape_xform,float p_margin,Vector3 *r_results,int p_result_max,int &r_result_count, const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask){ +bool PhysicsDirectSpaceStateSW::collide_shape(RID p_shape, const Transform& p_shape_xform,real_t p_margin,Vector3 *r_results,int p_result_max,int &r_result_count, const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask){ if (p_result_max<=0) return 0; @@ -329,7 +331,7 @@ bool PhysicsDirectSpaceStateSW::collide_shape(RID p_shape, const Transform& p_sh ShapeSW *shape = static_cast<PhysicsServerSW*>(PhysicsServer::get_singleton())->shape_owner.get(p_shape); ERR_FAIL_COND_V(!shape,0); - AABB aabb = p_shape_xform.xform(shape->get_aabb()); + Rect3 aabb = p_shape_xform.xform(shape->get_aabb()); aabb=aabb.grow(p_margin); int amount = space->broadphase->cull_aabb(aabb,space->intersection_query_results,SpaceSW::INTERSECTION_QUERY_MAX,space->intersection_query_subindex_results); @@ -386,7 +388,7 @@ struct _RestCallbackData { int best_shape; Vector3 best_contact; Vector3 best_normal; - float best_len; + real_t best_len; }; static void _rest_cbk_result(const Vector3& p_point_A,const Vector3& p_point_B,void *p_userdata) { @@ -395,7 +397,7 @@ static void _rest_cbk_result(const Vector3& p_point_A,const Vector3& p_point_B,v _RestCallbackData *rd=(_RestCallbackData*)p_userdata; Vector3 contact_rel = p_point_B - p_point_A; - float len = contact_rel.length(); + real_t len = contact_rel.length(); if (len <= rd->best_len) return; @@ -406,13 +408,13 @@ static void _rest_cbk_result(const Vector3& p_point_A,const Vector3& p_point_B,v rd->best_shape=rd->shape; } -bool PhysicsDirectSpaceStateSW::rest_info(RID p_shape, const Transform& p_shape_xform,float p_margin,ShapeRestInfo *r_info, const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) { +bool PhysicsDirectSpaceStateSW::rest_info(RID p_shape, const Transform& p_shape_xform,real_t p_margin,ShapeRestInfo *r_info, const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) { ShapeSW *shape = static_cast<PhysicsServerSW*>(PhysicsServer::get_singleton())->shape_owner.get(p_shape); ERR_FAIL_COND_V(!shape,0); - AABB aabb = p_shape_xform.xform(shape->get_aabb()); + Rect3 aabb = p_shape_xform.xform(shape->get_aabb()); aabb=aabb.grow(p_margin); int amount = space->broadphase->cull_aabb(aabb,space->intersection_query_results,SpaceSW::INTERSECTION_QUERY_MAX,space->intersection_query_subindex_results); @@ -719,9 +721,9 @@ SpaceSW::SpaceSW() { contact_max_allowed_penetration= 0.01; constraint_bias = 0.01; - body_linear_velocity_sleep_threshold=GLOBAL_DEF("physics/sleep_threshold_linear",0.1); - body_angular_velocity_sleep_threshold=GLOBAL_DEF("physics/sleep_threshold_angular", (8.0 / 180.0 * Math_PI) ); - body_time_to_sleep=0.5; + body_linear_velocity_sleep_threshold=GLOBAL_DEF("physics/3d/sleep_threshold_linear",0.1); + body_angular_velocity_sleep_threshold=GLOBAL_DEF("physics/3d/sleep_threshold_angular", (8.0 / 180.0 * Math_PI) ); + body_time_to_sleep=GLOBAL_DEF("physics/3d/time_before_sleep",0.5); body_angular_velocity_damp_ratio=10; diff --git a/servers/physics/space_sw.h b/servers/physics/space_sw.h index 3fdef7e62b..208831914f 100644 --- a/servers/physics/space_sw.h +++ b/servers/physics/space_sw.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -37,27 +37,28 @@ #include "area_pair_sw.h" #include "broad_phase_sw.h" #include "collision_object_sw.h" +#include "global_config.h" class PhysicsDirectSpaceStateSW : public PhysicsDirectSpaceState { - OBJ_TYPE( PhysicsDirectSpaceStateSW, PhysicsDirectSpaceState ); + GDCLASS( PhysicsDirectSpaceStateSW, PhysicsDirectSpaceState ); public: SpaceSW *space; virtual bool intersect_ray(const Vector3& p_from, const Vector3& p_to,RayResult &r_result,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION,bool p_pick_ray=false); - virtual int intersect_shape(const RID& p_shape, const Transform& p_xform,float p_margin,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION); - virtual bool cast_motion(const RID& p_shape, const Transform& p_xform,const Vector3& p_motion,float p_margin,float &p_closest_safe,float &p_closest_unsafe, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION,ShapeRestInfo *r_info=NULL); - virtual bool collide_shape(RID p_shape, const Transform& p_shape_xform,float p_margin,Vector3 *r_results,int p_result_max,int &r_result_count, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION); - virtual bool rest_info(RID p_shape, const Transform& p_shape_xform,float p_margin,ShapeRestInfo *r_info, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION); + virtual int intersect_shape(const RID& p_shape, const Transform& p_xform,real_t p_margin,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION); + virtual bool cast_motion(const RID& p_shape, const Transform& p_xform,const Vector3& p_motion,real_t p_margin,real_t &p_closest_safe,real_t &p_closest_unsafe, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION,ShapeRestInfo *r_info=NULL); + virtual bool collide_shape(RID p_shape, const Transform& p_shape_xform,real_t p_margin,Vector3 *r_results,int p_result_max,int &r_result_count, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION); + virtual bool rest_info(RID p_shape, const Transform& p_shape_xform,real_t p_margin,ShapeRestInfo *r_info, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION); PhysicsDirectSpaceStateSW(); }; -class SpaceSW { +class SpaceSW : public RID_Data { public: @@ -104,10 +105,10 @@ private: CollisionObjectSW *intersection_query_results[INTERSECTION_QUERY_MAX]; int intersection_query_subindex_results[INTERSECTION_QUERY_MAX]; - float body_linear_velocity_sleep_threshold; - float body_angular_velocity_sleep_threshold; - float body_time_to_sleep; - float body_angular_velocity_damp_ratio; + real_t body_linear_velocity_sleep_threshold; + real_t body_angular_velocity_sleep_threshold; + real_t body_time_to_sleep; + real_t body_angular_velocity_damp_ratio; bool locked; diff --git a/servers/physics/step_sw.cpp b/servers/physics/step_sw.cpp index 5b7ebce817..0bd5a874ea 100644 --- a/servers/physics/step_sw.cpp +++ b/servers/physics/step_sw.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -58,7 +58,7 @@ void StepSW::_populate_island(BodySW* p_body,BodySW** p_island,ConstraintSW **p_ } } -void StepSW::_setup_island(ConstraintSW *p_island,float p_delta) { +void StepSW::_setup_island(ConstraintSW *p_island,real_t p_delta) { ConstraintSW *ci=p_island; while(ci) { @@ -68,7 +68,7 @@ void StepSW::_setup_island(ConstraintSW *p_island,float p_delta) { } } -void StepSW::_solve_island(ConstraintSW *p_island,int p_iterations,float p_delta){ +void StepSW::_solve_island(ConstraintSW *p_island,int p_iterations,real_t p_delta){ int at_priority=1; @@ -107,7 +107,7 @@ void StepSW::_solve_island(ConstraintSW *p_island,int p_iterations,float p_delta } -void StepSW::_check_suspend(BodySW *p_island,float p_delta) { +void StepSW::_check_suspend(BodySW *p_island,real_t p_delta) { bool can_sleep=true; @@ -145,7 +145,7 @@ void StepSW::_check_suspend(BodySW *p_island,float p_delta) { } } -void StepSW::step(SpaceSW* p_space,float p_delta,int p_iterations) { +void StepSW::step(SpaceSW* p_space,real_t p_delta,int p_iterations) { p_space->lock(); // can't access space during this @@ -233,7 +233,7 @@ void StepSW::step(SpaceSW* p_space,float p_delta,int p_iterations) { } -// print_line("island count: "+itos(island_count)+" active count: "+itos(active_count)); + //print_line("island count: "+itos(island_count)+" active count: "+itos(active_count)); /* SETUP CONSTRAINT ISLANDS */ { diff --git a/servers/physics/step_sw.h b/servers/physics/step_sw.h index f6362f3777..7048a76937 100644 --- a/servers/physics/step_sw.h +++ b/servers/physics/step_sw.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -36,12 +36,12 @@ class StepSW { uint64_t _step; void _populate_island(BodySW* p_body,BodySW** p_island,ConstraintSW **p_constraint_island); - void _setup_island(ConstraintSW *p_island,float p_delta); - void _solve_island(ConstraintSW *p_island,int p_iterations,float p_delta); - void _check_suspend(BodySW *p_island,float p_delta); + void _setup_island(ConstraintSW *p_island,real_t p_delta); + void _solve_island(ConstraintSW *p_island,int p_iterations,real_t p_delta); + void _check_suspend(BodySW *p_island,real_t p_delta); public: - void step(SpaceSW* p_space,float p_delta,int p_iterations); + void step(SpaceSW* p_space,real_t p_delta,int p_iterations); StepSW(); }; diff --git a/servers/physics_2d/SCsub b/servers/physics_2d/SCsub index ebb7f8be00..d730144861 100644 --- a/servers/physics_2d/SCsub +++ b/servers/physics_2d/SCsub @@ -1,3 +1,5 @@ +#!/usr/bin/env python + Import('env') -env.add_source_files(env.servers_sources,"*.cpp") +env.add_source_files(env.servers_sources, "*.cpp") diff --git a/servers/physics_2d/area_2d_sw.cpp b/servers/physics_2d/area_2d_sw.cpp index 759a37e84f..2625502717 100644 --- a/servers/physics_2d/area_2d_sw.cpp +++ b/servers/physics_2d/area_2d_sw.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -38,7 +38,7 @@ void Area2DSW::_shapes_changed() { } -void Area2DSW::set_transform(const Matrix32& p_transform) { +void Area2DSW::set_transform(const Transform2D& p_transform) { if (!moved_list.in_list() && get_space()) get_space()->area_add_to_moved_list(&moved_list); @@ -125,14 +125,14 @@ void Area2DSW::set_space_override_mode(Physics2DServer::AreaSpaceOverrideMode p_ void Area2DSW::set_param(Physics2DServer::AreaParameter p_param, const Variant& p_value) { switch(p_param) { - case Physics2DServer::AREA_PARAM_GRAVITY: gravity=p_value; ; break; - case Physics2DServer::AREA_PARAM_GRAVITY_VECTOR: gravity_vector=p_value; ; break; - case Physics2DServer::AREA_PARAM_GRAVITY_IS_POINT: gravity_is_point=p_value; ; break; - case Physics2DServer::AREA_PARAM_GRAVITY_DISTANCE_SCALE: gravity_distance_scale=p_value; ; break; - case Physics2DServer::AREA_PARAM_GRAVITY_POINT_ATTENUATION: point_attenuation=p_value; ; break; - case Physics2DServer::AREA_PARAM_LINEAR_DAMP: linear_damp=p_value; ; break; - case Physics2DServer::AREA_PARAM_ANGULAR_DAMP: angular_damp=p_value; ; break; - case Physics2DServer::AREA_PARAM_PRIORITY: priority=p_value; ; break; + case Physics2DServer::AREA_PARAM_GRAVITY: gravity=p_value; break; + case Physics2DServer::AREA_PARAM_GRAVITY_VECTOR: gravity_vector=p_value; break; + case Physics2DServer::AREA_PARAM_GRAVITY_IS_POINT: gravity_is_point=p_value; break; + case Physics2DServer::AREA_PARAM_GRAVITY_DISTANCE_SCALE: gravity_distance_scale=p_value; break; + case Physics2DServer::AREA_PARAM_GRAVITY_POINT_ATTENUATION: point_attenuation=p_value; break; + case Physics2DServer::AREA_PARAM_LINEAR_DAMP: linear_damp=p_value; break; + case Physics2DServer::AREA_PARAM_ANGULAR_DAMP: angular_damp=p_value; break; + case Physics2DServer::AREA_PARAM_PRIORITY: priority=p_value; break; } diff --git a/servers/physics_2d/area_2d_sw.h b/servers/physics_2d/area_2d_sw.h index 71192db1df..02a65962e5 100644 --- a/servers/physics_2d/area_2d_sw.h +++ b/servers/physics_2d/area_2d_sw.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -43,13 +43,13 @@ class Area2DSW : public CollisionObject2DSW{ Physics2DServer::AreaSpaceOverrideMode space_override_mode; - float gravity; + real_t gravity; Vector2 gravity_vector; bool gravity_is_point; - float gravity_distance_scale; - float point_attenuation; - float linear_damp; - float angular_damp; + real_t gravity_distance_scale; + real_t point_attenuation; + real_t linear_damp; + real_t angular_damp; int priority; bool monitorable; @@ -131,8 +131,8 @@ public: void set_space_override_mode(Physics2DServer::AreaSpaceOverrideMode p_mode); Physics2DServer::AreaSpaceOverrideMode get_space_override_mode() const { return space_override_mode; } - _FORCE_INLINE_ void set_gravity(float p_gravity) { gravity=p_gravity; } - _FORCE_INLINE_ float get_gravity() const { return gravity; } + _FORCE_INLINE_ void set_gravity(real_t p_gravity) { gravity=p_gravity; } + _FORCE_INLINE_ real_t get_gravity() const { return gravity; } _FORCE_INLINE_ void set_gravity_vector(const Vector2& p_gravity) { gravity_vector=p_gravity; } _FORCE_INLINE_ Vector2 get_gravity_vector() const { return gravity_vector; } @@ -140,17 +140,17 @@ public: _FORCE_INLINE_ void set_gravity_as_point(bool p_enable) { gravity_is_point=p_enable; } _FORCE_INLINE_ bool is_gravity_point() const { return gravity_is_point; } - _FORCE_INLINE_ void set_gravity_distance_scale(float scale) { gravity_distance_scale=scale; } - _FORCE_INLINE_ float get_gravity_distance_scale() const { return gravity_distance_scale; } + _FORCE_INLINE_ void set_gravity_distance_scale(real_t scale) { gravity_distance_scale=scale; } + _FORCE_INLINE_ real_t get_gravity_distance_scale() const { return gravity_distance_scale; } - _FORCE_INLINE_ void set_point_attenuation(float p_point_attenuation) { point_attenuation=p_point_attenuation; } - _FORCE_INLINE_ float get_point_attenuation() const { return point_attenuation; } + _FORCE_INLINE_ void set_point_attenuation(real_t p_point_attenuation) { point_attenuation=p_point_attenuation; } + _FORCE_INLINE_ real_t get_point_attenuation() const { return point_attenuation; } - _FORCE_INLINE_ void set_linear_damp(float p_linear_damp) { linear_damp=p_linear_damp; } - _FORCE_INLINE_ float get_linear_damp() const { return linear_damp; } + _FORCE_INLINE_ void set_linear_damp(real_t p_linear_damp) { linear_damp=p_linear_damp; } + _FORCE_INLINE_ real_t get_linear_damp() const { return linear_damp; } - _FORCE_INLINE_ void set_angular_damp(float p_angular_damp) { angular_damp=p_angular_damp; } - _FORCE_INLINE_ float get_angular_damp() const { return angular_damp; } + _FORCE_INLINE_ void set_angular_damp(real_t p_angular_damp) { angular_damp=p_angular_damp; } + _FORCE_INLINE_ real_t get_angular_damp() const { return angular_damp; } _FORCE_INLINE_ void set_priority(int p_priority) { priority=p_priority; } _FORCE_INLINE_ int get_priority() const { return priority; } @@ -162,7 +162,7 @@ public: void set_monitorable(bool p_monitorable); _FORCE_INLINE_ bool is_monitorable() const { return monitorable; } - void set_transform(const Matrix32& p_transform); + void set_transform(const Transform2D& p_transform); void set_space(Space2DSW *p_space); diff --git a/servers/physics_2d/area_pair_2d_sw.cpp b/servers/physics_2d/area_pair_2d_sw.cpp index 0682d8abdd..cb91caf626 100644 --- a/servers/physics_2d/area_pair_2d_sw.cpp +++ b/servers/physics_2d/area_pair_2d_sw.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,7 +30,7 @@ #include "collision_solver_2d_sw.h" -bool AreaPair2DSW::setup(float p_step) { +bool AreaPair2DSW::setup(real_t p_step) { bool result = area->test_collision_mask(body) && CollisionSolver2DSW::solve(body->get_shape(body_shape),body->get_transform() * body->get_shape_transform(body_shape),Vector2(),area->get_shape(area_shape),area->get_transform() * area->get_shape_transform(area_shape),Vector2(),NULL,this); @@ -59,7 +59,7 @@ bool AreaPair2DSW::setup(float p_step) { return false; //never do any post solving } -void AreaPair2DSW::solve(float p_step) { +void AreaPair2DSW::solve(real_t p_step) { } @@ -100,7 +100,7 @@ AreaPair2DSW::~AreaPair2DSW() { -bool Area2Pair2DSW::setup(float p_step) { +bool Area2Pair2DSW::setup(real_t p_step) { bool result = area_a->test_collision_mask(area_b) && CollisionSolver2DSW::solve(area_a->get_shape(shape_a),area_a->get_transform() * area_a->get_shape_transform(shape_a),Vector2(),area_b->get_shape(shape_b),area_b->get_transform() * area_b->get_shape_transform(shape_b),Vector2(),NULL,this); @@ -130,7 +130,7 @@ bool Area2Pair2DSW::setup(float p_step) { return false; //never do any post solving } -void Area2Pair2DSW::solve(float p_step) { +void Area2Pair2DSW::solve(real_t p_step) { } diff --git a/servers/physics_2d/area_pair_2d_sw.h b/servers/physics_2d/area_pair_2d_sw.h index a03bdb572a..219ca30c4b 100644 --- a/servers/physics_2d/area_pair_2d_sw.h +++ b/servers/physics_2d/area_pair_2d_sw.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -42,8 +42,8 @@ class AreaPair2DSW : public Constraint2DSW { bool colliding; public: - bool setup(float p_step); - void solve(float p_step); + bool setup(real_t p_step); + void solve(real_t p_step); AreaPair2DSW(Body2DSW *p_body,int p_body_shape, Area2DSW *p_area,int p_area_shape); ~AreaPair2DSW(); @@ -59,8 +59,8 @@ class Area2Pair2DSW : public Constraint2DSW { bool colliding; public: - bool setup(float p_step); - void solve(float p_step); + bool setup(real_t p_step); + void solve(real_t p_step); Area2Pair2DSW(Area2DSW *p_area_a,int p_shape_a, Area2DSW *p_area_b,int p_shape_b); ~Area2Pair2DSW(); diff --git a/servers/physics_2d/body_2d_sw.cpp b/servers/physics_2d/body_2d_sw.cpp index 12ac0bd1ca..0dab534ef9 100644 --- a/servers/physics_2d/body_2d_sw.cpp +++ b/servers/physics_2d/body_2d_sw.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -51,7 +51,7 @@ void Body2DSW::update_inertias() { if(user_inertia) break; //update tensor for allshapes, not the best way but should be somehow OK. (inspired from bullet) - float total_area=0; + real_t total_area=0; for (int i=0;i<get_shape_count();i++) { @@ -64,11 +64,11 @@ void Body2DSW::update_inertias() { const Shape2DSW* shape=get_shape(i); - float area=get_shape_aabb(i).get_area(); + real_t area=get_shape_aabb(i).get_area(); - float mass = area * this->mass / total_area; + real_t mass = area * this->mass / total_area; - Matrix32 mtx = get_shape_transform(i); + Transform2D mtx = get_shape_transform(i); Vector2 scale = mtx.get_scale(); _inertia += shape->get_moment_of_inertia(mass,scale) + mass * mtx.get_origin().length_squared(); //Rect2 ab = get_shape_aabb(i); @@ -142,7 +142,7 @@ void Body2DSW::set_active(bool p_active) { -void Body2DSW::set_param(Physics2DServer::BodyParameter p_param, float p_value) { +void Body2DSW::set_param(Physics2DServer::BodyParameter p_param, real_t p_value) { switch(p_param) { case Physics2DServer::BODY_PARAM_BOUNCE: { @@ -183,7 +183,7 @@ void Body2DSW::set_param(Physics2DServer::BodyParameter p_param, float p_value) } } -float Body2DSW::get_param(Physics2DServer::BodyParameter p_param) const { +real_t Body2DSW::get_param(Physics2DServer::BodyParameter p_param) const { switch(p_param) { case Physics2DServer::BODY_PARAM_BOUNCE: { @@ -251,8 +251,10 @@ void Body2DSW::set_mode(Physics2DServer::BodyMode p_mode) { } _update_inertia(); - //if (get_space()) -// _update_queries(); + /* + if (get_space()) + _update_queries(); + */ } Physics2DServer::BodyMode Body2DSW::get_mode() const { @@ -287,7 +289,7 @@ void Body2DSW::set_state(Physics2DServer::BodyState p_state, const Variant& p_va _set_inv_transform(get_transform().affine_inverse()); wakeup_neighbours(); } else { - Matrix32 t = p_variant; + Transform2D t = p_variant; t.orthonormalize(); new_transform=get_transform(); //used as old to compute motion if (t==new_transform) @@ -301,15 +303,19 @@ void Body2DSW::set_state(Physics2DServer::BodyState p_state, const Variant& p_va } break; case Physics2DServer::BODY_STATE_LINEAR_VELOCITY: { - //if (mode==Physics2DServer::BODY_MODE_STATIC) - // break; + /* + if (mode==Physics2DServer::BODY_MODE_STATIC) + break; + */ linear_velocity=p_variant; wakeup(); } break; case Physics2DServer::BODY_STATE_ANGULAR_VELOCITY: { - //if (mode!=Physics2DServer::BODY_MODE_RIGID) - // break; + /* + if (mode!=Physics2DServer::BODY_MODE_RIGID) + break; + */ angular_velocity=p_variant; wakeup(); @@ -385,11 +391,13 @@ void Body2DSW::set_space(Space2DSW *p_space){ _update_inertia(); if (active) get_space()->body_add_to_active_list(&active_list); -// _update_queries(); - //if (is_active()) { - // active=false; - // set_active(true); - //} + /* + _update_queries(); + if (is_active()) { + active=false; + set_active(true); + } + */ } @@ -459,13 +467,17 @@ void Body2DSW::integrate_forces(real_t p_step) { // If less than 0, override dampenings with that of the Body2D if (angular_damp>=0) area_angular_damp = angular_damp; - //else - // area_angular_damp=damp_area->get_angular_damp(); + /* + else + area_angular_damp=damp_area->get_angular_damp(); + */ if (linear_damp>=0) area_linear_damp = linear_damp; - //else - // area_linear_damp=damp_area->get_linear_damp(); + /* + else + area_linear_damp=damp_area->get_linear_damp(); + */ Vector2 motion; bool do_motion=false; @@ -473,18 +485,21 @@ void Body2DSW::integrate_forces(real_t p_step) { if (mode==Physics2DServer::BODY_MODE_KINEMATIC) { //compute motion, angular and etc. velocities from prev transform - linear_velocity = (new_transform.elements[2] - get_transform().elements[2])/p_step; + motion = new_transform.get_origin() - get_transform().get_origin(); + linear_velocity = motion/p_step; - real_t rot = new_transform.affine_inverse().basis_xform(get_transform().elements[1]).angle(); + real_t rot = new_transform.get_rotation() - get_transform().get_rotation(); angular_velocity = rot / p_step; - motion = new_transform.elements[2] - get_transform().elements[2]; + do_motion=true; - //for(int i=0;i<get_shape_count();i++) { - // set_shape_kinematic_advance(i,Vector2()); - // set_shape_kinematic_retreat(i,0); - //} + /* + for(int i=0;i<get_shape_count();i++) { + set_shape_kinematic_advance(i,Vector2()); + set_shape_kinematic_retreat(i,0); + } + */ } else { if (!omit_force_integration && !first_integration) { @@ -556,10 +571,10 @@ void Body2DSW::integrate_velocities(real_t p_step) { real_t total_angular_velocity = angular_velocity+biased_angular_velocity; Vector2 total_linear_velocity=linear_velocity+biased_linear_velocity; - real_t angle = get_transform().get_rotation() - total_angular_velocity * p_step; + real_t angle = get_transform().get_rotation() + total_angular_velocity * p_step; Vector2 pos = get_transform().get_origin() + total_linear_velocity * p_step; - _set_transform(Matrix32(angle,pos),continuous_cd_mode==Physics2DServer::CCD_MODE_DISABLED); + _set_transform(Transform2D(angle,pos),continuous_cd_mode==Physics2DServer::CCD_MODE_DISABLED); _set_inv_transform(get_transform().inverse()); if (continuous_cd_mode!=Physics2DServer::CCD_MODE_DISABLED) diff --git a/servers/physics_2d/body_2d_sw.h b/servers/physics_2d/body_2d_sw.h index ed98017629..3fb01959a9 100644 --- a/servers/physics_2d/body_2d_sw.h +++ b/servers/physics_2d/body_2d_sw.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -69,7 +69,7 @@ class Body2DSW : public CollisionObject2DSW { real_t applied_torque; Vector2 one_way_collision_direction; - float one_way_collision_max_depth; + real_t one_way_collision_max_depth; SelfList<Body2DSW> active_list; @@ -86,7 +86,7 @@ class Body2DSW : public CollisionObject2DSW { bool using_one_way_cache; void _update_inertia(); virtual void _shapes_changed(); - Matrix32 new_transform; + Transform2D new_transform; Map<Constraint2DSW*,int> constraint_map; @@ -109,7 +109,7 @@ class Body2DSW : public CollisionObject2DSW { Vector2 local_pos; Vector2 local_normal; - float depth; + real_t depth; int local_shape; Vector2 collider_pos; int collider_shape; @@ -168,7 +168,7 @@ public: _FORCE_INLINE_ int get_max_contacts_reported() const { return contacts.size(); } _FORCE_INLINE_ bool can_report_contacts() const { return !contacts.empty(); } - _FORCE_INLINE_ void add_contact(const Vector2& p_local_pos,const Vector2& p_local_normal, float p_depth, int p_local_shape, const Vector2& p_collider_pos, int p_collider_shape, ObjectID p_collider_instance_id, const RID& p_collider,const Vector2& p_collider_velocity_at_pos); + _FORCE_INLINE_ void add_contact(const Vector2& p_local_pos,const Vector2& p_local_normal, real_t p_depth, int p_local_shape, const Vector2& p_collider_pos, int p_collider_shape, ObjectID p_collider_instance_id, const RID& p_collider,const Vector2& p_collider_velocity_at_pos); _FORCE_INLINE_ void add_exception(const RID& p_exception) { exceptions.insert(p_exception);} @@ -229,8 +229,8 @@ public: - void set_param(Physics2DServer::BodyParameter p_param, float); - float get_param(Physics2DServer::BodyParameter p_param) const; + void set_param(Physics2DServer::BodyParameter p_param, real_t); + real_t get_param(Physics2DServer::BodyParameter p_param) const; void set_mode(Physics2DServer::BodyMode p_mode); Physics2DServer::BodyMode get_mode() const; @@ -259,8 +259,8 @@ public: } Vector2 get_one_way_collision_direction() const { return one_way_collision_direction; } - void set_one_way_collision_max_depth(float p_depth) { one_way_collision_max_depth=p_depth; } - float get_one_way_collision_max_depth() const { return one_way_collision_max_depth; } + void set_one_way_collision_max_depth(real_t p_depth) { one_way_collision_max_depth=p_depth; } + real_t get_one_way_collision_max_depth() const { return one_way_collision_max_depth; } _FORCE_INLINE_ bool is_using_one_way_collision() const { return using_one_way_cache; } @@ -303,7 +303,7 @@ public: //add contact inline -void Body2DSW::add_contact(const Vector2& p_local_pos,const Vector2& p_local_normal, float p_depth, int p_local_shape, const Vector2& p_collider_pos, int p_collider_shape, ObjectID p_collider_instance_id, const RID& p_collider,const Vector2& p_collider_velocity_at_pos) { +void Body2DSW::add_contact(const Vector2& p_local_pos,const Vector2& p_local_normal, real_t p_depth, int p_local_shape, const Vector2& p_collider_pos, int p_collider_shape, ObjectID p_collider_instance_id, const RID& p_collider,const Vector2& p_collider_velocity_at_pos) { int c_max=contacts.size(); @@ -319,7 +319,7 @@ void Body2DSW::add_contact(const Vector2& p_local_pos,const Vector2& p_local_nor idx=contact_count++; } else { - float least_depth=1e20; + real_t least_depth=1e20; int least_deep=-1; for(int i=0;i<c_max;i++) { @@ -352,7 +352,7 @@ void Body2DSW::add_contact(const Vector2& p_local_pos,const Vector2& p_local_nor class Physics2DDirectBodyStateSW : public Physics2DDirectBodyState { - OBJ_TYPE( Physics2DDirectBodyStateSW, Physics2DDirectBodyState ); + GDCLASS( Physics2DDirectBodyStateSW, Physics2DDirectBodyState ); public: @@ -361,10 +361,10 @@ public: real_t step; virtual Vector2 get_total_gravity() const { return body->gravity; } // get gravity vector working on this body space/area - virtual float get_total_angular_damp() const { return body->area_angular_damp; } // get density of this body space/area - virtual float get_total_linear_damp() const { return body->area_linear_damp; } // get density of this body space/area + virtual real_t get_total_angular_damp() const { return body->area_angular_damp; } // get density of this body space/area + virtual real_t get_total_linear_damp() const { return body->area_linear_damp; } // get density of this body space/area - virtual float get_inverse_mass() const { return body->get_inv_mass(); } // get the mass + virtual real_t get_inverse_mass() const { return body->get_inv_mass(); } // get the mass virtual real_t get_inverse_inertia() const { return body->get_inv_inertia(); } // get density of this body space virtual void set_linear_velocity(const Vector2& p_velocity) { body->set_linear_velocity(p_velocity); } @@ -373,8 +373,8 @@ public: virtual void set_angular_velocity(real_t p_velocity) { body->set_angular_velocity(p_velocity); } virtual real_t get_angular_velocity() const { return body->get_angular_velocity(); } - virtual void set_transform(const Matrix32& p_transform) { body->set_state(Physics2DServer::BODY_STATE_TRANSFORM,p_transform); } - virtual Matrix32 get_transform() const { return body->get_transform(); } + virtual void set_transform(const Transform2D& p_transform) { body->set_state(Physics2DServer::BODY_STATE_TRANSFORM,p_transform); } + virtual Transform2D get_transform() const { return body->get_transform(); } virtual void set_sleep_state(bool p_enable) { body->set_active(!p_enable); } virtual bool is_sleeping() const { return !body->is_active(); } diff --git a/servers/physics_2d/body_pair_2d_sw.cpp b/servers/physics_2d/body_pair_2d_sw.cpp index ba0358a1f2..c05d61b658 100644 --- a/servers/physics_2d/body_pair_2d_sw.cpp +++ b/servers/physics_2d/body_pair_2d_sw.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -99,7 +99,7 @@ void BodyPair2DSW::_contact_added_callback(const Vector2& p_point_A,const Vector Vector2 global_B = B->get_transform().basis_xform(c.local_B)+offset_B; Vector2 axis = global_A - global_B; - float depth = axis.dot( c.normal ); + real_t depth = axis.dot( c.normal ); if (depth<min_depth) { @@ -149,7 +149,7 @@ void BodyPair2DSW::_validate_contacts() { Vector2 global_A = A->get_transform().basis_xform(c.local_A); Vector2 global_B = B->get_transform().basis_xform(c.local_B)+offset_B; Vector2 axis = global_A - global_B; - float depth = axis.dot( c.normal ); + real_t depth = axis.dot( c.normal ); @@ -175,7 +175,7 @@ void BodyPair2DSW::_validate_contacts() { } -bool BodyPair2DSW::_test_ccd(float p_step,Body2DSW *p_A, int p_shape_A,const Matrix32& p_xform_A,Body2DSW *p_B, int p_shape_B,const Matrix32& p_xform_B,bool p_swap_result) { +bool BodyPair2DSW::_test_ccd(real_t p_step,Body2DSW *p_A, int p_shape_A,const Transform2D& p_xform_A,Body2DSW *p_B, int p_shape_B,const Transform2D& p_xform_B,bool p_swap_result) { @@ -202,7 +202,7 @@ bool BodyPair2DSW::_test_ccd(float p_step,Body2DSW *p_A, int p_shape_A,const Mat Vector2 from = p_xform_A.xform(s[0]); Vector2 to = from + motion; - Matrix32 from_inv = p_xform_B.affine_inverse(); + Transform2D from_inv = p_xform_B.affine_inverse(); Vector2 local_from = from_inv.xform(from-mnormal*mlen*0.1); //start from a little inside the bounding box Vector2 local_to = from_inv.xform(to); @@ -230,7 +230,7 @@ bool BodyPair2DSW::_test_ccd(float p_step,Body2DSW *p_A, int p_shape_A,const Mat return true; } -bool BodyPair2DSW::setup(float p_step) { +bool BodyPair2DSW::setup(real_t p_step) { //cannot collide @@ -245,12 +245,12 @@ bool BodyPair2DSW::setup(float p_step) { _validate_contacts(); Vector2 offset_A = A->get_transform().get_origin(); - Matrix32 xform_Au = A->get_transform().untranslated(); - Matrix32 xform_A = xform_Au * A->get_shape_transform(shape_A); + Transform2D xform_Au = A->get_transform().untranslated(); + Transform2D xform_A = xform_Au * A->get_shape_transform(shape_A); - Matrix32 xform_Bu = B->get_transform(); + Transform2D xform_Bu = B->get_transform(); xform_Bu.elements[2]-=A->get_transform().get_origin(); - Matrix32 xform_B = xform_Bu * B->get_shape_transform(shape_B); + Transform2D xform_B = xform_Bu * B->get_shape_transform(shape_B); Shape2DSW *shape_A_ptr=A->get_shape(shape_A); Shape2DSW *shape_B_ptr=B->get_shape(shape_B); @@ -343,7 +343,7 @@ bool BodyPair2DSW::setup(float p_step) { real_t max_penetration = space->get_contact_max_allowed_penetration(); - float bias = 0.3f; + real_t bias = 0.3; if (shape_A_ptr->get_custom_bias() || shape_B_ptr->get_custom_bias()) { if (shape_A_ptr->get_custom_bias()==0) @@ -464,7 +464,7 @@ bool BodyPair2DSW::setup(float p_step) { return do_process; } -void BodyPair2DSW::solve(float p_step) { +void BodyPair2DSW::solve(real_t p_step) { if (!collided) return; diff --git a/servers/physics_2d/body_pair_2d_sw.h b/servers/physics_2d/body_pair_2d_sw.h index a16320585e..7a4771782a 100644 --- a/servers/physics_2d/body_pair_2d_sw.h +++ b/servers/physics_2d/body_pair_2d_sw.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -66,7 +66,7 @@ class BodyPair2DSW : public Constraint2DSW { bool active; Vector2 rA,rB; bool reused; - float bounce; + real_t bounce; }; @@ -80,15 +80,15 @@ class BodyPair2DSW : public Constraint2DSW { int cc; - bool _test_ccd(float p_step,Body2DSW *p_A, int p_shape_A,const Matrix32& p_xform_A,Body2DSW *p_B, int p_shape_B,const Matrix32& p_xform_B,bool p_swap_result=false); + bool _test_ccd(real_t p_step,Body2DSW *p_A, int p_shape_A,const Transform2D& p_xform_A,Body2DSW *p_B, int p_shape_B,const Transform2D& p_xform_B,bool p_swap_result=false); void _validate_contacts(); static void _add_contact(const Vector2& p_point_A,const Vector2& p_point_B,void *p_self); _FORCE_INLINE_ void _contact_added_callback(const Vector2& p_point_A,const Vector2& p_point_B); public: - bool setup(float p_step); - void solve(float p_step); + bool setup(real_t p_step); + void solve(real_t p_step); BodyPair2DSW(Body2DSW *p_A, int p_shape_A,Body2DSW *p_B, int p_shape_B); ~BodyPair2DSW(); diff --git a/servers/physics_2d/broad_phase_2d_basic.cpp b/servers/physics_2d/broad_phase_2d_basic.cpp index 3a95bb2411..e1f6f4f92b 100644 --- a/servers/physics_2d/broad_phase_2d_basic.cpp +++ b/servers/physics_2d/broad_phase_2d_basic.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -28,7 +28,7 @@ /*************************************************************************/ #include "broad_phase_2d_basic.h" -ID BroadPhase2DBasic::create(CollisionObject2DSW *p_object_, int p_subindex) { +BroadPhase2DBasic::ID BroadPhase2DBasic::create(CollisionObject2DSW *p_object_, int p_subindex) { current++; diff --git a/servers/physics_2d/broad_phase_2d_basic.h b/servers/physics_2d/broad_phase_2d_basic.h index 80aa423819..82e91118ce 100644 --- a/servers/physics_2d/broad_phase_2d_basic.h +++ b/servers/physics_2d/broad_phase_2d_basic.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/servers/physics_2d/broad_phase_2d_hash_grid.cpp b/servers/physics_2d/broad_phase_2d_hash_grid.cpp index 953c87021f..06eead64cd 100644 --- a/servers/physics_2d/broad_phase_2d_hash_grid.cpp +++ b/servers/physics_2d/broad_phase_2d_hash_grid.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -27,7 +27,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "broad_phase_2d_hash_grid.h" -#include "globals.h" +#include "global_config.h" #define LARGE_ELEMENT_FI 1.01239812 @@ -539,14 +539,14 @@ int BroadPhase2DHashGrid::cull_segment(const Vector2& p_from, const Vector2& p_t Vector2 max; if (dir.x<0) - max.x= (Math::floor(pos.x)*cell_size - p_from.x) / dir.x; + max.x= (Math::floor((double)pos.x)*cell_size - p_from.x) / dir.x; else - max.x= (Math::floor(pos.x + 1)*cell_size - p_from.x) / dir.x; + max.x= (Math::floor((double)pos.x + 1)*cell_size - p_from.x) / dir.x; if (dir.y<0) - max.y= (Math::floor(pos.y)*cell_size - p_from.y) / dir.y; + max.y= (Math::floor((double)pos.y)*cell_size - p_from.y) / dir.y; else - max.y= (Math::floor(pos.y + 1)*cell_size - p_from.y) / dir.y; + max.y= (Math::floor((double)pos.y + 1)*cell_size - p_from.y) / dir.y; int cullcount=0; _cull<false,true>(pos,Rect2(),p_from,p_to,p_results,p_max_results,p_result_indices,cullcount); @@ -599,8 +599,10 @@ int BroadPhase2DHashGrid::cull_segment(const Vector2& p_from, const Vector2& p_t E->key()->pass=pass; -// if (use_aabb && !p_aabb.intersects(E->key()->aabb)) -// continue; + /* + if (use_aabb && !p_aabb.intersects(E->key()->aabb)) + continue; + */ if (!E->key()->aabb.intersects_segment(p_from,p_to)) continue; @@ -645,8 +647,10 @@ int BroadPhase2DHashGrid::cull_aabb(const Rect2& p_aabb,CollisionObject2DSW** p_ if (!p_aabb.intersects(E->key()->aabb)) continue; -// if (!E->key()->aabb.intersects_segment(p_from,p_to)) -// continue; + /* + if (!E->key()->aabb.intersects_segment(p_from,p_to)) + continue; + */ p_results[cullcount]=E->key()->owner; p_result_indices[cullcount]=E->key()->subindex; @@ -683,12 +687,12 @@ BroadPhase2DSW *BroadPhase2DHashGrid::_create() { BroadPhase2DHashGrid::BroadPhase2DHashGrid() { - hash_table_size = GLOBAL_DEF("physics_2d/bp_hash_table_size",4096); + hash_table_size = GLOBAL_DEF("physics/2d/bp_hash_table_size",4096); hash_table_size = Math::larger_prime(hash_table_size); hash_table = memnew_arr( PosBin*, hash_table_size); - cell_size = GLOBAL_DEF("physics_2d/cell_size",128); - large_object_min_surface = GLOBAL_DEF("physics_2d/large_object_surface_treshold_in_cells",512); + cell_size = GLOBAL_DEF("physics/2d/cell_size",128); + large_object_min_surface = GLOBAL_DEF("physics/2d/large_object_surface_treshold_in_cells",512); for(int i=0;i<hash_table_size;i++) hash_table[i]=NULL; diff --git a/servers/physics_2d/broad_phase_2d_hash_grid.h b/servers/physics_2d/broad_phase_2d_hash_grid.h index 561d488484..857053ccf0 100644 --- a/servers/physics_2d/broad_phase_2d_hash_grid.h +++ b/servers/physics_2d/broad_phase_2d_hash_grid.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/servers/physics_2d/broad_phase_2d_sw.cpp b/servers/physics_2d/broad_phase_2d_sw.cpp index 0dead94ca1..4347155c2c 100644 --- a/servers/physics_2d/broad_phase_2d_sw.cpp +++ b/servers/physics_2d/broad_phase_2d_sw.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/servers/physics_2d/broad_phase_2d_sw.h b/servers/physics_2d/broad_phase_2d_sw.h index 056ef664fd..b9ec434ae9 100644 --- a/servers/physics_2d/broad_phase_2d_sw.h +++ b/servers/physics_2d/broad_phase_2d_sw.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/servers/physics_2d/collision_object_2d_sw.cpp b/servers/physics_2d/collision_object_2d_sw.cpp index 7f9d3312b9..9ae0e40417 100644 --- a/servers/physics_2d/collision_object_2d_sw.cpp +++ b/servers/physics_2d/collision_object_2d_sw.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -29,7 +29,7 @@ #include "collision_object_2d_sw.h" #include "space_2d_sw.h" -void CollisionObject2DSW::add_shape(Shape2DSW *p_shape,const Matrix32& p_transform) { +void CollisionObject2DSW::add_shape(Shape2DSW *p_shape,const Transform2D& p_transform) { Shape s; s.shape=p_shape; @@ -63,7 +63,7 @@ void CollisionObject2DSW::set_shape_metadata(int p_index,const Variant& p_metada } -void CollisionObject2DSW::set_shape_transform(int p_index,const Matrix32& p_transform){ +void CollisionObject2DSW::set_shape_transform(int p_index,const Transform2D& p_transform){ ERR_FAIL_INDEX(p_index,shapes.size()); @@ -149,7 +149,7 @@ void CollisionObject2DSW::_update_shapes() { //not quite correct, should compute the next matrix.. Rect2 shape_aabb=s.shape->get_aabb(); - Matrix32 xform = transform * s.xform; + Transform2D xform = transform * s.xform; shape_aabb=xform.xform(shape_aabb); s.aabb_cache=shape_aabb; s.aabb_cache=s.aabb_cache.grow( (s.aabb_cache.size.x + s.aabb_cache.size.y)*0.5*0.05 ); @@ -176,7 +176,7 @@ void CollisionObject2DSW::_update_shapes_with_motion(const Vector2& p_motion) { //not quite correct, should compute the next matrix.. Rect2 shape_aabb=s.shape->get_aabb(); - Matrix32 xform = transform * s.xform; + Transform2D xform = transform * s.xform; shape_aabb=xform.xform(shape_aabb); shape_aabb=shape_aabb.merge(Rect2( shape_aabb.pos+p_motion,shape_aabb.size)); //use motion s.aabb_cache=shape_aabb; diff --git a/servers/physics_2d/collision_object_2d_sw.h b/servers/physics_2d/collision_object_2d_sw.h index 1f213d8444..0f77e9b426 100644 --- a/servers/physics_2d/collision_object_2d_sw.h +++ b/servers/physics_2d/collision_object_2d_sw.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -51,8 +51,8 @@ private: struct Shape { - Matrix32 xform; - Matrix32 xform_inv; + Transform2D xform; + Transform2D xform_inv; BroadPhase2DSW::ID bpid; Rect2 aabb_cache; //for rayqueries Shape2DSW *shape; @@ -63,8 +63,8 @@ private: Vector<Shape> shapes; Space2DSW *space; - Matrix32 transform; - Matrix32 inv_transform; + Transform2D transform; + Transform2D inv_transform; uint32_t collision_mask; uint32_t layer_mask; bool _static; @@ -77,8 +77,8 @@ protected: void _update_shapes_with_motion(const Vector2& p_motion); void _unregister_shapes(); - _FORCE_INLINE_ void _set_transform(const Matrix32& p_transform, bool p_update_shapes=true) { transform=p_transform; if (p_update_shapes) {_update_shapes();} } - _FORCE_INLINE_ void _set_inv_transform(const Matrix32& p_transform) { inv_transform=p_transform; } + _FORCE_INLINE_ void _set_transform(const Transform2D& p_transform, bool p_update_shapes=true) { transform=p_transform; if (p_update_shapes) {_update_shapes();} } + _FORCE_INLINE_ void _set_inv_transform(const Transform2D& p_transform) { inv_transform=p_transform; } void _set_static(bool p_static); virtual void _shapes_changed()=0; @@ -96,21 +96,21 @@ public: void _shape_changed(); _FORCE_INLINE_ Type get_type() const { return type; } - void add_shape(Shape2DSW *p_shape,const Matrix32& p_transform=Matrix32()); + void add_shape(Shape2DSW *p_shape,const Transform2D& p_transform=Transform2D()); void set_shape(int p_index,Shape2DSW *p_shape); - void set_shape_transform(int p_index,const Matrix32& p_transform); + void set_shape_transform(int p_index,const Transform2D& p_transform); void set_shape_metadata(int p_index,const Variant& p_metadata); _FORCE_INLINE_ int get_shape_count() const { return shapes.size(); } _FORCE_INLINE_ Shape2DSW *get_shape(int p_index) const { return shapes[p_index].shape; } - _FORCE_INLINE_ const Matrix32& get_shape_transform(int p_index) const { return shapes[p_index].xform; } - _FORCE_INLINE_ const Matrix32& get_shape_inv_transform(int p_index) const { return shapes[p_index].xform_inv; } + _FORCE_INLINE_ const Transform2D& get_shape_transform(int p_index) const { return shapes[p_index].xform; } + _FORCE_INLINE_ const Transform2D& get_shape_inv_transform(int p_index) const { return shapes[p_index].xform_inv; } _FORCE_INLINE_ const Rect2& get_shape_aabb(int p_index) const { return shapes[p_index].aabb_cache; } _FORCE_INLINE_ const Variant& get_shape_metadata(int p_index) const { return shapes[p_index].metadata; } - _FORCE_INLINE_ Matrix32 get_transform() const { return transform; } - _FORCE_INLINE_ Matrix32 get_inv_transform() const { return inv_transform; } + _FORCE_INLINE_ Transform2D get_transform() const { return transform; } + _FORCE_INLINE_ Transform2D get_inv_transform() const { return inv_transform; } _FORCE_INLINE_ Space2DSW* get_space() const { return space; } _FORCE_INLINE_ void set_shape_as_trigger(int p_idx,bool p_enable) { shapes[p_idx].trigger=p_enable; } diff --git a/servers/physics_2d/collision_solver_2d_sat.cpp b/servers/physics_2d/collision_solver_2d_sat.cpp index a6d12bdada..4c116cee3f 100644 --- a/servers/physics_2d/collision_solver_2d_sat.cpp +++ b/servers/physics_2d/collision_solver_2d_sat.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -40,8 +40,10 @@ struct _CollectorCallback2D { _FORCE_INLINE_ void call(const Vector2& p_point_A, const Vector2& p_point_B) { - //if (normal.dot(p_point_A) >= normal.dot(p_point_B)) - // return; + /* + if (normal.dot(p_point_A) >= normal.dot(p_point_B)) + return; + */ if (swap) callback(p_point_B,p_point_A,userdata); else @@ -79,7 +81,7 @@ _FORCE_INLINE_ static void _generate_contacts_point_edge(const Vector2 * p_point struct _generate_contacts_Pair { bool a; int idx; - float d; + real_t d; _FORCE_INLINE_ bool operator <(const _generate_contacts_Pair& l) const { return d< l.d; } }; @@ -106,7 +108,7 @@ _FORCE_INLINE_ static void _generate_contacts_edge_edge(const Vector2 * p_points SWAP(pA[0],pA[1]); } - float dB[2]={t.dot(p_points_B[0]),t.dot(p_points_B[1])}; + real_t dB[2]={t.dot(p_points_B[0]),t.dot(p_points_B[1])}; Vector2 pB[2]={p_points_B[0],p_points_B[1]}; if (dB[0]>dB[1]) { SWAP(dB[0],dB[1]); @@ -263,10 +265,10 @@ _FORCE_INLINE_ static void _generate_contacts_edge_edge(const Vector2 * p_points Vector2 base_B = p_points_B[0] - axis * axis.dot(p_points_B[0]); //sort all 4 points in axis - float dvec[4]={ axis.dot(p_points_A[0]), axis.dot(p_points_A[1]), axis.dot(p_points_B[0]), axis.dot(p_points_B[1]) }; + real_t dvec[4]={ axis.dot(p_points_A[0]), axis.dot(p_points_A[1]), axis.dot(p_points_B[0]), axis.dot(p_points_B[1]) }; //todo , find max/min and then use 2 central points - SortArray<float> sa; + SortArray<real_t> sa; sa.sort(dvec,4); //use the middle ones as contacts @@ -343,8 +345,8 @@ class SeparatorAxisTest2D { const ShapeA *shape_A; const ShapeB *shape_B; - const Matrix32 *transform_A; - const Matrix32 *transform_B; + const Transform2D *transform_A; + const Transform2D *transform_B; real_t best_depth; Vector2 best_axis; int best_axis_count; @@ -462,7 +464,7 @@ public: } } - // print_line("test axis: "+p_axis+" depth: "+rtos(best_depth)); + //print_line("test axis: "+p_axis+" depth: "+rtos(best_depth)); #ifdef DEBUG_ENABLED best_axis_count++; #endif @@ -560,7 +562,7 @@ public: } - _FORCE_INLINE_ SeparatorAxisTest2D(const ShapeA *p_shape_A,const Matrix32& p_transform_a, const ShapeB *p_shape_B,const Matrix32& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_A=Vector2(), const Vector2& p_motion_B=Vector2(),real_t p_margin_A=0,real_t p_margin_B=0) { + _FORCE_INLINE_ SeparatorAxisTest2D(const ShapeA *p_shape_A,const Transform2D& p_transform_a, const ShapeB *p_shape_B,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_A=Vector2(), const Vector2& p_motion_B=Vector2(),real_t p_margin_A=0,real_t p_margin_B=0) { margin_A=p_margin_A; margin_B=p_margin_B; @@ -594,11 +596,11 @@ public: (castA && castB && !separator.test_axis(((m_a)+p_motion_a-((m_b)+p_motion_b)).normalized())) ) -typedef void (*CollisionFunc)(const Shape2DSW*,const Matrix32&,const Shape2DSW*,const Matrix32&,_CollectorCallback2D *p_collector,const Vector2&,const Vector2&,float,float); +typedef void (*CollisionFunc)(const Shape2DSW*,const Transform2D&,const Shape2DSW*,const Transform2D&,_CollectorCallback2D *p_collector,const Vector2&,const Vector2&,real_t,real_t); template<bool castA, bool castB,bool withMargin> -static void _collision_segment_segment(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,float p_margin_A,float p_margin_B) { +static void _collision_segment_segment(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,real_t p_margin_A,real_t p_margin_B) { const SegmentShape2DSW *segment_A = static_cast<const SegmentShape2DSW*>(p_a); const SegmentShape2DSW *segment_B = static_cast<const SegmentShape2DSW*>(p_b); @@ -610,8 +612,10 @@ static void _collision_segment_segment(const Shape2DSW* p_a,const Matrix32& p_tr //this collision is kind of pointless - //if (!separator.test_previous_axis()) - // return; + /* + if (!separator.test_previous_axis()) + return; + */ if (!separator.test_cast()) return; @@ -641,7 +645,7 @@ static void _collision_segment_segment(const Shape2DSW* p_a,const Matrix32& p_tr } template<bool castA, bool castB,bool withMargin> -static void _collision_segment_circle(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,float p_margin_A,float p_margin_B) { +static void _collision_segment_circle(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,real_t p_margin_A,real_t p_margin_B) { const SegmentShape2DSW *segment_A = static_cast<const SegmentShape2DSW*>(p_a); @@ -674,7 +678,7 @@ static void _collision_segment_circle(const Shape2DSW* p_a,const Matrix32& p_tra } template<bool castA, bool castB,bool withMargin> -static void _collision_segment_rectangle(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,float p_margin_A,float p_margin_B) { +static void _collision_segment_rectangle(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,real_t p_margin_A,real_t p_margin_B) { const SegmentShape2DSW *segment_A = static_cast<const SegmentShape2DSW*>(p_a); const RectangleShape2DSW *rectangle_B = static_cast<const RectangleShape2DSW*>(p_b); @@ -698,7 +702,7 @@ static void _collision_segment_rectangle(const Shape2DSW* p_a,const Matrix32& p_ if (withMargin) { - Matrix32 inv = p_transform_b.affine_inverse(); + Transform2D inv = p_transform_b.affine_inverse(); Vector2 a = p_transform_a.xform(segment_A->get_a()); Vector2 b = p_transform_a.xform(segment_A->get_b()); @@ -739,7 +743,7 @@ static void _collision_segment_rectangle(const Shape2DSW* p_a,const Matrix32& p_ } template<bool castA, bool castB,bool withMargin> -static void _collision_segment_capsule(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,float p_margin_A,float p_margin_B) { +static void _collision_segment_capsule(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,real_t p_margin_A,real_t p_margin_B) { const SegmentShape2DSW *segment_A = static_cast<const SegmentShape2DSW*>(p_a); const CapsuleShape2DSW *capsule_B = static_cast<const CapsuleShape2DSW*>(p_b); @@ -771,7 +775,7 @@ static void _collision_segment_capsule(const Shape2DSW* p_a,const Matrix32& p_tr } template<bool castA, bool castB,bool withMargin> -static void _collision_segment_convex_polygon(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,float p_margin_A,float p_margin_B) { +static void _collision_segment_convex_polygon(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,real_t p_margin_A,real_t p_margin_B) { const SegmentShape2DSW *segment_A = static_cast<const SegmentShape2DSW*>(p_a); const ConvexPolygonShape2DSW *convex_B = static_cast<const ConvexPolygonShape2DSW*>(p_b); @@ -811,7 +815,7 @@ static void _collision_segment_convex_polygon(const Shape2DSW* p_a,const Matrix3 ///////// template<bool castA, bool castB,bool withMargin> -static void _collision_circle_circle(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,float p_margin_A,float p_margin_B) { +static void _collision_circle_circle(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,real_t p_margin_A,real_t p_margin_B) { const CircleShape2DSW *circle_A = static_cast<const CircleShape2DSW*>(p_a); const CircleShape2DSW *circle_B = static_cast<const CircleShape2DSW*>(p_b); @@ -834,7 +838,7 @@ static void _collision_circle_circle(const Shape2DSW* p_a,const Matrix32& p_tran } template<bool castA, bool castB,bool withMargin> -static void _collision_circle_rectangle(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,float p_margin_A,float p_margin_B) { +static void _collision_circle_rectangle(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,real_t p_margin_A,real_t p_margin_B) { const CircleShape2DSW *circle_A = static_cast<const CircleShape2DSW*>(p_a); const RectangleShape2DSW *rectangle_B = static_cast<const RectangleShape2DSW*>(p_b); @@ -850,7 +854,7 @@ static void _collision_circle_rectangle(const Shape2DSW* p_a,const Matrix32& p_t const Vector2 &sphere=p_transform_a.elements[2]; const Vector2 *axis=&p_transform_b.elements[0]; -// const Vector2& half_extents = rectangle_B->get_half_extents(); + //const Vector2& half_extents = rectangle_B->get_half_extents(); if (!separator.test_axis(axis[0].normalized())) return; @@ -858,7 +862,7 @@ static void _collision_circle_rectangle(const Shape2DSW* p_a,const Matrix32& p_t if (!separator.test_axis(axis[1].normalized())) return; - Matrix32 binv = p_transform_b.affine_inverse(); + Transform2D binv = p_transform_b.affine_inverse(); { if (!separator.test_axis( rectangle_B->get_circle_axis(p_transform_b,binv,sphere ) ) ) @@ -890,7 +894,7 @@ static void _collision_circle_rectangle(const Shape2DSW* p_a,const Matrix32& p_t } template<bool castA, bool castB,bool withMargin> -static void _collision_circle_capsule(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,float p_margin_A,float p_margin_B) { +static void _collision_circle_capsule(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,real_t p_margin_A,real_t p_margin_B) { const CircleShape2DSW *circle_A = static_cast<const CircleShape2DSW*>(p_a); const CapsuleShape2DSW *capsule_B = static_cast<const CapsuleShape2DSW*>(p_b); @@ -920,7 +924,7 @@ static void _collision_circle_capsule(const Shape2DSW* p_a,const Matrix32& p_tra } template<bool castA, bool castB,bool withMargin> -static void _collision_circle_convex_polygon(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,float p_margin_A,float p_margin_B) { +static void _collision_circle_convex_polygon(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,real_t p_margin_A,real_t p_margin_B) { const CircleShape2DSW *circle_A = static_cast<const CircleShape2DSW*>(p_a); const ConvexPolygonShape2DSW *convex_B = static_cast<const ConvexPolygonShape2DSW*>(p_b); @@ -952,7 +956,7 @@ static void _collision_circle_convex_polygon(const Shape2DSW* p_a,const Matrix32 ///////// template<bool castA, bool castB,bool withMargin> -static void _collision_rectangle_rectangle(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,float p_margin_A,float p_margin_B) { +static void _collision_rectangle_rectangle(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,real_t p_margin_A,real_t p_margin_B) { const RectangleShape2DSW *rectangle_A = static_cast<const RectangleShape2DSW*>(p_a); const RectangleShape2DSW *rectangle_B = static_cast<const RectangleShape2DSW*>(p_b); @@ -982,22 +986,22 @@ static void _collision_rectangle_rectangle(const Shape2DSW* p_a,const Matrix32& if (withMargin) { - Matrix32 invA=p_transform_a.affine_inverse(); - Matrix32 invB=p_transform_b.affine_inverse(); + Transform2D invA=p_transform_a.affine_inverse(); + Transform2D invB=p_transform_b.affine_inverse(); if (!separator.test_axis( rectangle_A->get_box_axis(p_transform_a,invA,rectangle_B,p_transform_b,invB) ) ) return; if (castA || castB) { - Matrix32 aofs = p_transform_a; + Transform2D aofs = p_transform_a; aofs.elements[2]+=p_motion_a; - Matrix32 bofs = p_transform_b; + Transform2D bofs = p_transform_b; bofs.elements[2]+=p_motion_b; - Matrix32 aofsinv = aofs.affine_inverse(); - Matrix32 bofsinv = bofs.affine_inverse(); + Transform2D aofsinv = aofs.affine_inverse(); + Transform2D bofsinv = bofs.affine_inverse(); if (castA) { @@ -1023,7 +1027,7 @@ static void _collision_rectangle_rectangle(const Shape2DSW* p_a,const Matrix32& } template<bool castA, bool castB,bool withMargin> -static void _collision_rectangle_capsule(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,float p_margin_A,float p_margin_B) { +static void _collision_rectangle_capsule(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,real_t p_margin_A,real_t p_margin_B) { const RectangleShape2DSW *rectangle_A = static_cast<const RectangleShape2DSW*>(p_a); const CapsuleShape2DSW *capsule_B = static_cast<const CapsuleShape2DSW*>(p_b); @@ -1051,7 +1055,7 @@ static void _collision_rectangle_capsule(const Shape2DSW* p_a,const Matrix32& p_ //box endpoints to capsule circles - Matrix32 boxinv = p_transform_a.affine_inverse(); + Transform2D boxinv = p_transform_a.affine_inverse(); for(int i=0;i<2;i++) { @@ -1096,7 +1100,7 @@ static void _collision_rectangle_capsule(const Shape2DSW* p_a,const Matrix32& p_ } template<bool castA, bool castB,bool withMargin> -static void _collision_rectangle_convex_polygon(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,float p_margin_A,float p_margin_B) { +static void _collision_rectangle_convex_polygon(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,real_t p_margin_A,real_t p_margin_B) { const RectangleShape2DSW *rectangle_A = static_cast<const RectangleShape2DSW*>(p_a); const ConvexPolygonShape2DSW *convex_B = static_cast<const ConvexPolygonShape2DSW*>(p_b); @@ -1118,7 +1122,7 @@ static void _collision_rectangle_convex_polygon(const Shape2DSW* p_a,const Matri return; //convex faces - Matrix32 boxinv; + Transform2D boxinv; if (withMargin) { boxinv=p_transform_a.affine_inverse(); } @@ -1158,7 +1162,7 @@ static void _collision_rectangle_convex_polygon(const Shape2DSW* p_a,const Matri ///////// template<bool castA, bool castB,bool withMargin> -static void _collision_capsule_capsule(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,float p_margin_A,float p_margin_B) { +static void _collision_capsule_capsule(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,real_t p_margin_A,real_t p_margin_B) { const CapsuleShape2DSW *capsule_A = static_cast<const CapsuleShape2DSW*>(p_a); const CapsuleShape2DSW *capsule_B = static_cast<const CapsuleShape2DSW*>(p_b); @@ -1201,7 +1205,7 @@ static void _collision_capsule_capsule(const Shape2DSW* p_a,const Matrix32& p_tr } template<bool castA, bool castB,bool withMargin> -static void _collision_capsule_convex_polygon(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,float p_margin_A,float p_margin_B) { +static void _collision_capsule_convex_polygon(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,real_t p_margin_A,real_t p_margin_B) { const CapsuleShape2DSW *capsule_A = static_cast<const CapsuleShape2DSW*>(p_a); const ConvexPolygonShape2DSW *convex_B = static_cast<const ConvexPolygonShape2DSW*>(p_b); @@ -1247,7 +1251,7 @@ static void _collision_capsule_convex_polygon(const Shape2DSW* p_a,const Matrix3 template<bool castA, bool castB,bool withMargin> -static void _collision_convex_polygon_convex_polygon(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,float p_margin_A,float p_margin_B) { +static void _collision_convex_polygon_convex_polygon(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,real_t p_margin_A,real_t p_margin_B) { const ConvexPolygonShape2DSW *convex_A = static_cast<const ConvexPolygonShape2DSW*>(p_a); @@ -1294,7 +1298,7 @@ static void _collision_convex_polygon_convex_polygon(const Shape2DSW* p_a,const //////// -bool sat_2d_calculate_penetration(const Shape2DSW *p_shape_A, const Matrix32& p_transform_A, const Vector2& p_motion_A, const Shape2DSW *p_shape_B, const Matrix32& p_transform_B,const Vector2& p_motion_B, CollisionSolver2DSW::CallbackResult p_result_callback,void *p_userdata, bool p_swap,Vector2 *sep_axis,float p_margin_A,float p_margin_B) { +bool sat_2d_calculate_penetration(const Shape2DSW *p_shape_A, const Transform2D& p_transform_A, const Vector2& p_motion_A, const Shape2DSW *p_shape_B, const Transform2D& p_transform_B,const Vector2& p_motion_B, CollisionSolver2DSW::CallbackResult p_result_callback,void *p_userdata, bool p_swap,Vector2 *sep_axis,real_t p_margin_A,real_t p_margin_B) { Physics2DServer::ShapeType type_A=p_shape_A->get_type(); @@ -1551,8 +1555,8 @@ bool sat_2d_calculate_penetration(const Shape2DSW *p_shape_A, const Matrix32& p_ const Shape2DSW *A=p_shape_A; const Shape2DSW *B=p_shape_B; - const Matrix32 *transform_A=&p_transform_A; - const Matrix32 *transform_B=&p_transform_B; + const Transform2D *transform_A=&p_transform_A; + const Transform2D *transform_B=&p_transform_B; const Vector2 *motion_A=&p_motion_A; const Vector2 *motion_B=&p_motion_B; real_t margin_A=p_margin_A,margin_B=p_margin_B; diff --git a/servers/physics_2d/collision_solver_2d_sat.h b/servers/physics_2d/collision_solver_2d_sat.h index 91aeb53030..6b698a09f2 100644 --- a/servers/physics_2d/collision_solver_2d_sat.h +++ b/servers/physics_2d/collision_solver_2d_sat.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -32,6 +32,6 @@ #include "collision_solver_2d_sw.h" -bool sat_2d_calculate_penetration(const Shape2DSW *p_shape_A, const Matrix32& p_transform_A, const Vector2& p_motion_A,const Shape2DSW *p_shape_B, const Matrix32& p_transform_B,const Vector2& p_motion_B, CollisionSolver2DSW::CallbackResult p_result_callback,void *p_userdata, bool p_swap=false,Vector2 *sep_axis=NULL,float p_margin_A=0,float p_margin_B=0); +bool sat_2d_calculate_penetration(const Shape2DSW *p_shape_A, const Transform2D& p_transform_A, const Vector2& p_motion_A,const Shape2DSW *p_shape_B, const Transform2D& p_transform_B,const Vector2& p_motion_B, CollisionSolver2DSW::CallbackResult p_result_callback,void *p_userdata, bool p_swap=false,Vector2 *sep_axis=NULL,real_t p_margin_A=0,real_t p_margin_B=0); #endif // COLLISION_SOLVER_2D_SAT_H diff --git a/servers/physics_2d/collision_solver_2d_sw.cpp b/servers/physics_2d/collision_solver_2d_sw.cpp index fcc3f8067a..3fdecdf413 100644 --- a/servers/physics_2d/collision_solver_2d_sw.cpp +++ b/servers/physics_2d/collision_solver_2d_sw.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -34,7 +34,7 @@ //#define collision_solver gjk_epa_calculate_penetration -bool CollisionSolver2DSW::solve_static_line(const Shape2DSW *p_shape_A,const Matrix32& p_transform_A,const Shape2DSW *p_shape_B,const Matrix32& p_transform_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result) { +bool CollisionSolver2DSW::solve_static_line(const Shape2DSW *p_shape_A,const Transform2D& p_transform_A,const Shape2DSW *p_shape_B,const Transform2D& p_transform_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result) { const LineShape2DSW *line = static_cast<const LineShape2DSW*>(p_shape_A); @@ -77,7 +77,7 @@ bool CollisionSolver2DSW::solve_static_line(const Shape2DSW *p_shape_A,const Mat return found; } -bool CollisionSolver2DSW::solve_raycast(const Shape2DSW *p_shape_A,const Matrix32& p_transform_A,const Shape2DSW *p_shape_B,const Matrix32& p_transform_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result,Vector2 *sep_axis) { +bool CollisionSolver2DSW::solve_raycast(const Shape2DSW *p_shape_A,const Transform2D& p_transform_A,const Shape2DSW *p_shape_B,const Transform2D& p_transform_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result,Vector2 *sep_axis) { @@ -89,7 +89,7 @@ bool CollisionSolver2DSW::solve_raycast(const Shape2DSW *p_shape_A,const Matrix3 Vector2 to = from+p_transform_A[1]*ray->get_length(); Vector2 support_A=to; - Matrix32 invb = p_transform_B.affine_inverse(); + Transform2D invb = p_transform_B.affine_inverse(); from = invb.xform(from); to = invb.xform(to); @@ -145,9 +145,9 @@ bool CollisionSolver2DSW::solve_ray(const Shape2DSW *p_shape_A,const Matrix32& p struct _ConcaveCollisionInfo2D { - const Matrix32 *transform_A; + const Transform2D *transform_A; const Shape2DSW *shape_A; - const Matrix32 *transform_B; + const Transform2D *transform_B; Vector2 motion_A; Vector2 motion_B; real_t margin_A; @@ -181,7 +181,7 @@ void CollisionSolver2DSW::concave_callback(void *p_userdata, Shape2DSW *p_convex } -bool CollisionSolver2DSW::solve_concave(const Shape2DSW *p_shape_A,const Matrix32& p_transform_A,const Vector2& p_motion_A,const Shape2DSW *p_shape_B,const Matrix32& p_transform_B,const Vector2& p_motion_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result,Vector2 *sep_axis,float p_margin_A,float p_margin_B) { +bool CollisionSolver2DSW::solve_concave(const Shape2DSW *p_shape_A,const Transform2D& p_transform_A,const Vector2& p_motion_A,const Shape2DSW *p_shape_B,const Transform2D& p_transform_B,const Vector2& p_motion_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result,Vector2 *sep_axis,real_t p_margin_A,real_t p_margin_B) { const ConcaveShape2DSW *concave_B=static_cast<const ConcaveShape2DSW*>(p_shape_B); @@ -202,8 +202,8 @@ bool CollisionSolver2DSW::solve_concave(const Shape2DSW *p_shape_A,const Matrix3 cinfo.aabb_tests=0; - Matrix32 rel_transform = p_transform_A; - rel_transform.elements[2]-=p_transform_B.elements[2]; + Transform2D rel_transform = p_transform_A; + rel_transform.elements[2]-=p_transform_B.get_origin(); //quickly compute a local Rect2 @@ -211,10 +211,10 @@ bool CollisionSolver2DSW::solve_concave(const Shape2DSW *p_shape_A,const Matrix3 for(int i=0;i<2;i++) { Vector2 axis( p_transform_B.elements[i] ); - float axis_scale = 1.0/axis.length(); + real_t axis_scale = 1.0/axis.length(); axis*=axis_scale; - float smin,smax; + real_t smin,smax; p_shape_A->project_rangev(axis,rel_transform,smin,smax); smin*=axis_scale; smax*=axis_scale; @@ -226,12 +226,12 @@ bool CollisionSolver2DSW::solve_concave(const Shape2DSW *p_shape_A,const Matrix3 concave_B->cull(local_aabb,concave_callback,&cinfo); -// print_line("Rect2 TESTS: "+itos(cinfo.aabb_tests)); + //print_line("Rect2 TESTS: "+itos(cinfo.aabb_tests)); return cinfo.collided; } -bool CollisionSolver2DSW::solve(const Shape2DSW *p_shape_A,const Matrix32& p_transform_A,const Vector2& p_motion_A,const Shape2DSW *p_shape_B,const Matrix32& p_transform_B,const Vector2& p_motion_B,CallbackResult p_result_callback,void *p_userdata,Vector2 *sep_axis,float p_margin_A,float p_margin_B) { +bool CollisionSolver2DSW::solve(const Shape2DSW *p_shape_A,const Transform2D& p_transform_A,const Vector2& p_motion_A,const Shape2DSW *p_shape_B,const Transform2D& p_transform_B,const Vector2& p_motion_B,CallbackResult p_result_callback,void *p_userdata,Vector2 *sep_axis,real_t p_margin_A,real_t p_margin_B) { @@ -255,9 +255,11 @@ bool CollisionSolver2DSW::solve(const Shape2DSW *p_shape_A,const Matrix32& p_tra if (type_B==Physics2DServer::SHAPE_LINE || type_B==Physics2DServer::SHAPE_RAY) { return false; - //if (type_B==Physics2DServer::SHAPE_RAY) { - // return false; } + /* + if (type_B==Physics2DServer::SHAPE_RAY) { + return false; + */ if (swap) { return solve_static_line(p_shape_B,p_transform_B,p_shape_A,p_transform_A,p_result_callback,p_userdata,true); diff --git a/servers/physics_2d/collision_solver_2d_sw.h b/servers/physics_2d/collision_solver_2d_sw.h index 7e3542805c..2a5fc9fe1d 100644 --- a/servers/physics_2d/collision_solver_2d_sw.h +++ b/servers/physics_2d/collision_solver_2d_sw.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -35,16 +35,16 @@ class CollisionSolver2DSW { public: typedef void (*CallbackResult)(const Vector2& p_point_A,const Vector2& p_point_B,void *p_userdata); private: - static bool solve_static_line(const Shape2DSW *p_shape_A,const Matrix32& p_transform_A,const Shape2DSW *p_shape_B,const Matrix32& p_transform_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result); + static bool solve_static_line(const Shape2DSW *p_shape_A,const Transform2D& p_transform_A,const Shape2DSW *p_shape_B,const Transform2D& p_transform_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result); static void concave_callback(void *p_userdata, Shape2DSW *p_convex); - static bool solve_concave(const Shape2DSW *p_shape_A,const Matrix32& p_transform_A,const Vector2& p_motion_A,const Shape2DSW *p_shape_B,const Matrix32& p_transform_B,const Vector2& p_motion_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result,Vector2 *sep_axis=NULL,float p_margin_A=0,float p_margin_B=0); - static bool solve_raycast(const Shape2DSW *p_shape_A,const Matrix32& p_transform_A,const Shape2DSW *p_shape_B,const Matrix32& p_transform_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result,Vector2 *sep_axis=NULL); + static bool solve_concave(const Shape2DSW *p_shape_A,const Transform2D& p_transform_A,const Vector2& p_motion_A,const Shape2DSW *p_shape_B,const Transform2D& p_transform_B,const Vector2& p_motion_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result,Vector2 *sep_axis=NULL,real_t p_margin_A=0,real_t p_margin_B=0); + static bool solve_raycast(const Shape2DSW *p_shape_A,const Transform2D& p_transform_A,const Shape2DSW *p_shape_B,const Transform2D& p_transform_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result,Vector2 *sep_axis=NULL); public: - static bool solve(const Shape2DSW *p_shape_A,const Matrix32& p_transform_A,const Vector2& p_motion_A,const Shape2DSW *p_shape_B,const Matrix32& p_transform_B,const Vector2& p_motion_B,CallbackResult p_result_callback,void *p_userdata,Vector2 *sep_axis=NULL,float p_margin_A=0,float p_margin_B=0); + static bool solve(const Shape2DSW *p_shape_A,const Transform2D& p_transform_A,const Vector2& p_motion_A,const Shape2DSW *p_shape_B,const Transform2D& p_transform_B,const Vector2& p_motion_B,CallbackResult p_result_callback,void *p_userdata,Vector2 *sep_axis=NULL,real_t p_margin_A=0,real_t p_margin_B=0); }; diff --git a/servers/physics_2d/constraint_2d_sw.h b/servers/physics_2d/constraint_2d_sw.h index f776dbfe2c..cce668405c 100644 --- a/servers/physics_2d/constraint_2d_sw.h +++ b/servers/physics_2d/constraint_2d_sw.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -31,7 +31,7 @@ #include "body_2d_sw.h" -class Constraint2DSW { +class Constraint2DSW : public RID_Data { Body2DSW **_body_ptr; int _body_count; @@ -63,8 +63,8 @@ public: _FORCE_INLINE_ int get_body_count() const { return _body_count; } - virtual bool setup(float p_step)=0; - virtual void solve(float p_step)=0; + virtual bool setup(real_t p_step)=0; + virtual void solve(real_t p_step)=0; virtual ~Constraint2DSW() {} }; diff --git a/servers/physics_2d/joints_2d_sw.cpp b/servers/physics_2d/joints_2d_sw.cpp index 958780c2e6..76adf06429 100644 --- a/servers/physics_2d/joints_2d_sw.cpp +++ b/servers/physics_2d/joints_2d_sw.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -91,7 +91,7 @@ normal_relative_velocity(Body2DSW *a, Body2DSW *b, Vector2 rA, Vector2 rB, Vecto #if 0 -bool PinJoint2DSW::setup(float p_step) { +bool PinJoint2DSW::setup(real_t p_step) { Space2DSW *space = A->get_space(); ERR_FAIL_COND_V(!space,false;) @@ -136,7 +136,7 @@ bool PinJoint2DSW::setup(float p_step) { -void PinJoint2DSW::solve(float p_step){ +void PinJoint2DSW::solve(real_t p_step){ if (!correct) return; @@ -189,7 +189,7 @@ PinJoint2DSW::~PinJoint2DSW() { #else -bool PinJoint2DSW::setup(float p_step) { +bool PinJoint2DSW::setup(real_t p_step) { Space2DSW *space = A->get_space(); ERR_FAIL_COND_V(!space,false;) @@ -215,21 +215,21 @@ bool PinJoint2DSW::setup(float p_step) { real_t B_inv_mass = B?B->get_inv_mass():0.0; - Matrix32 K1; + Transform2D K1; K1[0].x = A->get_inv_mass() + B_inv_mass; K1[1].x = 0.0f; K1[0].y = 0.0f; K1[1].y = A->get_inv_mass() + B_inv_mass; - Matrix32 K2; + Transform2D K2; K2[0].x = A->get_inv_inertia() * rA.y * rA.y; K2[1].x = -A->get_inv_inertia() * rA.x * rA.y; K2[0].y = -A->get_inv_inertia() * rA.x * rA.y; K2[1].y = A->get_inv_inertia() * rA.x * rA.x; - Matrix32 K; + Transform2D K; K[0]= K1[0] + K2[0]; K[1]= K1[1] + K2[1]; if (B) { - Matrix32 K3; + Transform2D K3; K3[0].x = B->get_inv_inertia() * rB.y * rB.y; K3[1].x = -B->get_inv_inertia() * rB.x * rB.y; K3[0].y = -B->get_inv_inertia() * rB.x * rB.y; K3[1].y = B->get_inv_inertia() * rB.x * rB.x; @@ -257,7 +257,7 @@ bool PinJoint2DSW::setup(float p_step) { return true; } -void PinJoint2DSW::solve(float p_step){ +void PinJoint2DSW::solve(real_t p_step){ // compute relative velocity @@ -370,7 +370,7 @@ mult_k(const Vector2& vr, const Vector2 &k1, const Vector2 &k2) return Vector2(vr.dot(k1), vr.dot(k2)); } -bool GrooveJoint2DSW::setup(float p_step) { +bool GrooveJoint2DSW::setup(real_t p_step) { // calculate endpoints in worldspace @@ -407,12 +407,12 @@ bool GrooveJoint2DSW::setup(float p_step) { jn_max = get_max_force() * p_step; // calculate bias velocity -// cpVect delta = cpvsub(cpvadd(b->p, joint->r2), cpvadd(a->p, joint->r1)); -// joint->bias = cpvclamp(cpvmult(delta, -joint->constraint.biasCoef*dt_inv), joint->constraint.maxBias); + //cpVect delta = cpvsub(cpvadd(b->p, joint->r2), cpvadd(a->p, joint->r1)); + //joint->bias = cpvclamp(cpvmult(delta, -joint->constraint.biasCoef*dt_inv), joint->constraint.maxBias); Vector2 delta = (B->get_transform().get_origin() +rB) - (A->get_transform().get_origin() + rA); - float _b = get_bias(); + real_t _b = get_bias(); _b=0.001; gbias=(delta*-(_b==0?space->get_constraint_bias():_b)*(1.0/p_step)).clamped(get_max_bias()); @@ -424,7 +424,7 @@ bool GrooveJoint2DSW::setup(float p_step) { return true; } -void GrooveJoint2DSW::solve(float p_step){ +void GrooveJoint2DSW::solve(real_t p_step){ // compute impulse @@ -470,7 +470,7 @@ GrooveJoint2DSW::~GrooveJoint2DSW() { ////////////////////////////////////////////// -bool DampedSpringJoint2DSW::setup(float p_step) { +bool DampedSpringJoint2DSW::setup(real_t p_step) { rA = A->get_transform().basis_xform(anchor_A); rB = B->get_transform().basis_xform(anchor_B); @@ -500,7 +500,7 @@ bool DampedSpringJoint2DSW::setup(float p_step) { return true; } -void DampedSpringJoint2DSW::solve(float p_step) { +void DampedSpringJoint2DSW::solve(real_t p_step) { // compute relative velocity real_t vrn = normal_relative_velocity(A, B, rA, rB, n) - target_vrn; diff --git a/servers/physics_2d/joints_2d_sw.h b/servers/physics_2d/joints_2d_sw.h index 86a1397c53..1be15e4edc 100644 --- a/servers/physics_2d/joints_2d_sw.h +++ b/servers/physics_2d/joints_2d_sw.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -85,8 +85,8 @@ public: virtual Physics2DServer::JointType get_type() const { return Physics2DServer::JOINT_PIN; } - virtual bool setup(float p_step); - virtual void solve(float p_step); + virtual bool setup(real_t p_step); + virtual void solve(real_t p_step); PinJoint2DSW(const Vector2& p_pos,Body2DSW* p_body_a,Body2DSW* p_body_b=NULL); @@ -106,7 +106,7 @@ class PinJoint2DSW : public Joint2DSW { Body2DSW *_arr[2]; }; - Matrix32 M; + Transform2D M; Vector2 rA,rB; Vector2 anchor_A; Vector2 anchor_B; @@ -118,8 +118,8 @@ public: virtual Physics2DServer::JointType get_type() const { return Physics2DServer::JOINT_PIN; } - virtual bool setup(float p_step); - virtual void solve(float p_step); + virtual bool setup(real_t p_step); + virtual void solve(real_t p_step); void set_param(Physics2DServer::PinJointParam p_param, real_t p_value); real_t get_param(Physics2DServer::PinJointParam p_param) const; @@ -160,8 +160,8 @@ public: virtual Physics2DServer::JointType get_type() const { return Physics2DServer::JOINT_GROOVE; } - virtual bool setup(float p_step); - virtual void solve(float p_step); + virtual bool setup(real_t p_step); + virtual void solve(real_t p_step); GrooveJoint2DSW(const Vector2& p_a_groove1,const Vector2& p_a_groove2, const Vector2& p_b_anchor, Body2DSW* p_body_a,Body2DSW* p_body_b); @@ -198,8 +198,8 @@ public: virtual Physics2DServer::JointType get_type() const { return Physics2DServer::JOINT_DAMPED_SPRING; } - virtual bool setup(float p_step); - virtual void solve(float p_step); + virtual bool setup(real_t p_step); + virtual void solve(real_t p_step); void set_param(Physics2DServer::DampedStringParam p_param, real_t p_value); real_t get_param(Physics2DServer::DampedStringParam p_param) const; diff --git a/servers/physics_2d/physics_2d_server_sw.cpp b/servers/physics_2d/physics_2d_server_sw.cpp index 8e92a475ab..920742ea0b 100644 --- a/servers/physics_2d/physics_2d_server_sw.cpp +++ b/servers/physics_2d/physics_2d_server_sw.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,7 +30,7 @@ #include "broad_phase_2d_basic.h" #include "broad_phase_2d_hash_grid.h" #include "collision_solver_2d_sw.h" -#include "globals.h" +#include "global_config.h" #include "script_language.h" #include "os/os.h" @@ -158,11 +158,11 @@ void Physics2DServerSW::_shape_col_cbk(const Vector2& p_point_A,const Vector2& p if (cbk->amount == cbk->max) { //find least deep - float min_depth=1e20; + real_t min_depth=1e20; int min_depth_idx=0; for(int i=0;i<cbk->amount;i++) { - float d = cbk->ptr[i*2+0].distance_squared_to(cbk->ptr[i*2+1]); + real_t d = cbk->ptr[i*2+0].distance_squared_to(cbk->ptr[i*2+1]); if (d<min_depth) { min_depth=d; min_depth_idx=i; @@ -170,7 +170,7 @@ void Physics2DServerSW::_shape_col_cbk(const Vector2& p_point_A,const Vector2& p } - float d = p_point_A.distance_squared_to(p_point_B); + real_t d = p_point_A.distance_squared_to(p_point_B); if (d<min_depth) return; cbk->ptr[min_depth_idx*2+0]=p_point_A; @@ -185,7 +185,7 @@ void Physics2DServerSW::_shape_col_cbk(const Vector2& p_point_A,const Vector2& p } } -bool Physics2DServerSW::shape_collide(RID p_shape_A, const Matrix32& p_xform_A,const Vector2& p_motion_A,RID p_shape_B, const Matrix32& p_xform_B, const Vector2& p_motion_B,Vector2 *r_results,int p_result_max,int &r_result_count) { +bool Physics2DServerSW::shape_collide(RID p_shape_A, const Transform2D& p_xform_A,const Vector2& p_motion_A,RID p_shape_B, const Transform2D& p_xform_B, const Vector2& p_motion_B,Vector2 *r_results,int p_result_max,int &r_result_count) { Shape2DSW *shape_A = shape_owner.get(p_shape_A); @@ -348,7 +348,7 @@ Physics2DServer::AreaSpaceOverrideMode Physics2DServerSW::area_get_space_overrid } -void Physics2DServerSW::area_add_shape(RID p_area, RID p_shape, const Matrix32& p_transform) { +void Physics2DServerSW::area_add_shape(RID p_area, RID p_shape, const Transform2D& p_transform) { Area2DSW *area = area_owner.get(p_area); ERR_FAIL_COND(!area); @@ -372,7 +372,7 @@ void Physics2DServerSW::area_set_shape(RID p_area, int p_shape_idx,RID p_shape) area->set_shape(p_shape_idx,shape); } -void Physics2DServerSW::area_set_shape_transform(RID p_area, int p_shape_idx, const Matrix32& p_transform) { +void Physics2DServerSW::area_set_shape_transform(RID p_area, int p_shape_idx, const Transform2D& p_transform) { Area2DSW *area = area_owner.get(p_area); ERR_FAIL_COND(!area); @@ -398,10 +398,10 @@ RID Physics2DServerSW::area_get_shape(RID p_area, int p_shape_idx) const { return shape->get_self(); } -Matrix32 Physics2DServerSW::area_get_shape_transform(RID p_area, int p_shape_idx) const { +Transform2D Physics2DServerSW::area_get_shape_transform(RID p_area, int p_shape_idx) const { Area2DSW *area = area_owner.get(p_area); - ERR_FAIL_COND_V(!area,Matrix32()); + ERR_FAIL_COND_V(!area,Transform2D()); return area->get_shape_transform(p_shape_idx); } @@ -462,7 +462,7 @@ void Physics2DServerSW::area_set_param(RID p_area,AreaParameter p_param,const Va }; -void Physics2DServerSW::area_set_transform(RID p_area, const Matrix32& p_transform) { +void Physics2DServerSW::area_set_transform(RID p_area, const Transform2D& p_transform) { Area2DSW *area = area_owner.get(p_area); ERR_FAIL_COND(!area); @@ -482,10 +482,10 @@ Variant Physics2DServerSW::area_get_param(RID p_area,AreaParameter p_param) cons return area->get_param(p_param); }; -Matrix32 Physics2DServerSW::area_get_transform(RID p_area) const { +Transform2D Physics2DServerSW::area_get_transform(RID p_area) const { Area2DSW *area = area_owner.get(p_area); - ERR_FAIL_COND_V(!area,Matrix32()); + ERR_FAIL_COND_V(!area,Transform2D()); return area->get_transform(); }; @@ -600,7 +600,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 Matrix32& p_transform) { +void Physics2DServerSW::body_add_shape(RID p_body, RID p_shape, const Transform2D& p_transform) { Body2DSW *body = body_owner.get(p_body); ERR_FAIL_COND(!body); @@ -624,7 +624,7 @@ void Physics2DServerSW::body_set_shape(RID p_body, int p_shape_idx,RID p_shape) body->set_shape(p_shape_idx,shape); } -void Physics2DServerSW::body_set_shape_transform(RID p_body, int p_shape_idx, const Matrix32& p_transform) { +void Physics2DServerSW::body_set_shape_transform(RID p_body, int p_shape_idx, const Transform2D& p_transform) { Body2DSW *body = body_owner.get(p_body); ERR_FAIL_COND(!body); @@ -666,10 +666,10 @@ RID Physics2DServerSW::body_get_shape(RID p_body, int p_shape_idx) const { return shape->get_self(); } -Matrix32 Physics2DServerSW::body_get_shape_transform(RID p_body, int p_shape_idx) const { +Transform2D Physics2DServerSW::body_get_shape_transform(RID p_body, int p_shape_idx) const { Body2DSW *body = body_owner.get(p_body); - ERR_FAIL_COND_V(!body,Matrix32()); + ERR_FAIL_COND_V(!body,Transform2D()); return body->get_shape_transform(p_shape_idx); } @@ -785,7 +785,7 @@ uint32_t Physics2DServerSW::body_get_collision_mask(RID p_body) const { return body->get_collision_mask(); }; -void Physics2DServerSW::body_set_param(RID p_body, BodyParameter p_param, float p_value) { +void Physics2DServerSW::body_set_param(RID p_body, BodyParameter p_param, real_t p_value) { Body2DSW *body = body_owner.get(p_body); ERR_FAIL_COND(!body); @@ -793,7 +793,7 @@ void Physics2DServerSW::body_set_param(RID p_body, BodyParameter p_param, float body->set_param(p_param,p_value); }; -float Physics2DServerSW::body_get_param(RID p_body, BodyParameter p_param) const { +real_t Physics2DServerSW::body_get_param(RID p_body, BodyParameter p_param) const { Body2DSW *body = body_owner.get(p_body); ERR_FAIL_COND_V(!body,0); @@ -837,7 +837,7 @@ Vector2 Physics2DServerSW::body_get_applied_force(RID p_body) const { return body->get_applied_force(); }; -void Physics2DServerSW::body_set_applied_torque(RID p_body, float p_torque) { +void Physics2DServerSW::body_set_applied_torque(RID p_body, real_t p_torque) { Body2DSW *body = body_owner.get(p_body); ERR_FAIL_COND(!body); @@ -846,7 +846,7 @@ void Physics2DServerSW::body_set_applied_torque(RID p_body, float p_torque) { body->wakeup(); }; -float Physics2DServerSW::body_get_applied_torque(RID p_body) const { +real_t Physics2DServerSW::body_get_applied_torque(RID p_body) const { Body2DSW *body = body_owner.get(p_body); ERR_FAIL_COND_V(!body,0); @@ -915,14 +915,14 @@ void Physics2DServerSW::body_get_collision_exceptions(RID p_body, List<RID> *p_e }; -void Physics2DServerSW::body_set_contacts_reported_depth_treshold(RID p_body, float p_treshold) { +void Physics2DServerSW::body_set_contacts_reported_depth_treshold(RID p_body, real_t p_treshold) { Body2DSW *body = body_owner.get(p_body); ERR_FAIL_COND(!body); }; -float Physics2DServerSW::body_get_contacts_reported_depth_treshold(RID p_body) const { +real_t Physics2DServerSW::body_get_contacts_reported_depth_treshold(RID p_body) const { Body2DSW *body = body_owner.get(p_body); ERR_FAIL_COND_V(!body,0); @@ -973,7 +973,7 @@ Vector2 Physics2DServerSW::body_get_one_way_collision_direction(RID p_body) cons } -void Physics2DServerSW::body_set_one_way_collision_max_depth(RID p_body,float p_max_depth) { +void Physics2DServerSW::body_set_one_way_collision_max_depth(RID p_body,real_t p_max_depth) { Body2DSW *body = body_owner.get(p_body); ERR_FAIL_COND(!body); @@ -981,7 +981,7 @@ void Physics2DServerSW::body_set_one_way_collision_max_depth(RID p_body,float p_ } -float Physics2DServerSW::body_get_one_way_collision_max_depth(RID p_body) const { +real_t Physics2DServerSW::body_get_one_way_collision_max_depth(RID p_body) const { Body2DSW *body = body_owner.get(p_body); ERR_FAIL_COND_V(!body,0); @@ -998,7 +998,7 @@ void Physics2DServerSW::body_set_force_integration_callback(RID p_body,Object *p } -bool Physics2DServerSW::body_collide_shape(RID p_body, int p_body_shape, RID p_shape, const Matrix32& p_shape_xform,const Vector2& p_motion,Vector2 *r_results,int p_result_max,int &r_result_count) { +bool Physics2DServerSW::body_collide_shape(RID p_body, int p_body_shape, RID p_shape, const Transform2D& p_shape_xform,const Vector2& p_motion,Vector2 *r_results,int p_result_max,int &r_result_count) { Body2DSW *body = body_owner.get(p_body); ERR_FAIL_COND_V(!body,false); @@ -1016,7 +1016,7 @@ void Physics2DServerSW::body_set_pickable(RID p_body,bool p_pickable) { } -bool Physics2DServerSW::body_test_motion(RID p_body, const Matrix32 &p_from, const Vector2& p_motion, float p_margin, MotionResult *r_result) { +bool Physics2DServerSW::body_test_motion(RID p_body, const Transform2D &p_from, const Vector2& p_motion, real_t p_margin, MotionResult *r_result) { Body2DSW *body = body_owner.get(p_body); ERR_FAIL_COND_V(!body,false); @@ -1176,11 +1176,13 @@ void Physics2DServerSW::free(RID p_rid) { Body2DSW *body = body_owner.get(p_rid); -// if (body->get_state_query()) -// _clear_query(body->get_state_query()); + /* + if (body->get_state_query()) + _clear_query(body->get_state_query()); -// if (body->get_direct_state_query()) -// _clear_query(body->get_direct_state_query()); + if (body->get_direct_state_query()) + _clear_query(body->get_direct_state_query()); + */ body->set_space(NULL); @@ -1203,8 +1205,10 @@ void Physics2DServerSW::free(RID p_rid) { Area2DSW *area = area_owner.get(p_rid); -// if (area->get_monitor_query()) -// _clear_query(area->get_monitor_query()); + /* + if (area->get_monitor_query()) + _clear_query(area->get_monitor_query()); + */ area->set_space(NULL); @@ -1259,7 +1263,7 @@ void Physics2DServerSW::init() { }; -void Physics2DServerSW::step(float p_step) { +void Physics2DServerSW::step(real_t p_step) { if (!active) @@ -1380,13 +1384,13 @@ Physics2DServerSW::Physics2DServerSW() { singletonsw=this; BroadPhase2DSW::create_func=BroadPhase2DHashGrid::_create; -// BroadPhase2DSW::create_func=BroadPhase2DBasic::_create; + //BroadPhase2DSW::create_func=BroadPhase2DBasic::_create; active=true; island_count=0; active_objects=0; collision_pairs=0; - using_threads=int(Globals::get_singleton()->get("physics_2d/thread_model"))==2; + using_threads=int(GlobalConfig::get_singleton()->get("physics/2d/thread_model"))==2; }; diff --git a/servers/physics_2d/physics_2d_server_sw.h b/servers/physics_2d/physics_2d_server_sw.h index 1dc735289a..e33e2d78c7 100644 --- a/servers/physics_2d/physics_2d_server_sw.h +++ b/servers/physics_2d/physics_2d_server_sw.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -39,7 +39,7 @@ class Physics2DServerSW : public Physics2DServer { - OBJ_TYPE( Physics2DServerSW, Physics2DServer ); + GDCLASS( Physics2DServerSW, Physics2DServer ); friend class Physics2DDirectSpaceStateSW; friend class Physics2DDirectBodyStateSW; @@ -70,13 +70,13 @@ friend class Physics2DDirectBodyStateSW; static Physics2DServerSW *singletonsw; -// void _clear_query(Query2DSW *p_query); + //void _clear_query(Query2DSW *p_query); public: struct CollCbkData { Vector2 valid_dir; - float valid_depth; + real_t valid_depth; int max; int amount; Vector2 *ptr; @@ -93,7 +93,7 @@ public: virtual Variant shape_get_data(RID p_shape) const; virtual real_t shape_get_custom_solver_bias(RID p_shape) const; - virtual bool shape_collide(RID p_shape_A, const Matrix32& p_xform_A,const Vector2& p_motion_A,RID p_shape_B, const Matrix32& p_xform_B, const Vector2& p_motion_B,Vector2 *r_results,int p_result_max,int &r_result_count); + virtual bool shape_collide(RID p_shape_A, const Transform2D& p_xform_A,const Vector2& p_motion_A,RID p_shape_B, const Transform2D& p_xform_B, const Vector2& p_motion_B,Vector2 *r_results,int p_result_max,int &r_result_count); /* SPACE API */ @@ -123,13 +123,13 @@ 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 Matrix32& p_transform=Matrix32()); + virtual void area_add_shape(RID p_area, RID p_shape, const Transform2D& p_transform=Transform2D()); 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 Matrix32& p_transform); + virtual void area_set_shape_transform(RID p_area, int p_shape_idx, const Transform2D& p_transform); virtual int area_get_shape_count(RID p_area) const; virtual RID area_get_shape(RID p_area, int p_shape_idx) const; - virtual Matrix32 area_get_shape_transform(RID p_area, int p_shape_idx) const; + virtual Transform2D area_get_shape_transform(RID p_area, int p_shape_idx) const; virtual void area_remove_shape(RID p_area, int p_shape_idx); virtual void area_clear_shapes(RID p_area); @@ -138,10 +138,10 @@ public: 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); - virtual void area_set_transform(RID p_area, const Matrix32& p_transform); + virtual void area_set_transform(RID p_area, const Transform2D& p_transform); virtual Variant area_get_param(RID p_parea,AreaParameter p_param) const; - virtual Matrix32 area_get_transform(RID p_area) const; + virtual Transform2D area_get_transform(RID p_area) const; virtual void area_set_monitorable(RID p_area,bool p_monitorable); virtual void area_set_collision_mask(RID p_area,uint32_t p_mask); virtual void area_set_layer_mask(RID p_area,uint32_t p_mask); @@ -163,15 +163,15 @@ 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 Matrix32& p_transform=Matrix32()); + virtual void body_add_shape(RID p_body, RID p_shape, const Transform2D& p_transform=Transform2D()); 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 Matrix32& p_transform); + 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); virtual int body_get_shape_count(RID p_body) const; virtual RID body_get_shape(RID p_body, int p_shape_idx) const; - virtual Matrix32 body_get_shape_transform(RID p_body, int p_shape_idx) const; + virtual Transform2D body_get_shape_transform(RID p_body, int p_shape_idx) const; virtual Variant body_get_shape_metadata(RID p_body, int p_shape_idx) const; @@ -193,8 +193,8 @@ public: virtual void body_set_collision_mask(RID p_body, uint32_t p_mask); virtual uint32_t body_get_collision_mask(RID p_) const; - virtual void body_set_param(RID p_body, BodyParameter p_param, float p_value); - virtual float body_get_param(RID p_body, BodyParameter p_param) const; + virtual void body_set_param(RID p_body, BodyParameter p_param, real_t p_value); + virtual real_t body_get_param(RID p_body, BodyParameter p_param) const; virtual void body_set_state(RID p_body, BodyState p_state, const Variant& p_variant); @@ -203,8 +203,8 @@ public: virtual void body_set_applied_force(RID p_body, const Vector2& p_force); virtual Vector2 body_get_applied_force(RID p_body) const; - virtual void body_set_applied_torque(RID p_body, float p_torque); - virtual float body_get_applied_torque(RID p_body) const; + virtual void body_set_applied_torque(RID p_body, real_t p_torque); + virtual real_t body_get_applied_torque(RID p_body) const; virtual void body_add_force(RID p_body, const Vector2& p_offset, const Vector2& p_force); @@ -215,8 +215,8 @@ public: virtual void body_remove_collision_exception(RID p_body, RID p_body_b); virtual void body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions); - virtual void body_set_contacts_reported_depth_treshold(RID p_body, float p_treshold); - virtual float body_get_contacts_reported_depth_treshold(RID p_body) const; + virtual void body_set_contacts_reported_depth_treshold(RID p_body, real_t p_treshold); + virtual real_t body_get_contacts_reported_depth_treshold(RID p_body) const; virtual void body_set_omit_force_integration(RID p_body,bool p_omit); virtual bool body_is_omitting_force_integration(RID p_body) const; @@ -227,16 +227,16 @@ public: virtual void body_set_one_way_collision_direction(RID p_body,const Vector2& p_direction); virtual Vector2 body_get_one_way_collision_direction(RID p_body) const; - virtual void body_set_one_way_collision_max_depth(RID p_body,float p_max_depth); - virtual float body_get_one_way_collision_max_depth(RID p_body) const; + virtual void body_set_one_way_collision_max_depth(RID p_body,real_t p_max_depth); + virtual real_t body_get_one_way_collision_max_depth(RID p_body) const; virtual void body_set_force_integration_callback(RID p_body,Object *p_receiver,const StringName& p_method,const Variant& p_udata=Variant()); - virtual bool body_collide_shape(RID p_body, int p_body_shape,RID p_shape, const Matrix32& p_shape_xform,const Vector2& p_motion,Vector2 *r_results,int p_result_max,int &r_result_count); + virtual bool body_collide_shape(RID p_body, int p_body_shape,RID p_shape, const Transform2D& p_shape_xform,const Vector2& p_motion,Vector2 *r_results,int p_result_max,int &r_result_count); virtual void body_set_pickable(RID p_body,bool p_pickable); - virtual bool body_test_motion(RID p_body,const Matrix32& p_from,const Vector2& p_motion,float p_margin=0.001,MotionResult *r_result=NULL); + virtual bool body_test_motion(RID p_body,const Transform2D& p_from,const Vector2& p_motion,real_t p_margin=0.001,MotionResult *r_result=NULL); /* JOINT API */ @@ -260,7 +260,7 @@ public: virtual void set_active(bool p_active); virtual void init(); - virtual void step(float p_step); + virtual void step(real_t p_step); virtual void sync(); virtual void flush_queries(); virtual void end_sync(); diff --git a/servers/physics_2d/physics_2d_server_wrap_mt.cpp b/servers/physics_2d/physics_2d_server_wrap_mt.cpp index 3e8b284b9b..34ba149d23 100644 --- a/servers/physics_2d/physics_2d_server_wrap_mt.cpp +++ b/servers/physics_2d/physics_2d_server_wrap_mt.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -35,7 +35,7 @@ void Physics2DServerWrapMT::thread_exit() { exit=true; } -void Physics2DServerWrapMT::thread_step(float p_delta) { +void Physics2DServerWrapMT::thread_step(real_t p_delta) { physics_2d_server->step(p_delta); step_sem->post(); @@ -75,7 +75,7 @@ void Physics2DServerWrapMT::thread_loop() { /* EVENT QUEUING */ -void Physics2DServerWrapMT::step(float p_step) { +void Physics2DServerWrapMT::step(real_t p_step) { if (create_thread) { @@ -95,7 +95,7 @@ void Physics2DServerWrapMT::sync() { else step_sem->wait(); //must not wait if a step was not issued } - physics_2d_server->sync();; + physics_2d_server->sync(); } void Physics2DServerWrapMT::flush_queries(){ @@ -105,7 +105,7 @@ void Physics2DServerWrapMT::flush_queries(){ void Physics2DServerWrapMT::end_sync() { - physics_2d_server->end_sync();; + physics_2d_server->end_sync(); } void Physics2DServerWrapMT::init() { @@ -168,12 +168,12 @@ Physics2DServerWrapMT::Physics2DServerWrapMT(Physics2DServer* p_contained,bool p step_thread_up=false; alloc_mutex=Mutex::create(); - shape_pool_max_size=GLOBAL_DEF("core/thread_rid_pool_prealloc",20); - area_pool_max_size=GLOBAL_DEF("core/thread_rid_pool_prealloc",20); - body_pool_max_size=GLOBAL_DEF("core/thread_rid_pool_prealloc",20); - pin_joint_pool_max_size=GLOBAL_DEF("core/thread_rid_pool_prealloc",20); - groove_joint_pool_max_size=GLOBAL_DEF("core/thread_rid_pool_prealloc",20); - damped_spring_joint_pool_max_size=GLOBAL_DEF("core/thread_rid_pool_prealloc",20); + shape_pool_max_size=GLOBAL_GET("memory/multithread/thread_rid_pool_prealloc"); + area_pool_max_size=GLOBAL_GET("memory/multithread/thread_rid_pool_prealloc"); + body_pool_max_size=GLOBAL_GET("memory/multithread/thread_rid_pool_prealloc"); + pin_joint_pool_max_size=GLOBAL_GET("memory/multithread/thread_rid_pool_prealloc"); + groove_joint_pool_max_size=GLOBAL_GET("memory/multithread/thread_rid_pool_prealloc"); + damped_spring_joint_pool_max_size=GLOBAL_GET("memory/multithread/thread_rid_pool_prealloc"); if (!p_create_thread) { server_thread=Thread::get_caller_ID(); diff --git a/servers/physics_2d/physics_2d_server_wrap_mt.h b/servers/physics_2d/physics_2d_server_wrap_mt.h index 57da958f9a..f8b533080e 100644 --- a/servers/physics_2d/physics_2d_server_wrap_mt.h +++ b/servers/physics_2d/physics_2d_server_wrap_mt.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -33,7 +33,7 @@ #include "servers/physics_2d_server.h" #include "command_queue_mt.h" #include "os/thread.h" -#include "globals.h" +#include "global_config.h" #ifdef DEBUG_SYNC #define SYNC_DEBUG print_line("sync on: "+String(__FUNCTION__)); @@ -60,7 +60,7 @@ class Physics2DServerWrapMT : public Physics2DServer { Semaphore *step_sem; int step_pending; - void thread_step(float p_delta); + void thread_step(real_t p_delta); void thread_flush(); void thread_exit(); @@ -100,7 +100,7 @@ public: //these work well, but should be used from the main thread only - bool shape_collide(RID p_shape_A, const Matrix32& p_xform_A,const Vector2& p_motion_A,RID p_shape_B, const Matrix32& p_xform_B, const Vector2& p_motion_B,Vector2 *r_results,int p_result_max,int &r_result_count) { + bool shape_collide(RID p_shape_A, const Transform2D& p_xform_A,const Vector2& p_motion_A,RID p_shape_B, const Transform2D& p_xform_B, const Vector2& p_motion_B,Vector2 *r_results,int p_result_max,int &r_result_count) { ERR_FAIL_COND_V(main_thread!=Thread::get_caller_ID(),false); return physics_2d_server->shape_collide(p_shape_A,p_xform_A,p_motion_A,p_shape_B,p_xform_B,p_motion_B,r_results,p_result_max,r_result_count); @@ -150,13 +150,13 @@ public: FUNC2(area_set_space_override_mode,RID,AreaSpaceOverrideMode); FUNC1RC(AreaSpaceOverrideMode,area_get_space_override_mode,RID); - FUNC3(area_add_shape,RID,RID,const Matrix32&); + FUNC3(area_add_shape,RID,RID,const Transform2D&); FUNC3(area_set_shape,RID,int,RID); - FUNC3(area_set_shape_transform,RID,int,const Matrix32&); + FUNC3(area_set_shape_transform,RID,int,const Transform2D&); FUNC1RC(int,area_get_shape_count,RID); FUNC2RC(RID,area_get_shape,RID,int); - FUNC2RC(Matrix32,area_get_shape_transform,RID,int); + FUNC2RC(Transform2D,area_get_shape_transform,RID,int); FUNC2(area_remove_shape,RID,int); FUNC1(area_clear_shapes,RID); @@ -164,10 +164,10 @@ public: FUNC1RC(ObjectID,area_get_object_instance_ID,RID); FUNC3(area_set_param,RID,AreaParameter,const Variant&); - FUNC2(area_set_transform,RID,const Matrix32&); + FUNC2(area_set_transform,RID,const Transform2D&); FUNC2RC(Variant,area_get_param,RID,AreaParameter); - FUNC1RC(Matrix32,area_get_transform,RID); + FUNC1RC(Transform2D,area_get_transform,RID); FUNC2(area_set_collision_mask,RID,uint32_t); FUNC2(area_set_layer_mask,RID,uint32_t); @@ -191,13 +191,13 @@ public: FUNC1RC(BodyMode,body_get_mode,RID); - FUNC3(body_add_shape,RID,RID,const Matrix32&); + FUNC3(body_add_shape,RID,RID,const Transform2D&); FUNC3(body_set_shape,RID,int,RID); - FUNC3(body_set_shape_transform,RID,int,const Matrix32&); + FUNC3(body_set_shape_transform,RID,int,const Transform2D&); FUNC3(body_set_shape_metadata,RID,int,const Variant&); FUNC1RC(int,body_get_shape_count,RID); - FUNC2RC(Matrix32,body_get_shape_transform,RID,int); + FUNC2RC(Transform2D,body_get_shape_transform,RID,int); FUNC2RC(Variant,body_get_shape_metadata,RID,int); FUNC2RC(RID,body_get_shape,RID,int); @@ -220,8 +220,8 @@ public: FUNC1RC(uint32_t,body_get_collision_mask,RID); - FUNC3(body_set_param,RID,BodyParameter,float); - FUNC2RC(float,body_get_param,RID,BodyParameter); + FUNC3(body_set_param,RID,BodyParameter,real_t); + FUNC2RC(real_t,body_get_param,RID,BodyParameter); FUNC3(body_set_state,RID,BodyState,const Variant&); @@ -230,8 +230,8 @@ public: FUNC2(body_set_applied_force,RID,const Vector2&); FUNC1RC(Vector2,body_get_applied_force,RID); - FUNC2(body_set_applied_torque,RID,float); - FUNC1RC(float,body_get_applied_torque,RID); + FUNC2(body_set_applied_torque,RID,real_t); + FUNC1RC(real_t,body_get_applied_torque,RID); FUNC3(body_add_force,RID,const Vector2&,const Vector2&); FUNC3(body_apply_impulse,RID,const Vector2&,const Vector2&); @@ -247,12 +247,12 @@ public: FUNC2(body_set_one_way_collision_direction,RID,const Vector2&); FUNC1RC(Vector2,body_get_one_way_collision_direction,RID); - FUNC2(body_set_one_way_collision_max_depth,RID,float); - FUNC1RC(float,body_get_one_way_collision_max_depth,RID); + FUNC2(body_set_one_way_collision_max_depth,RID,real_t); + FUNC1RC(real_t,body_get_one_way_collision_max_depth,RID); - FUNC2(body_set_contacts_reported_depth_treshold,RID,float); - FUNC1RC(float,body_get_contacts_reported_depth_treshold,RID); + FUNC2(body_set_contacts_reported_depth_treshold,RID,real_t); + FUNC1RC(real_t,body_get_contacts_reported_depth_treshold,RID); FUNC2(body_set_omit_force_integration,RID,bool); FUNC1RC(bool,body_is_omitting_force_integration,RID); @@ -260,13 +260,13 @@ public: FUNC4(body_set_force_integration_callback,RID ,Object *,const StringName& ,const Variant& ); - bool body_collide_shape(RID p_body, int p_body_shape,RID p_shape, const Matrix32& p_shape_xform,const Vector2& p_motion,Vector2 *r_results,int p_result_max,int &r_result_count) { + bool body_collide_shape(RID p_body, int p_body_shape,RID p_shape, const Transform2D& p_shape_xform,const Vector2& p_motion,Vector2 *r_results,int p_result_max,int &r_result_count) { return physics_2d_server->body_collide_shape(p_body,p_body_shape,p_shape,p_shape_xform,p_motion,r_results,p_result_max,r_result_count); } FUNC2(body_set_pickable,RID,bool); - bool body_test_motion(RID p_body,const Matrix32& p_from,const Vector2& p_motion,float p_margin=0.001,MotionResult *r_result=NULL) { + bool body_test_motion(RID p_body,const Transform2D& p_from,const Vector2& p_motion,real_t p_margin=0.001,MotionResult *r_result=NULL) { ERR_FAIL_COND_V(main_thread!=Thread::get_caller_ID(),false); return physics_2d_server->body_test_motion(p_body,p_from,p_motion,p_margin,r_result); @@ -303,7 +303,7 @@ public: FUNC1(set_active,bool); virtual void init(); - virtual void step(float p_step); + virtual void step(real_t p_step); virtual void sync(); virtual void end_sync(); virtual void flush_queries(); @@ -320,7 +320,7 @@ public: template<class T> static Physics2DServer* init_server() { - int tm = GLOBAL_DEF("physics_2d/thread_model",1); + int tm = GLOBAL_DEF("physics/2d/thread_model",1); if (tm==0) //single unsafe return memnew( T ); else if (tm==1) //single saef diff --git a/servers/physics_2d/shape_2d_sw.cpp b/servers/physics_2d/shape_2d_sw.cpp index 9291aa6c17..b6eb427131 100644 --- a/servers/physics_2d/shape_2d_sw.cpp +++ b/servers/physics_2d/shape_2d_sw.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -136,7 +136,7 @@ bool LineShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p_en return true; } -real_t LineShape2DSW::get_moment_of_inertia(float p_mass, const Vector2 &p_scale) const { +real_t LineShape2DSW::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const { return 0; } @@ -191,7 +191,7 @@ bool RayShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p_end } -real_t RayShape2DSW::get_moment_of_inertia(float p_mass, const Vector2 &p_scale) const { +real_t RayShape2DSW::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const { return 0; //rays are mass-less } @@ -224,7 +224,7 @@ void SegmentShape2DSW::get_supports(const Vector2& p_normal,Vector2 *r_supports, } - float dp=p_normal.dot(b-a); + real_t dp=p_normal.dot(b-a); if (dp>0) *r_supports=b; else @@ -252,14 +252,14 @@ bool SegmentShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p return true; } -real_t SegmentShape2DSW::get_moment_of_inertia(float p_mass, const Vector2 &p_scale) const { +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.0f + ofs.length_squared()); + return p_mass*(l*l/12.0 + ofs.length_squared()); } void SegmentShape2DSW::set_data(const Variant& p_data) { @@ -336,7 +336,7 @@ bool CircleShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p_ return true; } -real_t CircleShape2DSW::get_moment_of_inertia(float p_mass, const Vector2 &p_scale) const { +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); @@ -367,11 +367,11 @@ void RectangleShape2DSW::get_supports(const Vector2& p_normal,Vector2 *r_support Vector2 ag; ag[i]=1.0; - float dp = ag.dot(p_normal); + real_t dp = ag.dot(p_normal); if (Math::abs(dp)<_SEGMENT_IS_VALID_SUPPORT_TRESHOLD) continue; - float sgn = dp>0 ? 1.0 : -1.0; + real_t sgn = dp>0 ? 1.0 : -1.0; r_amount=2; @@ -407,10 +407,10 @@ bool RectangleShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& return get_aabb().intersects_segment(p_begin,p_end,&r_point,&r_normal); } -real_t RectangleShape2DSW::get_moment_of_inertia(float p_mass,const Vector2& p_scale) const { +real_t RectangleShape2DSW::get_moment_of_inertia(real_t p_mass,const Size2& p_scale) const { Vector2 he2=half_extents*2*p_scale; - return p_mass*he2.dot(he2)/12.0f; + return p_mass*he2.dot(he2)/12.0; } void RectangleShape2DSW::set_data(const Variant& p_data) { @@ -438,7 +438,7 @@ void CapsuleShape2DSW::get_supports(const Vector2& p_normal,Vector2 *r_supports, Vector2 n=p_normal; - float d = n.y; + real_t d = n.y; if (Math::abs( d )<(1.0-_SEGMENT_IS_VALID_SUPPORT_TRESHOLD) ) { @@ -455,7 +455,7 @@ void CapsuleShape2DSW::get_supports(const Vector2& p_normal,Vector2 *r_supports, } else { - float h = (d > 0) ? height : -height; + real_t h = (d > 0) ? height : -height; n*=radius; n.y += h*0.5; @@ -479,7 +479,7 @@ bool CapsuleShape2DSW::contains_point(const Vector2& p_point) const { bool CapsuleShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const { - float d = 1e10; + real_t d = 1e10; Vector2 n = (p_end-p_begin).normalized(); bool collided=false; @@ -488,7 +488,7 @@ bool CapsuleShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p Vector2 begin = p_begin; Vector2 end = p_end; - float ofs = (i==0)?-height*0.5:height*0.5; + real_t ofs = (i==0)?-height*0.5:height*0.5; begin.y+=ofs; end.y+=ofs; @@ -540,10 +540,10 @@ bool CapsuleShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p return collided; //todo } -real_t CapsuleShape2DSW::get_moment_of_inertia(float p_mass, const Vector2 &p_scale) const { +real_t CapsuleShape2DSW::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const { Vector2 he2=Vector2(radius*2,height+radius*2)*p_scale; - return p_mass*he2.dot(he2)/12.0f; + return p_mass*he2.dot(he2)/12.0; } void CapsuleShape2DSW::set_data(const Variant& p_data) { @@ -619,7 +619,7 @@ bool ConvexPolygonShape2DSW::contains_point(const Vector2& p_point) const { for(int i=0;i<point_count;i++) { - float d = points[i].normal.dot(p_point) - points[i].normal.dot(points[i].pos); + real_t d = points[i].normal.dot(p_point) - points[i].normal.dot(points[i].pos); if (d>0) out=true; else @@ -639,8 +639,10 @@ bool ConvexPolygonShape2DSW::intersect_segment(const Vector2& p_begin,const Vect for(int i=0;i<point_count;i++) { //hmm crap.. no can do.. - //if (d.dot(points[i].normal)>=0) - // continue; + /* + if (d.dot(points[i].normal)>=0) + continue; + */ Vector2 res; @@ -648,7 +650,7 @@ bool ConvexPolygonShape2DSW::intersect_segment(const Vector2& p_begin,const Vect if (!Geometry::segment_intersects_segment_2d(p_begin,p_end,points[i].pos,points[(i+1)%point_count].pos,&res)) continue; - float nd = n.dot(res); + real_t nd = n.dot(res); if (nd<d) { d=nd; @@ -670,7 +672,7 @@ bool ConvexPolygonShape2DSW::intersect_segment(const Vector2& p_begin,const Vect return inters; //todo } -real_t ConvexPolygonShape2DSW::get_moment_of_inertia(float p_mass,const Vector2& p_scale) const { +real_t ConvexPolygonShape2DSW::get_moment_of_inertia(real_t p_mass,const Size2& p_scale) const { Rect2 aabb; aabb.pos=points[0].pos*p_scale; @@ -679,12 +681,12 @@ real_t ConvexPolygonShape2DSW::get_moment_of_inertia(float p_mass,const Vector2& aabb.expand_to(points[i].pos*p_scale); } - return p_mass*aabb.size.dot(aabb.size)/12.0f + p_mass * (aabb.pos+aabb.size*0.5).length_squared(); + return p_mass*aabb.size.dot(aabb.size)/12.0 + p_mass * (aabb.pos+aabb.size*0.5).length_squared(); } void ConvexPolygonShape2DSW::set_data(const Variant& p_data) { - ERR_FAIL_COND(p_data.get_type()!=Variant::VECTOR2_ARRAY && p_data.get_type()!=Variant::REAL_ARRAY); + ERR_FAIL_COND(p_data.get_type()!=Variant::POOL_VECTOR2_ARRAY && p_data.get_type()!=Variant::POOL_REAL_ARRAY); if (points) @@ -692,12 +694,12 @@ void ConvexPolygonShape2DSW::set_data(const Variant& p_data) { points=NULL; point_count=0; - if (p_data.get_type()==Variant::VECTOR2_ARRAY) { - DVector<Vector2> arr=p_data; + if (p_data.get_type()==Variant::POOL_VECTOR2_ARRAY) { + PoolVector<Vector2> arr=p_data; ERR_FAIL_COND(arr.size()==0); point_count=arr.size(); points = memnew_arr(Point,point_count); - DVector<Vector2>::Read r = arr.read(); + PoolVector<Vector2>::Read r = arr.read(); for(int i=0;i<point_count;i++) { points[i].pos=r[i]; @@ -711,12 +713,12 @@ void ConvexPolygonShape2DSW::set_data(const Variant& p_data) { } } else { - DVector<real_t> dvr = p_data; + PoolVector<real_t> dvr = p_data; point_count=dvr.size()/4; ERR_FAIL_COND(point_count==0); points = memnew_arr(Point,point_count); - DVector<real_t>::Read r = dvr.read(); + PoolVector<real_t>::Read r = dvr.read(); for(int i=0;i<point_count;i++) { @@ -741,7 +743,7 @@ void ConvexPolygonShape2DSW::set_data(const Variant& p_data) { Variant ConvexPolygonShape2DSW::get_data() const { - DVector<Vector2> dvr; + PoolVector<Vector2> dvr; dvr.resize(point_count); @@ -816,8 +818,10 @@ bool ConcavePolygonShape2DSW::intersect_segment(const Vector2& p_begin,const Vec real_t d=1e10; bool inters=false; - //for(int i=0;i<bvh_depth;i++) - // stack[i]=0; + /* + for(int i=0;i<bvh_depth;i++) + stack[i]=0; + */ int level=0; @@ -855,7 +859,7 @@ bool ConcavePolygonShape2DSW::intersect_segment(const Vector2& p_begin,const Vec if (Geometry::segment_intersects_segment_2d(p_begin,p_end,a,b,&res)) { - float nd = n.dot(res); + real_t nd = n.dot(res); if (nd<d) { d=nd; @@ -964,13 +968,13 @@ int ConcavePolygonShape2DSW::_generate_bvh(BVH *p_bvh,int p_len,int p_depth) { void ConcavePolygonShape2DSW::set_data(const Variant& p_data) { - ERR_FAIL_COND(p_data.get_type()!=Variant::VECTOR2_ARRAY && p_data.get_type()!=Variant::REAL_ARRAY); + ERR_FAIL_COND(p_data.get_type()!=Variant::POOL_VECTOR2_ARRAY && p_data.get_type()!=Variant::POOL_REAL_ARRAY); Rect2 aabb; - if (p_data.get_type()==Variant::VECTOR2_ARRAY) { + if (p_data.get_type()==Variant::POOL_VECTOR2_ARRAY) { - DVector<Vector2> p2arr = p_data; + PoolVector<Vector2> p2arr = p_data; int len = p2arr.size(); ERR_FAIL_COND(len%2); @@ -984,7 +988,7 @@ void ConcavePolygonShape2DSW::set_data(const Variant& p_data) { return; } - DVector<Vector2>::Read arr = p2arr.read(); + PoolVector<Vector2>::Read arr = p2arr.read(); Map<Point2,int> pointmap; for(int i=0;i<len;i+=2) { @@ -1046,17 +1050,17 @@ void ConcavePolygonShape2DSW::set_data(const Variant& p_data) { Variant ConcavePolygonShape2DSW::get_data() const { - DVector<Vector2> rsegments; + PoolVector<Vector2> rsegments; int len = segments.size(); rsegments.resize(len*2); - DVector<Vector2>::Write w = rsegments.write(); + PoolVector<Vector2>::Write w = rsegments.write(); for(int i=0;i<len;i++) { w[(i<<1)+0]=points[segments[i].points[0]]; w[(i<<1)+1]=points[segments[i].points[1]]; } - w=DVector<Vector2>::Write(); + w=PoolVector<Vector2>::Write(); return rsegments; } @@ -1077,8 +1081,10 @@ void ConcavePolygonShape2DSW::cull(const Rect2& p_local_aabb,Callback p_callback }; - //for(int i=0;i<bvh_depth;i++) - // stack[i]=0; + /* + for(int i=0;i<bvh_depth;i++) + stack[i]=0; + */ int level=0; diff --git a/servers/physics_2d/shape_2d_sw.h b/servers/physics_2d/shape_2d_sw.h index 4164896696..c04cdfa456 100644 --- a/servers/physics_2d/shape_2d_sw.h +++ b/servers/physics_2d/shape_2d_sw.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -35,8 +35,8 @@ /* SHAPE_LINE, ///< plane:"plane" -SHAPE_SEGMENT, ///< float:"length" -SHAPE_CIRCLE, ///< float:"radius" +SHAPE_SEGMENT, ///< real_t:"length" +SHAPE_CIRCLE, ///< real_t:"radius" SHAPE_RECTANGLE, ///< vec3:"extents" SHAPE_CONVEX_POLYGON, ///< array of planes:"planes" SHAPE_CONCAVE_POLYGON, ///< Vector2 array:"triangles" , or Dictionary with "indices" (int array) and "triangles" (Vector2 array) @@ -46,7 +46,7 @@ SHAPE_CUSTOM, ///< Server-Implementation based custom shape, calling shape_creat class Shape2DSW; -class ShapeOwner2DSW { +class ShapeOwner2DSW : public RID_Data{ public: virtual void _shape_changed()=0; @@ -55,7 +55,7 @@ public: virtual ~ShapeOwner2DSW() {} }; -class Shape2DSW { +class Shape2DSW : public RID_Data { RID self; Rect2 aabb; @@ -80,13 +80,13 @@ public: virtual bool contains_point(const Vector2& p_point) const=0; - virtual void project_rangev(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const=0; - virtual void project_range_castv(const Vector2& p_cast, const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const=0; + virtual void project_rangev(const Vector2& p_normal, const Transform2D& p_transform, real_t &r_min, real_t &r_max) const=0; + virtual void project_range_castv(const Vector2& p_cast, const Vector2& p_normal, const Transform2D& p_transform, real_t &r_min, real_t &r_max) const=0; virtual Vector2 get_support(const Vector2& p_normal) const; virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const=0; virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const=0; - virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const=0; + virtual real_t get_moment_of_inertia(real_t p_mass,const Size2& p_scale) const=0; virtual void set_data(const Variant& p_data)=0; virtual Variant get_data() const=0; @@ -99,7 +99,7 @@ public: const Map<ShapeOwner2DSW*,int>& get_owners() const; - _FORCE_INLINE_ void get_supports_transformed_cast(const Vector2& p_cast,const Vector2& p_normal,const Matrix32& p_xform,Vector2 *r_supports,int & r_amount) const { + _FORCE_INLINE_ void get_supports_transformed_cast(const Vector2& p_cast,const Vector2& p_normal,const Transform2D& p_xform,Vector2 *r_supports,int & r_amount) const { get_supports(p_xform.basis_xform_inv(p_normal).normalized(),r_supports,r_amount); for(int i=0;i<r_amount;i++) @@ -142,14 +142,14 @@ public: //let the optimizer do the magic #define DEFAULT_PROJECT_RANGE_CAST \ -virtual void project_range_castv(const Vector2& p_cast, const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const {\ +virtual void project_range_castv(const Vector2& p_cast, const Vector2& p_normal, const Transform2D& p_transform, real_t &r_min, real_t &r_max) const {\ project_range_cast(p_cast,p_normal,p_transform,r_min,r_max);\ }\ -_FORCE_INLINE_ void project_range_cast(const Vector2& p_cast, const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const {\ +_FORCE_INLINE_ void project_range_cast(const Vector2& p_cast, const Vector2& p_normal, const Transform2D& p_transform, real_t &r_min, real_t &r_max) const {\ \ real_t mina,maxa;\ real_t minb,maxb;\ - Matrix32 ofsb=p_transform;\ + Transform2D ofsb=p_transform;\ ofsb.elements[2]+=p_cast;\ project_range(p_normal,p_transform,mina,maxa);\ project_range(p_normal,ofsb,minb,maxb); \ @@ -170,27 +170,27 @@ public: virtual Physics2DServer::ShapeType get_type() const { return Physics2DServer::SHAPE_LINE; } - virtual void project_rangev(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); } + virtual void project_rangev(const Vector2& p_normal, const Transform2D& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); } virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const; virtual bool contains_point(const Vector2& p_point) const; virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const; - virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const; + virtual real_t get_moment_of_inertia(real_t p_mass,const Size2& p_scale) const; virtual void set_data(const Variant& p_data); virtual Variant get_data() const; - _FORCE_INLINE_ void project_range(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { + _FORCE_INLINE_ void project_range(const Vector2& p_normal, const Transform2D& p_transform, real_t &r_min, real_t &r_max) const { //real large r_min=-1e10; r_max=1e10; } - virtual void project_range_castv(const Vector2& p_cast, const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { + virtual void project_range_castv(const Vector2& p_cast, const Vector2& p_normal, const Transform2D& p_transform, real_t &r_min, real_t &r_max) const { project_range_cast(p_cast,p_normal,p_transform,r_min,r_max); } - _FORCE_INLINE_ void project_range_cast(const Vector2& p_cast, const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { + _FORCE_INLINE_ void project_range_cast(const Vector2& p_cast, const Vector2& p_normal, const Transform2D& p_transform, real_t &r_min, real_t &r_max) const { //real large r_min=-1e10; r_max=1e10; @@ -213,17 +213,17 @@ public: virtual Physics2DServer::ShapeType get_type() const { return Physics2DServer::SHAPE_RAY; } - virtual void project_rangev(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); } + virtual void project_rangev(const Vector2& p_normal, const Transform2D& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); } virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const; virtual bool contains_point(const Vector2& p_point) const; virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const; - virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const; + virtual real_t get_moment_of_inertia(real_t p_mass,const Size2& p_scale) const; virtual void set_data(const Variant& p_data); virtual Variant get_data() const; - _FORCE_INLINE_ void project_range(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { + _FORCE_INLINE_ void project_range(const Vector2& p_normal, const Transform2D& p_transform, real_t &r_min, real_t &r_max) const { //real large r_max = p_normal.dot(p_transform.get_origin()); r_min = p_normal.dot(p_transform.xform(Vector2(0,length))); @@ -257,21 +257,21 @@ public: virtual Physics2DServer::ShapeType get_type() const { return Physics2DServer::SHAPE_SEGMENT; } - _FORCE_INLINE_ Vector2 get_xformed_normal(const Matrix32& p_xform) const { + _FORCE_INLINE_ Vector2 get_xformed_normal(const Transform2D& p_xform) const { return (p_xform.xform(b) - p_xform.xform(a)).normalized().tangent(); } - virtual void project_rangev(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); } + virtual void project_rangev(const Vector2& p_normal, const Transform2D& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); } virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const; virtual bool contains_point(const Vector2& p_point) const; virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const; - virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const; + virtual real_t get_moment_of_inertia(real_t p_mass,const Size2& p_scale) const; virtual void set_data(const Variant& p_data); virtual Variant get_data() const; - _FORCE_INLINE_ void project_range(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { + _FORCE_INLINE_ void project_range(const Vector2& p_normal, const Transform2D& p_transform, real_t &r_min, real_t &r_max) const { //real large r_max = p_normal.dot(p_transform.xform(a)); r_min = p_normal.dot(p_transform.xform(b)); @@ -299,17 +299,17 @@ public: virtual Physics2DServer::ShapeType get_type() const { return Physics2DServer::SHAPE_CIRCLE; } - virtual void project_rangev(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); } + virtual void project_rangev(const Vector2& p_normal, const Transform2D& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); } virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const; virtual bool contains_point(const Vector2& p_point) const; virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const; - virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const; + virtual real_t get_moment_of_inertia(real_t p_mass,const Size2& p_scale) const; virtual void set_data(const Variant& p_data); virtual Variant get_data() const; - _FORCE_INLINE_ void project_range(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { + _FORCE_INLINE_ void project_range(const Vector2& p_normal, const Transform2D& p_transform, real_t &r_min, real_t &r_max) const { //real large real_t d = p_normal.dot( p_transform.get_origin() ); @@ -339,17 +339,17 @@ public: virtual Physics2DServer::ShapeType get_type() const { return Physics2DServer::SHAPE_RECTANGLE; } - virtual void project_rangev(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); } + virtual void project_rangev(const Vector2& p_normal, const Transform2D& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); } virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const; virtual bool contains_point(const Vector2& p_point) const; virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const; - virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const; + virtual real_t get_moment_of_inertia(real_t p_mass,const Size2& p_scale) const; virtual void set_data(const Variant& p_data); virtual Variant get_data() const; - _FORCE_INLINE_ void project_range(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { + _FORCE_INLINE_ void project_range(const Vector2& p_normal, const Transform2D& p_transform, real_t &r_min, real_t &r_max) const { // no matter the angle, the box is mirrored anyway r_max=-1e20; r_min=1e20; @@ -367,7 +367,7 @@ public: - _FORCE_INLINE_ Vector2 get_circle_axis(const Matrix32& p_xform, const Matrix32& p_xform_inv,const Vector2& p_circle) const { + _FORCE_INLINE_ Vector2 get_circle_axis(const Transform2D& p_xform, const Transform2D& p_xform_inv,const Vector2& p_circle) const { Vector2 local_v = p_xform_inv.xform(p_circle); @@ -379,7 +379,7 @@ public: return (p_xform.xform(he)-p_circle).normalized(); } - _FORCE_INLINE_ Vector2 get_box_axis(const Matrix32& p_xform, const Matrix32& p_xform_inv,const RectangleShape2DSW *p_B,const Matrix32& p_B_xform, const Matrix32& p_B_xform_inv) const { + _FORCE_INLINE_ Vector2 get_box_axis(const Transform2D& p_xform, const Transform2D& p_xform_inv,const RectangleShape2DSW *p_B,const Transform2D& p_B_xform, const Transform2D& p_B_xform_inv) const { Vector2 a,b; @@ -427,20 +427,20 @@ public: virtual Physics2DServer::ShapeType get_type() const { return Physics2DServer::SHAPE_CAPSULE; } - virtual void project_rangev(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); } + virtual void project_rangev(const Vector2& p_normal, const Transform2D& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); } virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const; virtual bool contains_point(const Vector2& p_point) const; virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const; - virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const; + virtual real_t get_moment_of_inertia(real_t p_mass,const Size2& p_scale) const; virtual void set_data(const Variant& p_data); virtual Variant get_data() const; - _FORCE_INLINE_ void project_range(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { + _FORCE_INLINE_ void project_range(const Vector2& p_normal, const Transform2D& p_transform, real_t &r_min, real_t &r_max) const { // no matter the angle, the box is mirrored anyway Vector2 n=p_transform.basis_xform_inv(p_normal).normalized(); - float h = (n.y > 0) ? height : -height; + real_t h = (n.y > 0) ? height : -height; n *= radius; n.y += h * 0.5; @@ -480,7 +480,7 @@ public: _FORCE_INLINE_ int get_point_count() const { return point_count; } _FORCE_INLINE_ const Vector2& get_point(int p_idx) const { return points[p_idx].pos; } _FORCE_INLINE_ const Vector2& get_segment_normal(int p_idx) const { return points[p_idx].normal; } - _FORCE_INLINE_ Vector2 get_xformed_segment_normal(const Matrix32& p_xform, int p_idx) const { + _FORCE_INLINE_ Vector2 get_xformed_segment_normal(const Transform2D& p_xform, int p_idx) const { Vector2 a = points[p_idx].pos; p_idx++; @@ -490,23 +490,23 @@ public: virtual Physics2DServer::ShapeType get_type() const { return Physics2DServer::SHAPE_CONVEX_POLYGON; } - virtual void project_rangev(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); } + virtual void project_rangev(const Vector2& p_normal, const Transform2D& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); } virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const; virtual bool contains_point(const Vector2& p_point) const; virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const; - virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const; + virtual real_t get_moment_of_inertia(real_t p_mass,const Size2& p_scale) const; virtual void set_data(const Variant& p_data); virtual Variant get_data() const; - _FORCE_INLINE_ void project_range(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { + _FORCE_INLINE_ void project_range(const Vector2& p_normal, const Transform2D& p_transform, real_t &r_min, real_t &r_max) const { // no matter the angle, the box is mirrored anyway r_min = r_max = p_normal.dot(p_transform.xform(points[0].pos)); for(int i=1;i<point_count;i++) { - float d = p_normal.dot(p_transform.xform(points[i].pos)); + real_t d = p_normal.dot(p_transform.xform(points[i].pos)); if (d>r_max) r_max=d; if (d<r_min) @@ -577,14 +577,14 @@ public: virtual Physics2DServer::ShapeType get_type() const { return Physics2DServer::SHAPE_CONCAVE_POLYGON; } - virtual void project_rangev(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { /*project_range(p_normal,p_transform,r_min,r_max);*/ } - virtual void project_range(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { /*project_range(p_normal,p_transform,r_min,r_max);*/ } + virtual void project_rangev(const Vector2& p_normal, const Transform2D& p_transform, real_t &r_min, real_t &r_max) const { /*project_range(p_normal,p_transform,r_min,r_max);*/ } + virtual void project_range(const Vector2& p_normal, const Transform2D& p_transform, real_t &r_min, real_t &r_max) const { /*project_range(p_normal,p_transform,r_min,r_max);*/ } virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const; virtual bool contains_point(const Vector2& p_point) const; virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const; - virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const { return 0; } + virtual real_t get_moment_of_inertia(real_t p_mass,const Size2& p_scale) const { return 0; } virtual void set_data(const Variant& p_data); virtual Variant get_data() const; diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp index d0dcee7763..9bced50061 100644 --- a/servers/physics_2d/space_2d_sw.cpp +++ b/servers/physics_2d/space_2d_sw.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -81,6 +81,9 @@ int Physics2DDirectSpaceStateSW::intersect_point(const Vector2& p_point,ShapeRes if (!shape->contains_point(local_point)) continue; + if (cc>=p_result_max) + continue; + r_results[cc].collider_id=col_obj->get_instance_id(); if (r_results[cc].collider_id!=0) r_results[cc].collider=ObjectDB::get_instance(r_results[cc].collider_id); @@ -130,7 +133,7 @@ bool Physics2DDirectSpaceStateSW::intersect_ray(const Vector2& p_from, const Vec const CollisionObject2DSW *col_obj=space->intersection_query_results[i]; int shape_idx=space->intersection_query_subindex_results[i]; - Matrix32 inv_xform = col_obj->get_shape_inv_transform(shape_idx) * col_obj->get_inv_transform(); + Transform2D inv_xform = col_obj->get_shape_inv_transform(shape_idx) * col_obj->get_inv_transform(); Vector2 local_from = inv_xform.xform(begin); Vector2 local_to = inv_xform.xform(end); @@ -150,7 +153,7 @@ bool Physics2DDirectSpaceStateSW::intersect_ray(const Vector2& p_from, const Vec - Matrix32 xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx); + Transform2D xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx); shape_point=xform.xform(shape_point); real_t ld = normal.dot(shape_point); @@ -187,7 +190,7 @@ bool Physics2DDirectSpaceStateSW::intersect_ray(const Vector2& p_from, const Vec } -int Physics2DDirectSpaceStateSW::intersect_shape(const RID& p_shape, const Matrix32& p_xform,const Vector2& p_motion,float p_margin,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) { +int Physics2DDirectSpaceStateSW::intersect_shape(const RID& p_shape, const Transform2D& p_xform,const Vector2& p_motion,real_t p_margin,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) { if (p_result_max<=0) return 0; @@ -234,7 +237,7 @@ int Physics2DDirectSpaceStateSW::intersect_shape(const RID& p_shape, const Matri -bool Physics2DDirectSpaceStateSW::cast_motion(const RID& p_shape, const Matrix32& p_xform,const Vector2& p_motion,float p_margin,float &p_closest_safe,float &p_closest_unsafe, const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) { +bool Physics2DDirectSpaceStateSW::cast_motion(const RID& p_shape, const Transform2D& p_xform,const Vector2& p_motion,real_t p_margin,real_t &p_closest_safe,real_t &p_closest_unsafe, const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) { @@ -245,13 +248,15 @@ bool Physics2DDirectSpaceStateSW::cast_motion(const RID& p_shape, const Matrix32 aabb=aabb.merge(Rect2(aabb.pos+p_motion,aabb.size)); //motion aabb=aabb.grow(p_margin); - //if (p_motion!=Vector2()) - // print_line(p_motion); + /* + if (p_motion!=Vector2()) + print_line(p_motion); + */ int amount = space->broadphase->cull_aabb(aabb,space->intersection_query_results,Space2DSW::INTERSECTION_QUERY_MAX,space->intersection_query_subindex_results); - float best_safe=1; - float best_unsafe=1; + real_t best_safe=1; + real_t best_unsafe=1; for(int i=0;i<amount;i++) { @@ -277,7 +282,7 @@ bool Physics2DDirectSpaceStateSW::cast_motion(const RID& p_shape, const Matrix32 }*/ - Matrix32 col_obj_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx); + Transform2D col_obj_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx); //test initial overlap, does it collide if going all the way? if (!CollisionSolver2DSW::solve(shape,p_xform,p_motion,col_obj->get_shape(shape_idx),col_obj_xform,Vector2() ,NULL,NULL,NULL,p_margin)) { continue; @@ -300,13 +305,13 @@ bool Physics2DDirectSpaceStateSW::cast_motion(const RID& p_shape, const Matrix32 //just do kinematic solving - float low=0; - float hi=1; + real_t low=0; + real_t hi=1; Vector2 mnormal=p_motion.normalized(); for(int i=0;i<8;i++) { //steps should be customizable.. - float ofs = (low+hi)*0.5; + real_t ofs = (low+hi)*0.5; Vector2 sep=mnormal; //important optimization for this to work fast enough bool collided = CollisionSolver2DSW::solve(shape,p_xform,p_motion*ofs,col_obj->get_shape(shape_idx),col_obj_xform,Vector2(),NULL,NULL,&sep,p_margin); @@ -359,7 +364,7 @@ bool Physics2DDirectSpaceStateSW::cast_motion(const RID& p_shape, const Matrix32 } -bool Physics2DDirectSpaceStateSW::collide_shape(RID p_shape, const Matrix32& p_shape_xform,const Vector2& p_motion,float p_margin,Vector2 *r_results,int p_result_max,int &r_result_count, const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) { +bool Physics2DDirectSpaceStateSW::collide_shape(RID p_shape, const Transform2D& p_shape_xform,const Vector2& p_motion,real_t p_margin,Vector2 *r_results,int p_result_max,int &r_result_count, const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) { if (p_result_max<=0) @@ -431,9 +436,9 @@ struct _RestCallbackData2D { int best_shape; Vector2 best_contact; Vector2 best_normal; - float best_len; + real_t best_len; Vector2 valid_dir; - float valid_depth; + real_t valid_depth; }; static void _rest_cbk_result(const Vector2& p_point_A,const Vector2& p_point_B,void *p_userdata) { @@ -453,7 +458,7 @@ static void _rest_cbk_result(const Vector2& p_point_A,const Vector2& p_point_B,v } Vector2 contact_rel = p_point_B - p_point_A; - float len = contact_rel.length(); + real_t len = contact_rel.length(); if (len <= rd->best_len) return; @@ -468,7 +473,7 @@ static void _rest_cbk_result(const Vector2& p_point_A,const Vector2& p_point_B,v } -bool Physics2DDirectSpaceStateSW::rest_info(RID p_shape, const Matrix32& p_shape_xform,const Vector2& p_motion,float p_margin,ShapeRestInfo *r_info, const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) { +bool Physics2DDirectSpaceStateSW::rest_info(RID p_shape, const Transform2D& p_shape_xform,const Vector2& p_motion,real_t p_margin,ShapeRestInfo *r_info, const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) { Shape2DSW *shape = Physics2DServerSW::singletonsw->shape_owner.get(p_shape); @@ -589,7 +594,7 @@ int Space2DSW::_cull_aabb_for_body(Body2DSW *p_body,const Rect2& p_aabb) { return amount; } -bool Space2DSW::test_body_motion(Body2DSW *p_body, const Matrix32 &p_from, const Vector2&p_motion, float p_margin, Physics2DServer::MotionResult *r_result) { +bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, const Vector2&p_motion, real_t p_margin, Physics2DServer::MotionResult *r_result) { //give me back regular physics engine logic //this is madness @@ -615,7 +620,8 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Matrix32 &p_from, const body_aabb=body_aabb.grow(p_margin); - Matrix32 body_transform = p_from; + Transform2D body_transform = p_from; + { //STEP 1, FREE BODY IF STUCK @@ -640,13 +646,14 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Matrix32 &p_from, const bool collided=false; + int amount = _cull_aabb_for_body(p_body,body_aabb); for(int j=0;j<p_body->get_shape_count();j++) { if (p_body->is_shape_set_as_trigger(j)) continue; - Matrix32 body_shape_xform = body_transform * p_body->get_shape_transform(j); + Transform2D body_shape_xform = body_transform * p_body->get_shape_transform(j); Shape2DSW *body_shape = p_body->get_shape(j); for(int i=0;i<amount;i++) { @@ -658,8 +665,10 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Matrix32 &p_from, const const Body2DSW *body=static_cast<const Body2DSW*>(col_obj); Vector2 cdir = body->get_one_way_collision_direction(); - //if (cdir!=Vector2() && p_motion.dot(cdir)<0) - // continue; + /* + if (cdir!=Vector2() && p_motion.dot(cdir)<0) + continue; + */ cbk.valid_dir=cdir; cbk.valid_depth=body->get_one_way_collision_max_depth(); @@ -675,11 +684,13 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Matrix32 &p_from, const } - if (!collided) + if (!collided) { break; + } Vector2 recover_motion; + for(int i=0;i<cbk.amount;i++) { Vector2 a = sr[i*2+0]; @@ -687,19 +698,18 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Matrix32 &p_from, const #if 0 Vector2 rel = b-a; - float d = rel.length(); + real_t d = rel.length(); if (d==0) continue; Vector2 n = rel/d; - float traveled = n.dot(recover_motion); + real_t traveled = n.dot(recover_motion); a+=n*traveled; + real_t d = a.distance_to(b); + if (d<margin) + continue; #endif - // float d = a.distance_to(b); - - //if (d<margin) - /// continue; recover_motion+=(b-a)*0.4; } @@ -718,8 +728,8 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Matrix32 &p_from, const - float safe = 1.0; - float unsafe = 1.0; + real_t safe = 1.0; + real_t unsafe = 1.0; int best_shape=-1; { @@ -736,13 +746,13 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Matrix32 &p_from, const if (p_body->is_shape_set_as_trigger(j)) continue; - Matrix32 body_shape_xform = body_transform * p_body->get_shape_transform(j); + Transform2D body_shape_xform = body_transform * p_body->get_shape_transform(j); Shape2DSW *body_shape = p_body->get_shape(j); bool stuck=false; - float best_safe=1; - float best_unsafe=1; + real_t best_safe=1; + real_t best_unsafe=1; for(int i=0;i<amount;i++) { @@ -750,7 +760,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Matrix32 &p_from, const int shape_idx=intersection_query_subindex_results[i]; - Matrix32 col_obj_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx); + Transform2D col_obj_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx); //test initial overlap, does it collide if going all the way? if (!CollisionSolver2DSW::solve(body_shape,body_shape_xform,p_motion,col_obj->get_shape(shape_idx),col_obj_xform,Vector2() ,NULL,NULL,NULL,0)) { continue; @@ -774,13 +784,13 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Matrix32 &p_from, const //just do kinematic solving - float low=0; - float hi=1; + real_t low=0; + real_t hi=1; Vector2 mnormal=p_motion.normalized(); for(int i=0;i<8;i++) { //steps should be customizable.. - float ofs = (low+hi)*0.5; + real_t ofs = (low+hi)*0.5; Vector2 sep=mnormal; //important optimization for this to work fast enough bool collided = CollisionSolver2DSW::solve(body_shape,body_shape_xform,p_motion*ofs,col_obj->get_shape(shape_idx),col_obj_xform,Vector2(),NULL,NULL,&sep,0); @@ -849,14 +859,14 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Matrix32 &p_from, const if (r_result) { r_result->motion=p_motion; - r_result->remainder=Vector2(); - r_result->motion+=(body_transform.elements[2]-p_from.elements[2]); + r_result->remainder=Vector2(); + r_result->motion+=(body_transform.get_origin()-p_from.get_origin()); } } else { //it collided, let's get the rest info in unsafe advance - Matrix32 ugt = body_transform; + Transform2D ugt = body_transform; ugt.elements[2]+=p_motion*unsafe; _RestCallbackData2D rcd; @@ -864,7 +874,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Matrix32 &p_from, const rcd.best_object=NULL; rcd.best_shape=0; - Matrix32 body_shape_xform = ugt * p_body->get_shape_transform(best_shape); + Transform2D body_shape_xform = ugt * p_body->get_shape_transform(best_shape); Shape2DSW *body_shape = p_body->get_shape(best_shape); body_aabb.pos+=p_motion*unsafe; @@ -913,7 +923,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Matrix32 &p_from, const r_result->motion=safe*p_motion; r_result->remainder=p_motion - safe * p_motion; - r_result->motion+=(body_transform.elements[2]-p_from.elements[2]); + r_result->motion+=(body_transform.get_origin()-p_from.get_origin()); } @@ -923,7 +933,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Matrix32 &p_from, const r_result->motion=p_motion; r_result->remainder=Vector2(); - r_result->motion+=(body_transform.elements[2]-p_from.elements[2]); + r_result->motion+=(body_transform.get_origin()-p_from.get_origin()); } collided=false; @@ -969,7 +979,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Matrix32 &p_from, const if (collide_character) mask|=Physics2DDirectSpaceState::TYPE_MASK_CHARACTER_BODY; -// print_line("motion: "+p_motion+" margin: "+rtos(margin)); + //print_line("motion: "+p_motion+" margin: "+rtos(margin)); //print_line("margin: "+rtos(margin)); do { @@ -994,10 +1004,12 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Matrix32 &p_from, const Vector2 a = sr[i*2+0]; Vector2 b = sr[i*2+1]; - float d = a.distance_to(b); + real_t d = a.distance_to(b); - //if (d<margin) - /// continue; + /* + if (d<margin) + continue; + */ recover_motion+=(b-a)*0.4; } @@ -1016,8 +1028,8 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Matrix32 &p_from, const //move second - float safe = 1.0; - float unsafe = 1.0; + real_t safe = 1.0; + real_t unsafe = 1.0; int best_shape=-1; for(int i=0;i<get_shape_count();i++) { @@ -1025,7 +1037,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Matrix32 &p_from, const if (is_shape_set_as_trigger(i)) continue; - float lsafe,lunsafe; + real_t lsafe,lunsafe; bool valid = dss->cast_motion(get_shape(i)->get_rid(), get_global_transform() * get_shape_transform(i), p_motion, 0,lsafe,lunsafe,exclude,get_layer_mask(),mask); //print_line("shape: "+itos(i)+" travel:"+rtos(ltravel)); if (!valid) { @@ -1321,14 +1333,14 @@ Space2DSW::Space2DSW() { contact_debug_count=0; locked=false; - contact_recycle_radius=0.01; - contact_max_separation=0.05; - contact_max_allowed_penetration= 0.01; - - constraint_bias = 0.01; - body_linear_velocity_sleep_treshold=0.01; - body_angular_velocity_sleep_treshold=(8.0 / 180.0 * Math_PI); - body_time_to_sleep=0.5; + contact_recycle_radius=1.0; + contact_max_separation=1.5; + contact_max_allowed_penetration= 0.3; + + constraint_bias = 0.2; + body_linear_velocity_sleep_treshold=GLOBAL_DEF("physics/2d/sleep_threashold_linear",2.0); + body_angular_velocity_sleep_treshold=GLOBAL_DEF("physics/2d/sleep_threshold_angular",(8.0 / 180.0 * Math_PI)); + body_time_to_sleep=GLOBAL_DEF("physics/2d/time_before_sleep",0.5); broadphase = BroadPhase2DSW::create_func(); diff --git a/servers/physics_2d/space_2d_sw.h b/servers/physics_2d/space_2d_sw.h index f58e8c3fe7..071aa7bdfb 100644 --- a/servers/physics_2d/space_2d_sw.h +++ b/servers/physics_2d/space_2d_sw.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -37,28 +37,29 @@ #include "area_pair_2d_sw.h" #include "broad_phase_2d_sw.h" #include "collision_object_2d_sw.h" +#include "global_config.h" class Physics2DDirectSpaceStateSW : public Physics2DDirectSpaceState { - OBJ_TYPE( Physics2DDirectSpaceStateSW, Physics2DDirectSpaceState ); + GDCLASS( Physics2DDirectSpaceStateSW, Physics2DDirectSpaceState ); public: Space2DSW *space; virtual int intersect_point(const Vector2& p_point,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION, bool p_pick_point=false); virtual bool intersect_ray(const Vector2& p_from, const Vector2& p_to,RayResult &r_result,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION); - virtual int intersect_shape(const RID& p_shape, const Matrix32& p_xform,const Vector2& p_motion,float p_margin,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION); - virtual bool cast_motion(const RID& p_shape, const Matrix32& p_xform,const Vector2& p_motion,float p_margin,float &p_closest_safe,float &p_closest_unsafe, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION); - virtual bool collide_shape(RID p_shape, const Matrix32& p_shape_xform,const Vector2& p_motion,float p_margin,Vector2 *r_results,int p_result_max,int &r_result_count, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION); - virtual bool rest_info(RID p_shape, const Matrix32& p_shape_xform,const Vector2& p_motion,float p_margin,ShapeRestInfo *r_info, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION); + virtual int intersect_shape(const RID& p_shape, const Transform2D& p_xform,const Vector2& p_motion,real_t p_margin,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION); + virtual bool cast_motion(const RID& p_shape, const Transform2D& p_xform,const Vector2& p_motion,real_t p_margin,real_t &p_closest_safe,real_t &p_closest_unsafe, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION); + virtual bool collide_shape(RID p_shape, const Transform2D& p_shape_xform,const Vector2& p_motion,real_t p_margin,Vector2 *r_results,int p_result_max,int &r_result_count, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION); + virtual bool rest_info(RID p_shape, const Transform2D& p_shape_xform,const Vector2& p_motion,real_t p_margin,ShapeRestInfo *r_info, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION); Physics2DDirectSpaceStateSW(); }; -class Space2DSW { +class Space2DSW : public RID_Data { public: @@ -105,9 +106,9 @@ private: CollisionObject2DSW *intersection_query_results[INTERSECTION_QUERY_MAX]; int intersection_query_subindex_results[INTERSECTION_QUERY_MAX]; - float body_linear_velocity_sleep_treshold; - float body_angular_velocity_sleep_treshold; - float body_time_to_sleep; + real_t body_linear_velocity_sleep_treshold; + real_t body_angular_velocity_sleep_treshold; + real_t body_time_to_sleep; bool locked; @@ -184,7 +185,7 @@ public: int get_collision_pairs() const { return collision_pairs; } - bool test_body_motion(Body2DSW *p_body, const Matrix32 &p_from, const Vector2&p_motion, float p_margin, Physics2DServer::MotionResult *r_result); + bool test_body_motion(Body2DSW *p_body, const Transform2D &p_from, const Vector2&p_motion, real_t p_margin, Physics2DServer::MotionResult *r_result); void set_debug_contacts(int p_amount) { contact_debug.resize(p_amount); } diff --git a/servers/physics_2d/step_2d_sw.cpp b/servers/physics_2d/step_2d_sw.cpp index 4f86168c1e..355cc25a69 100644 --- a/servers/physics_2d/step_2d_sw.cpp +++ b/servers/physics_2d/step_2d_sw.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -56,7 +56,7 @@ void Step2DSW::_populate_island(Body2DSW* p_body,Body2DSW** p_island,Constraint2 } } -bool Step2DSW::_setup_island(Constraint2DSW *p_island,float p_delta) { +bool Step2DSW::_setup_island(Constraint2DSW *p_island,real_t p_delta) { Constraint2DSW *ci=p_island; Constraint2DSW *prev_ci=NULL; @@ -81,7 +81,7 @@ bool Step2DSW::_setup_island(Constraint2DSW *p_island,float p_delta) { return removed_root; } -void Step2DSW::_solve_island(Constraint2DSW *p_island,int p_iterations,float p_delta){ +void Step2DSW::_solve_island(Constraint2DSW *p_island,int p_iterations,real_t p_delta){ for(int i=0;i<p_iterations;i++) { @@ -94,7 +94,7 @@ void Step2DSW::_solve_island(Constraint2DSW *p_island,int p_iterations,float p_d } } -void Step2DSW::_check_suspend(Body2DSW *p_island,float p_delta) { +void Step2DSW::_check_suspend(Body2DSW *p_island,real_t p_delta) { bool can_sleep=true; @@ -132,7 +132,7 @@ void Step2DSW::_check_suspend(Body2DSW *p_island,float p_delta) { } } -void Step2DSW::step(Space2DSW* p_space,float p_delta,int p_iterations) { +void Step2DSW::step(Space2DSW* p_space,real_t p_delta,int p_iterations) { p_space->lock(); // can't access space during this @@ -216,7 +216,7 @@ void Step2DSW::step(Space2DSW* p_space,float p_delta,int p_iterations) { p_space->area_remove_from_moved_list((SelfList<Area2DSW>*)aml.first()); //faster to remove here } -// print_line("island count: "+itos(island_count)+" active count: "+itos(active_count)); + //print_line("island count: "+itos(island_count)+" active count: "+itos(active_count)); { //profile profile_endtime=OS::get_singleton()->get_ticks_usec(); diff --git a/servers/physics_2d/step_2d_sw.h b/servers/physics_2d/step_2d_sw.h index 0c374d7e12..0896e1016d 100644 --- a/servers/physics_2d/step_2d_sw.h +++ b/servers/physics_2d/step_2d_sw.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -36,12 +36,12 @@ class Step2DSW { uint64_t _step; void _populate_island(Body2DSW* p_body,Body2DSW** p_island,Constraint2DSW **p_constraint_island); - bool _setup_island(Constraint2DSW *p_island,float p_delta); - void _solve_island(Constraint2DSW *p_island,int p_iterations,float p_delta); - void _check_suspend(Body2DSW *p_island,float p_delta); + bool _setup_island(Constraint2DSW *p_island,real_t p_delta); + void _solve_island(Constraint2DSW *p_island,int p_iterations,real_t p_delta); + void _check_suspend(Body2DSW *p_island,real_t p_delta); public: - void step(Space2DSW* p_space,float p_delta,int p_iterations); + void step(Space2DSW* p_space,real_t p_delta,int p_iterations); Step2DSW(); }; diff --git a/servers/physics_2d_server.cpp b/servers/physics_2d_server.cpp index a77b13eb21..bdbe85612f 100644 --- a/servers/physics_2d_server.cpp +++ b/servers/physics_2d_server.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -73,40 +73,40 @@ Physics2DServer * Physics2DServer::get_singleton() { void Physics2DDirectBodyState::_bind_methods() { - ObjectTypeDB::bind_method(_MD("get_total_gravity"),&Physics2DDirectBodyState::get_total_gravity); - ObjectTypeDB::bind_method(_MD("get_total_linear_damp"),&Physics2DDirectBodyState::get_total_linear_damp); - ObjectTypeDB::bind_method(_MD("get_total_angular_damp"),&Physics2DDirectBodyState::get_total_angular_damp); + ClassDB::bind_method(D_METHOD("get_total_gravity"),&Physics2DDirectBodyState::get_total_gravity); + ClassDB::bind_method(D_METHOD("get_total_linear_damp"),&Physics2DDirectBodyState::get_total_linear_damp); + ClassDB::bind_method(D_METHOD("get_total_angular_damp"),&Physics2DDirectBodyState::get_total_angular_damp); - ObjectTypeDB::bind_method(_MD("get_inverse_mass"),&Physics2DDirectBodyState::get_inverse_mass); - ObjectTypeDB::bind_method(_MD("get_inverse_inertia"),&Physics2DDirectBodyState::get_inverse_inertia); + ClassDB::bind_method(D_METHOD("get_inverse_mass"),&Physics2DDirectBodyState::get_inverse_mass); + ClassDB::bind_method(D_METHOD("get_inverse_inertia"),&Physics2DDirectBodyState::get_inverse_inertia); - ObjectTypeDB::bind_method(_MD("set_linear_velocity","velocity"),&Physics2DDirectBodyState::set_linear_velocity); - ObjectTypeDB::bind_method(_MD("get_linear_velocity"),&Physics2DDirectBodyState::get_linear_velocity); + ClassDB::bind_method(D_METHOD("set_linear_velocity","velocity"),&Physics2DDirectBodyState::set_linear_velocity); + ClassDB::bind_method(D_METHOD("get_linear_velocity"),&Physics2DDirectBodyState::get_linear_velocity); - ObjectTypeDB::bind_method(_MD("set_angular_velocity","velocity"),&Physics2DDirectBodyState::set_angular_velocity); - ObjectTypeDB::bind_method(_MD("get_angular_velocity"),&Physics2DDirectBodyState::get_angular_velocity); + ClassDB::bind_method(D_METHOD("set_angular_velocity","velocity"),&Physics2DDirectBodyState::set_angular_velocity); + ClassDB::bind_method(D_METHOD("get_angular_velocity"),&Physics2DDirectBodyState::get_angular_velocity); - ObjectTypeDB::bind_method(_MD("set_transform","transform"),&Physics2DDirectBodyState::set_transform); - ObjectTypeDB::bind_method(_MD("get_transform"),&Physics2DDirectBodyState::get_transform); + ClassDB::bind_method(D_METHOD("set_transform","transform"),&Physics2DDirectBodyState::set_transform); + ClassDB::bind_method(D_METHOD("get_transform"),&Physics2DDirectBodyState::get_transform); - ObjectTypeDB::bind_method(_MD("set_sleep_state","enabled"),&Physics2DDirectBodyState::set_sleep_state); - ObjectTypeDB::bind_method(_MD("is_sleeping"),&Physics2DDirectBodyState::is_sleeping); + ClassDB::bind_method(D_METHOD("set_sleep_state","enabled"),&Physics2DDirectBodyState::set_sleep_state); + ClassDB::bind_method(D_METHOD("is_sleeping"),&Physics2DDirectBodyState::is_sleeping); - ObjectTypeDB::bind_method(_MD("get_contact_count"),&Physics2DDirectBodyState::get_contact_count); + ClassDB::bind_method(D_METHOD("get_contact_count"),&Physics2DDirectBodyState::get_contact_count); - ObjectTypeDB::bind_method(_MD("get_contact_local_pos","contact_idx"),&Physics2DDirectBodyState::get_contact_local_pos); - ObjectTypeDB::bind_method(_MD("get_contact_local_normal","contact_idx"),&Physics2DDirectBodyState::get_contact_local_normal); - ObjectTypeDB::bind_method(_MD("get_contact_local_shape","contact_idx"),&Physics2DDirectBodyState::get_contact_local_shape); - ObjectTypeDB::bind_method(_MD("get_contact_collider","contact_idx"),&Physics2DDirectBodyState::get_contact_collider); - ObjectTypeDB::bind_method(_MD("get_contact_collider_pos","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_pos); - ObjectTypeDB::bind_method(_MD("get_contact_collider_id","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_id); - ObjectTypeDB::bind_method(_MD("get_contact_collider_object","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_object); - ObjectTypeDB::bind_method(_MD("get_contact_collider_shape","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_shape); - ObjectTypeDB::bind_method(_MD("get_contact_collider_shape_metadata:Variant","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_shape_metadata); - ObjectTypeDB::bind_method(_MD("get_contact_collider_velocity_at_pos","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_velocity_at_pos); - ObjectTypeDB::bind_method(_MD("get_step"),&Physics2DDirectBodyState::get_step); - ObjectTypeDB::bind_method(_MD("integrate_forces"),&Physics2DDirectBodyState::integrate_forces); - ObjectTypeDB::bind_method(_MD("get_space_state:Physics2DDirectSpaceState"),&Physics2DDirectBodyState::get_space_state); + ClassDB::bind_method(D_METHOD("get_contact_local_pos","contact_idx"),&Physics2DDirectBodyState::get_contact_local_pos); + ClassDB::bind_method(D_METHOD("get_contact_local_normal","contact_idx"),&Physics2DDirectBodyState::get_contact_local_normal); + ClassDB::bind_method(D_METHOD("get_contact_local_shape","contact_idx"),&Physics2DDirectBodyState::get_contact_local_shape); + ClassDB::bind_method(D_METHOD("get_contact_collider","contact_idx"),&Physics2DDirectBodyState::get_contact_collider); + ClassDB::bind_method(D_METHOD("get_contact_collider_pos","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_pos); + ClassDB::bind_method(D_METHOD("get_contact_collider_id","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_id); + ClassDB::bind_method(D_METHOD("get_contact_collider_object","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_object); + ClassDB::bind_method(D_METHOD("get_contact_collider_shape","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_shape); + ClassDB::bind_method(D_METHOD("get_contact_collider_shape_metadata:Variant","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_shape_metadata); + ClassDB::bind_method(D_METHOD("get_contact_collider_velocity_at_pos","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_velocity_at_pos); + ClassDB::bind_method(D_METHOD("get_step"),&Physics2DDirectBodyState::get_step); + ClassDB::bind_method(D_METHOD("integrate_forces"),&Physics2DDirectBodyState::integrate_forces); + ClassDB::bind_method(D_METHOD("get_space_state:Physics2DDirectSpaceState"),&Physics2DDirectBodyState::get_space_state); } @@ -132,11 +132,11 @@ RID Physics2DShapeQueryParameters::get_shape_rid() const { return shape; } -void Physics2DShapeQueryParameters::set_transform(const Matrix32& p_transform){ +void Physics2DShapeQueryParameters::set_transform(const Transform2D& p_transform){ transform=p_transform; } -Matrix32 Physics2DShapeQueryParameters::get_transform() const{ +Transform2D Physics2DShapeQueryParameters::get_transform() const{ return transform; } @@ -179,7 +179,7 @@ int Physics2DShapeQueryParameters::get_object_type_mask() const{ } void Physics2DShapeQueryParameters::set_exclude(const Vector<RID>& p_exclude) { - exclude.clear();; + exclude.clear(); for(int i=0;i<p_exclude.size();i++) exclude.insert(p_exclude[i]); @@ -198,27 +198,27 @@ Vector<RID> Physics2DShapeQueryParameters::get_exclude() const{ void Physics2DShapeQueryParameters::_bind_methods() { - ObjectTypeDB::bind_method(_MD("set_shape","shape:Shape2D"),&Physics2DShapeQueryParameters::set_shape); - ObjectTypeDB::bind_method(_MD("set_shape_rid","shape"),&Physics2DShapeQueryParameters::set_shape_rid); - ObjectTypeDB::bind_method(_MD("get_shape_rid"),&Physics2DShapeQueryParameters::get_shape_rid); + ClassDB::bind_method(D_METHOD("set_shape","shape:Shape2D"),&Physics2DShapeQueryParameters::set_shape); + ClassDB::bind_method(D_METHOD("set_shape_rid","shape"),&Physics2DShapeQueryParameters::set_shape_rid); + ClassDB::bind_method(D_METHOD("get_shape_rid"),&Physics2DShapeQueryParameters::get_shape_rid); - ObjectTypeDB::bind_method(_MD("set_transform","transform"),&Physics2DShapeQueryParameters::set_transform); - ObjectTypeDB::bind_method(_MD("get_transform"),&Physics2DShapeQueryParameters::get_transform); + ClassDB::bind_method(D_METHOD("set_transform","transform"),&Physics2DShapeQueryParameters::set_transform); + ClassDB::bind_method(D_METHOD("get_transform"),&Physics2DShapeQueryParameters::get_transform); - ObjectTypeDB::bind_method(_MD("set_motion","motion"),&Physics2DShapeQueryParameters::set_motion); - ObjectTypeDB::bind_method(_MD("get_motion"),&Physics2DShapeQueryParameters::get_motion); + ClassDB::bind_method(D_METHOD("set_motion","motion"),&Physics2DShapeQueryParameters::set_motion); + ClassDB::bind_method(D_METHOD("get_motion"),&Physics2DShapeQueryParameters::get_motion); - ObjectTypeDB::bind_method(_MD("set_margin","margin"),&Physics2DShapeQueryParameters::set_margin); - ObjectTypeDB::bind_method(_MD("get_margin"),&Physics2DShapeQueryParameters::get_margin); + ClassDB::bind_method(D_METHOD("set_margin","margin"),&Physics2DShapeQueryParameters::set_margin); + ClassDB::bind_method(D_METHOD("get_margin"),&Physics2DShapeQueryParameters::get_margin); - ObjectTypeDB::bind_method(_MD("set_layer_mask","layer_mask"),&Physics2DShapeQueryParameters::set_layer_mask); - ObjectTypeDB::bind_method(_MD("get_layer_mask"),&Physics2DShapeQueryParameters::get_layer_mask); + ClassDB::bind_method(D_METHOD("set_layer_mask","layer_mask"),&Physics2DShapeQueryParameters::set_layer_mask); + ClassDB::bind_method(D_METHOD("get_layer_mask"),&Physics2DShapeQueryParameters::get_layer_mask); - ObjectTypeDB::bind_method(_MD("set_object_type_mask","object_type_mask"),&Physics2DShapeQueryParameters::set_object_type_mask); - ObjectTypeDB::bind_method(_MD("get_object_type_mask"),&Physics2DShapeQueryParameters::get_object_type_mask); + ClassDB::bind_method(D_METHOD("set_object_type_mask","object_type_mask"),&Physics2DShapeQueryParameters::set_object_type_mask); + ClassDB::bind_method(D_METHOD("get_object_type_mask"),&Physics2DShapeQueryParameters::get_object_type_mask); - ObjectTypeDB::bind_method(_MD("set_exclude","exclude"),&Physics2DShapeQueryParameters::set_exclude); - ObjectTypeDB::bind_method(_MD("get_exclude"),&Physics2DShapeQueryParameters::get_exclude); + ClassDB::bind_method(D_METHOD("set_exclude","exclude"),&Physics2DShapeQueryParameters::set_exclude); + ClassDB::bind_method(D_METHOD("get_exclude"),&Physics2DShapeQueryParameters::get_exclude); } @@ -241,9 +241,9 @@ Dictionary Physics2DDirectSpaceState::_intersect_ray(const Vector2& p_from, cons bool res = intersect_ray(p_from,p_to,inters,exclude,p_layers,p_object_type_mask); if (!res) - return Dictionary(true); + return Dictionary(); - Dictionary d(true); + Dictionary d; d["position"]=inters.position; d["normal"]=inters.normal; d["collider_id"]=inters.collider_id; @@ -282,7 +282,7 @@ Array Physics2DDirectSpaceState::_cast_motion(const Ref<Physics2DShapeQueryParam bool res = cast_motion(psq->shape,psq->transform,psq->motion,psq->margin,closest_safe,closest_unsafe,psq->exclude,psq->layer_mask,psq->object_type_mask); if (!res) return Array(); - Array ret(true); + Array ret; ret.resize(2); ret[0]=closest_safe; ret[1]=closest_unsafe; @@ -339,7 +339,7 @@ Dictionary Physics2DDirectSpaceState::_get_rest_info(const Ref<Physics2DShapeQue ShapeRestInfo sri; bool res = rest_info(psq->shape,psq->transform,psq->motion,psq->margin,&sri,psq->exclude,psq->layer_mask,psq->object_type_mask); - Dictionary r(true); + Dictionary r; if (!res) return r; @@ -366,13 +366,13 @@ Physics2DDirectSpaceState::Physics2DDirectSpaceState() { void Physics2DDirectSpaceState::_bind_methods() { - ObjectTypeDB::bind_method(_MD("intersect_point","point","max_results","exclude","layer_mask","type_mask"),&Physics2DDirectSpaceState::_intersect_point,DEFVAL(32),DEFVAL(Array()),DEFVAL(0x7FFFFFFF),DEFVAL(TYPE_MASK_COLLISION)); - ObjectTypeDB::bind_method(_MD("intersect_ray:Dictionary","from","to","exclude","layer_mask","type_mask"),&Physics2DDirectSpaceState::_intersect_ray,DEFVAL(Array()),DEFVAL(0x7FFFFFFF),DEFVAL(TYPE_MASK_COLLISION)); - ObjectTypeDB::bind_method(_MD("intersect_shape","shape:Physics2DShapeQueryParameters","max_results"),&Physics2DDirectSpaceState::_intersect_shape,DEFVAL(32)); - ObjectTypeDB::bind_method(_MD("cast_motion","shape:Physics2DShapeQueryParameters"),&Physics2DDirectSpaceState::_cast_motion); - ObjectTypeDB::bind_method(_MD("collide_shape","shape:Physics2DShapeQueryParameters","max_results"),&Physics2DDirectSpaceState::_collide_shape,DEFVAL(32)); - ObjectTypeDB::bind_method(_MD("get_rest_info","shape:Physics2DShapeQueryParameters"),&Physics2DDirectSpaceState::_get_rest_info); - //ObjectTypeDB::bind_method(_MD("cast_motion","shape","xform","motion","exclude","umask"),&Physics2DDirectSpaceState::_intersect_shape,DEFVAL(Array()),DEFVAL(0)); + ClassDB::bind_method(D_METHOD("intersect_point","point","max_results","exclude","layer_mask","type_mask"),&Physics2DDirectSpaceState::_intersect_point,DEFVAL(32),DEFVAL(Array()),DEFVAL(0x7FFFFFFF),DEFVAL(TYPE_MASK_COLLISION)); + ClassDB::bind_method(D_METHOD("intersect_ray:Dictionary","from","to","exclude","layer_mask","type_mask"),&Physics2DDirectSpaceState::_intersect_ray,DEFVAL(Array()),DEFVAL(0x7FFFFFFF),DEFVAL(TYPE_MASK_COLLISION)); + ClassDB::bind_method(D_METHOD("intersect_shape","shape:Physics2DShapeQueryParameters","max_results"),&Physics2DDirectSpaceState::_intersect_shape,DEFVAL(32)); + ClassDB::bind_method(D_METHOD("cast_motion","shape:Physics2DShapeQueryParameters"),&Physics2DDirectSpaceState::_cast_motion); + ClassDB::bind_method(D_METHOD("collide_shape","shape:Physics2DShapeQueryParameters","max_results"),&Physics2DDirectSpaceState::_collide_shape,DEFVAL(32)); + ClassDB::bind_method(D_METHOD("get_rest_info","shape:Physics2DShapeQueryParameters"),&Physics2DDirectSpaceState::_get_rest_info); + //ClassDB::bind_method(D_METHOD("cast_motion","shape","xform","motion","exclude","umask"),&Physics2DDirectSpaceState::_intersect_shape,DEFVAL(Array()),DEFVAL(0)); BIND_CONSTANT( TYPE_MASK_STATIC_BODY ); BIND_CONSTANT( TYPE_MASK_KINEMATIC_BODY ); @@ -412,11 +412,11 @@ Physics2DShapeQueryResult::Physics2DShapeQueryResult() { void Physics2DShapeQueryResult::_bind_methods() { - ObjectTypeDB::bind_method(_MD("get_result_count"),&Physics2DShapeQueryResult::get_result_count); - ObjectTypeDB::bind_method(_MD("get_result_rid","idx"),&Physics2DShapeQueryResult::get_result_rid); - ObjectTypeDB::bind_method(_MD("get_result_object_id","idx"),&Physics2DShapeQueryResult::get_result_object_id); - ObjectTypeDB::bind_method(_MD("get_result_object","idx"),&Physics2DShapeQueryResult::get_result_object); - ObjectTypeDB::bind_method(_MD("get_result_object_shape","idx"),&Physics2DShapeQueryResult::get_result_object_shape); + ClassDB::bind_method(D_METHOD("get_result_count"),&Physics2DShapeQueryResult::get_result_count); + ClassDB::bind_method(D_METHOD("get_result_rid","idx"),&Physics2DShapeQueryResult::get_result_rid); + ClassDB::bind_method(D_METHOD("get_result_object_id","idx"),&Physics2DShapeQueryResult::get_result_object_id); + ClassDB::bind_method(D_METHOD("get_result_object","idx"),&Physics2DShapeQueryResult::get_result_object); + ClassDB::bind_method(D_METHOD("get_result_object_shape","idx"),&Physics2DShapeQueryResult::get_result_object_shape); } @@ -468,16 +468,16 @@ int Physics2DTestMotionResult::get_collider_shape() const{ void Physics2DTestMotionResult::_bind_methods() { - //ObjectTypeDB::bind_method(_MD("is_colliding"),&Physics2DTestMotionResult::is_colliding); - ObjectTypeDB::bind_method(_MD("get_motion"),&Physics2DTestMotionResult::get_motion); - ObjectTypeDB::bind_method(_MD("get_motion_remainder"),&Physics2DTestMotionResult::get_motion_remainder); - ObjectTypeDB::bind_method(_MD("get_collision_point"),&Physics2DTestMotionResult::get_collision_point); - ObjectTypeDB::bind_method(_MD("get_collision_normal"),&Physics2DTestMotionResult::get_collision_normal); - ObjectTypeDB::bind_method(_MD("get_collider_velocity"),&Physics2DTestMotionResult::get_collider_velocity); - ObjectTypeDB::bind_method(_MD("get_collider_id"),&Physics2DTestMotionResult::get_collider_id); - ObjectTypeDB::bind_method(_MD("get_collider_rid"),&Physics2DTestMotionResult::get_collider_rid); - ObjectTypeDB::bind_method(_MD("get_collider"),&Physics2DTestMotionResult::get_collider); - ObjectTypeDB::bind_method(_MD("get_collider_shape"),&Physics2DTestMotionResult::get_collider_shape); + //ClassDB::bind_method(D_METHOD("is_colliding"),&Physics2DTestMotionResult::is_colliding); + ClassDB::bind_method(D_METHOD("get_motion"),&Physics2DTestMotionResult::get_motion); + ClassDB::bind_method(D_METHOD("get_motion_remainder"),&Physics2DTestMotionResult::get_motion_remainder); + ClassDB::bind_method(D_METHOD("get_collision_point"),&Physics2DTestMotionResult::get_collision_point); + ClassDB::bind_method(D_METHOD("get_collision_normal"),&Physics2DTestMotionResult::get_collision_normal); + ClassDB::bind_method(D_METHOD("get_collider_velocity"),&Physics2DTestMotionResult::get_collider_velocity); + ClassDB::bind_method(D_METHOD("get_collider_id"),&Physics2DTestMotionResult::get_collider_id); + ClassDB::bind_method(D_METHOD("get_collider_rid"),&Physics2DTestMotionResult::get_collider_rid); + ClassDB::bind_method(D_METHOD("get_collider"),&Physics2DTestMotionResult::get_collider); + ClassDB::bind_method(D_METHOD("get_collider_shape"),&Physics2DTestMotionResult::get_collider_shape); } @@ -493,7 +493,7 @@ Physics2DTestMotionResult::Physics2DTestMotionResult(){ -bool Physics2DServer::_body_test_motion(RID p_body,const Matrix32& p_from,const Vector2& p_motion,float p_margin,const Ref<Physics2DTestMotionResult>& p_result) { +bool Physics2DServer::_body_test_motion(RID p_body,const Transform2D& p_from,const Vector2& p_motion,float p_margin,const Ref<Physics2DTestMotionResult>& p_result) { MotionResult *r=NULL; if (p_result.is_valid()) @@ -504,147 +504,147 @@ bool Physics2DServer::_body_test_motion(RID p_body,const Matrix32& p_from,const void Physics2DServer::_bind_methods() { - ObjectTypeDB::bind_method(_MD("shape_create","type"),&Physics2DServer::shape_create); - ObjectTypeDB::bind_method(_MD("shape_set_data","shape","data"),&Physics2DServer::shape_set_data); + ClassDB::bind_method(D_METHOD("shape_create","type"),&Physics2DServer::shape_create); + ClassDB::bind_method(D_METHOD("shape_set_data","shape","data"),&Physics2DServer::shape_set_data); - ObjectTypeDB::bind_method(_MD("shape_get_type","shape"),&Physics2DServer::shape_get_type); - ObjectTypeDB::bind_method(_MD("shape_get_data","shape"),&Physics2DServer::shape_get_data); + ClassDB::bind_method(D_METHOD("shape_get_type","shape"),&Physics2DServer::shape_get_type); + ClassDB::bind_method(D_METHOD("shape_get_data","shape"),&Physics2DServer::shape_get_data); - ObjectTypeDB::bind_method(_MD("space_create"),&Physics2DServer::space_create); - ObjectTypeDB::bind_method(_MD("space_set_active","space","active"),&Physics2DServer::space_set_active); - ObjectTypeDB::bind_method(_MD("space_is_active","space"),&Physics2DServer::space_is_active); - ObjectTypeDB::bind_method(_MD("space_set_param","space","param","value"),&Physics2DServer::space_set_param); - ObjectTypeDB::bind_method(_MD("space_get_param","space","param"),&Physics2DServer::space_get_param); - ObjectTypeDB::bind_method(_MD("space_get_direct_state:Physics2DDirectSpaceState","space"),&Physics2DServer::space_get_direct_state); + ClassDB::bind_method(D_METHOD("space_create"),&Physics2DServer::space_create); + ClassDB::bind_method(D_METHOD("space_set_active","space","active"),&Physics2DServer::space_set_active); + ClassDB::bind_method(D_METHOD("space_is_active","space"),&Physics2DServer::space_is_active); + ClassDB::bind_method(D_METHOD("space_set_param","space","param","value"),&Physics2DServer::space_set_param); + ClassDB::bind_method(D_METHOD("space_get_param","space","param"),&Physics2DServer::space_get_param); + ClassDB::bind_method(D_METHOD("space_get_direct_state:Physics2DDirectSpaceState","space"),&Physics2DServer::space_get_direct_state); - ObjectTypeDB::bind_method(_MD("area_create"),&Physics2DServer::area_create); - ObjectTypeDB::bind_method(_MD("area_set_space","area","space"),&Physics2DServer::area_set_space); - ObjectTypeDB::bind_method(_MD("area_get_space","area"),&Physics2DServer::area_get_space); + ClassDB::bind_method(D_METHOD("area_create"),&Physics2DServer::area_create); + ClassDB::bind_method(D_METHOD("area_set_space","area","space"),&Physics2DServer::area_set_space); + ClassDB::bind_method(D_METHOD("area_get_space","area"),&Physics2DServer::area_get_space); - ObjectTypeDB::bind_method(_MD("area_set_space_override_mode","area","mode"),&Physics2DServer::area_set_space_override_mode); - ObjectTypeDB::bind_method(_MD("area_get_space_override_mode","area"),&Physics2DServer::area_get_space_override_mode); + 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); - ObjectTypeDB::bind_method(_MD("area_add_shape","area","shape","transform"),&Physics2DServer::area_add_shape,DEFVAL(Matrix32())); - ObjectTypeDB::bind_method(_MD("area_set_shape","area","shape_idx","shape"),&Physics2DServer::area_set_shape); - ObjectTypeDB::bind_method(_MD("area_set_shape_transform","area","shape_idx","transform"),&Physics2DServer::area_set_shape_transform); + ClassDB::bind_method(D_METHOD("area_add_shape","area","shape","transform"),&Physics2DServer::area_add_shape,DEFVAL(Transform2D())); + 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); - ObjectTypeDB::bind_method(_MD("area_get_shape_count","area"),&Physics2DServer::area_get_shape_count); - ObjectTypeDB::bind_method(_MD("area_get_shape","area","shape_idx"),&Physics2DServer::area_get_shape); - ObjectTypeDB::bind_method(_MD("area_get_shape_transform","area","shape_idx"),&Physics2DServer::area_get_shape_transform); + 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); + ClassDB::bind_method(D_METHOD("area_get_shape_transform","area","shape_idx"),&Physics2DServer::area_get_shape_transform); - ObjectTypeDB::bind_method(_MD("area_remove_shape","area","shape_idx"),&Physics2DServer::area_remove_shape); - ObjectTypeDB::bind_method(_MD("area_clear_shapes","area"),&Physics2DServer::area_clear_shapes); + ClassDB::bind_method(D_METHOD("area_remove_shape","area","shape_idx"),&Physics2DServer::area_remove_shape); + ClassDB::bind_method(D_METHOD("area_clear_shapes","area"),&Physics2DServer::area_clear_shapes); - ObjectTypeDB::bind_method(_MD("area_set_layer_mask","area","mask"),&Physics2DServer::area_set_layer_mask); - ObjectTypeDB::bind_method(_MD("area_set_collision_mask","area","mask"),&Physics2DServer::area_set_collision_mask); + ClassDB::bind_method(D_METHOD("area_set_layer_mask","area","mask"),&Physics2DServer::area_set_layer_mask); + ClassDB::bind_method(D_METHOD("area_set_collision_mask","area","mask"),&Physics2DServer::area_set_collision_mask); - ObjectTypeDB::bind_method(_MD("area_set_param","area","param","value"),&Physics2DServer::area_set_param); - ObjectTypeDB::bind_method(_MD("area_set_transform","area","transform"),&Physics2DServer::area_set_transform); + ClassDB::bind_method(D_METHOD("area_set_param","area","param","value"),&Physics2DServer::area_set_param); + ClassDB::bind_method(D_METHOD("area_set_transform","area","transform"),&Physics2DServer::area_set_transform); - ObjectTypeDB::bind_method(_MD("area_get_param","area","param"),&Physics2DServer::area_get_param); - ObjectTypeDB::bind_method(_MD("area_get_transform","area"),&Physics2DServer::area_get_transform); + ClassDB::bind_method(D_METHOD("area_get_param","area","param"),&Physics2DServer::area_get_param); + ClassDB::bind_method(D_METHOD("area_get_transform","area"),&Physics2DServer::area_get_transform); - ObjectTypeDB::bind_method(_MD("area_attach_object_instance_ID","area","id"),&Physics2DServer::area_attach_object_instance_ID); - ObjectTypeDB::bind_method(_MD("area_get_object_instance_ID","area"),&Physics2DServer::area_get_object_instance_ID); + ClassDB::bind_method(D_METHOD("area_attach_object_instance_ID","area","id"),&Physics2DServer::area_attach_object_instance_ID); + ClassDB::bind_method(D_METHOD("area_get_object_instance_ID","area"),&Physics2DServer::area_get_object_instance_ID); - ObjectTypeDB::bind_method(_MD("area_set_monitor_callback","area","receiver","method"),&Physics2DServer::area_set_monitor_callback); + ClassDB::bind_method(D_METHOD("area_set_monitor_callback","area","receiver","method"),&Physics2DServer::area_set_monitor_callback); - ObjectTypeDB::bind_method(_MD("body_create","mode","init_sleeping"),&Physics2DServer::body_create,DEFVAL(BODY_MODE_RIGID),DEFVAL(false)); + ClassDB::bind_method(D_METHOD("body_create","mode","init_sleeping"),&Physics2DServer::body_create,DEFVAL(BODY_MODE_RIGID),DEFVAL(false)); - ObjectTypeDB::bind_method(_MD("body_set_space","body","space"),&Physics2DServer::body_set_space); - ObjectTypeDB::bind_method(_MD("body_get_space","body"),&Physics2DServer::body_get_space); + ClassDB::bind_method(D_METHOD("body_set_space","body","space"),&Physics2DServer::body_set_space); + ClassDB::bind_method(D_METHOD("body_get_space","body"),&Physics2DServer::body_get_space); - ObjectTypeDB::bind_method(_MD("body_set_mode","body","mode"),&Physics2DServer::body_set_mode); - ObjectTypeDB::bind_method(_MD("body_get_mode","body"),&Physics2DServer::body_get_mode); + 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); - ObjectTypeDB::bind_method(_MD("body_add_shape","body","shape","transform"),&Physics2DServer::body_add_shape,DEFVAL(Matrix32())); - ObjectTypeDB::bind_method(_MD("body_set_shape","body","shape_idx","shape"),&Physics2DServer::body_set_shape); - ObjectTypeDB::bind_method(_MD("body_set_shape_transform","body","shape_idx","transform"),&Physics2DServer::body_set_shape_transform); - ObjectTypeDB::bind_method(_MD("body_set_shape_metadata","body","shape_idx","metadata"),&Physics2DServer::body_set_shape_metadata); + ClassDB::bind_method(D_METHOD("body_add_shape","body","shape","transform"),&Physics2DServer::body_add_shape,DEFVAL(Transform2D())); + 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); - ObjectTypeDB::bind_method(_MD("body_get_shape_count","body"),&Physics2DServer::body_get_shape_count); - ObjectTypeDB::bind_method(_MD("body_get_shape","body","shape_idx"),&Physics2DServer::body_get_shape); - ObjectTypeDB::bind_method(_MD("body_get_shape_transform","body","shape_idx"),&Physics2DServer::body_get_shape_transform); - ObjectTypeDB::bind_method(_MD("body_get_shape_metadata","body","shape_idx"),&Physics2DServer::body_get_shape_metadata); + ClassDB::bind_method(D_METHOD("body_get_shape_count","body"),&Physics2DServer::body_get_shape_count); + ClassDB::bind_method(D_METHOD("body_get_shape","body","shape_idx"),&Physics2DServer::body_get_shape); + ClassDB::bind_method(D_METHOD("body_get_shape_transform","body","shape_idx"),&Physics2DServer::body_get_shape_transform); + ClassDB::bind_method(D_METHOD("body_get_shape_metadata","body","shape_idx"),&Physics2DServer::body_get_shape_metadata); - ObjectTypeDB::bind_method(_MD("body_remove_shape","body","shape_idx"),&Physics2DServer::body_remove_shape); - ObjectTypeDB::bind_method(_MD("body_clear_shapes","body"),&Physics2DServer::body_clear_shapes); + 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); - ObjectTypeDB::bind_method(_MD("body_set_shape_as_trigger","body","shape_idx","enable"),&Physics2DServer::body_set_shape_as_trigger); - ObjectTypeDB::bind_method(_MD("body_is_shape_set_as_trigger","body","shape_idx"),&Physics2DServer::body_is_shape_set_as_trigger); + ClassDB::bind_method(D_METHOD("body_set_shape_as_trigger","body","shape_idx","enable"),&Physics2DServer::body_set_shape_as_trigger); + ClassDB::bind_method(D_METHOD("body_is_shape_set_as_trigger","body","shape_idx"),&Physics2DServer::body_is_shape_set_as_trigger); - ObjectTypeDB::bind_method(_MD("body_attach_object_instance_ID","body","id"),&Physics2DServer::body_attach_object_instance_ID); - ObjectTypeDB::bind_method(_MD("body_get_object_instance_ID","body"),&Physics2DServer::body_get_object_instance_ID); + ClassDB::bind_method(D_METHOD("body_attach_object_instance_ID","body","id"),&Physics2DServer::body_attach_object_instance_ID); + ClassDB::bind_method(D_METHOD("body_get_object_instance_ID","body"),&Physics2DServer::body_get_object_instance_ID); - ObjectTypeDB::bind_method(_MD("body_set_continuous_collision_detection_mode","body","mode"),&Physics2DServer::body_set_continuous_collision_detection_mode); - ObjectTypeDB::bind_method(_MD("body_get_continuous_collision_detection_mode","body"),&Physics2DServer::body_get_continuous_collision_detection_mode); + ClassDB::bind_method(D_METHOD("body_set_continuous_collision_detection_mode","body","mode"),&Physics2DServer::body_set_continuous_collision_detection_mode); + ClassDB::bind_method(D_METHOD("body_get_continuous_collision_detection_mode","body"),&Physics2DServer::body_get_continuous_collision_detection_mode); - ObjectTypeDB::bind_method(_MD("body_set_layer_mask","body","mask"),&Physics2DServer::body_set_layer_mask); - ObjectTypeDB::bind_method(_MD("body_get_layer_mask","body"),&Physics2DServer::body_get_layer_mask); + ClassDB::bind_method(D_METHOD("body_set_layer_mask","body","mask"),&Physics2DServer::body_set_layer_mask); + ClassDB::bind_method(D_METHOD("body_get_layer_mask","body"),&Physics2DServer::body_get_layer_mask); - ObjectTypeDB::bind_method(_MD("body_set_collision_mask","body","mask"),&Physics2DServer::body_set_collision_mask); - ObjectTypeDB::bind_method(_MD("body_get_collision_mask","body"),&Physics2DServer::body_get_collision_mask); + ClassDB::bind_method(D_METHOD("body_set_collision_mask","body","mask"),&Physics2DServer::body_set_collision_mask); + ClassDB::bind_method(D_METHOD("body_get_collision_mask","body"),&Physics2DServer::body_get_collision_mask); - ObjectTypeDB::bind_method(_MD("body_set_param","body","param","value"),&Physics2DServer::body_set_param); - ObjectTypeDB::bind_method(_MD("body_get_param","body","param"),&Physics2DServer::body_get_param); + ClassDB::bind_method(D_METHOD("body_set_param","body","param","value"),&Physics2DServer::body_set_param); + ClassDB::bind_method(D_METHOD("body_get_param","body","param"),&Physics2DServer::body_get_param); - ObjectTypeDB::bind_method(_MD("body_set_state","body","state","value"),&Physics2DServer::body_set_state); - ObjectTypeDB::bind_method(_MD("body_get_state","body","state"),&Physics2DServer::body_get_state); + ClassDB::bind_method(D_METHOD("body_set_state","body","state","value"),&Physics2DServer::body_set_state); + ClassDB::bind_method(D_METHOD("body_get_state","body","state"),&Physics2DServer::body_get_state); - ObjectTypeDB::bind_method(_MD("body_apply_impulse","body","pos","impulse"),&Physics2DServer::body_apply_impulse); - ObjectTypeDB::bind_method(_MD("body_add_force","body","offset","force"),&Physics2DServer::body_add_force); - ObjectTypeDB::bind_method(_MD("body_set_axis_velocity","body","axis_velocity"),&Physics2DServer::body_set_axis_velocity); + ClassDB::bind_method(D_METHOD("body_apply_impulse","body","pos","impulse"),&Physics2DServer::body_apply_impulse); + ClassDB::bind_method(D_METHOD("body_add_force","body","offset","force"),&Physics2DServer::body_add_force); + ClassDB::bind_method(D_METHOD("body_set_axis_velocity","body","axis_velocity"),&Physics2DServer::body_set_axis_velocity); - ObjectTypeDB::bind_method(_MD("body_add_collision_exception","body","excepted_body"),&Physics2DServer::body_add_collision_exception); - ObjectTypeDB::bind_method(_MD("body_remove_collision_exception","body","excepted_body"),&Physics2DServer::body_remove_collision_exception); -// virtual void body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions)=0; + ClassDB::bind_method(D_METHOD("body_add_collision_exception","body","excepted_body"),&Physics2DServer::body_add_collision_exception); + ClassDB::bind_method(D_METHOD("body_remove_collision_exception","body","excepted_body"),&Physics2DServer::body_remove_collision_exception); + //virtual void body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions)=0; - ObjectTypeDB::bind_method(_MD("body_set_max_contacts_reported","body","amount"),&Physics2DServer::body_set_max_contacts_reported); - ObjectTypeDB::bind_method(_MD("body_get_max_contacts_reported","body"),&Physics2DServer::body_get_max_contacts_reported); + ClassDB::bind_method(D_METHOD("body_set_max_contacts_reported","body","amount"),&Physics2DServer::body_set_max_contacts_reported); + ClassDB::bind_method(D_METHOD("body_get_max_contacts_reported","body"),&Physics2DServer::body_get_max_contacts_reported); - ObjectTypeDB::bind_method(_MD("body_set_one_way_collision_direction","body","normal"),&Physics2DServer::body_set_one_way_collision_direction); - ObjectTypeDB::bind_method(_MD("body_get_one_way_collision_direction","body"),&Physics2DServer::body_get_one_way_collision_direction); + ClassDB::bind_method(D_METHOD("body_set_one_way_collision_direction","body","normal"),&Physics2DServer::body_set_one_way_collision_direction); + ClassDB::bind_method(D_METHOD("body_get_one_way_collision_direction","body"),&Physics2DServer::body_get_one_way_collision_direction); - ObjectTypeDB::bind_method(_MD("body_set_one_way_collision_max_depth","body","depth"),&Physics2DServer::body_set_one_way_collision_max_depth); - ObjectTypeDB::bind_method(_MD("body_get_one_way_collision_max_depth","body"),&Physics2DServer::body_get_one_way_collision_max_depth); + ClassDB::bind_method(D_METHOD("body_set_one_way_collision_max_depth","body","depth"),&Physics2DServer::body_set_one_way_collision_max_depth); + ClassDB::bind_method(D_METHOD("body_get_one_way_collision_max_depth","body"),&Physics2DServer::body_get_one_way_collision_max_depth); - ObjectTypeDB::bind_method(_MD("body_set_omit_force_integration","body","enable"),&Physics2DServer::body_set_omit_force_integration); - ObjectTypeDB::bind_method(_MD("body_is_omitting_force_integration","body"),&Physics2DServer::body_is_omitting_force_integration); + ClassDB::bind_method(D_METHOD("body_set_omit_force_integration","body","enable"),&Physics2DServer::body_set_omit_force_integration); + ClassDB::bind_method(D_METHOD("body_is_omitting_force_integration","body"),&Physics2DServer::body_is_omitting_force_integration); - ObjectTypeDB::bind_method(_MD("body_set_force_integration_callback","body","receiver","method","userdata"),&Physics2DServer::body_set_force_integration_callback,DEFVAL(Variant())); + ClassDB::bind_method(D_METHOD("body_set_force_integration_callback","body","receiver","method","userdata"),&Physics2DServer::body_set_force_integration_callback,DEFVAL(Variant())); - ObjectTypeDB::bind_method(_MD("body_test_motion","body","from","motion","margin","result:Physics2DTestMotionResult"),&Physics2DServer::_body_test_motion,DEFVAL(0.08),DEFVAL(Variant())); + ClassDB::bind_method(D_METHOD("body_test_motion","body","from","motion","margin","result:Physics2DTestMotionResult"),&Physics2DServer::_body_test_motion,DEFVAL(0.08),DEFVAL(Variant())); /* JOINT API */ - ObjectTypeDB::bind_method(_MD("joint_set_param","joint","param","value"),&Physics2DServer::joint_set_param); - ObjectTypeDB::bind_method(_MD("joint_get_param","joint","param"),&Physics2DServer::joint_get_param); + ClassDB::bind_method(D_METHOD("joint_set_param","joint","param","value"),&Physics2DServer::joint_set_param); + ClassDB::bind_method(D_METHOD("joint_get_param","joint","param"),&Physics2DServer::joint_get_param); - ObjectTypeDB::bind_method(_MD("pin_joint_create","anchor","body_a","body_b"),&Physics2DServer::pin_joint_create,DEFVAL(RID())); - ObjectTypeDB::bind_method(_MD("groove_joint_create","groove1_a","groove2_a","anchor_b","body_a","body_b"),&Physics2DServer::groove_joint_create,DEFVAL(RID()),DEFVAL(RID())); - ObjectTypeDB::bind_method(_MD("damped_spring_joint_create","anchor_a","anchor_b","body_a","body_b"),&Physics2DServer::damped_spring_joint_create,DEFVAL(RID())); + ClassDB::bind_method(D_METHOD("pin_joint_create","anchor","body_a","body_b"),&Physics2DServer::pin_joint_create,DEFVAL(RID())); + ClassDB::bind_method(D_METHOD("groove_joint_create","groove1_a","groove2_a","anchor_b","body_a","body_b"),&Physics2DServer::groove_joint_create,DEFVAL(RID()),DEFVAL(RID())); + ClassDB::bind_method(D_METHOD("damped_spring_joint_create","anchor_a","anchor_b","body_a","body_b"),&Physics2DServer::damped_spring_joint_create,DEFVAL(RID())); - ObjectTypeDB::bind_method(_MD("damped_string_joint_set_param","joint","param","value"),&Physics2DServer::damped_string_joint_set_param); - ObjectTypeDB::bind_method(_MD("damped_string_joint_get_param","joint","param"),&Physics2DServer::damped_string_joint_get_param); + ClassDB::bind_method(D_METHOD("damped_string_joint_set_param","joint","param","value"),&Physics2DServer::damped_string_joint_set_param); + ClassDB::bind_method(D_METHOD("damped_string_joint_get_param","joint","param"),&Physics2DServer::damped_string_joint_get_param); - ObjectTypeDB::bind_method(_MD("joint_get_type","joint"),&Physics2DServer::joint_get_type); + ClassDB::bind_method(D_METHOD("joint_get_type","joint"),&Physics2DServer::joint_get_type); - ObjectTypeDB::bind_method(_MD("free_rid","rid"),&Physics2DServer::free); + ClassDB::bind_method(D_METHOD("free_rid","rid"),&Physics2DServer::free); - ObjectTypeDB::bind_method(_MD("set_active","active"),&Physics2DServer::set_active); + ClassDB::bind_method(D_METHOD("set_active","active"),&Physics2DServer::set_active); - ObjectTypeDB::bind_method(_MD("get_process_info","process_info"),&Physics2DServer::get_process_info); + ClassDB::bind_method(D_METHOD("get_process_info","process_info"),&Physics2DServer::get_process_info); -// ObjectTypeDB::bind_method(_MD("init"),&Physics2DServer::init); -// ObjectTypeDB::bind_method(_MD("step"),&Physics2DServer::step); -// ObjectTypeDB::bind_method(_MD("sync"),&Physics2DServer::sync); - //ObjectTypeDB::bind_method(_MD("flush_queries"),&Physics2DServer::flush_queries); + //ClassDB::bind_method(D_METHOD("init"),&Physics2DServer::init); + //ClassDB::bind_method(D_METHOD("step"),&Physics2DServer::step); + //ClassDB::bind_method(D_METHOD("sync"),&Physics2DServer::sync); + //ClassDB::bind_method(D_METHOD("flush_queries"),&Physics2DServer::flush_queries); BIND_CONSTANT( SPACE_PARAM_CONTACT_RECYCLE_RADIUS ); BIND_CONSTANT( SPACE_PARAM_CONTACT_MAX_SEPARATION ); @@ -710,8 +710,8 @@ void Physics2DServer::_bind_methods() { BIND_CONSTANT( CCD_MODE_CAST_RAY ); BIND_CONSTANT( CCD_MODE_CAST_SHAPE ); -// BIND_CONSTANT( TYPE_BODY ); -// BIND_CONSTANT( TYPE_AREA ); + //BIND_CONSTANT( TYPE_BODY ); + //BIND_CONSTANT( TYPE_AREA ); BIND_CONSTANT( AREA_BODY_ADDED ); BIND_CONSTANT( AREA_BODY_REMOVED ); diff --git a/servers/physics_2d_server.h b/servers/physics_2d_server.h index 10707e9314..424d2fa7ce 100644 --- a/servers/physics_2d_server.h +++ b/servers/physics_2d_server.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -37,7 +37,7 @@ class Physics2DDirectSpaceState; class Physics2DDirectBodyState : public Object { - OBJ_TYPE( Physics2DDirectBodyState, Object ); + GDCLASS( Physics2DDirectBodyState, Object ); protected: static void _bind_methods(); public: @@ -55,8 +55,8 @@ public: virtual void set_angular_velocity(real_t p_velocity)=0; virtual real_t get_angular_velocity() const=0; - virtual void set_transform(const Matrix32& p_transform)=0; - virtual Matrix32 get_transform() const=0; + virtual void set_transform(const Transform2D& p_transform)=0; + virtual Transform2D get_transform() const=0; virtual void set_sleep_state(bool p_enable)=0; virtual bool is_sleeping() const=0; @@ -90,10 +90,10 @@ class Physics2DShapeQueryResult; //used for script class Physics2DShapeQueryParameters : public Reference { - OBJ_TYPE(Physics2DShapeQueryParameters, Reference); + GDCLASS(Physics2DShapeQueryParameters, Reference); friend class Physics2DDirectSpaceState; RID shape; - Matrix32 transform; + Transform2D transform; Vector2 motion; float margin; Set<RID> exclude; @@ -108,8 +108,8 @@ public: void set_shape_rid(const RID& p_shape); RID get_shape_rid() const; - void set_transform(const Matrix32& p_transform); - Matrix32 get_transform() const; + void set_transform(const Transform2D& p_transform); + Transform2D get_transform() const; void set_motion(const Vector2& p_motion); Vector2 get_motion() const; @@ -133,7 +133,7 @@ public: class Physics2DDirectSpaceState : public Object { - OBJ_TYPE( Physics2DDirectSpaceState, Object ); + GDCLASS( Physics2DDirectSpaceState, Object ); Dictionary _intersect_ray(const Vector2& p_from, const Vector2& p_to,const Vector<RID>& p_exclude=Vector<RID>(),uint32_t p_layers=0,uint32_t p_object_type_mask=TYPE_MASK_COLLISION); @@ -184,11 +184,11 @@ public: virtual int intersect_point(const Vector2& p_point,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION,bool p_pick_point=false)=0; - virtual int intersect_shape(const RID& p_shape, const Matrix32& p_xform,const Vector2& p_motion,float p_margin,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION)=0; + virtual int intersect_shape(const RID& p_shape, const Transform2D& p_xform,const Vector2& p_motion,float p_margin,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION)=0; - virtual bool cast_motion(const RID& p_shape, const Matrix32& p_xform,const Vector2& p_motion,float p_margin,float &p_closest_safe,float &p_closest_unsafe, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION)=0; + virtual bool cast_motion(const RID& p_shape, const Transform2D& p_xform,const Vector2& p_motion,float p_margin,float &p_closest_safe,float &p_closest_unsafe, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION)=0; - virtual bool collide_shape(RID p_shape, const Matrix32& p_shape_xform,const Vector2& p_motion,float p_margin,Vector2 *r_results,int p_result_max,int &r_result_count, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION)=0; + virtual bool collide_shape(RID p_shape, const Transform2D& p_shape_xform,const Vector2& p_motion,float p_margin,Vector2 *r_results,int p_result_max,int &r_result_count, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION)=0; struct ShapeRestInfo { @@ -202,7 +202,7 @@ public: }; - virtual bool rest_info(RID p_shape, const Matrix32& p_shape_xform,const Vector2& p_motion,float p_margin,ShapeRestInfo *r_info, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION)=0; + virtual bool rest_info(RID p_shape, const Transform2D& p_shape_xform,const Vector2& p_motion,float p_margin,ShapeRestInfo *r_info, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION)=0; Physics2DDirectSpaceState(); @@ -211,7 +211,7 @@ public: class Physics2DShapeQueryResult : public Reference { - OBJ_TYPE( Physics2DShapeQueryResult, Reference ); + GDCLASS( Physics2DShapeQueryResult, Reference ); Vector<Physics2DDirectSpaceState::ShapeResult> result; @@ -234,11 +234,11 @@ class Physics2DTestMotionResult; class Physics2DServer : public Object { - OBJ_TYPE( Physics2DServer, Object ); + GDCLASS( Physics2DServer, Object ); static Physics2DServer * singleton; - virtual bool _body_test_motion(RID p_body, const Matrix32 &p_from, const Vector2& p_motion, float p_margin=0.08, const Ref<Physics2DTestMotionResult>& p_result=Ref<Physics2DTestMotionResult>()); + virtual bool _body_test_motion(RID p_body, const Transform2D &p_from, const Vector2& p_motion, float p_margin=0.08, const Ref<Physics2DTestMotionResult>& p_result=Ref<Physics2DTestMotionResult>()); protected: static void _bind_methods(); @@ -268,7 +268,7 @@ public: virtual real_t shape_get_custom_solver_bias(RID p_shape) const=0; //these work well, but should be used from the main thread only - virtual bool shape_collide(RID p_shape_A, const Matrix32& p_xform_A,const Vector2& p_motion_A,RID p_shape_B, const Matrix32& p_xform_B, const Vector2& p_motion_B,Vector2 *r_results,int p_result_max,int &r_result_count)=0; + virtual bool shape_collide(RID p_shape_A, const Transform2D& p_xform_A,const Vector2& p_motion_A,RID p_shape_B, const Transform2D& p_xform_B, const Vector2& p_motion_B,Vector2 *r_results,int p_result_max,int &r_result_count)=0; /* SPACE API */ @@ -333,13 +333,13 @@ 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 Matrix32& p_transform=Matrix32())=0; + virtual void area_add_shape(RID p_area, RID p_shape, const Transform2D& p_transform=Transform2D())=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 Matrix32& p_transform)=0; + virtual void area_set_shape_transform(RID p_area, int p_shape_idx, const Transform2D& p_transform)=0; virtual int area_get_shape_count(RID p_area) const=0; virtual RID area_get_shape(RID p_area, int p_shape_idx) const=0; - virtual Matrix32 area_get_shape_transform(RID p_area, int p_shape_idx) const=0; + virtual Transform2D area_get_shape_transform(RID p_area, int p_shape_idx) const=0; virtual void area_remove_shape(RID p_area, int p_shape_idx)=0; virtual void area_clear_shapes(RID p_area)=0; @@ -348,10 +348,10 @@ public: 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; - virtual void area_set_transform(RID p_area, const Matrix32& p_transform)=0; + virtual void area_set_transform(RID p_area, const Transform2D& p_transform)=0; virtual Variant area_get_param(RID p_parea,AreaParameter p_param) const=0; - virtual Matrix32 area_get_transform(RID p_area) const=0; + virtual Transform2D area_get_transform(RID p_area) const=0; virtual void area_set_collision_mask(RID p_area,uint32_t p_mask)=0; virtual void area_set_layer_mask(RID p_area,uint32_t p_mask)=0; @@ -382,14 +382,14 @@ 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 Matrix32& p_transform=Matrix32())=0; + virtual void body_add_shape(RID p_body, RID p_shape, const Transform2D& p_transform=Transform2D())=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 Matrix32& p_transform)=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; virtual int body_get_shape_count(RID p_body) const=0; virtual RID body_get_shape(RID p_body, int p_shape_idx) const=0; - virtual Matrix32 body_get_shape_transform(RID p_body, int p_shape_idx) const=0; + virtual Transform2D body_get_shape_transform(RID p_body, int p_shape_idx) const=0; virtual Variant body_get_shape_metadata(RID p_body, int p_shape_idx) const=0; virtual void body_set_shape_as_trigger(RID p_body, int p_shape_idx,bool p_enable)=0; @@ -479,7 +479,7 @@ public: virtual void body_set_force_integration_callback(RID p_body,Object *p_receiver,const StringName& p_method,const Variant& p_udata=Variant())=0; - virtual bool body_collide_shape(RID p_body, int p_body_shape,RID p_shape, const Matrix32& p_shape_xform,const Vector2& p_motion,Vector2 *r_results,int p_result_max,int &r_result_count)=0; + virtual bool body_collide_shape(RID p_body, int p_body_shape,RID p_shape, const Transform2D& p_shape_xform,const Vector2& p_motion,Vector2 *r_results,int p_result_max,int &r_result_count)=0; virtual void body_set_pickable(RID p_body,bool p_pickable)=0; @@ -497,7 +497,7 @@ public: Variant collider_metadata; }; - virtual bool body_test_motion(RID p_body,const Matrix32& p_from,const Vector2& p_motion,float p_margin=0.001,MotionResult *r_result=NULL)=0; + virtual bool body_test_motion(RID p_body,const Transform2D& p_from,const Vector2& p_motion,float p_margin=0.001,MotionResult *r_result=NULL)=0; /* JOINT API */ @@ -576,7 +576,7 @@ public: class Physics2DTestMotionResult : public Reference { - OBJ_TYPE( Physics2DTestMotionResult, Reference ); + GDCLASS( Physics2DTestMotionResult, Reference ); Physics2DServer::MotionResult result; bool colliding; diff --git a/servers/physics_server.cpp b/servers/physics_server.cpp index 685477ed79..e76bfd113c 100644 --- a/servers/physics_server.cpp +++ b/servers/physics_server.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -74,42 +74,46 @@ PhysicsServer * PhysicsServer::get_singleton() { void PhysicsDirectBodyState::_bind_methods() { - ObjectTypeDB::bind_method(_MD("get_total_gravity"),&PhysicsDirectBodyState::get_total_gravity); - ObjectTypeDB::bind_method(_MD("get_total_linear_damp"),&PhysicsDirectBodyState::get_total_linear_damp); - ObjectTypeDB::bind_method(_MD("get_total_angular_damp"),&PhysicsDirectBodyState::get_total_angular_damp); + ClassDB::bind_method(D_METHOD("get_total_gravity"),&PhysicsDirectBodyState::get_total_gravity); + ClassDB::bind_method(D_METHOD("get_total_linear_damp"),&PhysicsDirectBodyState::get_total_linear_damp); + ClassDB::bind_method(D_METHOD("get_total_angular_damp"),&PhysicsDirectBodyState::get_total_angular_damp); - ObjectTypeDB::bind_method(_MD("get_inverse_mass"),&PhysicsDirectBodyState::get_inverse_mass); - ObjectTypeDB::bind_method(_MD("get_inverse_inertia"),&PhysicsDirectBodyState::get_inverse_inertia); + ClassDB::bind_method(D_METHOD("get_center_of_mass"),&PhysicsDirectBodyState::get_center_of_mass); + ClassDB::bind_method(D_METHOD("get_principal_inetria_axes"),&PhysicsDirectBodyState::get_principal_inertia_axes); - ObjectTypeDB::bind_method(_MD("set_linear_velocity","velocity"),&PhysicsDirectBodyState::set_linear_velocity); - ObjectTypeDB::bind_method(_MD("get_linear_velocity"),&PhysicsDirectBodyState::get_linear_velocity); + ClassDB::bind_method(D_METHOD("get_inverse_mass"),&PhysicsDirectBodyState::get_inverse_mass); + ClassDB::bind_method(D_METHOD("get_inverse_inertia"),&PhysicsDirectBodyState::get_inverse_inertia); - ObjectTypeDB::bind_method(_MD("set_angular_velocity","velocity"),&PhysicsDirectBodyState::set_angular_velocity); - ObjectTypeDB::bind_method(_MD("get_angular_velocity"),&PhysicsDirectBodyState::get_angular_velocity); + ClassDB::bind_method(D_METHOD("set_linear_velocity","velocity"),&PhysicsDirectBodyState::set_linear_velocity); + ClassDB::bind_method(D_METHOD("get_linear_velocity"),&PhysicsDirectBodyState::get_linear_velocity); - ObjectTypeDB::bind_method(_MD("set_transform","transform"),&PhysicsDirectBodyState::set_transform); - ObjectTypeDB::bind_method(_MD("get_transform"),&PhysicsDirectBodyState::get_transform); + ClassDB::bind_method(D_METHOD("set_angular_velocity","velocity"),&PhysicsDirectBodyState::set_angular_velocity); + ClassDB::bind_method(D_METHOD("get_angular_velocity"),&PhysicsDirectBodyState::get_angular_velocity); - ObjectTypeDB::bind_method(_MD("add_force","force","pos"),&PhysicsDirectBodyState::add_force); - ObjectTypeDB::bind_method(_MD("apply_impulse","pos","j"),&PhysicsDirectBodyState::apply_impulse); + ClassDB::bind_method(D_METHOD("set_transform","transform"),&PhysicsDirectBodyState::set_transform); + ClassDB::bind_method(D_METHOD("get_transform"),&PhysicsDirectBodyState::get_transform); - ObjectTypeDB::bind_method(_MD("set_sleep_state","enabled"),&PhysicsDirectBodyState::set_sleep_state); - ObjectTypeDB::bind_method(_MD("is_sleeping"),&PhysicsDirectBodyState::is_sleeping); + ClassDB::bind_method(D_METHOD("add_force","force","pos"),&PhysicsDirectBodyState::add_force); + ClassDB::bind_method(D_METHOD("apply_impulse","pos","j"),&PhysicsDirectBodyState::apply_impulse); + ClassDB::bind_method(D_METHOD("apply_torqe_impulse","j"),&PhysicsDirectBodyState::apply_torque_impulse); - ObjectTypeDB::bind_method(_MD("get_contact_count"),&PhysicsDirectBodyState::get_contact_count); + ClassDB::bind_method(D_METHOD("set_sleep_state","enabled"),&PhysicsDirectBodyState::set_sleep_state); + ClassDB::bind_method(D_METHOD("is_sleeping"),&PhysicsDirectBodyState::is_sleeping); - ObjectTypeDB::bind_method(_MD("get_contact_local_pos","contact_idx"),&PhysicsDirectBodyState::get_contact_local_pos); - ObjectTypeDB::bind_method(_MD("get_contact_local_normal","contact_idx"),&PhysicsDirectBodyState::get_contact_local_normal); - ObjectTypeDB::bind_method(_MD("get_contact_local_shape","contact_idx"),&PhysicsDirectBodyState::get_contact_local_shape); - ObjectTypeDB::bind_method(_MD("get_contact_collider","contact_idx"),&PhysicsDirectBodyState::get_contact_collider); - ObjectTypeDB::bind_method(_MD("get_contact_collider_pos","contact_idx"),&PhysicsDirectBodyState::get_contact_collider_pos); - ObjectTypeDB::bind_method(_MD("get_contact_collider_id","contact_idx"),&PhysicsDirectBodyState::get_contact_collider_id); - ObjectTypeDB::bind_method(_MD("get_contact_collider_object","contact_idx"),&PhysicsDirectBodyState::get_contact_collider_object); - ObjectTypeDB::bind_method(_MD("get_contact_collider_shape","contact_idx"),&PhysicsDirectBodyState::get_contact_collider_shape); - ObjectTypeDB::bind_method(_MD("get_contact_collider_velocity_at_pos","contact_idx"),&PhysicsDirectBodyState::get_contact_collider_velocity_at_pos); - ObjectTypeDB::bind_method(_MD("get_step"),&PhysicsDirectBodyState::get_step); - ObjectTypeDB::bind_method(_MD("integrate_forces"),&PhysicsDirectBodyState::integrate_forces); - ObjectTypeDB::bind_method(_MD("get_space_state:PhysicsDirectSpaceState"),&PhysicsDirectBodyState::get_space_state); + ClassDB::bind_method(D_METHOD("get_contact_count"),&PhysicsDirectBodyState::get_contact_count); + + ClassDB::bind_method(D_METHOD("get_contact_local_pos","contact_idx"),&PhysicsDirectBodyState::get_contact_local_pos); + ClassDB::bind_method(D_METHOD("get_contact_local_normal","contact_idx"),&PhysicsDirectBodyState::get_contact_local_normal); + ClassDB::bind_method(D_METHOD("get_contact_local_shape","contact_idx"),&PhysicsDirectBodyState::get_contact_local_shape); + ClassDB::bind_method(D_METHOD("get_contact_collider","contact_idx"),&PhysicsDirectBodyState::get_contact_collider); + ClassDB::bind_method(D_METHOD("get_contact_collider_pos","contact_idx"),&PhysicsDirectBodyState::get_contact_collider_pos); + ClassDB::bind_method(D_METHOD("get_contact_collider_id","contact_idx"),&PhysicsDirectBodyState::get_contact_collider_id); + ClassDB::bind_method(D_METHOD("get_contact_collider_object","contact_idx"),&PhysicsDirectBodyState::get_contact_collider_object); + ClassDB::bind_method(D_METHOD("get_contact_collider_shape","contact_idx"),&PhysicsDirectBodyState::get_contact_collider_shape); + ClassDB::bind_method(D_METHOD("get_contact_collider_velocity_at_pos","contact_idx"),&PhysicsDirectBodyState::get_contact_collider_velocity_at_pos); + ClassDB::bind_method(D_METHOD("get_step"),&PhysicsDirectBodyState::get_step); + ClassDB::bind_method(D_METHOD("integrate_forces"),&PhysicsDirectBodyState::integrate_forces); + ClassDB::bind_method(D_METHOD("get_space_state:PhysicsDirectSpaceState"),&PhysicsDirectBodyState::get_space_state); } @@ -174,7 +178,7 @@ int PhysicsShapeQueryParameters::get_object_type_mask() const{ } void PhysicsShapeQueryParameters::set_exclude(const Vector<RID>& p_exclude) { - exclude.clear();; + exclude.clear(); for(int i=0;i<p_exclude.size();i++) exclude.insert(p_exclude[i]); @@ -193,24 +197,24 @@ Vector<RID> PhysicsShapeQueryParameters::get_exclude() const{ void PhysicsShapeQueryParameters::_bind_methods() { - ObjectTypeDB::bind_method(_MD("set_shape","shape:Shape"),&PhysicsShapeQueryParameters::set_shape); - ObjectTypeDB::bind_method(_MD("set_shape_rid","shape"),&PhysicsShapeQueryParameters::set_shape_rid); - ObjectTypeDB::bind_method(_MD("get_shape_rid"),&PhysicsShapeQueryParameters::get_shape_rid); + ClassDB::bind_method(D_METHOD("set_shape","shape:Shape"),&PhysicsShapeQueryParameters::set_shape); + ClassDB::bind_method(D_METHOD("set_shape_rid","shape"),&PhysicsShapeQueryParameters::set_shape_rid); + ClassDB::bind_method(D_METHOD("get_shape_rid"),&PhysicsShapeQueryParameters::get_shape_rid); - ObjectTypeDB::bind_method(_MD("set_transform","transform"),&PhysicsShapeQueryParameters::set_transform); - ObjectTypeDB::bind_method(_MD("get_transform"),&PhysicsShapeQueryParameters::get_transform); + ClassDB::bind_method(D_METHOD("set_transform","transform"),&PhysicsShapeQueryParameters::set_transform); + ClassDB::bind_method(D_METHOD("get_transform"),&PhysicsShapeQueryParameters::get_transform); - ObjectTypeDB::bind_method(_MD("set_margin","margin"),&PhysicsShapeQueryParameters::set_margin); - ObjectTypeDB::bind_method(_MD("get_margin"),&PhysicsShapeQueryParameters::get_margin); + ClassDB::bind_method(D_METHOD("set_margin","margin"),&PhysicsShapeQueryParameters::set_margin); + ClassDB::bind_method(D_METHOD("get_margin"),&PhysicsShapeQueryParameters::get_margin); - ObjectTypeDB::bind_method(_MD("set_layer_mask","layer_mask"),&PhysicsShapeQueryParameters::set_layer_mask); - ObjectTypeDB::bind_method(_MD("get_layer_mask"),&PhysicsShapeQueryParameters::get_layer_mask); + ClassDB::bind_method(D_METHOD("set_layer_mask","layer_mask"),&PhysicsShapeQueryParameters::set_layer_mask); + ClassDB::bind_method(D_METHOD("get_layer_mask"),&PhysicsShapeQueryParameters::get_layer_mask); - ObjectTypeDB::bind_method(_MD("set_object_type_mask","object_type_mask"),&PhysicsShapeQueryParameters::set_object_type_mask); - ObjectTypeDB::bind_method(_MD("get_object_type_mask"),&PhysicsShapeQueryParameters::get_object_type_mask); + ClassDB::bind_method(D_METHOD("set_object_type_mask","object_type_mask"),&PhysicsShapeQueryParameters::set_object_type_mask); + ClassDB::bind_method(D_METHOD("get_object_type_mask"),&PhysicsShapeQueryParameters::get_object_type_mask); - ObjectTypeDB::bind_method(_MD("set_exclude","exclude"),&PhysicsShapeQueryParameters::set_exclude); - ObjectTypeDB::bind_method(_MD("get_exclude"),&PhysicsShapeQueryParameters::get_exclude); + ClassDB::bind_method(D_METHOD("set_exclude","exclude"),&PhysicsShapeQueryParameters::set_exclude); + ClassDB::bind_method(D_METHOD("get_exclude"),&PhysicsShapeQueryParameters::get_exclude); } @@ -267,9 +271,9 @@ Dictionary PhysicsDirectSpaceState::_intersect_ray(const Vector3& p_from, const bool res = intersect_ray(p_from,p_to,inters,exclude,p_layers,p_object_type_mask); if (!res) - return Dictionary(true); + return Dictionary(); - Dictionary d(true); + Dictionary d; d["position"]=inters.position; d["normal"]=inters.normal; d["collider_id"]=inters.collider_id; @@ -306,7 +310,7 @@ Array PhysicsDirectSpaceState::_cast_motion(const Ref<PhysicsShapeQueryParameter bool res = cast_motion(psq->shape,psq->transform,p_motion,psq->margin,closest_safe,closest_unsafe,psq->exclude,psq->layer_mask,psq->object_type_mask); if (!res) return Array(); - Array ret(true); + Array ret; ret.resize(2); ret[0]=closest_safe; ret[1]=closest_unsafe; @@ -333,7 +337,7 @@ Dictionary PhysicsDirectSpaceState::_get_rest_info(const Ref<PhysicsShapeQueryPa ShapeRestInfo sri; bool res = rest_info(psq->shape,psq->transform,psq->margin,&sri,psq->exclude,psq->layer_mask,psq->object_type_mask); - Dictionary r(true); + Dictionary r; if (!res) return r; @@ -359,14 +363,14 @@ PhysicsDirectSpaceState::PhysicsDirectSpaceState() { void PhysicsDirectSpaceState::_bind_methods() { -// ObjectTypeDB::bind_method(_MD("intersect_ray","from","to","exclude","umask"),&PhysicsDirectSpaceState::_intersect_ray,DEFVAL(Array()),DEFVAL(0)); -// ObjectTypeDB::bind_method(_MD("intersect_shape:PhysicsShapeQueryResult","shape","xform","result_max","exclude","umask"),&PhysicsDirectSpaceState::_intersect_shape,DEFVAL(Array()),DEFVAL(0)); + //ClassDB::bind_method(D_METHOD("intersect_ray","from","to","exclude","umask"),&PhysicsDirectSpaceState::_intersect_ray,DEFVAL(Array()),DEFVAL(0)); + //ClassDB::bind_method(D_METHOD("intersect_shape:PhysicsShapeQueryResult","shape","xform","result_max","exclude","umask"),&PhysicsDirectSpaceState::_intersect_shape,DEFVAL(Array()),DEFVAL(0)); - ObjectTypeDB::bind_method(_MD("intersect_ray:Dictionary","from","to","exclude","layer_mask","type_mask"),&PhysicsDirectSpaceState::_intersect_ray,DEFVAL(Array()),DEFVAL(0x7FFFFFFF),DEFVAL(TYPE_MASK_COLLISION)); - ObjectTypeDB::bind_method(_MD("intersect_shape","shape:PhysicsShapeQueryParameters","max_results"),&PhysicsDirectSpaceState::_intersect_shape,DEFVAL(32)); - ObjectTypeDB::bind_method(_MD("cast_motion","shape:PhysicsShapeQueryParameters","motion"),&PhysicsDirectSpaceState::_cast_motion); - ObjectTypeDB::bind_method(_MD("collide_shape","shape:PhysicsShapeQueryParameters","max_results"),&PhysicsDirectSpaceState::_collide_shape,DEFVAL(32)); - ObjectTypeDB::bind_method(_MD("get_rest_info","shape:PhysicsShapeQueryParameters"),&PhysicsDirectSpaceState::_get_rest_info); + ClassDB::bind_method(D_METHOD("intersect_ray:Dictionary","from","to","exclude","layer_mask","type_mask"),&PhysicsDirectSpaceState::_intersect_ray,DEFVAL(Array()),DEFVAL(0x7FFFFFFF),DEFVAL(TYPE_MASK_COLLISION)); + ClassDB::bind_method(D_METHOD("intersect_shape","shape:PhysicsShapeQueryParameters","max_results"),&PhysicsDirectSpaceState::_intersect_shape,DEFVAL(32)); + ClassDB::bind_method(D_METHOD("cast_motion","shape:PhysicsShapeQueryParameters","motion"),&PhysicsDirectSpaceState::_cast_motion); + ClassDB::bind_method(D_METHOD("collide_shape","shape:PhysicsShapeQueryParameters","max_results"),&PhysicsDirectSpaceState::_collide_shape,DEFVAL(32)); + ClassDB::bind_method(D_METHOD("get_rest_info","shape:PhysicsShapeQueryParameters"),&PhysicsDirectSpaceState::_get_rest_info); BIND_CONSTANT( TYPE_MASK_STATIC_BODY ); @@ -407,11 +411,11 @@ PhysicsShapeQueryResult::PhysicsShapeQueryResult() { void PhysicsShapeQueryResult::_bind_methods() { - ObjectTypeDB::bind_method(_MD("get_result_count"),&PhysicsShapeQueryResult::get_result_count); - ObjectTypeDB::bind_method(_MD("get_result_rid","idx"),&PhysicsShapeQueryResult::get_result_rid); - ObjectTypeDB::bind_method(_MD("get_result_object_id","idx"),&PhysicsShapeQueryResult::get_result_object_id); - ObjectTypeDB::bind_method(_MD("get_result_object","idx"),&PhysicsShapeQueryResult::get_result_object); - ObjectTypeDB::bind_method(_MD("get_result_object_shape","idx"),&PhysicsShapeQueryResult::get_result_object_shape); + ClassDB::bind_method(D_METHOD("get_result_count"),&PhysicsShapeQueryResult::get_result_count); + ClassDB::bind_method(D_METHOD("get_result_rid","idx"),&PhysicsShapeQueryResult::get_result_rid); + ClassDB::bind_method(D_METHOD("get_result_object_id","idx"),&PhysicsShapeQueryResult::get_result_object_id); + ClassDB::bind_method(D_METHOD("get_result_object","idx"),&PhysicsShapeQueryResult::get_result_object); + ClassDB::bind_method(D_METHOD("get_result_object_shape","idx"),&PhysicsShapeQueryResult::get_result_object_shape); } @@ -425,117 +429,118 @@ void PhysicsShapeQueryResult::_bind_methods() { void PhysicsServer::_bind_methods() { - ObjectTypeDB::bind_method(_MD("shape_create","type"),&PhysicsServer::shape_create); - ObjectTypeDB::bind_method(_MD("shape_set_data","shape","data"),&PhysicsServer::shape_set_data); + ClassDB::bind_method(D_METHOD("shape_create","type"),&PhysicsServer::shape_create); + ClassDB::bind_method(D_METHOD("shape_set_data","shape","data"),&PhysicsServer::shape_set_data); - ObjectTypeDB::bind_method(_MD("shape_get_type","shape"),&PhysicsServer::shape_get_type); - ObjectTypeDB::bind_method(_MD("shape_get_data","shape"),&PhysicsServer::shape_get_data); + ClassDB::bind_method(D_METHOD("shape_get_type","shape"),&PhysicsServer::shape_get_type); + ClassDB::bind_method(D_METHOD("shape_get_data","shape"),&PhysicsServer::shape_get_data); - ObjectTypeDB::bind_method(_MD("space_create"),&PhysicsServer::space_create); - ObjectTypeDB::bind_method(_MD("space_set_active","space","active"),&PhysicsServer::space_set_active); - ObjectTypeDB::bind_method(_MD("space_is_active","space"),&PhysicsServer::space_is_active); - ObjectTypeDB::bind_method(_MD("space_set_param","space","param","value"),&PhysicsServer::space_set_param); - ObjectTypeDB::bind_method(_MD("space_get_param","space","param"),&PhysicsServer::space_get_param); - ObjectTypeDB::bind_method(_MD("space_get_direct_state:PhysicsDirectSpaceState","space"),&PhysicsServer::space_get_direct_state); + ClassDB::bind_method(D_METHOD("space_create"),&PhysicsServer::space_create); + ClassDB::bind_method(D_METHOD("space_set_active","space","active"),&PhysicsServer::space_set_active); + ClassDB::bind_method(D_METHOD("space_is_active","space"),&PhysicsServer::space_is_active); + ClassDB::bind_method(D_METHOD("space_set_param","space","param","value"),&PhysicsServer::space_set_param); + ClassDB::bind_method(D_METHOD("space_get_param","space","param"),&PhysicsServer::space_get_param); + ClassDB::bind_method(D_METHOD("space_get_direct_state:PhysicsDirectSpaceState","space"),&PhysicsServer::space_get_direct_state); - ObjectTypeDB::bind_method(_MD("area_create"),&PhysicsServer::area_create); - ObjectTypeDB::bind_method(_MD("area_set_space","area","space"),&PhysicsServer::area_set_space); - ObjectTypeDB::bind_method(_MD("area_get_space","area"),&PhysicsServer::area_get_space); + ClassDB::bind_method(D_METHOD("area_create"),&PhysicsServer::area_create); + ClassDB::bind_method(D_METHOD("area_set_space","area","space"),&PhysicsServer::area_set_space); + ClassDB::bind_method(D_METHOD("area_get_space","area"),&PhysicsServer::area_get_space); - ObjectTypeDB::bind_method(_MD("area_set_space_override_mode","area","mode"),&PhysicsServer::area_set_space_override_mode); - ObjectTypeDB::bind_method(_MD("area_get_space_override_mode","area"),&PhysicsServer::area_get_space_override_mode); + 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); - ObjectTypeDB::bind_method(_MD("area_add_shape","area","shape","transform"),&PhysicsServer::area_add_shape,DEFVAL(Transform())); - ObjectTypeDB::bind_method(_MD("area_set_shape","area","shape_idx","shape"),&PhysicsServer::area_set_shape); - ObjectTypeDB::bind_method(_MD("area_set_shape_transform","area","shape_idx","transform"),&PhysicsServer::area_set_shape_transform); + ClassDB::bind_method(D_METHOD("area_add_shape","area","shape","transform"),&PhysicsServer::area_add_shape,DEFVAL(Transform())); + 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); - ObjectTypeDB::bind_method(_MD("area_get_shape_count","area"),&PhysicsServer::area_get_shape_count); - ObjectTypeDB::bind_method(_MD("area_get_shape","area","shape_idx"),&PhysicsServer::area_get_shape); - ObjectTypeDB::bind_method(_MD("area_get_shape_transform","area","shape_idx"),&PhysicsServer::area_get_shape_transform); + 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); + ClassDB::bind_method(D_METHOD("area_get_shape_transform","area","shape_idx"),&PhysicsServer::area_get_shape_transform); - ObjectTypeDB::bind_method(_MD("area_remove_shape","area","shape_idx"),&PhysicsServer::area_remove_shape); - ObjectTypeDB::bind_method(_MD("area_clear_shapes","area"),&PhysicsServer::area_clear_shapes); + ClassDB::bind_method(D_METHOD("area_remove_shape","area","shape_idx"),&PhysicsServer::area_remove_shape); + ClassDB::bind_method(D_METHOD("area_clear_shapes","area"),&PhysicsServer::area_clear_shapes); - ObjectTypeDB::bind_method(_MD("area_set_layer_mask","area","mask"),&PhysicsServer::area_set_layer_mask); - ObjectTypeDB::bind_method(_MD("area_set_collision_mask","area","mask"),&PhysicsServer::area_set_collision_mask); + ClassDB::bind_method(D_METHOD("area_set_layer_mask","area","mask"),&PhysicsServer::area_set_layer_mask); + ClassDB::bind_method(D_METHOD("area_set_collision_mask","area","mask"),&PhysicsServer::area_set_collision_mask); - ObjectTypeDB::bind_method(_MD("area_set_param","area","param","value"),&PhysicsServer::area_set_param); - ObjectTypeDB::bind_method(_MD("area_set_transform","area","transform"),&PhysicsServer::area_set_transform); + ClassDB::bind_method(D_METHOD("area_set_param","area","param","value"),&PhysicsServer::area_set_param); + ClassDB::bind_method(D_METHOD("area_set_transform","area","transform"),&PhysicsServer::area_set_transform); - ObjectTypeDB::bind_method(_MD("area_get_param","area","param"),&PhysicsServer::area_get_param); - ObjectTypeDB::bind_method(_MD("area_get_transform","area"),&PhysicsServer::area_get_transform); + ClassDB::bind_method(D_METHOD("area_get_param","area","param"),&PhysicsServer::area_get_param); + ClassDB::bind_method(D_METHOD("area_get_transform","area"),&PhysicsServer::area_get_transform); - ObjectTypeDB::bind_method(_MD("area_attach_object_instance_ID","area","id"),&PhysicsServer::area_attach_object_instance_ID); - ObjectTypeDB::bind_method(_MD("area_get_object_instance_ID","area"),&PhysicsServer::area_get_object_instance_ID); + ClassDB::bind_method(D_METHOD("area_attach_object_instance_ID","area","id"),&PhysicsServer::area_attach_object_instance_ID); + ClassDB::bind_method(D_METHOD("area_get_object_instance_ID","area"),&PhysicsServer::area_get_object_instance_ID); - ObjectTypeDB::bind_method(_MD("area_set_monitor_callback","area","receiver","method"),&PhysicsServer::area_set_monitor_callback); + ClassDB::bind_method(D_METHOD("area_set_monitor_callback","area","receiver","method"),&PhysicsServer::area_set_monitor_callback); - ObjectTypeDB::bind_method(_MD("area_set_ray_pickable","area","enable"),&PhysicsServer::area_set_ray_pickable); - ObjectTypeDB::bind_method(_MD("area_is_ray_pickable","area"),&PhysicsServer::area_is_ray_pickable); + ClassDB::bind_method(D_METHOD("area_set_ray_pickable","area","enable"),&PhysicsServer::area_set_ray_pickable); + ClassDB::bind_method(D_METHOD("area_is_ray_pickable","area"),&PhysicsServer::area_is_ray_pickable); - ObjectTypeDB::bind_method(_MD("body_create","mode","init_sleeping"),&PhysicsServer::body_create,DEFVAL(BODY_MODE_RIGID),DEFVAL(false)); + ClassDB::bind_method(D_METHOD("body_create","mode","init_sleeping"),&PhysicsServer::body_create,DEFVAL(BODY_MODE_RIGID),DEFVAL(false)); - ObjectTypeDB::bind_method(_MD("body_set_space","body","space"),&PhysicsServer::body_set_space); - ObjectTypeDB::bind_method(_MD("body_get_space","body"),&PhysicsServer::body_get_space); + ClassDB::bind_method(D_METHOD("body_set_space","body","space"),&PhysicsServer::body_set_space); + ClassDB::bind_method(D_METHOD("body_get_space","body"),&PhysicsServer::body_get_space); - ObjectTypeDB::bind_method(_MD("body_set_mode","body","mode"),&PhysicsServer::body_set_mode); - ObjectTypeDB::bind_method(_MD("body_get_mode","body"),&PhysicsServer::body_get_mode); + ClassDB::bind_method(D_METHOD("body_set_mode","body","mode"),&PhysicsServer::body_set_mode); + ClassDB::bind_method(D_METHOD("body_get_mode","body"),&PhysicsServer::body_get_mode); - ObjectTypeDB::bind_method(_MD("body_set_layer_mask","body","mask"),&PhysicsServer::body_set_layer_mask); - ObjectTypeDB::bind_method(_MD("body_get_layer_mask","body"),&PhysicsServer::body_get_layer_mask); + ClassDB::bind_method(D_METHOD("body_set_layer_mask","body","mask"),&PhysicsServer::body_set_layer_mask); + ClassDB::bind_method(D_METHOD("body_get_layer_mask","body"),&PhysicsServer::body_get_layer_mask); - ObjectTypeDB::bind_method(_MD("body_set_collision_mask","body","mask"),&PhysicsServer::body_set_collision_mask); - ObjectTypeDB::bind_method(_MD("body_get_collision_mask","body"),&PhysicsServer::body_get_collision_mask); + 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); - ObjectTypeDB::bind_method(_MD("body_add_shape","body","shape","transform"),&PhysicsServer::body_add_shape,DEFVAL(Transform())); - ObjectTypeDB::bind_method(_MD("body_set_shape","body","shape_idx","shape"),&PhysicsServer::body_set_shape); - ObjectTypeDB::bind_method(_MD("body_set_shape_transform","body","shape_idx","transform"),&PhysicsServer::body_set_shape_transform); + ClassDB::bind_method(D_METHOD("body_add_shape","body","shape","transform"),&PhysicsServer::body_add_shape,DEFVAL(Transform())); + 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); - ObjectTypeDB::bind_method(_MD("body_get_shape_count","body"),&PhysicsServer::body_get_shape_count); - ObjectTypeDB::bind_method(_MD("body_get_shape","body","shape_idx"),&PhysicsServer::body_get_shape); - ObjectTypeDB::bind_method(_MD("body_get_shape_transform","body","shape_idx"),&PhysicsServer::body_get_shape_transform); + 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); + ClassDB::bind_method(D_METHOD("body_get_shape_transform","body","shape_idx"),&PhysicsServer::body_get_shape_transform); - ObjectTypeDB::bind_method(_MD("body_remove_shape","body","shape_idx"),&PhysicsServer::body_remove_shape); - ObjectTypeDB::bind_method(_MD("body_clear_shapes","body"),&PhysicsServer::body_clear_shapes); + ClassDB::bind_method(D_METHOD("body_remove_shape","body","shape_idx"),&PhysicsServer::body_remove_shape); + ClassDB::bind_method(D_METHOD("body_clear_shapes","body"),&PhysicsServer::body_clear_shapes); - ObjectTypeDB::bind_method(_MD("body_attach_object_instance_ID","body","id"),&PhysicsServer::body_attach_object_instance_ID); - ObjectTypeDB::bind_method(_MD("body_get_object_instance_ID","body"),&PhysicsServer::body_get_object_instance_ID); + ClassDB::bind_method(D_METHOD("body_attach_object_instance_ID","body","id"),&PhysicsServer::body_attach_object_instance_ID); + ClassDB::bind_method(D_METHOD("body_get_object_instance_ID","body"),&PhysicsServer::body_get_object_instance_ID); - ObjectTypeDB::bind_method(_MD("body_set_enable_continuous_collision_detection","body","enable"),&PhysicsServer::body_set_enable_continuous_collision_detection); - ObjectTypeDB::bind_method(_MD("body_is_continuous_collision_detection_enabled","body"),&PhysicsServer::body_is_continuous_collision_detection_enabled); + ClassDB::bind_method(D_METHOD("body_set_enable_continuous_collision_detection","body","enable"),&PhysicsServer::body_set_enable_continuous_collision_detection); + ClassDB::bind_method(D_METHOD("body_is_continuous_collision_detection_enabled","body"),&PhysicsServer::body_is_continuous_collision_detection_enabled); - //ObjectTypeDB::bind_method(_MD("body_set_user_flags","flags""),&PhysicsServer::body_set_shape,DEFVAL(Transform)); - //ObjectTypeDB::bind_method(_MD("body_get_user_flags","body","shape_idx","shape"),&PhysicsServer::body_get_shape); + //ClassDB::bind_method(D_METHOD("body_set_user_flags","flags""),&PhysicsServer::body_set_shape,DEFVAL(Transform)); + //ClassDB::bind_method(D_METHOD("body_get_user_flags","body","shape_idx","shape"),&PhysicsServer::body_get_shape); - ObjectTypeDB::bind_method(_MD("body_set_param","body","param","value"),&PhysicsServer::body_set_param); - ObjectTypeDB::bind_method(_MD("body_get_param","body","param"),&PhysicsServer::body_get_param); + ClassDB::bind_method(D_METHOD("body_set_param","body","param","value"),&PhysicsServer::body_set_param); + ClassDB::bind_method(D_METHOD("body_get_param","body","param"),&PhysicsServer::body_get_param); - ObjectTypeDB::bind_method(_MD("body_set_state","body","state","value"),&PhysicsServer::body_set_state); - ObjectTypeDB::bind_method(_MD("body_get_state","body","state"),&PhysicsServer::body_get_state); + ClassDB::bind_method(D_METHOD("body_set_state","body","state","value"),&PhysicsServer::body_set_state); + ClassDB::bind_method(D_METHOD("body_get_state","body","state"),&PhysicsServer::body_get_state); - ObjectTypeDB::bind_method(_MD("body_apply_impulse","body","pos","impulse"),&PhysicsServer::body_apply_impulse); - ObjectTypeDB::bind_method(_MD("body_set_axis_velocity","body","axis_velocity"),&PhysicsServer::body_set_axis_velocity); + ClassDB::bind_method(D_METHOD("body_apply_impulse","body","pos","impulse"),&PhysicsServer::body_apply_impulse); + ClassDB::bind_method(D_METHOD("body_apply_torque_impulse","body","impulse"),&PhysicsServer::body_apply_torque_impulse); + ClassDB::bind_method(D_METHOD("body_set_axis_velocity","body","axis_velocity"),&PhysicsServer::body_set_axis_velocity); - ObjectTypeDB::bind_method(_MD("body_set_axis_lock","body","axis"),&PhysicsServer::body_set_axis_lock); - ObjectTypeDB::bind_method(_MD("body_get_axis_lock","body"),&PhysicsServer::body_get_axis_lock); + ClassDB::bind_method(D_METHOD("body_set_axis_lock","body","axis"),&PhysicsServer::body_set_axis_lock); + ClassDB::bind_method(D_METHOD("body_get_axis_lock","body"),&PhysicsServer::body_get_axis_lock); - ObjectTypeDB::bind_method(_MD("body_add_collision_exception","body","excepted_body"),&PhysicsServer::body_add_collision_exception); - ObjectTypeDB::bind_method(_MD("body_remove_collision_exception","body","excepted_body"),&PhysicsServer::body_remove_collision_exception); -// virtual void body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions)=0; + ClassDB::bind_method(D_METHOD("body_add_collision_exception","body","excepted_body"),&PhysicsServer::body_add_collision_exception); + ClassDB::bind_method(D_METHOD("body_remove_collision_exception","body","excepted_body"),&PhysicsServer::body_remove_collision_exception); + //virtual void body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions)=0; - ObjectTypeDB::bind_method(_MD("body_set_max_contacts_reported","body","amount"),&PhysicsServer::body_set_max_contacts_reported); - ObjectTypeDB::bind_method(_MD("body_get_max_contacts_reported","body"),&PhysicsServer::body_get_max_contacts_reported); + ClassDB::bind_method(D_METHOD("body_set_max_contacts_reported","body","amount"),&PhysicsServer::body_set_max_contacts_reported); + ClassDB::bind_method(D_METHOD("body_get_max_contacts_reported","body"),&PhysicsServer::body_get_max_contacts_reported); - ObjectTypeDB::bind_method(_MD("body_set_omit_force_integration","body","enable"),&PhysicsServer::body_set_omit_force_integration); - ObjectTypeDB::bind_method(_MD("body_is_omitting_force_integration","body"),&PhysicsServer::body_is_omitting_force_integration); + ClassDB::bind_method(D_METHOD("body_set_omit_force_integration","body","enable"),&PhysicsServer::body_set_omit_force_integration); + ClassDB::bind_method(D_METHOD("body_is_omitting_force_integration","body"),&PhysicsServer::body_is_omitting_force_integration); - ObjectTypeDB::bind_method(_MD("body_set_force_integration_callback","body","receiver","method","userdata"),&PhysicsServer::body_set_force_integration_callback,DEFVAL(Variant())); + ClassDB::bind_method(D_METHOD("body_set_force_integration_callback","body","receiver","method","userdata"),&PhysicsServer::body_set_force_integration_callback,DEFVAL(Variant())); - ObjectTypeDB::bind_method(_MD("body_set_ray_pickable","body","enable"),&PhysicsServer::body_set_ray_pickable); - ObjectTypeDB::bind_method(_MD("body_is_ray_pickable","body"),&PhysicsServer::body_is_ray_pickable); + ClassDB::bind_method(D_METHOD("body_set_ray_pickable","body","enable"),&PhysicsServer::body_set_ray_pickable); + ClassDB::bind_method(D_METHOD("body_is_ray_pickable","body"),&PhysicsServer::body_is_ray_pickable); /* JOINT API */ @@ -545,15 +550,15 @@ void PhysicsServer::_bind_methods() { BIND_CONSTANT( JOINT_CONE_TWIST ); BIND_CONSTANT( JOINT_6DOF ); - ObjectTypeDB::bind_method(_MD("joint_create_pin","body_A","local_A","body_B","local_B"),&PhysicsServer::joint_create_pin); - ObjectTypeDB::bind_method(_MD("pin_joint_set_param","joint","param","value"),&PhysicsServer::pin_joint_set_param); - ObjectTypeDB::bind_method(_MD("pin_joint_get_param","joint","param"),&PhysicsServer::pin_joint_get_param); + ClassDB::bind_method(D_METHOD("joint_create_pin","body_A","local_A","body_B","local_B"),&PhysicsServer::joint_create_pin); + ClassDB::bind_method(D_METHOD("pin_joint_set_param","joint","param","value"),&PhysicsServer::pin_joint_set_param); + ClassDB::bind_method(D_METHOD("pin_joint_get_param","joint","param"),&PhysicsServer::pin_joint_get_param); - ObjectTypeDB::bind_method(_MD("pin_joint_set_local_A","joint","local_A"),&PhysicsServer::pin_joint_set_local_A); - ObjectTypeDB::bind_method(_MD("pin_joint_get_local_A","joint"),&PhysicsServer::pin_joint_get_local_A); + ClassDB::bind_method(D_METHOD("pin_joint_set_local_A","joint","local_A"),&PhysicsServer::pin_joint_set_local_A); + ClassDB::bind_method(D_METHOD("pin_joint_get_local_A","joint"),&PhysicsServer::pin_joint_get_local_A); - ObjectTypeDB::bind_method(_MD("pin_joint_set_local_B","joint","local_B"),&PhysicsServer::pin_joint_set_local_B); - ObjectTypeDB::bind_method(_MD("pin_joint_get_local_B","joint"),&PhysicsServer::pin_joint_get_local_B); + ClassDB::bind_method(D_METHOD("pin_joint_set_local_B","joint","local_B"),&PhysicsServer::pin_joint_set_local_B); + ClassDB::bind_method(D_METHOD("pin_joint_get_local_B","joint"),&PhysicsServer::pin_joint_get_local_B); BIND_CONSTANT(PIN_JOINT_BIAS ); BIND_CONSTANT(PIN_JOINT_DAMPING ); @@ -571,18 +576,18 @@ void PhysicsServer::_bind_methods() { BIND_CONSTANT(HINGE_JOINT_FLAG_USE_LIMIT); BIND_CONSTANT(HINGE_JOINT_FLAG_ENABLE_MOTOR); - ObjectTypeDB::bind_method(_MD("joint_create_hinge","body_A","hinge_A","body_B","hinge_B"),&PhysicsServer::joint_create_hinge); + ClassDB::bind_method(D_METHOD("joint_create_hinge","body_A","hinge_A","body_B","hinge_B"),&PhysicsServer::joint_create_hinge); - ObjectTypeDB::bind_method(_MD("hinge_joint_set_param","joint","param","value"),&PhysicsServer::hinge_joint_set_param); - ObjectTypeDB::bind_method(_MD("hinge_joint_get_param","joint","param"),&PhysicsServer::hinge_joint_get_param); + ClassDB::bind_method(D_METHOD("hinge_joint_set_param","joint","param","value"),&PhysicsServer::hinge_joint_set_param); + ClassDB::bind_method(D_METHOD("hinge_joint_get_param","joint","param"),&PhysicsServer::hinge_joint_get_param); - ObjectTypeDB::bind_method(_MD("hinge_joint_set_flag","joint","flag","enabled"),&PhysicsServer::hinge_joint_set_flag); - ObjectTypeDB::bind_method(_MD("hinge_joint_get_flag","joint","flag"),&PhysicsServer::hinge_joint_get_flag); + ClassDB::bind_method(D_METHOD("hinge_joint_set_flag","joint","flag","enabled"),&PhysicsServer::hinge_joint_set_flag); + ClassDB::bind_method(D_METHOD("hinge_joint_get_flag","joint","flag"),&PhysicsServer::hinge_joint_get_flag); - ObjectTypeDB::bind_method(_MD("joint_create_slider","body_A","local_ref_A","body_B","local_ref_B"),&PhysicsServer::joint_create_slider); + ClassDB::bind_method(D_METHOD("joint_create_slider","body_A","local_ref_A","body_B","local_ref_B"),&PhysicsServer::joint_create_slider); - ObjectTypeDB::bind_method(_MD("slider_joint_set_param","joint","param","value"),&PhysicsServer::slider_joint_set_param); - ObjectTypeDB::bind_method(_MD("slider_joint_get_param","joint","param"),&PhysicsServer::slider_joint_get_param); + ClassDB::bind_method(D_METHOD("slider_joint_set_param","joint","param","value"),&PhysicsServer::slider_joint_set_param); + ClassDB::bind_method(D_METHOD("slider_joint_get_param","joint","param"),&PhysicsServer::slider_joint_get_param); BIND_CONSTANT( SLIDER_JOINT_LINEAR_LIMIT_UPPER ); BIND_CONSTANT( SLIDER_JOINT_LINEAR_LIMIT_LOWER ); @@ -610,10 +615,10 @@ void PhysicsServer::_bind_methods() { BIND_CONSTANT( SLIDER_JOINT_MAX ); - ObjectTypeDB::bind_method(_MD("joint_create_cone_twist","body_A","local_ref_A","body_B","local_ref_B"),&PhysicsServer::joint_create_cone_twist); + ClassDB::bind_method(D_METHOD("joint_create_cone_twist","body_A","local_ref_A","body_B","local_ref_B"),&PhysicsServer::joint_create_cone_twist); - ObjectTypeDB::bind_method(_MD("cone_twist_joint_set_param","joint","param","value"),&PhysicsServer::cone_twist_joint_set_param); - ObjectTypeDB::bind_method(_MD("cone_twist_joint_get_param","joint","param"),&PhysicsServer::cone_twist_joint_get_param); + ClassDB::bind_method(D_METHOD("cone_twist_joint_set_param","joint","param","value"),&PhysicsServer::cone_twist_joint_set_param); + ClassDB::bind_method(D_METHOD("cone_twist_joint_get_param","joint","param"),&PhysicsServer::cone_twist_joint_get_param); BIND_CONSTANT( CONE_TWIST_JOINT_SWING_SPAN ); BIND_CONSTANT( CONE_TWIST_JOINT_TWIST_SPAN ); @@ -642,44 +647,44 @@ void PhysicsServer::_bind_methods() { BIND_CONSTANT( G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT ); BIND_CONSTANT( G6DOF_JOINT_FLAG_ENABLE_MOTOR ); - ObjectTypeDB::bind_method(_MD("joint_get_type","joint"),&PhysicsServer::joint_get_type); + ClassDB::bind_method(D_METHOD("joint_get_type","joint"),&PhysicsServer::joint_get_type); - ObjectTypeDB::bind_method(_MD("joint_set_solver_priority","joint","priority"),&PhysicsServer::joint_set_solver_priority); - ObjectTypeDB::bind_method(_MD("joint_get_solver_priority","joint"),&PhysicsServer::joint_get_solver_priority); + ClassDB::bind_method(D_METHOD("joint_set_solver_priority","joint","priority"),&PhysicsServer::joint_set_solver_priority); + ClassDB::bind_method(D_METHOD("joint_get_solver_priority","joint"),&PhysicsServer::joint_get_solver_priority); - ObjectTypeDB::bind_method(_MD("joint_create_generic_6dof","body_A","local_ref_A","body_B","local_ref_B"),&PhysicsServer::joint_create_generic_6dof); + ClassDB::bind_method(D_METHOD("joint_create_generic_6dof","body_A","local_ref_A","body_B","local_ref_B"),&PhysicsServer::joint_create_generic_6dof); - ObjectTypeDB::bind_method(_MD("generic_6dof_joint_set_param","joint","axis","param","value"),&PhysicsServer::generic_6dof_joint_set_param); - ObjectTypeDB::bind_method(_MD("generic_6dof_joint_get_param","joint","axis","param"),&PhysicsServer::generic_6dof_joint_get_param); + ClassDB::bind_method(D_METHOD("generic_6dof_joint_set_param","joint","axis","param","value"),&PhysicsServer::generic_6dof_joint_set_param); + ClassDB::bind_method(D_METHOD("generic_6dof_joint_get_param","joint","axis","param"),&PhysicsServer::generic_6dof_joint_get_param); - ObjectTypeDB::bind_method(_MD("generic_6dof_joint_set_flag","joint","axis","flag","enable"),&PhysicsServer::generic_6dof_joint_set_flag); - ObjectTypeDB::bind_method(_MD("generic_6dof_joint_get_flag","joint","axis","flag"),&PhysicsServer::generic_6dof_joint_get_flag); + ClassDB::bind_method(D_METHOD("generic_6dof_joint_set_flag","joint","axis","flag","enable"),&PhysicsServer::generic_6dof_joint_set_flag); + ClassDB::bind_method(D_METHOD("generic_6dof_joint_get_flag","joint","axis","flag"),&PhysicsServer::generic_6dof_joint_get_flag); /* - ObjectTypeDB::bind_method(_MD("joint_set_param","joint","param","value"),&PhysicsServer::joint_set_param); - ObjectTypeDB::bind_method(_MD("joint_get_param","joint","param"),&PhysicsServer::joint_get_param); + ClassDB::bind_method(D_METHOD("joint_set_param","joint","param","value"),&PhysicsServer::joint_set_param); + ClassDB::bind_method(D_METHOD("joint_get_param","joint","param"),&PhysicsServer::joint_get_param); - ObjectTypeDB::bind_method(_MD("pin_joint_create","anchor","body_a","body_b"),&PhysicsServer::pin_joint_create,DEFVAL(RID())); - ObjectTypeDB::bind_method(_MD("groove_joint_create","groove1_a","groove2_a","anchor_b","body_a","body_b"),&PhysicsServer::groove_joint_create,DEFVAL(RID()),DEFVAL(RID())); - ObjectTypeDB::bind_method(_MD("damped_spring_joint_create","anchor_a","anchor_b","body_a","body_b"),&PhysicsServer::damped_spring_joint_create,DEFVAL(RID())); + ClassDB::bind_method(D_METHOD("pin_joint_create","anchor","body_a","body_b"),&PhysicsServer::pin_joint_create,DEFVAL(RID())); + ClassDB::bind_method(D_METHOD("groove_joint_create","groove1_a","groove2_a","anchor_b","body_a","body_b"),&PhysicsServer::groove_joint_create,DEFVAL(RID()),DEFVAL(RID())); + ClassDB::bind_method(D_METHOD("damped_spring_joint_create","anchor_a","anchor_b","body_a","body_b"),&PhysicsServer::damped_spring_joint_create,DEFVAL(RID())); - ObjectTypeDB::bind_method(_MD("damped_string_joint_set_param","joint","param","value"),&PhysicsServer::damped_string_joint_set_param,DEFVAL(RID())); - ObjectTypeDB::bind_method(_MD("damped_string_joint_get_param","joint","param"),&PhysicsServer::damped_string_joint_get_param); + ClassDB::bind_method(D_METHOD("damped_string_joint_set_param","joint","param","value"),&PhysicsServer::damped_string_joint_set_param,DEFVAL(RID())); + ClassDB::bind_method(D_METHOD("damped_string_joint_get_param","joint","param"),&PhysicsServer::damped_string_joint_get_param); - ObjectTypeDB::bind_method(_MD("joint_get_type","joint"),&PhysicsServer::joint_get_type); + ClassDB::bind_method(D_METHOD("joint_get_type","joint"),&PhysicsServer::joint_get_type); */ - ObjectTypeDB::bind_method(_MD("free_rid","rid"),&PhysicsServer::free); + ClassDB::bind_method(D_METHOD("free_rid","rid"),&PhysicsServer::free); - ObjectTypeDB::bind_method(_MD("set_active","active"),&PhysicsServer::set_active); + ClassDB::bind_method(D_METHOD("set_active","active"),&PhysicsServer::set_active); -// ObjectTypeDB::bind_method(_MD("init"),&PhysicsServer::init); -// ObjectTypeDB::bind_method(_MD("step"),&PhysicsServer::step); -// ObjectTypeDB::bind_method(_MD("sync"),&PhysicsServer::sync); - //ObjectTypeDB::bind_method(_MD("flush_queries"),&PhysicsServer::flush_queries); + //ClassDB::bind_method(D_METHOD("init"),&PhysicsServer::init); + //ClassDB::bind_method(D_METHOD("step"),&PhysicsServer::step); + //ClassDB::bind_method(D_METHOD("sync"),&PhysicsServer::sync); + //ClassDB::bind_method(D_METHOD("flush_queries"),&PhysicsServer::flush_queries); - ObjectTypeDB::bind_method(_MD("get_process_info","process_info"),&PhysicsServer::get_process_info); + ClassDB::bind_method(D_METHOD("get_process_info","process_info"),&PhysicsServer::get_process_info); BIND_CONSTANT( SHAPE_PLANE ); BIND_CONSTANT( SHAPE_RAY ); @@ -734,8 +739,8 @@ void PhysicsServer::_bind_methods() { BIND_CONSTANT( DAMPED_STRING_STIFFNESS ); BIND_CONSTANT( DAMPED_STRING_DAMPING ); */ -// BIND_CONSTANT( TYPE_BODY ); -// BIND_CONSTANT( TYPE_AREA ); + //BIND_CONSTANT( TYPE_BODY ); + //BIND_CONSTANT( TYPE_AREA ); BIND_CONSTANT( AREA_BODY_ADDED ); BIND_CONSTANT( AREA_BODY_REMOVED ); diff --git a/servers/physics_server.h b/servers/physics_server.h index 5221b38ccb..653959be45 100644 --- a/servers/physics_server.h +++ b/servers/physics_server.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -36,7 +36,7 @@ class PhysicsDirectSpaceState; class PhysicsDirectBodyState : public Object { - OBJ_TYPE( PhysicsDirectBodyState, Object ); + GDCLASS( PhysicsDirectBodyState, Object ); protected: static void _bind_methods(); public: @@ -45,9 +45,11 @@ public: virtual float get_total_angular_damp() const=0; virtual float get_total_linear_damp() const=0; + virtual Vector3 get_center_of_mass() const=0; + virtual Basis get_principal_inertia_axes() const=0; virtual float get_inverse_mass() const=0; // get the mass virtual Vector3 get_inverse_inertia() const=0; // get density of this body space - virtual Matrix3 get_inverse_inertia_tensor() const=0; // get density of this body space + virtual Basis get_inverse_inertia_tensor() const=0; // get density of this body space virtual void set_linear_velocity(const Vector3& p_velocity)=0; virtual Vector3 get_linear_velocity() const=0; @@ -60,6 +62,7 @@ public: virtual void add_force(const Vector3& p_force, const Vector3& p_pos)=0; virtual void apply_impulse(const Vector3& p_pos, const Vector3& p_j)=0; + virtual void apply_torque_impulse(const Vector3& p_j)=0; virtual void set_sleep_state(bool p_enable)=0; virtual bool is_sleeping() const=0; @@ -90,7 +93,7 @@ class PhysicsShapeQueryResult; class PhysicsShapeQueryParameters : public Reference { - OBJ_TYPE(PhysicsShapeQueryParameters, Reference); + GDCLASS(PhysicsShapeQueryParameters, Reference); friend class PhysicsDirectSpaceState; RID shape; Transform transform; @@ -130,10 +133,10 @@ public: class PhysicsDirectSpaceState : public Object { - OBJ_TYPE( PhysicsDirectSpaceState, Object ); + GDCLASS( PhysicsDirectSpaceState, Object ); -// Variant _intersect_ray(const Vector3& p_from, const Vector3& p_to,const Vector<RID>& p_exclude=Vector<RID>(),uint32_t p_collision_mask=0); -// Variant _intersect_shape(const RID& p_shape, const Transform& p_xform,int p_result_max=64,const Vector<RID>& p_exclude=Vector<RID>(),uint32_t p_collision_mask=0); + //Variant _intersect_ray(const Vector3& p_from, const Vector3& p_to,const Vector<RID>& p_exclude=Vector<RID>(),uint32_t p_collision_mask=0); + //Variant _intersect_shape(const RID& p_shape, const Transform& p_xform,int p_result_max=64,const Vector<RID>& p_exclude=Vector<RID>(),uint32_t p_collision_mask=0); public: enum ObjectTypeMask { @@ -207,7 +210,7 @@ public: class PhysicsShapeQueryResult : public Reference { - OBJ_TYPE( PhysicsShapeQueryResult, Reference ); + GDCLASS( PhysicsShapeQueryResult, Reference ); Vector<PhysicsDirectSpaceState::ShapeResult> result; @@ -229,7 +232,7 @@ public: class PhysicsServer : public Object { - OBJ_TYPE( PhysicsServer, Object ); + GDCLASS( PhysicsServer, Object ); static PhysicsServer * singleton; @@ -441,6 +444,7 @@ public: virtual Vector3 body_get_applied_torque(RID p_body) const=0; virtual void body_apply_impulse(RID p_body, const Vector3& p_pos, const Vector3& p_impulse)=0; + virtual void body_apply_torque_impulse(RID p_body, const Vector3& p_impulse)=0; virtual void body_set_axis_velocity(RID p_body, const Vector3& p_axis_velocity)=0; enum BodyAxisLock { diff --git a/servers/register_server_types.cpp b/servers/register_server_types.cpp index 06eaa4d122..0d0619e880 100644 --- a/servers/register_server_types.cpp +++ b/servers/register_server_types.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -27,15 +27,29 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "register_server_types.h" -#include "globals.h" +#include "global_config.h" #include "visual_server.h" #include "audio_server.h" #include "physics_server.h" #include "physics_2d_server.h" -#include "spatial_sound_server.h" -#include "spatial_sound_2d_server.h" #include "script_debugger_remote.h" +#include "visual/shader_types.h" +#include "audio/audio_stream.h" +#include "audio/audio_effect.h" +#include "audio/effects/audio_effect_amplify.h" +#include "audio/effects/audio_effect_reverb.h" +#include "audio/effects/audio_effect_filter.h" +#include "audio/effects/audio_effect_eq.h" +#include "audio/effects/audio_effect_distortion.h" +#include "audio/effects/audio_effect_stereo_enhance.h" +#include "audio/effects/audio_effect_panner.h" +#include "audio/effects/audio_effect_chorus.h" +#include "audio/effects/audio_effect_delay.h" +#include "audio/effects/audio_effect_compressor.h" +#include "audio/effects/audio_effect_limiter.h" +#include "audio/effects/audio_effect_pitch_shift.h" +#include "audio/effects/audio_effect_phaser.h" static void _debugger_get_resource_usage(List<ScriptDebuggerRemote::ResourceUsage>* r_usage) { @@ -55,37 +69,71 @@ static void _debugger_get_resource_usage(List<ScriptDebuggerRemote::ResourceUsag } +ShaderTypes *shader_types=NULL; + void register_server_types() { - Globals::get_singleton()->add_singleton( Globals::Singleton("VisualServer",VisualServer::get_singleton()) ); - Globals::get_singleton()->add_singleton( Globals::Singleton("VS",VisualServer::get_singleton()) ); - Globals::get_singleton()->add_singleton( Globals::Singleton("AudioServer",AudioServer::get_singleton()) ); - Globals::get_singleton()->add_singleton( Globals::Singleton("AS",AudioServer::get_singleton()) ); - Globals::get_singleton()->add_singleton( Globals::Singleton("PhysicsServer",PhysicsServer::get_singleton()) ); - Globals::get_singleton()->add_singleton( Globals::Singleton("PS",PhysicsServer::get_singleton()) ); - Globals::get_singleton()->add_singleton( Globals::Singleton("Physics2DServer",Physics2DServer::get_singleton()) ); - Globals::get_singleton()->add_singleton( Globals::Singleton("PS2D",Physics2DServer::get_singleton()) ); - Globals::get_singleton()->add_singleton( Globals::Singleton("SpatialSoundServer",SpatialSoundServer::get_singleton()) ); - Globals::get_singleton()->add_singleton( Globals::Singleton("SS",SpatialSoundServer::get_singleton()) ); - Globals::get_singleton()->add_singleton( Globals::Singleton("SpatialSound2DServer",SpatialSound2DServer::get_singleton()) ); - Globals::get_singleton()->add_singleton( Globals::Singleton("SS2D",SpatialSound2DServer::get_singleton()) ); - - - ObjectTypeDB::register_virtual_type<Physics2DDirectBodyState>(); - ObjectTypeDB::register_virtual_type<Physics2DDirectSpaceState>(); - ObjectTypeDB::register_virtual_type<Physics2DShapeQueryResult>(); - ObjectTypeDB::register_type<Physics2DTestMotionResult>(); - ObjectTypeDB::register_type<Physics2DShapeQueryParameters>(); - - ObjectTypeDB::register_type<PhysicsShapeQueryParameters>(); - ObjectTypeDB::register_virtual_type<PhysicsDirectBodyState>(); - ObjectTypeDB::register_virtual_type<PhysicsDirectSpaceState>(); - ObjectTypeDB::register_virtual_type<PhysicsShapeQueryResult>(); + GLOBAL_DEF("memory/multithread/thread_rid_pool_prealloc",20); + + GlobalConfig::get_singleton()->add_singleton( GlobalConfig::Singleton("VisualServer",VisualServer::get_singleton()) ); + GlobalConfig::get_singleton()->add_singleton( GlobalConfig::Singleton("AudioServer",AudioServer::get_singleton()) ); + GlobalConfig::get_singleton()->add_singleton( GlobalConfig::Singleton("PhysicsServer",PhysicsServer::get_singleton()) ); + GlobalConfig::get_singleton()->add_singleton( GlobalConfig::Singleton("Physics2DServer",Physics2DServer::get_singleton()) ); + + shader_types = memnew( ShaderTypes ); + + ClassDB::register_virtual_class<AudioStream>(); + ClassDB::register_virtual_class<AudioStreamPlayback>(); + ClassDB::register_virtual_class<AudioEffect>(); + ClassDB::register_class<AudioBusLayout>(); + + { + //audio effects + ClassDB::register_class<AudioEffectAmplify>(); + + ClassDB::register_class<AudioEffectReverb>(); + + ClassDB::register_class<AudioEffectLowPassFilter>(); + ClassDB::register_class<AudioEffectHighPassFilter>(); + ClassDB::register_class<AudioEffectBandPassFilter>(); + ClassDB::register_class<AudioEffectNotchFilter>(); + ClassDB::register_class<AudioEffectBandLimitFilter>(); + ClassDB::register_class<AudioEffectLowShelfFilter>(); + ClassDB::register_class<AudioEffectHighShelfFilter>(); + + ClassDB::register_class<AudioEffectEQ6>(); + ClassDB::register_class<AudioEffectEQ10>(); + ClassDB::register_class<AudioEffectEQ21>(); + + ClassDB::register_class<AudioEffectDistortion>(); + + ClassDB::register_class<AudioEffectStereoEnhance>(); + + ClassDB::register_class<AudioEffectPanner>(); + ClassDB::register_class<AudioEffectChorus>(); + ClassDB::register_class<AudioEffectDelay>(); + ClassDB::register_class<AudioEffectCompressor>(); + ClassDB::register_class<AudioEffectLimiter>(); + ClassDB::register_class<AudioEffectPitchShift>(); + ClassDB::register_class<AudioEffectPhaser>(); + } + + + ClassDB::register_virtual_class<Physics2DDirectBodyState>(); + ClassDB::register_virtual_class<Physics2DDirectSpaceState>(); + ClassDB::register_virtual_class<Physics2DShapeQueryResult>(); + ClassDB::register_class<Physics2DTestMotionResult>(); + ClassDB::register_class<Physics2DShapeQueryParameters>(); + + ClassDB::register_class<PhysicsShapeQueryParameters>(); + ClassDB::register_virtual_class<PhysicsDirectBodyState>(); + ClassDB::register_virtual_class<PhysicsDirectSpaceState>(); + ClassDB::register_virtual_class<PhysicsShapeQueryResult>(); ScriptDebuggerRemote::resource_usage_func=_debugger_get_resource_usage; } void unregister_server_types(){ - + memdelete( shader_types ); } diff --git a/servers/register_server_types.h b/servers/register_server_types.h index a62af905b3..a3e7d3ee32 100644 --- a/servers/register_server_types.h +++ b/servers/register_server_types.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/servers/server_wrap_mt_common.h b/servers/server_wrap_mt_common.h index dd9d603852..fbc68fc879 100644 --- a/servers/server_wrap_mt_common.h +++ b/servers/server_wrap_mt_common.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ diff --git a/servers/spatial_sound/SCsub b/servers/spatial_sound/SCsub deleted file mode 100644 index d31af2c1c4..0000000000 --- a/servers/spatial_sound/SCsub +++ /dev/null @@ -1,5 +0,0 @@ -Import('env') - -env.add_source_files(env.servers_sources,"*.cpp") - -Export('env') diff --git a/servers/spatial_sound/spatial_sound_server_sw.cpp b/servers/spatial_sound/spatial_sound_server_sw.cpp deleted file mode 100644 index dc15d61afa..0000000000 --- a/servers/spatial_sound/spatial_sound_server_sw.cpp +++ /dev/null @@ -1,1071 +0,0 @@ -/*************************************************************************/ -/* spatial_sound_server_sw.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "spatial_sound_server_sw.h" -#include "os/os.h" -#include "servers/audio/audio_filter_sw.h" - - - -int SpatialSoundServerSW::InternalAudioStream::get_channel_count() const { - - return AudioServer::get_singleton()->get_default_channel_count(); -} - -void SpatialSoundServerSW::InternalAudioStream::set_mix_rate(int p_rate) { - - -} - -void SpatialSoundServerSW::InternalAudioStream::update() { - - owner->_update_sources(); -} - -bool SpatialSoundServerSW::InternalAudioStream::mix(int32_t *p_buffer,int p_frames) { - - return owner->internal_buffer_mix(p_buffer,p_frames); -} - -void SpatialSoundServerSW::_update_sources() { - - _THREAD_SAFE_METHOD_ - for (Set<Source*>::Element *E=streaming_sources.front();E;E=E->next()) { - - Source *s=E->get(); - ERR_CONTINUE(!s->stream); - s->stream->update(); - } -} - - -SpatialSoundServerSW::Room::Room() { - -// params[ROOM_PARAM_SPEED_OF_SOUND]=343.0; - params[ROOM_PARAM_SPEED_OF_SOUND_SCALE]=1; - params[ROOM_PARAM_DOPPLER_FACTOR]=1.0; - params[ROOM_PARAM_PITCH_SCALE]=1.0; - params[ROOM_PARAM_VOLUME_SCALE_DB]=0; - params[ROOM_PARAM_REVERB_SEND]=0; - params[ROOM_PARAM_CHORUS_SEND]=0; - params[ROOM_PARAM_ATTENUATION_SCALE]=1.0; - params[ROOM_PARAM_ATTENUATION_HF_CUTOFF]=5000; - params[ROOM_PARAM_ATTENUATION_HF_FLOOR_DB]=-24.0; - params[ROOM_PARAM_ATTENUATION_HF_RATIO_EXP]=1.0; - params[ROOM_PARAM_ATTENUATION_REVERB_SCALE]=0.0; - override_other_sources=false; - reverb=ROOM_REVERB_HALL; - octree_id=0; - level=-1; - - -} - - -SpatialSoundServerSW::Source::Source() { - - params[SOURCE_PARAM_VOLUME_DB]=0.0; - params[SOURCE_PARAM_PITCH_SCALE]=1.0; - params[SOURCE_PARAM_ATTENUATION_MIN_DISTANCE]=1; - params[SOURCE_PARAM_ATTENUATION_MAX_DISTANCE]=100; - params[SOURCE_PARAM_ATTENUATION_DISTANCE_EXP]=1.0; //linear (and not really good) - params[SOURCE_PARAM_EMISSION_CONE_DEGREES]=180.0; //cone disabled - params[SOURCE_PARAM_EMISSION_CONE_ATTENUATION_DB]=-6.0; //minus 6 db attenuation - stream=NULL; - voices.resize(1); - last_voice=0; -} - -SpatialSoundServerSW::Source::Voice::Voice() { - - active=false; - restart=false; - pitch_scale=1.0; - volume_scale=0.0; - voice_rid=AudioServer::get_singleton()->voice_create(); - -} -SpatialSoundServerSW::Source::Voice::~Voice() { - - AudioServer::get_singleton()->free(voice_rid); -} - - -SpatialSoundServerSW::Listener::Listener() { - - params[LISTENER_PARAM_VOLUME_SCALE_DB]=0.0; - params[LISTENER_PARAM_PITCH_SCALE]=1.0; - params[LISTENER_PARAM_ATTENUATION_SCALE]=1.0; - params[LISTENER_PARAM_RECEPTION_CONE_DEGREES]=60.0; - params[LISTENER_PARAM_RECEPTION_CONE_ATTENUATION_DB]=-6; // minus six decibels - -} - -/* SPACE */ -RID SpatialSoundServerSW::space_create() { - - Space* space = memnew( Space ); - RID space_rid = space_owner.make_rid(space); - space->default_room=room_create(); - room_set_space(space->default_room,space_rid); - return space_rid; -} - -/* ROOM */ - -RID SpatialSoundServerSW::room_create() { - - Room *room = memnew( Room ); - return room_owner.make_rid(room); -} - -void SpatialSoundServerSW::room_set_space(RID p_room,RID p_space) { - - Room *room = room_owner.get(p_room); - ERR_FAIL_COND(!room); - - if (room->space.is_valid()) { - - Space *space = space_owner.get(room->space); - space->rooms.erase(p_room); - space->octree.erase(room->octree_id); - //room->octree_id=0; - } - - room->space=RID(); - - if (p_space.is_valid()) { - - Space *space = space_owner.get(p_space); - ERR_FAIL_COND(!space); - space->rooms.insert(p_room); - room->octree_id=space->octree.create(room,AABB()); - //set bounds - AABB aabb = room->bounds.is_empty()?AABB():room->bounds.get_aabb(); - space->octree.move(room->octree_id,room->transform.xform(aabb)); - room->space=p_space; - } - - -} - -RID SpatialSoundServerSW::room_get_space(RID p_room) const { - - Room *room = room_owner.get(p_room); - ERR_FAIL_COND_V(!room,RID()); - - - return room->space; -} - - - -void SpatialSoundServerSW::room_set_bounds(RID p_room, const BSP_Tree& p_bounds) { - - Room *room = room_owner.get(p_room); - ERR_FAIL_COND(!room); - - room->bounds=p_bounds; - - if (!room->space.is_valid()) - return; - - AABB aabb = room->bounds.is_empty()?AABB():room->bounds.get_aabb(); - Space* space = space_owner.get(room->space); - ERR_FAIL_COND(!space); - - space->octree.move(room->octree_id,room->transform.xform(aabb)); - -} -BSP_Tree SpatialSoundServerSW::room_get_bounds(RID p_room) const { - Room *room = room_owner.get(p_room); - ERR_FAIL_COND_V(!room,BSP_Tree()); - - return room->bounds; -} - -void SpatialSoundServerSW::room_set_transform(RID p_room, const Transform& p_transform) { - - if (space_owner.owns(p_room)) - p_room=space_owner.get(p_room)->default_room; - - Room *room = room_owner.get(p_room); - ERR_FAIL_COND(!room); - room->transform=p_transform; - room->inverse_transform=p_transform.affine_inverse(); // needs to be done to unscale BSP properly - - if (!room->space.is_valid()) - return; - - if (!room->bounds.is_empty()) { - - Space* space = space_owner.get(room->space); - ERR_FAIL_COND(!space); - - space->octree.move(room->octree_id,room->transform.xform(room->bounds.get_aabb())); - } -} - -Transform SpatialSoundServerSW::room_get_transform(RID p_room) const { - - if (space_owner.owns(p_room)) - p_room=space_owner.get(p_room)->default_room; - - Room *room = room_owner.get(p_room); - ERR_FAIL_COND_V(!room,Transform()); - return room->transform; -} - - -void SpatialSoundServerSW::room_set_param(RID p_room, RoomParam p_param, float p_value) { - - if (space_owner.owns(p_room)) - p_room=space_owner.get(p_room)->default_room; - - ERR_FAIL_INDEX(p_param,ROOM_PARAM_MAX); - Room *room = room_owner.get(p_room); - ERR_FAIL_COND(!room); - room->params[p_param]=p_value; - -} -float SpatialSoundServerSW::room_get_param(RID p_room, RoomParam p_param) const { - - if (space_owner.owns(p_room)) - p_room=space_owner.get(p_room)->default_room; - - ERR_FAIL_INDEX_V(p_param,ROOM_PARAM_MAX,0); - Room *room = room_owner.get(p_room); - ERR_FAIL_COND_V(!room,0); - return room->params[p_param]; -} - -void SpatialSoundServerSW::room_set_level(RID p_room, int p_level) { - - Room *room = room_owner.get(p_room); - ERR_FAIL_COND(!room); - room->level =p_level; - -} - -int SpatialSoundServerSW::room_get_level(RID p_room) const { - - Room *room = room_owner.get(p_room); - ERR_FAIL_COND_V(!room,0); - return room->level; - -} - - -void SpatialSoundServerSW::room_set_reverb(RID p_room, RoomReverb p_reverb) { - - if (space_owner.owns(p_room)) - p_room=space_owner.get(p_room)->default_room; - - Room *room = room_owner.get(p_room); - ERR_FAIL_COND(!room); - room->reverb=p_reverb; - -} -SpatialSoundServerSW::RoomReverb SpatialSoundServerSW::room_get_reverb(RID p_room) const { - - if (space_owner.owns(p_room)) - p_room=space_owner.get(p_room)->default_room; - - Room *room = room_owner.get(p_room); - ERR_FAIL_COND_V(!room,ROOM_REVERB_SMALL); - return room->reverb; -} - -//useful for underwater or rooms with very strange conditions -void SpatialSoundServerSW::room_set_force_params_to_all_sources(RID p_room, bool p_force) { - - if (space_owner.owns(p_room)) - p_room=space_owner.get(p_room)->default_room; - - Room *room = room_owner.get(p_room); - ERR_FAIL_COND(!room); - room->override_other_sources=p_force; - -} -bool SpatialSoundServerSW::room_is_forcing_params_to_all_sources(RID p_room) const { - - if (space_owner.owns(p_room)) - p_room=space_owner.get(p_room)->default_room; - - Room *room = room_owner.get(p_room); - ERR_FAIL_COND_V(!room,false); - return room->override_other_sources; -} - -/* SOURCE */ - -RID SpatialSoundServerSW::source_create(RID p_space) { - - Space *space = space_owner.get(p_space); - ERR_FAIL_COND_V(!space,RID()); - - Source *source = memnew( Source ); - source->space=p_space; - RID source_rid = source_owner.make_rid(source); - space->sources.insert(source_rid); - - return source_rid; -} - - -void SpatialSoundServerSW::source_set_polyphony(RID p_source,int p_voice_count) { - - - ERR_FAIL_COND(p_voice_count<=0); // more than 32 is too much, change this if you really need more - if (p_voice_count>32) { - - ERR_PRINT("Voices will be clipped to 32"); - p_voice_count=32; - } - Source *source = source_owner.get(p_source); - ERR_FAIL_COND(!source); - - if (p_voice_count<source->voices.size()) { - - for(int i=p_voice_count;i<source->voices.size();i++) { - active_voices.erase(ActiveVoice(source,i)); //erase from active voices - } - } - source->voices.resize(p_voice_count); - -} - -int SpatialSoundServerSW::source_get_polyphony(RID p_source) const { - - Source *source = source_owner.get(p_source); - ERR_FAIL_COND_V(!source,-1); - return source->voices.size(); - -} - -void SpatialSoundServerSW::source_set_transform(RID p_source, const Transform& p_transform) { - - Source *source = source_owner.get(p_source); - ERR_FAIL_COND(!source); - source->transform=p_transform; - source->transform.orthonormalize(); -} -Transform SpatialSoundServerSW::source_get_transform(RID p_source) const { - - Source *source = source_owner.get(p_source); - ERR_FAIL_COND_V(!source,Transform()); - return source->transform; -} - -void SpatialSoundServerSW::source_set_param(RID p_source, SourceParam p_param, float p_value) { - - ERR_FAIL_INDEX(p_param,SOURCE_PARAM_MAX); - Source *source = source_owner.get(p_source); - ERR_FAIL_COND(!source); - source->params[p_param]=p_value; - -} -float SpatialSoundServerSW::source_get_param(RID p_source, SourceParam p_param) const { - ERR_FAIL_INDEX_V(p_param,SOURCE_PARAM_MAX,0); - Source *source = source_owner.get(p_source); - ERR_FAIL_COND_V(!source,0); - return source->params[p_param]; - - -} - -void SpatialSoundServerSW::source_set_audio_stream(RID p_source, AudioServer::AudioStream *p_stream) { - - Source *source = source_owner.get(p_source); - ERR_FAIL_COND(!source); - AudioServer::get_singleton()->lock(); - source->stream=p_stream; - _THREAD_SAFE_METHOD_ - - if (!p_stream) { - streaming_sources.erase(source); - active_voices.erase(ActiveVoice(source,VOICE_IS_STREAM)); - } else { - streaming_sources.insert(source); - active_voices.insert(ActiveVoice(source,VOICE_IS_STREAM)); - zeromem(source->stream_data.filter_state,sizeof(Source::StreamData::FilterState)*4); //reset filter for safetyness - p_stream->set_mix_rate(AudioServer::get_singleton()->get_default_mix_rate()); - } - - AudioServer::get_singleton()->unlock(); - -} //null to unset - -SpatialSoundServer::SourceVoiceID SpatialSoundServerSW::source_play_sample(RID p_source, RID p_sample, int p_mix_rate, int p_voice) { - - Source *source = source_owner.get(p_source); - ERR_FAIL_COND_V(!source,SOURCE_INVALID_VOICE); - - int to_play=0; - - if (p_voice==SOURCE_NEXT_VOICE) { - to_play=source->last_voice+1; - if (to_play>=source->voices.size()) - to_play=0; - - } else - to_play=p_voice; - - ERR_FAIL_INDEX_V(to_play,source->voices.size(),SOURCE_INVALID_VOICE); - - source->voices[to_play].restart=true; - source->voices[to_play].sample_rid=p_sample; - source->voices[to_play].sample_mix_rate=p_mix_rate; - source->voices[to_play].pitch_scale=1; - source->voices[to_play].volume_scale=0; - source->last_voice=to_play; - active_voices.insert(ActiveVoice(source,to_play)); - return to_play; -} - -/* VOICES */ -void SpatialSoundServerSW::source_voice_set_pitch_scale(RID p_source, SourceVoiceID p_voice, float p_pitch_scale) { - - Source *source = source_owner.get(p_source); - ERR_FAIL_COND(!source); - ERR_FAIL_INDEX(p_voice,source->voices.size()); - source->voices[p_voice].pitch_scale=p_pitch_scale; - -} -void SpatialSoundServerSW::source_voice_set_volume_scale_db(RID p_source, SourceVoiceID p_voice, float p_db) { - - Source *source = source_owner.get(p_source); - ERR_FAIL_COND(!source); - ERR_FAIL_INDEX(p_voice,source->voices.size()); - source->voices[p_voice].volume_scale=p_db; - -} - -bool SpatialSoundServerSW::source_is_voice_active(RID p_source, SourceVoiceID p_voice) const { - - Source *source = source_owner.get(p_source); - ERR_FAIL_COND_V(!source,false); - ERR_FAIL_INDEX_V(p_voice,source->voices.size(),false); - return source->voices[p_voice].active || source->voices[p_voice].restart; - -} -void SpatialSoundServerSW::source_stop_voice(RID p_source, SourceVoiceID p_voice) { - - Source *source = source_owner.get(p_source); - ERR_FAIL_COND(!source); - ERR_FAIL_INDEX(p_voice,source->voices.size()); - if (source->voices[p_voice].active) { - AudioServer::get_singleton()->voice_stop(source->voices[p_voice].voice_rid); - } - source->voices[p_voice].active=false; - source->voices[p_voice].restart=false; - active_voices.erase(ActiveVoice(source,p_voice)); -} - -/* LISTENER */ - -RID SpatialSoundServerSW::listener_create() { - - Listener *listener = memnew( Listener ); - RID listener_rid = listener_owner.make_rid(listener); - return listener_rid; - -} - -void SpatialSoundServerSW::listener_set_space(RID p_listener,RID p_space) { - - Listener *listener = listener_owner.get(p_listener); - ERR_FAIL_COND(!listener); - - if (listener->space.is_valid()) { - - Space *lspace = space_owner.get(listener->space); - ERR_FAIL_COND(!lspace); - lspace->listeners.erase(p_listener); - } - - listener->space=RID(); - - if (p_space.is_valid()) { - Space *space = space_owner.get(p_space); - ERR_FAIL_COND(!space); - - listener->space=p_space; - space->listeners.insert(p_listener); - } - -} - -void SpatialSoundServerSW::listener_set_transform(RID p_listener, const Transform& p_transform) { - - Listener *listener = listener_owner.get(p_listener); - ERR_FAIL_COND(!listener); - listener->transform=p_transform; - listener->transform.orthonormalize(); //must be done.. -} -Transform SpatialSoundServerSW::listener_get_transform(RID p_listener) const { - - Listener *listener = listener_owner.get(p_listener); - ERR_FAIL_COND_V(!listener,Transform()); - return listener->transform; -} - -void SpatialSoundServerSW::listener_set_param(RID p_listener, ListenerParam p_param, float p_value) { - - ERR_FAIL_INDEX(p_param,LISTENER_PARAM_MAX); - Listener *listener = listener_owner.get(p_listener); - ERR_FAIL_COND(!listener); - listener->params[p_param]=p_value; -} - -float SpatialSoundServerSW::listener_get_param(RID p_listener, ListenerParam p_param) const { - - ERR_FAIL_INDEX_V(p_param,LISTENER_PARAM_MAX,0); - Listener *listener = listener_owner.get(p_listener); - ERR_FAIL_COND_V(!listener,0); - return listener->params[p_param]; -} - - -/* MISC */ - -void SpatialSoundServerSW::free(RID p_id) { - - - if (space_owner.owns(p_id)) { - - Space *space = space_owner.get(p_id); - free(space->default_room); - - while(space->listeners.size()) { - listener_set_space(space->listeners.front()->get(),RID()); - } - while(space->sources.size()) { - free(space->sources.front()->get()); - } - while(space->rooms.size()) { - room_set_space(space->rooms.front()->get(),RID()); - } - space_owner.free(p_id); - memdelete(space); - - } else if (source_owner.owns(p_id)) { - - Source *source = source_owner.get(p_id); - if (source->stream) - source_set_audio_stream(p_id,NULL); - - Space *space = space_owner.get(source->space); - ERR_FAIL_COND(!space); - space->sources.erase(p_id); - for(int i=0;i<source->voices.size();i++) { - active_voices.erase(ActiveVoice(source,i)); - } - source_owner.free(p_id); - memdelete(source); - } else if (listener_owner.owns(p_id)) { - - Listener *listener = listener_owner.get(p_id); - if (listener->space.is_valid()) { - Space *space = space_owner.get(listener->space); - ERR_FAIL_COND(!space); - space->listeners.erase(p_id); - } - listener_owner.free(p_id); - memdelete(listener); - - } else if (room_owner.owns(p_id)) { - - Room *room = room_owner.get(p_id); - - if (room->space.is_valid()) { - Space *space = space_owner.get(room->space); - ERR_FAIL_COND(!space); - space->octree.erase(room->octree_id); - space->rooms.erase(p_id); - } - room_owner.free(p_id); - memdelete(room); - } else { - ERR_PRINT("Attempt to free invalid ID") ; - } - -} - -void SpatialSoundServerSW::_clean_up_owner(RID_OwnerBase *p_owner, const char *p_area) { - - List<RID> rids; - p_owner->get_owned_list(&rids); - - for(List<RID>::Element *I=rids.front();I;I=I->next()) { - if (OS::get_singleton()->is_stdout_verbose()) { - - print_line("Leaked RID ("+itos(I->get().get_id())+") of type "+String(p_area)); - } - free(I->get()); - } -} - -void SpatialSoundServerSW::init() { - - internal_buffer = memnew_arr(int32_t, INTERNAL_BUFFER_SIZE*INTERNAL_BUFFER_MAX_CHANNELS); - internal_buffer_channels=AudioServer::get_singleton()->get_default_channel_count(); - - internal_audio_stream = memnew( InternalAudioStream ); - internal_audio_stream->owner=this; - internal_audio_stream_rid = AudioServer::get_singleton()->audio_stream_create(internal_audio_stream); - - AudioServer::get_singleton()->stream_set_active(internal_audio_stream_rid,true); - -} - - - -static float _get_attenuation(float cosine, float angle, float attenuation) { - - - float listener_ang = Math::rad2deg(Math::acos(cosine))-angle; - - if (listener_ang>0 && angle<180.0) { - listener_ang/=(180.0-angle); - return Math::db2linear(Math::sin(listener_ang*(Math_PI/2.0))*attenuation); - } - return 1.0; -} - - -bool SpatialSoundServerSW::internal_buffer_mix(int32_t *p_buffer,int p_frames) { - - if (streaming_sources.size()==0) - return false; //nothing to mix - - - for (Set<Source*>::Element *E=streaming_sources.front();E;E=E->next()) { - - Source *s=E->get(); - ERR_CONTINUE(!s->stream); - - int channels = s->stream->get_channel_count(); - Source::StreamData &sd=s->stream_data; - - int todo=p_frames; - - AudioFilterSW filter; - filter.set_sampling_rate(AudioServer::get_singleton()->get_default_mix_rate()); - filter.set_cutoff(sd.filter_cutoff); - filter.set_gain(sd.filter_gain); - filter.set_resonance(1); - filter.set_mode(AudioFilterSW::HIGHSHELF); - filter.set_stages(1); - AudioFilterSW::Coeffs coefs; - filter.prepare_coefficients(&coefs); - - int32_t in[4]; -#ifndef SPATIAL_SOUND_SERVER_NO_FILTER -#define DO_FILTER(m_c)\ - {\ - float val = in[m_c];\ - float pre=val;\ - val = val*coefs.b0 + sd.filter_state[m_c].hb[0]*coefs.b1 + sd.filter_state[m_c].hb[1]*coefs.b2 + sd.filter_state[m_c].ha[0]*coefs.a1 + sd.filter_state[m_c].ha[1]*coefs.a2;\ - sd.filter_state[m_c].ha[1]=sd.filter_state[m_c].ha[0];\ - sd.filter_state[m_c].hb[1]=sd.filter_state[m_c].hb[0]; \ - sd.filter_state[m_c].hb[0]=pre;\ - sd.filter_state[m_c].ha[0]=val;\ - in[m_c]=Math::fast_ftoi(val);\ - } -#else -#define DO_FILTER(m_c) -#endif - - while(todo) { - - int to_mix=MIN(todo,INTERNAL_BUFFER_SIZE); - - s->stream->mix(internal_buffer,to_mix); - - switch(internal_buffer_channels) { - - case 2: { - - float p = sd.panning.x*0.5+0.5; - float panf[2]={ (1.0-p),p }; - panf[0]*=sd.volume; - panf[1]*=sd.volume; - - int32_t pan[2]={Math::fast_ftoi(panf[0]*(1<<16)),Math::fast_ftoi(panf[1]*(1<<16))}; - - switch(channels) { - case 1: { - - for(int i=0;i<to_mix;i++) { - - in[0]=internal_buffer[i]; - in[1]=internal_buffer[i]; - DO_FILTER(0); - DO_FILTER(1); - p_buffer[(i<<1)+0]=((in[0]>>16)*pan[0]); - p_buffer[(i<<1)+1]=((in[1]>>16)*pan[1]); - } - } break; - case 2: { - - for(int i=0;i<to_mix;i++) { - - in[0]=internal_buffer[(i<<1)+0]; - in[1]=internal_buffer[(i<<1)+1]; - DO_FILTER(0); - DO_FILTER(1); - p_buffer[(i<<1)+0]=((in[0]>>16)*pan[0]); - p_buffer[(i<<1)+1]=((in[1]>>16)*pan[1]); - } - } break; - case 4: { - - for(int i=0;i<to_mix;i++) { - - in[0]=(internal_buffer[(i<<2)+0]+internal_buffer[(i<<2)+2])>>1; - in[1]=(internal_buffer[(i<<2)+1]+internal_buffer[(i<<2)+3])>>1; - DO_FILTER(0); - DO_FILTER(1); - p_buffer[(i<<1)+0]=((in[0]>>16)*pan[0]); - p_buffer[(i<<1)+1]=((in[1]>>16)*pan[1]); - } - } break; - - } break; - - } break; - case 4: { - - float xp = sd.panning.x*0.5+0.5; - float yp = sd.panning.y*0.5+0.5; - float panf[4]={ (1.0-xp)*(1.0-yp),(xp)*(1.0-yp),(1.0-xp)*(yp),(xp)*(yp) }; - panf[0]*=sd.volume; - panf[1]*=sd.volume; - panf[2]*=sd.volume; - panf[3]*=sd.volume; - - int32_t pan[4]={ - Math::fast_ftoi(panf[0]*(1<<16)), - Math::fast_ftoi(panf[1]*(1<<16)), - Math::fast_ftoi(panf[2]*(1<<16)), - Math::fast_ftoi(panf[3]*(1<<16))}; - - switch(channels) { - case 1: { - - for(int i=0;i<to_mix;i++) { - - in[0]=internal_buffer[i]; - in[1]=internal_buffer[i]; - in[2]=internal_buffer[i]; - in[3]=internal_buffer[i]; - DO_FILTER(0); - DO_FILTER(1); - DO_FILTER(2); - DO_FILTER(3); - p_buffer[(i<<2)+0]=((in[0]>>16)*pan[0]); - p_buffer[(i<<2)+1]=((in[1]>>16)*pan[1]); - p_buffer[(i<<2)+2]=((in[2]>>16)*pan[2]); - p_buffer[(i<<2)+3]=((in[3]>>16)*pan[3]); - } - } break; - case 2: { - - for(int i=0;i<to_mix;i++) { - - in[0]=internal_buffer[(i<<1)+0]; - in[1]=internal_buffer[(i<<1)+1]; - in[2]=internal_buffer[(i<<1)+0]; - in[3]=internal_buffer[(i<<1)+1]; - DO_FILTER(0); - DO_FILTER(1); - DO_FILTER(2); - DO_FILTER(3); - p_buffer[(i<<2)+0]=((in[0]>>16)*pan[0]); - p_buffer[(i<<2)+1]=((in[1]>>16)*pan[1]); - p_buffer[(i<<2)+2]=((in[2]>>16)*pan[2]); - p_buffer[(i<<2)+3]=((in[3]>>16)*pan[3]); - } - } break; - case 4: { - - for(int i=0;i<to_mix;i++) { - - in[0]=internal_buffer[(i<<2)+0]; - in[1]=internal_buffer[(i<<2)+1]; - in[2]=internal_buffer[(i<<2)+2]; - in[3]=internal_buffer[(i<<2)+3]; - DO_FILTER(0); - DO_FILTER(1); - DO_FILTER(2); - DO_FILTER(3); - p_buffer[(i<<2)+0]=((in[0]>>16)*pan[0]); - p_buffer[(i<<2)+1]=((in[1]>>16)*pan[1]); - p_buffer[(i<<2)+2]=((in[2]>>16)*pan[2]); - p_buffer[(i<<2)+3]=((in[3]>>16)*pan[3]); - } - } break; - - } break; - - } break; - case 6: { - - - } break; - } - p_buffer+=to_mix*internal_buffer_channels; - todo-=to_mix; - - } - - } - - return true; -} - -void SpatialSoundServerSW::update(float p_delta) { - - List<ActiveVoice> to_disable; - - - for(Set<ActiveVoice>::Element *E=active_voices.front();E;E=E->next()) { - - Source *source = E->get().source; - int voice = E->get().voice; - - if (voice!=VOICE_IS_STREAM) { - Source::Voice &v=source->voices[voice]; - ERR_CONTINUE(!v.active && !v.restart); // likely a bug... - } - - //this could be optimized at some point... am not sure - Space *space=space_owner.get(source->space); - Room *room=room_owner.get(space->default_room); - int max_level=-0x80000000; - int rooms_culled = space->octree.cull_point(source->transform.origin,cull_rooms,MAX_CULL_ROOMS); - for(int i=0;i<rooms_culled;i++) { - - Room *r=cull_rooms[i]; - ERR_CONTINUE( r->bounds.is_empty() ); // how did this happen?? - if (r->level<=max_level) //ignore optimization (level too low) - continue; - Vector3 local_point = r->inverse_transform.xform(source->transform.origin); - if (!r->bounds.point_is_inside(local_point)) - continue; - room=r; - max_level=r->level; - - } - - - //compute mixing weights (support for multiple listeners in the same output) - float total_distance=0; - for(Set<RID>::Element *L=space->listeners.front();L;L=L->next()) { - Listener *listener=listener_owner.get(L->get()); - total_distance+=listener->transform.origin.distance_to(source->transform.origin); - } - - //compute spatialization variables, weighted according to distance - float volume_attenuation = 0.0; - float air_absorption_hf_cutoff = 0.0; - float air_absorption = 0.0; - float pitch_scale=1.0; - Vector3 panning; - - - //print_line("listeners: "+itos(space->listeners.size())); - - - for(Set<RID>::Element *L=space->listeners.front();L;L=L->next()) { - - Listener *listener=listener_owner.get(L->get()); - - Vector3 rel_vector = listener->transform.xform_inv(source->transform.origin); - Vector3 source_rel_vector = source->transform.xform_inv(listener->transform.origin).normalized(); - float distance=rel_vector.length(); - float weight = distance/total_distance; - float pscale=1.0; - - float distance_scale=listener->params[LISTENER_PARAM_ATTENUATION_SCALE]*room->params[ROOM_PARAM_ATTENUATION_SCALE]; - float distance_min=source->params[SOURCE_PARAM_ATTENUATION_MIN_DISTANCE]*distance_scale; - float distance_max=source->params[SOURCE_PARAM_ATTENUATION_MAX_DISTANCE]*distance_scale; - float attenuation_exp=source->params[SOURCE_PARAM_ATTENUATION_DISTANCE_EXP]; - float attenuation=1; - - //print_line("DIST MIN: "+rtos(distance_min)); - //print_line("DIST MAX: "+rtos(distance_max)); - if (distance_max>0) { - distance = CLAMP(distance,distance_min,distance_max); - attenuation = Math::pow(1.0 - ((distance - distance_min)/(distance_max-distance_min)),CLAMP(attenuation_exp,0.001,16)); - } - - float hf_attenuation_cutoff = room->params[ROOM_PARAM_ATTENUATION_HF_CUTOFF]; - float hf_attenuation_exp = room->params[ROOM_PARAM_ATTENUATION_HF_RATIO_EXP]; - float hf_attenuation_floor = room->params[ROOM_PARAM_ATTENUATION_HF_FLOOR_DB]; - float absorption=Math::db2linear(Math::lerp(hf_attenuation_floor,0,Math::pow(attenuation,hf_attenuation_exp))); - - // source emission cone - - float emission_deg=source->params[SOURCE_PARAM_EMISSION_CONE_DEGREES]; - float emission_attdb=source->params[SOURCE_PARAM_EMISSION_CONE_ATTENUATION_DB]; - absorption*=_get_attenuation(source_rel_vector.dot(Vector3(0,0,-1)),emission_deg,emission_attdb); - - Vector3 vpanning=rel_vector.normalized(); - - //listener stuff - - { - - // head cone - - float reception_deg=listener->params[LISTENER_PARAM_RECEPTION_CONE_DEGREES]; - float reception_attdb=listener->params[LISTENER_PARAM_RECEPTION_CONE_ATTENUATION_DB]; - - absorption*=_get_attenuation(vpanning.dot(Vector3(0,0,-1)),reception_deg,reception_attdb); - - // scale - - attenuation*=Math::db2linear(listener->params[LISTENER_PARAM_VOLUME_SCALE_DB]); - pscale*=Math::db2linear(listener->params[LISTENER_PARAM_PITCH_SCALE]); - - - } - - - - - //add values - - volume_attenuation+=weight*attenuation; // plus other stuff i guess - air_absorption+=weight*absorption; - air_absorption_hf_cutoff+=weight*hf_attenuation_cutoff; - panning+=vpanning*weight; - //pitch_scale+=pscale*weight; - - } - - RoomReverb reverb_room; - float reverb_send; - - /* APPLY ROOM SETTINGS */ - - { - pitch_scale*=room->params[ROOM_PARAM_PITCH_SCALE]; - volume_attenuation*=Math::db2linear(room->params[ROOM_PARAM_VOLUME_SCALE_DB]); - reverb_room=room->reverb; - reverb_send=Math::lerp(1.0,volume_attenuation,room->params[ROOM_PARAM_ATTENUATION_REVERB_SCALE])*room->params[ROOM_PARAM_REVERB_SEND]; - - } - - /* UPDATE VOICE & STREAM */ - - - - if (voice==VOICE_IS_STREAM) { - - //update voice!! - source->stream_data.panning=panning; - source->stream_data.volume=volume_attenuation*Math::db2linear(source->params[SOURCE_PARAM_VOLUME_DB]); - source->stream_data.reverb=reverb_room; - source->stream_data.reverb_send=reverb_send; - source->stream_data.filter_gain=air_absorption; - source->stream_data.filter_cutoff=air_absorption_hf_cutoff; - - if (!source->stream) //stream is gone bye bye - to_disable.push_back(ActiveVoice(source,voice)); // oh well.. - - } else if (voice>=0) { - //update stream!! - Source::Voice &v=source->voices[voice]; - - if (v.restart) - AudioServer::get_singleton()->voice_play(v.voice_rid,v.sample_rid); - - float volume_scale = Math::db2linear(v.volume_scale)*Math::db2linear(source->params[SOURCE_PARAM_VOLUME_DB]); - float volume = volume_attenuation*volume_scale; - reverb_send*=volume_scale; - int mix_rate = v.sample_mix_rate*v.pitch_scale*pitch_scale*source->params[SOURCE_PARAM_PITCH_SCALE]; - - - if (mix_rate<=0) { - ERR_PRINT("Invalid mix rate for voice (0) check for invalid pitch_scale param."); - to_disable.push_back(ActiveVoice(source,voice)); // oh well.. - continue; //invalid mix rate, disabling - } - if (v.restart || v.last_volume!=volume) - AudioServer::get_singleton()->voice_set_volume(v.voice_rid,volume); - if (v.restart || v.last_mix_rate!=mix_rate) - AudioServer::get_singleton()->voice_set_mix_rate(v.voice_rid,mix_rate); - if (v.restart || v.last_filter_gain!=air_absorption || v.last_filter_cutoff!=air_absorption_hf_cutoff) - AudioServer::get_singleton()->voice_set_filter(v.voice_rid,AudioServer::FILTER_HIGH_SHELF,air_absorption_hf_cutoff,1.0,air_absorption); - if (v.restart || v.last_panning!=panning) - AudioServer::get_singleton()->voice_set_pan(v.voice_rid,panning.x,panning.y,panning.z); - if (v.restart || v.last_reverb_room!=reverb_room || v.last_reverb_send!=reverb_send) - AudioServer::get_singleton()->voice_set_reverb(v.voice_rid,AudioServer::ReverbRoomType(reverb_room),reverb_send); - - v.last_volume=volume; - v.last_mix_rate=mix_rate; - v.last_filter_gain=air_absorption; - v.last_filter_cutoff=air_absorption_hf_cutoff; - v.last_panning=panning; - v.restart=false; - v.active=true; - - if (!AudioServer::get_singleton()->voice_is_active(v.voice_rid)) - to_disable.push_back(ActiveVoice(source,voice)); // oh well.. - } - } - - while(to_disable.size()) { - - ActiveVoice av = to_disable.front()->get(); - av.source->voices[av.voice].active=false; - av.source->voices[av.voice].restart=false; - active_voices.erase(av); - to_disable.pop_front(); - } - -} -void SpatialSoundServerSW::finish() { - - AudioServer::get_singleton()->free(internal_audio_stream_rid); - memdelete(internal_audio_stream); - - _clean_up_owner(&source_owner,"Source"); - _clean_up_owner(&listener_owner,"Listener"); - _clean_up_owner(&room_owner,"Room"); - _clean_up_owner(&space_owner,"Space"); - - memdelete_arr(internal_buffer); -} - -SpatialSoundServerSW::SpatialSoundServerSW() { - -} diff --git a/servers/spatial_sound/spatial_sound_server_sw.h b/servers/spatial_sound/spatial_sound_server_sw.h deleted file mode 100644 index b4295bf145..0000000000 --- a/servers/spatial_sound/spatial_sound_server_sw.h +++ /dev/null @@ -1,266 +0,0 @@ -/*************************************************************************/ -/* spatial_sound_server_sw.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#ifndef SPATIAL_SOUND_SERVER_SW_H -#define SPATIAL_SOUND_SERVER_SW_H - -#include "servers/spatial_sound_server.h" -#include "octree.h" -#include "os/thread_safe.h" - - -class SpatialSoundServerSW : public SpatialSoundServer { - - OBJ_TYPE(SpatialSoundServerSW,SpatialSoundServer); - - _THREAD_SAFE_CLASS_ - - enum { - MAX_CULL_ROOMS=128, - INTERNAL_BUFFER_SIZE=4096, - INTERNAL_BUFFER_MAX_CHANNELS=4, - VOICE_IS_STREAM=-1 - - }; - - - struct InternalAudioStream : public AudioServer::AudioStream { - - ::SpatialSoundServerSW *owner; - virtual int get_channel_count() const; - virtual void set_mix_rate(int p_rate); //notify the stream of the mix rate - virtual bool mix(int32_t *p_buffer,int p_frames); - virtual void update(); - }; - - InternalAudioStream *internal_audio_stream; - RID internal_audio_stream_rid; - int32_t *internal_buffer; - int internal_buffer_channels; - - bool internal_buffer_mix(int32_t *p_buffer,int p_frames); - - struct Room; - - struct Space { - - RID default_room; - Set<RID> rooms; - Set<RID> sources; - Set<RID> listeners; - - Octree<Room> octree; - }; - - mutable RID_Owner<Space> space_owner; - - struct Room { - RID space; - Transform transform; - Transform inverse_transform; - BSP_Tree bounds; - RoomReverb reverb; - float params[ROOM_PARAM_MAX]; - bool override_other_sources; - OctreeElementID octree_id; - int level; - - Room(); - }; - - mutable RID_Owner<Room> room_owner; - - - - struct Source { - - struct Voice { - - RID voice_rid; - RID sample_rid; - bool active; - bool restart; - float pitch_scale; - float volume_scale; - int sample_mix_rate; - - - float last_volume; - float last_filter_gain; - float last_filter_cutoff; - Vector3 last_panning; - int last_mix_rate; - RoomReverb last_reverb_room; - float last_reverb_send; - - Voice(); - ~Voice(); - }; - - struct StreamData { - - - Vector3 panning; - RoomReverb reverb; - float reverb_send; - float volume; - float filter_gain; - float filter_cutoff; - - struct FilterState { - - float ha[2]; - float hb[2]; - } filter_state[4]; - - StreamData() { - - reverb_send=0; - reverb=ROOM_REVERB_HALL; - volume=1.0; - filter_gain=1; - filter_cutoff=5000; - - } - } stream_data; - - RID space; - Transform transform; - float params[SOURCE_PARAM_MAX]; - AudioServer::AudioStream *stream; - Vector<Voice> voices; - int last_voice; - - Source(); - }; - - mutable RID_Owner<Source> source_owner; - - struct Listener { - - RID space; - Transform transform; - float params[LISTENER_PARAM_MAX]; - - Listener(); - }; - - mutable RID_Owner<Listener> listener_owner; - - struct ActiveVoice { - - Source *source; - int voice; - bool operator<(const ActiveVoice& p_voice) const { return (voice==p_voice.voice)?(source<p_voice.source):(voice<p_voice.voice); } - ActiveVoice(Source *p_source=NULL,int p_voice=0) { source=p_source; voice=p_voice; } - }; - - Room *cull_rooms[MAX_CULL_ROOMS]; - - Set<Source*> streaming_sources; - Set<ActiveVoice> active_voices; - - void _clean_up_owner(RID_OwnerBase *p_owner, const char *p_area); - void _update_sources(); - -public: - - /* SPACE */ - virtual RID space_create(); - - /* ROOM */ - - virtual RID room_create(); - virtual void room_set_space(RID p_room,RID p_space); - virtual RID room_get_space(RID p_room) const; - - virtual void room_set_bounds(RID p_room, const BSP_Tree& p_bounds); - virtual BSP_Tree room_get_bounds(RID p_room) const; - virtual void room_set_transform(RID p_room, const Transform& p_transform); - virtual Transform room_get_transform(RID p_room) const; - - - virtual void room_set_param(RID p_room, RoomParam p_param, float p_value); - virtual float room_get_param(RID p_room, RoomParam p_param) const; - - virtual void room_set_level(RID p_room, int p_level); - virtual int room_get_level(RID p_room) const; - - virtual void room_set_reverb(RID p_room, RoomReverb p_reverb); - virtual RoomReverb room_get_reverb(RID p_room) const; - - //useful for underwater or rooms with very strange conditions - virtual void room_set_force_params_to_all_sources(RID p_room, bool p_force); - virtual bool room_is_forcing_params_to_all_sources(RID p_room) const; - - /* SOURCE */ - - virtual RID source_create(RID p_space); - - virtual void source_set_polyphony(RID p_source,int p_voice_count); - virtual int source_get_polyphony(RID p_source) const; - - virtual void source_set_transform(RID p_source, const Transform& p_transform); - virtual Transform source_get_transform(RID p_source) const; - - virtual void source_set_param(RID p_source, SourceParam p_param, float p_value); - virtual float source_get_param(RID p_source, SourceParam p_param) const; - - virtual void source_set_audio_stream(RID p_source, AudioServer::AudioStream *p_stream); //null to unset - virtual SourceVoiceID source_play_sample(RID p_source, RID p_sample, int p_mix_rate, int p_voice=SOURCE_NEXT_VOICE); - /* VOICES */ - virtual void source_voice_set_pitch_scale(RID p_source, SourceVoiceID p_voice, float p_pitch_scale); - virtual void source_voice_set_volume_scale_db(RID p_source, SourceVoiceID p_voice, float p_volume); - - virtual bool source_is_voice_active(RID p_source, SourceVoiceID p_voice) const; - virtual void source_stop_voice(RID p_source, SourceVoiceID p_voice); - - /* LISTENER */ - - virtual RID listener_create(); - virtual void listener_set_space(RID p_listener, RID p_space); - - virtual void listener_set_transform(RID p_listener, const Transform& p_transform); - virtual Transform listener_get_transform(RID p_listener) const; - - virtual void listener_set_param(RID p_listener, ListenerParam p_param, float p_value); - virtual float listener_get_param(RID p_listener, ListenerParam p_param) const; - - - /* MISC */ - - virtual void free(RID p_id); - - virtual void init(); - virtual void update(float p_delta); - virtual void finish(); - - SpatialSoundServerSW(); -}; - -#endif // SPATIAL_SOUND_SERVER_SW_H diff --git a/servers/spatial_sound_2d/SCsub b/servers/spatial_sound_2d/SCsub deleted file mode 100644 index d31af2c1c4..0000000000 --- a/servers/spatial_sound_2d/SCsub +++ /dev/null @@ -1,5 +0,0 @@ -Import('env') - -env.add_source_files(env.servers_sources,"*.cpp") - -Export('env') diff --git a/servers/spatial_sound_2d/spatial_sound_2d_server_sw.cpp b/servers/spatial_sound_2d/spatial_sound_2d_server_sw.cpp deleted file mode 100644 index 6c42c2f527..0000000000 --- a/servers/spatial_sound_2d/spatial_sound_2d_server_sw.cpp +++ /dev/null @@ -1,1042 +0,0 @@ -/*************************************************************************/ -/* spatial_sound_2d_server_sw.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "spatial_sound_2d_server_sw.h" - -#include "os/os.h" -#include "servers/audio/audio_filter_sw.h" - - - -int SpatialSound2DServerSW::InternalAudioStream::get_channel_count() const { - - return AudioServer::get_singleton()->get_default_channel_count(); -} - -void SpatialSound2DServerSW::InternalAudioStream::set_mix_rate(int p_rate) { - - -} - -void SpatialSound2DServerSW::InternalAudioStream::update() { - - owner->_update_sources(); -} - -bool SpatialSound2DServerSW::InternalAudioStream::mix(int32_t *p_buffer,int p_frames) { - - return owner->internal_buffer_mix(p_buffer,p_frames); -} - -void SpatialSound2DServerSW::_update_sources() { - - _THREAD_SAFE_METHOD_ - for (Set<Source*>::Element *E=streaming_sources.front();E;E=E->next()) { - - Source *s=E->get(); - ERR_CONTINUE(!s->stream); - s->stream->update(); - } -} - - -SpatialSound2DServerSW::Room::Room() { - -// params[ROOM_PARAM_SPEED_OF_SOUND]=343.0; - params[ROOM_PARAM_PITCH_SCALE]=1.0; - params[ROOM_PARAM_VOLUME_SCALE_DB]=0; - params[ROOM_PARAM_REVERB_SEND]=0; - params[ROOM_PARAM_CHORUS_SEND]=0; - params[ROOM_PARAM_ATTENUATION_SCALE]=1.0; - params[ROOM_PARAM_ATTENUATION_HF_CUTOFF]=5000; - params[ROOM_PARAM_ATTENUATION_HF_FLOOR_DB]=-24.0; - params[ROOM_PARAM_ATTENUATION_HF_RATIO_EXP]=1.0; - params[ROOM_PARAM_ATTENUATION_REVERB_SCALE]=0.0; - override_other_sources=false; - reverb=ROOM_REVERB_HALL; -// octree_id=0; - level=-1; - - -} - - -SpatialSound2DServerSW::Source::Source() { - - params[SOURCE_PARAM_VOLUME_DB]=0.0; - params[SOURCE_PARAM_PITCH_SCALE]=1.0; - params[SOURCE_PARAM_ATTENUATION_MIN_DISTANCE]=1; - params[SOURCE_PARAM_ATTENUATION_MAX_DISTANCE]=100; - params[SOURCE_PARAM_ATTENUATION_DISTANCE_EXP]=1.0; //linear (and not really good) - stream=NULL; - voices.resize(1); - last_voice=0; -} - -SpatialSound2DServerSW::Source::Voice::Voice() { - - active=false; - restart=false; - pitch_scale=1.0; - volume_scale=0.0; - voice_rid=AudioServer::get_singleton()->voice_create(); - -} -SpatialSound2DServerSW::Source::Voice::~Voice() { - - AudioServer::get_singleton()->free(voice_rid); -} - - -SpatialSound2DServerSW::Listener::Listener() { - - params[LISTENER_PARAM_VOLUME_SCALE_DB]=0.0; - params[LISTENER_PARAM_PITCH_SCALE]=1.0; - params[LISTENER_PARAM_ATTENUATION_SCALE]=1.0; - params[LISTENER_PARAM_PAN_RANGE]=128; - -} - -/* SPACE */ -RID SpatialSound2DServerSW::space_create() { - - Space* space = memnew( Space ); - RID space_rid = space_owner.make_rid(space); - space->default_room=room_create(); - room_set_space(space->default_room,space_rid); - return space_rid; -} - -/* ROOM */ - -RID SpatialSound2DServerSW::room_create() { - - Room *room = memnew( Room ); - return room_owner.make_rid(room); -} - -void SpatialSound2DServerSW::room_set_space(RID p_room,RID p_space) { - - Room *room = room_owner.get(p_room); - ERR_FAIL_COND(!room); - - if (room->space.is_valid()) { - - Space *space = space_owner.get(room->space); - space->rooms.erase(p_room); -// space->octree.erase(room->octree_id); - //room->octree_id=0; - } - - room->space=RID(); - - if (p_space.is_valid()) { - - Space *space = space_owner.get(p_space); - ERR_FAIL_COND(!space); - space->rooms.insert(p_room); -// room->octree_id=space->octree.create(room,AABB()); - //set bounds -// AABB aabb = room->bounds.is_empty()?AABB():room->bounds.get_aabb(); - // space->octree.move(room->octree_id,room->transform.xform(aabb)); - room->space=p_space; - } - - -} - -RID SpatialSound2DServerSW::room_get_space(RID p_room) const { - - Room *room = room_owner.get(p_room); - ERR_FAIL_COND_V(!room,RID()); - - - return room->space; -} - - - -void SpatialSound2DServerSW::room_set_bounds(RID p_room, const DVector<Point2>& p_bounds) { - - Room *room = room_owner.get(p_room); - ERR_FAIL_COND(!room); - - room->bounds=p_bounds; - - if (!room->space.is_valid()) - return; - -// AABB aabb = room->bounds.is_empty()?AABB():room->bounds.get_aabb(); -// Space* space = space_owner.get(room->space); -// ERR_FAIL_COND(!space); - -// space->octree.move(room->octree_id,room->transform.xform(aabb)); - -} -DVector<Point2> SpatialSound2DServerSW::room_get_bounds(RID p_room) const { - Room *room = room_owner.get(p_room); - ERR_FAIL_COND_V(!room,DVector<Point2>()); - - return room->bounds; -} - -void SpatialSound2DServerSW::room_set_transform(RID p_room, const Matrix32& p_transform) { - - if (space_owner.owns(p_room)) - p_room=space_owner.get(p_room)->default_room; - - Room *room = room_owner.get(p_room); - ERR_FAIL_COND(!room); - room->transform=p_transform; - room->inverse_transform=p_transform.affine_inverse(); // needs to be done to unscale BSP properly - - if (!room->space.is_valid()) - return; - - /* - if (!room->bounds.is_empty()) { - - Space* space = space_owner.get(room->space); - ERR_FAIL_COND(!space); - - //space->octree.move(room->octree_id,room->transform.xform(room->bounds.get_aabb())); - }*/ -} - -Matrix32 SpatialSound2DServerSW::room_get_transform(RID p_room) const { - - if (space_owner.owns(p_room)) - p_room=space_owner.get(p_room)->default_room; - - Room *room = room_owner.get(p_room); - ERR_FAIL_COND_V(!room,Matrix32()); - return room->transform; -} - - -void SpatialSound2DServerSW::room_set_param(RID p_room, RoomParam p_param, float p_value) { - - if (space_owner.owns(p_room)) - p_room=space_owner.get(p_room)->default_room; - - ERR_FAIL_INDEX(p_param,ROOM_PARAM_MAX); - Room *room = room_owner.get(p_room); - ERR_FAIL_COND(!room); - room->params[p_param]=p_value; - -} -float SpatialSound2DServerSW::room_get_param(RID p_room, RoomParam p_param) const { - - if (space_owner.owns(p_room)) - p_room=space_owner.get(p_room)->default_room; - - ERR_FAIL_INDEX_V(p_param,ROOM_PARAM_MAX,0); - Room *room = room_owner.get(p_room); - ERR_FAIL_COND_V(!room,0); - return room->params[p_param]; -} - -void SpatialSound2DServerSW::room_set_level(RID p_room, int p_level) { - - Room *room = room_owner.get(p_room); - ERR_FAIL_COND(!room); - room->level =p_level; - -} - -int SpatialSound2DServerSW::room_get_level(RID p_room) const { - - Room *room = room_owner.get(p_room); - ERR_FAIL_COND_V(!room,0); - return room->level; - -} - - -void SpatialSound2DServerSW::room_set_reverb(RID p_room, RoomReverb p_reverb) { - - if (space_owner.owns(p_room)) - p_room=space_owner.get(p_room)->default_room; - - Room *room = room_owner.get(p_room); - ERR_FAIL_COND(!room); - room->reverb=p_reverb; - -} -SpatialSound2DServerSW::RoomReverb SpatialSound2DServerSW::room_get_reverb(RID p_room) const { - - if (space_owner.owns(p_room)) - p_room=space_owner.get(p_room)->default_room; - - Room *room = room_owner.get(p_room); - ERR_FAIL_COND_V(!room,ROOM_REVERB_SMALL); - return room->reverb; -} - -//useful for underwater or rooms with very strange conditions -void SpatialSound2DServerSW::room_set_force_params_to_all_sources(RID p_room, bool p_force) { - - if (space_owner.owns(p_room)) - p_room=space_owner.get(p_room)->default_room; - - Room *room = room_owner.get(p_room); - ERR_FAIL_COND(!room); - room->override_other_sources=p_force; - -} -bool SpatialSound2DServerSW::room_is_forcing_params_to_all_sources(RID p_room) const { - - if (space_owner.owns(p_room)) - p_room=space_owner.get(p_room)->default_room; - - Room *room = room_owner.get(p_room); - ERR_FAIL_COND_V(!room,false); - return room->override_other_sources; -} - -/* SOURCE */ - -RID SpatialSound2DServerSW::source_create(RID p_space) { - - Space *space = space_owner.get(p_space); - ERR_FAIL_COND_V(!space,RID()); - - Source *source = memnew( Source ); - source->space=p_space; - RID source_rid = source_owner.make_rid(source); - space->sources.insert(source_rid); - - return source_rid; -} - - -void SpatialSound2DServerSW::source_set_polyphony(RID p_source,int p_voice_count) { - - - ERR_FAIL_COND(p_voice_count<=0); // more than 32 is too much, change this if you really need more - if (p_voice_count>32) { - - ERR_PRINT("Voices will be clipped to 32"); - p_voice_count=32; - } - Source *source = source_owner.get(p_source); - ERR_FAIL_COND(!source); - - if (p_voice_count<source->voices.size()) { - - for(int i=p_voice_count;i<source->voices.size();i++) { - active_voices.erase(ActiveVoice(source,i)); //erase from active voices - } - } - source->voices.resize(p_voice_count); - -} - -int SpatialSound2DServerSW::source_get_polyphony(RID p_source) const { - - Source *source = source_owner.get(p_source); - ERR_FAIL_COND_V(!source,-1); - return source->voices.size(); - -} - -void SpatialSound2DServerSW::source_set_transform(RID p_source, const Matrix32& p_transform) { - - Source *source = source_owner.get(p_source); - ERR_FAIL_COND(!source); - source->transform=p_transform; - source->transform.orthonormalize(); -} -Matrix32 SpatialSound2DServerSW::source_get_transform(RID p_source) const { - - Source *source = source_owner.get(p_source); - ERR_FAIL_COND_V(!source,Matrix32()); - return source->transform; -} - -void SpatialSound2DServerSW::source_set_param(RID p_source, SourceParam p_param, float p_value) { - - ERR_FAIL_INDEX(p_param,SOURCE_PARAM_MAX); - Source *source = source_owner.get(p_source); - ERR_FAIL_COND(!source); - source->params[p_param]=p_value; - -} -float SpatialSound2DServerSW::source_get_param(RID p_source, SourceParam p_param) const { - ERR_FAIL_INDEX_V(p_param,SOURCE_PARAM_MAX,0); - Source *source = source_owner.get(p_source); - ERR_FAIL_COND_V(!source,0); - return source->params[p_param]; - - -} - -void SpatialSound2DServerSW::source_set_audio_stream(RID p_source, AudioServer::AudioStream *p_stream) { - - Source *source = source_owner.get(p_source); - ERR_FAIL_COND(!source); - AudioServer::get_singleton()->lock(); - source->stream=p_stream; - _THREAD_SAFE_METHOD_ - - if (!p_stream) { - streaming_sources.erase(source); - active_voices.erase(ActiveVoice(source,VOICE_IS_STREAM)); - } else { - streaming_sources.insert(source); - active_voices.insert(ActiveVoice(source,VOICE_IS_STREAM)); - zeromem(source->stream_data.filter_state,sizeof(Source::StreamData::FilterState)*4); //reset filter for safetyness - p_stream->set_mix_rate(AudioServer::get_singleton()->get_default_mix_rate()); - } - - AudioServer::get_singleton()->unlock(); - -} //null to unset - -SpatialSound2DServer::SourceVoiceID SpatialSound2DServerSW::source_play_sample(RID p_source, RID p_sample, int p_mix_rate, int p_voice) { - - Source *source = source_owner.get(p_source); - ERR_FAIL_COND_V(!source,SOURCE_INVALID_VOICE); - - int to_play=0; - - if (p_voice==SOURCE_NEXT_VOICE) { - to_play=source->last_voice+1; - if (to_play>=source->voices.size()) - to_play=0; - - } else - to_play=p_voice; - - ERR_FAIL_INDEX_V(to_play,source->voices.size(),SOURCE_INVALID_VOICE); - - source->voices[to_play].restart=true; - source->voices[to_play].sample_rid=p_sample; - source->voices[to_play].sample_mix_rate=p_mix_rate; - source->voices[to_play].pitch_scale=1; - source->voices[to_play].volume_scale=0; - source->last_voice=to_play; - active_voices.insert(ActiveVoice(source,to_play)); - return to_play; -} - -/* VOICES */ -void SpatialSound2DServerSW::source_voice_set_pitch_scale(RID p_source, SourceVoiceID p_voice, float p_pitch_scale) { - - Source *source = source_owner.get(p_source); - ERR_FAIL_COND(!source); - ERR_FAIL_INDEX(p_voice,source->voices.size()); - source->voices[p_voice].pitch_scale=p_pitch_scale; - -} -void SpatialSound2DServerSW::source_voice_set_volume_scale_db(RID p_source, SourceVoiceID p_voice, float p_db) { - - Source *source = source_owner.get(p_source); - ERR_FAIL_COND(!source); - ERR_FAIL_INDEX(p_voice,source->voices.size()); - source->voices[p_voice].volume_scale=p_db; - -} - -bool SpatialSound2DServerSW::source_is_voice_active(RID p_source, SourceVoiceID p_voice) const { - - Source *source = source_owner.get(p_source); - ERR_FAIL_COND_V(!source,false); - ERR_FAIL_INDEX_V(p_voice,source->voices.size(),false); - return source->voices[p_voice].active || source->voices[p_voice].restart; - -} -void SpatialSound2DServerSW::source_stop_voice(RID p_source, SourceVoiceID p_voice) { - - Source *source = source_owner.get(p_source); - ERR_FAIL_COND(!source); - ERR_FAIL_INDEX(p_voice,source->voices.size()); - if (source->voices[p_voice].active) { - AudioServer::get_singleton()->voice_stop(source->voices[p_voice].voice_rid); - } - source->voices[p_voice].active=false; - source->voices[p_voice].restart=false; - active_voices.erase(ActiveVoice(source,p_voice)); -} - -/* LISTENER */ - -RID SpatialSound2DServerSW::listener_create() { - - Listener *listener = memnew( Listener ); - RID listener_rid = listener_owner.make_rid(listener); - return listener_rid; - -} - -void SpatialSound2DServerSW::listener_set_space(RID p_listener,RID p_space) { - - Listener *listener = listener_owner.get(p_listener); - ERR_FAIL_COND(!listener); - - if (listener->space.is_valid()) { - - Space *lspace = space_owner.get(listener->space); - ERR_FAIL_COND(!lspace); - lspace->listeners.erase(p_listener); - } - - listener->space=RID(); - - if (p_space.is_valid()) { - Space *space = space_owner.get(p_space); - ERR_FAIL_COND(!space); - - listener->space=p_space; - space->listeners.insert(p_listener); - } - -} - -void SpatialSound2DServerSW::listener_set_transform(RID p_listener, const Matrix32& p_transform) { - - Listener *listener = listener_owner.get(p_listener); - ERR_FAIL_COND(!listener); - listener->transform=p_transform; - listener->transform.orthonormalize(); //must be done.. -} -Matrix32 SpatialSound2DServerSW::listener_get_transform(RID p_listener) const { - - Listener *listener = listener_owner.get(p_listener); - ERR_FAIL_COND_V(!listener,Matrix32()); - return listener->transform; -} - -void SpatialSound2DServerSW::listener_set_param(RID p_listener, ListenerParam p_param, float p_value) { - - ERR_FAIL_INDEX(p_param,LISTENER_PARAM_MAX); - Listener *listener = listener_owner.get(p_listener); - ERR_FAIL_COND(!listener); - listener->params[p_param]=p_value; -} - -float SpatialSound2DServerSW::listener_get_param(RID p_listener, ListenerParam p_param) const { - - ERR_FAIL_INDEX_V(p_param,LISTENER_PARAM_MAX,0); - Listener *listener = listener_owner.get(p_listener); - ERR_FAIL_COND_V(!listener,0); - return listener->params[p_param]; -} - - -/* MISC */ - -void SpatialSound2DServerSW::free(RID p_id) { - - - if (space_owner.owns(p_id)) { - - Space *space = space_owner.get(p_id); - free(space->default_room); - - while(space->listeners.size()) { - listener_set_space(space->listeners.front()->get(),RID()); - } - while(space->sources.size()) { - free(space->sources.front()->get()); - } - while(space->rooms.size()) { - room_set_space(space->rooms.front()->get(),RID()); - } - space_owner.free(p_id); - memdelete(space); - - } else if (source_owner.owns(p_id)) { - - Source *source = source_owner.get(p_id); - if (source->stream) - source_set_audio_stream(p_id,NULL); - - Space *space = space_owner.get(source->space); - ERR_FAIL_COND(!space); - space->sources.erase(p_id); - for(int i=0;i<source->voices.size();i++) { - active_voices.erase(ActiveVoice(source,i)); - } - source_owner.free(p_id); - memdelete(source); - } else if (listener_owner.owns(p_id)) { - - Listener *listener = listener_owner.get(p_id); - if (listener->space.is_valid()) { - Space *space = space_owner.get(listener->space); - ERR_FAIL_COND(!space); - space->listeners.erase(p_id); - } - listener_owner.free(p_id); - memdelete(listener); - - } else if (room_owner.owns(p_id)) { - - Room *room = room_owner.get(p_id); - - if (room->space.is_valid()) { - Space *space = space_owner.get(room->space); - ERR_FAIL_COND(!space); -// space->octree.erase(room->octree_id); - space->rooms.erase(p_id); - } - room_owner.free(p_id); - memdelete(room); - } else { - ERR_PRINT("Attempt to free invalid ID") ; - } - -} - -void SpatialSound2DServerSW::_clean_up_owner(RID_OwnerBase *p_owner, const char *p_area) { - - List<RID> rids; - p_owner->get_owned_list(&rids); - - for(List<RID>::Element *I=rids.front();I;I=I->next()) { - if (OS::get_singleton()->is_stdout_verbose()) { - - print_line("Leaked RID ("+itos(I->get().get_id())+") of type "+String(p_area)); - } - free(I->get()); - } -} - -void SpatialSound2DServerSW::init() { - - internal_buffer = memnew_arr(int32_t, INTERNAL_BUFFER_SIZE*INTERNAL_BUFFER_MAX_CHANNELS); - internal_buffer_channels=AudioServer::get_singleton()->get_default_channel_count(); - - internal_audio_stream = memnew( InternalAudioStream ); - internal_audio_stream->owner=this; - internal_audio_stream_rid = AudioServer::get_singleton()->audio_stream_create(internal_audio_stream); - - AudioServer::get_singleton()->stream_set_active(internal_audio_stream_rid,true); - -} - - - -bool SpatialSound2DServerSW::internal_buffer_mix(int32_t *p_buffer,int p_frames) { - - if (streaming_sources.size()==0) - return false; //nothing to mix - - - for (Set<Source*>::Element *E=streaming_sources.front();E;E=E->next()) { - - Source *s=E->get(); - ERR_CONTINUE(!s->stream); - - int channels = s->stream->get_channel_count(); - Source::StreamData &sd=s->stream_data; - - int todo=p_frames; - - AudioFilterSW filter; - filter.set_sampling_rate(AudioServer::get_singleton()->get_default_mix_rate()); - filter.set_cutoff(sd.filter_cutoff); - filter.set_gain(sd.filter_gain); - filter.set_resonance(1); - filter.set_mode(AudioFilterSW::HIGHSHELF); - filter.set_stages(1); - AudioFilterSW::Coeffs coefs; - filter.prepare_coefficients(&coefs); - - int32_t in[4]; -#ifndef SPATIAL_SOUND_SERVER_NO_FILTER -#define DO_FILTER(m_c)\ - {\ - float val = in[m_c];\ - float pre=val;\ - val = val*coefs.b0 + sd.filter_state[m_c].hb[0]*coefs.b1 + sd.filter_state[m_c].hb[1]*coefs.b2 + sd.filter_state[m_c].ha[0]*coefs.a1 + sd.filter_state[m_c].ha[1]*coefs.a2;\ - sd.filter_state[m_c].ha[1]=sd.filter_state[m_c].ha[0];\ - sd.filter_state[m_c].hb[1]=sd.filter_state[m_c].hb[0]; \ - sd.filter_state[m_c].hb[0]=pre;\ - sd.filter_state[m_c].ha[0]=val;\ - in[m_c]=Math::fast_ftoi(val);\ - } -#else -#define DO_FILTER(m_c) -#endif - - while(todo) { - - int to_mix=MIN(todo,INTERNAL_BUFFER_SIZE); - - s->stream->mix(internal_buffer,to_mix); - - switch(internal_buffer_channels) { - - case 2: { - - float p = sd.panning.x*0.5+0.5; - float panf[2]={ (1.0-p),p }; - panf[0]*=sd.volume; - panf[1]*=sd.volume; - - int32_t pan[2]={Math::fast_ftoi(panf[0]*(1<<16)),Math::fast_ftoi(panf[1]*(1<<16))}; - - switch(channels) { - case 1: { - - for(int i=0;i<to_mix;i++) { - - in[0]=internal_buffer[i]; - in[1]=internal_buffer[i]; - DO_FILTER(0); - DO_FILTER(1); - p_buffer[(i<<1)+0]=((in[0]>>16)*pan[0]); - p_buffer[(i<<1)+1]=((in[1]>>16)*pan[1]); - } - } break; - case 2: { - - for(int i=0;i<to_mix;i++) { - - in[0]=internal_buffer[(i<<1)+0]; - in[1]=internal_buffer[(i<<1)+1]; - DO_FILTER(0); - DO_FILTER(1); - p_buffer[(i<<1)+0]=((in[0]>>16)*pan[0]); - p_buffer[(i<<1)+1]=((in[1]>>16)*pan[1]); - } - } break; - case 4: { - - for(int i=0;i<to_mix;i++) { - - in[0]=(internal_buffer[(i<<2)+0]+internal_buffer[(i<<2)+2])>>1; - in[1]=(internal_buffer[(i<<2)+1]+internal_buffer[(i<<2)+3])>>1; - DO_FILTER(0); - DO_FILTER(1); - p_buffer[(i<<1)+0]=((in[0]>>16)*pan[0]); - p_buffer[(i<<1)+1]=((in[1]>>16)*pan[1]); - } - } break; - - } break; - - } break; - case 4: { - - float xp = sd.panning.x*0.5+0.5; - float yp = sd.panning.y*0.5+0.5; - float panf[4]={ (1.0-xp)*(1.0-yp),(xp)*(1.0-yp),(1.0-xp)*(yp),(xp)*(yp) }; - panf[0]*=sd.volume; - panf[1]*=sd.volume; - panf[2]*=sd.volume; - panf[3]*=sd.volume; - - int32_t pan[4]={ - Math::fast_ftoi(panf[0]*(1<<16)), - Math::fast_ftoi(panf[1]*(1<<16)), - Math::fast_ftoi(panf[2]*(1<<16)), - Math::fast_ftoi(panf[3]*(1<<16))}; - - switch(channels) { - case 1: { - - for(int i=0;i<to_mix;i++) { - - in[0]=internal_buffer[i]; - in[1]=internal_buffer[i]; - in[2]=internal_buffer[i]; - in[3]=internal_buffer[i]; - DO_FILTER(0); - DO_FILTER(1); - DO_FILTER(2); - DO_FILTER(3); - p_buffer[(i<<2)+0]=((in[0]>>16)*pan[0]); - p_buffer[(i<<2)+1]=((in[1]>>16)*pan[1]); - p_buffer[(i<<2)+2]=((in[2]>>16)*pan[2]); - p_buffer[(i<<2)+3]=((in[3]>>16)*pan[3]); - } - } break; - case 2: { - - for(int i=0;i<to_mix;i++) { - - in[0]=internal_buffer[(i<<1)+0]; - in[1]=internal_buffer[(i<<1)+1]; - in[2]=internal_buffer[(i<<1)+0]; - in[3]=internal_buffer[(i<<1)+1]; - DO_FILTER(0); - DO_FILTER(1); - DO_FILTER(2); - DO_FILTER(3); - p_buffer[(i<<2)+0]=((in[0]>>16)*pan[0]); - p_buffer[(i<<2)+1]=((in[1]>>16)*pan[1]); - p_buffer[(i<<2)+2]=((in[2]>>16)*pan[2]); - p_buffer[(i<<2)+3]=((in[3]>>16)*pan[3]); - } - } break; - case 4: { - - for(int i=0;i<to_mix;i++) { - - in[0]=internal_buffer[(i<<2)+0]; - in[1]=internal_buffer[(i<<2)+1]; - in[2]=internal_buffer[(i<<2)+2]; - in[3]=internal_buffer[(i<<2)+3]; - DO_FILTER(0); - DO_FILTER(1); - DO_FILTER(2); - DO_FILTER(3); - p_buffer[(i<<2)+0]=((in[0]>>16)*pan[0]); - p_buffer[(i<<2)+1]=((in[1]>>16)*pan[1]); - p_buffer[(i<<2)+2]=((in[2]>>16)*pan[2]); - p_buffer[(i<<2)+3]=((in[3]>>16)*pan[3]); - } - } break; - - } break; - - } break; - case 6: { - - - } break; - } - p_buffer+=to_mix*internal_buffer_channels; - todo-=to_mix; - - } - - } - - return true; -} - -void SpatialSound2DServerSW::update(float p_delta) { - - List<ActiveVoice> to_disable; - - for(Set<ActiveVoice>::Element *E=active_voices.front();E;E=E->next()) { - - Source *source = E->get().source; - int voice = E->get().voice; - - if (voice!=VOICE_IS_STREAM) { - Source::Voice &v=source->voices[voice]; - ERR_CONTINUE(!v.active && !v.restart); // likely a bug... - } - - //this could be optimized at some point... am not sure - Space *space=space_owner.get(source->space); - Room *room=room_owner.get(space->default_room); - - //compute mixing weights (support for multiple listeners in the same output) - float total_distance=0; - for(Set<RID>::Element *L=space->listeners.front();L;L=L->next()) { - Listener *listener=listener_owner.get(L->get()); - float d = listener->transform.get_origin().distance_to(source->transform.get_origin()); - if (d==0) - d=0.1; - total_distance+=d; - } - - //compute spatialization variables, weighted according to distance - float volume_attenuation = 0.0; - float air_absorption_hf_cutoff = 0.0; - float air_absorption = 0.0; - float pitch_scale=0.0; - Vector2 panning; - - for(Set<RID>::Element *L=space->listeners.front();L;L=L->next()) { - - Listener *listener=listener_owner.get(L->get()); - - Vector2 rel_vector = -listener->transform.xform_inv(source->transform.get_origin()); - //Vector2 source_rel_vector = source->transform.xform_inv(listener->transform.get_origin()).normalized(); - float distance=rel_vector.length(); - float weight = distance/total_distance; - float pscale=1.0; - - float distance_scale=listener->params[LISTENER_PARAM_ATTENUATION_SCALE]*room->params[ROOM_PARAM_ATTENUATION_SCALE]; - float distance_min=source->params[SOURCE_PARAM_ATTENUATION_MIN_DISTANCE]*distance_scale; - float distance_max=source->params[SOURCE_PARAM_ATTENUATION_MAX_DISTANCE]*distance_scale; - float attenuation_exp=source->params[SOURCE_PARAM_ATTENUATION_DISTANCE_EXP]; - float attenuation=1; - - if (distance_max>0) { - distance = CLAMP(distance,distance_min,distance_max); - attenuation = Math::pow(1.0 - ((distance - distance_min)/(distance_max-distance_min)),CLAMP(attenuation_exp,0.001,16)); - } - - float hf_attenuation_cutoff = room->params[ROOM_PARAM_ATTENUATION_HF_CUTOFF]; - float hf_attenuation_exp = room->params[ROOM_PARAM_ATTENUATION_HF_RATIO_EXP]; - float hf_attenuation_floor = room->params[ROOM_PARAM_ATTENUATION_HF_FLOOR_DB]; - float absorption=Math::db2linear(Math::lerp(hf_attenuation_floor,0,Math::pow(attenuation,hf_attenuation_exp))); - - // source emission cone -/* only for 3D - float emission_deg=source->params[SOURCE_PARAM_EMISSION_CONE_DEGREES]; - float emission_attdb=source->params[SOURCE_PARAM_EMISSION_CONE_ATTENUATION_DB]; - absorption*=_get_attenuation(source_rel_vector.dot(Vector2(0,0,-1)),emission_deg,emission_attdb); -*/ - Vector2 vpanning=rel_vector.normalized(); - if (distance < listener->params[LISTENER_PARAM_PAN_RANGE]) - vpanning*=distance/listener->params[LISTENER_PARAM_PAN_RANGE]; - - //listener stuff - - { - - // head cone -/* only for 3D - float reception_deg=listener->params[LISTENER_PARAM_RECEPTION_CONE_DEGREES]; - float reception_attdb=listener->params[LISTENER_PARAM_RECEPTION_CONE_ATTENUATION_DB]; - - absorption*=_get_attenuation(vpanning.dot(Vector2(0,0,-1)),reception_deg,reception_attdb); -*/ - - // scale - - attenuation*=Math::db2linear(listener->params[LISTENER_PARAM_VOLUME_SCALE_DB]); - pscale*=Math::db2linear(listener->params[LISTENER_PARAM_PITCH_SCALE]); - - - } - - - - - //add values - - volume_attenuation+=weight*attenuation; // plus other stuff i guess - air_absorption+=weight*absorption; - air_absorption_hf_cutoff+=weight*hf_attenuation_cutoff; - panning+=vpanning*weight; - pitch_scale+=pscale*weight; - - } - - RoomReverb reverb_room=ROOM_REVERB_HALL; - float reverb_send=0; - - /* APPLY ROOM SETTINGS */ - - { - pitch_scale*=room->params[ROOM_PARAM_PITCH_SCALE]; - volume_attenuation*=Math::db2linear(room->params[ROOM_PARAM_VOLUME_SCALE_DB]); - reverb_room=room->reverb; - reverb_send=Math::lerp(1.0,volume_attenuation,room->params[ROOM_PARAM_ATTENUATION_REVERB_SCALE])*room->params[ROOM_PARAM_REVERB_SEND]; - - } - - /* UPDATE VOICE & STREAM */ - - - - if (voice==VOICE_IS_STREAM) { - - //update voice!! - source->stream_data.panning=panning; - source->stream_data.volume=volume_attenuation*Math::db2linear(source->params[SOURCE_PARAM_VOLUME_DB]); - source->stream_data.reverb=reverb_room; - source->stream_data.reverb_send=reverb_send; - source->stream_data.filter_gain=air_absorption; - source->stream_data.filter_cutoff=air_absorption_hf_cutoff; - - if (!source->stream) //stream is gone bye bye - to_disable.push_back(ActiveVoice(source,voice)); // oh well.. - - } else if (voice>=0) { - //update stream!! - Source::Voice &v=source->voices[voice]; - - if (v.restart) - AudioServer::get_singleton()->voice_play(v.voice_rid,v.sample_rid); - - float volume_scale = Math::db2linear(v.volume_scale)*Math::db2linear(source->params[SOURCE_PARAM_VOLUME_DB]); - float volume = volume_attenuation*volume_scale; - reverb_send*=volume_scale; - int mix_rate = v.sample_mix_rate*v.pitch_scale*pitch_scale*source->params[SOURCE_PARAM_PITCH_SCALE]; - - - if (mix_rate<=0) { - - ERR_PRINT("Invalid mix rate for voice (0) check for invalid pitch_scale param."); - to_disable.push_back(ActiveVoice(source,voice)); // oh well.. - continue; //invalid mix rate, disabling - } - if (v.restart || v.last_volume!=volume) - AudioServer::get_singleton()->voice_set_volume(v.voice_rid,volume); - if (v.restart || v.last_mix_rate!=mix_rate) - AudioServer::get_singleton()->voice_set_mix_rate(v.voice_rid,mix_rate); - if (v.restart || v.last_filter_gain!=air_absorption || v.last_filter_cutoff!=air_absorption_hf_cutoff) - AudioServer::get_singleton()->voice_set_filter(v.voice_rid,AudioServer::FILTER_HIGH_SHELF,air_absorption_hf_cutoff,1.0,air_absorption); - if (v.restart || v.last_panning!=panning) { - AudioServer::get_singleton()->voice_set_pan(v.voice_rid,-panning.x,panning.y,0); - } - if (v.restart || v.last_reverb_room!=reverb_room || v.last_reverb_send!=reverb_send) - AudioServer::get_singleton()->voice_set_reverb(v.voice_rid,AudioServer::ReverbRoomType(reverb_room),reverb_send); - - v.last_volume=volume; - v.last_mix_rate=mix_rate; - v.last_filter_gain=air_absorption; - v.last_filter_cutoff=air_absorption_hf_cutoff; - v.last_panning=panning; - v.last_reverb_room=reverb_room; - v.last_reverb_send=reverb_send; - v.restart=false; - v.active=true; - - if (!AudioServer::get_singleton()->voice_is_active(v.voice_rid)) - to_disable.push_back(ActiveVoice(source,voice)); // oh well.. - } - } - - while(to_disable.size()) { - - ActiveVoice av = to_disable.front()->get(); - av.source->voices[av.voice].active=false; - av.source->voices[av.voice].restart=false; - active_voices.erase(av); - to_disable.pop_front(); - } - -} -void SpatialSound2DServerSW::finish() { - - AudioServer::get_singleton()->free(internal_audio_stream_rid); - memdelete(internal_audio_stream); - - _clean_up_owner(&source_owner,"Source"); - _clean_up_owner(&listener_owner,"Listener"); - _clean_up_owner(&room_owner,"Room"); - _clean_up_owner(&space_owner,"Space"); - - memdelete_arr(internal_buffer); -} - -SpatialSound2DServerSW::SpatialSound2DServerSW() { - -} diff --git a/servers/spatial_sound_2d/spatial_sound_2d_server_sw.h b/servers/spatial_sound_2d/spatial_sound_2d_server_sw.h deleted file mode 100644 index 619b11f376..0000000000 --- a/servers/spatial_sound_2d/spatial_sound_2d_server_sw.h +++ /dev/null @@ -1,265 +0,0 @@ -/*************************************************************************/ -/* spatial_sound_2d_server_sw.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#ifndef SPATIAL_SOUND_2D_SERVER_SW_H -#define SPATIAL_SOUND_2D_SERVER_SW_H - -#include "servers/spatial_sound_2d_server.h" - -#include "os/thread_safe.h" - - -class SpatialSound2DServerSW : public SpatialSound2DServer { - - OBJ_TYPE(SpatialSound2DServerSW,SpatialSound2DServer); - - _THREAD_SAFE_CLASS_ - - enum { - INTERNAL_BUFFER_SIZE=4096, - INTERNAL_BUFFER_MAX_CHANNELS=4, - VOICE_IS_STREAM=-1 - - }; - - - struct InternalAudioStream : public AudioServer::AudioStream { - - ::SpatialSound2DServerSW *owner; - virtual int get_channel_count() const; - virtual void set_mix_rate(int p_rate); //notify the stream of the mix rate - virtual bool mix(int32_t *p_buffer,int p_frames); - virtual void update(); - }; - - InternalAudioStream *internal_audio_stream; - RID internal_audio_stream_rid; - int32_t *internal_buffer; - int internal_buffer_channels; - - bool internal_buffer_mix(int32_t *p_buffer,int p_frames); - - struct Room; - - struct Space { - - RID default_room; - Set<RID> rooms; - Set<RID> sources; - Set<RID> listeners; - - //Octree<Room> octree; - }; - - mutable RID_Owner<Space> space_owner; - - struct Room { - RID space; - Matrix32 transform; - Matrix32 inverse_transform; - DVector<Point2> bounds; - RoomReverb reverb; - float params[ROOM_PARAM_MAX]; - bool override_other_sources; - //OctreeElementID octree_id; - int level; - - Room(); - }; - - mutable RID_Owner<Room> room_owner; - - - - struct Source { - - struct Voice { - - RID voice_rid; - RID sample_rid; - bool active; - bool restart; - float pitch_scale; - float volume_scale; - int sample_mix_rate; - - - float last_volume; - float last_filter_gain; - float last_filter_cutoff; - Vector2 last_panning; - int last_mix_rate; - RoomReverb last_reverb_room; - float last_reverb_send; - - Voice(); - ~Voice(); - }; - - struct StreamData { - - - Vector2 panning; - RoomReverb reverb; - float reverb_send; - float volume; - float filter_gain; - float filter_cutoff; - - struct FilterState { - - float ha[2]; - float hb[2]; - } filter_state[4]; - - StreamData() { - - reverb_send=0; - reverb=ROOM_REVERB_HALL; - volume=1.0; - filter_gain=1; - filter_cutoff=5000; - - } - } stream_data; - - RID space; - Matrix32 transform; - float params[SOURCE_PARAM_MAX]; - AudioServer::AudioStream *stream; - Vector<Voice> voices; - int last_voice; - - Source(); - }; - - mutable RID_Owner<Source> source_owner; - - struct Listener { - - RID space; - Matrix32 transform; - float params[LISTENER_PARAM_MAX]; - - Listener(); - }; - - mutable RID_Owner<Listener> listener_owner; - - struct ActiveVoice { - - Source *source; - int voice; - bool operator<(const ActiveVoice& p_voice) const { return (voice==p_voice.voice)?(source<p_voice.source):(voice<p_voice.voice); } - ActiveVoice(Source *p_source=NULL,int p_voice=0) { source=p_source; voice=p_voice; } - }; - -// Room *cull_rooms[MAX_CULL_ROOMS]; - - Set<Source*> streaming_sources; - Set<ActiveVoice> active_voices; - - void _clean_up_owner(RID_OwnerBase *p_owner, const char *p_area); - void _update_sources(); - -public: - - /* SPACE */ - virtual RID space_create(); - - /* ROOM */ - - virtual RID room_create(); - virtual void room_set_space(RID p_room,RID p_space); - virtual RID room_get_space(RID p_room) const; - - virtual void room_set_bounds(RID p_room, const DVector<Point2>& p_bounds); - virtual DVector<Point2> room_get_bounds(RID p_room) const; - virtual void room_set_transform(RID p_room, const Matrix32& p_transform); - virtual Matrix32 room_get_transform(RID p_room) const; - - - virtual void room_set_param(RID p_room, RoomParam p_param, float p_value); - virtual float room_get_param(RID p_room, RoomParam p_param) const; - - virtual void room_set_level(RID p_room, int p_level); - virtual int room_get_level(RID p_room) const; - - virtual void room_set_reverb(RID p_room, RoomReverb p_reverb); - virtual RoomReverb room_get_reverb(RID p_room) const; - - //useful for underwater or rooms with very strange conditions - virtual void room_set_force_params_to_all_sources(RID p_room, bool p_force); - virtual bool room_is_forcing_params_to_all_sources(RID p_room) const; - - /* SOURCE */ - - virtual RID source_create(RID p_space); - - virtual void source_set_polyphony(RID p_source,int p_voice_count); - virtual int source_get_polyphony(RID p_source) const; - - virtual void source_set_transform(RID p_source, const Matrix32& p_transform); - virtual Matrix32 source_get_transform(RID p_source) const; - - virtual void source_set_param(RID p_source, SourceParam p_param, float p_value); - virtual float source_get_param(RID p_source, SourceParam p_param) const; - - virtual void source_set_audio_stream(RID p_source, AudioServer::AudioStream *p_stream); //null to unset - virtual SourceVoiceID source_play_sample(RID p_source, RID p_sample, int p_mix_rate, int p_voice=SOURCE_NEXT_VOICE); - /* VOICES */ - virtual void source_voice_set_pitch_scale(RID p_source, SourceVoiceID p_voice, float p_pitch_scale); - virtual void source_voice_set_volume_scale_db(RID p_source, SourceVoiceID p_voice, float p_volume); - - virtual bool source_is_voice_active(RID p_source, SourceVoiceID p_voice) const; - virtual void source_stop_voice(RID p_source, SourceVoiceID p_voice); - - /* LISTENER */ - - virtual RID listener_create(); - virtual void listener_set_space(RID p_listener, RID p_space); - - virtual void listener_set_transform(RID p_listener, const Matrix32& p_transform); - virtual Matrix32 listener_get_transform(RID p_listener) const; - - virtual void listener_set_param(RID p_listener, ListenerParam p_param, float p_value); - virtual float listener_get_param(RID p_listener, ListenerParam p_param) const; - - - /* MISC */ - - virtual void free(RID p_id); - - virtual void init(); - virtual void update(float p_delta); - virtual void finish(); - - SpatialSound2DServerSW(); -}; - -#endif // SPATIAL_SOUND_2D_SERVER_SW_H diff --git a/servers/spatial_sound_2d_server.h b/servers/spatial_sound_2d_server.h deleted file mode 100644 index 2d388feb49..0000000000 --- a/servers/spatial_sound_2d_server.h +++ /dev/null @@ -1,164 +0,0 @@ -/*************************************************************************/ -/* spatial_sound_2d_server.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#ifndef SPATIAL_SOUND_2D_SERVER_H -#define SPATIAL_SOUND_2D_SERVER_H - -#include "object.h" -#include "bsp_tree.h" -#include "servers/audio_server.h" - -class SpatialSound2DServer : public Object { - - OBJ_TYPE(SpatialSound2DServer,Object); - static SpatialSound2DServer *singleton; -public: - - - enum { - SOURCE_INVALID_VOICE=-1, - SOURCE_NEXT_VOICE=-2, - }; - - typedef int SourceVoiceID; - - /* SPACE */ - virtual RID space_create()=0; - - /* ROOM */ - - virtual RID room_create()=0; - virtual void room_set_space(RID p_room,RID p_space)=0; - virtual RID room_get_space(RID p_room) const=0; - - - virtual void room_set_bounds(RID p_room, const DVector<Point2>& p_bounds)=0; - virtual DVector<Point2> room_get_bounds(RID p_room) const=0; - virtual void room_set_transform(RID p_room, const Matrix32& p_transform)=0; - virtual Matrix32 room_get_transform(RID p_room) const=0; - - enum RoomParam { - ROOM_PARAM_PITCH_SCALE, - ROOM_PARAM_VOLUME_SCALE_DB, - ROOM_PARAM_REVERB_SEND, - ROOM_PARAM_CHORUS_SEND, - ROOM_PARAM_ATTENUATION_SCALE, - ROOM_PARAM_ATTENUATION_HF_CUTOFF, - ROOM_PARAM_ATTENUATION_HF_FLOOR_DB, - ROOM_PARAM_ATTENUATION_HF_RATIO_EXP, - ROOM_PARAM_ATTENUATION_REVERB_SCALE, - ROOM_PARAM_MAX - }; - - virtual void room_set_param(RID p_room, RoomParam p_param, float p_value)=0; - virtual float room_get_param(RID p_room, RoomParam p_param) const=0; - - enum RoomReverb { - ROOM_REVERB_SMALL, - ROOM_REVERB_MEDIUM, - ROOM_REVERB_LARGE, - ROOM_REVERB_HALL - }; - - virtual void room_set_reverb(RID p_room, RoomReverb p_reverb)=0; - virtual RoomReverb room_get_reverb(RID p_room) const=0; - - virtual void room_set_level(RID p_room, int p_level)=0; - virtual int room_get_level(RID p_room) const=0; - - //useful for underwater or rooms with very strange conditions - virtual void room_set_force_params_to_all_sources(RID p_room, bool p_force)=0; - virtual bool room_is_forcing_params_to_all_sources(RID p_room) const=0; - - /* SOURCE */ - - virtual RID source_create(RID p_space)=0; - - virtual void source_set_transform(RID p_source, const Matrix32& p_transform)=0; - virtual Matrix32 source_get_transform(RID p_source) const=0; - - virtual void source_set_polyphony(RID p_source,int p_voice_count)=0; - virtual int source_get_polyphony(RID p_source) const=0; - - enum SourceParam { - - SOURCE_PARAM_VOLUME_DB, - SOURCE_PARAM_PITCH_SCALE, - SOURCE_PARAM_ATTENUATION_MIN_DISTANCE, - SOURCE_PARAM_ATTENUATION_MAX_DISTANCE, - SOURCE_PARAM_ATTENUATION_DISTANCE_EXP, - SOURCE_PARAM_MAX - }; - - virtual void source_set_param(RID p_source, SourceParam p_param, float p_value)=0; - virtual float source_get_param(RID p_source, SourceParam p_param) const=0; - - virtual void source_set_audio_stream(RID p_source, AudioServer::AudioStream *p_stream)=0; //null to unset - virtual SourceVoiceID source_play_sample(RID p_source, RID p_sample, int p_mix_rate, int p_voice=SOURCE_NEXT_VOICE)=0; - //voices - virtual void source_voice_set_pitch_scale(RID p_source,SourceVoiceID p_voice, float p_pitch_scale)=0; - virtual void source_voice_set_volume_scale_db(RID p_source,SourceVoiceID p_voice, float p_volume_db)=0; - - virtual bool source_is_voice_active(RID p_source,SourceVoiceID p_voice) const=0; - virtual void source_stop_voice(RID p_source,SourceVoiceID p_voice)=0; - - /* LISTENER */ - - enum ListenerParam { - - LISTENER_PARAM_VOLUME_SCALE_DB, - LISTENER_PARAM_PITCH_SCALE, - LISTENER_PARAM_ATTENUATION_SCALE, - LISTENER_PARAM_PAN_RANGE, - LISTENER_PARAM_MAX - }; - - virtual RID listener_create()=0; - virtual void listener_set_space(RID p_listener, RID p_space)=0; - - virtual void listener_set_transform(RID p_listener, const Matrix32& p_transform)=0; - virtual Matrix32 listener_get_transform(RID p_listener) const=0; - - virtual void listener_set_param(RID p_listener, ListenerParam p_param, float p_value)=0; - virtual float listener_get_param(RID p_listener, ListenerParam p_param) const=0; - - /* MISC */ - - virtual void free(RID p_id)=0; - - virtual void init()=0; - virtual void update(float p_delta)=0; - virtual void finish()=0; - - static SpatialSound2DServer *get_singleton(); - - SpatialSound2DServer(); - -}; - -#endif // SPATIAL_SOUND_2D_SERVER_H diff --git a/servers/spatial_sound_server.h b/servers/spatial_sound_server.h deleted file mode 100644 index 5037ee6e2f..0000000000 --- a/servers/spatial_sound_server.h +++ /dev/null @@ -1,168 +0,0 @@ -/*************************************************************************/ -/* spatial_sound_server.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#ifndef SPATIAL_SOUND_SERVER_H -#define SPATIAL_SOUND_SERVER_H - -#include "object.h" -#include "bsp_tree.h" -#include "servers/audio_server.h" - -class SpatialSoundServer : public Object { - OBJ_TYPE(SpatialSoundServer,Object); - - static SpatialSoundServer *singleton; -public: - - - enum { - SOURCE_INVALID_VOICE=-1, - SOURCE_NEXT_VOICE=-2, - }; - - typedef int SourceVoiceID; - - /* SPACE */ - virtual RID space_create()=0; - - /* ROOM */ - - virtual RID room_create()=0; - virtual void room_set_space(RID p_room,RID p_space)=0; - virtual RID room_get_space(RID p_room) const=0; - - - virtual void room_set_bounds(RID p_room, const BSP_Tree& p_bounds)=0; - virtual BSP_Tree room_get_bounds(RID p_room) const=0; - virtual void room_set_transform(RID p_room, const Transform& p_transform)=0; - virtual Transform room_get_transform(RID p_room) const=0; - - enum RoomParam { - ROOM_PARAM_SPEED_OF_SOUND_SCALE, - ROOM_PARAM_DOPPLER_FACTOR, - ROOM_PARAM_PITCH_SCALE, - ROOM_PARAM_VOLUME_SCALE_DB, - ROOM_PARAM_REVERB_SEND, - ROOM_PARAM_CHORUS_SEND, - ROOM_PARAM_ATTENUATION_SCALE, - ROOM_PARAM_ATTENUATION_HF_CUTOFF, - ROOM_PARAM_ATTENUATION_HF_FLOOR_DB, - ROOM_PARAM_ATTENUATION_HF_RATIO_EXP, - ROOM_PARAM_ATTENUATION_REVERB_SCALE, - ROOM_PARAM_MAX - }; - - virtual void room_set_param(RID p_room, RoomParam p_param, float p_value)=0; - virtual float room_get_param(RID p_room, RoomParam p_param) const=0; - - enum RoomReverb { - ROOM_REVERB_SMALL, - ROOM_REVERB_MEDIUM, - ROOM_REVERB_LARGE, - ROOM_REVERB_HALL - }; - - virtual void room_set_reverb(RID p_room, RoomReverb p_reverb)=0; - virtual RoomReverb room_get_reverb(RID p_room) const=0; - - virtual void room_set_level(RID p_room, int p_level)=0; - virtual int room_get_level(RID p_room) const=0; - - //useful for underwater or rooms with very strange conditions - virtual void room_set_force_params_to_all_sources(RID p_room, bool p_force)=0; - virtual bool room_is_forcing_params_to_all_sources(RID p_room) const=0; - - /* SOURCE */ - - virtual RID source_create(RID p_space)=0; - - virtual void source_set_transform(RID p_source, const Transform& p_transform)=0; - virtual Transform source_get_transform(RID p_source) const=0; - - virtual void source_set_polyphony(RID p_source,int p_voice_count)=0; - virtual int source_get_polyphony(RID p_source) const=0; - - enum SourceParam { - - SOURCE_PARAM_VOLUME_DB, - SOURCE_PARAM_PITCH_SCALE, - SOURCE_PARAM_ATTENUATION_MIN_DISTANCE, - SOURCE_PARAM_ATTENUATION_MAX_DISTANCE, - SOURCE_PARAM_ATTENUATION_DISTANCE_EXP, - SOURCE_PARAM_EMISSION_CONE_DEGREES, - SOURCE_PARAM_EMISSION_CONE_ATTENUATION_DB, - SOURCE_PARAM_MAX - }; - - virtual void source_set_param(RID p_source, SourceParam p_param, float p_value)=0; - virtual float source_get_param(RID p_source, SourceParam p_param) const=0; - - virtual void source_set_audio_stream(RID p_source, AudioServer::AudioStream *p_stream)=0; //null to unset - virtual SourceVoiceID source_play_sample(RID p_source, RID p_sample, int p_mix_rate, int p_voice=SOURCE_NEXT_VOICE)=0; - //voices - virtual void source_voice_set_pitch_scale(RID p_source,SourceVoiceID p_voice, float p_pitch_scale)=0; - virtual void source_voice_set_volume_scale_db(RID p_source,SourceVoiceID p_voice, float p_volume_db)=0; - - virtual bool source_is_voice_active(RID p_source,SourceVoiceID p_voice) const=0; - virtual void source_stop_voice(RID p_source,SourceVoiceID p_voice)=0; - - /* LISTENER */ - - enum ListenerParam { - - LISTENER_PARAM_VOLUME_SCALE_DB, - LISTENER_PARAM_PITCH_SCALE, - LISTENER_PARAM_ATTENUATION_SCALE, - LISTENER_PARAM_RECEPTION_CONE_DEGREES, - LISTENER_PARAM_RECEPTION_CONE_ATTENUATION_DB, - LISTENER_PARAM_MAX - }; - - virtual RID listener_create()=0; - virtual void listener_set_space(RID p_listener, RID p_space)=0; - - virtual void listener_set_transform(RID p_listener, const Transform& p_transform)=0; - virtual Transform listener_get_transform(RID p_listener) const=0; - - virtual void listener_set_param(RID p_listener, ListenerParam p_param, float p_value)=0; - virtual float listener_get_param(RID p_listener, ListenerParam p_param) const=0; - - /* MISC */ - - virtual void free(RID p_id)=0; - - virtual void init()=0; - virtual void update(float p_delta)=0; - virtual void finish()=0; - - static SpatialSoundServer *get_singleton(); - - SpatialSoundServer(); -}; - -#endif // SPATIAL_SOUND_SERVER_H diff --git a/servers/visual/SCsub b/servers/visual/SCsub index d31af2c1c4..ccc76e823f 100644 --- a/servers/visual/SCsub +++ b/servers/visual/SCsub @@ -1,5 +1,7 @@ +#!/usr/bin/env python + Import('env') -env.add_source_files(env.servers_sources,"*.cpp") +env.add_source_files(env.servers_sources, "*.cpp") Export('env') diff --git a/servers/visual/particle_system_sw.cpp b/servers/visual/particle_system_sw.cpp deleted file mode 100644 index 07cc6d8a2a..0000000000 --- a/servers/visual/particle_system_sw.cpp +++ /dev/null @@ -1,412 +0,0 @@ -/*************************************************************************/ -/* particle_system_sw.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "particle_system_sw.h" -#include "sort.h" - - -ParticleSystemSW::ParticleSystemSW() { - - amount=8; - emitting=true; - - for (int i=0;i<VS::PARTICLE_VAR_MAX;i++) { - particle_randomness[i]=0.0; - } - - particle_vars[VS::PARTICLE_LIFETIME]=2.0;// - particle_vars[VS::PARTICLE_SPREAD]=0.2;// - particle_vars[VS::PARTICLE_GRAVITY]=9.8;// - particle_vars[VS::PARTICLE_LINEAR_VELOCITY]=0.2;// - particle_vars[VS::PARTICLE_ANGULAR_VELOCITY]=0.0;// - particle_vars[VS::PARTICLE_LINEAR_ACCELERATION]=0.0;// - particle_vars[VS::PARTICLE_RADIAL_ACCELERATION]=0.0;// - particle_vars[VS::PARTICLE_TANGENTIAL_ACCELERATION]=1.0;// - particle_vars[VS::PARTICLE_DAMPING]=0.0;// - particle_vars[VS::PARTICLE_INITIAL_SIZE]=1.0; - particle_vars[VS::PARTICLE_FINAL_SIZE]=0.8; - particle_vars[VS::PARTICLE_HEIGHT]=1; - particle_vars[VS::PARTICLE_HEIGHT_SPEED_SCALE]=1; - - height_from_velocity=false; - local_coordinates=false; - - particle_vars[VS::PARTICLE_INITIAL_ANGLE]=0.0;// - - gravity_normal=Vector3(0,-1.0,0); - //emission_half_extents=Vector3(0.1,0.1,0.1); - emission_half_extents=Vector3(1,1,1); - color_phase_count=0; - color_phases[0].pos=0.0; - color_phases[0].color=Color(1.0,0.0,0.0); - visibility_aabb=AABB(Vector3(-64,-64,-64),Vector3(128,128,128)); - - attractor_count=0; - -} - - -ParticleSystemSW::~ParticleSystemSW() -{ -} - - -#define DEFAULT_SEED 1234567 - -_FORCE_INLINE_ static float _rand_from_seed(uint32_t *seed) { - - uint32_t k; - uint32_t s = (*seed); - if (s == 0) - s = 0x12345987; - k = s / 127773; - s = 16807 * (s - k * 127773) - 2836 * k; - if (s < 0) - s += 2147483647; - (*seed) = s; - - float v=((float)((*seed) & 0xFFFFF))/(float)0xFFFFF; - v=v*2.0-1.0; - return v; -} - -_FORCE_INLINE_ static uint32_t _irand_from_seed(uint32_t *seed) { - - uint32_t k; - uint32_t s = (*seed); - if (s == 0) - s = 0x12345987; - k = s / 127773; - s = 16807 * (s - k * 127773) - 2836 * k; - if (s < 0) - s += 2147483647; - (*seed) = s; - - return s; -} - -void ParticleSystemProcessSW::process(const ParticleSystemSW *p_system,const Transform& p_transform,float p_time) { - - valid=false; - if (p_system->amount<=0) { - ERR_EXPLAIN("Invalid amount of particles: "+itos(p_system->amount)); - ERR_FAIL_COND(p_system->amount<=0); - } - if (p_system->attractor_count<0 || p_system->attractor_count>VS::MAX_PARTICLE_ATTRACTORS) { - ERR_EXPLAIN("Invalid amount of particle attractors."); - ERR_FAIL_COND(p_system->attractor_count<0 || p_system->attractor_count>VS::MAX_PARTICLE_ATTRACTORS); - } - float lifetime = p_system->particle_vars[VS::PARTICLE_LIFETIME]; - if (lifetime<CMP_EPSILON) { - ERR_EXPLAIN("Particle system lifetime too small."); - ERR_FAIL_COND(lifetime<CMP_EPSILON); - } - valid=true; - int particle_count=MIN(p_system->amount,ParticleSystemSW::MAX_PARTICLES);; - - - int emission_point_count = p_system->emission_points.size(); - DVector<Vector3>::Read r; - if (emission_point_count) - r=p_system->emission_points.read(); - - if (particle_count!=particle_data.size()) { - - //clear the whole system if particle amount changed - particle_data.clear(); - particle_data.resize(p_system->amount); - particle_system_time=0; - } - - float next_time = particle_system_time+p_time; - - if (next_time > lifetime) - next_time=Math::fmod(next_time,lifetime); - - - ParticleData *pdata=&particle_data[0]; - Vector3 attractor_positions[VS::MAX_PARTICLE_ATTRACTORS]; - - for(int i=0;i<p_system->attractor_count;i++) { - - attractor_positions[i]=p_transform.xform(p_system->attractors[i].pos); - } - - - for(int i=0;i<particle_count;i++) { - - ParticleData &p=pdata[i]; - - float restart_time = (i * lifetime / p_system->amount); - - bool restart=false; - - if ( next_time < particle_system_time ) { - - if (restart_time > particle_system_time || restart_time < next_time ) - restart=true; - - } else if (restart_time > particle_system_time && restart_time < next_time ) { - restart=true; - } - - if (restart) { - - - if (p_system->emitting) { - if (emission_point_count==0) { //use AABB - if (p_system->local_coordinates) - p.pos = p_system->emission_half_extents * Vector3( _rand_from_seed(&rand_seed), _rand_from_seed(&rand_seed), _rand_from_seed(&rand_seed) ); - else - p.pos = p_transform.xform( p_system->emission_half_extents * Vector3( _rand_from_seed(&rand_seed), _rand_from_seed(&rand_seed), _rand_from_seed(&rand_seed) ) ); - } else { - //use preset positions - if (p_system->local_coordinates) - p.pos = r[_irand_from_seed(&rand_seed)%emission_point_count]; - else - p.pos = p_transform.xform( r[_irand_from_seed(&rand_seed)%emission_point_count] ); - } - - - float angle1 = _rand_from_seed(&rand_seed)*p_system->particle_vars[VS::PARTICLE_SPREAD]*Math_PI; - float angle2 = _rand_from_seed(&rand_seed)*20.0*Math_PI; // make it more random like - - Vector3 rot_xz=Vector3( Math::sin(angle1), 0.0, Math::cos(angle1) ); - Vector3 rot = Vector3( Math::cos(angle2)*rot_xz.x,Math::sin(angle2)*rot_xz.x, rot_xz.z); - - p.vel=(rot*p_system->particle_vars[VS::PARTICLE_LINEAR_VELOCITY]+rot*p_system->particle_randomness[VS::PARTICLE_LINEAR_VELOCITY]*_rand_from_seed(&rand_seed)); - if (!p_system->local_coordinates) - p.vel=p_transform.basis.xform( p.vel ); - - p.vel+=p_system->emission_base_velocity; - - p.rot=p_system->particle_vars[VS::PARTICLE_INITIAL_ANGLE]+p_system->particle_randomness[VS::PARTICLE_INITIAL_ANGLE]*_rand_from_seed(&rand_seed); - p.active=true; - for(int r=0;r<PARTICLE_RANDOM_NUMBERS;r++) - p.random[r]=_rand_from_seed(&rand_seed); - - } else { - - p.pos=Vector3(); - p.rot=0; - p.vel=Vector3(); - p.active=false; - } - - } else { - - if (!p.active) - continue; - - Vector3 force; - //apply gravity - force=p_system->gravity_normal * (p_system->particle_vars[VS::PARTICLE_GRAVITY]+(p_system->particle_randomness[VS::PARTICLE_GRAVITY]*p.random[0])); - //apply linear acceleration - force+=p.vel.normalized() * (p_system->particle_vars[VS::PARTICLE_LINEAR_ACCELERATION]+p_system->particle_randomness[VS::PARTICLE_LINEAR_ACCELERATION]*p.random[1]); - //apply radial acceleration - Vector3 org; - if (!p_system->local_coordinates) - org=p_transform.origin; - force+=(p.pos-org).normalized() * (p_system->particle_vars[VS::PARTICLE_RADIAL_ACCELERATION]+p_system->particle_randomness[VS::PARTICLE_RADIAL_ACCELERATION]*p.random[2]); - //apply tangential acceleration - force+=(p.pos-org).cross(p_system->gravity_normal).normalized() * (p_system->particle_vars[VS::PARTICLE_TANGENTIAL_ACCELERATION]+p_system->particle_randomness[VS::PARTICLE_TANGENTIAL_ACCELERATION]*p.random[3]); - //apply attractor forces - for(int a=0;a<p_system->attractor_count;a++) { - - force+=(p.pos-attractor_positions[a]).normalized() * p_system->attractors[a].force; - } - - - p.vel+=force * p_time; - if (p_system->particle_vars[VS::PARTICLE_DAMPING]) { - - float v = p.vel.length(); - float damp = p_system->particle_vars[VS::PARTICLE_DAMPING] + p_system->particle_vars[VS::PARTICLE_DAMPING] * p_system->particle_randomness[VS::PARTICLE_DAMPING]; - v -= damp * p_time; - if (v<0) { - p.vel=Vector3(); - } else { - p.vel=p.vel.normalized() * v; - } - - } - p.rot+=(p_system->particle_vars[VS::PARTICLE_ANGULAR_VELOCITY]+p_system->particle_randomness[VS::PARTICLE_ANGULAR_VELOCITY]*p.random[4]) *p_time; - p.pos+=p.vel * p_time; - } - } - - particle_system_time=Math::fmod( particle_system_time+p_time, lifetime ); - - -} - -ParticleSystemProcessSW::ParticleSystemProcessSW() { - - particle_system_time=0; - rand_seed=1234567; - valid=false; -} - - -struct _ParticleSorterSW { - - - _FORCE_INLINE_ bool operator()(const ParticleSystemDrawInfoSW::ParticleDrawInfo *p_a,const ParticleSystemDrawInfoSW::ParticleDrawInfo *p_b) const { - - return p_a->d > p_b->d; // draw from further away to closest - } -}; - -void ParticleSystemDrawInfoSW::prepare(const ParticleSystemSW *p_system,const ParticleSystemProcessSW *p_process,const Transform& p_system_transform,const Transform& p_camera_transform) { - - ERR_FAIL_COND(p_process->particle_data.size() != p_system->amount); - ERR_FAIL_COND(p_system->amount<=0 || p_system->amount>=ParticleSystemSW::MAX_PARTICLES); - - const ParticleSystemProcessSW::ParticleData *pdata=&p_process->particle_data[0]; - float time_pos=p_process->particle_system_time/p_system->particle_vars[VS::PARTICLE_LIFETIME]; - - ParticleSystemSW::ColorPhase cphase[VS::MAX_PARTICLE_COLOR_PHASES]; - - float last=-1; - int col_count=0; - - for(int i=0;i<p_system->color_phase_count;i++) { - - if (p_system->color_phases[i].pos<=last) - break; - cphase[i]=p_system->color_phases[i]; - col_count++; - } - - - - - - Vector3 camera_z_axis = p_camera_transform.basis.get_axis(2); - - for(int i=0;i<p_system->amount;i++) { - - ParticleDrawInfo &pdi=draw_info[i]; - pdi.data=&pdata[i]; - pdi.transform.origin=pdi.data->pos; - if (p_system->local_coordinates) - pdi.transform.origin=p_system_transform.xform(pdi.transform.origin); - - pdi.d=-camera_z_axis.dot(pdi.transform.origin); - - // adjust particle size, color and rotation - - float time = ((float)i / p_system->amount); - if (time<time_pos) - time=time_pos-time; - else - time=(1.0-time)+time_pos; - - Vector3 up=p_camera_transform.basis.get_axis(1); // up determines the rotation - float up_scale=1.0; - - if (p_system->height_from_velocity) { - - Vector3 veld = pdi.data->vel; - Vector3 cam_z = camera_z_axis.normalized(); - float vc = Math::abs(veld.normalized().dot(cam_z)); - - if (vc<(1.0-CMP_EPSILON)) { - up = Plane(cam_z,0).project(veld).normalized(); - float h = p_system->particle_vars[VS::PARTICLE_HEIGHT]+p_system->particle_randomness[VS::PARTICLE_HEIGHT]*pdi.data->random[7]; - float velh = veld.length(); - h+=velh*(p_system->particle_vars[VS::PARTICLE_HEIGHT_SPEED_SCALE]+p_system->particle_randomness[VS::PARTICLE_HEIGHT_SPEED_SCALE]*pdi.data->random[7]); - - - up_scale=Math::lerp(1.0,h,(1.0-vc)); - } - - } else if (pdi.data->rot) { - - up.rotate(camera_z_axis,pdi.data->rot); - } - - { - // matrix - Vector3 v_z = (p_camera_transform.origin-pdi.transform.origin).normalized(); -// Vector3 v_z = (p_camera_transform.origin-pdi.data->pos).normalized(); - Vector3 v_y = up; - Vector3 v_x = v_y.cross(v_z); - v_y = v_z.cross(v_x); - v_x.normalize(); - v_y.normalize(); - - - float initial_scale, final_scale; - initial_scale = p_system->particle_vars[VS::PARTICLE_INITIAL_SIZE]+p_system->particle_randomness[VS::PARTICLE_INITIAL_SIZE]*pdi.data->random[5]; - final_scale = p_system->particle_vars[VS::PARTICLE_FINAL_SIZE]+p_system->particle_randomness[VS::PARTICLE_FINAL_SIZE]*pdi.data->random[6]; - float scale = initial_scale + time * (final_scale - initial_scale); - - pdi.transform.basis.set_axis(0,v_x * scale); - pdi.transform.basis.set_axis(1,v_y * scale * up_scale); - pdi.transform.basis.set_axis(2,v_z * scale); - } - - - - int cpos=0; - - while(cpos<col_count) { - - if (cphase[cpos].pos > time) - break; - cpos++; - } - - cpos--; - - - if (cpos==-1) - pdi.color=Color(1,1,1,1); - else { - if (cpos==col_count-1) - pdi.color=cphase[cpos].color; - else { - float diff = (cphase[cpos+1].pos-cphase[cpos].pos); - if (diff>0) - pdi.color=cphase[cpos].color.linear_interpolate(cphase[cpos+1].color, (time - cphase[cpos].pos) / diff ); - else - pdi.color=cphase[cpos+1].color; - } - } - - - draw_info_order[i]=&pdi; - - } - - - SortArray<ParticleDrawInfo*,_ParticleSorterSW> particle_sort; - particle_sort.sort(&draw_info_order[0],p_system->amount); - -} diff --git a/servers/visual/particle_system_sw.h b/servers/visual/particle_system_sw.h deleted file mode 100644 index 4edcecaaa9..0000000000 --- a/servers/visual/particle_system_sw.h +++ /dev/null @@ -1,131 +0,0 @@ -/*************************************************************************/ -/* particle_system_sw.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#ifndef PARTICLE_SYSTEM_SW_H -#define PARTICLE_SYSTEM_SW_H - -/** - @author Juan Linietsky <reduzio@gmail.com> -*/ - -#include "servers/visual_server.h" - -struct ParticleSystemSW { - enum { - - MAX_PARTICLES=1024 - }; - - float particle_vars[VS::PARTICLE_VAR_MAX]; - float particle_randomness[VS::PARTICLE_VAR_MAX]; - - Vector3 emission_half_extents; - DVector<Vector3> emission_points; - Vector3 gravity_normal; - Vector3 emission_base_velocity; - int amount; - bool emitting; - bool height_from_velocity; - AABB visibility_aabb; - bool sort; - bool local_coordinates; - - struct ColorPhase { - - float pos; - Color color; - ColorPhase() { pos=1.0; color=Color(0.0,0.0,1.0,1.0); } - }; - - int color_phase_count; - ColorPhase color_phases[VS::MAX_PARTICLE_COLOR_PHASES]; - - - struct Attractor { - - Vector3 pos; - float force; - }; - - int attractor_count; - Attractor attractors[VS::MAX_PARTICLE_ATTRACTORS]; - - - ParticleSystemSW(); - ~ParticleSystemSW(); - -}; - - -struct ParticleSystemProcessSW { - - enum { - PARTICLE_RANDOM_NUMBERS = 8, - }; - - struct ParticleData { - - Vector3 pos; - Vector3 vel; - float rot; - bool active; - float random[PARTICLE_RANDOM_NUMBERS]; - - ParticleData() { active=0; rot=0; } - }; - - - bool valid; - float particle_system_time; - uint32_t rand_seed; - Vector<ParticleData> particle_data; - - void process(const ParticleSystemSW *p_system,const Transform& p_transform,float p_time); - - ParticleSystemProcessSW(); -}; - -struct ParticleSystemDrawInfoSW { - - struct ParticleDrawInfo { - - const ParticleSystemProcessSW::ParticleData *data; - float d; - Transform transform; - Color color; - - }; - - ParticleDrawInfo draw_info[ParticleSystemSW::MAX_PARTICLES]; - ParticleDrawInfo *draw_info_order[ParticleSystemSW::MAX_PARTICLES]; - - void prepare(const ParticleSystemSW *p_system,const ParticleSystemProcessSW *p_process,const Transform& p_system_transform,const Transform& p_camera_transform); - -}; - -#endif diff --git a/servers/visual/rasterizer.cpp b/servers/visual/rasterizer.cpp index 32f5b80e55..ba85f92e37 100644 --- a/servers/visual/rasterizer.cpp +++ b/servers/visual/rasterizer.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -30,6 +30,23 @@ #include "print_string.h" #include "os/os.h" + +Rasterizer* (*Rasterizer::_create_func)()=NULL; + +Rasterizer *Rasterizer::create() { + + return _create_func(); +} + +RasterizerStorage*RasterizerStorage::base_signleton=NULL; + +RasterizerStorage::RasterizerStorage() { + + base_signleton=this; +} + +#if 0 + RID Rasterizer::create_default_material() { return material_create(); @@ -38,10 +55,10 @@ RID Rasterizer::create_default_material() { /* Fixed MAterial SHADER API */ -RID Rasterizer::_create_shader(const FixedMaterialShaderKey& p_key) { +RID Rasterizer::_create_shader(const FixedSpatialMaterialShaderKey& p_key) { ERR_FAIL_COND_V(!p_key.valid,RID()); - Map<FixedMaterialShaderKey,FixedMaterialShader>::Element *E=fixed_material_shaders.find(p_key); + Map<FixedSpatialMaterialShaderKey,FixedSpatialMaterialShader>::Element *E=fixed_material_shaders.find(p_key); if (E) { E->get().refcount++; @@ -50,7 +67,7 @@ RID Rasterizer::_create_shader(const FixedMaterialShaderKey& p_key) { uint64_t t = OS::get_singleton()->get_ticks_usec(); - FixedMaterialShader fms; + FixedSpatialMaterialShader fms; fms.refcount=1; fms.shader=shader_create(); @@ -239,7 +256,7 @@ RID Rasterizer::_create_shader(const FixedMaterialShaderKey& p_key) { vcode+="uniform float "+_fixed_material_point_size_name+";\n"; vcode+="POINT_SIZE="+_fixed_material_point_size_name+";\n"; -// vcode+="POINT_SIZE=10.0;\n"; + //vcode+="POINT_SIZE=10.0;\n"; } String lcode; @@ -290,21 +307,18 @@ RID Rasterizer::_create_shader(const FixedMaterialShaderKey& p_key) { //print_line("**VERTEX SHADER GENERATED code: \n"+vcode); - double tf = (OS::get_singleton()->get_ticks_usec()-t)/1000.0; -// print_line("generate: "+rtos(tf)); - shader_set_code(fms.shader,vcode,code,lcode,0,0); fixed_material_shaders[p_key]=fms; return fms.shader; } -void Rasterizer::_free_shader(const FixedMaterialShaderKey& p_key) { +void Rasterizer::_free_shader(const FixedSpatialMaterialShaderKey& p_key) { if (p_key.valid==0) return; //not a valid key - Map<FixedMaterialShaderKey,FixedMaterialShader>::Element *E=fixed_material_shaders.find(p_key); + Map<FixedSpatialMaterialShaderKey,FixedSpatialMaterialShader>::Element *E=fixed_material_shaders.find(p_key); ERR_FAIL_COND(!E); E->get().refcount--; @@ -316,12 +330,12 @@ void Rasterizer::_free_shader(const FixedMaterialShaderKey& p_key) { } -void Rasterizer::fixed_material_set_flag(RID p_material, VS::FixedMaterialFlags p_flag, bool p_enabled) { +void Rasterizer::fixed_material_set_flag(RID p_material, VS::FixedSpatialMaterialFlags p_flag, bool p_enabled) { - Map<RID,FixedMaterial*>::Element *E = fixed_materials.find(p_material); + Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material); ERR_FAIL_COND(!E); - FixedMaterial &fm=*E->get(); + FixedSpatialMaterial &fm=*E->get(); switch(p_flag) { @@ -337,11 +351,11 @@ void Rasterizer::fixed_material_set_flag(RID p_material, VS::FixedMaterialFlags } -bool Rasterizer::fixed_material_get_flag(RID p_material, VS::FixedMaterialFlags p_flag) const{ +bool Rasterizer::fixed_material_get_flag(RID p_material, VS::FixedSpatialMaterialFlags p_flag) const{ - const Map<RID,FixedMaterial*>::Element *E = fixed_materials.find(p_material); + const Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material); ERR_FAIL_COND_V(!E,false); - const FixedMaterial &fm=*E->get(); + const FixedSpatialMaterial &fm=*E->get(); switch(p_flag) { case VS::FIXED_MATERIAL_FLAG_USE_ALPHA: return fm.use_alpha;; break; @@ -360,8 +374,8 @@ bool Rasterizer::fixed_material_get_flag(RID p_material, VS::FixedMaterialFlags RID Rasterizer::fixed_material_create() { RID mat = material_create(); - fixed_materials[mat]=memnew( FixedMaterial() ); - FixedMaterial &fm=*fixed_materials[mat]; + fixed_materials[mat]=memnew( FixedSpatialMaterial() ); + FixedSpatialMaterial &fm=*fixed_materials[mat]; fm.self=mat; fm.get_key(); material_set_flag(mat,VS::MATERIAL_FLAG_COLOR_ARRAY_SRGB,true); @@ -377,11 +391,11 @@ RID Rasterizer::fixed_material_create() { -void Rasterizer::fixed_material_set_parameter(RID p_material, VS::FixedMaterialParam p_parameter, const Variant& p_value){ +void Rasterizer::fixed_material_set_parameter(RID p_material, VS::FixedSpatialMaterialParam p_parameter, const Variant& p_value){ - Map<RID,FixedMaterial*>::Element *E = fixed_materials.find(p_material); + Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material); ERR_FAIL_COND(!E); - FixedMaterial &fm=*E->get(); + FixedSpatialMaterial &fm=*E->get(); RID material=E->key(); ERR_FAIL_INDEX(p_parameter,VS::FIXED_MATERIAL_PARAM_MAX); @@ -404,24 +418,24 @@ void Rasterizer::fixed_material_set_parameter(RID p_material, VS::FixedMaterialP } -Variant Rasterizer::fixed_material_get_parameter(RID p_material,VS::FixedMaterialParam p_parameter) const{ +Variant Rasterizer::fixed_material_get_parameter(RID p_material,VS::FixedSpatialMaterialParam p_parameter) const{ - const Map<RID,FixedMaterial*>::Element *E = fixed_materials.find(p_material); + const Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material); ERR_FAIL_COND_V(!E,Variant()); - const FixedMaterial &fm=*E->get(); + const FixedSpatialMaterial &fm=*E->get(); ERR_FAIL_INDEX_V(p_parameter,VS::FIXED_MATERIAL_PARAM_MAX,Variant()); return fm.param[p_parameter]; } -void Rasterizer::fixed_material_set_texture(RID p_material,VS::FixedMaterialParam p_parameter, RID p_texture){ +void Rasterizer::fixed_material_set_texture(RID p_material,VS::FixedSpatialMaterialParam p_parameter, RID p_texture){ - Map<RID,FixedMaterial*>::Element *E = fixed_materials.find(p_material); + Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material); if (!E) { print_line("Not found: "+itos(p_material.get_id())); } ERR_FAIL_COND(!E); - FixedMaterial &fm=*E->get(); + FixedSpatialMaterial &fm=*E->get(); ERR_FAIL_INDEX(p_parameter,VS::FIXED_MATERIAL_PARAM_MAX); @@ -436,22 +450,22 @@ void Rasterizer::fixed_material_set_texture(RID p_material,VS::FixedMaterialPara } -RID Rasterizer::fixed_material_get_texture(RID p_material,VS::FixedMaterialParam p_parameter) const{ +RID Rasterizer::fixed_material_get_texture(RID p_material,VS::FixedSpatialMaterialParam p_parameter) const{ - const Map<RID,FixedMaterial*>::Element *E = fixed_materials.find(p_material); + const Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material); ERR_FAIL_COND_V(!E,RID()); - const FixedMaterial &fm=*E->get(); + const FixedSpatialMaterial &fm=*E->get(); ERR_FAIL_INDEX_V(p_parameter,VS::FIXED_MATERIAL_PARAM_MAX,RID()); return fm.texture[p_parameter]; } -void Rasterizer::fixed_material_set_texcoord_mode(RID p_material,VS::FixedMaterialParam p_parameter, VS::FixedMaterialTexCoordMode p_mode) { +void Rasterizer::fixed_material_set_texcoord_mode(RID p_material,VS::FixedSpatialMaterialParam p_parameter, VS::FixedSpatialMaterialTexCoordMode p_mode) { - Map<RID,FixedMaterial*>::Element *E = fixed_materials.find(p_material); + Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material); ERR_FAIL_COND(!E); - FixedMaterial &fm=*E->get(); + FixedSpatialMaterial &fm=*E->get(); ERR_FAIL_INDEX(p_parameter,VS::FIXED_MATERIAL_PARAM_MAX); fm.get_key(); @@ -463,11 +477,11 @@ void Rasterizer::fixed_material_set_texcoord_mode(RID p_material,VS::FixedMateri } -VS::FixedMaterialTexCoordMode Rasterizer::fixed_material_get_texcoord_mode(RID p_material,VS::FixedMaterialParam p_parameter) const { +VS::FixedSpatialMaterialTexCoordMode Rasterizer::fixed_material_get_texcoord_mode(RID p_material,VS::FixedSpatialMaterialParam p_parameter) const { - const Map<RID,FixedMaterial*>::Element *E = fixed_materials.find(p_material); + const Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material); ERR_FAIL_COND_V(!E,VS::FIXED_MATERIAL_TEXCOORD_UV); - const FixedMaterial &fm=*E->get(); + const FixedSpatialMaterial &fm=*E->get(); ERR_FAIL_INDEX_V(p_parameter,VS::FIXED_MATERIAL_PARAM_MAX,VS::FIXED_MATERIAL_TEXCOORD_UV); return fm.texture_tc[p_parameter]; @@ -475,9 +489,9 @@ VS::FixedMaterialTexCoordMode Rasterizer::fixed_material_get_texcoord_mode(RID p void Rasterizer::fixed_material_set_uv_transform(RID p_material,const Transform& p_transform) { - Map<RID,FixedMaterial*>::Element *E = fixed_materials.find(p_material); + Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material); ERR_FAIL_COND(!E); - FixedMaterial &fm=*E->get(); + FixedSpatialMaterial &fm=*E->get(); RID material=E->key(); VS::get_singleton()->material_set_param(material,_fixed_material_uv_xform_name,p_transform); @@ -490,18 +504,18 @@ void Rasterizer::fixed_material_set_uv_transform(RID p_material,const Transform& Transform Rasterizer::fixed_material_get_uv_transform(RID p_material) const { - const Map<RID,FixedMaterial*>::Element *E = fixed_materials.find(p_material); + const Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material); ERR_FAIL_COND_V(!E,Transform()); - const FixedMaterial &fm=*E->get(); + const FixedSpatialMaterial &fm=*E->get(); return fm.uv_xform; } -void Rasterizer::fixed_material_set_light_shader(RID p_material,VS::FixedMaterialLightShader p_shader) { +void Rasterizer::fixed_material_set_light_shader(RID p_material,VS::FixedSpatialMaterialLightShader p_shader) { - Map<RID,FixedMaterial*>::Element *E = fixed_materials.find(p_material); + Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material); ERR_FAIL_COND(!E); - FixedMaterial &fm=*E->get(); + FixedSpatialMaterial &fm=*E->get(); fm.light_shader=p_shader; @@ -510,20 +524,20 @@ void Rasterizer::fixed_material_set_light_shader(RID p_material,VS::FixedMateria } -VS::FixedMaterialLightShader Rasterizer::fixed_material_get_light_shader(RID p_material) const { +VS::FixedSpatialMaterialLightShader Rasterizer::fixed_material_get_light_shader(RID p_material) const { - const Map<RID,FixedMaterial*>::Element *E = fixed_materials.find(p_material); + const Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material); ERR_FAIL_COND_V(!E,VS::FIXED_MATERIAL_LIGHT_SHADER_LAMBERT); - const FixedMaterial &fm=*E->get(); + const FixedSpatialMaterial &fm=*E->get(); return fm.light_shader; } void Rasterizer::fixed_material_set_point_size(RID p_material,float p_size) { - Map<RID,FixedMaterial*>::Element *E = fixed_materials.find(p_material); + Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material); ERR_FAIL_COND(!E); - FixedMaterial &fm=*E->get(); + FixedSpatialMaterial &fm=*E->get(); RID material=E->key(); VS::get_singleton()->material_set_param(material,_fixed_material_point_size_name,p_size); @@ -535,9 +549,9 @@ void Rasterizer::fixed_material_set_point_size(RID p_material,float p_size) { float Rasterizer::fixed_material_get_point_size(RID p_material) const{ - const Map<RID,FixedMaterial*>::Element *E = fixed_materials.find(p_material); + const Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material); ERR_FAIL_COND_V(!E,1.0); - const FixedMaterial &fm=*E->get(); + const FixedSpatialMaterial &fm=*E->get(); return fm.point_size; @@ -548,9 +562,9 @@ void Rasterizer::_update_fixed_materials() { while(fixed_material_dirty_list.first()) { - FixedMaterial &fm=*fixed_material_dirty_list.first()->self(); + FixedSpatialMaterial &fm=*fixed_material_dirty_list.first()->self(); - FixedMaterialShaderKey new_key = fm.get_key(); + FixedSpatialMaterialShaderKey new_key = fm.get_key(); if (new_key.key!=fm.current_key.key) { _free_shader(fm.current_key); @@ -580,7 +594,7 @@ void Rasterizer::_update_fixed_materials() { void Rasterizer::_free_fixed_material(const RID& p_material) { - Map<RID,FixedMaterial*>::Element *E = fixed_materials.find(p_material); + Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material); if (E) { @@ -623,7 +637,7 @@ Rasterizer::Rasterizer() { draw_viewport_func=NULL; - ERR_FAIL_COND( sizeof(FixedMaterialShaderKey)!=4); + ERR_FAIL_COND( sizeof(FixedSpatialMaterialShaderKey)!=4); } @@ -639,3 +653,5 @@ RID Rasterizer::create_overdraw_debug_material() { return mat; } + +#endif diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h index 8cc567072f..dd22986865 100644 --- a/servers/visual/rasterizer.h +++ b/servers/visual/rasterizer.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -29,6 +29,932 @@ #ifndef RASTERIZER_H #define RASTERIZER_H + +#include "servers/visual_server.h" +#include "camera_matrix.h" + +#include "self_list.h" + + +class RasterizerScene { +public: + + /* SHADOW ATLAS API */ + + virtual RID shadow_atlas_create()=0; + virtual void shadow_atlas_set_size(RID p_atlas,int p_size)=0; + virtual void shadow_atlas_set_quadrant_subdivision(RID p_atlas,int p_quadrant,int p_subdivision)=0; + virtual bool shadow_atlas_update_light(RID p_atlas,RID p_light_intance,float p_coverage,uint64_t p_light_version)=0; + + virtual int get_directional_light_shadow_size(RID p_light_intance)=0; + virtual void set_directional_shadow_count(int p_count)=0; + + /* ENVIRONMENT API */ + + virtual RID environment_create()=0; + + virtual void environment_set_background(RID p_env,VS::EnvironmentBG p_bg)=0; + virtual void environment_set_skybox(RID p_env,RID p_skybox)=0; + virtual void environment_set_skybox_scale(RID p_env,float p_scale)=0; + virtual void environment_set_bg_color(RID p_env,const Color& p_color)=0; + virtual void environment_set_bg_energy(RID p_env,float p_energy)=0; + virtual void environment_set_canvas_max_layer(RID p_env,int p_max_layer)=0; + virtual void environment_set_ambient_light(RID p_env,const Color& p_color,float p_energy=1.0,float p_skybox_contribution=0.0)=0; + + virtual void environment_set_dof_blur_near(RID p_env,bool p_enable,float p_distance,float p_transition,float p_far_amount,VS::EnvironmentDOFBlurQuality p_quality)=0; + virtual void environment_set_dof_blur_far(RID p_env,bool p_enable,float p_distance,float p_transition,float p_far_amount,VS::EnvironmentDOFBlurQuality p_quality)=0; + virtual void environment_set_glow(RID p_env,bool p_enable,int p_level_flags,float p_intensity,float p_strength,float p_bloom_treshold,VS::EnvironmentGlowBlendMode p_blend_mode,float p_hdr_bleed_treshold,float p_hdr_bleed_scale,bool p_bicubic_upscale)=0; + virtual void environment_set_fog(RID p_env,bool p_enable,float p_begin,float p_end,RID p_gradient_texture)=0; + + virtual void environment_set_ssr(RID p_env,bool p_enable, int p_max_steps,float p_accel,float p_fade,float p_depth_tolerance,bool p_smooth,bool p_roughness)=0; + virtual void environment_set_ssao(RID p_env,bool p_enable, float p_radius, float p_intensity, float p_radius2, float p_intensity2, float p_bias, float p_light_affect,const Color &p_color,bool p_blur)=0; + + virtual void environment_set_tonemap(RID p_env,VS::EnvironmentToneMapper p_tone_mapper,float p_exposure,float p_white,bool p_auto_exposure,float p_min_luminance,float p_max_luminance,float p_auto_exp_speed,float p_auto_exp_scale)=0; + + virtual void environment_set_adjustment(RID p_env,bool p_enable,float p_brightness,float p_contrast,float p_saturation,RID p_ramp)=0; + + struct InstanceBase : RID_Data { + + VS::InstanceType base_type; + RID base; + + RID skeleton; + RID material_override; + + Transform transform; + + int depth_layer; + uint32_t layer_mask; + + //RID sampled_light; + + Vector<RID> materials; + Vector<RID> light_instances; + Vector<RID> reflection_probe_instances; + Vector<RID> gi_probe_instances; + + Vector<float> blend_values; + + //BakedLightData *baked_light; + VS::ShadowCastingSetting cast_shadows; + //Transform *baked_light_octree_xform; + //int baked_lightmap_id; + + bool mirror :8; + bool depth_scale :8; + bool billboard :8; + bool billboard_y :8; + bool receive_shadows : 8; + bool visible : 8; + + float depth; //used for sorting + + SelfList<InstanceBase> dependency_item; + InstanceBase *baked_light; //baked light to use + SelfList<InstanceBase> baked_light_item; + + virtual void base_removed()=0; + virtual void base_changed()=0; + virtual void base_material_changed()=0; + + InstanceBase() : dependency_item(this), baked_light_item(this) { + + base_type=VS::INSTANCE_NONE; + cast_shadows=VS::SHADOW_CASTING_SETTING_ON; + receive_shadows=true; + depth_scale=false; + billboard=false; + billboard_y=false; + visible=true; + depth_layer=0; + layer_mask=1; + baked_light=NULL; + + + } + }; + + virtual RID light_instance_create(RID p_light)=0; + virtual void light_instance_set_transform(RID p_light_instance,const Transform& p_transform)=0; + virtual void light_instance_set_shadow_transform(RID p_light_instance,const CameraMatrix& p_projection,const Transform& p_transform,float p_far,float p_split,int p_pass)=0; + virtual void light_instance_mark_visible(RID p_light_instance)=0; + + virtual RID reflection_atlas_create()=0; + virtual void reflection_atlas_set_size(RID p_ref_atlas,int p_size)=0; + virtual void reflection_atlas_set_subdivision(RID p_ref_atlas,int p_subdiv)=0; + + virtual RID reflection_probe_instance_create(RID p_probe)=0; + virtual void reflection_probe_instance_set_transform(RID p_instance,const Transform& p_transform)=0; + virtual void reflection_probe_release_atlas_index(RID p_instance)=0; + virtual bool reflection_probe_instance_needs_redraw(RID p_instance)=0; + virtual bool reflection_probe_instance_has_reflection(RID p_instance)=0; + virtual bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas)=0; + virtual bool reflection_probe_instance_postprocess_step(RID p_instance)=0; + + virtual RID gi_probe_instance_create()=0; + virtual void gi_probe_instance_set_light_data(RID p_probe,RID p_base,RID p_data)=0; + virtual void gi_probe_instance_set_transform_to_data(RID p_probe,const Transform& p_xform)=0; + virtual void gi_probe_instance_set_bounds(RID p_probe,const Vector3& p_bounds)=0; + + virtual void render_scene(const Transform& p_cam_transform,const CameraMatrix& p_cam_projection,bool p_cam_ortogonal,InstanceBase** p_cull_result,int p_cull_count,RID* p_light_cull_result,int p_light_cull_count,RID* p_reflection_probe_cull_result,int p_reflection_probe_cull_count,RID p_environment,RID p_shadow_atlas,RID p_reflection_atlas,RID p_reflection_probe,int p_reflection_probe_pass)=0; + virtual void render_shadow(RID p_light,RID p_shadow_atlas,int p_pass,InstanceBase** p_cull_result,int p_cull_count)=0; + + virtual void set_scene_pass(uint64_t p_pass)=0; + + virtual bool free(RID p_rid)=0; + + virtual ~RasterizerScene() {} +}; + + + + + + + +class RasterizerStorage { +public: + /* TEXTURE API */ + + virtual RID texture_create()=0; + virtual void texture_allocate(RID p_texture,int p_width, int p_height,Image::Format p_format,uint32_t p_flags=VS::TEXTURE_FLAGS_DEFAULT)=0; + virtual void texture_set_data(RID p_texture,const Image& p_image,VS::CubeMapSide p_cube_side=VS::CUBEMAP_LEFT)=0; + virtual Image texture_get_data(RID p_texture,VS::CubeMapSide p_cube_side=VS::CUBEMAP_LEFT) const=0; + virtual void texture_set_flags(RID p_texture,uint32_t p_flags)=0; + virtual uint32_t texture_get_flags(RID p_texture) const=0; + virtual Image::Format texture_get_format(RID p_texture) const=0; + virtual uint32_t texture_get_width(RID p_texture) const=0; + virtual uint32_t texture_get_height(RID p_texture) const=0; + virtual void texture_set_size_override(RID p_texture,int p_width, int p_height)=0; + + virtual void texture_set_path(RID p_texture,const String& p_path)=0; + virtual String texture_get_path(RID p_texture) const=0; + + virtual void texture_set_shrink_all_x2_on_set_data(bool p_enable)=0; + + virtual void texture_debug_usage(List<VS::TextureInfo> *r_info)=0; + + virtual RID texture_create_radiance_cubemap(RID p_source,int p_resolution=-1) const=0; + + virtual void texture_set_detect_3d_callback(RID p_texture,VisualServer::TextureDetectCallback p_callback,void* p_userdata)=0; + virtual void texture_set_detect_srgb_callback(RID p_texture,VisualServer::TextureDetectCallback p_callback,void* p_userdata)=0; + + virtual void textures_keep_original(bool p_enable)=0; + + /* SKYBOX API */ + + virtual RID skybox_create()=0; + virtual void skybox_set_texture(RID p_skybox,RID p_cube_map,int p_radiance_size)=0; + + /* SHADER API */ + + + virtual RID shader_create(VS::ShaderMode p_mode=VS::SHADER_SPATIAL)=0; + + virtual void shader_set_mode(RID p_shader,VS::ShaderMode p_mode)=0; + virtual VS::ShaderMode shader_get_mode(RID p_shader) const=0; + + virtual void shader_set_code(RID p_shader, const String& p_code)=0; + virtual String shader_get_code(RID p_shader) const=0; + virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const=0; + + virtual void shader_set_default_texture_param(RID p_shader, const StringName& p_name, RID p_texture)=0; + virtual RID shader_get_default_texture_param(RID p_shader, const StringName& p_name) const=0; + + + /* COMMON MATERIAL API */ + + virtual RID material_create()=0; + + virtual void material_set_shader(RID p_shader_material, RID p_shader)=0; + virtual RID material_get_shader(RID p_shader_material) const=0; + + virtual void material_set_param(RID p_material, const StringName& p_param, const Variant& p_value)=0; + virtual Variant material_get_param(RID p_material, const StringName& p_param) const=0; + + virtual void material_set_line_width(RID p_material, float p_width)=0; + + virtual bool material_is_animated(RID p_material)=0; + virtual bool material_casts_shadows(RID p_material)=0; + + virtual void material_add_instance_owner(RID p_material, RasterizerScene::InstanceBase *p_instance)=0; + virtual void material_remove_instance_owner(RID p_material, RasterizerScene::InstanceBase *p_instance)=0; + + /* MESH API */ + + virtual RID mesh_create()=0; + + virtual void mesh_add_surface(RID p_mesh,uint32_t p_format,VS::PrimitiveType p_primitive,const PoolVector<uint8_t>& p_array,int p_vertex_count,const PoolVector<uint8_t>& p_index_array,int p_index_count,const Rect3& p_aabb,const Vector<PoolVector<uint8_t> >& p_blend_shapes=Vector<PoolVector<uint8_t> >(),const Vector<Rect3>& p_bone_aabbs=Vector<Rect3>())=0; + + virtual void mesh_set_blend_shape_count(RID p_mesh,int p_amount)=0; + virtual int mesh_get_blend_shape_count(RID p_mesh) const=0; + + + virtual void mesh_set_blend_shape_mode(RID p_mesh,VS::BlendShapeMode p_mode)=0; + virtual VS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const=0; + + virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material)=0; + virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const=0; + + virtual int mesh_surface_get_array_len(RID p_mesh, int p_surface) const=0; + virtual int mesh_surface_get_array_index_len(RID p_mesh, int p_surface) const=0; + + virtual PoolVector<uint8_t> mesh_surface_get_array(RID p_mesh, int p_surface) const=0; + virtual PoolVector<uint8_t> mesh_surface_get_index_array(RID p_mesh, int p_surface) const=0; + + + virtual uint32_t mesh_surface_get_format(RID p_mesh, int p_surface) const=0; + virtual VS::PrimitiveType mesh_surface_get_primitive_type(RID p_mesh, int p_surface) const=0; + + virtual Rect3 mesh_surface_get_aabb(RID p_mesh, int p_surface) const=0; + virtual Vector<PoolVector<uint8_t> > mesh_surface_get_blend_shapes(RID p_mesh, int p_surface) const=0; + virtual Vector<Rect3> mesh_surface_get_skeleton_aabb(RID p_mesh, int p_surface) const=0; + + virtual void mesh_remove_surface(RID p_mesh,int p_index)=0; + virtual int mesh_get_surface_count(RID p_mesh) const=0; + + virtual void mesh_set_custom_aabb(RID p_mesh,const Rect3& p_aabb)=0; + virtual Rect3 mesh_get_custom_aabb(RID p_mesh) const=0; + + virtual Rect3 mesh_get_aabb(RID p_mesh, RID p_skeleton) const=0; + virtual void mesh_clear(RID p_mesh)=0; + + /* MULTIMESH API */ + + + virtual RID multimesh_create()=0; + + virtual void multimesh_allocate(RID p_multimesh,int p_instances,VS::MultimeshTransformFormat p_transform_format,VS::MultimeshColorFormat p_color_format)=0; + virtual int multimesh_get_instance_count(RID p_multimesh) const=0; + + virtual void multimesh_set_mesh(RID p_multimesh,RID p_mesh)=0; + virtual void multimesh_instance_set_transform(RID p_multimesh,int p_index,const Transform& p_transform)=0; + virtual void multimesh_instance_set_transform_2d(RID p_multimesh,int p_index,const Transform2D& p_transform)=0; + virtual void multimesh_instance_set_color(RID p_multimesh,int p_index,const Color& p_color)=0; + + virtual RID multimesh_get_mesh(RID p_multimesh) const=0; + + virtual Transform multimesh_instance_get_transform(RID p_multimesh,int p_index) const=0; + virtual Transform2D multimesh_instance_get_transform_2d(RID p_multimesh,int p_index) const=0; + virtual Color multimesh_instance_get_color(RID p_multimesh,int p_index) const=0; + + virtual void multimesh_set_visible_instances(RID p_multimesh,int p_visible)=0; + virtual int multimesh_get_visible_instances(RID p_multimesh) const=0; + + virtual Rect3 multimesh_get_aabb(RID p_multimesh) const=0; + + /* IMMEDIATE API */ + + virtual RID immediate_create()=0; + virtual void immediate_begin(RID p_immediate,VS::PrimitiveType p_rimitive,RID p_texture=RID())=0; + virtual void immediate_vertex(RID p_immediate,const Vector3& p_vertex)=0; + virtual void immediate_normal(RID p_immediate,const Vector3& p_normal)=0; + virtual void immediate_tangent(RID p_immediate,const Plane& p_tangent)=0; + virtual void immediate_color(RID p_immediate,const Color& p_color)=0; + virtual void immediate_uv(RID p_immediate,const Vector2& tex_uv)=0; + virtual void immediate_uv2(RID p_immediate,const Vector2& tex_uv)=0; + virtual void immediate_end(RID p_immediate)=0; + virtual void immediate_clear(RID p_immediate)=0; + virtual void immediate_set_material(RID p_immediate,RID p_material)=0; + virtual RID immediate_get_material(RID p_immediate) const=0; + virtual Rect3 immediate_get_aabb(RID p_immediate) const=0; + + + /* SKELETON API */ + + virtual RID skeleton_create()=0; + virtual void skeleton_allocate(RID p_skeleton,int p_bones,bool p_2d_skeleton=false)=0; + virtual int skeleton_get_bone_count(RID p_skeleton) const=0; + virtual void skeleton_bone_set_transform(RID p_skeleton,int p_bone, const Transform& p_transform)=0; + virtual Transform skeleton_bone_get_transform(RID p_skeleton,int p_bone) const =0; + virtual void skeleton_bone_set_transform_2d(RID p_skeleton,int p_bone, const Transform2D& p_transform)=0; + virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton,int p_bone) const=0; + + /* Light API */ + + virtual RID light_create(VS::LightType p_type)=0; + + virtual void light_set_color(RID p_light,const Color& p_color)=0; + virtual void light_set_param(RID p_light,VS::LightParam p_param,float p_value)=0; + virtual void light_set_shadow(RID p_light,bool p_enabled)=0; + virtual void light_set_shadow_color(RID p_light,const Color& p_color)=0; + virtual void light_set_projector(RID p_light,RID p_texture)=0; + 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_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; + + virtual void light_directional_set_shadow_mode(RID p_light,VS::LightDirectionalShadowMode p_mode)=0; + virtual void light_directional_set_blend_splits(RID p_light,bool p_enable)=0; + virtual bool light_directional_get_blend_splits(RID p_light) const=0; + + virtual VS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light)=0; + virtual VS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light)=0; + + virtual bool light_has_shadow(RID p_light) const=0; + + virtual VS::LightType light_get_type(RID p_light) const=0; + virtual Rect3 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 uint64_t light_get_version(RID p_light) const=0; + + + /* PROBE API */ + + virtual RID reflection_probe_create()=0; + + virtual void reflection_probe_set_update_mode(RID p_probe, VS::ReflectionProbeUpdateMode p_mode)=0; + virtual void reflection_probe_set_intensity(RID p_probe, float p_intensity)=0; + virtual void reflection_probe_set_interior_ambient(RID p_probe, const Color& p_ambient)=0; + virtual void reflection_probe_set_interior_ambient_energy(RID p_probe, float p_energy)=0; + virtual void reflection_probe_set_interior_ambient_probe_contribution(RID p_probe, float p_contrib)=0; + virtual void reflection_probe_set_max_distance(RID p_probe, float p_distance)=0; + virtual void reflection_probe_set_extents(RID p_probe, const Vector3& p_extents)=0; + virtual void reflection_probe_set_origin_offset(RID p_probe, const Vector3& p_offset)=0; + virtual void reflection_probe_set_as_interior(RID p_probe, bool p_enable)=0; + virtual void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable)=0; + virtual void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable)=0; + virtual void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers)=0; + + virtual Rect3 reflection_probe_get_aabb(RID p_probe) const=0; + virtual VS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const=0; + virtual uint32_t reflection_probe_get_cull_mask(RID p_probe) const=0; + virtual Vector3 reflection_probe_get_extents(RID p_probe) const=0; + virtual Vector3 reflection_probe_get_origin_offset(RID p_probe) const=0; + virtual float reflection_probe_get_origin_max_distance(RID p_probe) const=0; + virtual bool reflection_probe_renders_shadows(RID p_probe) const=0; + + + /* ROOM API */ + + virtual RID room_create()=0; + virtual void room_add_bounds(RID p_room, const PoolVector<Vector2>& p_convex_polygon,float p_height,const Transform& p_transform)=0; + virtual void room_clear_bounds(RID p_room)=0; + + /* PORTAL API */ + + // portals are only (x/y) points, forming a convex shape, which its clockwise + // order points outside. (z is 0)=0; + + virtual RID portal_create()=0; + virtual void portal_set_shape(RID p_portal, const Vector<Point2>& p_shape)=0; + virtual void portal_set_enabled(RID p_portal, bool p_enabled)=0; + virtual void portal_set_disable_distance(RID p_portal, float p_distance)=0; + virtual void portal_set_disabled_color(RID p_portal, const Color& p_color)=0; + + virtual void instance_add_skeleton(RID p_skeleton,RasterizerScene::InstanceBase *p_instance)=0; + virtual void instance_remove_skeleton(RID p_skeleton,RasterizerScene::InstanceBase *p_instance)=0; + + virtual void instance_add_dependency(RID p_base,RasterizerScene::InstanceBase *p_instance)=0; + virtual void instance_remove_dependency(RID p_base,RasterizerScene::InstanceBase *p_instance)=0; + + /* GI PROBE API */ + + virtual RID gi_probe_create()=0; + + virtual void gi_probe_set_bounds(RID p_probe,const Rect3& p_bounds)=0; + virtual Rect3 gi_probe_get_bounds(RID p_probe) const=0; + + virtual void gi_probe_set_cell_size(RID p_probe,float p_range)=0; + virtual float gi_probe_get_cell_size(RID p_probe) const=0; + + virtual void gi_probe_set_to_cell_xform(RID p_probe,const Transform& p_xform)=0; + virtual Transform gi_probe_get_to_cell_xform(RID p_probe) const=0; + + virtual void gi_probe_set_dynamic_data(RID p_probe,const PoolVector<int>& p_data)=0; + virtual PoolVector<int> gi_probe_get_dynamic_data(RID p_probe) const=0; + + virtual void gi_probe_set_dynamic_range(RID p_probe,int p_range)=0; + virtual int gi_probe_get_dynamic_range(RID p_probe) const=0; + + virtual void gi_probe_set_energy(RID p_probe,float p_range)=0; + virtual float gi_probe_get_energy(RID p_probe) const=0; + + virtual void gi_probe_set_bias(RID p_probe,float p_range)=0; + virtual float gi_probe_get_bias(RID p_probe) const=0; + + virtual void gi_probe_set_propagation(RID p_probe,float p_range)=0; + virtual float gi_probe_get_propagation(RID p_probe) const=0; + + virtual void gi_probe_set_interior(RID p_probe,bool p_enable)=0; + virtual bool gi_probe_is_interior(RID p_probe) const=0; + + virtual void gi_probe_set_compress(RID p_probe,bool p_enable)=0; + virtual bool gi_probe_is_compressed(RID p_probe) const=0; + + virtual uint32_t gi_probe_get_version(RID p_probe)=0; + + enum GIProbeCompression { + GI_PROBE_UNCOMPRESSED, + GI_PROBE_S3TC, + GI_PROBE_ETC2 + }; + + virtual GIProbeCompression gi_probe_get_dynamic_data_get_preferred_compression() const=0; + virtual RID gi_probe_dynamic_data_create(int p_width,int p_height,int p_depth,GIProbeCompression p_compression)=0; + virtual void gi_probe_dynamic_data_update(RID p_gi_probe_data,int p_depth_slice,int p_slice_count,int p_mipmap,const void* p_data)=0; + + + /* PARTICLES */ + + virtual RID particles_create()=0; + + virtual void particles_set_emitting(RID p_particles,bool p_emitting)=0; + virtual void particles_set_amount(RID p_particles,int p_amount)=0; + virtual void particles_set_lifetime(RID p_particles,float p_lifetime)=0; + virtual void particles_set_pre_process_time(RID p_particles,float p_time)=0; + virtual void particles_set_explosiveness_ratio(RID p_particles,float p_ratio)=0; + virtual void particles_set_randomness_ratio(RID p_particles,float p_ratio)=0; + virtual void particles_set_custom_aabb(RID p_particles,const Rect3& p_aabb)=0; + virtual void particles_set_gravity(RID p_particles,const Vector3& p_gravity)=0; + virtual void particles_set_use_local_coordinates(RID p_particles,bool p_enable)=0; + virtual void particles_set_process_material(RID p_particles,RID p_material)=0; + + virtual void particles_set_emission_shape(RID p_particles,VS::ParticlesEmissionShape p_shape)=0; + virtual void particles_set_emission_sphere_radius(RID p_particles,float p_radius)=0; + virtual void particles_set_emission_box_extents(RID p_particles,const Vector3& p_extents)=0; + virtual void particles_set_emission_points(RID p_particles,const PoolVector<Vector3>& p_points)=0; + + + virtual void particles_set_draw_order(RID p_particles,VS::ParticlesDrawOrder p_order)=0; + + virtual void particles_set_draw_passes(RID p_particles,int p_count)=0; + virtual void particles_set_draw_pass_material(RID p_particles,int p_pass, RID p_material)=0; + virtual void particles_set_draw_pass_mesh(RID p_particles,int p_pass, RID p_mesh)=0; + + virtual Rect3 particles_get_current_aabb(RID p_particles)=0; + + + + /* RENDER TARGET */ + + enum RenderTargetFlags { + RENDER_TARGET_VFLIP, + RENDER_TARGET_TRANSPARENT, + RENDER_TARGET_NO_3D, + RENDER_TARGET_NO_SAMPLING, + RENDER_TARGET_HDR, + RENDER_TARGET_FLAG_MAX + }; + + virtual RID render_target_create()=0; + virtual void render_target_set_size(RID p_render_target,int p_width, int p_height)=0; + virtual RID render_target_get_texture(RID p_render_target) const=0; + virtual void render_target_set_flag(RID p_render_target,RenderTargetFlags p_flag,bool p_value)=0; + virtual bool render_target_renedered_in_frame(RID p_render_target)=0; + virtual void render_target_set_msaa(RID p_render_target,VS::ViewportMSAA p_msaa)=0; + + + /* CANVAS SHADOW */ + + virtual RID canvas_light_shadow_buffer_create(int p_width)=0; + + /* LIGHT SHADOW MAPPING */ + + virtual RID canvas_light_occluder_create()=0; + virtual void canvas_light_occluder_set_polylines(RID p_occluder, const PoolVector<Vector2>& p_lines)=0; + + + virtual VS::InstanceType get_base_type(RID p_rid) const=0; + virtual bool free(RID p_rid)=0; + + virtual bool has_os_feature(const String& p_feature) const=0; + + virtual void update_dirty_resources()=0; + + static RasterizerStorage*base_signleton; + RasterizerStorage(); + virtual ~RasterizerStorage() {} +}; + + + + + +class RasterizerCanvas { +public: + + enum CanvasRectFlags { + + CANVAS_RECT_REGION=1, + CANVAS_RECT_TILE=2, + CANVAS_RECT_FLIP_H=4, + CANVAS_RECT_FLIP_V=8, + CANVAS_RECT_TRANSPOSE=16 + }; + + + struct Light : public RID_Data { + + + + bool enabled; + Color color; + Transform2D xform; + float height; + float energy; + float scale; + int z_min; + int z_max; + int layer_min; + int layer_max; + int item_mask; + int item_shadow_mask; + VS::CanvasLightMode mode; + RID texture; + Vector2 texture_offset; + RID canvas; + RID shadow_buffer; + int shadow_buffer_size; + float shadow_gradient_length; + VS::CanvasLightShadowFilter shadow_filter; + Color shadow_color; + + + void *texture_cache; // implementation dependent + Rect2 rect_cache; + Transform2D xform_cache; + float radius_cache; //used for shadow far plane + CameraMatrix shadow_matrix_cache; + + Transform2D light_shader_xform; + Vector2 light_shader_pos; + + Light *shadows_next_ptr; + Light *filter_next_ptr; + Light *next_ptr; + Light *mask_next_ptr; + + RID light_internal; + + Light() { + enabled=true; + color=Color(1,1,1); + shadow_color=Color(0,0,0,0); + height=0; + z_min=-1024; + z_max=1024; + layer_min=0; + layer_max=0; + item_mask=1; + scale=1.0; + energy=1.0; + item_shadow_mask=-1; + mode=VS::CANVAS_LIGHT_MODE_ADD; + texture_cache=NULL; + next_ptr=NULL; + mask_next_ptr=NULL; + filter_next_ptr=NULL; + shadow_buffer_size=256; + shadow_gradient_length=0; + shadow_filter=VS::CANVAS_LIGHT_FILTER_NONE; + + } + }; + + virtual RID light_internal_create()=0; + virtual void light_internal_update(RID p_rid, Light* p_light)=0; + virtual void light_internal_free(RID p_rid)=0; + + struct Item : public RID_Data { + + struct Command { + + enum Type { + + TYPE_LINE, + TYPE_RECT, + TYPE_NINEPATCH, + TYPE_PRIMITIVE, + TYPE_POLYGON, + TYPE_MESH, + TYPE_MULTIMESH, + TYPE_CIRCLE, + TYPE_TRANSFORM, + TYPE_CLIP_IGNORE, + }; + + Type type; + virtual ~Command(){} + }; + + struct CommandLine : public Command { + + Point2 from,to; + Color color; + float width; + bool antialiased; + CommandLine() { type = TYPE_LINE; } + }; + + struct CommandRect : public Command { + + Rect2 rect; + RID texture; + Color modulate; + Rect2 source; + uint8_t flags; + + CommandRect() { flags=0; type = TYPE_RECT; } + }; + + struct CommandNinePatch : public Command { + + Rect2 rect; + Rect2 source; + RID texture; + float margin[4]; + bool draw_center; + Color color; + VS::NinePatchAxisMode axis_x; + VS::NinePatchAxisMode axis_y; + CommandNinePatch() { draw_center=true; type = TYPE_NINEPATCH; } + }; + + struct CommandPrimitive : public Command { + + Vector<Point2> points; + Vector<Point2> uvs; + Vector<Color> colors; + RID texture; + float width; + + CommandPrimitive() { type = TYPE_PRIMITIVE; width=1;} + }; + + struct CommandPolygon : public Command { + + Vector<int> indices; + Vector<Point2> points; + Vector<Point2> uvs; + Vector<Color> colors; + RID texture; + int count; + + CommandPolygon() { type = TYPE_POLYGON; count = 0; } + }; + + + struct CommandMesh : public Command { + + RID mesh; + RID skeleton; + CommandMesh() { type = TYPE_MESH; } + }; + + struct CommandMultiMesh : public Command { + + RID multimesh; + RID skeleton; + CommandMultiMesh() { type = TYPE_MULTIMESH; } + }; + + struct CommandCircle : public Command { + + Point2 pos; + float radius; + Color color; + CommandCircle() { type = TYPE_CIRCLE; } + }; + + struct CommandTransform : public Command { + + Transform2D xform; + CommandTransform() { type = TYPE_TRANSFORM; } + }; + + + struct CommandClipIgnore : public Command { + + bool ignore; + CommandClipIgnore() { type = TYPE_CLIP_IGNORE; ignore=false; } + }; + + + struct ViewportRender { + VisualServer*owner; + void* udata; + Rect2 rect; + }; + + Transform2D xform; + bool clip; + bool visible; + bool behind; + //VS::MaterialBlendMode blend_mode; + int light_mask; + Vector<Command*> commands; + mutable bool custom_rect; + mutable bool rect_dirty; + mutable Rect2 rect; + RID material; + Item*next; + + struct CopyBackBuffer { + Rect2 rect; + Rect2 screen_rect; + bool full; + }; + CopyBackBuffer *copy_back_buffer; + + + Color final_modulate; + Transform2D final_transform; + Rect2 final_clip_rect; + Item* final_clip_owner; + Item* material_owner; + ViewportRender *vp_render; + bool distance_field; + bool light_masked; + + Rect2 global_rect_cache; + + const Rect2& get_rect() const { + if (custom_rect || !rect_dirty) + return rect; + + //must update rect + int s=commands.size(); + if (s==0) { + + rect=Rect2(); + rect_dirty=false; + return rect; + } + + Transform2D xf; + bool found_xform=false; + bool first=true; + + const Item::Command * const *cmd = &commands[0]; + + + for (int i=0;i<s;i++) { + + const Item::Command *c=cmd[i]; + Rect2 r; + + switch(c->type) { + case Item::Command::TYPE_LINE: { + + const Item::CommandLine* line = static_cast< const Item::CommandLine*>(c); + r.pos=line->from; + r.expand_to(line->to); + } break; + case Item::Command::TYPE_RECT: { + + const Item::CommandRect* crect = static_cast< const Item::CommandRect*>(c); + r=crect->rect; + + } break; + case Item::Command::TYPE_NINEPATCH: { + + const Item::CommandNinePatch* style = static_cast< const Item::CommandNinePatch*>(c); + r=style->rect; + } break; + case Item::Command::TYPE_PRIMITIVE: { + + const Item::CommandPrimitive* primitive = static_cast< const Item::CommandPrimitive*>(c); + r.pos=primitive->points[0]; + for(int i=1;i<primitive->points.size();i++) { + + r.expand_to(primitive->points[i]); + + } + } break; + case Item::Command::TYPE_POLYGON: { + + const Item::CommandPolygon* polygon = static_cast< const Item::CommandPolygon*>(c); + int l = polygon->points.size(); + const Point2*pp=&polygon->points[0]; + r.pos=pp[0]; + for(int i=1;i<l;i++) { + + r.expand_to(pp[i]); + + } + } break; + case Item::Command::TYPE_MESH: { + + const Item::CommandMesh* mesh = static_cast< const Item::CommandMesh*>(c); + Rect3 aabb = RasterizerStorage::base_signleton->mesh_get_aabb(mesh->mesh,mesh->skeleton); + + r=Rect2(aabb.pos.x,aabb.pos.y,aabb.size.x,aabb.size.y); + + } break; + case Item::Command::TYPE_MULTIMESH: { + + const Item::CommandMultiMesh* multimesh = static_cast< const Item::CommandMultiMesh*>(c); + Rect3 aabb = RasterizerStorage::base_signleton->multimesh_get_aabb(multimesh->multimesh); + + r=Rect2(aabb.pos.x,aabb.pos.y,aabb.size.x,aabb.size.y); + + } break; + case Item::Command::TYPE_CIRCLE: { + + const Item::CommandCircle* circle = static_cast< const Item::CommandCircle*>(c); + r.pos=Point2(-circle->radius,-circle->radius)+circle->pos; + r.size=Point2(circle->radius*2.0,circle->radius*2.0); + } break; + case Item::Command::TYPE_TRANSFORM: { + + const Item::CommandTransform* transform = static_cast<const Item::CommandTransform*>(c); + xf=transform->xform; + found_xform=true; + continue; + } break; + + case Item::Command::TYPE_CLIP_IGNORE: { + + } break; + } + + if (found_xform) { + r = xf.xform(r); + found_xform=false; + } + + + if (first) { + rect=r; + first=false; + } else + rect=rect.merge(r); + } + + rect_dirty=false; + return rect; + } + + void clear() { for (int i=0;i<commands.size();i++) memdelete( commands[i] ); commands.clear(); clip=false; rect_dirty=true; final_clip_owner=NULL; material_owner=NULL; light_masked=false; } + Item() { light_mask=1; vp_render=NULL; next=NULL; final_clip_owner=NULL; clip=false; final_modulate=Color(1,1,1,1); visible=true; rect_dirty=true; custom_rect=false; behind=false; material_owner=NULL; copy_back_buffer=NULL; distance_field=false; light_masked=false; } + virtual ~Item() { clear(); if (copy_back_buffer) memdelete(copy_back_buffer); } + }; + + + virtual void canvas_begin()=0; + + virtual void canvas_render_items(Item *p_item_list,int p_z,const Color& p_modulate,Light *p_light)=0; + virtual void canvas_debug_viewport_shadows(Light* p_lights_with_shadow)=0; + + + + struct LightOccluderInstance : public RID_Data { + + + bool enabled; + RID canvas; + RID polygon; + RID polygon_buffer; + Rect2 aabb_cache; + Transform2D xform; + Transform2D xform_cache; + int light_mask; + VS::CanvasOccluderPolygonCullMode cull_cache; + + LightOccluderInstance *next; + + LightOccluderInstance() { enabled=true; next=NULL; light_mask=1; cull_cache=VS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED; } + }; + + + + virtual void canvas_light_shadow_buffer_update(RID p_buffer, const Transform2D& p_light_xform, int p_light_mask,float p_near, float p_far, LightOccluderInstance* p_occluders, CameraMatrix *p_xform_cache)=0; + + + virtual void reset_canvas()=0; + + virtual ~RasterizerCanvas() {} +}; + + +class Rasterizer { +protected: + static Rasterizer* (*_create_func)(); +public: + static Rasterizer *create(); + + virtual RasterizerStorage *get_storage()=0; + virtual RasterizerCanvas *get_canvas()=0; + virtual RasterizerScene *get_scene()=0; + + virtual void initialize()=0; + virtual void begin_frame()=0; + virtual void set_current_render_target(RID p_render_target)=0; + virtual void restore_render_target()=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 end_frame()=0; + virtual void finalize()=0; + + + virtual ~Rasterizer() {} +}; + + +#if 0 /** @author Juan Linietsky <reduzio@gmail.com> */ @@ -41,7 +967,7 @@ class Rasterizer { protected: - typedef void (*CanvasItemDrawViewportFunc)(VisualServer*owner,void*ud,const Rect2& p_rect); + typedef void (*ItemDrawViewportFunc)(VisualServer*owner,void*ud,const Rect2& p_rect); RID create_default_material(); RID create_overdraw_debug_material(); @@ -49,7 +975,7 @@ protected: /* Fixed Material Shader API */ - union FixedMaterialShaderKey { + union FixedSpatialMaterialShaderKey { struct { uint16_t texcoord_mask; @@ -65,21 +991,21 @@ protected: uint32_t key; - _FORCE_INLINE_ bool operator<(const FixedMaterialShaderKey& p_key) const { return key<p_key.key; } + _FORCE_INLINE_ bool operator<(const FixedSpatialMaterialShaderKey& p_key) const { return key<p_key.key; } }; - struct FixedMaterialShader { + struct FixedSpatialMaterialShader { int refcount; RID shader; }; - Map<FixedMaterialShaderKey,FixedMaterialShader> fixed_material_shaders; + Map<FixedSpatialMaterialShaderKey,FixedSpatialMaterialShader> fixed_material_shaders; - RID _create_shader(const FixedMaterialShaderKey& p_key); - void _free_shader(const FixedMaterialShaderKey& p_key); + RID _create_shader(const FixedSpatialMaterialShaderKey& p_key); + void _free_shader(const FixedSpatialMaterialShaderKey& p_key); - struct FixedMaterial { + struct FixedSpatialMaterial { RID self; @@ -90,19 +1016,19 @@ protected: bool use_xy_normalmap; float point_size; Transform uv_xform; - VS::FixedMaterialLightShader light_shader; + VS::FixedSpatialMaterialLightShader light_shader; RID texture[VS::FIXED_MATERIAL_PARAM_MAX]; Variant param[VS::FIXED_MATERIAL_PARAM_MAX]; - VS::FixedMaterialTexCoordMode texture_tc[VS::FIXED_MATERIAL_PARAM_MAX]; + VS::FixedSpatialMaterialTexCoordMode texture_tc[VS::FIXED_MATERIAL_PARAM_MAX]; - SelfList<FixedMaterial> dirty_list; + SelfList<FixedSpatialMaterial> dirty_list; - FixedMaterialShaderKey current_key; + FixedSpatialMaterialShaderKey current_key; - _FORCE_INLINE_ FixedMaterialShaderKey get_key() const { + _FORCE_INLINE_ FixedSpatialMaterialShaderKey get_key() const { - FixedMaterialShaderKey k; + FixedSpatialMaterialShaderKey k; k.key=0; k.use_alpha=use_alpha; k.use_color_array=use_color_array; @@ -123,7 +1049,7 @@ protected: } - FixedMaterial() : dirty_list(this) { + FixedSpatialMaterial() : dirty_list(this) { use_alpha=false; use_color_array=false; @@ -155,9 +1081,9 @@ protected: StringName _fixed_material_uv_xform_name; StringName _fixed_material_point_size_name; - Map<RID,FixedMaterial*> fixed_materials; + Map<RID,FixedSpatialMaterial*> fixed_materials; - SelfList<FixedMaterial>::List fixed_material_dirty_list; + SelfList<FixedSpatialMaterial>::List fixed_material_dirty_list; protected: void _update_fixed_materials(); @@ -244,23 +1170,23 @@ public: virtual RID fixed_material_create(); - virtual void fixed_material_set_flag(RID p_material, VS::FixedMaterialFlags p_flag, bool p_enabled); - virtual bool fixed_material_get_flag(RID p_material, VS::FixedMaterialFlags p_flag) const; + virtual void fixed_material_set_flag(RID p_material, VS::FixedSpatialMaterialFlags p_flag, bool p_enabled); + virtual bool fixed_material_get_flag(RID p_material, VS::FixedSpatialMaterialFlags p_flag) const; - virtual void fixed_material_set_parameter(RID p_material, VS::FixedMaterialParam p_parameter, const Variant& p_value); - virtual Variant fixed_material_get_parameter(RID p_material,VS::FixedMaterialParam p_parameter) const; + virtual void fixed_material_set_parameter(RID p_material, VS::FixedSpatialMaterialParam p_parameter, const Variant& p_value); + virtual Variant fixed_material_get_parameter(RID p_material,VS::FixedSpatialMaterialParam p_parameter) const; - virtual void fixed_material_set_texture(RID p_material,VS::FixedMaterialParam p_parameter, RID p_texture); - virtual RID fixed_material_get_texture(RID p_material,VS::FixedMaterialParam p_parameter) const; + virtual void fixed_material_set_texture(RID p_material,VS::FixedSpatialMaterialParam p_parameter, RID p_texture); + virtual RID fixed_material_get_texture(RID p_material,VS::FixedSpatialMaterialParam p_parameter) const; - virtual void fixed_material_set_texcoord_mode(RID p_material,VS::FixedMaterialParam p_parameter, VS::FixedMaterialTexCoordMode p_mode); - virtual VS::FixedMaterialTexCoordMode fixed_material_get_texcoord_mode(RID p_material,VS::FixedMaterialParam p_parameter) const; + virtual void fixed_material_set_texcoord_mode(RID p_material,VS::FixedSpatialMaterialParam p_parameter, VS::FixedSpatialMaterialTexCoordMode p_mode); + virtual VS::FixedSpatialMaterialTexCoordMode fixed_material_get_texcoord_mode(RID p_material,VS::FixedSpatialMaterialParam p_parameter) const; virtual void fixed_material_set_uv_transform(RID p_material,const Transform& p_transform); virtual Transform fixed_material_get_uv_transform(RID p_material) const; - virtual void fixed_material_set_light_shader(RID p_material,VS::FixedMaterialLightShader p_shader); - virtual VS::FixedMaterialLightShader fixed_material_get_light_shader(RID p_material) const; + virtual void fixed_material_set_light_shader(RID p_material,VS::FixedSpatialMaterialLightShader p_shader); + virtual VS::FixedSpatialMaterialLightShader fixed_material_get_light_shader(RID p_material) const; virtual void fixed_material_set_point_size(RID p_material,float p_size); virtual float fixed_material_get_point_size(RID p_material) const; @@ -311,7 +1237,7 @@ public: virtual void multimesh_instance_set_color(RID p_multimesh,int p_index,const Color& p_color)=0; virtual RID multimesh_get_mesh(RID p_multimesh) const=0; - virtual AABB multimesh_get_aabb(RID p_multimesh) const=0;; + virtual AABB multimesh_get_aabb(RID p_multimesh) const=0; virtual Transform multimesh_instance_get_transform(RID p_multimesh,int p_index) const=0; virtual Color multimesh_instance_get_color(RID p_multimesh,int p_index) const=0; @@ -360,8 +1286,8 @@ public: virtual void particles_set_emission_base_velocity(RID p_particles, const Vector3& p_base_velocity)=0; virtual Vector3 particles_get_emission_base_velocity(RID p_particles) const=0; - virtual void particles_set_emission_points(RID p_particles, const DVector<Vector3>& p_points)=0; - virtual DVector<Vector3> particles_get_emission_points(RID p_particles) const=0; + virtual void particles_set_emission_points(RID p_particles, const PoolVector<Vector3>& p_points)=0; + virtual PoolVector<Vector3> particles_get_emission_points(RID p_particles) const=0; virtual void particles_set_gravity_normal(RID p_particles, const Vector3& p_normal)=0; virtual Vector3 particles_get_gravity_normal(RID p_particles) const=0; @@ -581,7 +1507,7 @@ public: }; - struct CanvasLight { + struct Light { @@ -597,7 +1523,7 @@ public: int layer_max; int item_mask; int item_shadow_mask; - VS::CanvasLightMode mode; + VS::LightMode mode; RID texture; Vector2 texture_offset; RID canvas; @@ -616,12 +1542,12 @@ public: Matrix32 light_shader_xform; Vector2 light_shader_pos; - CanvasLight *shadows_next_ptr; - CanvasLight *filter_next_ptr; - CanvasLight *next_ptr; - CanvasLight *mask_next_ptr; + Light *shadows_next_ptr; + Light *filter_next_ptr; + Light *next_ptr; + Light *mask_next_ptr; - CanvasLight() { + Light() { enabled=true; color=Color(1,1,1); shadow_color=Color(0,0,0,0); @@ -645,20 +1571,20 @@ public: } }; - struct CanvasItem; + struct Item; - struct CanvasItemMaterial { + struct ItemMaterial { RID shader; Map<StringName,Variant> shader_param; uint32_t shader_version; - Set<CanvasItem*> owners; - VS::CanvasItemShadingMode shading_mode; + Set<Item*> owners; + VS::ItemShadingMode shading_mode; - CanvasItemMaterial() {shading_mode=VS::CANVAS_ITEM_SHADING_NORMAL; shader_version=0; } + ItemMaterial() {shading_mode=VS::CANVAS_ITEM_SHADING_NORMAL; shader_version=0; } }; - struct CanvasItem { + struct Item { struct Command { @@ -788,8 +1714,8 @@ public: mutable bool custom_rect; mutable bool rect_dirty; mutable Rect2 rect; - CanvasItem*next; - CanvasItemMaterial* material; + Item*next; + ItemMaterial* material; struct CopyBackBuffer { Rect2 rect; Rect2 screen_rect; @@ -801,8 +1727,8 @@ public: float final_opacity; Matrix32 final_transform; Rect2 final_clip_rect; - CanvasItem* final_clip_owner; - CanvasItem* material_owner; + Item* final_clip_owner; + Item* material_owner; ViewportRender *vp_render; bool distance_field; bool light_masked; @@ -826,35 +1752,35 @@ public: bool found_xform=false; bool first=true; - const CanvasItem::Command * const *cmd = &commands[0]; + const Item::Command * const *cmd = &commands[0]; for (int i=0;i<s;i++) { - const CanvasItem::Command *c=cmd[i]; + const Item::Command *c=cmd[i]; Rect2 r; switch(c->type) { - case CanvasItem::Command::TYPE_LINE: { + case Item::Command::TYPE_LINE: { - const CanvasItem::CommandLine* line = static_cast< const CanvasItem::CommandLine*>(c); + const Item::CommandLine* line = static_cast< const Item::CommandLine*>(c); r.pos=line->from; r.expand_to(line->to); } break; - case CanvasItem::Command::TYPE_RECT: { + case Item::Command::TYPE_RECT: { - const CanvasItem::CommandRect* crect = static_cast< const CanvasItem::CommandRect*>(c); + const Item::CommandRect* crect = static_cast< const Item::CommandRect*>(c); r=crect->rect; } break; - case CanvasItem::Command::TYPE_STYLE: { + case Item::Command::TYPE_STYLE: { - const CanvasItem::CommandStyle* style = static_cast< const CanvasItem::CommandStyle*>(c); + const Item::CommandStyle* style = static_cast< const Item::CommandStyle*>(c); r=style->rect; } break; - case CanvasItem::Command::TYPE_PRIMITIVE: { + case Item::Command::TYPE_PRIMITIVE: { - const CanvasItem::CommandPrimitive* primitive = static_cast< const CanvasItem::CommandPrimitive*>(c); + const Item::CommandPrimitive* primitive = static_cast< const Item::CommandPrimitive*>(c); r.pos=primitive->points[0]; for(int i=1;i<primitive->points.size();i++) { @@ -862,9 +1788,9 @@ public: } } break; - case CanvasItem::Command::TYPE_POLYGON: { + case Item::Command::TYPE_POLYGON: { - const CanvasItem::CommandPolygon* polygon = static_cast< const CanvasItem::CommandPolygon*>(c); + const Item::CommandPolygon* polygon = static_cast< const Item::CommandPolygon*>(c); int l = polygon->points.size(); const Point2*pp=&polygon->points[0]; r.pos=pp[0]; @@ -875,9 +1801,9 @@ public: } } break; - case CanvasItem::Command::TYPE_POLYGON_PTR: { + case Item::Command::TYPE_POLYGON_PTR: { - const CanvasItem::CommandPolygonPtr* polygon = static_cast< const CanvasItem::CommandPolygonPtr*>(c); + const Item::CommandPolygonPtr* polygon = static_cast< const Item::CommandPolygonPtr*>(c); int l = polygon->count; if (polygon->indices != NULL) { @@ -894,23 +1820,23 @@ public: } } } break; - case CanvasItem::Command::TYPE_CIRCLE: { + case Item::Command::TYPE_CIRCLE: { - const CanvasItem::CommandCircle* circle = static_cast< const CanvasItem::CommandCircle*>(c); + const Item::CommandCircle* circle = static_cast< const Item::CommandCircle*>(c); r.pos=Point2(-circle->radius,-circle->radius)+circle->pos; r.size=Point2(circle->radius*2.0,circle->radius*2.0); } break; - case CanvasItem::Command::TYPE_TRANSFORM: { + case Item::Command::TYPE_TRANSFORM: { - const CanvasItem::CommandTransform* transform = static_cast<const CanvasItem::CommandTransform*>(c); + const Item::CommandTransform* transform = static_cast<const Item::CommandTransform*>(c); xf=transform->xform; found_xform=true; continue; } break; - case CanvasItem::Command::TYPE_BLEND_MODE: { + case Item::Command::TYPE_BLEND_MODE: { } break; - case CanvasItem::Command::TYPE_CLIP_IGNORE: { + case Item::Command::TYPE_CLIP_IGNORE: { } break; } @@ -933,12 +1859,12 @@ public: } void clear() { for (int i=0;i<commands.size();i++) memdelete( commands[i] ); commands.clear(); clip=false; rect_dirty=true; final_clip_owner=NULL; material_owner=NULL; light_masked=false; } - CanvasItem() { light_mask=1; vp_render=NULL; next=NULL; final_clip_owner=NULL; clip=false; final_opacity=1; blend_mode=VS::MATERIAL_BLEND_MODE_MIX; visible=true; rect_dirty=true; custom_rect=false; ontop=true; material_owner=NULL; material=NULL; copy_back_buffer=NULL; distance_field=false; light_masked=false; } - virtual ~CanvasItem() { clear(); if (copy_back_buffer) memdelete(copy_back_buffer); } + Item() { light_mask=1; vp_render=NULL; next=NULL; final_clip_owner=NULL; clip=false; final_opacity=1; blend_mode=VS::MATERIAL_BLEND_MODE_MIX; visible=true; rect_dirty=true; custom_rect=false; ontop=true; material_owner=NULL; material=NULL; copy_back_buffer=NULL; distance_field=false; light_masked=false; } + virtual ~Item() { clear(); if (copy_back_buffer) memdelete(copy_back_buffer); } }; - CanvasItemDrawViewportFunc draw_viewport_func; + ItemDrawViewportFunc draw_viewport_func; virtual void begin_canvas_bg()=0; @@ -956,17 +1882,17 @@ public: virtual void canvas_draw_polygon(int p_vertex_count, const int* p_indices, const Vector2* p_vertices, const Vector2* p_uvs, const Color* p_colors,const RID& p_texture,bool p_singlecolor)=0; virtual void canvas_set_transform(const Matrix32& p_transform)=0; - virtual void canvas_render_items(CanvasItem *p_item_list,int p_z,const Color& p_modulate,CanvasLight *p_light)=0; - virtual void canvas_debug_viewport_shadows(CanvasLight* p_lights_with_shadow)=0; + virtual void canvas_render_items(Item *p_item_list,int p_z,const Color& p_modulate,Light *p_light)=0; + virtual void canvas_debug_viewport_shadows(Light* p_lights_with_shadow)=0; /* LIGHT SHADOW MAPPING */ virtual RID canvas_light_occluder_create()=0; - virtual void canvas_light_occluder_set_polylines(RID p_occluder, const DVector<Vector2>& p_lines)=0; + virtual void canvas_light_occluder_set_polylines(RID p_occluder, const PoolVector<Vector2>& p_lines)=0; virtual RID canvas_light_shadow_buffer_create(int p_width)=0; - struct CanvasLightOccluderInstance { + struct LightOccluderInstance { bool enabled; @@ -979,14 +1905,14 @@ public: int light_mask; VS::CanvasOccluderPolygonCullMode cull_cache; - CanvasLightOccluderInstance *next; + LightOccluderInstance *next; - CanvasLightOccluderInstance() { enabled=true; next=NULL; light_mask=1; cull_cache=VS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED; } + LightOccluderInstance() { enabled=true; next=NULL; light_mask=1; cull_cache=VS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED; } }; - virtual void canvas_light_shadow_buffer_update(RID p_buffer, const Matrix32& p_light_xform, int p_light_mask,float p_near, float p_far, CanvasLightOccluderInstance* p_occluders, CameraMatrix *p_xform_cache)=0; + virtual void canvas_light_shadow_buffer_update(RID p_buffer, const Matrix32& p_light_xform, int p_light_mask,float p_near, float p_far, LightOccluderInstance* p_occluders, CameraMatrix *p_xform_cache)=0; /* ENVIRONMENT */ @@ -1050,5 +1976,5 @@ public: }; - +#endif #endif diff --git a/servers/visual/rasterizer_dummy.cpp b/servers/visual/rasterizer_dummy.cpp deleted file mode 100644 index edbdc2fe23..0000000000 --- a/servers/visual/rasterizer_dummy.cpp +++ /dev/null @@ -1,1961 +0,0 @@ -/*************************************************************************/ -/* rasterizer_dummy.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "rasterizer_dummy.h" - -/* TEXTURE API */ - - -RID RasterizerDummy::texture_create() { - - Texture *texture = memnew(Texture); - ERR_FAIL_COND_V(!texture,RID()); - return texture_owner.make_rid( texture ); - -} - -void RasterizerDummy::texture_allocate(RID p_texture,int p_width, int p_height,Image::Format p_format,uint32_t p_flags) { - - - Texture *texture = texture_owner.get( p_texture ); - ERR_FAIL_COND(!texture); - texture->width=p_width; - texture->height=p_height; - texture->format=p_format; - texture->flags=p_flags; -} - -void RasterizerDummy::texture_set_data(RID p_texture,const Image& p_image,VS::CubeMapSide p_cube_side) { - - Texture * texture = texture_owner.get(p_texture); - - ERR_FAIL_COND(!texture); - ERR_FAIL_COND(texture->format != p_image.get_format() ); - - texture->image[p_cube_side]=p_image; - -} - -Image RasterizerDummy::texture_get_data(RID p_texture,VS::CubeMapSide p_cube_side) const { - - Texture * texture = texture_owner.get(p_texture); - - ERR_FAIL_COND_V(!texture,Image()); - - return texture->image[p_cube_side]; -} - -void RasterizerDummy::texture_set_flags(RID p_texture,uint32_t p_flags) { - - Texture *texture = texture_owner.get( p_texture ); - ERR_FAIL_COND(!texture); - uint32_t cube = texture->flags & VS::TEXTURE_FLAG_CUBEMAP; - texture->flags=p_flags|cube; // can't remove a cube from being a cube - -} -uint32_t RasterizerDummy::texture_get_flags(RID p_texture) const { - - Texture * texture = texture_owner.get(p_texture); - - ERR_FAIL_COND_V(!texture,0); - - return texture->flags; - -} -Image::Format RasterizerDummy::texture_get_format(RID p_texture) const { - - Texture * texture = texture_owner.get(p_texture); - - ERR_FAIL_COND_V(!texture,Image::FORMAT_GRAYSCALE); - - return texture->format; -} -uint32_t RasterizerDummy::texture_get_width(RID p_texture) const { - - Texture * texture = texture_owner.get(p_texture); - - ERR_FAIL_COND_V(!texture,0); - - return texture->width; -} -uint32_t RasterizerDummy::texture_get_height(RID p_texture) const { - - Texture * texture = texture_owner.get(p_texture); - - ERR_FAIL_COND_V(!texture,0); - - return texture->height; -} - -bool RasterizerDummy::texture_has_alpha(RID p_texture) const { - - Texture * texture = texture_owner.get(p_texture); - - ERR_FAIL_COND_V(!texture,0); - - return false; - -} - -void RasterizerDummy::texture_set_size_override(RID p_texture,int p_width, int p_height) { - - Texture * texture = texture_owner.get(p_texture); - - ERR_FAIL_COND(!texture); - - ERR_FAIL_COND(p_width<=0 || p_width>4096); - ERR_FAIL_COND(p_height<=0 || p_height>4096); - //real texture size is in alloc width and height -// texture->width=p_width; -// texture->height=p_height; - -} - -void RasterizerDummy::texture_set_reload_hook(RID p_texture,ObjectID p_owner,const StringName& p_function) const { - - -} - -/* SHADER API */ - -/* SHADER API */ - -RID RasterizerDummy::shader_create(VS::ShaderMode p_mode) { - - Shader *shader = memnew( Shader ); - shader->mode=p_mode; - shader->fragment_line=0; - shader->vertex_line=0; - shader->light_line=0; - RID rid = shader_owner.make_rid(shader); - - return rid; - -} - - - -void RasterizerDummy::shader_set_mode(RID p_shader,VS::ShaderMode p_mode) { - - ERR_FAIL_INDEX(p_mode,3); - Shader *shader=shader_owner.get(p_shader); - ERR_FAIL_COND(!shader); - shader->mode=p_mode; - -} -VS::ShaderMode RasterizerDummy::shader_get_mode(RID p_shader) const { - - Shader *shader=shader_owner.get(p_shader); - ERR_FAIL_COND_V(!shader,VS::SHADER_MATERIAL); - return shader->mode; -} - -void RasterizerDummy::shader_set_code(RID p_shader, const String& p_vertex, const String& p_fragment,const String& p_light,int p_vertex_ofs,int p_fragment_ofs,int p_light_ofs) { - - - Shader *shader=shader_owner.get(p_shader); - ERR_FAIL_COND(!shader); - shader->fragment_code=p_fragment; - shader->vertex_code=p_vertex; - shader->light_code=p_light; - shader->fragment_line=p_fragment_ofs; - shader->vertex_line=p_vertex_ofs; - shader->light_line=p_vertex_ofs; - -} - - -String RasterizerDummy::shader_get_vertex_code(RID p_shader) const { - - Shader *shader=shader_owner.get(p_shader); - ERR_FAIL_COND_V(!shader,String()); - return shader->vertex_code; - -} - -String RasterizerDummy::shader_get_fragment_code(RID p_shader) const { - - Shader *shader=shader_owner.get(p_shader); - ERR_FAIL_COND_V(!shader,String()); - return shader->fragment_code; - -} - -String RasterizerDummy::shader_get_light_code(RID p_shader) const { - - Shader *shader=shader_owner.get(p_shader); - ERR_FAIL_COND_V(!shader,String()); - return shader->light_code; - -} - -void RasterizerDummy::shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const { - - Shader *shader=shader_owner.get(p_shader); - ERR_FAIL_COND(!shader); - -} - - -void RasterizerDummy::shader_set_default_texture_param(RID p_shader, const StringName& p_name, RID p_texture) { - -} - -RID RasterizerDummy::shader_get_default_texture_param(RID p_shader, const StringName& p_name) const { - - return RID(); -} - -Variant RasterizerDummy::shader_get_default_param(RID p_shader, const StringName& p_name) { - - return Variant(); -} - -/* COMMON MATERIAL API */ - - -RID RasterizerDummy::material_create() { - - return material_owner.make_rid( memnew( Material ) ); -} - -void RasterizerDummy::material_set_shader(RID p_material, RID p_shader) { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND(!material); - material->shader=p_shader; - -} - -RID RasterizerDummy::material_get_shader(RID p_material) const { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND_V(!material,RID()); - return material->shader; -} - -void RasterizerDummy::material_set_param(RID p_material, const StringName& p_param, const Variant& p_value) { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND(!material); - - if (p_value.get_type()==Variant::NIL) - material->shader_params.erase(p_param); - else - material->shader_params[p_param]=p_value; -} -Variant RasterizerDummy::material_get_param(RID p_material, const StringName& p_param) const { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND_V(!material,Variant()); - - if (material->shader_params.has(p_param)) - return material->shader_params[p_param]; - else - return Variant(); -} - - -void RasterizerDummy::material_set_flag(RID p_material, VS::MaterialFlag p_flag,bool p_enabled) { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND(!material); - ERR_FAIL_INDEX(p_flag,VS::MATERIAL_FLAG_MAX); - material->flags[p_flag]=p_enabled; - -} -bool RasterizerDummy::material_get_flag(RID p_material,VS::MaterialFlag p_flag) const { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND_V(!material,false); - ERR_FAIL_INDEX_V(p_flag,VS::MATERIAL_FLAG_MAX,false); - return material->flags[p_flag]; - - -} - -void RasterizerDummy::material_set_depth_draw_mode(RID p_material, VS::MaterialDepthDrawMode p_mode) { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND(!material); - material->depth_draw_mode=p_mode; -} - -VS::MaterialDepthDrawMode RasterizerDummy::material_get_depth_draw_mode(RID p_material) const{ - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND_V(!material,VS::MATERIAL_DEPTH_DRAW_ALWAYS); - return material->depth_draw_mode; - -} - - -void RasterizerDummy::material_set_blend_mode(RID p_material,VS::MaterialBlendMode p_mode) { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND(!material); - material->blend_mode=p_mode; - -} -VS::MaterialBlendMode RasterizerDummy::material_get_blend_mode(RID p_material) const { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND_V(!material,VS::MATERIAL_BLEND_MODE_ADD); - return material->blend_mode; -} - -void RasterizerDummy::material_set_line_width(RID p_material,float p_line_width) { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND(!material); - material->line_width=p_line_width; - -} -float RasterizerDummy::material_get_line_width(RID p_material) const { - - Material *material = material_owner.get(p_material); - ERR_FAIL_COND_V(!material,0); - - return material->line_width; -} - -/* MESH API */ - - -RID RasterizerDummy::mesh_create() { - - - return mesh_owner.make_rid( memnew( Mesh ) ); -} - - -void RasterizerDummy::mesh_add_surface(RID p_mesh,VS::PrimitiveType p_primitive,const Array& p_arrays,const Array& p_blend_shapes,bool p_alpha_sort) { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND(!mesh); - - ERR_FAIL_INDEX( p_primitive, VS::PRIMITIVE_MAX ); - ERR_FAIL_COND(p_arrays.size()!=VS::ARRAY_MAX); - - Surface s; - - - s.format=0; - - for(int i=0;i<p_arrays.size();i++) { - - if (p_arrays[i].get_type()==Variant::NIL) - continue; - - s.format|=(1<<i); - - if (i==VS::ARRAY_VERTEX) { - - Vector3Array v = p_arrays[i]; - int len = v.size(); - ERR_FAIL_COND(len==0); - Vector3Array::Read r = v.read(); - - - for(int i=0;i<len;i++) { - - if (i==0) - s.aabb.pos=r[0]; - else - s.aabb.expand_to(r[i]); - } - - } - } - - ERR_FAIL_COND((s.format&VS::ARRAY_FORMAT_VERTEX)==0); // mandatory - - s.data=p_arrays; - s.morph_data=p_blend_shapes; - s.primitive=p_primitive; - s.alpha_sort=p_alpha_sort; - s.morph_target_count=mesh->morph_target_count; - s.morph_format=s.format; - - - Surface *surface = memnew( Surface ); - *surface=s; - - mesh->surfaces.push_back(surface); - - -} - - - -void RasterizerDummy::mesh_add_custom_surface(RID p_mesh,const Variant& p_dat) { - - ERR_EXPLAIN("Dummy Rasterizer does not support custom surfaces. Running on wrong platform?"); - ERR_FAIL_V(); -} - -Array RasterizerDummy::mesh_get_surface_arrays(RID p_mesh,int p_surface) const { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND_V(!mesh,Array()); - ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), Array() ); - Surface *surface = mesh->surfaces[p_surface]; - ERR_FAIL_COND_V( !surface, Array() ); - - return surface->data; - - -} -Array RasterizerDummy::mesh_get_surface_morph_arrays(RID p_mesh,int p_surface) const{ - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND_V(!mesh,Array()); - ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), Array() ); - Surface *surface = mesh->surfaces[p_surface]; - ERR_FAIL_COND_V( !surface, Array() ); - - return surface->morph_data; - -} - - -void RasterizerDummy::mesh_set_morph_target_count(RID p_mesh,int p_amount) { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND(!mesh); - ERR_FAIL_COND( mesh->surfaces.size()!=0 ); - - mesh->morph_target_count=p_amount; - -} - -int RasterizerDummy::mesh_get_morph_target_count(RID p_mesh) const{ - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND_V(!mesh,-1); - - return mesh->morph_target_count; - -} - -void RasterizerDummy::mesh_set_morph_target_mode(RID p_mesh,VS::MorphTargetMode p_mode) { - - ERR_FAIL_INDEX(p_mode,2); - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND(!mesh); - - mesh->morph_target_mode=p_mode; - -} - -VS::MorphTargetMode RasterizerDummy::mesh_get_morph_target_mode(RID p_mesh) const { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND_V(!mesh,VS::MORPH_MODE_NORMALIZED); - - return mesh->morph_target_mode; - -} - - - -void RasterizerDummy::mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material,bool p_owned) { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND(!mesh); - ERR_FAIL_INDEX(p_surface, mesh->surfaces.size() ); - Surface *surface = mesh->surfaces[p_surface]; - ERR_FAIL_COND( !surface); - - if (surface->material_owned && surface->material.is_valid()) - free(surface->material); - - surface->material_owned=p_owned; - surface->material=p_material; -} - -RID RasterizerDummy::mesh_surface_get_material(RID p_mesh, int p_surface) const { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND_V(!mesh,RID()); - ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), RID() ); - Surface *surface = mesh->surfaces[p_surface]; - ERR_FAIL_COND_V( !surface, RID() ); - - return surface->material; -} - -int RasterizerDummy::mesh_surface_get_array_len(RID p_mesh, int p_surface) const { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND_V(!mesh,-1); - ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), -1 ); - Surface *surface = mesh->surfaces[p_surface]; - ERR_FAIL_COND_V( !surface, -1 ); - - Vector3Array arr = surface->data[VS::ARRAY_VERTEX]; - return arr.size(); - -} - -int RasterizerDummy::mesh_surface_get_array_index_len(RID p_mesh, int p_surface) const { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND_V(!mesh,-1); - ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), -1 ); - Surface *surface = mesh->surfaces[p_surface]; - ERR_FAIL_COND_V( !surface, -1 ); - - IntArray arr = surface->data[VS::ARRAY_INDEX]; - return arr.size(); - -} -uint32_t RasterizerDummy::mesh_surface_get_format(RID p_mesh, int p_surface) const { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND_V(!mesh,0); - ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), 0 ); - Surface *surface = mesh->surfaces[p_surface]; - ERR_FAIL_COND_V( !surface, 0 ); - - return surface->format; -} -VS::PrimitiveType RasterizerDummy::mesh_surface_get_primitive_type(RID p_mesh, int p_surface) const { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND_V(!mesh,VS::PRIMITIVE_POINTS); - ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), VS::PRIMITIVE_POINTS ); - Surface *surface = mesh->surfaces[p_surface]; - ERR_FAIL_COND_V( !surface, VS::PRIMITIVE_POINTS ); - - return surface->primitive; -} - -void RasterizerDummy::mesh_remove_surface(RID p_mesh,int p_index) { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND(!mesh); - ERR_FAIL_INDEX(p_index, mesh->surfaces.size() ); - Surface *surface = mesh->surfaces[p_index]; - ERR_FAIL_COND( !surface); - - memdelete( mesh->surfaces[p_index] ); - mesh->surfaces.remove(p_index); - -} -int RasterizerDummy::mesh_get_surface_count(RID p_mesh) const { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND_V(!mesh,-1); - - return mesh->surfaces.size(); -} - -AABB RasterizerDummy::mesh_get_aabb(RID p_mesh,RID p_skeleton) const { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND_V(!mesh,AABB()); - - AABB aabb; - - for (int i=0;i<mesh->surfaces.size();i++) { - - if (i==0) - aabb=mesh->surfaces[i]->aabb; - else - aabb.merge_with(mesh->surfaces[i]->aabb); - } - - return aabb; -} - -void RasterizerDummy::mesh_set_custom_aabb(RID p_mesh,const AABB& p_aabb) { - - Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND(!mesh); - - mesh->custom_aabb=p_aabb; -} - -AABB RasterizerDummy::mesh_get_custom_aabb(RID p_mesh) const { - - const Mesh *mesh = mesh_owner.get( p_mesh ); - ERR_FAIL_COND_V(!mesh,AABB()); - - return mesh->custom_aabb; - -} - -/* MULTIMESH API */ - -RID RasterizerDummy::multimesh_create() { - - return multimesh_owner.make_rid( memnew( MultiMesh )); -} - -void RasterizerDummy::multimesh_set_instance_count(RID p_multimesh,int p_count) { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND(!multimesh); - - multimesh->elements.clear(); // make sure to delete everything, so it "fails" in all implementations - multimesh->elements.resize(p_count); - -} -int RasterizerDummy::multimesh_get_instance_count(RID p_multimesh) const { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND_V(!multimesh,-1); - - return multimesh->elements.size(); -} - -void RasterizerDummy::multimesh_set_mesh(RID p_multimesh,RID p_mesh) { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND(!multimesh); - - multimesh->mesh=p_mesh; - -} -void RasterizerDummy::multimesh_set_aabb(RID p_multimesh,const AABB& p_aabb) { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND(!multimesh); - multimesh->aabb=p_aabb; -} -void RasterizerDummy::multimesh_instance_set_transform(RID p_multimesh,int p_index,const Transform& p_transform) { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND(!multimesh); - ERR_FAIL_INDEX(p_index,multimesh->elements.size()); - multimesh->elements[p_index].xform=p_transform; - -} -void RasterizerDummy::multimesh_instance_set_color(RID p_multimesh,int p_index,const Color& p_color) { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND(!multimesh) - ERR_FAIL_INDEX(p_index,multimesh->elements.size()); - multimesh->elements[p_index].color=p_color; - -} - -RID RasterizerDummy::multimesh_get_mesh(RID p_multimesh) const { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND_V(!multimesh,RID()); - - return multimesh->mesh; -} -AABB RasterizerDummy::multimesh_get_aabb(RID p_multimesh) const { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND_V(!multimesh,AABB()); - - return multimesh->aabb; -} - -Transform RasterizerDummy::multimesh_instance_get_transform(RID p_multimesh,int p_index) const { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND_V(!multimesh,Transform()); - - ERR_FAIL_INDEX_V(p_index,multimesh->elements.size(),Transform()); - - return multimesh->elements[p_index].xform; - -} -Color RasterizerDummy::multimesh_instance_get_color(RID p_multimesh,int p_index) const { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND_V(!multimesh,Color()); - ERR_FAIL_INDEX_V(p_index,multimesh->elements.size(),Color()); - - return multimesh->elements[p_index].color; -} - -void RasterizerDummy::multimesh_set_visible_instances(RID p_multimesh,int p_visible) { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND(!multimesh); - multimesh->visible=p_visible; - -} - -int RasterizerDummy::multimesh_get_visible_instances(RID p_multimesh) const { - - MultiMesh *multimesh = multimesh_owner.get(p_multimesh); - ERR_FAIL_COND_V(!multimesh,-1); - return multimesh->visible; - -} - -/* IMMEDIATE API */ - - -RID RasterizerDummy::immediate_create() { - - Immediate *im = memnew( Immediate ); - return immediate_owner.make_rid(im); - -} - -void RasterizerDummy::immediate_begin(RID p_immediate,VS::PrimitiveType p_rimitive,RID p_texture){ - - -} -void RasterizerDummy::immediate_vertex(RID p_immediate,const Vector3& p_vertex){ - - -} -void RasterizerDummy::immediate_normal(RID p_immediate,const Vector3& p_normal){ - - -} -void RasterizerDummy::immediate_tangent(RID p_immediate,const Plane& p_tangent){ - - -} -void RasterizerDummy::immediate_color(RID p_immediate,const Color& p_color){ - - -} -void RasterizerDummy::immediate_uv(RID p_immediate,const Vector2& tex_uv){ - - -} -void RasterizerDummy::immediate_uv2(RID p_immediate,const Vector2& tex_uv){ - - -} - -void RasterizerDummy::immediate_end(RID p_immediate){ - - -} -void RasterizerDummy::immediate_clear(RID p_immediate) { - - -} - -AABB RasterizerDummy::immediate_get_aabb(RID p_immediate) const { - - return AABB(Vector3(-1,-1,-1),Vector3(2,2,2)); -} - -void RasterizerDummy::immediate_set_material(RID p_immediate,RID p_material) { - - Immediate *im = immediate_owner.get(p_immediate); - ERR_FAIL_COND(!im); - im->material=p_material; - -} - -RID RasterizerDummy::immediate_get_material(RID p_immediate) const { - - const Immediate *im = immediate_owner.get(p_immediate); - ERR_FAIL_COND_V(!im,RID()); - return im->material; - -} - -/* PARTICLES API */ - -RID RasterizerDummy::particles_create() { - - Particles *particles = memnew( Particles ); - ERR_FAIL_COND_V(!particles,RID()); - return particles_owner.make_rid(particles); -} - -void RasterizerDummy::particles_set_amount(RID p_particles, int p_amount) { - - ERR_FAIL_COND(p_amount<1); - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - particles->data.amount=p_amount; - -} - -int RasterizerDummy::particles_get_amount(RID p_particles) const { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,-1); - return particles->data.amount; - -} - -void RasterizerDummy::particles_set_emitting(RID p_particles, bool p_emitting) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - particles->data.emitting=p_emitting;; - -} -bool RasterizerDummy::particles_is_emitting(RID p_particles) const { - - const Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,false); - return particles->data.emitting; - -} - -void RasterizerDummy::particles_set_visibility_aabb(RID p_particles, const AABB& p_visibility) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - particles->data.visibility_aabb=p_visibility; - -} - -void RasterizerDummy::particles_set_emission_half_extents(RID p_particles, const Vector3& p_half_extents) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - - particles->data.emission_half_extents=p_half_extents; -} -Vector3 RasterizerDummy::particles_get_emission_half_extents(RID p_particles) const { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,Vector3()); - - return particles->data.emission_half_extents; -} - -void RasterizerDummy::particles_set_emission_base_velocity(RID p_particles, const Vector3& p_base_velocity) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - - particles->data.emission_base_velocity=p_base_velocity; -} - -Vector3 RasterizerDummy::particles_get_emission_base_velocity(RID p_particles) const { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,Vector3()); - - return particles->data.emission_base_velocity; -} - - -void RasterizerDummy::particles_set_emission_points(RID p_particles, const DVector<Vector3>& p_points) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - - particles->data.emission_points=p_points; -} - -DVector<Vector3> RasterizerDummy::particles_get_emission_points(RID p_particles) const { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,DVector<Vector3>()); - - return particles->data.emission_points; - -} - -void RasterizerDummy::particles_set_gravity_normal(RID p_particles, const Vector3& p_normal) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - - particles->data.gravity_normal=p_normal; - -} -Vector3 RasterizerDummy::particles_get_gravity_normal(RID p_particles) const { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,Vector3()); - - return particles->data.gravity_normal; -} - - -AABB RasterizerDummy::particles_get_visibility_aabb(RID p_particles) const { - - const Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,AABB()); - return particles->data.visibility_aabb; - -} - -void RasterizerDummy::particles_set_variable(RID p_particles, VS::ParticleVariable p_variable,float p_value) { - - ERR_FAIL_INDEX(p_variable,VS::PARTICLE_VAR_MAX); - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - particles->data.particle_vars[p_variable]=p_value; - -} -float RasterizerDummy::particles_get_variable(RID p_particles, VS::ParticleVariable p_variable) const { - - const Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,-1); - return particles->data.particle_vars[p_variable]; -} - -void RasterizerDummy::particles_set_randomness(RID p_particles, VS::ParticleVariable p_variable,float p_randomness) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - particles->data.particle_randomness[p_variable]=p_randomness; - -} -float RasterizerDummy::particles_get_randomness(RID p_particles, VS::ParticleVariable p_variable) const { - - const Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,-1); - return particles->data.particle_randomness[p_variable]; - -} - -void RasterizerDummy::particles_set_color_phases(RID p_particles, int p_phases) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - ERR_FAIL_COND( p_phases<0 || p_phases>VS::MAX_PARTICLE_COLOR_PHASES ); - particles->data.color_phase_count=p_phases; - -} -int RasterizerDummy::particles_get_color_phases(RID p_particles) const { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,-1); - return particles->data.color_phase_count; -} - - -void RasterizerDummy::particles_set_color_phase_pos(RID p_particles, int p_phase, float p_pos) { - - ERR_FAIL_INDEX(p_phase, VS::MAX_PARTICLE_COLOR_PHASES); - if (p_pos<0.0) - p_pos=0.0; - if (p_pos>1.0) - p_pos=1.0; - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - particles->data.color_phases[p_phase].pos=p_pos; - -} -float RasterizerDummy::particles_get_color_phase_pos(RID p_particles, int p_phase) const { - - ERR_FAIL_INDEX_V(p_phase, VS::MAX_PARTICLE_COLOR_PHASES, -1.0); - - const Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,-1); - return particles->data.color_phases[p_phase].pos; - -} - -void RasterizerDummy::particles_set_color_phase_color(RID p_particles, int p_phase, const Color& p_color) { - - ERR_FAIL_INDEX(p_phase, VS::MAX_PARTICLE_COLOR_PHASES); - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - particles->data.color_phases[p_phase].color=p_color; - - //update alpha - particles->has_alpha=false; - for(int i=0;i<VS::MAX_PARTICLE_COLOR_PHASES;i++) { - if (particles->data.color_phases[i].color.a<0.99) - particles->has_alpha=true; - } - -} - -Color RasterizerDummy::particles_get_color_phase_color(RID p_particles, int p_phase) const { - - ERR_FAIL_INDEX_V(p_phase, VS::MAX_PARTICLE_COLOR_PHASES, Color()); - - const Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,Color()); - return particles->data.color_phases[p_phase].color; - -} - -void RasterizerDummy::particles_set_attractors(RID p_particles, int p_attractors) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - ERR_FAIL_COND( p_attractors<0 || p_attractors>VisualServer::MAX_PARTICLE_ATTRACTORS ); - particles->data.attractor_count=p_attractors; - -} -int RasterizerDummy::particles_get_attractors(RID p_particles) const { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,-1); - return particles->data.attractor_count; -} - -void RasterizerDummy::particles_set_attractor_pos(RID p_particles, int p_attractor, const Vector3& p_pos) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - ERR_FAIL_INDEX(p_attractor,particles->data.attractor_count); - particles->data.attractors[p_attractor].pos=p_pos;; -} -Vector3 RasterizerDummy::particles_get_attractor_pos(RID p_particles,int p_attractor) const { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,Vector3()); - ERR_FAIL_INDEX_V(p_attractor,particles->data.attractor_count,Vector3()); - return particles->data.attractors[p_attractor].pos; -} - -void RasterizerDummy::particles_set_attractor_strength(RID p_particles, int p_attractor, float p_force) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - ERR_FAIL_INDEX(p_attractor,particles->data.attractor_count); - particles->data.attractors[p_attractor].force=p_force; -} - -float RasterizerDummy::particles_get_attractor_strength(RID p_particles,int p_attractor) const { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,0); - ERR_FAIL_INDEX_V(p_attractor,particles->data.attractor_count,0); - return particles->data.attractors[p_attractor].force; -} - -void RasterizerDummy::particles_set_material(RID p_particles, RID p_material,bool p_owned) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - if (particles->material_owned && particles->material.is_valid()) - free(particles->material); - - particles->material_owned=p_owned; - - particles->material=p_material; - -} -RID RasterizerDummy::particles_get_material(RID p_particles) const { - - const Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,RID()); - return particles->material; - -} - -void RasterizerDummy::particles_set_use_local_coordinates(RID p_particles, bool p_enable) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - particles->data.local_coordinates=p_enable; - -} - -bool RasterizerDummy::particles_is_using_local_coordinates(RID p_particles) const { - - const Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,false); - return particles->data.local_coordinates; -} -bool RasterizerDummy::particles_has_height_from_velocity(RID p_particles) const { - - const Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,false); - return particles->data.height_from_velocity; -} - -void RasterizerDummy::particles_set_height_from_velocity(RID p_particles, bool p_enable) { - - Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND(!particles); - particles->data.height_from_velocity=p_enable; - -} - -AABB RasterizerDummy::particles_get_aabb(RID p_particles) const { - - const Particles* particles = particles_owner.get( p_particles ); - ERR_FAIL_COND_V(!particles,AABB()); - return particles->data.visibility_aabb; -} - -/* SKELETON API */ - -RID RasterizerDummy::skeleton_create() { - - Skeleton *skeleton = memnew( Skeleton ); - ERR_FAIL_COND_V(!skeleton,RID()); - return skeleton_owner.make_rid( skeleton ); -} -void RasterizerDummy::skeleton_resize(RID p_skeleton,int p_bones) { - - Skeleton *skeleton = skeleton_owner.get( p_skeleton ); - ERR_FAIL_COND(!skeleton); - if (p_bones == skeleton->bones.size()) { - return; - }; - - skeleton->bones.resize(p_bones); - -} -int RasterizerDummy::skeleton_get_bone_count(RID p_skeleton) const { - - Skeleton *skeleton = skeleton_owner.get( p_skeleton ); - ERR_FAIL_COND_V(!skeleton, -1); - return skeleton->bones.size(); -} -void RasterizerDummy::skeleton_bone_set_transform(RID p_skeleton,int p_bone, const Transform& p_transform) { - - Skeleton *skeleton = skeleton_owner.get( p_skeleton ); - ERR_FAIL_COND(!skeleton); - ERR_FAIL_INDEX( p_bone, skeleton->bones.size() ); - - skeleton->bones[p_bone] = p_transform; -} - -Transform RasterizerDummy::skeleton_bone_get_transform(RID p_skeleton,int p_bone) { - - Skeleton *skeleton = skeleton_owner.get( p_skeleton ); - ERR_FAIL_COND_V(!skeleton, Transform()); - ERR_FAIL_INDEX_V( p_bone, skeleton->bones.size(), Transform() ); - - // something - return skeleton->bones[p_bone]; -} - - -/* LIGHT API */ - -RID RasterizerDummy::light_create(VS::LightType p_type) { - - Light *light = memnew( Light ); - light->type=p_type; - return light_owner.make_rid(light); -} - -VS::LightType RasterizerDummy::light_get_type(RID p_light) const { - - Light *light = light_owner.get(p_light); - ERR_FAIL_COND_V(!light,VS::LIGHT_OMNI); - return light->type; -} - -void RasterizerDummy::light_set_color(RID p_light,VS::LightColor p_type, const Color& p_color) { - - Light *light = light_owner.get(p_light); - ERR_FAIL_COND(!light); - ERR_FAIL_INDEX( p_type, 3 ); - light->colors[p_type]=p_color; -} -Color RasterizerDummy::light_get_color(RID p_light,VS::LightColor p_type) const { - - Light *light = light_owner.get(p_light); - ERR_FAIL_COND_V(!light, Color()); - ERR_FAIL_INDEX_V( p_type, 3, Color() ); - return light->colors[p_type]; -} - -void RasterizerDummy::light_set_shadow(RID p_light,bool p_enabled) { - - Light *light = light_owner.get(p_light); - ERR_FAIL_COND(!light); - light->shadow_enabled=p_enabled; -} - -bool RasterizerDummy::light_has_shadow(RID p_light) const { - - Light *light = light_owner.get(p_light); - ERR_FAIL_COND_V(!light,false); - return light->shadow_enabled; -} - -void RasterizerDummy::light_set_volumetric(RID p_light,bool p_enabled) { - - Light *light = light_owner.get(p_light); - ERR_FAIL_COND(!light); - light->volumetric_enabled=p_enabled; - -} -bool RasterizerDummy::light_is_volumetric(RID p_light) const { - - Light *light = light_owner.get(p_light); - ERR_FAIL_COND_V(!light,false); - return light->volumetric_enabled; -} - -void RasterizerDummy::light_set_projector(RID p_light,RID p_texture) { - - Light *light = light_owner.get(p_light); - ERR_FAIL_COND(!light); - light->projector=p_texture; -} -RID RasterizerDummy::light_get_projector(RID p_light) const { - - Light *light = light_owner.get(p_light); - ERR_FAIL_COND_V(!light,RID()); - return light->projector; -} - -void RasterizerDummy::light_set_var(RID p_light, VS::LightParam p_var, float p_value) { - - Light * light = light_owner.get( p_light ); - ERR_FAIL_COND(!light); - ERR_FAIL_INDEX( p_var, VS::LIGHT_PARAM_MAX ); - - light->vars[p_var]=p_value; -} -float RasterizerDummy::light_get_var(RID p_light, VS::LightParam p_var) const { - - Light * light = light_owner.get( p_light ); - ERR_FAIL_COND_V(!light,0); - - ERR_FAIL_INDEX_V( p_var, VS::LIGHT_PARAM_MAX,0 ); - - return light->vars[p_var]; -} - -void RasterizerDummy::light_set_operator(RID p_light,VS::LightOp p_op) { - - Light * light = light_owner.get( p_light ); - ERR_FAIL_COND(!light); - - -}; - -VS::LightOp RasterizerDummy::light_get_operator(RID p_light) const { - - return VS::LightOp(0); -}; - -void RasterizerDummy::light_omni_set_shadow_mode(RID p_light,VS::LightOmniShadowMode p_mode) { - - -} - -VS::LightOmniShadowMode RasterizerDummy::light_omni_get_shadow_mode(RID p_light) const{ - - return VS::LightOmniShadowMode(0); -} - -void RasterizerDummy::light_directional_set_shadow_mode(RID p_light,VS::LightDirectionalShadowMode p_mode) { - - -} - -VS::LightDirectionalShadowMode RasterizerDummy::light_directional_get_shadow_mode(RID p_light) const { - - return VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL; -} - -void RasterizerDummy::light_directional_set_shadow_param(RID p_light,VS::LightDirectionalShadowParam p_param, float p_value) { - - -} - -float RasterizerDummy::light_directional_get_shadow_param(RID p_light,VS::LightDirectionalShadowParam p_param) const { - - return 0; -} - - -AABB RasterizerDummy::light_get_aabb(RID p_light) const { - - Light *light = light_owner.get( p_light ); - ERR_FAIL_COND_V(!light,AABB()); - - switch( light->type ) { - - case VS::LIGHT_SPOT: { - - float len=light->vars[VS::LIGHT_PARAM_RADIUS]; - float size=Math::tan(Math::deg2rad(light->vars[VS::LIGHT_PARAM_SPOT_ANGLE]))*len; - return AABB( Vector3( -size,-size,-len ), Vector3( size*2, size*2, len ) ); - } break; - case VS::LIGHT_OMNI: { - - float r = light->vars[VS::LIGHT_PARAM_RADIUS]; - return AABB( -Vector3(r,r,r), Vector3(r,r,r)*2 ); - } break; - case VS::LIGHT_DIRECTIONAL: { - - return AABB(); - } break; - default: {} - } - - ERR_FAIL_V( AABB() ); -} - - -RID RasterizerDummy::light_instance_create(RID p_light) { - - Light *light = light_owner.get( p_light ); - ERR_FAIL_COND_V(!light, RID()); - - LightInstance *light_instance = memnew( LightInstance ); - - light_instance->light=p_light; - light_instance->base=light; - - - return light_instance_owner.make_rid( light_instance ); -} -void RasterizerDummy::light_instance_set_transform(RID p_light_instance,const Transform& p_transform) { - - LightInstance *lighti = light_instance_owner.get( p_light_instance ); - ERR_FAIL_COND(!lighti); - lighti->transform=p_transform; - -} - -bool RasterizerDummy::light_instance_has_shadow(RID p_light_instance) const { - - return false; - -} - - -bool RasterizerDummy::light_instance_assign_shadow(RID p_light_instance) { - - return false; - -} - - -Rasterizer::ShadowType RasterizerDummy::light_instance_get_shadow_type(RID p_light_instance) const { - - LightInstance *lighti = light_instance_owner.get( p_light_instance ); - ERR_FAIL_COND_V(!lighti,Rasterizer::SHADOW_NONE); - - switch(lighti->base->type) { - - case VS::LIGHT_DIRECTIONAL: return SHADOW_PSM; break; - case VS::LIGHT_OMNI: return SHADOW_DUAL_PARABOLOID; break; - case VS::LIGHT_SPOT: return SHADOW_SIMPLE; break; - } - - return Rasterizer::SHADOW_NONE; -} - -Rasterizer::ShadowType RasterizerDummy::light_instance_get_shadow_type(RID p_light_instance,bool p_far) const { - - return SHADOW_NONE; -} -void RasterizerDummy::light_instance_set_shadow_transform(RID p_light_instance, int p_index, const CameraMatrix& p_camera, const Transform& p_transform, float p_split_near,float p_split_far) { - - -} - -int RasterizerDummy::light_instance_get_shadow_passes(RID p_light_instance) const { - - return 0; -} - -bool RasterizerDummy::light_instance_get_pssm_shadow_overlap(RID p_light_instance) const { - - return false; -} - - -void RasterizerDummy::light_instance_set_custom_transform(RID p_light_instance, int p_index, const CameraMatrix& p_camera, const Transform& p_transform, float p_split_near,float p_split_far) { - - LightInstance *lighti = light_instance_owner.get( p_light_instance ); - ERR_FAIL_COND(!lighti); - - ERR_FAIL_COND(lighti->base->type!=VS::LIGHT_DIRECTIONAL); - ERR_FAIL_INDEX(p_index,1); - - lighti->custom_projection=p_camera; - lighti->custom_transform=p_transform; - -} -void RasterizerDummy::shadow_clear_near() { - - -} - -bool RasterizerDummy::shadow_allocate_near(RID p_light) { - - return false; -} - -bool RasterizerDummy::shadow_allocate_far(RID p_light) { - - return false; -} - -/* PARTICLES INSTANCE */ - -RID RasterizerDummy::particles_instance_create(RID p_particles) { - - ERR_FAIL_COND_V(!particles_owner.owns(p_particles),RID()); - ParticlesInstance *particles_instance = memnew( ParticlesInstance ); - ERR_FAIL_COND_V(!particles_instance, RID() ); - particles_instance->particles=p_particles; - return particles_instance_owner.make_rid(particles_instance); -} - -void RasterizerDummy::particles_instance_set_transform(RID p_particles_instance,const Transform& p_transform) { - - ParticlesInstance *particles_instance=particles_instance_owner.get(p_particles_instance); - ERR_FAIL_COND(!particles_instance); - particles_instance->transform=p_transform; -} - - -/* RENDER API */ -/* all calls (inside begin/end shadow) are always warranted to be in the following order: */ - - -RID RasterizerDummy::viewport_data_create() { - - return RID(); -} - -RID RasterizerDummy::render_target_create(){ - - return RID(); - -} -void RasterizerDummy::render_target_set_size(RID p_render_target, int p_width, int p_height){ - - -} -RID RasterizerDummy::render_target_get_texture(RID p_render_target) const{ - - return RID(); - -} -bool RasterizerDummy::render_target_renedered_in_frame(RID p_render_target){ - - return false; -} - - -void RasterizerDummy::begin_frame() { - - - -} - -void RasterizerDummy::capture_viewport(Image* r_capture) { - - -} - - -void RasterizerDummy::clear_viewport(const Color& p_color) { - - -}; - -void RasterizerDummy::set_viewport(const VS::ViewportRect& p_viewport) { - - - -} - -void RasterizerDummy::set_render_target(RID p_render_target, bool p_transparent_bg, bool p_vflip) { - - -} - - -void RasterizerDummy::begin_scene(RID p_viewport_data,RID p_env,VS::ScenarioDebugMode p_debug) { - - -}; - -void RasterizerDummy::begin_shadow_map( RID p_light_instance, int p_shadow_pass ) { - -} - -void RasterizerDummy::set_camera(const Transform& p_world, const CameraMatrix& p_projection, bool p_ortho_hint) { - - -} - -void RasterizerDummy::add_light( RID p_light_instance ) { - - - -} - - - - -void RasterizerDummy::add_mesh( const RID& p_mesh, const InstanceData *p_data) { - - -} - -void RasterizerDummy::add_multimesh( const RID& p_multimesh, const InstanceData *p_data){ - - - - -} - -void RasterizerDummy::add_particles( const RID& p_particle_instance, const InstanceData *p_data){ - - - -} - - - -void RasterizerDummy::end_scene() { - - -} -void RasterizerDummy::end_shadow_map() { - -} - - -void RasterizerDummy::end_frame() { - - -} - -RID RasterizerDummy::canvas_light_occluder_create() { - return RID(); -} - -void RasterizerDummy::canvas_light_occluder_set_polylines(RID p_occluder, const DVector<Vector2>& p_lines) { - - -} - -RID RasterizerDummy::canvas_light_shadow_buffer_create(int p_width) { - - return RID(); -} - -void RasterizerDummy::canvas_light_shadow_buffer_update(RID p_buffer, const Matrix32& p_light_xform, int p_light_mask,float p_near, float p_far, CanvasLightOccluderInstance* p_occluders, CameraMatrix *p_xform_cache) { - - -} - -void RasterizerDummy::canvas_debug_viewport_shadows(CanvasLight* p_lights_with_shadow) { - - -} - -/* CANVAS API */ - - -void RasterizerDummy::begin_canvas_bg() { - -} -void RasterizerDummy::canvas_begin() { - - - -} -void RasterizerDummy::canvas_disable_blending() { - - - -} - -void RasterizerDummy::canvas_set_opacity(float p_opacity) { - - -} - -void RasterizerDummy::canvas_set_blend_mode(VS::MaterialBlendMode p_mode) { - - -} - - -void RasterizerDummy::canvas_begin_rect(const Matrix32& p_transform) { - - - -} - -void RasterizerDummy::canvas_set_clip(bool p_clip, const Rect2& p_rect) { - - - - -} - -void RasterizerDummy::canvas_end_rect() { - - -} - -void RasterizerDummy::canvas_draw_line(const Point2& p_from, const Point2& p_to, const Color& p_color, float p_width, bool p_antialiased) { - - - -} - -void RasterizerDummy::canvas_draw_rect(const Rect2& p_rect, int p_flags, const Rect2& p_source,RID p_texture,const Color& p_modulate) { - - - - -} -void RasterizerDummy::canvas_draw_style_box(const Rect2& p_rect, const Rect2& p_src_region, RID p_texture,const float *p_margin, bool p_draw_center,const Color& p_modulate) { - - -} -void RasterizerDummy::canvas_draw_primitive(const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs, RID p_texture,float p_width) { - - - -} - - -void RasterizerDummy::canvas_draw_polygon(int p_vertex_count, const int* p_indices, const Vector2* p_vertices, const Vector2* p_uvs, const Color* p_colors,const RID& p_texture,bool p_singlecolor) { - - - -} - -void RasterizerDummy::canvas_set_transform(const Matrix32& p_transform) { - - -} - -void RasterizerDummy::canvas_render_items(CanvasItem *p_item_list,int p_z,const Color& p_modulate,CanvasLight *p_light) { - - -} - -/* ENVIRONMENT */ - -RID RasterizerDummy::environment_create() { - - Environment * env = memnew( Environment ); - return environment_owner.make_rid(env); -} - -void RasterizerDummy::environment_set_background(RID p_env,VS::EnvironmentBG p_bg) { - - ERR_FAIL_INDEX(p_bg,VS::ENV_BG_MAX); - Environment * env = environment_owner.get(p_env); - ERR_FAIL_COND(!env); - env->bg_mode=p_bg; -} - -VS::EnvironmentBG RasterizerDummy::environment_get_background(RID p_env) const{ - - const Environment * env = environment_owner.get(p_env); - ERR_FAIL_COND_V(!env,VS::ENV_BG_MAX); - return env->bg_mode; -} - -void RasterizerDummy::environment_set_background_param(RID p_env,VS::EnvironmentBGParam p_param, const Variant& p_value){ - - ERR_FAIL_INDEX(p_param,VS::ENV_BG_PARAM_MAX); - Environment * env = environment_owner.get(p_env); - ERR_FAIL_COND(!env); - env->bg_param[p_param]=p_value; - -} -Variant RasterizerDummy::environment_get_background_param(RID p_env,VS::EnvironmentBGParam p_param) const{ - - ERR_FAIL_INDEX_V(p_param,VS::ENV_BG_PARAM_MAX,Variant()); - const Environment * env = environment_owner.get(p_env); - ERR_FAIL_COND_V(!env,Variant()); - return env->bg_param[p_param]; - -} - -void RasterizerDummy::environment_set_enable_fx(RID p_env,VS::EnvironmentFx p_effect,bool p_enabled){ - - ERR_FAIL_INDEX(p_effect,VS::ENV_FX_MAX); - Environment * env = environment_owner.get(p_env); - ERR_FAIL_COND(!env); - env->fx_enabled[p_effect]=p_enabled; -} -bool RasterizerDummy::environment_is_fx_enabled(RID p_env,VS::EnvironmentFx p_effect) const{ - - ERR_FAIL_INDEX_V(p_effect,VS::ENV_FX_MAX,false); - const Environment * env = environment_owner.get(p_env); - ERR_FAIL_COND_V(!env,false); - return env->fx_enabled[p_effect]; - -} - -void RasterizerDummy::environment_fx_set_param(RID p_env,VS::EnvironmentFxParam p_param,const Variant& p_value){ - - ERR_FAIL_INDEX(p_param,VS::ENV_FX_PARAM_MAX); - Environment * env = environment_owner.get(p_env); - ERR_FAIL_COND(!env); - env->fx_param[p_param]=p_value; -} -Variant RasterizerDummy::environment_fx_get_param(RID p_env,VS::EnvironmentFxParam p_param) const{ - - ERR_FAIL_INDEX_V(p_param,VS::ENV_FX_PARAM_MAX,Variant()); - const Environment * env = environment_owner.get(p_env); - ERR_FAIL_COND_V(!env,Variant()); - return env->fx_param[p_param]; - -} - - -RID RasterizerDummy::sampled_light_dp_create(int p_width,int p_height) { - - return sampled_light_owner.make_rid(memnew(SampledLight)); -} - -void RasterizerDummy::sampled_light_dp_update(RID p_sampled_light, const Color *p_data, float p_multiplier) { - - -} - - -/*MISC*/ - -bool RasterizerDummy::is_texture(const RID& p_rid) const { - - return texture_owner.owns(p_rid); -} -bool RasterizerDummy::is_material(const RID& p_rid) const { - - return material_owner.owns(p_rid); -} -bool RasterizerDummy::is_mesh(const RID& p_rid) const { - - return mesh_owner.owns(p_rid); -} - -bool RasterizerDummy::is_immediate(const RID& p_rid) const { - - return immediate_owner.owns(p_rid); -} - -bool RasterizerDummy::is_multimesh(const RID& p_rid) const { - - return multimesh_owner.owns(p_rid); -} -bool RasterizerDummy::is_particles(const RID &p_beam) const { - - return particles_owner.owns(p_beam); -} - -bool RasterizerDummy::is_light(const RID& p_rid) const { - - return light_owner.owns(p_rid); -} -bool RasterizerDummy::is_light_instance(const RID& p_rid) const { - - return light_instance_owner.owns(p_rid); -} -bool RasterizerDummy::is_particles_instance(const RID& p_rid) const { - - return particles_instance_owner.owns(p_rid); -} -bool RasterizerDummy::is_skeleton(const RID& p_rid) const { - - return skeleton_owner.owns(p_rid); -} -bool RasterizerDummy::is_environment(const RID& p_rid) const { - - return environment_owner.owns(p_rid); -} - -bool RasterizerDummy::is_canvas_light_occluder(const RID& p_rid) const { - - return false; -} - -bool RasterizerDummy::is_shader(const RID& p_rid) const { - - return false; -} - -void RasterizerDummy::free(const RID& p_rid) { - - if (texture_owner.owns(p_rid)) { - - // delete the texture - Texture *texture = texture_owner.get(p_rid); - texture_owner.free(p_rid); - memdelete(texture); - - } else if (shader_owner.owns(p_rid)) { - - // delete the texture - Shader *shader = shader_owner.get(p_rid); - shader_owner.free(p_rid); - memdelete(shader); - - } else if (material_owner.owns(p_rid)) { - - Material *material = material_owner.get( p_rid ); - material_owner.free(p_rid); - memdelete(material); - - } else if (mesh_owner.owns(p_rid)) { - - Mesh *mesh = mesh_owner.get(p_rid); - - for (int i=0;i<mesh->surfaces.size();i++) { - - memdelete( mesh->surfaces[i] ); - }; - - mesh->surfaces.clear(); - mesh_owner.free(p_rid); - memdelete(mesh); - - } else if (multimesh_owner.owns(p_rid)) { - - MultiMesh *multimesh = multimesh_owner.get(p_rid); - multimesh_owner.free(p_rid); - memdelete(multimesh); - - } else if (immediate_owner.owns(p_rid)) { - - Immediate *immediate = immediate_owner.get(p_rid); - immediate_owner.free(p_rid); - memdelete(immediate); - - } else if (particles_owner.owns(p_rid)) { - - Particles *particles = particles_owner.get(p_rid); - particles_owner.free(p_rid); - memdelete(particles); - } else if (particles_instance_owner.owns(p_rid)) { - - ParticlesInstance *particles_isntance = particles_instance_owner.get(p_rid); - particles_instance_owner.free(p_rid); - memdelete(particles_isntance); - - } else if (skeleton_owner.owns(p_rid)) { - - Skeleton *skeleton = skeleton_owner.get( p_rid ); - skeleton_owner.free(p_rid); - memdelete(skeleton); - - } else if (light_owner.owns(p_rid)) { - - Light *light = light_owner.get( p_rid ); - light_owner.free(p_rid); - memdelete(light); - - } else if (light_instance_owner.owns(p_rid)) { - - LightInstance *light_instance = light_instance_owner.get( p_rid ); - light_instance_owner.free(p_rid); - memdelete( light_instance ); - - - } else if (environment_owner.owns(p_rid)) { - - Environment *env = environment_owner.get( p_rid ); - environment_owner.free(p_rid); - memdelete( env ); - } else if (sampled_light_owner.owns(p_rid)) { - - SampledLight *sampled_light = sampled_light_owner.get( p_rid ); - ERR_FAIL_COND(!sampled_light); - - sampled_light_owner.free(p_rid); - memdelete( sampled_light ); - - }; -} - - -void RasterizerDummy::custom_shade_model_set_shader(int p_model, RID p_shader) { - - -}; - -RID RasterizerDummy::custom_shade_model_get_shader(int p_model) const { - - return RID(); -}; - -void RasterizerDummy::custom_shade_model_set_name(int p_model, const String& p_name) { - -}; - -String RasterizerDummy::custom_shade_model_get_name(int p_model) const { - - return String(); -}; - -void RasterizerDummy::custom_shade_model_set_param_info(int p_model, const List<PropertyInfo>& p_info) { - -}; - -void RasterizerDummy::custom_shade_model_get_param_info(int p_model, List<PropertyInfo>* p_info) const { - -}; - - - -void RasterizerDummy::init() { - - -} - -void RasterizerDummy::finish() { - - -} - -int RasterizerDummy::get_render_info(VS::RenderInfo p_info) { - - return 0; -} - -bool RasterizerDummy::needs_to_draw_next_frame() const { - - return false; -} - - -bool RasterizerDummy::has_feature(VS::Features p_feature) const { - - return false; - -} - -void RasterizerDummy::restore_framebuffer() { - -} - -RasterizerDummy::RasterizerDummy() { - -}; - -RasterizerDummy::~RasterizerDummy() { - -}; diff --git a/servers/visual/rasterizer_dummy.h b/servers/visual/rasterizer_dummy.h deleted file mode 100644 index cac36eb6fc..0000000000 --- a/servers/visual/rasterizer_dummy.h +++ /dev/null @@ -1,791 +0,0 @@ -/*************************************************************************/ -/* rasterizer_dummy.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#ifndef RASTERIZER_DUMMY_H -#define RASTERIZER_DUMMY_H - -#include "servers/visual/rasterizer.h" - - -#include "image.h" -#include "rid.h" -#include "servers/visual_server.h" -#include "list.h" -#include "map.h" -#include "camera_matrix.h" -#include "sort.h" - - -#include "servers/visual/particle_system_sw.h" - -/** - @author Juan Linietsky <reduzio@gmail.com> -*/ -class RasterizerDummy : public Rasterizer { - - struct Texture { - - uint32_t flags; - int width,height; - Image::Format format; - Image image[6]; - Texture() { - - flags=width=height=0; - format=Image::FORMAT_GRAYSCALE; - } - - ~Texture() { - - } - }; - - mutable RID_Owner<Texture> texture_owner; - - struct Shader { - - String vertex_code; - String fragment_code; - String light_code; - VS::ShaderMode mode; - Map<StringName,Variant> params; - int fragment_line; - int vertex_line; - int light_line; - bool valid; - bool has_alpha; - bool use_world_transform; - - }; - - mutable RID_Owner<Shader> shader_owner; - - - struct Material { - - bool flags[VS::MATERIAL_FLAG_MAX]; - - VS::MaterialDepthDrawMode depth_draw_mode; - - VS::MaterialBlendMode blend_mode; - - float line_width; - float point_size; - - RID shader; // shader material - - Map<StringName,Variant> shader_params; - - - Material() { - - - for(int i=0;i<VS::MATERIAL_FLAG_MAX;i++) - flags[i]=false; - flags[VS::MATERIAL_FLAG_VISIBLE]=true; - - depth_draw_mode=VS::MATERIAL_DEPTH_DRAW_OPAQUE_ONLY; - line_width=1; - blend_mode=VS::MATERIAL_BLEND_MODE_MIX; - point_size = 1.0; - - } - }; - mutable RID_Owner<Material> material_owner; - - void _material_check_alpha(Material *p_material); - - - struct Geometry { - - enum Type { - GEOMETRY_INVALID, - GEOMETRY_SURFACE, - GEOMETRY_POLY, - GEOMETRY_PARTICLES, - GEOMETRY_MULTISURFACE, - }; - - Type type; - RID material; - bool has_alpha; - bool material_owned; - - Geometry() { has_alpha=false; material_owned = false; } - virtual ~Geometry() {}; - }; - - struct GeometryOwner { - - virtual ~GeometryOwner() {} - }; - - class Mesh; - - struct Surface : public Geometry { - - Array data; - Array morph_data; - - bool packed; - bool alpha_sort; - int morph_target_count; - AABB aabb; - - VS::PrimitiveType primitive; - - uint32_t format; - uint32_t morph_format; - - Surface() { - - packed=false; - morph_target_count=0; - material_owned=false; - format=0; - morph_format=0; - - primitive=VS::PRIMITIVE_POINTS; - } - - ~Surface() { - - } - }; - - - struct Mesh { - - bool active; - Vector<Surface*> surfaces; - int morph_target_count; - VS::MorphTargetMode morph_target_mode; - AABB custom_aabb; - - mutable uint64_t last_pass; - Mesh() { - morph_target_mode=VS::MORPH_MODE_NORMALIZED; - morph_target_count=0; - last_pass=0; - active=false; - } - }; - mutable RID_Owner<Mesh> mesh_owner; - - struct MultiMesh; - - struct MultiMeshSurface : public Geometry { - - Surface *surface; - MultiMeshSurface() { type=GEOMETRY_MULTISURFACE; } - }; - - struct MultiMesh : public GeometryOwner { - - struct Element { - - Transform xform; - Color color; - }; - - AABB aabb; - RID mesh; - int visible; - - //IDirect3DVertexBuffer9* instance_buffer; - Vector<Element> elements; - - MultiMesh() { - visible=-1; - } - - - }; - - - mutable RID_Owner<MultiMesh> multimesh_owner; - - struct Immediate { - - - RID material; - int empty; - }; - - mutable RID_Owner<Immediate> immediate_owner; - - struct Particles : public Geometry { - - ParticleSystemSW data; // software particle system - - Particles() { - type=GEOMETRY_PARTICLES; - - } - }; - - mutable RID_Owner<Particles> particles_owner; - - struct ParticlesInstance : public GeometryOwner { - - RID particles; - - ParticleSystemProcessSW particles_process; - Transform transform; - - ParticlesInstance() { } - }; - - mutable RID_Owner<ParticlesInstance> particles_instance_owner; - ParticleSystemDrawInfoSW particle_draw_info; - - struct Skeleton { - - Vector<Transform> bones; - - }; - - mutable RID_Owner<Skeleton> skeleton_owner; - - - struct Light { - - VS::LightType type; - float vars[VS::LIGHT_PARAM_MAX]; - Color colors[3]; - bool shadow_enabled; - RID projector; - bool volumetric_enabled; - Color volumetric_color; - - - Light() { - - vars[VS::LIGHT_PARAM_SPOT_ATTENUATION]=1; - vars[VS::LIGHT_PARAM_SPOT_ANGLE]=45; - vars[VS::LIGHT_PARAM_ATTENUATION]=1.0; - vars[VS::LIGHT_PARAM_ENERGY]=1.0; - vars[VS::LIGHT_PARAM_RADIUS]=1.0; - vars[VS::LIGHT_PARAM_SHADOW_Z_OFFSET]=0.05; - - colors[VS::LIGHT_COLOR_DIFFUSE]=Color(1,1,1); - colors[VS::LIGHT_COLOR_SPECULAR]=Color(1,1,1); - shadow_enabled=false; - volumetric_enabled=false; - } - }; - - - struct Environment { - - - VS::EnvironmentBG bg_mode; - Variant bg_param[VS::ENV_BG_PARAM_MAX]; - bool fx_enabled[VS::ENV_FX_MAX]; - Variant fx_param[VS::ENV_FX_PARAM_MAX]; - - Environment() { - - bg_mode=VS::ENV_BG_DEFAULT_COLOR; - bg_param[VS::ENV_BG_PARAM_COLOR]=Color(0,0,0); - bg_param[VS::ENV_BG_PARAM_TEXTURE]=RID(); - bg_param[VS::ENV_BG_PARAM_CUBEMAP]=RID(); - bg_param[VS::ENV_BG_PARAM_ENERGY]=1.0; - - for(int i=0;i<VS::ENV_FX_MAX;i++) - fx_enabled[i]=false; - - fx_param[VS::ENV_FX_PARAM_GLOW_BLUR_PASSES]=1; - fx_param[VS::ENV_FX_PARAM_GLOW_BLOOM]=0.0; - fx_param[VS::ENV_FX_PARAM_GLOW_BLOOM_TRESHOLD]=0.5; - fx_param[VS::ENV_FX_PARAM_DOF_BLUR_PASSES]=1; - fx_param[VS::ENV_FX_PARAM_DOF_BLUR_BEGIN]=100.0; - fx_param[VS::ENV_FX_PARAM_DOF_BLUR_RANGE]=10.0; - fx_param[VS::ENV_FX_PARAM_HDR_EXPOSURE]=0.4; - fx_param[VS::ENV_FX_PARAM_HDR_WHITE]=1.0; - fx_param[VS::ENV_FX_PARAM_HDR_GLOW_TRESHOLD]=0.95; - fx_param[VS::ENV_FX_PARAM_HDR_GLOW_SCALE]=0.2; - fx_param[VS::ENV_FX_PARAM_HDR_MIN_LUMINANCE]=0.4; - fx_param[VS::ENV_FX_PARAM_HDR_MAX_LUMINANCE]=8.0; - fx_param[VS::ENV_FX_PARAM_HDR_EXPOSURE_ADJUST_SPEED]=0.5; - fx_param[VS::ENV_FX_PARAM_FOG_BEGIN]=100.0; - fx_param[VS::ENV_FX_PARAM_FOG_ATTENUATION]=1.0; - fx_param[VS::ENV_FX_PARAM_FOG_BEGIN_COLOR]=Color(0,0,0); - fx_param[VS::ENV_FX_PARAM_FOG_END_COLOR]=Color(0,0,0); - fx_param[VS::ENV_FX_PARAM_FOG_BG]=true; - fx_param[VS::ENV_FX_PARAM_BCS_BRIGHTNESS]=1.0; - fx_param[VS::ENV_FX_PARAM_BCS_CONTRAST]=1.0; - fx_param[VS::ENV_FX_PARAM_BCS_SATURATION]=1.0; - - - } - - }; - - mutable RID_Owner<Environment> environment_owner; - - struct SampledLight { - - int w,h; - }; - - mutable RID_Owner<SampledLight> sampled_light_owner; - - struct ShadowBuffer; - - struct LightInstance { - - struct SplitInfo { - - CameraMatrix camera; - Transform transform; - float near; - float far; - }; - - RID light; - Light *base; - Transform transform; - CameraMatrix projection; - - Transform custom_transform; - CameraMatrix custom_projection; - - Vector3 light_vector; - Vector3 spot_vector; - float linear_att; - - - LightInstance() { linear_att=1.0; } - - }; - - mutable RID_Owner<Light> light_owner; - mutable RID_Owner<LightInstance> light_instance_owner; - - - RID default_material; - - - - -public: - - /* TEXTURE API */ - - virtual RID texture_create(); - virtual void texture_allocate(RID p_texture,int p_width, int p_height,Image::Format p_format,uint32_t p_flags=VS::TEXTURE_FLAGS_DEFAULT); - virtual void texture_set_data(RID p_texture,const Image& p_image,VS::CubeMapSide p_cube_side=VS::CUBEMAP_LEFT); - virtual Image texture_get_data(RID p_texture,VS::CubeMapSide p_cube_side=VS::CUBEMAP_LEFT) const; - virtual void texture_set_flags(RID p_texture,uint32_t p_flags); - virtual uint32_t texture_get_flags(RID p_texture) const; - virtual Image::Format texture_get_format(RID p_texture) const; - virtual uint32_t texture_get_width(RID p_texture) const; - virtual uint32_t texture_get_height(RID p_texture) const; - virtual bool texture_has_alpha(RID p_texture) const; - virtual void texture_set_size_override(RID p_texture,int p_width, int p_height); - virtual void texture_set_reload_hook(RID p_texture,ObjectID p_owner,const StringName& p_function) const; - - virtual void texture_set_path(RID p_texture,const String& p_path) {} - virtual String texture_get_path(RID p_texture) const { return String(); } - virtual void texture_debug_usage(List<VS::TextureInfo> *r_info) {} - - virtual void texture_set_shrink_all_x2_on_set_data(bool p_enable) {} - - /* SHADER API */ - - virtual RID shader_create(VS::ShaderMode p_mode=VS::SHADER_MATERIAL); - - virtual void shader_set_mode(RID p_shader,VS::ShaderMode p_mode); - virtual VS::ShaderMode shader_get_mode(RID p_shader) const; - - virtual void shader_set_code(RID p_shader, const String& p_vertex, const String& p_fragment,const String& p_light,int p_vertex_ofs=0,int p_fragment_ofs=0,int p_light_ofs=0); - virtual String shader_get_fragment_code(RID p_shader) const; - virtual String shader_get_vertex_code(RID p_shader) const; - virtual String shader_get_light_code(RID p_shader) const; - - virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const; - - - virtual void shader_set_default_texture_param(RID p_shader, const StringName& p_name, RID p_texture); - virtual RID shader_get_default_texture_param(RID p_shader, const StringName& p_name) const; - - virtual Variant shader_get_default_param(RID p_shader, const StringName& p_name); - - /* COMMON MATERIAL API */ - - virtual RID material_create(); - - virtual void material_set_shader(RID p_shader_material, RID p_shader); - virtual RID material_get_shader(RID p_shader_material) const; - - virtual void material_set_param(RID p_material, const StringName& p_param, const Variant& p_value); - virtual Variant material_get_param(RID p_material, const StringName& p_param) const; - - virtual void material_set_flag(RID p_material, VS::MaterialFlag p_flag,bool p_enabled); - virtual bool material_get_flag(RID p_material,VS::MaterialFlag p_flag) const; - - virtual void material_set_depth_draw_mode(RID p_material, VS::MaterialDepthDrawMode p_mode); - virtual VS::MaterialDepthDrawMode material_get_depth_draw_mode(RID p_material) const; - - virtual void material_set_blend_mode(RID p_material,VS::MaterialBlendMode p_mode); - virtual VS::MaterialBlendMode material_get_blend_mode(RID p_material) const; - - virtual void material_set_line_width(RID p_material,float p_line_width); - virtual float material_get_line_width(RID p_material) const; - - /* MESH API */ - - - virtual RID mesh_create(); - - virtual void mesh_add_surface(RID p_mesh,VS::PrimitiveType p_primitive,const Array& p_arrays,const Array& p_blend_shapes=Array(),bool p_alpha_sort=false); - virtual Array mesh_get_surface_arrays(RID p_mesh,int p_surface) const; - virtual Array mesh_get_surface_morph_arrays(RID p_mesh,int p_surface) const; - virtual void mesh_add_custom_surface(RID p_mesh,const Variant& p_dat); - - virtual void mesh_set_morph_target_count(RID p_mesh,int p_amount); - virtual int mesh_get_morph_target_count(RID p_mesh) const; - - virtual void mesh_set_morph_target_mode(RID p_mesh,VS::MorphTargetMode p_mode); - virtual VS::MorphTargetMode mesh_get_morph_target_mode(RID p_mesh) const; - - virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material,bool p_owned=false); - virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const; - - virtual int mesh_surface_get_array_len(RID p_mesh, int p_surface) const; - virtual int mesh_surface_get_array_index_len(RID p_mesh, int p_surface) const; - virtual uint32_t mesh_surface_get_format(RID p_mesh, int p_surface) const; - virtual VS::PrimitiveType mesh_surface_get_primitive_type(RID p_mesh, int p_surface) const; - - virtual void mesh_remove_surface(RID p_mesh,int p_index); - virtual int mesh_get_surface_count(RID p_mesh) const; - - virtual AABB mesh_get_aabb(RID p_mesh,RID p_skeleton=RID()) const; - - virtual void mesh_set_custom_aabb(RID p_mesh,const AABB& p_aabb); - virtual AABB mesh_get_custom_aabb(RID p_mesh) const; - - - /* MULTIMESH API */ - - virtual RID multimesh_create(); - - virtual void multimesh_set_instance_count(RID p_multimesh,int p_count); - virtual int multimesh_get_instance_count(RID p_multimesh) const; - - virtual void multimesh_set_mesh(RID p_multimesh,RID p_mesh); - virtual void multimesh_set_aabb(RID p_multimesh,const AABB& p_aabb); - virtual void multimesh_instance_set_transform(RID p_multimesh,int p_index,const Transform& p_transform); - virtual void multimesh_instance_set_color(RID p_multimesh,int p_index,const Color& p_color); - - virtual RID multimesh_get_mesh(RID p_multimesh) const; - virtual AABB multimesh_get_aabb(RID p_multimesh) const;; - - virtual Transform multimesh_instance_get_transform(RID p_multimesh,int p_index) const; - virtual Color multimesh_instance_get_color(RID p_multimesh,int p_index) const; - - virtual void multimesh_set_visible_instances(RID p_multimesh,int p_visible); - virtual int multimesh_get_visible_instances(RID p_multimesh) const; - - /* IMMEDIATE API */ - - virtual RID immediate_create(); - virtual void immediate_begin(RID p_immediate,VS::PrimitiveType p_rimitive,RID p_texture=RID()); - virtual void immediate_vertex(RID p_immediate,const Vector3& p_vertex); - virtual void immediate_normal(RID p_immediate,const Vector3& p_normal); - virtual void immediate_tangent(RID p_immediate,const Plane& p_tangent); - virtual void immediate_color(RID p_immediate,const Color& p_color); - virtual void immediate_uv(RID p_immediate,const Vector2& tex_uv); - virtual void immediate_uv2(RID p_immediate,const Vector2& tex_uv); - virtual void immediate_end(RID p_immediate); - virtual void immediate_clear(RID p_immediate); - virtual void immediate_set_material(RID p_immediate,RID p_material); - virtual RID immediate_get_material(RID p_immediate) const; - - virtual AABB immediate_get_aabb(RID p_mesh) const; - - /* PARTICLES API */ - - virtual RID particles_create(); - - virtual void particles_set_amount(RID p_particles, int p_amount); - virtual int particles_get_amount(RID p_particles) const; - - virtual void particles_set_emitting(RID p_particles, bool p_emitting); - virtual bool particles_is_emitting(RID p_particles) const; - - virtual void particles_set_visibility_aabb(RID p_particles, const AABB& p_visibility); - virtual AABB particles_get_visibility_aabb(RID p_particles) const; - - virtual void particles_set_emission_half_extents(RID p_particles, const Vector3& p_half_extents); - virtual Vector3 particles_get_emission_half_extents(RID p_particles) const; - - virtual void particles_set_emission_base_velocity(RID p_particles, const Vector3& p_base_velocity); - virtual Vector3 particles_get_emission_base_velocity(RID p_particles) const; - - virtual void particles_set_emission_points(RID p_particles, const DVector<Vector3>& p_points); - virtual DVector<Vector3> particles_get_emission_points(RID p_particles) const; - - virtual void particles_set_gravity_normal(RID p_particles, const Vector3& p_normal); - virtual Vector3 particles_get_gravity_normal(RID p_particles) const; - - virtual void particles_set_variable(RID p_particles, VS::ParticleVariable p_variable,float p_value); - virtual float particles_get_variable(RID p_particles, VS::ParticleVariable p_variable) const; - - virtual void particles_set_randomness(RID p_particles, VS::ParticleVariable p_variable,float p_randomness); - virtual float particles_get_randomness(RID p_particles, VS::ParticleVariable p_variable) const; - - virtual void particles_set_color_phase_pos(RID p_particles, int p_phase, float p_pos); - virtual float particles_get_color_phase_pos(RID p_particles, int p_phase) const; - - virtual void particles_set_color_phases(RID p_particles, int p_phases); - virtual int particles_get_color_phases(RID p_particles) const; - - virtual void particles_set_color_phase_color(RID p_particles, int p_phase, const Color& p_color); - virtual Color particles_get_color_phase_color(RID p_particles, int p_phase) const; - - virtual void particles_set_attractors(RID p_particles, int p_attractors); - virtual int particles_get_attractors(RID p_particles) const; - - virtual void particles_set_attractor_pos(RID p_particles, int p_attractor, const Vector3& p_pos); - virtual Vector3 particles_get_attractor_pos(RID p_particles,int p_attractor) const; - - virtual void particles_set_attractor_strength(RID p_particles, int p_attractor, float p_force); - virtual float particles_get_attractor_strength(RID p_particles,int p_attractor) const; - - virtual void particles_set_material(RID p_particles, RID p_material,bool p_owned=false); - virtual RID particles_get_material(RID p_particles) const; - - virtual AABB particles_get_aabb(RID p_particles) const; - - virtual void particles_set_height_from_velocity(RID p_particles, bool p_enable); - virtual bool particles_has_height_from_velocity(RID p_particles) const; - - virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable); - virtual bool particles_is_using_local_coordinates(RID p_particles) const; - - /* SKELETON API */ - - virtual RID skeleton_create(); - virtual void skeleton_resize(RID p_skeleton,int p_bones); - virtual int skeleton_get_bone_count(RID p_skeleton) const; - virtual void skeleton_bone_set_transform(RID p_skeleton,int p_bone, const Transform& p_transform); - virtual Transform skeleton_bone_get_transform(RID p_skeleton,int p_bone); - - - /* LIGHT API */ - - virtual RID light_create(VS::LightType p_type); - virtual VS::LightType light_get_type(RID p_light) const; - - virtual void light_set_color(RID p_light,VS::LightColor p_type, const Color& p_color); - virtual Color light_get_color(RID p_light,VS::LightColor p_type) const; - - virtual void light_set_shadow(RID p_light,bool p_enabled); - virtual bool light_has_shadow(RID p_light) const; - - virtual void light_set_volumetric(RID p_light,bool p_enabled); - virtual bool light_is_volumetric(RID p_light) const; - - virtual void light_set_projector(RID p_light,RID p_texture); - virtual RID light_get_projector(RID p_light) const; - - virtual void light_set_var(RID p_light, VS::LightParam p_var, float p_value); - virtual float light_get_var(RID p_light, VS::LightParam p_var) const; - - virtual void light_set_operator(RID p_light,VS::LightOp p_op); - virtual VS::LightOp light_get_operator(RID p_light) const; - - virtual void light_omni_set_shadow_mode(RID p_light,VS::LightOmniShadowMode p_mode); - virtual VS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) const; - - - virtual void light_directional_set_shadow_mode(RID p_light,VS::LightDirectionalShadowMode p_mode); - virtual VS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) const; - virtual void light_directional_set_shadow_param(RID p_light,VS::LightDirectionalShadowParam p_param, float p_value); - virtual float light_directional_get_shadow_param(RID p_light,VS::LightDirectionalShadowParam p_param) const; - - virtual AABB light_get_aabb(RID p_poly) const; - - - virtual RID light_instance_create(RID p_light); - virtual void light_instance_set_transform(RID p_light_instance,const Transform& p_transform); - - virtual bool light_instance_has_shadow(RID p_light_instance) const; - virtual bool light_instance_assign_shadow(RID p_light_instance); - virtual ShadowType light_instance_get_shadow_type(RID p_light_instance) const; - virtual int light_instance_get_shadow_passes(RID p_light_instance) const; - virtual bool light_instance_get_pssm_shadow_overlap(RID p_light_instance) const; - virtual void light_instance_set_custom_transform(RID p_light_instance, int p_index, const CameraMatrix& p_camera, const Transform& p_transform, float p_split_near=0,float p_split_far=0); - virtual int light_instance_get_shadow_size(RID p_light_instance, int p_index=0) const { return 1; } - - virtual ShadowType light_instance_get_shadow_type(RID p_light_instance,bool p_far=false) const; - virtual void light_instance_set_shadow_transform(RID p_light_instance, int p_index, const CameraMatrix& p_camera, const Transform& p_transform, float p_split_near=0,float p_split_far=0); - - virtual void shadow_clear_near(); - virtual bool shadow_allocate_near(RID p_light); - virtual bool shadow_allocate_far(RID p_light); - - - /* PARTICLES INSTANCE */ - - virtual RID particles_instance_create(RID p_particles); - virtual void particles_instance_set_transform(RID p_particles_instance,const Transform& p_transform); - - /* VIEWPORT */ - - virtual RID viewport_data_create(); - - virtual RID render_target_create(); - virtual void render_target_set_size(RID p_render_target, int p_width, int p_height); - virtual RID render_target_get_texture(RID p_render_target) const; - virtual bool render_target_renedered_in_frame(RID p_render_target); - - /* RENDER API */ - /* all calls (inside begin/end shadow) are always warranted to be in the following order: */ - - virtual void begin_frame(); - - virtual void set_viewport(const VS::ViewportRect& p_viewport); - virtual void set_render_target(RID p_render_target,bool p_transparent_bg=false,bool p_vflip=false); - virtual void clear_viewport(const Color& p_color); - virtual void capture_viewport(Image* r_capture); - - - virtual void begin_scene(RID p_viewport_data,RID p_env,VS::ScenarioDebugMode p_debug); - virtual void begin_shadow_map( RID p_light_instance, int p_shadow_pass ); - - virtual void set_camera(const Transform& p_world,const CameraMatrix& p_projection,bool p_ortho_hint); - - virtual void add_light( RID p_light_instance ); ///< all "add_light" calls happen before add_geometry calls - - - virtual void add_mesh( const RID& p_mesh, const InstanceData *p_data); - virtual void add_multimesh( const RID& p_multimesh, const InstanceData *p_data); - virtual void add_immediate( const RID& p_immediate, const InstanceData *p_data) {} - virtual void add_particles( const RID& p_particle_instance, const InstanceData *p_data); - - virtual void end_scene(); - virtual void end_shadow_map(); - - virtual void end_frame(); - - /* CANVAS API */ - - virtual void begin_canvas_bg(); - virtual void canvas_begin(); - virtual void canvas_disable_blending(); - virtual void canvas_set_opacity(float p_opacity); - virtual void canvas_set_blend_mode(VS::MaterialBlendMode p_mode); - virtual void canvas_begin_rect(const Matrix32& p_transform); - virtual void canvas_set_clip(bool p_clip, const Rect2& p_rect); - virtual void canvas_end_rect(); - virtual void canvas_draw_line(const Point2& p_from, const Point2& p_to,const Color& p_color,float p_width,bool p_antialiased); - virtual void canvas_draw_rect(const Rect2& p_rect, int p_flags, const Rect2& p_source,RID p_texture,const Color& p_modulate); - virtual void canvas_draw_style_box(const Rect2& p_rect, const Rect2& p_src_region, RID p_texture,const float *p_margins, bool p_draw_center=true,const Color& p_modulate=Color(1,1,1)); - virtual void canvas_draw_primitive(const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs, RID p_texture,float p_width); - virtual void canvas_draw_polygon(int p_vertex_count, const int* p_indices, const Vector2* p_vertices, const Vector2* p_uvs, const Color* p_colors,const RID& p_texture,bool p_singlecolor); - virtual void canvas_set_transform(const Matrix32& p_transform); - - virtual void canvas_render_items(CanvasItem *p_item_list,int p_z,const Color& p_modulate,CanvasLight *p_light); - - virtual RID canvas_light_occluder_create(); - virtual void canvas_light_occluder_set_polylines(RID p_occluder, const DVector<Vector2>& p_lines); - - virtual RID canvas_light_shadow_buffer_create(int p_width); - virtual void canvas_light_shadow_buffer_update(RID p_buffer, const Matrix32& p_light_xform, int p_light_mask,float p_near, float p_far, CanvasLightOccluderInstance* p_occluders, CameraMatrix *p_xform_cache); - - virtual void canvas_debug_viewport_shadows(CanvasLight* p_lights_with_shadow); - - /* ENVIRONMENT */ - - virtual RID environment_create(); - - virtual void environment_set_background(RID p_env,VS::EnvironmentBG p_bg); - virtual VS::EnvironmentBG environment_get_background(RID p_env) const; - - virtual void environment_set_background_param(RID p_env,VS::EnvironmentBGParam p_param, const Variant& p_value); - virtual Variant environment_get_background_param(RID p_env,VS::EnvironmentBGParam p_param) const; - - virtual void environment_set_enable_fx(RID p_env,VS::EnvironmentFx p_effect,bool p_enabled); - virtual bool environment_is_fx_enabled(RID p_env,VS::EnvironmentFx p_effect) const; - - virtual void environment_fx_set_param(RID p_env,VS::EnvironmentFxParam p_param,const Variant& p_value); - virtual Variant environment_fx_get_param(RID p_env,VS::EnvironmentFxParam p_param) const; - - /* SAMPLED LIGHT */ - virtual RID sampled_light_dp_create(int p_width,int p_height); - virtual void sampled_light_dp_update(RID p_sampled_light,const Color *p_data,float p_multiplier); - - - /*MISC*/ - - virtual bool is_texture(const RID& p_rid) const; - virtual bool is_material(const RID& p_rid) const; - virtual bool is_mesh(const RID& p_rid) const; - virtual bool is_immediate(const RID& p_rid) const; - virtual bool is_multimesh(const RID& p_rid) const; - virtual bool is_particles(const RID &p_beam) const; - - virtual bool is_light(const RID& p_rid) const; - virtual bool is_light_instance(const RID& p_rid) const; - virtual bool is_particles_instance(const RID& p_rid) const; - virtual bool is_skeleton(const RID& p_rid) const; - virtual bool is_environment(const RID& p_rid) const; - virtual bool is_canvas_light_occluder(const RID& p_rid) const; - - virtual bool is_shader(const RID& p_rid) const; - - virtual void free(const RID& p_rid); - - virtual void custom_shade_model_set_shader(int p_model, RID p_shader); - virtual RID custom_shade_model_get_shader(int p_model) const; - virtual void custom_shade_model_set_name(int p_model, const String& p_name); - virtual String custom_shade_model_get_name(int p_model) const; - virtual void custom_shade_model_set_param_info(int p_model, const List<PropertyInfo>& p_info); - virtual void custom_shade_model_get_param_info(int p_model, List<PropertyInfo>* p_info) const; - - - virtual void init(); - virtual void finish(); - - virtual int get_render_info(VS::RenderInfo p_info); - - virtual bool needs_to_draw_next_frame() const; - - virtual bool has_feature(VS::Features p_feature) const; - - virtual void restore_framebuffer(); - - RasterizerDummy(); - virtual ~RasterizerDummy(); -}; - - -#endif // RASTERIZER_DUMMY_H diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp index 09b3ada509..7dfd9822f7 100644 --- a/servers/visual/shader_language.cpp +++ b/servers/visual/shader_language.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -44,14 +44,71 @@ static bool _is_hex(CharType c) { return (c>='0' && c<='9') || (c>='a' && c<='f') || (c>='A' && c<='F'); } + +String ShaderLanguage::get_operator_text(Operator p_op) { + + static const char* op_names[OP_MAX]={"==", + "!=", + "<", + "<=", + ">", + ">=", + "&&", + "||", + "!", + "-", + "+", + "-", + "*", + "/", + "%", + "<<", + ">>", + "=", + "+=", + "-=", + "*=", + "/=", + "%=", + "<<=", + ">>=", + "&=", + "|=", + "^=", + "&", + "|", + "^", + "~", + "++" + "--", + "()", + "construct"}; + + return op_names[p_op]; + +} + + const char * ShaderLanguage::token_names[TK_MAX]={ "EMPTY", - "INDENTIFIER", + "IDENTIFIER", "TRUE", "FALSE", "REAL_CONSTANT", + "INT_CONSTANT", "TYPE_VOID", "TYPE_BOOL", + "TYPE_BVEC2", + "TYPE_BVEC3", + "TYPE_BVEC4", + "TYPE_INT", + "TYPE_IVEC2", + "TYPE_IVEC3", + "TYPE_IVEC4", + "TYPE_UINT", + "TYPE_UVEC2", + "TYPE_UVEC3", + "TYPE_UVEC4", "TYPE_FLOAT", "TYPE_VEC2", "TYPE_VEC3", @@ -59,9 +116,13 @@ const char * ShaderLanguage::token_names[TK_MAX]={ "TYPE_MAT2", "TYPE_MAT3", "TYPE_MAT4", - "TYPE_TEXTURE", - "TYPE_CUBEMAP", - "TYPE_COLOR", + "TYPE_SAMPLER2D", + "TYPE_ISAMPLER2D", + "TYPE_USAMPLER2D", + "TYPE_SAMPLERCUBE", + "PRECISION_LOW", + "PRECISION_MID", + "PRECISION_HIGH", "OP_EQUAL", "OP_NOT_EQUAL", "OP_LESS", @@ -75,14 +136,35 @@ const char * ShaderLanguage::token_names[TK_MAX]={ "OP_SUB", "OP_MUL", "OP_DIV", - "OP_NEG", + "OP_MOD", + "OP_SHIFT_LEFT", + "OP_SHIFT_RIGHT", "OP_ASSIGN", "OP_ASSIGN_ADD", "OP_ASSIGN_SUB", "OP_ASSIGN_MUL", "OP_ASSIGN_DIV", + "OP_ASSIGN_MOD", + "OP_ASSIGN_SHIFT_LEFT", + "OP_ASSIGN_SHIFT_RIGHT", + "OP_ASSIGN_BIT_AND", + "OP_ASSIGN_BIT_OR", + "OP_ASSIGN_BIT_XOR", + "OP_BIT_AND", + "OP_BIT_OR", + "OP_BIT_XOR", + "OP_BIT_INVERT", + "OP_INCREMENT", + "OP_DECREMENT", "CF_IF", "CF_ELSE", + "CF_FOR", + "CF_WHILE", + "CF_DO", + "CF_SWITCH", + "CF_CASE", + "CF_BREAK", + "CF_CONTINUE", "CF_RETURN", "BRACKET_OPEN", "BRACKET_CLOSE", @@ -90,460 +172,504 @@ const char * ShaderLanguage::token_names[TK_MAX]={ "CURLY_BRACKET_CLOSE", "PARENTHESIS_OPEN", "PARENTHESIS_CLOSE", + "QUESTION", "COMMA", + "COLON", "SEMICOLON", "PERIOD", "UNIFORM", + "VARYING", + "RENDER_MODE", + "HINT_WHITE_TEXTURE", + "HINT_BLACK_TEXTURE", + "HINT_NORMAL_TEXTURE", + "HINT_ANISO_TEXTURE", + "HINT_ALBEDO_TEXTURE", + "HINT_BLACK_ALBEDO_TEXTURE", + "HINT_COLOR", + "HINT_RANGE", + "CURSOR", "ERROR", + "EOF", }; -ShaderLanguage::Token ShaderLanguage::read_token(const CharType* p_text,int p_len,int &r_line,int &r_chars) { +String ShaderLanguage::get_token_text(Token p_token) { -#define GETCHAR(m_idx) ((m_idx<p_len)?p_text[m_idx]:CharType(0)) + String name=token_names[p_token.type]; + if (p_token.type==TK_INT_CONSTANT || p_token.type==TK_REAL_CONSTANT) { + name+="("+rtos(p_token.constant)+")"; + } else if (p_token.type==TK_IDENTIFIER) { + name+="("+String(p_token.text)+")"; + } else if (p_token.type==TK_ERROR) { + name+="("+String(p_token.text)+")"; + } - r_chars=1; //by default everything eats one char - switch(GETCHAR(0)) { + return name; +} - case '\t': - case '\r': - case ' ': - return Token(); - case '\n': - r_line++; - return Token(); - case '/': { +ShaderLanguage::Token ShaderLanguage::_make_token(TokenType p_type,const StringName& p_text) { - switch(GETCHAR(1)) { - case '*': { // block comment + Token tk; + tk.type=p_type; + tk.text=p_text; + tk.line=tk_line; + if (tk.type==TK_ERROR) { + _set_error(p_text); + } + return tk; +} +const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[]={ + {TK_TRUE,"true"}, + {TK_FALSE,"false"}, + {TK_TYPE_VOID,"void"}, + {TK_TYPE_BOOL,"bool"}, + {TK_TYPE_BVEC2,"bvec2"}, + {TK_TYPE_BVEC3,"bvec3"}, + {TK_TYPE_BVEC4,"bvec4"}, + {TK_TYPE_INT,"int"}, + {TK_TYPE_IVEC2,"ivec2"}, + {TK_TYPE_IVEC3,"ivec3"}, + {TK_TYPE_IVEC4,"ivec4"}, + {TK_TYPE_UINT,"uint"}, + {TK_TYPE_UVEC2,"uvec2"}, + {TK_TYPE_UVEC3,"uvec3"}, + {TK_TYPE_UVEC4,"uvec4"}, + {TK_TYPE_FLOAT,"float"}, + {TK_TYPE_VEC2,"vec2"}, + {TK_TYPE_VEC3,"vec3"}, + {TK_TYPE_VEC4,"vec4"}, + {TK_TYPE_MAT2,"mat2"}, + {TK_TYPE_MAT3,"mat3"}, + {TK_TYPE_MAT4,"mat4"}, + {TK_TYPE_SAMPLER2D,"sampler2D"}, + {TK_TYPE_ISAMPLER2D,"isampler2D"}, + {TK_TYPE_USAMPLER2D,"usampler2D"}, + {TK_TYPE_SAMPLERCUBE,"samplerCube"}, + {TK_PRECISION_LOW,"lowp"}, + {TK_PRECISION_MID,"mediump"}, + {TK_PRECISION_HIGH,"highp"}, + {TK_CF_IF,"if"}, + {TK_CF_ELSE,"else"}, + {TK_CF_FOR,"for"}, + {TK_CF_WHILE,"while"}, + {TK_CF_DO,"do"}, + {TK_CF_SWITCH,"switch"}, + {TK_CF_CASE,"case"}, + {TK_CF_BREAK,"break"}, + {TK_CF_CONTINUE,"continue"}, + {TK_CF_RETURN,"return"}, + {TK_UNIFORM,"uniform"}, + {TK_VARYING,"varying"}, + {TK_RENDER_MODE,"render_mode"}, + {TK_HINT_WHITE_TEXTURE,"hint_white"}, + {TK_HINT_BLACK_TEXTURE,"hint_black"}, + {TK_HINT_NORMAL_TEXTURE,"hint_normal"}, + {TK_HINT_ANISO_TEXTURE,"hint_aniso"}, + {TK_HINT_ALBEDO_TEXTURE,"hint_albedo"}, + {TK_HINT_BLACK_ALBEDO_TEXTURE,"hint_black_albedo"}, + {TK_HINT_COLOR,"hint_color"}, + {TK_HINT_RANGE,"hint_range"}, + + {TK_ERROR,NULL} +}; - while(true) { - if (GETCHAR(r_chars+1)==0) { - r_chars+=1; - break; - } if (GETCHAR(r_chars+1)=='*' && GETCHAR(r_chars+2)=='/') { - r_chars+=3; - break; - } if (GETCHAR(r_chars+1)=='\n') { - r_line++; - } - r_chars++; - } - return Token(); +ShaderLanguage::Token ShaderLanguage::_get_token() { - } break; - case '/': { // line comment skip +#define GETCHAR(m_idx) (((char_idx+m_idx)<code.length())?code[char_idx+m_idx]:CharType(0)) - while(GETCHAR(r_chars+1)!='\n' && GETCHAR(r_chars+1)!=0) { - r_chars++; - } - r_chars++; - //r_line++; - - return Token(); + while(true) { + char_idx++; + switch(GETCHAR(-1)) { + + case 0: + return _make_token(TK_EOF); + case 0xFFFF: + return _make_token(TK_CURSOR); //for completion + case '\t': + case '\r': + case ' ': + continue; + case '\n': + tk_line++; + continue; + case '/': { - } break; - case '=': { // diveq + switch(GETCHAR(0)) { + case '*': { // block comment - r_chars=2; - return Token(TK_OP_ASSIGN_DIV); + char_idx++; + while(true) { + if (GETCHAR(0)==0) { + return _make_token(TK_EOF); + } if (GETCHAR(0)=='*' && GETCHAR(1)=='/') { + char_idx+=2; + break; + } if (GETCHAR(0)=='\n') { + tk_line++; + } - } break; - default: - return Token(TK_OP_DIV); + char_idx++; + } - } - } break; - case '=': { - if (GETCHAR(1)=='=') { - r_chars++; - return Token(TK_OP_EQUAL); - } + } break; + case '/': { // line comment skip - return Token(TK_OP_ASSIGN); - } break; - case '<': { - if (GETCHAR(1)=='=') { - r_chars++; - return Token(TK_OP_LESS_EQUAL); - } /*else if (GETCHAR(1)=='<') { - r_chars++; - if (GETCHAR(2)=='=') { - r_chars++; - return Token(TK_OP_ASSIGN_SHIFT_LEFT); - } + while(true) { + if (GETCHAR(0)=='\n') { + char_idx++; + break; + } + if (GETCHAR(0)==0) { + return _make_token(TK_EOF); + } + char_idx++; + } - return Token(TK_OP_SHIFT_LEFT); - }*/ + } break; + case '=': { // diveq - return Token(TK_OP_LESS); + char_idx++; + return _make_token(TK_OP_ASSIGN_DIV); - } break; - case '>': { - if (GETCHAR(1)=='=') { - r_chars++; - return Token(TK_OP_GREATER_EQUAL); - }/* else if (GETCHAR(1)=='<') { - r_chars++; - if (GETCHAR(2)=='=') { - r_chars++; - return Token(TK_OP_ASSIGN_SHIFT_RIGHT); + } break; + default: + return _make_token(TK_OP_DIV); } - return Token(TK_OP_SHIFT_RIGHT); - }*/ - - return Token(TK_OP_GREATER); - - } break; - case '!': { - if (GETCHAR(1)=='=') { - r_chars++; - return Token(TK_OP_NOT_EQUAL); - } + continue; //a comment, continue to next token + } break; + case '=': { - return Token(TK_OP_NOT); - - } break; - //case '"' //string - no strings in shader - //case '\'' //string - no strings in shader - case '{': - return Token(TK_CURLY_BRACKET_OPEN); - case '}': - return Token(TK_CURLY_BRACKET_CLOSE); - //case '[': - // return Token(TK_BRACKET_OPEN); - //case ']': - // return Token(TK_BRACKET_CLOSE); - case '(': - return Token(TK_PARENTHESIS_OPEN); - case ')': - return Token(TK_PARENTHESIS_CLOSE); - case ',': - return Token(TK_COMMA); - case ';': - return Token(TK_SEMICOLON); - //case '?': - // return Token(TK_QUESTION_MARK); - //case ':': - // return Token(TK_COLON); //for methods maybe but now useless. - //case '^': - // return Token(TK_OP_BIT_XOR); - //case '~': - // return Token(TK_OP_BIT_INVERT); - case '&': { - - if (GETCHAR(1)=='&') { - - r_chars++; - return Token(TK_OP_AND); - } - - return Token(TK_ERROR,"Unknown character"); - -/* - if (GETCHAR(1)=='=') { - r_chars++; - return Token(TK_OP_ASSIGN_BIT_AND); - } else if (GETCHAR(1)=='&') { - r_chars++; - return Token(TK_OP_AND); - } - return TK_OP_BIT_AND;*/ - } break; - case '|': { + if (GETCHAR(0)=='=') { + char_idx++; + return _make_token(TK_OP_EQUAL); + } - if (GETCHAR(1)=='|') { + return _make_token(TK_OP_ASSIGN); + + } break; + case '<': { + if (GETCHAR(0)=='=') { + char_idx++; + return _make_token(TK_OP_LESS_EQUAL); + } else if (GETCHAR(0)=='<') { + char_idx++; + if (GETCHAR(0)=='=') { + char_idx++; + return _make_token(TK_OP_ASSIGN_SHIFT_LEFT); + } - r_chars++; - return Token(TK_OP_OR); - } + return _make_token(TK_OP_SHIFT_LEFT); + } - return Token(TK_ERROR,"Unknown character"); + return _make_token(TK_OP_LESS); + + } break; + case '>': { + if (GETCHAR(0)=='=') { + char_idx++; + return _make_token(TK_OP_GREATER_EQUAL); + } else if (GETCHAR(0)=='<') { + char_idx++; + if (GETCHAR(0)=='=') { + char_idx++; + return _make_token(TK_OP_ASSIGN_SHIFT_RIGHT); + } - /* - if (GETCHAR(1)=='=') { - r_chars++; - return Token(TK_OP_ASSIGN_BIT_OR); - } else if (GETCHAR(1)=='|') { - r_chars++; - return Token(TK_OP_OR); - } - return TK_OP_BIT_OR; - */ - } break; - case '*': { + return _make_token(TK_OP_SHIFT_RIGHT); + } - if (GETCHAR(1)=='=') { - r_chars++; - return Token(TK_OP_ASSIGN_MUL); - } - return TK_OP_MUL; - } break; - case '+': { + return _make_token(TK_OP_GREATER); - if (GETCHAR(1)=='=') { - r_chars++; - return Token(TK_OP_ASSIGN_ADD); - } /*else if (GETCHAR(1)=='+') { + } break; + case '!': { + if (GETCHAR(0)=='=') { + char_idx++; + return _make_token(TK_OP_NOT_EQUAL); + } - r_chars++; - return Token(TK_OP_PLUS_PLUS); - }*/ + return _make_token(TK_OP_NOT); + + } break; + //case '"' //string - no strings in shader + //case '\'' //string - no strings in shader + case '{': + return _make_token(TK_CURLY_BRACKET_OPEN); + case '}': + return _make_token(TK_CURLY_BRACKET_CLOSE); + case '[': + return _make_token(TK_BRACKET_OPEN); + case ']': + return _make_token(TK_BRACKET_CLOSE); + case '(': + return _make_token(TK_PARENTHESIS_OPEN); + case ')': + return _make_token(TK_PARENTHESIS_CLOSE); + case ',': + return _make_token(TK_COMMA); + case ';': + return _make_token(TK_SEMICOLON); + case '?': + return _make_token(TK_QUESTION); + case ':': + return _make_token(TK_COLON); + case '^': + return _make_token(TK_OP_BIT_XOR); + case '~': + return _make_token(TK_OP_BIT_INVERT); + case '&': { + if (GETCHAR(0)=='=') { + char_idx++; + return _make_token(TK_OP_ASSIGN_BIT_AND); + } else if (GETCHAR(0)=='&') { + char_idx++; + return _make_token(TK_OP_AND); + } + return _make_token(TK_OP_BIT_AND); + } break; + case '|': { + + if (GETCHAR(0)=='=') { + char_idx++; + return _make_token(TK_OP_ASSIGN_BIT_OR); + } else if (GETCHAR(0)=='|') { + char_idx++; + return _make_token(TK_OP_OR); + } + return _make_token(TK_OP_BIT_OR); - return TK_OP_ADD; - } break; - case '-': { + } break; + case '*': { - if (GETCHAR(1)=='=') { - r_chars++; - return Token(TK_OP_ASSIGN_SUB); - }/* else if (GETCHAR(1)=='-') { + if (GETCHAR(0)=='=') { + char_idx++; + return _make_token(TK_OP_ASSIGN_MUL); + } + return _make_token(TK_OP_MUL); + } break; + case '+': { - r_chars++; - return Token(TK_OP_MINUS_MINUS); - }*/ + if (GETCHAR(0)=='=') { + char_idx++; + return _make_token(TK_OP_ASSIGN_ADD); + } else if (GETCHAR(0)=='+') { - return TK_OP_SUB; - } break; - /*case '%': { + char_idx++; + return _make_token(TK_OP_INCREMENT); + } - if (GETCHAR(1)=='=') { - r_chars++; - return Token(TK_OP_ASSIGN_MOD); - } + return _make_token(TK_OP_ADD); + } break; + case '-': { - return TK_OP_MOD; - } break;*/ - default: { + if (GETCHAR(0)=='=') { + char_idx++; + return _make_token(TK_OP_ASSIGN_SUB); + }else if (GETCHAR(0)=='-') { - if (_is_number(GETCHAR(0)) || (GETCHAR(0)=='.' && _is_number(GETCHAR(1)))) { - // parse number - bool period_found=false; - bool exponent_found=false; - bool hexa_found=false; - bool sign_found=false; + char_idx++; + return _make_token(TK_OP_DECREMENT); + } - String str; - int i=0; + return _make_token(TK_OP_SUB); + } break; + case '%': { - while(true) { - if (GETCHAR(i)=='.') { - if (period_found || exponent_found) - return Token(TK_ERROR,"Invalid numeric constant"); - period_found=true; - } else if (GETCHAR(i)=='x') { - if (hexa_found || str.length()!=1 || str[0]!='0') - return Token(TK_ERROR,"Invalid numeric constant"); - hexa_found=true; - } else if (GETCHAR(i)=='e') { - if (hexa_found || exponent_found) - return Token(TK_ERROR,"Invalid numeric constant"); - exponent_found=true; - } else if (_is_number(GETCHAR(i))) { - //all ok - } else if (hexa_found && _is_hex(GETCHAR(i))) { - - } else if ((GETCHAR(i)=='-' || GETCHAR(i)=='+') && exponent_found) { - if (sign_found) - return Token(TK_ERROR,"Invalid numeric constant"); - sign_found=true; - } else - break; - - str+=CharType(GETCHAR(i)); - i++; + if (GETCHAR(0)=='=') { + char_idx++; + return _make_token(TK_OP_ASSIGN_MOD); } - if (!_is_number(str[str.length()-1])) - return Token(TK_ERROR,"Invalid numeric constant"); + return _make_token(TK_OP_MOD); + } break; + default: { - r_chars+=str.length()-1; - return Token(TK_REAL_CONSTANT,str); - /* - if (period_found) - return Token(TK_NUMBER_REAL,str); - else - return Token(TK_NUMBER_INTEGER,str);*/ + char_idx--; //go back one, since we have no idea what this is - } + if (_is_number(GETCHAR(0)) || (GETCHAR(0)=='.' && _is_number(GETCHAR(1)))) { + // parse number + bool period_found=false; + bool exponent_found=false; + bool hexa_found=false; + bool sign_found=false; + bool minus_exponent_found=false; - if (GETCHAR(0)=='.') { - //parse period - return Token(TK_PERIOD); - } + String str; + int i=0; - if (_is_text_char(GETCHAR(0))) { - // parse identifier - String str; - str+=CharType(GETCHAR(0)); + while(true) { + if (GETCHAR(i)=='.') { + if (period_found || exponent_found) + return _make_token(TK_ERROR,"Invalid numeric constant"); + period_found=true; + } else if (GETCHAR(i)=='x') { + if (hexa_found || str.length()!=1 || str[0]!='0') + return _make_token(TK_ERROR,"Invalid numeric constant"); + hexa_found=true; + } else if (GETCHAR(i)=='e') { + if (hexa_found || exponent_found) + return _make_token(TK_ERROR,"Invalid numeric constant"); + exponent_found=true; + } else if (_is_number(GETCHAR(i))) { + //all ok + } else if (hexa_found && _is_hex(GETCHAR(i))) { + + } else if ((GETCHAR(i)=='-' || GETCHAR(i)=='+') && exponent_found) { + if (sign_found) + return _make_token(TK_ERROR,"Invalid numeric constant"); + sign_found=true; + if (GETCHAR(i)=='-') + minus_exponent_found=true; + } else + break; - while(_is_text_char(GETCHAR(r_chars))) { + str+=CharType(GETCHAR(i)); + i++; + } - str+=CharType(GETCHAR(r_chars)); - r_chars++; - } + if (!_is_number(str[str.length()-1])) + return _make_token(TK_ERROR,"Invalid numeric constant"); - //see if keyword - struct _kws { TokenType token; const char *text;}; - static const _kws keyword_list[]={ - {TK_TRUE,"true"}, - {TK_FALSE,"false"}, - {TK_TYPE_VOID,"void"}, - {TK_TYPE_BOOL,"bool"}, - /*{TK_TYPE_INT,"int"}, - {TK_TYPE_INT2,"int2"}, - {TK_TYPE_INT3,"int3"}, - {TK_TYPE_INT4,"int4"},*/ - {TK_TYPE_FLOAT,"float"}, - /*{TK_TYPE_FLOAT2,"float2"}, - {TK_TYPE_FLOAT3,"float3"}, - {TK_TYPE_FLOAT4,"float4"},*/ - {TK_TYPE_VEC2,"vec2"}, - {TK_TYPE_VEC3,"vec3"}, - {TK_TYPE_VEC4,"vec4"}, - {TK_TYPE_TEXTURE,"texture"}, - {TK_TYPE_CUBEMAP,"cubemap"}, - {TK_TYPE_COLOR,"color"}, + char_idx+=str.length(); + Token tk; + if (period_found || minus_exponent_found) + tk.type=TK_REAL_CONSTANT; + else + tk.type=TK_INT_CONSTANT; - {TK_TYPE_MAT2,"mat2"}, - /*{TK_TYPE_MAT3,"mat3"}, - {TK_TYPE_MAT4,"mat3"},*/ - {TK_TYPE_MAT3,"mat3"}, - {TK_TYPE_MAT4,"mat4"}, - {TK_CF_IF,"if"}, - {TK_CF_ELSE,"else"}, - /* - {TK_CF_FOR,"for"}, - {TK_CF_WHILE,"while"}, - {TK_CF_DO,"do"}, - {TK_CF_SWITCH,"switch"}, - {TK_CF_BREAK,"break"}, - {TK_CF_CONTINUE,"continue"},*/ - {TK_CF_RETURN,"return"}, - {TK_UNIFORM,"uniform"}, - {TK_ERROR,NULL} - }; + if (!str.is_valid_float()) { + return _make_token(TK_ERROR,"Invalid numeric constant"); + } - int idx=0; + tk.constant=str.to_double(); + tk.line=tk_line; - while(keyword_list[idx].text) { + return tk; - if (str==keyword_list[idx].text) - return Token(keyword_list[idx].token); - idx++; } + if (GETCHAR(0)=='.') { + //parse period + char_idx++; + return _make_token(TK_PERIOD); + } - return Token(TK_INDENTIFIER,str); - } - - if (GETCHAR(0)>32) - return Token(TK_ERROR,"Tokenizer: Unknown character #"+itos(GETCHAR(0))+": '"+String::chr(GETCHAR(0))+"'"); - else - return Token(TK_ERROR,"Tokenizer: Unknown character #"+itos(GETCHAR(0))); + if (_is_text_char(GETCHAR(0))) { + // parse identifier + String str; - } break; - } + while(_is_text_char(GETCHAR(0))) { - ERR_PRINT("BUG"); - return Token(); -} + str+=CharType(GETCHAR(0)); + char_idx++; + } -Error ShaderLanguage::tokenize(const String& p_text,Vector<Token> *p_tokens,String *r_error,int *r_err_line,int *r_err_column) { + //see if keyword + //should be converted to a static map + int idx=0; + while(keyword_list[idx].text) { - int len =p_text.length(); - int pos=0; + if (str==keyword_list[idx].text) { - int line=0; + return _make_token(keyword_list[idx].token); + } + idx++; + } - while(pos<len) { - int advance=0; - int prev_line=line; - Token t = read_token(&p_text[pos],len-pos,line,advance); - t.line=prev_line; + return _make_token(TK_IDENTIFIER,str); + } - if (t.type==TK_ERROR) { + if (GETCHAR(0)>32) + return _make_token(TK_ERROR,"Tokenizer: Unknown character #"+itos(GETCHAR(0))+": '"+String::chr(GETCHAR(0))+"'"); + else + return _make_token(TK_ERROR,"Tokenizer: Unknown character #"+itos(GETCHAR(0))); - if (r_error) { - *r_error=t.text; - *r_err_line=line; - return ERR_COMPILATION_FAILED; - } + } break; } + } + ERR_PRINT("BUG"); + return Token(); +} - if (t.type!=TK_EMPTY) - p_tokens->push_back(t); - //if (prev_line!=line) - // p_tokens->push_back(Token(TK_LINE,itos(line))); - pos+=advance; +String ShaderLanguage::token_debug(const String& p_code) { - } + clear(); - return OK; + code=p_code; -} + String output; -String ShaderLanguage::lex_debug(const String& p_code) { + Token tk = _get_token(); + while(tk.type!=TK_EOF && tk.type!=TK_ERROR) { - Vector<Token> tokens; - String error; - int errline,errcol; - if (tokenize(p_code,&tokens,&error,&errline,&errcol)!=OK) - return error; - String ret; - for(int i=0;i<tokens.size();i++) { - ret+=String(token_names[tokens[i].type])+":"+itos(tokens[i].line)+":"+itos(tokens[i].col)+":"+tokens[i].text+"\n"; + output+=itos(tk_line)+": "+get_token_text(tk)+"\n"; + tk = _get_token(); } - return ret; + return output; } bool ShaderLanguage::is_token_datatype(TokenType p_type) { - return - (p_type==TK_TYPE_VOID) || - (p_type==TK_TYPE_BOOL) || - (p_type==TK_TYPE_FLOAT) || - (p_type==TK_TYPE_VEC2) || - (p_type==TK_TYPE_VEC3) || - (p_type==TK_TYPE_VEC4) || - (p_type==TK_TYPE_COLOR) || - (p_type==TK_TYPE_MAT2) || - (p_type==TK_TYPE_MAT3) || - (p_type==TK_TYPE_MAT4) || - (p_type==TK_TYPE_CUBEMAP) || - (p_type==TK_TYPE_TEXTURE); + return ( + p_type==TK_TYPE_VOID || + p_type==TK_TYPE_BOOL || + p_type==TK_TYPE_BVEC2 || + p_type==TK_TYPE_BVEC3 || + p_type==TK_TYPE_BVEC4 || + p_type==TK_TYPE_INT || + p_type==TK_TYPE_IVEC2 || + p_type==TK_TYPE_IVEC3 || + p_type==TK_TYPE_IVEC4 || + p_type==TK_TYPE_UINT || + p_type==TK_TYPE_UVEC2 || + p_type==TK_TYPE_UVEC3 || + p_type==TK_TYPE_UVEC4 || + p_type==TK_TYPE_FLOAT || + p_type==TK_TYPE_VEC2 || + p_type==TK_TYPE_VEC3 || + p_type==TK_TYPE_VEC4 || + p_type==TK_TYPE_MAT2 || + p_type==TK_TYPE_MAT3 || + p_type==TK_TYPE_MAT4 || + p_type==TK_TYPE_SAMPLER2D || + p_type==TK_TYPE_ISAMPLER2D || + p_type==TK_TYPE_USAMPLER2D || + p_type==TK_TYPE_SAMPLERCUBE ); } ShaderLanguage::DataType ShaderLanguage::get_token_datatype(TokenType p_type) { - switch(p_type) { + return DataType(p_type-TK_TYPE_VOID); +} - case TK_TYPE_VOID: return TYPE_VOID; - case TK_TYPE_BOOL: return TYPE_BOOL; - case TK_TYPE_FLOAT: return TYPE_FLOAT; - case TK_TYPE_VEC2: return TYPE_VEC2; - case TK_TYPE_VEC3: return TYPE_VEC3; - case TK_TYPE_VEC4: return TYPE_VEC4; - case TK_TYPE_COLOR: return TYPE_VEC4; - case TK_TYPE_MAT2: return TYPE_MAT2; - case TK_TYPE_MAT3: return TYPE_MAT3; - case TK_TYPE_MAT4: return TYPE_MAT4; - case TK_TYPE_TEXTURE: return TYPE_TEXTURE; - case TK_TYPE_CUBEMAP: return TYPE_CUBEMAP; - default: return TYPE_VOID; - } - return TYPE_VOID; +bool ShaderLanguage::is_token_precision(TokenType p_type) { + + return ( + p_type==TK_PRECISION_LOW || + p_type==TK_PRECISION_MID || + p_type==TK_PRECISION_HIGH ); + +} + +ShaderLanguage::DataPrecision ShaderLanguage::get_token_precision(TokenType p_type) { + + if (p_type==TK_PRECISION_LOW) + return PRECISION_LOWP; + else if (p_type==TK_PRECISION_HIGH) + return PRECISION_HIGHP; + else + return PRECISION_MEDIUMP; } @@ -553,6 +679,17 @@ String ShaderLanguage::get_datatype_name(DataType p_type) { case TYPE_VOID: return "void"; case TYPE_BOOL: return "bool"; + case TYPE_BVEC2: return "bvec2"; + case TYPE_BVEC3: return "bvec3"; + case TYPE_BVEC4: return "bvec4"; + case TYPE_INT: return "int"; + case TYPE_IVEC2: return "ivec2"; + case TYPE_IVEC3: return "ivec3"; + case TYPE_IVEC4: return "ivec4"; + case TYPE_UINT: return "uint"; + case TYPE_UVEC2: return "uvec2"; + case TYPE_UVEC3: return "uvec3"; + case TYPE_UVEC4: return "uvec4"; case TYPE_FLOAT: return "float"; case TYPE_VEC2: return "vec2"; case TYPE_VEC3: return "vec3"; @@ -560,9 +697,10 @@ String ShaderLanguage::get_datatype_name(DataType p_type) { case TYPE_MAT2: return "mat2"; case TYPE_MAT3: return "mat3"; case TYPE_MAT4: return "mat4"; - case TYPE_TEXTURE: return "texture"; - case TYPE_CUBEMAP: return "cubemap"; - default: return ""; + case TYPE_SAMPLER2D: return "sampler2D"; + case TYPE_ISAMPLER2D: return "isampler2D"; + case TYPE_USAMPLER2D: return "usampler2D"; + case TYPE_SAMPLERCUBE: return "samplerCube"; } return ""; @@ -571,211 +709,495 @@ String ShaderLanguage::get_datatype_name(DataType p_type) { bool ShaderLanguage::is_token_nonvoid_datatype(TokenType p_type) { - return - (p_type==TK_TYPE_BOOL) || - (p_type==TK_TYPE_FLOAT) || - (p_type==TK_TYPE_VEC2) || - (p_type==TK_TYPE_VEC3) || - (p_type==TK_TYPE_VEC4) || - (p_type==TK_TYPE_COLOR) || - (p_type==TK_TYPE_MAT2) || - (p_type==TK_TYPE_MAT3) || - (p_type==TK_TYPE_MAT4) || - (p_type==TK_TYPE_TEXTURE) || - (p_type==TK_TYPE_CUBEMAP); + return is_token_datatype(p_type) && p_type!=TK_TYPE_VOID; } -bool ShaderLanguage::parser_is_at_function(Parser& parser) { - - return (is_token_datatype(parser.get_token_type(0)) && parser.get_token_type(1)==TK_INDENTIFIER && parser.get_token_type(2)==TK_PARENTHESIS_OPEN); -} - - - -bool ShaderLanguage::test_existing_identifier(Node *p_node,const StringName p_identifier,bool p_func,bool p_var,bool p_builtin) { +void ShaderLanguage::clear() { - Node *node = p_node; + current_function=StringName(); - while(node) { + completion_type=COMPLETION_NONE; + completion_block=NULL; + completion_function=StringName(); - if (node->type==Node::TYPE_BLOCK) { + error_line=0; + tk_line=1; + char_idx=0; + error_set=false; + error_str=""; + while(nodes) { + Node *n = nodes; + nodes=nodes->next; + memdelete(n); + } - BlockNode *block = (BlockNode*)node; - if (block->variables.has(p_identifier)) - return true; - } else if (node->type==Node::TYPE_PROGRAM) { +} - ProgramNode *program = (ProgramNode*)node; - for(int i=0;i<program->functions.size();i++) { - if (program->functions[i].name==p_identifier) { - return true; - } - } +bool ShaderLanguage::_find_identifier(const BlockNode* p_block,const Map<StringName, DataType> &p_builtin_types,const StringName& p_identifier, DataType *r_data_type, IdentifierType *r_type) { - if(program->builtin_variables.has(p_identifier)) { - return true; - } - if(program->uniforms.has(p_identifier)) { - return true; - } - } else if (node->type==Node::TYPE_FUNCTION) { + if (p_builtin_types.has(p_identifier)) { - FunctionNode *func=(FunctionNode*)node; - for(int i=0;i<func->arguments.size();i++) - if (func->arguments[i].name==p_identifier) - return true; + if (r_data_type) { + *r_data_type=p_builtin_types[p_identifier]; + } + if (r_type) { + *r_type=IDENTIFIER_BUILTIN_VAR; } - node=node->parent; + return true; } - // try keywords + FunctionNode *function=NULL; - int idx=0; + while(p_block) { - //todo optimize - while(intrinsic_func_defs[idx].name) { + if (p_block->variables.has(p_identifier)) { + if (r_data_type) { + *r_data_type=p_block->variables[p_identifier].type; + } + if (r_type) { + *r_type=IDENTIFIER_LOCAL_VAR; + } - if (p_identifier.operator String()==intrinsic_func_defs[idx].name) return true; - idx++; - } - + } - return false; + if (p_block->parent_function) { + function=p_block->parent_function; + break; + } else { + ERR_FAIL_COND_V(!p_block->parent_block,false); + p_block=p_block->parent_block; + } + } -} + if (function) { + for(int i=0;i<function->arguments.size();i++) { + if (function->arguments[i].name==p_identifier) { + if (r_data_type) { + *r_data_type=function->arguments[i].type; + } + if (r_type) { + *r_type=IDENTIFIER_FUNCTION_ARGUMENT; + } + return true; + } + } + } -Error ShaderLanguage::parse_function(Parser& parser,BlockNode *p_block) { - if (!p_block->parent || p_block->parent->type!=Node::TYPE_PROGRAM) { - parser.set_error("Misplaced function"); - return ERR_PARSE_ERROR; + if (shader->varyings.has(p_identifier)) { + if (r_data_type) { + *r_data_type=shader->varyings[p_identifier].type; + } + if (r_type) { + *r_type=IDENTIFIER_VARYING; + } + return true; + } + if (shader->uniforms.has(p_identifier)) { + if (r_data_type) { + *r_data_type=shader->uniforms[p_identifier].type; + } + if (r_type) { + *r_type=IDENTIFIER_UNIFORM; + } + return true; } + for(int i=0;i<shader->functions.size();i++) { - ProgramNode *program = (ProgramNode*)p_block->parent; + if (!shader->functions[i].callable) + continue; - StringName name = parser.get_token(1).text; + if (shader->functions[i].name==p_identifier) { + if (r_data_type) { + *r_data_type=shader->functions[i].function->return_type; + } + if (r_type) { + *r_type=IDENTIFIER_FUNCTION; + } + } + } - if (test_existing_identifier(p_block,name)) { + return false; - parser.set_error("Duplicate Identifier (existing variable/builtin/function): "+name); - return ERR_PARSE_ERROR; +} - } +bool ShaderLanguage::_validate_operator(OperatorNode *p_op,DataType *r_ret_type) { - FunctionNode *function = parser.create_node<FunctionNode>(program); - function->body = parser.create_node<BlockNode>(function); + bool valid=false; + DataType ret_type; + + switch(p_op->op) { + case OP_EQUAL: + case OP_NOT_EQUAL: { + DataType na = p_op->arguments[0]->get_datatype(); + DataType nb = p_op->arguments[1]->get_datatype(); + valid=na==nb; + ret_type=TYPE_BOOL; + } break; + case OP_LESS: + case OP_LESS_EQUAL: + case OP_GREATER: + case OP_GREATER_EQUAL: { + DataType na = p_op->arguments[0]->get_datatype(); + DataType nb = p_op->arguments[1]->get_datatype(); - function->name=name; + valid = na==nb && (na==TYPE_UINT || na==TYPE_INT || na==TYPE_FLOAT); + ret_type=TYPE_BOOL; - function->return_type=get_token_datatype(parser.get_token_type(0)); + } break; + case OP_AND: + case OP_OR: { + DataType na = p_op->arguments[0]->get_datatype(); + DataType nb = p_op->arguments[1]->get_datatype(); - { //add to programnode - ProgramNode::Function f; - f.name=name; - f.function=function; - program->functions.push_back(f); - } + valid = na==nb && na==TYPE_BOOL; + ret_type=TYPE_BOOL; - int ofs=3; + } break; + case OP_NOT: { - while(true) { + DataType na = p_op->arguments[0]->get_datatype(); + valid = na==TYPE_BOOL; + ret_type=TYPE_BOOL; - //end of arguments - if (parser.get_token_type(ofs)==TK_PARENTHESIS_CLOSE) { - ofs++; - break; - } - //next argument awaits - if (parser.get_token_type(ofs)==TK_COMMA) { - if (!is_token_nonvoid_datatype(parser.get_token_type(ofs+1))) { - parser.set_error("Expected Identifier or ')' following ','"); - return ERR_PARSE_ERROR; + } break; + case OP_INCREMENT: + case OP_DECREMENT: + case OP_POST_INCREMENT: + case OP_POST_DECREMENT: + case OP_NEGATE: { + DataType na = p_op->arguments[0]->get_datatype(); + valid = na>TYPE_BOOL && na<TYPE_MAT2; + ret_type=na; + } break; + case OP_ADD: + case OP_SUB: + case OP_MUL: + case OP_DIV: { + DataType na = p_op->arguments[0]->get_datatype(); + DataType nb = p_op->arguments[1]->get_datatype(); + + if (na>nb) { + //make things easier; + SWAP(na,nb); + } + + if (na==nb) { + valid = (na>TYPE_BOOL && na<TYPE_MAT2) || (p_op->op==OP_MUL && na>=TYPE_MAT2 && na<=TYPE_MAT4); + ret_type=na; + } else if (na==TYPE_INT && nb==TYPE_IVEC2) { + valid=true; + ret_type=TYPE_IVEC2; + } else if (na==TYPE_INT && nb==TYPE_IVEC3) { + valid=true; + ret_type=TYPE_IVEC3; + } else if (na==TYPE_INT && nb==TYPE_IVEC4) { + valid=true; + ret_type=TYPE_IVEC4; + } else if (na==TYPE_UINT && nb==TYPE_UVEC2) { + valid=true; + ret_type=TYPE_UVEC2; + } else if (na==TYPE_UINT && nb==TYPE_UVEC3) { + valid=true; + ret_type=TYPE_UVEC3; + } else if (na==TYPE_UINT && nb==TYPE_UVEC4) { + valid=true; + ret_type=TYPE_UVEC4; + } else if (na==TYPE_FLOAT && nb==TYPE_VEC2) { + valid=true; + ret_type=TYPE_VEC2; + } else if (na==TYPE_FLOAT && nb==TYPE_VEC3) { + valid=true; + ret_type=TYPE_VEC3; + } else if (na==TYPE_FLOAT && nb==TYPE_VEC4) { + valid=true; + ret_type=TYPE_VEC4; + } else if (p_op->op==OP_MUL && na==TYPE_VEC2 && nb==TYPE_MAT2) { + valid=true; + ret_type=TYPE_MAT2; + } else if (p_op->op==OP_MUL && na==TYPE_VEC3 && nb==TYPE_MAT3) { + valid=true; + ret_type=TYPE_MAT3; + } else if (p_op->op==OP_MUL && na==TYPE_VEC4 && nb==TYPE_MAT4) { + valid=true; + ret_type=TYPE_MAT4; } - ofs++; - continue; - } + } break; + case OP_ASSIGN_MOD: + case OP_MOD: { + /* + * The operator modulus (%) operates on signed or unsigned integers or integer vectors. The operand + * types must both be signed or both be unsigned. The operands cannot be vectors of differing size. If + * one operand is a scalar and the other vector, then the scalar is applied component-wise to the vector, + * resulting in the same type as the vector. If both are vectors of the same size, the result is computed + * component-wise. + */ + DataType na = p_op->arguments[0]->get_datatype(); + DataType nb = p_op->arguments[1]->get_datatype(); - if (!is_token_nonvoid_datatype(parser.get_token_type(ofs+0))) { - parser.set_error("Invalid Argument Type"); - return ERR_PARSE_ERROR; - } + if (na==TYPE_INT && nb==TYPE_INT) { + valid=true; + ret_type=TYPE_INT; + } else if (na==TYPE_IVEC2 && nb==TYPE_INT) { + valid=true; + ret_type=TYPE_IVEC2; + } else if (na==TYPE_IVEC3 && nb==TYPE_INT) { + valid=true; + ret_type=TYPE_IVEC3; + } else if (na==TYPE_IVEC4 && nb==TYPE_INT) { + valid=true; + ret_type=TYPE_IVEC4; + } else if (na==TYPE_IVEC2 && nb==TYPE_IVEC2) { + valid=true; + ret_type=TYPE_IVEC2; + } else if (na==TYPE_IVEC3 && nb==TYPE_IVEC3) { + valid=true; + ret_type=TYPE_IVEC3; + } else if (na==TYPE_IVEC4 && nb==TYPE_IVEC4) { + valid=true; + ret_type=TYPE_IVEC4; + ///// + } else if (na==TYPE_UINT && nb==TYPE_UINT) { + valid=true; + ret_type=TYPE_UINT; + } else if (na==TYPE_UVEC2 && nb==TYPE_UINT) { + valid=true; + ret_type=TYPE_UVEC2; + } else if (na==TYPE_UVEC3 && nb==TYPE_UINT) { + valid=true; + ret_type=TYPE_UVEC3; + } else if (na==TYPE_UVEC4 && nb==TYPE_UINT) { + valid=true; + ret_type=TYPE_UVEC4; + } else if (na==TYPE_UVEC2 && nb==TYPE_UVEC2) { + valid=true; + ret_type=TYPE_UVEC2; + } else if (na==TYPE_UVEC3 && nb==TYPE_UVEC3) { + valid=true; + ret_type=TYPE_UVEC3; + } else if (na==TYPE_UVEC4 && nb==TYPE_UVEC4) { + valid=true; + ret_type=TYPE_UVEC4; + } + } break; + case OP_ASSIGN_SHIFT_LEFT: + case OP_ASSIGN_SHIFT_RIGHT: + case OP_SHIFT_LEFT: + case OP_SHIFT_RIGHT: { - DataType identtype=get_token_datatype(parser.get_token_type(ofs+0)); + DataType na = p_op->arguments[0]->get_datatype(); + DataType nb = p_op->arguments[1]->get_datatype(); - if (parser.get_token_type(ofs+1)!=TK_INDENTIFIER) { - parser.set_error("Expected Argument Identifier"); - return ERR_PARSE_ERROR; - } + if (na>=TYPE_UINT && na<=TYPE_UVEC4) { + na=DataType(na-4); + } - StringName identname=parser.get_token(ofs+1).text; + if (nb>=TYPE_UINT && nb<=TYPE_UVEC4) { + nb=DataType(nb-4); + } - if (test_existing_identifier(function,identname)) { - parser.set_error("Duplicate Argument Identifier: "+identname); - return ERR_DUPLICATE_SYMBOL; - } + if (na==TYPE_INT && nb==TYPE_INT) { + valid=true; + ret_type=TYPE_INT; + } else if (na==TYPE_IVEC2 && nb==TYPE_INT) { + valid=true; + ret_type=TYPE_IVEC2; + } else if (na==TYPE_IVEC3 && nb==TYPE_INT) { + valid=true; + ret_type=TYPE_IVEC3; + } else if (na==TYPE_IVEC4 && nb==TYPE_INT) { + valid=true; + ret_type=TYPE_IVEC4; + } else if (na==TYPE_IVEC2 && nb==TYPE_IVEC2) { + valid=true; + ret_type=TYPE_IVEC2; + } else if (na==TYPE_IVEC3 && nb==TYPE_IVEC3) { + valid=true; + ret_type=TYPE_IVEC3; + } else if (na==TYPE_IVEC4 && nb==TYPE_IVEC4) { + valid=true; + ret_type=TYPE_IVEC4; + } + } break; + case OP_ASSIGN: { + DataType na = p_op->arguments[0]->get_datatype(); + DataType nb = p_op->arguments[1]->get_datatype(); + valid=na==nb; + ret_type=na; + } break; + case OP_ASSIGN_ADD: + case OP_ASSIGN_SUB: + case OP_ASSIGN_MUL: + case OP_ASSIGN_DIV: { - FunctionNode::Argument arg; - arg.name=identname; - arg.type=identtype; - //function->body->variables[arg.name]=arg.type; - function->arguments.push_back(arg); + DataType na = p_op->arguments[0]->get_datatype(); + DataType nb = p_op->arguments[1]->get_datatype(); - ofs+=2; - } - parser.advance(ofs); - // match { - if (parser.get_token_type()!=TK_CURLY_BRACKET_OPEN) { - parser.set_error("Expected '{'"); - return ERR_PARSE_ERROR; - } + if (na==nb) { + valid = (na>TYPE_BOOL && na<TYPE_MAT2) || (p_op->op==OP_ASSIGN_MUL && na>=TYPE_MAT2 && na<=TYPE_MAT4); + ret_type=na; + } else if (na==TYPE_IVEC2 && nb==TYPE_INT) { + valid=true; + ret_type=TYPE_IVEC2; + } else if (na==TYPE_IVEC3 && nb==TYPE_INT) { + valid=true; + ret_type=TYPE_IVEC3; + } else if (na==TYPE_IVEC4 && nb==TYPE_INT ) { + valid=true; + ret_type=TYPE_IVEC4; + } else if (na==TYPE_UVEC2 && nb==TYPE_UINT) { + valid=true; + ret_type=TYPE_UVEC2; + } else if (na==TYPE_UVEC3 && nb==TYPE_UINT) { + valid=true; + ret_type=TYPE_UVEC3; + } else if (na==TYPE_UVEC4 && nb==TYPE_UINT) { + valid=true; + ret_type=TYPE_UVEC4; + } else if (na==TYPE_VEC2 && nb==TYPE_FLOAT ) { + valid=true; + ret_type=TYPE_VEC2; + } else if (na==TYPE_VEC3 && nb==TYPE_FLOAT) { + valid=true; + ret_type=TYPE_VEC3; + } else if (na==TYPE_VEC4 && nb==TYPE_FLOAT) { + valid=true; + ret_type=TYPE_VEC4; + } else if (p_op->op==OP_ASSIGN_MUL && na==TYPE_MAT2 && nb==TYPE_VEC2) { + valid=true; + ret_type=TYPE_MAT2; + } else if (p_op->op==OP_ASSIGN_MUL && na==TYPE_MAT3 && nb==TYPE_VEC3) { + valid=true; + ret_type=TYPE_MAT3; + } else if (p_op->op==OP_ASSIGN_MUL && na==TYPE_MAT4 && nb==TYPE_VEC4) { + valid=true; + ret_type=TYPE_MAT4; + } + } break; + case OP_ASSIGN_BIT_AND: + case OP_ASSIGN_BIT_OR: + case OP_ASSIGN_BIT_XOR: + case OP_BIT_AND: + case OP_BIT_OR: + case OP_BIT_XOR: { - parser.advance(); - Error err = parse_block(parser,function->body); + /* + * The bitwise operators and (&), exclusive-or (^), and inclusive-or (|). The operands must be of type + * signed or unsigned integers or integer vectors. The operands cannot be vectors of differing size. If + * one operand is a scalar and the other a vector, the scalar is applied component-wise to the vector, + * resulting in the same type as the vector. The fundamental types of the operands (signed or unsigned) + * must match. + */ - if (err) - return err; + DataType na = p_op->arguments[0]->get_datatype(); + DataType nb = p_op->arguments[1]->get_datatype(); - // make sure that if the function has a return type, it does return something.. - if (function->return_type!=TYPE_VOID) { - bool found=false; - for(int i=0;i<function->body->statements.size();i++) { - if (function->body->statements[i]->type==Node::TYPE_CONTROL_FLOW) { + if (na>nb && p_op->op>=OP_BIT_AND) { + //can swap for non assign + SWAP(na,nb); + } - ControlFlowNode *cf = (ControlFlowNode*)function->body->statements[i]; - if (cf->flow_op==FLOW_OP_RETURN) { - // type of return was already checked when inserted - // no need to check here - found=true; - } + if (na==TYPE_INT && nb==TYPE_INT) { + valid=true; + ret_type=TYPE_INT; + } else if (na==TYPE_IVEC2 && nb==TYPE_INT) { + valid=true; + ret_type=TYPE_IVEC2; + } else if (na==TYPE_IVEC3 && nb==TYPE_INT) { + valid=true; + ret_type=TYPE_IVEC3; + } else if (na==TYPE_IVEC4 && nb==TYPE_INT) { + valid=true; + ret_type=TYPE_IVEC4; + } else if (na==TYPE_IVEC2 && nb==TYPE_IVEC2) { + valid=true; + ret_type=TYPE_IVEC2; + } else if (na==TYPE_IVEC3 && nb==TYPE_IVEC3) { + valid=true; + ret_type=TYPE_IVEC3; + } else if (na==TYPE_IVEC4 && nb==TYPE_IVEC4) { + valid=true; + ret_type=TYPE_IVEC4; + ///// + } else if (na==TYPE_UINT && nb==TYPE_UINT) { + valid=true; + ret_type=TYPE_UINT; + } else if (na==TYPE_UVEC2 && nb==TYPE_UINT) { + valid=true; + ret_type=TYPE_UVEC2; + } else if (na==TYPE_UVEC3 && nb==TYPE_UINT) { + valid=true; + ret_type=TYPE_UVEC3; + } else if (na==TYPE_UVEC4 && nb==TYPE_UINT) { + valid=true; + ret_type=TYPE_UVEC4; + } else if (na==TYPE_UVEC2 && nb==TYPE_UVEC2) { + valid=true; + ret_type=TYPE_UVEC2; + } else if (na==TYPE_UVEC3 && nb==TYPE_UVEC3) { + valid=true; + ret_type=TYPE_UVEC3; + } else if (na==TYPE_UVEC4 && nb==TYPE_UVEC4) { + valid=true; + ret_type=TYPE_UVEC4; } - } + } break; + case OP_BIT_INVERT: { //unaries + DataType na = p_op->arguments[0]->get_datatype(); + valid = na>=TYPE_INT && na<TYPE_FLOAT; + ret_type=na; + } break; + case OP_SELECT_IF: { + DataType na = p_op->arguments[0]->get_datatype(); + DataType nb = p_op->arguments[1]->get_datatype(); + DataType nc = p_op->arguments[2]->get_datatype(); - if (!found) { - parser.set_error("Function must return a value (use the main block)"); - return ERR_PARSE_ERROR; + valid = na==TYPE_BOOL && (nb==nc); + ret_type=nb; + } break; + default: { + ERR_FAIL_V(false); } } - return OK; -} + if (r_ret_type) + *r_ret_type=ret_type; + return valid; +} -const ShaderLanguage::IntrinsicFuncDef ShaderLanguage::intrinsic_func_defs[]={ +const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[]={ //constructors {"bool",TYPE_BOOL,{TYPE_BOOL,TYPE_VOID}}, + {"bvec2",TYPE_BVEC2,{TYPE_BOOL,TYPE_VOID}}, + {"bvec2",TYPE_BVEC2,{TYPE_BOOL,TYPE_BOOL,TYPE_VOID}}, + {"bvec3",TYPE_BVEC3,{TYPE_BOOL,TYPE_VOID}}, + {"bvec3",TYPE_BVEC3,{TYPE_BOOL,TYPE_BOOL,TYPE_BOOL,TYPE_VOID}}, + {"bvec3",TYPE_BVEC3,{TYPE_BVEC2,TYPE_BOOL,TYPE_VOID}}, + {"bvec3",TYPE_BVEC3,{TYPE_BOOL,TYPE_BVEC2,TYPE_VOID}}, + {"bvec4",TYPE_BVEC4,{TYPE_BOOL,TYPE_VOID}}, + {"bvec4",TYPE_BVEC4,{TYPE_BOOL,TYPE_BOOL,TYPE_BOOL,TYPE_BOOL,TYPE_VOID}}, + {"bvec4",TYPE_BVEC4,{TYPE_BOOL,TYPE_BVEC2,TYPE_BOOL,TYPE_VOID}}, + {"bvec4",TYPE_BVEC4,{TYPE_BVEC2,TYPE_BOOL,TYPE_BOOL,TYPE_VOID}}, + {"bvec4",TYPE_BVEC4,{TYPE_BOOL,TYPE_BOOL,TYPE_BVEC2,TYPE_VOID}}, + {"bvec4",TYPE_BVEC4,{TYPE_BOOL,TYPE_BVEC3,TYPE_VOID}}, + {"bvec4",TYPE_BVEC4,{TYPE_BVEC3,TYPE_BOOL,TYPE_VOID}}, + {"bvec4",TYPE_BVEC4,{TYPE_BVEC2,TYPE_BVEC2,TYPE_VOID}}, + + {"float",TYPE_FLOAT,{TYPE_FLOAT,TYPE_VOID}}, {"vec2",TYPE_VEC2,{TYPE_FLOAT,TYPE_VOID}}, {"vec2",TYPE_VEC2,{TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}}, @@ -791,10 +1213,132 @@ const ShaderLanguage::IntrinsicFuncDef ShaderLanguage::intrinsic_func_defs[]={ {"vec4",TYPE_VEC4,{TYPE_FLOAT,TYPE_VEC3,TYPE_VOID}}, {"vec4",TYPE_VEC4,{TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}}, {"vec4",TYPE_VEC4,{TYPE_VEC2,TYPE_VEC2,TYPE_VOID}}, + + {"int",TYPE_INT,{TYPE_INT,TYPE_VOID}}, + {"ivec2",TYPE_IVEC2,{TYPE_INT,TYPE_VOID}}, + {"ivec2",TYPE_IVEC2,{TYPE_INT,TYPE_INT,TYPE_VOID}}, + {"ivec3",TYPE_IVEC3,{TYPE_INT,TYPE_VOID}}, + {"ivec3",TYPE_IVEC3,{TYPE_INT,TYPE_INT,TYPE_INT,TYPE_VOID}}, + {"ivec3",TYPE_IVEC3,{TYPE_IVEC2,TYPE_INT,TYPE_VOID}}, + {"ivec3",TYPE_IVEC3,{TYPE_INT,TYPE_IVEC2,TYPE_VOID}}, + {"ivec4",TYPE_IVEC4,{TYPE_INT,TYPE_VOID}}, + {"ivec4",TYPE_IVEC4,{TYPE_INT,TYPE_INT,TYPE_INT,TYPE_INT,TYPE_VOID}}, + {"ivec4",TYPE_IVEC4,{TYPE_INT,TYPE_IVEC2,TYPE_INT,TYPE_VOID}}, + {"ivec4",TYPE_IVEC4,{TYPE_IVEC2,TYPE_INT,TYPE_INT,TYPE_VOID}}, + {"ivec4",TYPE_IVEC4,{TYPE_INT,TYPE_INT,TYPE_IVEC2,TYPE_VOID}}, + {"ivec4",TYPE_IVEC4,{TYPE_INT,TYPE_IVEC3,TYPE_VOID}}, + {"ivec4",TYPE_IVEC4,{TYPE_IVEC3,TYPE_INT,TYPE_VOID}}, + {"ivec4",TYPE_IVEC4,{TYPE_IVEC2,TYPE_IVEC2,TYPE_VOID}}, + + {"uint",TYPE_UINT,{TYPE_UINT,TYPE_VOID}}, + {"uvec2",TYPE_UVEC2,{TYPE_UINT,TYPE_VOID}}, + {"uvec2",TYPE_UVEC2,{TYPE_UINT,TYPE_UINT,TYPE_VOID}}, + {"uvec3",TYPE_UVEC3,{TYPE_UINT,TYPE_VOID}}, + {"uvec3",TYPE_UVEC3,{TYPE_UINT,TYPE_UINT,TYPE_UINT,TYPE_VOID}}, + {"uvec3",TYPE_UVEC3,{TYPE_UVEC2,TYPE_UINT,TYPE_VOID}}, + {"uvec3",TYPE_UVEC3,{TYPE_UINT,TYPE_UVEC2,TYPE_VOID}}, + {"uvec4",TYPE_UVEC4,{TYPE_UINT,TYPE_VOID}}, + {"uvec4",TYPE_UVEC4,{TYPE_UINT,TYPE_UINT,TYPE_UINT,TYPE_UINT,TYPE_VOID}}, + {"uvec4",TYPE_UVEC4,{TYPE_UINT,TYPE_UVEC2,TYPE_UINT,TYPE_VOID}}, + {"uvec4",TYPE_UVEC4,{TYPE_UVEC2,TYPE_UINT,TYPE_UINT,TYPE_VOID}}, + {"uvec4",TYPE_UVEC4,{TYPE_UINT,TYPE_UINT,TYPE_UVEC2,TYPE_VOID}}, + {"uvec4",TYPE_UVEC4,{TYPE_UINT,TYPE_UVEC3,TYPE_VOID}}, + {"uvec4",TYPE_UVEC4,{TYPE_UVEC3,TYPE_UINT,TYPE_VOID}}, + {"uvec4",TYPE_UVEC4,{TYPE_UVEC2,TYPE_UVEC2,TYPE_VOID}}, + {"mat2",TYPE_MAT2,{TYPE_VEC2,TYPE_VEC2,TYPE_VOID}}, {"mat3",TYPE_MAT3,{TYPE_VEC3,TYPE_VEC3,TYPE_VEC3,TYPE_VOID}}, {"mat4",TYPE_MAT4,{TYPE_VEC4,TYPE_VEC4,TYPE_VEC4,TYPE_VEC4,TYPE_VOID}}, - //intrinsics - trigonometry + + {"mat2",TYPE_MAT2,{TYPE_FLOAT,TYPE_VOID}}, + {"mat3",TYPE_MAT3,{TYPE_FLOAT,TYPE_VOID}}, + {"mat4",TYPE_MAT4,{TYPE_FLOAT,TYPE_VOID}}, + + //conversion scalars + + {"int",TYPE_INT,{TYPE_BOOL,TYPE_VOID}}, + {"int",TYPE_INT,{TYPE_INT,TYPE_VOID}}, + {"int",TYPE_INT,{TYPE_UINT,TYPE_VOID}}, + {"int",TYPE_INT,{TYPE_FLOAT,TYPE_VOID}}, + + {"float",TYPE_FLOAT,{TYPE_BOOL,TYPE_VOID}}, + {"float",TYPE_FLOAT,{TYPE_INT,TYPE_VOID}}, + {"float",TYPE_FLOAT,{TYPE_UINT,TYPE_VOID}}, + {"float",TYPE_FLOAT,{TYPE_FLOAT,TYPE_VOID}}, + + {"uint",TYPE_UINT,{TYPE_BOOL,TYPE_VOID}}, + {"uint",TYPE_UINT,{TYPE_INT,TYPE_VOID}}, + {"uint",TYPE_UINT,{TYPE_UINT,TYPE_VOID}}, + {"uint",TYPE_UINT,{TYPE_FLOAT,TYPE_VOID}}, + + {"bool",TYPE_BOOL,{TYPE_BOOL,TYPE_VOID}}, + {"bool",TYPE_BOOL,{TYPE_INT,TYPE_VOID}}, + {"bool",TYPE_BOOL,{TYPE_UINT,TYPE_VOID}}, + {"bool",TYPE_BOOL,{TYPE_FLOAT,TYPE_VOID}}, + + //conversion vectors + + {"ivec2",TYPE_IVEC2,{TYPE_BVEC2,TYPE_VOID}}, + {"ivec2",TYPE_IVEC2,{TYPE_IVEC2,TYPE_VOID}}, + {"ivec2",TYPE_IVEC2,{TYPE_UVEC2,TYPE_VOID}}, + {"ivec2",TYPE_IVEC2,{TYPE_VEC2,TYPE_VOID}}, + + {"vec2",TYPE_VEC2,{TYPE_BVEC2,TYPE_VOID}}, + {"vec2",TYPE_VEC2,{TYPE_IVEC2,TYPE_VOID}}, + {"vec2",TYPE_VEC2,{TYPE_UVEC2,TYPE_VOID}}, + {"vec2",TYPE_VEC2,{TYPE_VEC2,TYPE_VOID}}, + + {"uvec2",TYPE_UVEC2,{TYPE_BVEC2,TYPE_VOID}}, + {"uvec2",TYPE_UVEC2,{TYPE_IVEC2,TYPE_VOID}}, + {"uvec2",TYPE_UVEC2,{TYPE_UVEC2,TYPE_VOID}}, + {"uvec2",TYPE_UVEC2,{TYPE_VEC2,TYPE_VOID}}, + + {"bvec2",TYPE_BVEC2,{TYPE_BVEC2,TYPE_VOID}}, + {"bvec2",TYPE_BVEC2,{TYPE_IVEC2,TYPE_VOID}}, + {"bvec2",TYPE_BVEC2,{TYPE_UVEC2,TYPE_VOID}}, + {"bvec2",TYPE_BVEC2,{TYPE_VEC2,TYPE_VOID}}, + + {"ivec3",TYPE_IVEC3,{TYPE_BVEC3,TYPE_VOID}}, + {"ivec3",TYPE_IVEC3,{TYPE_IVEC3,TYPE_VOID}}, + {"ivec3",TYPE_IVEC3,{TYPE_UVEC3,TYPE_VOID}}, + {"ivec3",TYPE_IVEC3,{TYPE_VEC3,TYPE_VOID}}, + + {"vec3",TYPE_VEC3,{TYPE_BVEC3,TYPE_VOID}}, + {"vec3",TYPE_VEC3,{TYPE_IVEC3,TYPE_VOID}}, + {"vec3",TYPE_VEC3,{TYPE_UVEC3,TYPE_VOID}}, + {"vec3",TYPE_VEC3,{TYPE_VEC3,TYPE_VOID}}, + + {"uvec3",TYPE_UVEC3,{TYPE_BVEC3,TYPE_VOID}}, + {"uvec3",TYPE_UVEC3,{TYPE_IVEC3,TYPE_VOID}}, + {"uvec3",TYPE_UVEC3,{TYPE_UVEC3,TYPE_VOID}}, + {"uvec3",TYPE_UVEC3,{TYPE_VEC3,TYPE_VOID}}, + + {"bvec3",TYPE_BVEC3,{TYPE_BVEC3,TYPE_VOID}}, + {"bvec3",TYPE_BVEC3,{TYPE_IVEC3,TYPE_VOID}}, + {"bvec3",TYPE_BVEC3,{TYPE_UVEC3,TYPE_VOID}}, + {"bvec3",TYPE_BVEC3,{TYPE_VEC3,TYPE_VOID}}, + + {"ivec4",TYPE_IVEC4,{TYPE_BVEC4,TYPE_VOID}}, + {"ivec4",TYPE_IVEC4,{TYPE_IVEC4,TYPE_VOID}}, + {"ivec4",TYPE_IVEC4,{TYPE_UVEC4,TYPE_VOID}}, + {"ivec4",TYPE_IVEC4,{TYPE_VEC4,TYPE_VOID}}, + + {"vec4",TYPE_VEC4,{TYPE_BVEC4,TYPE_VOID}}, + {"vec4",TYPE_VEC4,{TYPE_IVEC4,TYPE_VOID}}, + {"vec4",TYPE_VEC4,{TYPE_UVEC4,TYPE_VOID}}, + {"vec4",TYPE_VEC4,{TYPE_VEC4,TYPE_VOID}}, + + {"uvec4",TYPE_UVEC4,{TYPE_BVEC4,TYPE_VOID}}, + {"uvec4",TYPE_UVEC4,{TYPE_IVEC4,TYPE_VOID}}, + {"uvec4",TYPE_UVEC4,{TYPE_UVEC4,TYPE_VOID}}, + {"uvec4",TYPE_UVEC4,{TYPE_VEC4,TYPE_VOID}}, + + {"bvec4",TYPE_BVEC4,{TYPE_BVEC4,TYPE_VOID}}, + {"bvec4",TYPE_BVEC4,{TYPE_IVEC4,TYPE_VOID}}, + {"bvec4",TYPE_BVEC4,{TYPE_UVEC4,TYPE_VOID}}, + {"bvec4",TYPE_BVEC4,{TYPE_VEC4,TYPE_VOID}}, + + //builtins - trigonometry {"sin",TYPE_FLOAT,{TYPE_FLOAT,TYPE_VOID}}, {"cos",TYPE_FLOAT,{TYPE_FLOAT,TYPE_VOID}}, {"tan",TYPE_FLOAT,{TYPE_FLOAT,TYPE_VOID}}, @@ -805,7 +1349,7 @@ const ShaderLanguage::IntrinsicFuncDef ShaderLanguage::intrinsic_func_defs[]={ {"sinh",TYPE_FLOAT,{TYPE_FLOAT,TYPE_VOID}}, {"cosh",TYPE_FLOAT,{TYPE_FLOAT,TYPE_VOID}}, {"tanh",TYPE_FLOAT,{TYPE_FLOAT,TYPE_VOID}}, - //intrinsics - exponential + //builtins - exponential {"pow",TYPE_FLOAT,{TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}}, {"pow",TYPE_VEC2,{TYPE_VEC2,TYPE_FLOAT,TYPE_VOID}}, {"pow",TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_VOID}}, @@ -825,15 +1369,34 @@ const ShaderLanguage::IntrinsicFuncDef ShaderLanguage::intrinsic_func_defs[]={ {"sqrt",TYPE_VEC2,{TYPE_VEC2,TYPE_VOID}}, {"sqrt",TYPE_VEC3,{TYPE_VEC3,TYPE_VOID}}, {"sqrt",TYPE_VEC4,{TYPE_VEC4,TYPE_VOID}}, - //intrinsics - common + //builtins - common {"abs",TYPE_FLOAT,{TYPE_FLOAT,TYPE_VOID}}, {"abs",TYPE_VEC2,{TYPE_VEC2,TYPE_VOID}}, {"abs",TYPE_VEC3,{TYPE_VEC3,TYPE_VOID}}, {"abs",TYPE_VEC4,{TYPE_VEC4,TYPE_VOID}}, + + {"abs",TYPE_INT,{TYPE_INT,TYPE_VOID}}, + {"abs",TYPE_IVEC2,{TYPE_IVEC2,TYPE_VOID}}, + {"abs",TYPE_IVEC3,{TYPE_IVEC3,TYPE_VOID}}, + {"abs",TYPE_IVEC4,{TYPE_IVEC4,TYPE_VOID}}, + + {"abs",TYPE_UINT,{TYPE_UINT,TYPE_VOID}}, + {"abs",TYPE_UVEC2,{TYPE_UVEC2,TYPE_VOID}}, + {"abs",TYPE_UVEC3,{TYPE_UVEC3,TYPE_VOID}}, + {"abs",TYPE_UVEC4,{TYPE_UVEC4,TYPE_VOID}}, + + {"sign",TYPE_FLOAT,{TYPE_FLOAT,TYPE_VOID}}, {"sign",TYPE_VEC2,{TYPE_VEC2,TYPE_VOID}}, {"sign",TYPE_VEC3,{TYPE_VEC3,TYPE_VOID}}, {"sign",TYPE_VEC4,{TYPE_VEC4,TYPE_VOID}}, + + {"sign",TYPE_INT,{TYPE_INT,TYPE_VOID}}, + {"sign",TYPE_IVEC2,{TYPE_IVEC2,TYPE_VOID}}, + {"sign",TYPE_IVEC3,{TYPE_IVEC3,TYPE_VOID}}, + {"sign",TYPE_IVEC4,{TYPE_IVEC4,TYPE_VOID}}, + + {"floor",TYPE_FLOAT,{TYPE_FLOAT,TYPE_VOID}}, {"floor",TYPE_VEC2,{TYPE_VEC2,TYPE_VOID}}, {"floor",TYPE_VEC3,{TYPE_VEC3,TYPE_VOID}}, @@ -854,18 +1417,51 @@ const ShaderLanguage::IntrinsicFuncDef ShaderLanguage::intrinsic_func_defs[]={ {"fract",TYPE_VEC2,{TYPE_VEC2,TYPE_VOID}}, {"fract",TYPE_VEC3,{TYPE_VEC3,TYPE_VOID}}, {"fract",TYPE_VEC4,{TYPE_VEC4,TYPE_VOID}}, + {"mod",TYPE_FLOAT,{TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}}, {"mod",TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_VOID}}, + {"mod",TYPE_VEC2,{TYPE_VEC2,TYPE_FLOAT,TYPE_VOID}}, {"mod",TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_VOID}}, + {"mod",TYPE_VEC3,{TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}}, {"mod",TYPE_VEC4,{TYPE_VEC4,TYPE_VEC4,TYPE_VOID}}, + {"mod",TYPE_VEC4,{TYPE_VEC4,TYPE_FLOAT,TYPE_VOID}}, + + {"modf",TYPE_FLOAT,{TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}}, + {"modf",TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_VOID}}, + {"modf",TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_VOID}}, + {"modf",TYPE_VEC4,{TYPE_VEC4,TYPE_VEC4,TYPE_VOID}}, + {"min",TYPE_FLOAT,{TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}}, {"min",TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_VOID}}, {"min",TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_VOID}}, {"min",TYPE_VEC4,{TYPE_VEC4,TYPE_VEC4,TYPE_VOID}}, + + {"min",TYPE_INT,{TYPE_INT,TYPE_INT,TYPE_VOID}}, + {"min",TYPE_IVEC2,{TYPE_IVEC2,TYPE_IVEC2,TYPE_VOID}}, + {"min",TYPE_IVEC3,{TYPE_IVEC3,TYPE_IVEC3,TYPE_VOID}}, + {"min",TYPE_IVEC4,{TYPE_IVEC4,TYPE_IVEC4,TYPE_VOID}}, + + {"min",TYPE_UINT,{TYPE_UINT,TYPE_UINT,TYPE_VOID}}, + {"min",TYPE_UVEC2,{TYPE_UVEC2,TYPE_UVEC2,TYPE_VOID}}, + {"min",TYPE_UVEC3,{TYPE_UVEC3,TYPE_UVEC3,TYPE_VOID}}, + {"min",TYPE_UVEC4,{TYPE_UVEC4,TYPE_UVEC4,TYPE_VOID}}, + {"max",TYPE_FLOAT,{TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}}, {"max",TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_VOID}}, {"max",TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_VOID}}, {"max",TYPE_VEC4,{TYPE_VEC4,TYPE_VEC4,TYPE_VOID}}, + + {"max",TYPE_INT,{TYPE_INT,TYPE_INT,TYPE_VOID}}, + {"max",TYPE_IVEC2,{TYPE_IVEC2,TYPE_IVEC2,TYPE_VOID}}, + {"max",TYPE_IVEC3,{TYPE_IVEC3,TYPE_IVEC3,TYPE_VOID}}, + {"max",TYPE_IVEC4,{TYPE_IVEC4,TYPE_IVEC4,TYPE_VOID}}, + + {"max",TYPE_UINT,{TYPE_UINT,TYPE_UINT,TYPE_VOID}}, + {"max",TYPE_UVEC2,{TYPE_UVEC2,TYPE_UVEC2,TYPE_VOID}}, + {"max",TYPE_UVEC3,{TYPE_UVEC3,TYPE_UVEC3,TYPE_VOID}}, + {"max",TYPE_UVEC4,{TYPE_UVEC4,TYPE_UVEC4,TYPE_VOID}}, + + {"clamp",TYPE_FLOAT,{TYPE_FLOAT,TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}}, {"clamp",TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_VEC2,TYPE_VOID}}, {"clamp",TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_VEC3,TYPE_VOID}}, @@ -873,13 +1469,39 @@ const ShaderLanguage::IntrinsicFuncDef ShaderLanguage::intrinsic_func_defs[]={ {"clamp",TYPE_VEC2,{TYPE_VEC2,TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}}, {"clamp",TYPE_VEC3,{TYPE_VEC3,TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}}, {"clamp",TYPE_VEC4,{TYPE_VEC4,TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}}, + + + {"clamp",TYPE_INT,{TYPE_INT,TYPE_INT,TYPE_INT,TYPE_VOID}}, + {"clamp",TYPE_IVEC2,{TYPE_IVEC2,TYPE_IVEC2,TYPE_IVEC2,TYPE_VOID}}, + {"clamp",TYPE_IVEC3,{TYPE_IVEC3,TYPE_IVEC3,TYPE_IVEC3,TYPE_VOID}}, + {"clamp",TYPE_IVEC4,{TYPE_IVEC4,TYPE_IVEC4,TYPE_IVEC4,TYPE_VOID}}, + {"clamp",TYPE_IVEC2,{TYPE_IVEC2,TYPE_INT,TYPE_INT,TYPE_VOID}}, + {"clamp",TYPE_IVEC3,{TYPE_IVEC3,TYPE_INT,TYPE_INT,TYPE_VOID}}, + {"clamp",TYPE_IVEC4,{TYPE_IVEC4,TYPE_INT,TYPE_INT,TYPE_VOID}}, + + {"clamp",TYPE_UINT,{TYPE_UINT,TYPE_UINT,TYPE_UINT,TYPE_VOID}}, + {"clamp",TYPE_UVEC2,{TYPE_UVEC2,TYPE_UVEC2,TYPE_UVEC2,TYPE_VOID}}, + {"clamp",TYPE_UVEC3,{TYPE_UVEC3,TYPE_UVEC3,TYPE_UVEC3,TYPE_VOID}}, + {"clamp",TYPE_UVEC4,{TYPE_UVEC4,TYPE_UVEC4,TYPE_UVEC4,TYPE_VOID}}, + {"clamp",TYPE_UVEC2,{TYPE_UVEC2,TYPE_UINT,TYPE_UINT,TYPE_VOID}}, + {"clamp",TYPE_UVEC3,{TYPE_UVEC3,TYPE_UINT,TYPE_UINT,TYPE_VOID}}, + {"clamp",TYPE_UVEC4,{TYPE_UVEC4,TYPE_UINT,TYPE_UINT,TYPE_VOID}}, + {"mix",TYPE_FLOAT,{TYPE_FLOAT,TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}}, + {"mix",TYPE_FLOAT,{TYPE_FLOAT,TYPE_FLOAT,TYPE_BOOL,TYPE_VOID}}, {"mix",TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_FLOAT,TYPE_VOID}}, + {"mix",TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_BOOL,TYPE_VOID}}, + {"mix",TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_BVEC2,TYPE_VOID}}, {"mix",TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_VEC2,TYPE_VOID}}, {"mix",TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}}, + {"mix",TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_BOOL,TYPE_VOID}}, + {"mix",TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_BVEC3,TYPE_VOID}}, {"mix",TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_VEC3,TYPE_VOID}}, {"mix",TYPE_VEC4,{TYPE_VEC4,TYPE_VEC4,TYPE_FLOAT,TYPE_VOID}}, + {"mix",TYPE_VEC4,{TYPE_VEC4,TYPE_VEC4,TYPE_BOOL,TYPE_VOID}}, + {"mix",TYPE_VEC4,{TYPE_VEC4,TYPE_VEC4,TYPE_BVEC3,TYPE_VOID}}, {"mix",TYPE_VEC4,{TYPE_VEC4,TYPE_VEC4,TYPE_VEC4,TYPE_VOID}}, + {"step",TYPE_FLOAT,{TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}}, {"step",TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_VOID}}, {"step",TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_VOID}}, @@ -895,7 +1517,37 @@ const ShaderLanguage::IntrinsicFuncDef ShaderLanguage::intrinsic_func_defs[]={ {"smoothstep",TYPE_VEC3,{TYPE_FLOAT,TYPE_FLOAT,TYPE_VEC3,TYPE_VOID}}, {"smoothstep",TYPE_VEC4,{TYPE_FLOAT,TYPE_FLOAT,TYPE_VEC4,TYPE_VOID}}, - //intrinsics - geometric + {"isnan",TYPE_BOOL,{TYPE_FLOAT,TYPE_VOID}}, + {"isnan",TYPE_BOOL,{TYPE_VEC2,TYPE_VOID}}, + {"isnan",TYPE_BOOL,{TYPE_VEC3,TYPE_VOID}}, + {"isnan",TYPE_BOOL,{TYPE_VEC4,TYPE_VOID}}, + + {"isinf",TYPE_BOOL,{TYPE_FLOAT,TYPE_VOID}}, + {"isinf",TYPE_BOOL,{TYPE_VEC2,TYPE_VOID}}, + {"isinf",TYPE_BOOL,{TYPE_VEC3,TYPE_VOID}}, + {"isinf",TYPE_BOOL,{TYPE_VEC4,TYPE_VOID}}, + + {"floatBitsToInt",TYPE_INT,{TYPE_FLOAT,TYPE_VOID}}, + {"floatBitsToInt",TYPE_IVEC2,{TYPE_VEC2,TYPE_VOID}}, + {"floatBitsToInt",TYPE_IVEC3,{TYPE_VEC3,TYPE_VOID}}, + {"floatBitsToInt",TYPE_IVEC4,{TYPE_VEC4,TYPE_VOID}}, + + {"floatBitsToUInt",TYPE_UINT,{TYPE_FLOAT,TYPE_VOID}}, + {"floatBitsToUInt",TYPE_UVEC2,{TYPE_VEC2,TYPE_VOID}}, + {"floatBitsToUInt",TYPE_UVEC3,{TYPE_VEC3,TYPE_VOID}}, + {"floatBitsToUInt",TYPE_UVEC4,{TYPE_VEC4,TYPE_VOID}}, + + {"intBitsToFloat",TYPE_FLOAT,{TYPE_INT,TYPE_VOID}}, + {"intBitsToFloat",TYPE_VEC2,{TYPE_IVEC2,TYPE_VOID}}, + {"intBitsToFloat",TYPE_VEC3,{TYPE_IVEC3,TYPE_VOID}}, + {"intBitsToFloat",TYPE_VEC4,{TYPE_IVEC4,TYPE_VOID}}, + + {"uintBitsToFloat",TYPE_FLOAT,{TYPE_UINT,TYPE_VOID}}, + {"uintBitsToFloat",TYPE_VEC2,{TYPE_UVEC2,TYPE_VOID}}, + {"uintBitsToFloat",TYPE_VEC3,{TYPE_UVEC3,TYPE_VOID}}, + {"uintBitsToFloat",TYPE_VEC4,{TYPE_UVEC4,TYPE_VOID}}, + + //builtins - geometric {"length",TYPE_FLOAT,{TYPE_VEC2,TYPE_VOID}}, {"length",TYPE_FLOAT,{TYPE_VEC3,TYPE_VOID}}, {"length",TYPE_FLOAT,{TYPE_VEC4,TYPE_VOID}}, @@ -911,317 +1563,211 @@ const ShaderLanguage::IntrinsicFuncDef ShaderLanguage::intrinsic_func_defs[]={ {"normalize",TYPE_VEC4,{TYPE_VEC4,TYPE_VOID}}, {"reflect",TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_VOID}}, {"refract",TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}}, - //intrinsics - texture - {"tex",TYPE_VEC4,{TYPE_TEXTURE,TYPE_VEC2,TYPE_VOID}}, - {"texcube",TYPE_VEC4,{TYPE_CUBEMAP,TYPE_VEC3,TYPE_VOID}}, - {"texscreen",TYPE_VEC3,{TYPE_VEC2,TYPE_VOID}}, - {"texpos",TYPE_VEC3,{TYPE_VEC3,TYPE_VOID}}, - {NULL,TYPE_VOID,{TYPE_VOID}} + {"facefordward",TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_VEC2,TYPE_VOID}}, + {"facefordward",TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_VEC3,TYPE_VOID}}, + {"facefordward",TYPE_VEC4,{TYPE_VEC4,TYPE_VEC4,TYPE_VEC4,TYPE_VOID}}, -}; + {"matrixCompMult",TYPE_MAT2,{TYPE_MAT2,TYPE_MAT2,TYPE_VOID}}, + {"matrixCompMult",TYPE_MAT3,{TYPE_MAT3,TYPE_MAT3,TYPE_VOID}}, + {"matrixCompMult",TYPE_MAT4,{TYPE_MAT4,TYPE_MAT4,TYPE_VOID}}, -const ShaderLanguage::OperatorDef ShaderLanguage::operator_defs[]={ - - {OP_ASSIGN,TYPE_VOID,{TYPE_BOOL,TYPE_BOOL}}, - {OP_ASSIGN,TYPE_VOID,{TYPE_FLOAT,TYPE_FLOAT}}, - {OP_ASSIGN,TYPE_VOID,{TYPE_VEC2,TYPE_VEC2}}, - {OP_ASSIGN,TYPE_VOID,{TYPE_VEC3,TYPE_VEC3}}, - {OP_ASSIGN,TYPE_VOID,{TYPE_VEC4,TYPE_VEC4}}, - {OP_ASSIGN,TYPE_VOID,{TYPE_MAT2,TYPE_MAT2}}, - {OP_ASSIGN,TYPE_VOID,{TYPE_MAT3,TYPE_MAT3}}, - {OP_ASSIGN,TYPE_VOID,{TYPE_MAT4,TYPE_MAT4}}, - {OP_ADD,TYPE_FLOAT,{TYPE_FLOAT,TYPE_FLOAT}}, - {OP_ADD,TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2}}, - {OP_ADD,TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3}}, - {OP_ADD,TYPE_VEC4,{TYPE_VEC4,TYPE_VEC4}}, - {OP_SUB,TYPE_FLOAT,{TYPE_FLOAT,TYPE_FLOAT}}, - {OP_SUB,TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2}}, - {OP_SUB,TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3}}, - {OP_SUB,TYPE_VEC4,{TYPE_VEC4,TYPE_VEC4}}, - {OP_MUL,TYPE_FLOAT,{TYPE_FLOAT,TYPE_FLOAT}}, - {OP_MUL,TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2}}, - {OP_MUL,TYPE_VEC2,{TYPE_VEC2,TYPE_FLOAT}}, - {OP_MUL,TYPE_VEC2,{TYPE_FLOAT,TYPE_VEC2}}, - {OP_MUL,TYPE_VEC2,{TYPE_VEC2,TYPE_MAT3}}, - {OP_MUL,TYPE_VEC2,{TYPE_MAT2,TYPE_VEC2}}, - {OP_MUL,TYPE_VEC2,{TYPE_VEC2,TYPE_MAT2}}, - {OP_MUL,TYPE_VEC2,{TYPE_MAT3,TYPE_VEC2}}, - {OP_MUL,TYPE_VEC2,{TYPE_VEC2,TYPE_MAT4}}, - {OP_MUL,TYPE_VEC2,{TYPE_MAT4,TYPE_VEC2}}, - {OP_MUL,TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3}}, - {OP_MUL,TYPE_VEC3,{TYPE_VEC3,TYPE_FLOAT}}, - {OP_MUL,TYPE_VEC3,{TYPE_FLOAT,TYPE_VEC3}}, - {OP_MUL,TYPE_VEC3,{TYPE_MAT3,TYPE_VEC3}}, - {OP_MUL,TYPE_VEC3,{TYPE_MAT4,TYPE_VEC3}}, - {OP_MUL,TYPE_VEC3,{TYPE_VEC3,TYPE_MAT3}}, - {OP_MUL,TYPE_VEC4,{TYPE_VEC4,TYPE_VEC4}}, - {OP_MUL,TYPE_VEC4,{TYPE_VEC4,TYPE_FLOAT}}, - {OP_MUL,TYPE_VEC4,{TYPE_FLOAT,TYPE_VEC4}}, - {OP_MUL,TYPE_VEC4,{TYPE_MAT4,TYPE_VEC4}}, - {OP_MUL,TYPE_VEC4,{TYPE_VEC4,TYPE_MAT4}}, - {OP_MUL,TYPE_MAT2,{TYPE_MAT2,TYPE_MAT2}}, - {OP_MUL,TYPE_MAT3,{TYPE_MAT3,TYPE_MAT3}}, - {OP_MUL,TYPE_MAT4,{TYPE_MAT4,TYPE_MAT4}}, - {OP_DIV,TYPE_FLOAT,{TYPE_FLOAT,TYPE_FLOAT}}, - {OP_DIV,TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2}}, - {OP_DIV,TYPE_VEC2,{TYPE_VEC2,TYPE_FLOAT}}, - {OP_DIV,TYPE_VEC2,{TYPE_FLOAT,TYPE_VEC2}}, - {OP_DIV,TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3}}, - {OP_DIV,TYPE_VEC3,{TYPE_VEC3,TYPE_FLOAT}}, - {OP_DIV,TYPE_VEC3,{TYPE_FLOAT,TYPE_VEC3}}, - {OP_DIV,TYPE_VEC4,{TYPE_VEC4,TYPE_VEC4}}, - {OP_DIV,TYPE_VEC4,{TYPE_VEC4,TYPE_FLOAT}}, - {OP_DIV,TYPE_VEC4,{TYPE_FLOAT,TYPE_VEC4}}, - {OP_ASSIGN_ADD,TYPE_VOID,{TYPE_FLOAT,TYPE_FLOAT}}, - {OP_ASSIGN_ADD,TYPE_VOID,{TYPE_VEC2,TYPE_VEC2}}, - {OP_ASSIGN_ADD,TYPE_VOID,{TYPE_VEC3,TYPE_VEC3}}, - {OP_ASSIGN_ADD,TYPE_VOID,{TYPE_VEC4,TYPE_VEC4}}, - {OP_ASSIGN_ADD,TYPE_VOID,{TYPE_VEC2,TYPE_FLOAT}}, - {OP_ASSIGN_ADD,TYPE_VOID,{TYPE_VEC3,TYPE_FLOAT}}, - {OP_ASSIGN_ADD,TYPE_VOID,{TYPE_VEC4,TYPE_FLOAT}}, - {OP_ASSIGN_SUB,TYPE_VOID,{TYPE_FLOAT,TYPE_FLOAT}}, - {OP_ASSIGN_SUB,TYPE_VOID,{TYPE_VEC2,TYPE_VEC2}}, - {OP_ASSIGN_SUB,TYPE_VOID,{TYPE_VEC3,TYPE_VEC3}}, - {OP_ASSIGN_SUB,TYPE_VOID,{TYPE_VEC4,TYPE_VEC4}}, - {OP_ASSIGN_SUB,TYPE_VOID,{TYPE_VEC2,TYPE_FLOAT}}, - {OP_ASSIGN_SUB,TYPE_VOID,{TYPE_VEC3,TYPE_FLOAT}}, - {OP_ASSIGN_SUB,TYPE_VOID,{TYPE_VEC4,TYPE_FLOAT}}, - {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_FLOAT,TYPE_FLOAT}}, - {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_VEC2,TYPE_VEC2}}, - {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_VEC2,TYPE_FLOAT}}, - {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_VEC2,TYPE_MAT2}}, - {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_MAT2,TYPE_MAT2}}, - {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_VEC3,TYPE_MAT3}}, - {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_VEC3,TYPE_VEC3}}, - {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_VEC3,TYPE_FLOAT}}, - {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_VEC3,TYPE_MAT4}}, - {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_VEC4,TYPE_VEC4}}, - {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_VEC4,TYPE_FLOAT}}, - {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_VEC4,TYPE_MAT4}}, - {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_MAT3,TYPE_MAT3}}, - {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_MAT4,TYPE_MAT4}}, - {OP_ASSIGN_DIV,TYPE_VOID,{TYPE_FLOAT,TYPE_FLOAT}}, - {OP_ASSIGN_DIV,TYPE_VOID,{TYPE_VEC2,TYPE_VEC2}}, - {OP_ASSIGN_DIV,TYPE_VOID,{TYPE_VEC2,TYPE_FLOAT}}, - {OP_ASSIGN_DIV,TYPE_VOID,{TYPE_VEC3,TYPE_VEC3}}, - {OP_ASSIGN_DIV,TYPE_VOID,{TYPE_VEC3,TYPE_FLOAT}}, - {OP_ASSIGN_DIV,TYPE_VOID,{TYPE_VEC4,TYPE_VEC4}}, - {OP_ASSIGN_DIV,TYPE_VOID,{TYPE_VEC4,TYPE_FLOAT}}, - {OP_NEG,TYPE_FLOAT,{TYPE_FLOAT,TYPE_VOID}}, - {OP_NEG,TYPE_VEC2,{TYPE_VEC2,TYPE_VOID}}, - {OP_NEG,TYPE_VEC3,{TYPE_VEC3,TYPE_VOID}}, - {OP_NEG,TYPE_VEC4,{TYPE_VEC4,TYPE_VOID}}, - {OP_NOT,TYPE_BOOL,{TYPE_BOOL,TYPE_VOID}}, - {OP_CMP_EQ,TYPE_BOOL,{TYPE_BOOL,TYPE_BOOL}}, - {OP_CMP_EQ,TYPE_BOOL,{TYPE_FLOAT,TYPE_FLOAT}}, - {OP_CMP_EQ,TYPE_BOOL,{TYPE_VEC3,TYPE_VEC2}}, - {OP_CMP_EQ,TYPE_BOOL,{TYPE_VEC3,TYPE_VEC3}}, - {OP_CMP_EQ,TYPE_BOOL,{TYPE_VEC3,TYPE_VEC4}}, - //{OP_CMP_EQ,TYPE_MAT3,{TYPE_MAT4,TYPE_MAT3}}, ?? - //{OP_CMP_EQ,TYPE_MAT4,{TYPE_MAT4,TYPE_MAT4}}, ?? - {OP_CMP_NEQ,TYPE_BOOL,{TYPE_BOOL,TYPE_BOOL}}, - {OP_CMP_NEQ,TYPE_BOOL,{TYPE_FLOAT,TYPE_FLOAT}}, - {OP_CMP_NEQ,TYPE_BOOL,{TYPE_VEC2,TYPE_VEC2}}, - {OP_CMP_NEQ,TYPE_BOOL,{TYPE_VEC3,TYPE_VEC3}}, - {OP_CMP_NEQ,TYPE_BOOL,{TYPE_VEC4,TYPE_VEC4}}, - //{OP_CMP_NEQ,TYPE_MAT4,{TYPE_MAT4,TYPE_MAT4}}, //? - {OP_CMP_LEQ,TYPE_BOOL,{TYPE_FLOAT,TYPE_FLOAT}}, - {OP_CMP_GEQ,TYPE_BOOL,{TYPE_FLOAT,TYPE_FLOAT}}, - {OP_CMP_LESS,TYPE_BOOL,{TYPE_FLOAT,TYPE_FLOAT}}, - {OP_CMP_GREATER,TYPE_BOOL,{TYPE_FLOAT,TYPE_FLOAT}}, - {OP_CMP_OR,TYPE_BOOL,{TYPE_BOOL,TYPE_BOOL}}, - {OP_CMP_AND,TYPE_BOOL,{TYPE_BOOL,TYPE_BOOL}}, - {OP_MAX,TYPE_VOID,{TYPE_VOID,TYPE_VOID}} -}; + {"outerProduct",TYPE_MAT2,{TYPE_VEC2,TYPE_VEC2,TYPE_VOID}}, + {"outerProduct",TYPE_MAT3,{TYPE_VEC3,TYPE_VEC3,TYPE_VOID}}, + {"outerProduct",TYPE_MAT4,{TYPE_VEC4,TYPE_VEC4,TYPE_VOID}}, + {"transpose",TYPE_MAT2,{TYPE_MAT2,TYPE_VOID}}, + {"transpose",TYPE_MAT3,{TYPE_MAT3,TYPE_VOID}}, + {"transpose",TYPE_MAT4,{TYPE_MAT4,TYPE_VOID}}, -const ShaderLanguage::BuiltinsDef ShaderLanguage::vertex_builtins_defs[]={ - - { "SRC_VERTEX", TYPE_VEC3}, - { "SRC_NORMAL", TYPE_VEC3}, - { "SRC_TANGENT", TYPE_VEC3}, - { "SRC_BINORMALF", TYPE_FLOAT}, - - { "POSITION", TYPE_VEC4 }, - { "VERTEX", TYPE_VEC3}, - { "NORMAL", TYPE_VEC3}, - { "TANGENT", TYPE_VEC3}, - { "BINORMAL", TYPE_VEC3}, - { "UV", TYPE_VEC2}, - { "UV2", TYPE_VEC2}, - { "COLOR", TYPE_VEC4}, - { "BONES", TYPE_VEC4}, - { "WEIGHTS", TYPE_VEC4}, - { "VAR1", TYPE_VEC4}, - { "VAR2", TYPE_VEC4}, - { "SPEC_EXP", TYPE_FLOAT}, - { "POINT_SIZE", TYPE_FLOAT}, - - //builtins - { "WORLD_MATRIX", TYPE_MAT4}, - { "INV_CAMERA_MATRIX", TYPE_MAT4}, - { "PROJECTION_MATRIX", TYPE_MAT4}, - { "MODELVIEW_MATRIX", TYPE_MAT4}, - { "INSTANCE_ID", TYPE_FLOAT}, - { "TIME", TYPE_FLOAT}, - { NULL, TYPE_VOID}, -}; -const ShaderLanguage::BuiltinsDef ShaderLanguage::fragment_builtins_defs[]={ - - { "VERTEX", TYPE_VEC3}, - { "POSITION", TYPE_VEC4}, - { "NORMAL", TYPE_VEC3}, - { "TANGENT", TYPE_VEC3}, - { "BINORMAL", TYPE_VEC3}, - { "NORMALMAP", TYPE_VEC3}, - { "NORMALMAP_DEPTH", TYPE_FLOAT}, - { "UV", TYPE_VEC2}, - { "UV2", TYPE_VEC2}, - { "COLOR", TYPE_VEC4}, - { "NORMAL", TYPE_VEC3}, - { "VAR1", TYPE_VEC4}, - { "VAR2", TYPE_VEC4}, - { "DIFFUSE", TYPE_VEC3}, - { "DIFFUSE_ALPHA", TYPE_VEC4}, - { "SPECULAR", TYPE_VEC3}, - { "EMISSION", TYPE_VEC3}, - { "SPEC_EXP", TYPE_FLOAT}, - { "GLOW", TYPE_FLOAT}, - { "SHADE_PARAM", TYPE_FLOAT}, - { "DISCARD", TYPE_BOOL}, - { "SCREEN_UV", TYPE_VEC2}, - { "POINT_COORD", TYPE_VEC2}, - { "INV_CAMERA_MATRIX", TYPE_MAT4}, - -// { "SCREEN_POS", TYPE_VEC2}, -// { "SCREEN_TEXEL_SIZE", TYPE_VEC2}, - { "TIME", TYPE_FLOAT}, - { NULL, TYPE_VOID} + {"determinant",TYPE_FLOAT,{TYPE_MAT2,TYPE_VOID}}, + {"determinant",TYPE_FLOAT,{TYPE_MAT3,TYPE_VOID}}, + {"determinant",TYPE_FLOAT,{TYPE_MAT4,TYPE_VOID}}, -}; + {"inverse",TYPE_MAT2,{TYPE_MAT2,TYPE_VOID}}, + {"inverse",TYPE_MAT3,{TYPE_MAT3,TYPE_VOID}}, + {"inverse",TYPE_MAT4,{TYPE_MAT4,TYPE_VOID}}, -const ShaderLanguage::BuiltinsDef ShaderLanguage::light_builtins_defs[]={ - - { "NORMAL", TYPE_VEC3}, - { "LIGHT_DIR", TYPE_VEC3}, - { "LIGHT_DIFFUSE", TYPE_VEC3}, - { "LIGHT_SPECULAR", TYPE_VEC3}, - { "EYE_VEC", TYPE_VEC3}, - { "DIFFUSE", TYPE_VEC3}, - { "SPECULAR", TYPE_VEC3}, - { "SPECULAR_EXP", TYPE_FLOAT}, - { "SHADE_PARAM", TYPE_FLOAT}, - { "LIGHT", TYPE_VEC3}, - { "SHADOW", TYPE_VEC3 }, - { "POINT_COORD", TYPE_VEC2 }, -// { "SCREEN_POS", TYPE_VEC2}, -// { "SCREEN_TEXEL_SIZE", TYPE_VEC2}, - { "TIME", TYPE_FLOAT}, - { NULL, TYPE_VOID} -}; + {"lessThan",TYPE_BVEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_VOID}}, + {"lessThan",TYPE_BVEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_VOID}}, + {"lessThan",TYPE_BVEC4,{TYPE_VEC4,TYPE_VEC4,TYPE_VOID}}, + {"lessThan",TYPE_BVEC2,{TYPE_IVEC2,TYPE_IVEC2,TYPE_VOID}}, + {"lessThan",TYPE_BVEC3,{TYPE_IVEC3,TYPE_IVEC3,TYPE_VOID}}, + {"lessThan",TYPE_BVEC4,{TYPE_IVEC4,TYPE_IVEC4,TYPE_VOID}}, + {"lessThan",TYPE_BVEC2,{TYPE_UVEC2,TYPE_UVEC2,TYPE_VOID}}, + {"lessThan",TYPE_BVEC3,{TYPE_UVEC3,TYPE_UVEC3,TYPE_VOID}}, + {"lessThan",TYPE_BVEC4,{TYPE_UVEC4,TYPE_UVEC4,TYPE_VOID}}, -const ShaderLanguage::BuiltinsDef ShaderLanguage::ci_vertex_builtins_defs[]={ + {"greaterThan",TYPE_BVEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_VOID}}, + {"greaterThan",TYPE_BVEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_VOID}}, + {"greaterThan",TYPE_BVEC4,{TYPE_VEC4,TYPE_VEC4,TYPE_VOID}}, - { "SRC_VERTEX", TYPE_VEC2}, - { "VERTEX", TYPE_VEC2}, - { "WORLD_VERTEX", TYPE_VEC2}, - { "UV", TYPE_VEC2}, - { "COLOR", TYPE_VEC4}, - { "VAR1", TYPE_VEC4}, - { "VAR2", TYPE_VEC4}, - { "POINT_SIZE", TYPE_FLOAT}, + {"greaterThan",TYPE_BVEC2,{TYPE_IVEC2,TYPE_IVEC2,TYPE_VOID}}, + {"greaterThan",TYPE_BVEC3,{TYPE_IVEC3,TYPE_IVEC3,TYPE_VOID}}, + {"greaterThan",TYPE_BVEC4,{TYPE_IVEC4,TYPE_IVEC4,TYPE_VOID}}, - //builtins - { "WORLD_MATRIX", TYPE_MAT4}, - { "PROJECTION_MATRIX", TYPE_MAT4}, - { "EXTRA_MATRIX", TYPE_MAT4}, - { "TIME", TYPE_FLOAT}, - { NULL, TYPE_VOID}, -}; -const ShaderLanguage::BuiltinsDef ShaderLanguage::ci_fragment_builtins_defs[]={ - - { "SRC_COLOR", TYPE_VEC4}, - { "POSITION", TYPE_VEC4}, - { "NORMAL", TYPE_VEC3}, - { "NORMALMAP", TYPE_VEC3}, - { "NORMALMAP_DEPTH", TYPE_FLOAT}, - { "UV", TYPE_VEC2}, - { "COLOR", TYPE_VEC4}, - { "TEXTURE", TYPE_TEXTURE}, - { "TEXTURE_PIXEL_SIZE", TYPE_VEC2}, - { "VAR1", TYPE_VEC4}, - { "VAR2", TYPE_VEC4}, - { "SCREEN_UV", TYPE_VEC2}, - { "POINT_COORD", TYPE_VEC2}, - -// { "SCREEN_POS", TYPE_VEC2}, -// { "SCREEN_TEXEL_SIZE", TYPE_VEC2}, - { "TIME", TYPE_FLOAT}, - { NULL, TYPE_VOID} + {"greaterThan",TYPE_BVEC2,{TYPE_UVEC2,TYPE_UVEC2,TYPE_VOID}}, + {"greaterThan",TYPE_BVEC3,{TYPE_UVEC3,TYPE_UVEC3,TYPE_VOID}}, + {"greaterThan",TYPE_BVEC4,{TYPE_UVEC4,TYPE_UVEC4,TYPE_VOID}}, -}; + {"lessThanEqual",TYPE_BVEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_VOID}}, + {"lessThanEqual",TYPE_BVEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_VOID}}, + {"lessThanEqual",TYPE_BVEC4,{TYPE_VEC4,TYPE_VEC4,TYPE_VOID}}, -const ShaderLanguage::BuiltinsDef ShaderLanguage::ci_light_builtins_defs[]={ - - { "POSITION", TYPE_VEC4}, - { "NORMAL", TYPE_VEC3}, - { "UV", TYPE_VEC2}, - { "COLOR", TYPE_VEC4}, - { "TEXTURE", TYPE_TEXTURE}, - { "TEXTURE_PIXEL_SIZE", TYPE_VEC2}, - { "VAR1", TYPE_VEC4}, - { "VAR2", TYPE_VEC4}, - { "SCREEN_UV", TYPE_VEC2}, - { "LIGHT_VEC", TYPE_VEC2}, - { "LIGHT_HEIGHT", TYPE_FLOAT}, - { "LIGHT_COLOR", TYPE_VEC4}, - { "LIGHT_UV", TYPE_VEC2}, - { "LIGHT", TYPE_VEC4}, - { "SHADOW", TYPE_VEC4}, - { "POINT_COORD", TYPE_VEC2}, -// { "SCREEN_POS", TYPE_VEC2}, -// { "SCREEN_TEXEL_SIZE", TYPE_VEC2}, - { "TIME", TYPE_FLOAT}, - { NULL, TYPE_VOID} + {"lessThanEqual",TYPE_BVEC2,{TYPE_IVEC2,TYPE_IVEC2,TYPE_VOID}}, + {"lessThanEqual",TYPE_BVEC3,{TYPE_IVEC3,TYPE_IVEC3,TYPE_VOID}}, + {"lessThanEqual",TYPE_BVEC4,{TYPE_IVEC4,TYPE_IVEC4,TYPE_VOID}}, -}; + {"lessThanEqual",TYPE_BVEC2,{TYPE_UVEC2,TYPE_UVEC2,TYPE_VOID}}, + {"lessThanEqual",TYPE_BVEC3,{TYPE_UVEC3,TYPE_UVEC3,TYPE_VOID}}, + {"lessThanEqual",TYPE_BVEC4,{TYPE_UVEC4,TYPE_UVEC4,TYPE_VOID}}, -const ShaderLanguage::BuiltinsDef ShaderLanguage::postprocess_fragment_builtins_defs[]={ + {"greaterThanEqual",TYPE_BVEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_VOID}}, + {"greaterThanEqual",TYPE_BVEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_VOID}}, + {"greaterThanEqual",TYPE_BVEC4,{TYPE_VEC4,TYPE_VEC4,TYPE_VOID}}, - { "IN_COLOR", TYPE_VEC3}, - { "IN_POSITION", TYPE_VEC3}, - { "OUT_COLOR", TYPE_VEC3}, - { "SCREEN_POS", TYPE_VEC2}, - { "SCREEN_TEXEL_SIZE", TYPE_VEC2}, - { "TIME", TYPE_FLOAT}, - { NULL, TYPE_VOID} -}; + {"greaterThanEqual",TYPE_BVEC2,{TYPE_IVEC2,TYPE_IVEC2,TYPE_VOID}}, + {"greaterThanEqual",TYPE_BVEC3,{TYPE_IVEC3,TYPE_IVEC3,TYPE_VOID}}, + {"greaterThanEqual",TYPE_BVEC4,{TYPE_IVEC4,TYPE_IVEC4,TYPE_VOID}}, + {"greaterThanEqual",TYPE_BVEC2,{TYPE_UVEC2,TYPE_UVEC2,TYPE_VOID}}, + {"greaterThanEqual",TYPE_BVEC3,{TYPE_UVEC3,TYPE_UVEC3,TYPE_VOID}}, + {"greaterThanEqual",TYPE_BVEC4,{TYPE_UVEC4,TYPE_UVEC4,TYPE_VOID}}, + {"equal",TYPE_BVEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_VOID}}, + {"equal",TYPE_BVEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_VOID}}, + {"equal",TYPE_BVEC4,{TYPE_VEC4,TYPE_VEC4,TYPE_VOID}}, -ShaderLanguage::DataType ShaderLanguage::compute_node_type(Node *p_node) { + {"equal",TYPE_BVEC2,{TYPE_IVEC2,TYPE_IVEC2,TYPE_VOID}}, + {"equal",TYPE_BVEC3,{TYPE_IVEC3,TYPE_IVEC3,TYPE_VOID}}, + {"equal",TYPE_BVEC4,{TYPE_IVEC4,TYPE_IVEC4,TYPE_VOID}}, - switch(p_node->type) { + {"equal",TYPE_BVEC2,{TYPE_UVEC2,TYPE_UVEC2,TYPE_VOID}}, + {"equal",TYPE_BVEC3,{TYPE_UVEC3,TYPE_UVEC3,TYPE_VOID}}, + {"equal",TYPE_BVEC4,{TYPE_UVEC4,TYPE_UVEC4,TYPE_VOID}}, - case Node::TYPE_PROGRAM: ERR_FAIL_V(TYPE_VOID); - case Node::TYPE_FUNCTION: return static_cast<FunctionNode*>(p_node)->return_type; - case Node::TYPE_BLOCK: ERR_FAIL_V(TYPE_VOID); - case Node::TYPE_VARIABLE: return static_cast<VariableNode*>(p_node)->datatype_cache; - case Node::TYPE_CONSTANT: return static_cast<ConstantNode*>(p_node)->datatype; - case Node::TYPE_OPERATOR: return static_cast<OperatorNode*>(p_node)->return_cache; - case Node::TYPE_CONTROL_FLOW: ERR_FAIL_V(TYPE_VOID); - case Node::TYPE_MEMBER: return static_cast<MemberNode*>(p_node)->datatype; - } + {"equal",TYPE_BVEC2,{TYPE_BVEC2,TYPE_BVEC2,TYPE_VOID}}, + {"equal",TYPE_BVEC3,{TYPE_BVEC3,TYPE_BVEC3,TYPE_VOID}}, + {"equal",TYPE_BVEC4,{TYPE_BVEC4,TYPE_BVEC4,TYPE_VOID}}, - return TYPE_VOID; -} + {"notEqual",TYPE_BVEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_VOID}}, + {"notEqual",TYPE_BVEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_VOID}}, + {"notEqual",TYPE_BVEC4,{TYPE_VEC4,TYPE_VEC4,TYPE_VOID}}, + + {"notEqual",TYPE_BVEC2,{TYPE_IVEC2,TYPE_IVEC2,TYPE_VOID}}, + {"notEqual",TYPE_BVEC3,{TYPE_IVEC3,TYPE_IVEC3,TYPE_VOID}}, + {"notEqual",TYPE_BVEC4,{TYPE_IVEC4,TYPE_IVEC4,TYPE_VOID}}, + {"notEqual",TYPE_BVEC2,{TYPE_UVEC2,TYPE_UVEC2,TYPE_VOID}}, + {"notEqual",TYPE_BVEC3,{TYPE_UVEC3,TYPE_UVEC3,TYPE_VOID}}, + {"notEqual",TYPE_BVEC4,{TYPE_UVEC4,TYPE_UVEC4,TYPE_VOID}}, -ShaderLanguage::Node* ShaderLanguage::validate_function_call(Parser&parser, OperatorNode *p_func) { + {"notEqual",TYPE_BVEC2,{TYPE_BVEC2,TYPE_BVEC2,TYPE_VOID}}, + {"notEqual",TYPE_BVEC3,{TYPE_BVEC3,TYPE_BVEC3,TYPE_VOID}}, + {"notEqual",TYPE_BVEC4,{TYPE_BVEC4,TYPE_BVEC4,TYPE_VOID}}, + + {"any",TYPE_BOOL,{TYPE_BVEC2,TYPE_VOID}}, + {"any",TYPE_BOOL,{TYPE_BVEC3,TYPE_VOID}}, + {"any",TYPE_BOOL,{TYPE_BVEC4,TYPE_VOID}}, + + {"all",TYPE_BOOL,{TYPE_BVEC2,TYPE_VOID}}, + {"all",TYPE_BOOL,{TYPE_BVEC3,TYPE_VOID}}, + {"all",TYPE_BOOL,{TYPE_BVEC4,TYPE_VOID}}, + + {"not",TYPE_BOOL,{TYPE_BVEC2,TYPE_VOID}}, + {"not",TYPE_BOOL,{TYPE_BVEC3,TYPE_VOID}}, + {"not",TYPE_BOOL,{TYPE_BVEC4,TYPE_VOID}}, + + //builtins - texture + {"textureSize",TYPE_VEC2,{TYPE_SAMPLER2D,TYPE_INT,TYPE_VOID}}, + {"textureSize",TYPE_VEC2,{TYPE_ISAMPLER2D,TYPE_INT,TYPE_VOID}}, + {"textureSize",TYPE_VEC2,{TYPE_USAMPLER2D,TYPE_INT,TYPE_VOID}}, + {"textureSize",TYPE_VEC2,{TYPE_SAMPLERCUBE,TYPE_INT,TYPE_VOID}}, + + {"texture",TYPE_VEC4,{TYPE_SAMPLER2D,TYPE_VEC2,TYPE_VOID}}, + {"texture",TYPE_VEC4,{TYPE_SAMPLER2D,TYPE_VEC3,TYPE_VOID}}, + {"texture",TYPE_VEC4,{TYPE_SAMPLER2D,TYPE_VEC2,TYPE_FLOAT,TYPE_VOID}}, + {"texture",TYPE_VEC4,{TYPE_SAMPLER2D,TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}}, + + {"texture",TYPE_UVEC4,{TYPE_USAMPLER2D,TYPE_VEC2,TYPE_VOID}}, + {"texture",TYPE_UVEC4,{TYPE_USAMPLER2D,TYPE_VEC3,TYPE_VOID}}, + {"texture",TYPE_UVEC4,{TYPE_USAMPLER2D,TYPE_VEC2,TYPE_FLOAT,TYPE_VOID}}, + {"texture",TYPE_UVEC4,{TYPE_USAMPLER2D,TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}}, + + {"texture",TYPE_IVEC4,{TYPE_ISAMPLER2D,TYPE_VEC2,TYPE_VOID}}, + {"texture",TYPE_IVEC4,{TYPE_ISAMPLER2D,TYPE_VEC3,TYPE_VOID}}, + {"texture",TYPE_IVEC4,{TYPE_ISAMPLER2D,TYPE_VEC2,TYPE_FLOAT,TYPE_VOID}}, + {"texture",TYPE_IVEC4,{TYPE_ISAMPLER2D,TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}}, + + {"texture",TYPE_VEC4,{TYPE_SAMPLERCUBE,TYPE_VEC3,TYPE_VOID}}, + {"texture",TYPE_VEC4,{TYPE_SAMPLERCUBE,TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}}, + + {"textureProj",TYPE_VEC4,{TYPE_SAMPLER2D,TYPE_VEC3,TYPE_VOID}}, + {"textureProj",TYPE_VEC4,{TYPE_SAMPLER2D,TYPE_VEC4,TYPE_VOID}}, + {"textureProj",TYPE_VEC4,{TYPE_SAMPLER2D,TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}}, + {"textureProj",TYPE_VEC4,{TYPE_SAMPLER2D,TYPE_VEC4,TYPE_FLOAT,TYPE_VOID}}, + + {"textureProj",TYPE_IVEC4,{TYPE_ISAMPLER2D,TYPE_VEC3,TYPE_VOID}}, + {"textureProj",TYPE_IVEC4,{TYPE_ISAMPLER2D,TYPE_VEC4,TYPE_VOID}}, + {"textureProj",TYPE_IVEC4,{TYPE_ISAMPLER2D,TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}}, + {"textureProj",TYPE_IVEC4,{TYPE_ISAMPLER2D,TYPE_VEC4,TYPE_FLOAT,TYPE_VOID}}, + + {"textureProj",TYPE_UVEC4,{TYPE_USAMPLER2D,TYPE_VEC3,TYPE_VOID}}, + {"textureProj",TYPE_UVEC4,{TYPE_USAMPLER2D,TYPE_VEC4,TYPE_VOID}}, + {"textureProj",TYPE_UVEC4,{TYPE_USAMPLER2D,TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}}, + {"textureProj",TYPE_UVEC4,{TYPE_USAMPLER2D,TYPE_VEC4,TYPE_FLOAT,TYPE_VOID}}, + + {"textureLod",TYPE_VEC4,{TYPE_SAMPLER2D,TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}}, + {"textureLod",TYPE_IVEC4,{TYPE_ISAMPLER2D,TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}}, + {"textureLod",TYPE_UVEC4,{TYPE_USAMPLER2D,TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}}, + {"textureLod",TYPE_VEC4,{TYPE_SAMPLERCUBE,TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}}, + + {"texelFetch",TYPE_VEC4,{TYPE_SAMPLER2D,TYPE_IVEC2,TYPE_INT,TYPE_VOID}}, + {"texelFetch",TYPE_IVEC4,{TYPE_ISAMPLER2D,TYPE_IVEC2,TYPE_INT,TYPE_VOID}}, + {"texelFetch",TYPE_UVEC4,{TYPE_USAMPLER2D,TYPE_IVEC2,TYPE_INT,TYPE_VOID}}, + + {"textureProjLod",TYPE_VEC4,{TYPE_SAMPLER2D,TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}}, + {"textureProjLod",TYPE_VEC4,{TYPE_SAMPLER2D,TYPE_VEC4,TYPE_FLOAT,TYPE_VOID}}, + + {"textureProjLod",TYPE_IVEC4,{TYPE_ISAMPLER2D,TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}}, + {"textureProjLod",TYPE_IVEC4,{TYPE_ISAMPLER2D,TYPE_VEC4,TYPE_FLOAT,TYPE_VOID}}, + + {"textureProjLod",TYPE_UVEC4,{TYPE_USAMPLER2D,TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}}, + {"textureProjLod",TYPE_UVEC4,{TYPE_USAMPLER2D,TYPE_VEC4,TYPE_FLOAT,TYPE_VOID}}, + + {"textureGrad",TYPE_VEC4,{TYPE_SAMPLER2D,TYPE_VEC2,TYPE_VEC2,TYPE_VEC2,TYPE_VOID}}, + {"textureGrad",TYPE_IVEC4,{TYPE_ISAMPLER2D,TYPE_VEC2,TYPE_VEC2,TYPE_VEC2,TYPE_VOID}}, + {"textureGrad",TYPE_UVEC4,{TYPE_USAMPLER2D,TYPE_VEC2,TYPE_VEC2,TYPE_VEC2,TYPE_VOID}}, + {"textureGrad",TYPE_VEC4,{TYPE_SAMPLERCUBE,TYPE_VEC3,TYPE_VEC3,TYPE_VEC3,TYPE_VOID}}, + + {"textureScreen",TYPE_VEC4,{TYPE_VEC2,TYPE_VOID}}, + + {"dFdx",TYPE_FLOAT,{TYPE_FLOAT,TYPE_VOID}}, + {"dFdx",TYPE_VEC2,{TYPE_VEC2,TYPE_VOID}}, + {"dFdx",TYPE_VEC3,{TYPE_VEC3,TYPE_VOID}}, + {"dFdx",TYPE_VEC4,{TYPE_VEC4,TYPE_VOID}}, + + {"dFdy",TYPE_FLOAT,{TYPE_FLOAT,TYPE_VOID}}, + {"dFdy",TYPE_VEC2,{TYPE_VEC2,TYPE_VOID}}, + {"dFdy",TYPE_VEC3,{TYPE_VEC3,TYPE_VOID}}, + {"dFdy",TYPE_VEC4,{TYPE_VEC4,TYPE_VOID}}, + + {"fwidth",TYPE_FLOAT,{TYPE_FLOAT,TYPE_VOID}}, + {"fwidth",TYPE_VEC2,{TYPE_VEC2,TYPE_VOID}}, + {"fwidth",TYPE_VEC3,{TYPE_VEC3,TYPE_VOID}}, + {"fwidth",TYPE_VEC4,{TYPE_VEC4,TYPE_VOID}}, + + + {NULL,TYPE_VOID,{TYPE_VOID}} + +}; + + + +bool ShaderLanguage::_validate_function_call(BlockNode* p_block, OperatorNode *p_func,DataType *r_ret_type) { ERR_FAIL_COND_V(p_func->op!=OP_CALL && p_func->op!=OP_CONSTRUCT,NULL); @@ -1230,44 +1776,49 @@ ShaderLanguage::Node* ShaderLanguage::validate_function_call(Parser&parser, Oper ERR_FAIL_COND_V( p_func->arguments[0]->type!=Node::TYPE_VARIABLE, NULL ); - String name = static_cast<VariableNode*>(p_func->arguments[0])->name.operator String(); + StringName name = static_cast<VariableNode*>(p_func->arguments[0])->name.operator String(); bool all_const=true; for(int i=1;i<p_func->arguments.size();i++) { if (p_func->arguments[i]->type!=Node::TYPE_CONSTANT) all_const=false; - args.push_back(compute_node_type(p_func->arguments[i])); + args.push_back(p_func->arguments[i]->get_datatype()); } int argcount=args.size(); - bool found_intrinsic=false; + bool failed_builtin=false; + if (argcount<=4) { - // test intrinsics + // test builtins int idx=0; - while (intrinsic_func_defs[idx].name) { + while (builtin_func_defs[idx].name) { - if (name==intrinsic_func_defs[idx].name) { + if (name==builtin_func_defs[idx].name) { + failed_builtin=true; bool fail=false; for(int i=0;i<argcount;i++) { - if (args[i]!=intrinsic_func_defs[idx].args[i]) { + if (get_scalar_type(args[i])==args[i] && p_func->arguments[i+1]->type==Node::TYPE_CONSTANT && convert_constant(static_cast<ConstantNode*>(p_func->arguments[i+1]),builtin_func_defs[idx].args[i])) { + //all good + } else if (args[i]!=builtin_func_defs[idx].args[i]) { fail=true; break; } } - if (!fail && argcount<4 && intrinsic_func_defs[idx].args[argcount]!=TYPE_VOID) + if (!fail && argcount<4 && builtin_func_defs[idx].args[argcount]!=TYPE_VOID) fail=true; //make sure the number of arguments matches if (!fail) { - p_func->return_cache=intrinsic_func_defs[idx].rettype; - found_intrinsic=true; - break; + if (r_ret_type) + *r_ret_type=builtin_func_defs[idx].rettype; + + return true; } } @@ -1276,8 +1827,24 @@ ShaderLanguage::Node* ShaderLanguage::validate_function_call(Parser&parser, Oper } } + if (failed_builtin) { + String err ="Invalid arguments for built-in function: "+String(name)+"("; + for(int i=0;i<argcount;i++) { + if (i>0) + err+=","; + + if (p_func->arguments[i+1]->type==Node::TYPE_CONSTANT && p_func->arguments[i+1]->get_datatype()==TYPE_INT && static_cast<ConstantNode*>(p_func->arguments[i+1])->values[0].sint<0) { + err+="-"; + } + err+=get_datatype_name(args[i]); + } + err+=")"; + _set_error(err); + return false; + } - if (found_intrinsic) { +#if 0 + if (found_builtin) { if (p_func->op==OP_CONSTRUCT && all_const) { @@ -1289,6 +1856,7 @@ ShaderLanguage::Node* ShaderLanguage::validate_function_call(Parser&parser, Oper switch(v.get_type()) { case Variant::REAL: cdata.push_back(v); break; + case Variant::INT: cdata.push_back(v); break; case Variant::VECTOR2: { Vector2 v2=v; cdata.push_back(v2.x); cdata.push_back(v2.y); } break; case Variant::VECTOR3: { Vector3 v3=v; cdata.push_back(v3.x); cdata.push_back(v3.y); cdata.push_back(v3.z);} break; case Variant::PLANE: { Plane v4=v; cdata.push_back(v4.normal.x); cdata.push_back(v4.normal.y); cdata.push_back(v4.normal.z); cdata.push_back(v4.d); } break; @@ -1330,193 +1898,335 @@ ShaderLanguage::Node* ShaderLanguage::validate_function_call(Parser&parser, Oper } return p_func; } - +#endif // try existing functions.. - FunctionNode *exclude_function=NULL; //exclude current function (in case inside one) - - - Node *node = p_func; + StringName exclude_function; + BlockNode *block = p_block; - while(node->parent) { + while(block) { - if (node->type==Node::TYPE_FUNCTION) { - - exclude_function = (FunctionNode*)node; + if (block->parent_function) { + exclude_function=block->parent_function->name; } + block=block->parent_block; + } - node=node->parent; + if (name==exclude_function) { + _set_error("Recursion is not allowed"); + return false; } - ERR_FAIL_COND_V(node->type!=Node::TYPE_PROGRAM,NULL); - ProgramNode *program = (ProgramNode*)node; + for(int i=0;i<shader->functions.size();i++) { - for(int i=0;i<program->functions.size();i++) { - if (program->functions[i].function==exclude_function) + if (name != shader->functions[i].name) continue; - FunctionNode *pfunc = program->functions[i].function; + if (!shader->functions[i].callable) { + _set_error("Function '"+String(name)+" can't be called from source code."); + return false; + } + + FunctionNode *pfunc = shader->functions[i].function; + if (pfunc->arguments.size()!=args.size()) continue; bool fail=false; + for(int i=0;i<args.size();i++) { - if (args[i]!=pfunc->arguments[i].type) { + + if (get_scalar_type(args[i])==args[i] && p_func->arguments[i+1]->type==Node::TYPE_CONSTANT && convert_constant(static_cast<ConstantNode*>(p_func->arguments[i+1]),pfunc->arguments[i].type)) { + //all good + } else if (args[i]!=pfunc->arguments[i].type) { fail=true; break; } } - if (!fail && name == program->functions[i].name) { + if (!fail) { p_func->return_cache=pfunc->return_type; - return p_func; + return true; } } - return NULL; + return false; } -ShaderLanguage::Node * ShaderLanguage::validate_operator(Parser& parser,OperatorNode *p_func) { +bool ShaderLanguage::_parse_function_arguments(BlockNode* p_block,const Map<StringName,DataType> &p_builtin_types,OperatorNode* p_func,int *r_complete_arg) { - int argcount = p_func->arguments.size(); - ERR_FAIL_COND_V(argcount>2,NULL); + TkPos pos = _get_tkpos(); + Token tk = _get_token(); - DataType argtype[2]={TYPE_VOID,TYPE_VOID}; - bool all_const=true; + if (tk.type==TK_PARENTHESIS_CLOSE) { + return true; + } - for(int i=0;i<argcount;i++) { + _set_tkpos(pos); + + + while(true) { + + + if (r_complete_arg) { + pos = _get_tkpos(); + tk = _get_token(); + + if (tk.type==TK_CURSOR) { + + *r_complete_arg=p_func->arguments.size()-1; + } else { + + _set_tkpos(pos); + } + } + + Node *arg= _parse_and_reduce_expression(p_block,p_builtin_types); + + if (!arg) { + + return false; + } + + + p_func->arguments.push_back(arg); + + tk = _get_token(); + + + if (tk.type==TK_PARENTHESIS_CLOSE) { + + return true; + } else if (tk.type!=TK_COMMA) { + // something is broken + _set_error("Expected ',' or ')' after argument"); + return false; + } - argtype[i]=compute_node_type(p_func->arguments[i]); - if (p_func->arguments[i]->type!=Node::TYPE_CONSTANT) - all_const=false; } - int idx=0; - bool valid=false; - while(operator_defs[idx].op!=OP_MAX) { + return true; +} + +bool ShaderLanguage::is_token_operator(TokenType p_type) { - if (p_func->op==operator_defs[idx].op) { + return (p_type==TK_OP_EQUAL || + p_type==TK_OP_NOT_EQUAL || + p_type==TK_OP_LESS || + p_type==TK_OP_LESS_EQUAL || + p_type==TK_OP_GREATER || + p_type==TK_OP_GREATER_EQUAL || + p_type==TK_OP_AND || + p_type==TK_OP_OR || + p_type==TK_OP_NOT || + p_type==TK_OP_ADD || + p_type==TK_OP_SUB || + p_type==TK_OP_MUL || + p_type==TK_OP_DIV || + p_type==TK_OP_MOD || + p_type==TK_OP_SHIFT_LEFT || + p_type==TK_OP_SHIFT_RIGHT || + p_type==TK_OP_ASSIGN || + p_type==TK_OP_ASSIGN_ADD || + p_type==TK_OP_ASSIGN_SUB || + p_type==TK_OP_ASSIGN_MUL || + p_type==TK_OP_ASSIGN_DIV || + p_type==TK_OP_ASSIGN_MOD || + p_type==TK_OP_ASSIGN_SHIFT_LEFT || + p_type==TK_OP_ASSIGN_SHIFT_RIGHT || + p_type==TK_OP_ASSIGN_BIT_AND || + p_type==TK_OP_ASSIGN_BIT_OR || + p_type==TK_OP_ASSIGN_BIT_XOR || + p_type==TK_OP_BIT_AND || + p_type==TK_OP_BIT_OR || + p_type==TK_OP_BIT_XOR || + p_type==TK_OP_BIT_INVERT || + p_type==TK_OP_INCREMENT || + p_type==TK_OP_DECREMENT || + p_type==TK_QUESTION || + p_type==TK_COLON ); +} - if (operator_defs[idx].args[0]==argtype[0] && operator_defs[idx].args[1]==argtype[1]) { +bool ShaderLanguage::convert_constant(ConstantNode* p_constant, DataType p_to_type,ConstantNode::Value *p_value) { - p_func->return_cache=operator_defs[idx].rettype; - valid=true; - break; + if (p_constant->datatype==p_to_type) { + if (p_value) { + for(int i=0;i<p_constant->values.size();i++) { + p_value[i]=p_constant->values[i]; } } + return true; + } else if (p_constant->datatype==TYPE_INT && p_to_type==TYPE_FLOAT) { + + if (p_value) { + p_value->real=p_constant->values[0].sint; + } + return true; + } else if (p_constant->datatype==TYPE_UINT && p_to_type==TYPE_FLOAT) { + + if (p_value) { + p_value->real=p_constant->values[0].uint; + } + return true; + } else if (p_constant->datatype==TYPE_INT && p_to_type==TYPE_UINT) { + if (p_constant->values[0].sint<0) { + return false; + } + if (p_value) { + p_value->uint=p_constant->values[0].sint; + } + return true; + } else if (p_constant->datatype==TYPE_UINT && p_to_type==TYPE_INT) { + + if (p_constant->values[0].uint>0x7FFFFFFF) { + return false; + } + if (p_value) { + p_value->sint=p_constant->values[0].uint; + } + return true; + } else + return false; + +} + +bool ShaderLanguage::is_scalar_type(DataType p_type) { + + return p_type==TYPE_BOOL || p_type==TYPE_INT || p_type==TYPE_UINT || p_type==TYPE_FLOAT; +} + +bool ShaderLanguage::is_sampler_type(DataType p_type) { + + return p_type==TYPE_SAMPLER2D || p_type==TYPE_ISAMPLER2D || p_type==TYPE_USAMPLER2D || p_type==TYPE_SAMPLERCUBE; + +} + +void ShaderLanguage::get_keyword_list(List<String> *r_keywords) { + + Set<String> kws; + + int idx=0; + + while(keyword_list[idx].text) { + kws.insert(keyword_list[idx].text); idx++; } - if (!valid) - return NULL; + idx=0; -#define _RCO2(m_op,m_vop)\ -case m_op: {\ - ConstantNode *cn = parser.create_node<ConstantNode>(p_func->parent);\ - cn->datatype=p_func->return_cache; \ - Variant::evaluate(m_vop,static_cast<ConstantNode*>(p_func->arguments[0])->value,static_cast<ConstantNode*>(p_func->arguments[1])->value,cn->value,valid);\ - if (!valid)\ - return NULL;\ - return cn;\ -} break; - -#define _RCO1(m_op,m_vop)\ -case m_op: {\ - ConstantNode *cn = parser.create_node<ConstantNode>(p_func->parent);\ - cn->datatype=p_func->return_cache; \ - Variant::evaluate(m_vop,static_cast<ConstantNode*>(p_func->arguments[0])->value,Variant(),cn->value,valid);\ - if (!valid)\ - return NULL;\ - return cn;\ -} break; - - if (all_const) { - //reduce constant operator - switch(p_func->op) { - _RCO2(OP_ADD,Variant::OP_ADD); - _RCO2(OP_SUB,Variant::OP_SUBSTRACT); - _RCO2(OP_MUL,Variant::OP_MULTIPLY); - _RCO2(OP_DIV,Variant::OP_DIVIDE); - _RCO1(OP_NEG,Variant::OP_NEGATE); - _RCO1(OP_NOT,Variant::OP_NOT); - _RCO2(OP_CMP_EQ,Variant::OP_EQUAL); - _RCO2(OP_CMP_NEQ,Variant::OP_NOT_EQUAL); - _RCO2(OP_CMP_LEQ,Variant::OP_LESS_EQUAL); - _RCO2(OP_CMP_GEQ,Variant::OP_GREATER_EQUAL); - _RCO2(OP_CMP_LESS,Variant::OP_LESS); - _RCO2(OP_CMP_GREATER,Variant::OP_GREATER); - _RCO2(OP_CMP_OR,Variant::OP_OR); - _RCO2(OP_CMP_AND,Variant::OP_AND); - default: {} - } + while (builtin_func_defs[idx].name) { + + kws.insert(builtin_func_defs[idx].name); + + idx++; + } + + for(Set<String>::Element *E=kws.front();E;E=E->next()) { + r_keywords->push_back(E->get()); } +} +void ShaderLanguage::get_builtin_funcs(List<String> *r_keywords) { - return p_func; + Set<String> kws; + + int idx=0; + + while (builtin_func_defs[idx].name) { + + kws.insert(builtin_func_defs[idx].name); + + idx++; + } + + for(Set<String>::Element *E=kws.front();E;E=E->next()) { + r_keywords->push_back(E->get()); + } } -bool ShaderLanguage::is_token_operator(TokenType p_type) { - return (p_type==TK_OP_EQUAL) || - (p_type==TK_OP_NOT_EQUAL) || - (p_type==TK_OP_LESS) || - (p_type==TK_OP_LESS_EQUAL) || - (p_type==TK_OP_GREATER) || - (p_type==TK_OP_GREATER_EQUAL) || - (p_type==TK_OP_AND) || - (p_type==TK_OP_OR) || - (p_type==TK_OP_NOT) || - (p_type==TK_OP_ADD) || - (p_type==TK_OP_SUB) || - (p_type==TK_OP_MUL) || - (p_type==TK_OP_DIV) || - (p_type==TK_OP_NEG) || - (p_type==TK_OP_ASSIGN) || - (p_type==TK_OP_ASSIGN_ADD) || - (p_type==TK_OP_ASSIGN_SUB) || - (p_type==TK_OP_ASSIGN_MUL) || - (p_type==TK_OP_ASSIGN_DIV); +ShaderLanguage::DataType ShaderLanguage::get_scalar_type(DataType p_type) { + + static const DataType scalar_types[]={ + TYPE_VOID, + TYPE_BOOL, + TYPE_BOOL, + TYPE_BOOL, + TYPE_BOOL, + TYPE_INT, + TYPE_INT, + TYPE_INT, + TYPE_INT, + TYPE_UINT, + TYPE_UINT, + TYPE_UINT, + TYPE_UINT, + TYPE_FLOAT, + TYPE_FLOAT, + TYPE_FLOAT, + TYPE_FLOAT, + TYPE_FLOAT, + TYPE_FLOAT, + TYPE_FLOAT, + TYPE_FLOAT, + TYPE_INT, + TYPE_UINT, + TYPE_FLOAT, + }; + + return scalar_types[p_type]; } -ShaderLanguage::Operator ShaderLanguage::get_token_operator(TokenType p_type) { - switch(p_type) { - case TK_OP_EQUAL: return OP_CMP_EQ ; - case TK_OP_NOT_EQUAL: return OP_CMP_NEQ; - case TK_OP_LESS: return OP_CMP_LESS ; - case TK_OP_LESS_EQUAL: return OP_CMP_LEQ ; - case TK_OP_GREATER: return OP_CMP_GREATER ; - case TK_OP_GREATER_EQUAL: return OP_CMP_GEQ ; - case TK_OP_AND: return OP_CMP_AND ; - case TK_OP_OR: return OP_CMP_OR ; - case TK_OP_NOT: return OP_NOT ; - case TK_OP_ADD: return OP_ADD ; - case TK_OP_SUB: return OP_SUB ; - case TK_OP_MUL: return OP_MUL ; - case TK_OP_DIV: return OP_DIV ; - case TK_OP_NEG: return OP_NEG ; - case TK_OP_ASSIGN: return OP_ASSIGN ; - case TK_OP_ASSIGN_ADD: return OP_ASSIGN_ADD ; - case TK_OP_ASSIGN_SUB: return OP_ASSIGN_SUB ; - case TK_OP_ASSIGN_MUL: return OP_ASSIGN_MUL ; - case TK_OP_ASSIGN_DIV: return OP_ASSIGN_DIV ; - default: ERR_FAIL_V(OP_MAX); + +bool ShaderLanguage::_get_completable_identifier(BlockNode *p_block,CompletionType p_type,StringName& identifier) { + + identifier=StringName(); + + TkPos pos; + + Token tk = _get_token(); + + if (tk.type==TK_IDENTIFIER) { + identifier=tk.text; + pos = _get_tkpos(); + tk = _get_token(); + } + + if (tk.type==TK_CURSOR) { + + completion_type=p_type; + completion_line=tk_line; + completion_block=p_block; + + pos = _get_tkpos(); + tk = _get_token(); + + if (tk.type==TK_IDENTIFIER) { + identifier=identifier.operator String() + tk.text.operator String(); + } else { + _set_tkpos(pos); + } + return true; + } else if (identifier!=StringName()){ + _set_tkpos(pos); } - return OP_MAX; + return false; } -Error ShaderLanguage::parse_expression(Parser& parser,Node *p_parent,Node **r_expr) { + +ShaderLanguage::Node* ShaderLanguage::_parse_expression(BlockNode* p_block,const Map<StringName,DataType> &p_builtin_types) { Vector<Expression> expression; //Vector<TokenType> operators; @@ -1524,416 +2234,462 @@ Error ShaderLanguage::parse_expression(Parser& parser,Node *p_parent,Node **r_ex while(true) { Node *expr=NULL; + TkPos prepos = _get_tkpos(); + Token tk = _get_token(); + TkPos pos = _get_tkpos(); - if (parser.get_token_type()==TK_PARENTHESIS_OPEN) { + if (tk.type==TK_PARENTHESIS_OPEN) { //handle subexpression - parser.advance(); - Error err = parse_expression(parser,p_parent,&expr); - if (err) - return err; - if (parser.get_token_type()!=TK_PARENTHESIS_CLOSE) { + expr = _parse_and_reduce_expression(p_block,p_builtin_types); + if (!expr) + return NULL; - parser.set_error("Expected ')' in expression"); - return ERR_PARSE_ERROR; - } + tk = _get_token(); + + if (tk.type!=TK_PARENTHESIS_CLOSE) { - parser.advance(); + _set_error("Expected ')' in expression"); + return NULL; + } - } else if (parser.get_token_type()==TK_REAL_CONSTANT) { + } else if (tk.type==TK_REAL_CONSTANT) { - ConstantNode *constant = parser.create_node<ConstantNode>(p_parent); - constant->value=parser.get_token().text.operator String().to_double(); + ConstantNode *constant = alloc_node<ConstantNode>(); + ConstantNode::Value v; + v.real=tk.constant; + constant->values.push_back(v); constant->datatype=TYPE_FLOAT; expr=constant; - parser.advance(); - } else if (parser.get_token_type()==TK_TRUE) { + + } else if (tk.type==TK_INT_CONSTANT) { + + + ConstantNode *constant = alloc_node<ConstantNode>(); + ConstantNode::Value v; + v.sint=tk.constant; + constant->values.push_back(v); + constant->datatype=TYPE_INT; + expr=constant; + + } else if (tk.type==TK_TRUE) { //print_line("found true"); //handle true constant - ConstantNode *constant = parser.create_node<ConstantNode>(p_parent); - constant->value=true; + ConstantNode *constant = alloc_node<ConstantNode>(); + ConstantNode::Value v; + v.boolean=true; + constant->values.push_back(v); constant->datatype=TYPE_BOOL; expr=constant; - parser.advance(); - } else if (parser.get_token_type()==TK_FALSE) { + + } else if (tk.type==TK_FALSE) { //handle false constant - ConstantNode *constant = parser.create_node<ConstantNode>(p_parent); - constant->value=false; + ConstantNode *constant = alloc_node<ConstantNode>(); + ConstantNode::Value v; + v.boolean=false; + constant->values.push_back(v); constant->datatype=TYPE_BOOL; expr=constant; - parser.advance(); - } else if (parser.get_token_type()==TK_TYPE_VOID) { - - //make sure void is not used in expression - parser.set_error("Void value not allowed in Expression"); - return ERR_PARSE_ERROR; - } else if (parser.get_token_type(1)==TK_PARENTHESIS_OPEN && (is_token_nonvoid_datatype(parser.get_token_type()) || parser.get_token_type()==TK_INDENTIFIER)) { - - - //function or constructor - StringName name; - DataType constructor=TYPE_VOID; - if (is_token_nonvoid_datatype(parser.get_token_type())) { - - constructor=get_token_datatype(parser.get_token_type()); - switch(get_token_datatype(parser.get_token_type())) { - case TYPE_BOOL: name="bool"; break; - case TYPE_FLOAT: name="float"; break; - case TYPE_VEC2: name="vec2"; break; - case TYPE_VEC3: name="vec3"; break; - case TYPE_VEC4: name="vec4"; break; - case TYPE_MAT2: name="mat2"; break; - case TYPE_MAT3: name="mat3"; break; - case TYPE_MAT4: name="mat4"; break; - default: ERR_FAIL_V(ERR_BUG); - } - } else { - name=parser.get_token().text; - } + } else if (tk.type==TK_TYPE_VOID) { - if (!test_existing_identifier(p_parent,name)) { + //make sure void is not used in expression + _set_error("Void value not allowed in Expression"); + return NULL; + } else if (is_token_nonvoid_datatype(tk.type)) { + //basic type constructor - parser.set_error("Unknown identifier in expression: "+name); - return ERR_PARSE_ERROR; - } + OperatorNode *func = alloc_node<OperatorNode>(); + func->op=OP_CONSTRUCT; - parser.advance(2); - OperatorNode *func = parser.create_node<OperatorNode>(p_parent); + if (is_token_precision(tk.type)) { - func->op=constructor!=TYPE_VOID?OP_CONSTRUCT:OP_CALL; + func->return_precision_cache=get_token_precision(tk.type); + tk=_get_token(); + } - VariableNode *funcname = parser.create_node<VariableNode>(func); - funcname->name=name; + VariableNode *funcname = alloc_node<VariableNode>(); + funcname->name=get_datatype_name(get_token_datatype(tk.type)); func->arguments.push_back(funcname); - //parse parameters + tk=_get_token(); + if (tk.type!=TK_PARENTHESIS_OPEN) { + _set_error("Expected '(' after type name"); + return NULL; + } - if (parser.get_token_type()==TK_PARENTHESIS_CLOSE) { - parser.advance(); - } else { + int carg=-1; - while(true) { + bool ok = _parse_function_arguments(p_block,p_builtin_types,func,&carg); + if (carg>=0) { + completion_type=COMPLETION_CALL_ARGUMENTS; + completion_line=tk_line; + completion_block=p_block; + completion_function=funcname->name; + completion_argument=carg; + } - Node *arg=NULL; - Error err = parse_expression(parser,func,&arg); - if (err) - return err; - func->arguments.push_back(arg); + if (!ok) + return NULL; - if (parser.get_token_type()==TK_PARENTHESIS_CLOSE) { - parser.advance(); - break; + if (!_validate_function_call(p_block,func,&func->return_cache)) { + _set_error("No matching constructor found for: '"+String(funcname->name)+"'"); + return NULL; + } + //validate_Function_call() - } else if (parser.get_token_type()==TK_COMMA) { + expr=_reduce_expression(p_block,func); - if (parser.get_token_type(1)==TK_PARENTHESIS_CLOSE) { - parser.set_error("Expression expected"); - return ERR_PARSE_ERROR; - } + } else if (tk.type==TK_IDENTIFIER) { - parser.advance(); - } else { - // something is broken - parser.set_error("Expected ',' or ')'"); - return ERR_PARSE_ERROR; - } + _set_tkpos(prepos); - } - } + StringName identifier; - expr=validate_function_call(parser,func); - if (!expr) { + _get_completable_identifier(p_block,COMPLETION_IDENTIFIER,identifier); - parser.set_error("Invalid arguments to function/constructor: "+StringName(name)); - return ERR_PARSE_ERROR; - } + tk=_get_token(); + if (tk.type==TK_PARENTHESIS_OPEN) { + //a function + StringName name = identifier; - } else if (parser.get_token_type()==TK_INDENTIFIER) { - //probably variable + OperatorNode *func = alloc_node<OperatorNode>(); + func->op=OP_CALL; + VariableNode *funcname = alloc_node<VariableNode>(); + funcname->name=name; + func->arguments.push_back(funcname); + int carg=-1; - Node *node =p_parent; - bool existing=false; - DataType datatype; - StringName identifier=parser.get_token().text; + bool ok =_parse_function_arguments(p_block,p_builtin_types,func,&carg); - while(node) { + for(int i=0;i<shader->functions.size();i++) { + if (shader->functions[i].name==name) { + shader->functions[i].uses_function.insert(name); + } + } - if (node->type==Node::TYPE_BLOCK) { - BlockNode *block = (BlockNode*)node; - if (block->variables.has(identifier)) { - existing=true; - datatype=block->variables[identifier]; - break; - } + if (carg>=0) { + completion_type=COMPLETION_CALL_ARGUMENTS; + completion_line=tk_line; + completion_block=p_block; + completion_function=funcname->name; + completion_argument=carg; } - if (node->type==Node::TYPE_FUNCTION) { + if (!ok) + return NULL; - FunctionNode *function=(FunctionNode*)node; - for(int i=0;i<function->arguments.size();i++) { - if (function->arguments[i].name==identifier) { - existing=true; - datatype=function->arguments[i].type; - break; - } - } + if (!_validate_function_call(p_block,func,&func->return_cache)) { + _set_error("No matching function found for: '"+String(funcname->name)+"'"); + return NULL; + } - if (existing) - break; + expr=func; - } + } else { + //an identifier - if (node->type==Node::TYPE_PROGRAM) { + _set_tkpos(pos); - ProgramNode *program = (ProgramNode*)node; - if (program->builtin_variables.has(identifier)) { - datatype = program->builtin_variables[identifier]; - existing=true; - break; - } - if (program->uniforms.has(identifier)) { - datatype = program->uniforms[identifier].type; - existing=true; - break; - } + DataType data_type; + IdentifierType ident_type; + if (!_find_identifier(p_block,p_builtin_types,identifier,&data_type,&ident_type)) { + _set_error("Unknown identifier in expression: "+String(identifier)); + return NULL; } - node=node->parent; - } + if (ident_type==IDENTIFIER_FUNCTION) { + _set_error("Can't use function as identifier: "+String(identifier)); + return NULL; + } - if (!existing) { - parser.set_error("Nonexistent identifier in expression: "+identifier); - return ERR_PARSE_ERROR; + VariableNode *varname = alloc_node<VariableNode>(); + varname->name=identifier; + varname->datatype_cache=data_type; + expr=varname; } - VariableNode *varname = parser.create_node<VariableNode>(p_parent); - varname->name=identifier; - varname->datatype_cache=datatype; - parser.advance(); - expr=varname; - - } else if (parser.get_token_type()==TK_OP_SUB || parser.get_token_type()==TK_OP_NOT) { - //single prefix operators - TokenType token_type=parser.get_token_type(); - parser.advance(); - //Node *subexpr=NULL; - //Error err = parse_expression(parser,p_parent,&subexpr); - //if (err) - // return err; + } else if (tk.type==TK_OP_ADD) { + continue; //this one does nothing + } else if (tk.type==TK_OP_SUB || tk.type==TK_OP_NOT || tk.type==TK_OP_BIT_INVERT || tk.type==TK_OP_INCREMENT || tk.type==TK_OP_DECREMENT) { - //OperatorNode *op = parser.create_node<OperatorNode>(p_parent); Expression e; e.is_op=true; - switch(token_type) { - case TK_OP_SUB: e.op=TK_OP_NEG; break; - case TK_OP_NOT: e.op=TK_OP_NOT; break; - //case TK_OP_PLUS_PLUS: op->op=OP_PLUS_PLUS; break; - //case TK_OP_MINUS_MINUS: op->op=OP_MINUS_MINUS; break; - default: ERR_FAIL_V(ERR_BUG); + switch(tk.type) { + case TK_OP_SUB: e.op=OP_NEGATE; break; + case TK_OP_NOT: e.op=OP_NOT; break; + case TK_OP_BIT_INVERT: e.op=OP_BIT_INVERT; break; + case TK_OP_INCREMENT: e.op=OP_INCREMENT; break; + case TK_OP_DECREMENT: e.op=OP_DECREMENT; break; + default: ERR_FAIL_V(NULL); } expression.push_back(e); - continue; } else { - print_line("found bug?"); - print_line("misplaced token: "+String(token_names[parser.get_token_type()])); - - parser.set_error("Error parsing expression, misplaced: "+String(token_names[parser.get_token_type()])); - return ERR_PARSE_ERROR; + _set_error("Expected expression, found: "+get_token_text(tk)); + return NULL; //nothing } - ERR_FAIL_COND_V(!expr,ERR_BUG); + ERR_FAIL_COND_V(!expr,NULL); /* OK now see what's NEXT to the operator.. */ /* OK now see what's NEXT to the operator.. */ /* OK now see what's NEXT to the operator.. */ + while(true) { + TkPos pos = _get_tkpos(); + tk=_get_token(); - if (parser.get_token_type()==TK_PERIOD) { + if (tk.type==TK_PERIOD) { - if (parser.get_token_type(1)!=TK_INDENTIFIER) { - parser.set_error("Expected identifier as member"); - return ERR_PARSE_ERROR; - } - - DataType dt = compute_node_type(expr); - String ident = parser.get_token(1).text; - - bool ok=true; - DataType member_type; - switch(dt) { - case TYPE_VEC2: { - - int l = ident.length(); - if (l==1) { - member_type=TYPE_FLOAT; - } else if (l==2) { - member_type=TYPE_VEC2; - } else { - ok=false; - break; - } + StringName identifier; + if (_get_completable_identifier(p_block,COMPLETION_INDEX,identifier)) { + completion_base=expr->get_datatype(); + } - const CharType *c=ident.ptr(); - for(int i=0;i<l;i++) { + if (identifier==StringName()) { + _set_error("Expected identifier as member"); + return NULL; + } - switch(c[i]) { - case 'r': - case 'g': - case 'x': - case 'y': - break; - default: - ok=false; - break; + DataType dt = expr->get_datatype(); + String ident = identifier; + + bool ok=true; + DataType member_type; + switch(dt) { + case TYPE_BVEC2: + case TYPE_IVEC2: + case TYPE_UVEC2: + case TYPE_VEC2: { + + int l = ident.length(); + if (l==1) { + member_type=DataType(dt-1); + } else if (l==2) { + member_type=dt; + } else { + ok=false; + break; } - } - } break; - case TYPE_VEC3: { + const CharType *c=ident.ptr(); + for(int i=0;i<l;i++) { + + switch(c[i]) { + case 'r': + case 'g': + case 'x': + case 'y': + break; + default: + ok=false; + break; + } + } - int l = ident.length(); - if (l==1) { - member_type=TYPE_FLOAT; - } else if (l==2) { - member_type=TYPE_VEC2; - } else if (l==3) { - member_type=TYPE_VEC3; - } else { - ok=false; - break; - } + } break; + case TYPE_BVEC3: + case TYPE_IVEC3: + case TYPE_UVEC3: + case TYPE_VEC3: { + + int l = ident.length(); + if (l==1) { + member_type=DataType(dt-2); + } else if (l==2) { + member_type=DataType(dt-1); + } else if (l==3) { + member_type=dt; + } else { + ok=false; + break; + } - const CharType *c=ident.ptr(); - for(int i=0;i<l;i++) { + const CharType *c=ident.ptr(); + for(int i=0;i<l;i++) { + + switch(c[i]) { + case 'r': + case 'g': + case 'b': + case 'x': + case 'y': + case 'z': + break; + default: + ok=false; + break; + } + } - switch(c[i]) { - case 'r': - case 'g': - case 'b': - case 'x': - case 'y': - case 'z': - break; - default: - ok=false; - break; + } break; + case TYPE_BVEC4: + case TYPE_IVEC4: + case TYPE_UVEC4: + case TYPE_VEC4: { + + int l = ident.length(); + if (l==1) { + member_type=DataType(dt-3); + } else if (l==2) { + member_type=DataType(dt-2); + } else if (l==3) { + member_type=DataType(dt-1); + } else if (l==4) { + member_type=dt; + } else { + ok=false; + break; } - } - } break; - case TYPE_VEC4: { + const CharType *c=ident.ptr(); + for(int i=0;i<l;i++) { + + switch(c[i]) { + case 'r': + case 'g': + case 'b': + case 'a': + case 'x': + case 'y': + case 'z': + case 'w': + break; + default: + ok=false; + break; + } + } - int l = ident.length(); - if (l==1) { - member_type=TYPE_FLOAT; - } else if (l==2) { - member_type=TYPE_VEC2; - } else if (l==3) { - member_type=TYPE_VEC3; - } else if (l==4) { - member_type=TYPE_VEC4; - } else { - ok=false; - break; - } + } break; + case TYPE_MAT2: ok=(ident=="x" || ident=="y"); member_type=TYPE_VEC2; break; + case TYPE_MAT3: ok=(ident=="x" || ident=="y" || ident=="z" ); member_type=TYPE_VEC3; break; + case TYPE_MAT4: ok=(ident=="x" || ident=="y" || ident=="z" || ident=="w"); member_type=TYPE_VEC4; break; + default: {} + } - const CharType *c=ident.ptr(); - for(int i=0;i<l;i++) { - - switch(c[i]) { - case 'r': - case 'g': - case 'b': - case 'a': - case 'x': - case 'y': - case 'z': - case 'w': - break; - default: - ok=false; - break; - } - } + if (!ok) { - } break; - case TYPE_MAT2: ok=(ident=="x" || ident=="y"); member_type=TYPE_VEC2; break; - case TYPE_MAT3: ok=(ident=="x" || ident=="y" || ident=="z" ); member_type=TYPE_VEC3; break; - case TYPE_MAT4: ok=(ident=="x" || ident=="y" || ident=="z" || ident=="w"); member_type=TYPE_VEC4; break; - default: {} - } + _set_error("Invalid member for expression: ."+ident); + return NULL; + } - if (!ok) { + MemberNode *mn = alloc_node<MemberNode>(); + mn->basetype=dt; + mn->datatype=member_type; + mn->name=ident; + mn->owner=expr; + expr=mn; - parser.set_error("Invalid member for expression: ."+ident); - return ERR_PARSE_ERROR; - } - MemberNode *mn = parser.create_node<MemberNode>(p_parent); - mn->basetype=dt; - mn->datatype=member_type; - mn->name=ident; - mn->owner=expr; - expr=mn; + //todo + //member (period) has priority over any operator + //creates a subindexing expression in place - parser.advance(2); - //todo - //member (period) has priority over any operator - //creates a subindexing expression in place + /*} else if (tk.type==TK_BRACKET_OPEN) { + //todo + //subindexing has priority over any operator + //creates a subindexing expression in place - } else if (parser.get_token_type()==TK_BRACKET_OPEN) { - //todo - //subindexing has priority over any operator - //creates a subindexing expression in place + */ + } else if (tk.type==TK_OP_INCREMENT || tk.type==TK_OP_DECREMENT) { + OperatorNode *op = alloc_node<OperatorNode>(); + op->op=tk.type==TK_OP_DECREMENT ? OP_POST_DECREMENT : OP_POST_INCREMENT; + op->arguments.push_back(expr); - } /*else if (parser.get_token_type()==TK_OP_PLUS_PLUS || parser.get_token_type()==TK_OP_MINUS_MINUS) { - //todo - //inc/dec operators have priority over any operator - //creates a subindexing expression in place - //return OK; //wtfs + if (!_validate_operator(op,&op->return_cache)) { + _set_error("Invalid base type for increment/decrement operator"); + return NULL; + } + expr=op; + } else { - } */ + _set_tkpos(pos); + break; + } + } Expression e; e.is_op=false; e.node=expr; expression.push_back(e); + pos = _get_tkpos(); + tk = _get_token(); - if (is_token_operator(parser.get_token_type())) { + if (is_token_operator(tk.type)) { Expression o; o.is_op=true; - o.op=parser.get_token_type(); + + switch(tk.type) { + + case TK_OP_EQUAL: o.op = OP_EQUAL; break; + case TK_OP_NOT_EQUAL: o.op = OP_NOT_EQUAL; break; + case TK_OP_LESS: o.op = OP_LESS; break; + case TK_OP_LESS_EQUAL: o.op = OP_LESS_EQUAL; break; + case TK_OP_GREATER: o.op = OP_GREATER; break; + case TK_OP_GREATER_EQUAL: o.op = OP_GREATER_EQUAL; break; + case TK_OP_AND: o.op = OP_AND; break; + case TK_OP_OR: o.op = OP_OR; break; + case TK_OP_ADD: o.op = OP_ADD; break; + case TK_OP_SUB: o.op = OP_SUB; break; + case TK_OP_MUL: o.op = OP_MUL; break; + case TK_OP_DIV: o.op = OP_DIV; break; + case TK_OP_MOD: o.op = OP_MOD; break; + case TK_OP_SHIFT_LEFT: o.op = OP_SHIFT_LEFT; break; + case TK_OP_SHIFT_RIGHT: o.op = OP_SHIFT_RIGHT; break; + case TK_OP_ASSIGN: o.op = OP_ASSIGN; break; + case TK_OP_ASSIGN_ADD: o.op = OP_ASSIGN_ADD; break; + case TK_OP_ASSIGN_SUB: o.op = OP_ASSIGN_SUB; break; + case TK_OP_ASSIGN_MUL: o.op = OP_ASSIGN_MUL; break; + case TK_OP_ASSIGN_DIV: o.op = OP_ASSIGN_DIV; break; + case TK_OP_ASSIGN_MOD: o.op = OP_ASSIGN_MOD; break; + case TK_OP_ASSIGN_SHIFT_LEFT: o.op = OP_ASSIGN_SHIFT_LEFT; break; + case TK_OP_ASSIGN_SHIFT_RIGHT: o.op = OP_ASSIGN_SHIFT_RIGHT; break; + case TK_OP_ASSIGN_BIT_AND: o.op = OP_ASSIGN_BIT_AND; break; + case TK_OP_ASSIGN_BIT_OR: o.op = OP_ASSIGN_BIT_OR; break; + case TK_OP_ASSIGN_BIT_XOR: o.op = OP_ASSIGN_BIT_XOR; break; + case TK_OP_BIT_AND: o.op = OP_BIT_AND; break; + case TK_OP_BIT_OR: o.op = OP_BIT_OR ; break; + case TK_OP_BIT_XOR: o.op = OP_BIT_XOR; break; + case TK_QUESTION: o.op = OP_SELECT_IF; break; + case TK_COLON: o.op = OP_SELECT_ELSE; break; + default: { + _set_error("Invalid token for operator: "+get_token_text(tk)); + return NULL; + } + } + expression.push_back(o); - parser.advance(); + } else { + _set_tkpos(pos); //something else, so rollback and end break; } } @@ -1947,6 +2703,7 @@ Error ShaderLanguage::parse_expression(Parser& parser,Node *p_parent,Node **r_ex int next_op=-1; int min_priority=0xFFFFF; bool is_unary=false; + bool is_ternary=false; for(int i=0;i<expression.size();i++) { @@ -1956,45 +2713,48 @@ Error ShaderLanguage::parse_expression(Parser& parser,Node *p_parent,Node **r_ex } bool unary=false; + bool ternary=false; int priority; switch(expression[i].op) { - - case TK_OP_NOT: priority=0; unary=true; break; - case TK_OP_NEG: priority=0; unary=true; break; - - case TK_OP_MUL: priority=1; break; - case TK_OP_DIV: priority=1; break; - - case TK_OP_ADD: priority=2; break; - case TK_OP_SUB: priority=2; break; - - // shift left/right =2 - - case TK_OP_LESS: priority=4; break; - case TK_OP_LESS_EQUAL: priority=4; break; - case TK_OP_GREATER: priority=4; break; - case TK_OP_GREATER_EQUAL: priority=4; break; - - case TK_OP_EQUAL: priority=5; break; - case TK_OP_NOT_EQUAL: priority=5; break; - - //bit and =5 - //bit xor =6 - //bit or=7 - - case TK_OP_AND: priority=8; break; - case TK_OP_OR: priority=9; break; - - // ?: = 10 - - case TK_OP_ASSIGN_ADD: priority=11; break; - case TK_OP_ASSIGN_SUB: priority=11; break; - case TK_OP_ASSIGN_MUL: priority=11; break; - case TK_OP_ASSIGN_DIV: priority=11; break; - case TK_OP_ASSIGN: priority=11; break; - - default: ERR_FAIL_V(ERR_BUG); //unexpected operator + case OP_EQUAL: priority=8; break; + case OP_NOT_EQUAL: priority=8; break; + case OP_LESS: priority=7; break; + case OP_LESS_EQUAL: priority=7; break; + case OP_GREATER: priority=7; break; + case OP_GREATER_EQUAL: priority=7; break; + case OP_AND: priority=12; break; + case OP_OR: priority=14; break; + case OP_NOT: priority=3; unary=true; break; + case OP_NEGATE: priority=3; unary=true; break; + case OP_ADD: priority=5; break; + case OP_SUB: priority=5; break; + case OP_MUL: priority=4; break; + case OP_DIV: priority=4; break; + case OP_MOD: priority=4; break; + case OP_SHIFT_LEFT: priority=6; break; + case OP_SHIFT_RIGHT: priority=6; break; + case OP_ASSIGN: priority=16; break; + case OP_ASSIGN_ADD: priority=16; break; + case OP_ASSIGN_SUB: priority=16; break; + case OP_ASSIGN_MUL: priority=16; break; + case OP_ASSIGN_DIV: priority=16; break; + case OP_ASSIGN_MOD: priority=16; break; + case OP_ASSIGN_SHIFT_LEFT: priority=16; break; + case OP_ASSIGN_SHIFT_RIGHT: priority=16; break; + case OP_ASSIGN_BIT_AND: priority=16; break; + case OP_ASSIGN_BIT_OR: priority=16; break; + case OP_ASSIGN_BIT_XOR: priority=16; break; + case OP_BIT_AND: priority=9; break; + case OP_BIT_OR: priority=11; break; + case OP_BIT_XOR: priority=10; break; + case OP_BIT_INVERT: priority=3; unary=true; break; + case OP_INCREMENT: priority=3; unary=true; break; + case OP_DECREMENT: priority=3; unary=true; break; + case OP_SELECT_IF: priority=15; ternary=true; break; + case OP_SELECT_ELSE: priority=15; ternary=true; break; + + default: ERR_FAIL_V(NULL); //unexpected operator } @@ -2004,11 +2764,12 @@ Error ShaderLanguage::parse_expression(Parser& parser,Node *p_parent,Node **r_ex next_op=i; min_priority=priority; is_unary=unary; + is_ternary=ternary; } } - ERR_FAIL_COND_V(next_op==-1,ERR_BUG); + ERR_FAIL_COND_V(next_op==-1,NULL); // OK! create operator.. // OK! create operator.. @@ -2020,48 +2781,90 @@ Error ShaderLanguage::parse_expression(Parser& parser,Node *p_parent,Node **r_ex expr_pos++; if (expr_pos==expression.size()) { //can happen.. - parser.set_error("Unexpected end of expression.."); - return ERR_BUG; + _set_error("Unexpected end of expression.."); + return NULL; } } //consecutively do unary opeators for(int i=expr_pos-1;i>=next_op;i--) { - OperatorNode *op = parser.create_node<OperatorNode>(p_parent); - op->op=get_token_operator(expression[i].op); + OperatorNode *op = alloc_node<OperatorNode>(); + op->op=expression[i].op; op->arguments.push_back(expression[i+1].node); expression[i].is_op=false; - expression[i].node=validate_operator(parser,op); - if (!expression[i].node) { + expression[i].node=op; + + + if (!_validate_operator(op,&op->return_cache)) { String at; for(int i=0;i<op->arguments.size();i++) { if (i>0) at+=" and "; - at+=get_datatype_name(compute_node_type(op->arguments[i])); + at+=get_datatype_name(op->arguments[i]->get_datatype()); } - parser.set_error("Invalid argument to unary operator "+String(token_names[op->op])+": "+at); - return ERR_PARSE_ERROR; + _set_error("Invalid arguments to unary operator '"+get_operator_text(op->op)+"' :" +at); + return NULL; } expression.remove(i+1); } + + } else if (is_ternary) { + + if (next_op <1 || next_op>=(expression.size()-1)) { + _set_error("Parser bug.."); + ERR_FAIL_V(NULL); + } + + if (next_op+2 >= expression.size() || !expression[next_op+2].is_op || expression[next_op+2].op!=OP_SELECT_ELSE) { + _set_error("Mising matching ':' for select operator"); + return NULL; + } + + + + OperatorNode *op = alloc_node<OperatorNode>(); + op->op=expression[next_op].op; + op->arguments.push_back(expression[next_op-1].node); + op->arguments.push_back(expression[next_op+1].node); + op->arguments.push_back(expression[next_op+3].node); + + expression[next_op-1].is_op=false; + expression[next_op-1].node=op; + if (!_validate_operator(op,&op->return_cache)) { + + String at; + for(int i=0;i<op->arguments.size();i++) { + if (i>0) + at+=" and "; + at+=get_datatype_name(op->arguments[i]->get_datatype()); + + } + _set_error("Invalid argument to ternary ?: operator: "+at); + return NULL; + } + + for(int i=0;i<4;i++) { + expression.remove(next_op); + } + } else { if (next_op <1 || next_op>=(expression.size()-1)) { - parser.set_error("Parser bug.."); - ERR_FAIL_V(ERR_BUG); + _set_error("Parser bug.."); + ERR_FAIL_V(NULL); } - OperatorNode *op = parser.create_node<OperatorNode>(p_parent); - op->op=get_token_operator(expression[next_op].op); + OperatorNode *op = alloc_node<OperatorNode>(); + op->op=expression[next_op].op; if (expression[next_op-1].is_op) { - parser.set_error("Parser bug.."); - ERR_FAIL_V(ERR_BUG); + _set_error("Parser bug.."); + ERR_FAIL_V(NULL); } if (expression[next_op+1].is_op) { @@ -2070,645 +2873,1032 @@ Error ShaderLanguage::parse_expression(Parser& parser,Node *p_parent,Node **r_ex // can be followed by an unary op in a valid combination, // due to how precedence works, unaries will always dissapear first - parser.set_error("Parser bug.."); + _set_error("Parser bug.."); } op->arguments.push_back(expression[next_op-1].node); //expression goes as left op->arguments.push_back(expression[next_op+1].node); //next expression goes as right + expression[next_op-1].node=op; //replace all 3 nodes by this operator and make it an expression - expression[next_op-1].node=validate_operator(parser,op); - if (!expression[next_op-1].node) { + + if (!_validate_operator(op,&op->return_cache)) { String at; for(int i=0;i<op->arguments.size();i++) { if (i>0) at+=" and "; - at+=get_datatype_name(compute_node_type(op->arguments[i])); + at+=get_datatype_name(op->arguments[i]->get_datatype()); } - static const char *op_names[OP_MAX]={"=","+","-","*","/","+=","-=","*=","/=","-","!","==","!=","<=",">=","<",">","||","&&","call","()"}; - - parser.set_error("Invalid arguments to operator "+String(op_names[op->op])+": "+at); - return ERR_PARSE_ERROR; + _set_error("Invalid arguments to operator '"+get_operator_text(op->op)+"' :" +at); + return NULL; } + expression.remove(next_op); expression.remove(next_op); } -#if 0 - OperatorNode *op = parser.create_node<OperatorNode>(p_parent); - op->op=get_token_operator(operators[next_op]); + } + + return expression[0].node; +} + + +ShaderLanguage::Node* ShaderLanguage::_reduce_expression(BlockNode *p_block, ShaderLanguage::Node *p_node) { + + if (p_node->type!=Node::TYPE_OPERATOR) + return p_node; + + //for now only reduce simple constructors + OperatorNode *op=static_cast<OperatorNode*>(p_node); + + if (op->op==OP_CONSTRUCT) { + + + ERR_FAIL_COND_V(op->arguments[0]->type!=Node::TYPE_VARIABLE,p_node); + VariableNode *vn = static_cast<VariableNode*>(op->arguments[0]); + //StringName name=vn->name; + + DataType base=get_scalar_type(op->get_datatype()); - op->arguments.push_back(expressions[next_op]); //expression goes as left - op->arguments.push_back(expressions[next_op+1]); //next expression goes as right + Vector<ConstantNode::Value> values; - expressions[next_op]=validate_operator(parser,op); - if (!expressions[next_op]) { - String at; - for(int i=0;i<op->arguments.size();i++) { - if (i>0) - at+=" and "; - at+=get_datatype_name(compute_node_type(op->arguments[i])); + for(int i=1;i<op->arguments.size();i++) { + + op->arguments[i]=_reduce_expression(p_block,op->arguments[i]); + if (op->arguments[i]->type==Node::TYPE_CONSTANT) { + ConstantNode *cn = static_cast<ConstantNode*>(op->arguments[i]); + + if (get_scalar_type(cn->datatype)==base) { + + for(int j=0;j<cn->values.size();j++) { + values.push_back(cn->values[j]); + } + } else if (get_scalar_type(cn->datatype)==cn->datatype) { + + ConstantNode::Value v; + if (!convert_constant(cn,base,&v)) { + return p_node; + } + values.push_back(v); + } else { + return p_node; + } + + } else { + return p_node; } - parser.set_error("Invalid arguments to operator "+String(token_names[operators[next_op]])+": "+at); - return ERR_PARSE_ERROR; } - expressions.remove(next_op+1); - operators.remove(next_op); -#endif + ConstantNode *cn=alloc_node<ConstantNode>(); + cn->datatype=op->get_datatype(); + cn->values=values; + return cn; + } else if (op->op==OP_NEGATE) { - } + op->arguments[0]=_reduce_expression(p_block,op->arguments[0]); + if (op->arguments[0]->type==Node::TYPE_CONSTANT) { - *r_expr=expression[0].node; + ConstantNode *cn = static_cast<ConstantNode*>(op->arguments[0]); - return OK; + DataType base=get_scalar_type(cn->datatype); -/* - TokenType token_type=parser.get_token_type(); - OperatorNode *op = parser.create_node<OperatorNode>(p_parent); - op->op=get_token_operator(parser.get_token_type()); + Vector<ConstantNode::Value> values; - op->arguments.push_back(*r_expr); //expression goes as left - parser.advance(); - Node *right_expr=NULL; - Error err = parse_expression(parser,p_parent,&right_expr); - if (err) - return err; - op->arguments.push_back(right_expr); + for(int i=0;i<cn->values.size();i++) { - if (!validate_operator(op)) { + ConstantNode::Value nv; + switch(base) { + case TYPE_BOOL: { + nv.boolean=!cn->values[i].boolean; + } break; + case TYPE_INT: { + nv.sint=-cn->values[i].sint; + } break; + case TYPE_UINT: { + nv.uint=-cn->values[i].uint; + } break; + case TYPE_FLOAT: { + nv.real=-cn->values[i].real; + } break; + default: {} + } - parser.set_error("Invalid arguments to operator "+String(token_names[token_type])); - return ERR_PARSE_ERROR; + values.push_back(nv); } -*/ + + cn->values=values; + return cn; + } + } + + return p_node; + } -Error ShaderLanguage::parse_variable_declaration(Parser& parser,BlockNode *p_block) { - bool uniform = parser.get_token(-1).type==TK_UNIFORM; +ShaderLanguage::Node* ShaderLanguage::_parse_and_reduce_expression(BlockNode *p_block, const Map<StringName,DataType> &p_builtin_types) { - DataType type=get_token_datatype(parser.get_token_type(0)); - bool iscolor = parser.get_token_type(0)==TK_TYPE_COLOR; - if (type==TYPE_VOID) { + ShaderLanguage::Node* expr = _parse_expression(p_block,p_builtin_types); + if (!expr) //errored + return NULL; - parser.set_error("Cannot Declare a 'void' Variable"); - return ERR_PARSE_ERROR; - } + expr = _reduce_expression(p_block,expr); - if (type==TYPE_TEXTURE && !uniform) { + return expr; +} - parser.set_error("Cannot Declare a Non-Uniform Texture"); - return ERR_PARSE_ERROR; - } - if (type==TYPE_CUBEMAP && !uniform) { - parser.set_error("Cannot Declare a Non-Uniform Cubemap"); - return ERR_PARSE_ERROR; - } - parser.advance(); - int found=0; +Error ShaderLanguage::_parse_block(BlockNode* p_block,const Map<StringName,DataType> &p_builtin_types,bool p_just_one,bool p_can_break,bool p_can_continue) { while(true) { + TkPos pos = _get_tkpos(); - if (found && parser.get_token_type()!=TK_COMMA) { - break; - } + Token tk = _get_token(); + if (tk.type==TK_CURLY_BRACKET_CLOSE) { //end of block + if (p_just_one) { + _set_error("Unexpected '}'"); + return ERR_PARSE_ERROR; + } - if (parser.get_token_type()!=TK_INDENTIFIER) { + return OK; - parser.set_error("Identifier Expected"); - return ERR_PARSE_ERROR; + } else if (is_token_precision(tk.type) || is_token_nonvoid_datatype(tk.type)) { + DataPrecision precision=PRECISION_DEFAULT; + if (is_token_precision(tk.type)) { + precision=get_token_precision(tk.type); + tk = _get_token(); + if (!is_token_nonvoid_datatype(tk.type)) { + _set_error("Expected datatype after precission"); + return ERR_PARSE_ERROR; + } + } - } + DataType type = get_token_datatype(tk.type); - StringName name = parser.get_token().text; + tk = _get_token(); - if (test_existing_identifier(p_block,name)) { - parser.set_error("Duplicate Identifier (existing variable/function): "+name); - return ERR_PARSE_ERROR; - } + while(true) { - found=true; + if (tk.type!=TK_IDENTIFIER) { + _set_error("Expected identifier after type"); + return ERR_PARSE_ERROR; + } - parser.advance(); - //see if declaration has an initializer - if (parser.get_token_type()==TK_OP_ASSIGN) { - parser.advance(); - OperatorNode * op = parser.create_node<OperatorNode>(p_block); - VariableNode * var = parser.create_node<VariableNode>(op); - var->name=name; - var->datatype_cache=type; - var->uniform=uniform; - Node *expr; - Error err = parse_expression(parser,p_block,&expr); + StringName name = tk.text; + if (_find_identifier(p_block,p_builtin_types,name)) { + _set_error("Redefinition of '"+String(name)+"'"); + return ERR_PARSE_ERROR; + } - if (err) - return err; + BlockNode::Variable var; + var.type=type; + var.precision=precision; + var.line=tk_line; + p_block->variables[name]=var; - if (var->uniform) { + tk = _get_token(); - if (expr->type!=Node::TYPE_CONSTANT) { + if (tk.type==TK_OP_ASSIGN) { + //variable creted with assignment! must parse an expression + Node* n = _parse_and_reduce_expression(p_block,p_builtin_types); + if (!n) + return ERR_PARSE_ERROR; - parser.set_error("Uniform can only be initialized to a constant."); - return ERR_PARSE_ERROR; + OperatorNode *assign = alloc_node<OperatorNode>(); + VariableNode *vnode = alloc_node<VariableNode>(); + vnode->name=name; + vnode->datatype_cache=type; + assign->arguments.push_back(vnode); + assign->arguments.push_back(n); + assign->op=OP_ASSIGN; + p_block->statements.push_back(assign); + tk = _get_token(); } - Uniform u; - u.order=parser.program->uniforms.size(); - u.type=type; - u.default_value=static_cast<ConstantNode*>(expr)->value; - if (iscolor && u.default_value.get_type()==Variant::PLANE) { - Color c; - Plane p = u.default_value; - c=Color(p.normal.x,p.normal.y,p.normal.z,p.d); - u.default_value=c; - } - parser.program->uniforms[var->name]=u; - } else { - op->op=OP_ASSIGN; - op->arguments.push_back(var); - op->arguments.push_back(expr); - Node *n=validate_operator(parser,op); - if (!n) { - parser.set_error("Invalid initializer for variable: "+name); + if (tk.type==TK_COMMA) { + tk = _get_token(); + //another variable + } else if (tk.type==TK_SEMICOLON) { + break; + } else { + _set_error("Expected ',' or ';' after variable"); return ERR_PARSE_ERROR; } - p_block->statements.push_back(n); + } + } else if (tk.type==TK_CURLY_BRACKET_OPEN) { + //a sub block, just because.. + BlockNode* block = alloc_node<BlockNode>(); + block->parent_block=p_block; + _parse_block(block,p_builtin_types,false,p_can_break,p_can_continue); + p_block->statements.push_back(block); + } else if (tk.type==TK_CF_IF) { + //if () {} + tk = _get_token(); + if (tk.type!=TK_PARENTHESIS_OPEN) { + _set_error("Expected '(' after if"); + return ERR_PARSE_ERROR; } - } else { - //initialize it EMPTY - - OperatorNode * op = parser.create_node<OperatorNode>(p_block); - VariableNode * var = parser.create_node<VariableNode>(op); - ConstantNode * con = parser.create_node<ConstantNode>(op); - - var->name=name; - var->datatype_cache=type; - var->uniform=uniform; - con->datatype=type; - - switch(type) { - case TYPE_BOOL: con->value=false; break; - case TYPE_FLOAT: con->value=0.0; break; - case TYPE_VEC2: con->value=Vector2(); break; - case TYPE_VEC3: con->value=Vector3(); break; - case TYPE_VEC4: con->value=iscolor?Variant(Color()):Variant(Plane()); break; - case TYPE_MAT2: con->value=Matrix32(); break; - case TYPE_MAT3: con->value=Matrix3(); break; - case TYPE_MAT4: con->value=Transform(); break; - case TYPE_TEXTURE: - case TYPE_CUBEMAP: con->value=RID(); break; - default: {} + ControlFlowNode *cf = alloc_node<ControlFlowNode>(); + cf->flow_op=FLOW_OP_IF; + Node* n = _parse_and_reduce_expression(p_block,p_builtin_types); + if (!n) + return ERR_PARSE_ERROR; + + tk = _get_token(); + if (tk.type!=TK_PARENTHESIS_CLOSE) { + _set_error("Expected '(' after expression"); + return ERR_PARSE_ERROR; } - if (uniform) { - Uniform u; - u.type=type; - u.default_value=con->value; - u.order=parser.program->uniforms.size(); - parser.program->uniforms[var->name]=u; + BlockNode* block = alloc_node<BlockNode>(); + block->parent_block=p_block; + cf->expressions.push_back(n); + cf->blocks.push_back(block); + p_block->statements.push_back(cf); + + + Error err=_parse_block(block,p_builtin_types,true,p_can_break,p_can_continue); + + pos=_get_tkpos(); + tk = _get_token(); + if (tk.type==TK_CF_ELSE) { + + block = alloc_node<BlockNode>(); + block->parent_block=p_block; + cf->blocks.push_back(block); + err=_parse_block(block,p_builtin_types,true,p_can_break,p_can_continue); } else { - op->op=OP_ASSIGN; - op->arguments.push_back(var); - op->arguments.push_back(con); - p_block->statements.push_back(op); + _set_tkpos(pos); //rollback } - } + } else { - if (!uniform) - p_block->variables[name]=type; + //nothng else, so expression + _set_tkpos(pos); //rollback + Node*expr = _parse_and_reduce_expression(p_block,p_builtin_types); + if (!expr) + return ERR_PARSE_ERROR; + p_block->statements.push_back(expr); + tk = _get_token(); - } + if (tk.type!=TK_SEMICOLON) { + _set_error("Expected ';' after statement"); + return ERR_PARSE_ERROR; + } + } - if (parser.get_token_type()!=TK_SEMICOLON) { - parser.set_error("Expected ';'"); - return ERR_PARSE_ERROR; + if (p_just_one) + break; } - return OK; - } -Error ShaderLanguage::parse_flow_if(Parser& parser,Node *p_parent,Node **r_statement) { - ControlFlowNode *cf = parser.create_node<ControlFlowNode>(p_parent); +Error ShaderLanguage::_parse_shader(const Map< StringName, Map<StringName,DataType> > &p_functions, const Set<String> &p_render_modes) { - cf->flow_op=FLOW_OP_IF; - parser.advance(); + Token tk = _get_token(); - if (parser.get_token_type()!=TK_PARENTHESIS_OPEN) { - parser.set_error("Expected '(' after 'if'"); - return ERR_PARSE_ERROR; - } - parser.advance(); + int texture_uniforms = 0; + int uniforms =0; - Node *expression=NULL; - Error err = parse_expression(parser,cf,&expression); - if (err) - return err; + while(tk.type!=TK_EOF) { - if (compute_node_type(expression)!=TYPE_BOOL) { + switch(tk.type) { + case TK_RENDER_MODE: { - parser.set_error("Expression for 'if' is not boolean"); - return ERR_PARSE_ERROR; - } + while(true) { - cf->statements.push_back(expression); + StringName mode; + _get_completable_identifier(NULL,COMPLETION_RENDER_MODE,mode); - if (parser.get_token_type()!=TK_PARENTHESIS_CLOSE) { - parser.set_error("Expected ')' after expression"); - return ERR_PARSE_ERROR; - } + if (mode==StringName()) { + _set_error("Expected identifier for render mode"); + return ERR_PARSE_ERROR; + } - parser.advance(); + if (!p_render_modes.has(mode)) { + _set_error("Invalid render mode: '"+String(mode)+"'"); + return ERR_PARSE_ERROR; + } - if (parser.get_token_type()!=TK_CURLY_BRACKET_OPEN) { - parser.set_error("Expected statement block after 'if()'"); - return ERR_PARSE_ERROR; - } + if (shader->render_modes.find(mode)!=-1) { + _set_error("Duplicate render mode: '"+String(mode)+"'"); + return ERR_PARSE_ERROR; + } - Node *substatement=NULL; - err = parse_statement(parser,cf,&substatement); - if (err) - return err; + shader->render_modes.push_back(mode); - cf->statements.push_back(substatement); + tk = _get_token(); + if (tk.type==TK_COMMA) { + //all good, do nothing + } else if (tk.type==TK_SEMICOLON) { + break; //done + } else { + _set_error("Unexpected token: "+get_token_text(tk)); + return ERR_PARSE_ERROR; + } + } + } break; + case TK_UNIFORM: + case TK_VARYING: { + + bool uniform = tk.type==TK_UNIFORM; + DataPrecision precision = PRECISION_DEFAULT; + DataType type; + StringName name; + + tk = _get_token(); + if (is_token_precision(tk.type)) { + precision=get_token_precision(tk.type); + tk = _get_token(); + } - if (parser.get_token_type()==TK_CF_ELSE) { + if (!is_token_datatype(tk.type)) { + _set_error("Expected datatype. "); + return ERR_PARSE_ERROR; + } - parser.advance(); + type = get_token_datatype(tk.type); - if (parser.get_token_type()!=TK_CURLY_BRACKET_OPEN) { - parser.set_error("Expected statement block after 'else'"); - return ERR_PARSE_ERROR; - } + if (type==TYPE_VOID) { + _set_error("void datatype not allowed here"); + return ERR_PARSE_ERROR; + } + if (!uniform && type<TYPE_FLOAT && type>TYPE_VEC4) { + _set_error("Invalid type for varying, only float,vec2,vec3,vec4 allowed."); + return ERR_PARSE_ERROR; + } - substatement=NULL; - err = parse_statement(parser,cf,&substatement); - if (err) - return err; + tk = _get_token(); + if (tk.type!=TK_IDENTIFIER) { + _set_error("Expected identifier!"); + return ERR_PARSE_ERROR; + } - cf->statements.push_back(substatement); - } + name=tk.text; + if (_find_identifier(NULL,Map<StringName,DataType>(),name)) { + _set_error("Redefinition of '"+String(name)+"'"); + return ERR_PARSE_ERROR; + } + if (uniform) { - *r_statement=cf; + ShaderNode::Uniform uniform; - return OK; -} + if (is_sampler_type(type)) { + uniform.texture_order=texture_uniforms++; + uniform.order=-1; + } else { + uniform.texture_order=-1; + uniform.order=uniforms++; + } + uniform.type=type; + uniform.precission=precision; -Error ShaderLanguage::parse_flow_return(Parser& parser,Node *p_parent,Node **r_statement) { + //todo parse default value + tk = _get_token(); + if (tk.type==TK_OP_ASSIGN) { - FunctionNode *function=NULL; + Node* expr = _parse_and_reduce_expression(NULL,Map<StringName,DataType>()); + if (!expr) + return ERR_PARSE_ERROR; + if (expr->type!=Node::TYPE_CONSTANT) { + _set_error("Expected constant expression after '='"); + return ERR_PARSE_ERROR; + } - Node *parent=p_parent; + ConstantNode* cn = static_cast<ConstantNode*>(expr); - while(parent) { + uniform.default_value.resize(cn->values.size()); - if (parent->type==Node::TYPE_FUNCTION) { + if (!convert_constant(cn,uniform.type,uniform.default_value.ptr())) { + _set_error("Can't convert constant to "+get_datatype_name(uniform.type)); + return ERR_PARSE_ERROR; + } + tk = _get_token(); + } - function=(FunctionNode*)parent; - break; - } + if (tk.type==TK_COLON) { + //hint + + tk = _get_token(); + if (tk.type==TK_HINT_WHITE_TEXTURE) { + uniform.hint=ShaderNode::Uniform::HINT_WHITE; + } else if (tk.type==TK_HINT_BLACK_TEXTURE) { + uniform.hint=ShaderNode::Uniform::HINT_BLACK; + } else if (tk.type==TK_HINT_NORMAL_TEXTURE) { + uniform.hint=ShaderNode::Uniform::HINT_NORMAL; + } else if (tk.type==TK_HINT_ANISO_TEXTURE) { + uniform.hint=ShaderNode::Uniform::HINT_ANISO; + } else if (tk.type==TK_HINT_ALBEDO_TEXTURE) { + uniform.hint=ShaderNode::Uniform::HINT_ALBEDO; + } else if (tk.type==TK_HINT_BLACK_ALBEDO_TEXTURE) { + uniform.hint=ShaderNode::Uniform::HINT_BLACK_ALBEDO; + } else if (tk.type==TK_HINT_COLOR) { + if (type!=TYPE_VEC4) { + _set_error("Color hint is for vec4 only"); + return ERR_PARSE_ERROR; + } + uniform.hint=ShaderNode::Uniform::HINT_COLOR; + } else if (tk.type==TK_HINT_RANGE) { + + uniform.hint=ShaderNode::Uniform::HINT_RANGE; + if (type!=TYPE_FLOAT && type!=TYPE_INT) { + _set_error("Range hint is for float and int only"); + return ERR_PARSE_ERROR; + } + + tk = _get_token(); + if (tk.type!=TK_PARENTHESIS_OPEN) { + _set_error("Expected '(' after hint_range"); + return ERR_PARSE_ERROR; + } + + tk = _get_token(); + + float sign=1.0; + + if (tk.type==TK_OP_SUB) { + sign=-1.0; + tk = _get_token(); + } + + if (tk.type!=TK_REAL_CONSTANT && tk.type!=TK_INT_CONSTANT) { + _set_error("Expected integer constant"); + return ERR_PARSE_ERROR; + } + + uniform.hint_range[0]=tk.constant; + uniform.hint_range[0]*=sign; + + tk = _get_token(); + + if (tk.type!=TK_COMMA) { + _set_error("Expected ',' after integer constant"); + return ERR_PARSE_ERROR; + } + + tk = _get_token(); + + sign=1.0; + + if (tk.type==TK_OP_SUB) { + sign=-1.0; + tk = _get_token(); + } + + + if (tk.type!=TK_REAL_CONSTANT && tk.type!=TK_INT_CONSTANT) { + _set_error("Expected integer constant after ','"); + return ERR_PARSE_ERROR; + } + + uniform.hint_range[1]=tk.constant; + uniform.hint_range[1]*=sign; + + tk = _get_token(); + + if (tk.type==TK_COMMA) { + tk = _get_token(); + + if (tk.type!=TK_REAL_CONSTANT && tk.type!=TK_INT_CONSTANT) { + _set_error("Expected integer constant after ','"); + return ERR_PARSE_ERROR; + } + + uniform.hint_range[2]=tk.constant; + tk = _get_token(); + } else { + if (type==TYPE_INT) { + uniform.hint_range[2]=1; + } else { + uniform.hint_range[2]=0.001; + } + } + + if (tk.type!=TK_PARENTHESIS_CLOSE) { + _set_error("Expected ','"); + return ERR_PARSE_ERROR; + } + + + } else { + _set_error("Expected valid type hint after ':'."); + } - parent=parent->parent; - } + if (uniform.hint!=ShaderNode::Uniform::HINT_RANGE && uniform.hint!=ShaderNode::Uniform::HINT_NONE && uniform.hint!=ShaderNode::Uniform::HINT_COLOR && type <=TYPE_MAT4) { + _set_error("This hint is only for sampler types"); + return ERR_PARSE_ERROR; - if (!function) { + } - parser.set_error("'return' must be inside a function"); - return ERR_PARSE_ERROR; - } + tk = _get_token(); + } - ControlFlowNode *cf = parser.create_node<ControlFlowNode>(p_parent); + shader->uniforms[name]=uniform; - cf->flow_op=FLOW_OP_RETURN; + if (tk.type!=TK_SEMICOLON) { + _set_error("Expected ';'"); + return ERR_PARSE_ERROR; + } + } else { - parser.advance(); + ShaderNode::Varying varying; + varying.type=type; + varying.precission=precision; + shader->varyings[name]=varying; - if (function->return_type!=TYPE_VOID) { - // should expect a return expression. + tk = _get_token(); + if (tk.type!=TK_SEMICOLON) { + _set_error("Expected ';'"); + return ERR_PARSE_ERROR; + } - Node *expr=NULL; - Error err = parse_expression(parser,cf,&expr); - if (err) - return err; + } - if (compute_node_type(expr)!=function->return_type) { - parser.set_error("Invalid type for 'return' expression"); - return ERR_PARSE_ERROR; - } - cf->statements.push_back(expr); - } - *r_statement=cf; + } break; + default: { + //function - if (parser.get_token_type()!=TK_SEMICOLON) { - parser.set_error("Expected ';'"); - return ERR_PARSE_ERROR; - } + DataPrecision precision = PRECISION_DEFAULT; + DataType type; + StringName name; - return OK; -} + if (is_token_precision(tk.type)) { + precision=get_token_precision(tk.type); + tk = _get_token(); + } -Error ShaderLanguage::parse_statement(Parser& parser,Node *p_parent,Node **r_statement) { + if (!is_token_datatype(tk.type)) { + _set_error("Expected funtion, uniform or varying "); + return ERR_PARSE_ERROR; + } - *r_statement=NULL; + type = get_token_datatype(tk.type); - TokenType token_type = parser.get_token_type(); + _get_completable_identifier(NULL,COMPLETION_MAIN_FUNCTION,name); - if (token_type==TK_CURLY_BRACKET_OPEN) { - //sub-block - parser.advance(); - BlockNode *block = parser.create_node<BlockNode>(p_parent); + if (name==StringName()) { + _set_error("Expected function name after datatype"); + return ERR_PARSE_ERROR; - *r_statement=block; - return parse_block(parser,block); - } else if (token_type==TK_SEMICOLON) { - // empty ; - parser.advance(); - return OK; - } else if (token_type==TK_CF_IF) { - return parse_flow_if(parser,p_parent,r_statement); + } - } else if (token_type==TK_CF_RETURN) { - return parse_flow_return(parser,p_parent,r_statement); - } else { - Error err=parse_expression(parser,p_parent,r_statement); - if (err) - return err; + if (_find_identifier(NULL,Map<StringName,DataType>(),name)) { + _set_error("Redefinition of '"+String(name)+"'"); + return ERR_PARSE_ERROR; + } - if (parser.get_token_type()!=TK_SEMICOLON) { - parser.set_error("Expected ';'"); - return ERR_PARSE_ERROR; - } + tk = _get_token(); + if (tk.type!=TK_PARENTHESIS_OPEN) { + _set_error("Expected '(' after identifier"); + return ERR_PARSE_ERROR; - } + } - return OK; -} -Error ShaderLanguage::parse_block(Parser& parser,BlockNode *p_block) { + Map<StringName,DataType> builtin_types; + if (p_functions.has(name)) { + builtin_types=p_functions[name]; + } - while(true) { + ShaderNode::Function function; - if (parser.is_at_end()) { - if (p_block->parent->type!=Node::TYPE_PROGRAM) { - parser.set_error("Unexpected End of File"); - return ERR_PARSE_ERROR; - } - return OK; //bye - } + function.callable=!p_functions.has(name); + function.name=name; - TokenType token_type = parser.get_token_type(); + FunctionNode* func_node=alloc_node<FunctionNode>(); - if (token_type==TK_CURLY_BRACKET_CLOSE) { - if (p_block->parent->type==Node::TYPE_PROGRAM) { - parser.set_error("Unexpected '}'"); - return ERR_PARSE_ERROR; - } - parser.advance(); - return OK; // exit block + function.function=func_node; - } else if (token_type==TK_UNIFORM) { + shader->functions.push_back(function); - if (p_block!=parser.program->body) { + func_node->name=name; + func_node->return_type=type; + func_node->return_precision=precision; - parser.set_error("Uniform only allowed in main program body."); - return ERR_PARSE_ERROR; - } - parser.advance(); - Error err=parse_variable_declaration(parser,p_block); - if (err) - return err; + func_node->body = alloc_node<BlockNode>(); + func_node->body->parent_function=func_node; - } else if (is_token_datatype(token_type)) { - Error err=OK; - if (parser_is_at_function(parser)) - err = parse_function(parser,p_block); - else { - err = parse_variable_declaration(parser,p_block); - } + tk = _get_token(); - if (err) - return err; + while(true) { + if (tk.type==TK_PARENTHESIS_CLOSE) { + break; + } - } else { - // must be a statement - Node *statement=NULL; + DataType ptype; + StringName pname; + DataPrecision pprecision = PRECISION_DEFAULT; - Error err = parse_statement(parser,p_block,&statement); - if (err) - return err; - if (statement) { - p_block->statements.push_back(statement); - } + if (is_token_precision(tk.type)) { + pprecision=get_token_precision(tk.type); + tk = _get_token(); + } + + if (!is_token_datatype(tk.type)) { + _set_error("Expected a valid datatype for argument"); + return ERR_PARSE_ERROR; + } + + ptype=get_token_datatype(tk.type); + + if (ptype==TYPE_VOID) { + _set_error("void not allowed in argument"); + return ERR_PARSE_ERROR; + } + + tk = _get_token(); + + if (tk.type!=TK_IDENTIFIER) { + _set_error("Expected identifier for argument name"); + return ERR_PARSE_ERROR; + } + + pname = tk.text; + + if (_find_identifier(func_node->body,builtin_types,pname)) { + _set_error("Redefinition of '"+String(pname)+"'"); + return ERR_PARSE_ERROR; + } + FunctionNode::Argument arg; + arg.type=ptype; + arg.name=pname; + arg.precision=pprecision; + + func_node->arguments.push_back(arg); + + tk = _get_token(); + + + if (tk.type==TK_COMMA) { + tk = _get_token(); + //do none and go on + } else if (tk.type!=TK_PARENTHESIS_CLOSE) { + _set_error("Expected ',' or ')' after identifier"); + return ERR_PARSE_ERROR; + } + + } + + if (p_functions.has(name)) { + //if one of the core functions, make sure they are of the correct form + if (func_node->arguments.size() > 0) { + _set_error("Function '"+String(name)+"' expects no arguments."); + return ERR_PARSE_ERROR; + } + if (func_node->return_type!=TYPE_VOID) { + _set_error("Function '"+String(name)+"' must be of void return type."); + return ERR_PARSE_ERROR; + } + } + + + //all good let's parse inside the fucntion! + tk = _get_token(); + if (tk.type!=TK_CURLY_BRACKET_OPEN) { + _set_error("Expected '{' to begin function"); + return ERR_PARSE_ERROR; + } + + current_function = name; + + Error err = _parse_block(func_node->body,builtin_types); + if (err) + return err; + current_function=StringName(); + } } + + tk = _get_token(); } return OK; } +Error ShaderLanguage::compile(const String& p_code, const Map< StringName, Map<StringName,DataType> > &p_functions, const Set<String> &p_render_modes) { + clear(); -Error ShaderLanguage::parse(const Vector<Token>& p_tokens,ShaderType p_type,CompileFunc p_compile_func,void *p_userdata,String *r_error,int *r_err_line,int *r_err_column) { + code=p_code; + nodes=NULL; - Parser parser(p_tokens); - parser.program = parser.create_node<ProgramNode>(NULL); - parser.program->body = parser.create_node<BlockNode>(parser.program); + shader = alloc_node<ShaderNode>(); + Error err = _parse_shader(p_functions,p_render_modes); + if (err!=OK) { + return err; + } + return OK; +} - //add builtins - switch(p_type) { - case SHADER_MATERIAL_VERTEX: { - int idx=0; - while (vertex_builtins_defs[idx].name) { - parser.program->builtin_variables[vertex_builtins_defs[idx].name]=vertex_builtins_defs[idx].type; - idx++; - } +Error ShaderLanguage::complete(const String& p_code,const Map< StringName, Map<StringName,DataType> > &p_functions,const Set<String>& p_render_modes,List<String>* r_options,String& r_call_hint) { + + clear(); + + code=p_code; + + nodes=NULL; + + shader = alloc_node<ShaderNode>(); + Error err = _parse_shader(p_functions,p_render_modes); + + switch(completion_type) { + + case COMPLETION_NONE: { + //do none + return ERR_PARSE_ERROR; } break; - case SHADER_MATERIAL_FRAGMENT: { - int idx=0; - while (fragment_builtins_defs[idx].name) { - parser.program->builtin_variables[fragment_builtins_defs[idx].name]=fragment_builtins_defs[idx].type; - idx++; + case COMPLETION_RENDER_MODE: { + for(const Set<String>::Element *E=p_render_modes.front();E;E=E->next()) { + + r_options->push_back(E->get()); } + + return OK; } break; - case SHADER_MATERIAL_LIGHT: { - int idx=0; - while (light_builtins_defs[idx].name) { - parser.program->builtin_variables[light_builtins_defs[idx].name]=light_builtins_defs[idx].type; - idx++; + case COMPLETION_MAIN_FUNCTION: { + + for(const Map< StringName, Map<StringName,DataType> >::Element *E=p_functions.front();E;E=E->next()) { + + r_options->push_back(E->key()); } + + return OK; } break; - case SHADER_CANVAS_ITEM_VERTEX: { - int idx=0; - while (ci_vertex_builtins_defs[idx].name) { - parser.program->builtin_variables[ci_vertex_builtins_defs[idx].name]=ci_vertex_builtins_defs[idx].type; - idx++; + case COMPLETION_IDENTIFIER: + case COMPLETION_FUNCTION_CALL: { + + bool comp_ident=completion_type==COMPLETION_IDENTIFIER; + Set<String> matches; + + StringName skip_function; + + BlockNode *block=completion_block; + + + while(block) { + + if (comp_ident) { + for (const Map<StringName,BlockNode::Variable>::Element *E=block->variables.front();E;E=E->next()) { + + if (E->get().line<completion_line) { + matches.insert(E->key()); + } + } + } + + + if (block->parent_function) { + if (comp_ident) { + for(int i=0;i<block->parent_function->arguments.size();i++) { + matches.insert(block->parent_function->arguments[i].name); + } + } + skip_function=block->parent_function->name; + } + block=block->parent_block; } - } break; - case SHADER_CANVAS_ITEM_FRAGMENT: { - int idx=0; - while (ci_fragment_builtins_defs[idx].name) { - parser.program->builtin_variables[ci_fragment_builtins_defs[idx].name]=ci_fragment_builtins_defs[idx].type; - idx++; + + if (comp_ident && skip_function!=StringName() && p_functions.has(skip_function)) { + + for (Map<StringName,DataType>::Element *E=p_functions[skip_function].front();E;E=E->next()) { + matches.insert(E->key()); + } } - } break; - case SHADER_CANVAS_ITEM_LIGHT: { - int idx=0; - while (ci_light_builtins_defs[idx].name) { - parser.program->builtin_variables[ci_light_builtins_defs[idx].name]=ci_light_builtins_defs[idx].type; - idx++; + + if (comp_ident) { + for (const Map<StringName,ShaderNode::Varying>::Element *E=shader->varyings.front();E;E=E->next()) { + matches.insert(E->key()); + + } + for (const Map<StringName,ShaderNode::Uniform>::Element *E=shader->uniforms.front();E;E=E->next()) { + matches.insert(E->key()); + } + + } - } break; - case SHADER_POST_PROCESS: { + + for(int i=0;i<shader->functions.size();i++) { + if (!shader->functions[i].callable || shader->functions[i].name==skip_function) + continue; + matches.insert(String(shader->functions[i].name)+"("); + } + int idx=0; - while (postprocess_fragment_builtins_defs[idx].name) { - parser.program->builtin_variables[postprocess_fragment_builtins_defs[idx].name]=postprocess_fragment_builtins_defs[idx].type; + + while (builtin_func_defs[idx].name) { + + matches.insert(String(builtin_func_defs[idx].name)+"("); idx++; } + + for(Set<String>::Element *E=matches.front();E;E=E->next()) { + r_options->push_back(E->get()); + } + + return OK; + } break; - } + case COMPLETION_CALL_ARGUMENTS: { - Error err = parse_block(parser,parser.program->body); - if (err) { - parser.get_error(r_error,r_err_line,r_err_column); - return err; - } + for(int i=0;i<shader->functions.size();i++) { + if (!shader->functions[i].callable) + continue; + if (shader->functions[i].name==completion_function) { - if (p_compile_func) { - err = p_compile_func(p_userdata,parser.program); - } + String calltip; - //clean up nodes created - while(parser.nodegc.size()) { + calltip+=get_datatype_name( shader->functions[i].function->return_type ); + calltip+=" "; + calltip+=shader->functions[i].name; + calltip+="("; - memdelete( parser.nodegc.front()->get() ); - parser.nodegc.pop_front(); - } - return err; -} + for(int j=0;j<shader->functions[i].function->arguments.size();j++) { -Error ShaderLanguage::compile(const String& p_code,ShaderType p_type,CompileFunc p_compile_func,void *p_userdata,String *r_error,int *r_err_line,int *r_err_column) { + if (j>0) + calltip+=", "; + else + calltip+=" "; - *r_error=""; - *r_err_line=0; - *r_err_column=0; - Vector<Token> tokens; + if (j==completion_argument) { + calltip+=CharType(0xFFFF); + } - Error err = tokenize(p_code,&tokens,r_error,r_err_line,r_err_column); - if (err!=OK) { - print_line("tokenizer error!"); - } + calltip+=get_datatype_name(shader->functions[i].function->arguments[j].type); + calltip+=" "; + calltip+=shader->functions[i].function->arguments[j].name; - if (err!=OK) { - return err; - } - err = parse(tokens,p_type,p_compile_func,p_userdata,r_error,r_err_line,r_err_column); - if (err!=OK) { - return err; - } - return OK; -} + if (j==completion_argument) { + calltip+=CharType(0xFFFF); + } + } -void ShaderLanguage::get_keyword_list(ShaderType p_type, List<String> *p_keywords) { + if (shader->functions[i].function->arguments.size()) + calltip+=" "; + calltip+=")"; - int idx=0; + r_call_hint=calltip; + return OK; + } - p_keywords->push_back("uniform"); - p_keywords->push_back("texture"); - p_keywords->push_back("cubemap"); - p_keywords->push_back("color"); - p_keywords->push_back("if"); - p_keywords->push_back("else"); + } - while(intrinsic_func_defs[idx].name) { + int idx=0; - p_keywords->push_back(intrinsic_func_defs[idx].name); - idx++; - } + String calltip; + while (builtin_func_defs[idx].name) { - switch(p_type) { - case SHADER_MATERIAL_VERTEX: { - idx=0; - while (vertex_builtins_defs[idx].name) { - p_keywords->push_back(vertex_builtins_defs[idx].name); - idx++; - } - } break; - case SHADER_MATERIAL_FRAGMENT: { - idx=0; - while (fragment_builtins_defs[idx].name) { - p_keywords->push_back(fragment_builtins_defs[idx].name); - idx++; - } - } break; - case SHADER_MATERIAL_LIGHT: { - idx=0; - while (light_builtins_defs[idx].name) { - p_keywords->push_back(light_builtins_defs[idx].name); - idx++; - } - } break; - case SHADER_CANVAS_ITEM_VERTEX: { - idx=0; - while (ci_vertex_builtins_defs[idx].name) { - p_keywords->push_back(ci_vertex_builtins_defs[idx].name); - idx++; - } - } break; - case SHADER_CANVAS_ITEM_FRAGMENT: { - idx=0; - while (ci_fragment_builtins_defs[idx].name) { - p_keywords->push_back(ci_fragment_builtins_defs[idx].name); + if (completion_function==builtin_func_defs[idx].name) { + + if (calltip.length()) + calltip+="\n"; + + calltip+=get_datatype_name( builtin_func_defs[idx].rettype ); + calltip+=" "; + calltip+=builtin_func_defs[idx].name; + calltip+="("; + + bool found_arg=false; + for(int i=0;i<4;i++) { + + if (builtin_func_defs[idx].args[i]==TYPE_VOID) + break; + + if (i>0) + calltip+=", "; + else + calltip+=" "; + + if (i==completion_argument) { + calltip+=CharType(0xFFFF); + } + + calltip+=get_datatype_name(builtin_func_defs[idx].args[i]); + + if (i==completion_argument) { + calltip+=CharType(0xFFFF); + } + + found_arg=true; + + } + + if (found_arg) + calltip+=" "; + calltip+=")"; + + + } idx++; } + + r_call_hint=calltip; + + return OK; + } break; - case SHADER_CANVAS_ITEM_LIGHT: { - idx=0; - while (ci_light_builtins_defs[idx].name) { - p_keywords->push_back(ci_light_builtins_defs[idx].name); - idx++; + case COMPLETION_INDEX: { + + const char colv[4]={'r','g','b','a'}; + const char coordv[4]={'x','y','z','w'}; + + + int limit=0; + + switch(completion_base) { + case TYPE_BVEC2: + case TYPE_IVEC2: + case TYPE_UVEC2: + case TYPE_VEC2: { + limit=2; + + } break; + case TYPE_BVEC3: + case TYPE_IVEC3: + case TYPE_UVEC3: + case TYPE_VEC3: { + + limit=3; + + } break; + case TYPE_BVEC4: + case TYPE_IVEC4: + case TYPE_UVEC4: + case TYPE_VEC4: { + + limit=4; + + } break; + case TYPE_MAT2: limit=2; break; + case TYPE_MAT3: limit=3; break; + case TYPE_MAT4: limit=4; break; + default: {} } - } break; - case SHADER_POST_PROCESS: { - idx=0; - while (postprocess_fragment_builtins_defs[idx].name) { - p_keywords->push_back(postprocess_fragment_builtins_defs[idx].name); - idx++; + for(int i=0;i<limit;i++) { + r_options->push_back(String::chr(colv[i])); + r_options->push_back(String::chr(coordv[i])); } + } break; + } + return ERR_PARSE_ERROR; +} + +String ShaderLanguage::get_error_text() { + + return error_str; +} + +int ShaderLanguage::get_error_line() { + + return error_line; } + +ShaderLanguage::ShaderNode *ShaderLanguage::get_shader() { + + return shader; +} + +ShaderLanguage::ShaderLanguage() { + + nodes=NULL; +} + +ShaderLanguage::~ShaderLanguage() { + + clear(); +} + + diff --git a/servers/visual/shader_language.h b/servers/visual/shader_language.h index 31e9fcda5b..4f8717088e 100644 --- a/servers/visual/shader_language.h +++ b/servers/visual/shader_language.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -46,12 +46,24 @@ public: enum TokenType { TK_EMPTY, - TK_INDENTIFIER, + TK_IDENTIFIER, TK_TRUE, TK_FALSE, TK_REAL_CONSTANT, + TK_INT_CONSTANT, TK_TYPE_VOID, TK_TYPE_BOOL, + TK_TYPE_BVEC2, + TK_TYPE_BVEC3, + TK_TYPE_BVEC4, + TK_TYPE_INT, + TK_TYPE_IVEC2, + TK_TYPE_IVEC3, + TK_TYPE_IVEC4, + TK_TYPE_UINT, + TK_TYPE_UVEC2, + TK_TYPE_UVEC3, + TK_TYPE_UVEC4, TK_TYPE_FLOAT, TK_TYPE_VEC2, TK_TYPE_VEC3, @@ -59,9 +71,13 @@ public: TK_TYPE_MAT2, TK_TYPE_MAT3, TK_TYPE_MAT4, - TK_TYPE_TEXTURE, - TK_TYPE_CUBEMAP, - TK_TYPE_COLOR, + TK_TYPE_SAMPLER2D, + TK_TYPE_ISAMPLER2D, + TK_TYPE_USAMPLER2D, + TK_TYPE_SAMPLERCUBE, + TK_PRECISION_LOW, + TK_PRECISION_MID, + TK_PRECISION_HIGH, TK_OP_EQUAL, TK_OP_NOT_EQUAL, TK_OP_LESS, @@ -75,14 +91,35 @@ public: TK_OP_SUB, TK_OP_MUL, TK_OP_DIV, - TK_OP_NEG, + TK_OP_MOD, + TK_OP_SHIFT_LEFT, + TK_OP_SHIFT_RIGHT, TK_OP_ASSIGN, TK_OP_ASSIGN_ADD, TK_OP_ASSIGN_SUB, TK_OP_ASSIGN_MUL, TK_OP_ASSIGN_DIV, + TK_OP_ASSIGN_MOD, + TK_OP_ASSIGN_SHIFT_LEFT, + TK_OP_ASSIGN_SHIFT_RIGHT, + TK_OP_ASSIGN_BIT_AND, + TK_OP_ASSIGN_BIT_OR, + TK_OP_ASSIGN_BIT_XOR, + TK_OP_BIT_AND, + TK_OP_BIT_OR, + TK_OP_BIT_XOR, + TK_OP_BIT_INVERT, + TK_OP_INCREMENT, + TK_OP_DECREMENT, TK_CF_IF, TK_CF_ELSE, + TK_CF_FOR, + TK_CF_WHILE, + TK_CF_DO, + TK_CF_SWITCH, + TK_CF_CASE, + TK_CF_BREAK, + TK_CF_CONTINUE, TK_CF_RETURN, TK_BRACKET_OPEN, TK_BRACKET_CLOSE, @@ -90,31 +127,49 @@ public: TK_CURLY_BRACKET_CLOSE, TK_PARENTHESIS_OPEN, TK_PARENTHESIS_CLOSE, + TK_QUESTION, TK_COMMA, + TK_COLON, TK_SEMICOLON, TK_PERIOD, TK_UNIFORM, + TK_VARYING, + TK_RENDER_MODE, + TK_HINT_WHITE_TEXTURE, + TK_HINT_BLACK_TEXTURE, + TK_HINT_NORMAL_TEXTURE, + TK_HINT_ANISO_TEXTURE, + TK_HINT_ALBEDO_TEXTURE, + TK_HINT_BLACK_ALBEDO_TEXTURE, + TK_HINT_COLOR, + TK_HINT_RANGE, + TK_CURSOR, TK_ERROR, + TK_EOF, TK_MAX }; - - /* COMPILER */ - enum ShaderType { - SHADER_MATERIAL_VERTEX, - SHADER_MATERIAL_FRAGMENT, - SHADER_MATERIAL_LIGHT, - SHADER_CANVAS_ITEM_VERTEX, - SHADER_CANVAS_ITEM_FRAGMENT, - SHADER_CANVAS_ITEM_LIGHT, - SHADER_POST_PROCESS, - }; + // lame work around to Apple defining this as a macro in 10.12 SDK + #ifdef TYPE_BOOL + #undef TYPE_BOOL + #endif enum DataType { TYPE_VOID, TYPE_BOOL, + TYPE_BVEC2, + TYPE_BVEC3, + TYPE_BVEC4, + TYPE_INT, + TYPE_IVEC2, + TYPE_IVEC3, + TYPE_IVEC4, + TYPE_UINT, + TYPE_UVEC2, + TYPE_UVEC3, + TYPE_UVEC4, TYPE_FLOAT, TYPE_VEC2, TYPE_VEC3, @@ -122,30 +177,58 @@ public: TYPE_MAT2, TYPE_MAT3, TYPE_MAT4, - TYPE_TEXTURE, - TYPE_CUBEMAP, + TYPE_SAMPLER2D, + TYPE_ISAMPLER2D, + TYPE_USAMPLER2D, + TYPE_SAMPLERCUBE, + }; + + enum DataPrecision { + PRECISION_LOWP, + PRECISION_MEDIUMP, + PRECISION_HIGHP, + PRECISION_DEFAULT, }; enum Operator { - OP_ASSIGN, + OP_EQUAL, + OP_NOT_EQUAL, + OP_LESS, + OP_LESS_EQUAL, + OP_GREATER, + OP_GREATER_EQUAL, + OP_AND, + OP_OR, + OP_NOT, + OP_NEGATE, OP_ADD, OP_SUB, OP_MUL, OP_DIV, + OP_MOD, + OP_SHIFT_LEFT, + OP_SHIFT_RIGHT, + OP_ASSIGN, OP_ASSIGN_ADD, OP_ASSIGN_SUB, OP_ASSIGN_MUL, OP_ASSIGN_DIV, - OP_NEG, - OP_NOT, - OP_CMP_EQ, - OP_CMP_NEQ, - OP_CMP_LEQ, - OP_CMP_GEQ, - OP_CMP_LESS, - OP_CMP_GREATER, - OP_CMP_OR, - OP_CMP_AND, + OP_ASSIGN_MOD, + OP_ASSIGN_SHIFT_LEFT, + OP_ASSIGN_SHIFT_RIGHT, + OP_ASSIGN_BIT_AND, + OP_ASSIGN_BIT_OR, + OP_ASSIGN_BIT_XOR, + OP_BIT_AND, + OP_BIT_OR, + OP_BIT_XOR, + OP_BIT_INVERT, + OP_INCREMENT, + OP_DECREMENT, + OP_SELECT_IF, + OP_SELECT_ELSE, //used only internally, then only IF appears with 3 arguments + OP_POST_INCREMENT, + OP_POST_DECREMENT, OP_CALL, OP_CONSTRUCT, OP_MAX @@ -154,18 +237,21 @@ public: enum FlowOperation { FLOW_OP_IF, FLOW_OP_RETURN, - //FLOW_OP_FOR, - //FLOW_OP_WHILE, - //FLOW_OP_DO, - //FLOW_OP_BREAK, - //FLOW_OP_CONTINUE, + FLOW_OP_FOR, + FLOW_OP_WHILE, + FLOW_OP_DO, + FLOW_OP_BREAK, + FLOW_OP_SWITCH, + FLOW_OP_CONTINUE }; struct Node { + Node *next; + enum Type { - TYPE_PROGRAM, + TYPE_SHADER, TYPE_FUNCTION, TYPE_BLOCK, TYPE_VARIABLE, @@ -175,7 +261,6 @@ public: TYPE_MEMBER }; - Node * parent; Type type; virtual DataType get_datatype() const { return TYPE_VOID; } @@ -183,46 +268,75 @@ public: virtual ~Node() {} }; + template<class T> + T* alloc_node() { + T* node = memnew(T); + node->next=nodes; + nodes=node; + return node; + } + + Node *nodes; + struct OperatorNode : public Node { DataType return_cache; + DataPrecision return_precision_cache; Operator op; Vector<Node*> arguments; virtual DataType get_datatype() const { return return_cache; } - OperatorNode() { type=TYPE_OPERATOR; return_cache=TYPE_VOID; } + OperatorNode() { type=TYPE_OPERATOR; return_cache=TYPE_VOID; return_precision_cache=PRECISION_DEFAULT; } }; struct VariableNode : public Node { - bool uniform; DataType datatype_cache; StringName name; virtual DataType get_datatype() const { return datatype_cache; } - VariableNode() { type=TYPE_VARIABLE; datatype_cache=TYPE_VOID; uniform=false; } + VariableNode() { type=TYPE_VARIABLE; datatype_cache=TYPE_VOID; } }; struct ConstantNode : public Node { DataType datatype; - Variant value; + + union Value { + bool boolean; + float real; + int32_t sint; + uint32_t uint; + }; + + Vector<Value> values; virtual DataType get_datatype() const { return datatype; } ConstantNode() { type=TYPE_CONSTANT; } }; + struct FunctionNode; + struct BlockNode : public Node { + FunctionNode *parent_function; + BlockNode *parent_block; + + struct Variable { + DataType type; + DataPrecision precision; + int line; //for completion + }; - Map<StringName,DataType> variables; + Map<StringName,Variable> variables; List<Node*> statements; - BlockNode() { type=TYPE_BLOCK; } + BlockNode() { type=TYPE_BLOCK; parent_block=NULL; parent_function=NULL; } }; struct ControlFlowNode : public Node { FlowOperation flow_op; - Vector<Node*> statements; + Vector<Node*> expressions; + Vector<BlockNode*> blocks; ControlFlowNode() { type=TYPE_CONTROL_FLOW; flow_op=FLOW_OP_IF;} }; @@ -244,39 +358,67 @@ public: StringName name; DataType type; + DataPrecision precision; }; StringName name; DataType return_type; + DataPrecision return_precision; Vector<Argument> arguments; BlockNode *body; - FunctionNode() { type=TYPE_FUNCTION; } + FunctionNode() { type=TYPE_FUNCTION; return_precision=PRECISION_DEFAULT; } }; - struct Uniform { - int order; - DataType type; - Variant default_value; - }; - - struct ProgramNode : public Node { + struct ShaderNode : public Node { struct Function { StringName name; FunctionNode*function; + Set<StringName> uses_function; + bool callable; + }; + + struct Varying { + DataType type; + DataPrecision precission; + }; + + struct Uniform { + enum Hint { + HINT_NONE, + HINT_COLOR, + HINT_RANGE, + HINT_ALBEDO, + HINT_BLACK_ALBEDO, + HINT_NORMAL, + HINT_BLACK, + HINT_WHITE, + HINT_ANISO, + HINT_MAX + }; + + int order; + int texture_order; + DataType type; + DataPrecision precission; + Vector<ConstantNode::Value> default_value; + Hint hint; + float hint_range[3]; + + Uniform() { hint=HINT_NONE; hint_range[0]=0; hint_range[1]=1; hint_range[2]=0.001;} }; - Map<StringName,DataType> builtin_variables; + Map<StringName,Varying> varyings; Map<StringName,Uniform> uniforms; + Vector<StringName> render_modes; Vector<Function> functions; - BlockNode *body; - ProgramNode() { type=TYPE_PROGRAM; } + ShaderNode() { type=TYPE_SHADER; } }; @@ -284,12 +426,12 @@ public: bool is_op; union { - TokenType op; + Operator op; Node *node; }; }; - typedef Error (*CompileFunc)(void*,ProgramNode*); + struct VarInfo { @@ -297,133 +439,163 @@ public: DataType type; }; -private: - - - - static const char * token_names[TK_MAX]; + enum CompletionType { + COMPLETION_NONE, + COMPLETION_RENDER_MODE, + COMPLETION_MAIN_FUNCTION, + COMPLETION_IDENTIFIER, + COMPLETION_FUNCTION_CALL, + COMPLETION_CALL_ARGUMENTS, + COMPLETION_INDEX, + }; struct Token { TokenType type; StringName text; - uint16_t line,col; - - Token(TokenType p_type=TK_EMPTY,const String& p_text=String()) { type=p_type; text=p_text; line=0; col=0; } + double constant; + uint16_t line; }; + static String get_operator_text(Operator p_op); + static String get_token_text(Token p_token); + + static bool is_token_datatype(TokenType p_type); + static DataType get_token_datatype(TokenType p_type); + static bool is_token_precision(TokenType p_type); + static DataPrecision get_token_precision(TokenType p_type); + static String get_datatype_name(DataType p_type); + static bool is_token_nonvoid_datatype(TokenType p_type); + static bool is_token_operator(TokenType p_type); + + static bool convert_constant(ConstantNode* p_constant, DataType p_to_type,ConstantNode::Value *p_value=NULL); + static DataType get_scalar_type(DataType p_type); + static bool is_scalar_type(DataType p_type); + static bool is_sampler_type(DataType p_type); + + static void get_keyword_list(List<String> *r_keywords); + static void get_builtin_funcs(List<String> *r_keywords); +private: - static Token read_token(const CharType* p_text,int p_len,int &r_line,int &r_chars); - static Error tokenize(const String& p_text,Vector<Token> *p_tokens,String *r_error,int *r_err_line,int *r_err_column); + struct KeyWord { TokenType token; const char *text;}; + static const KeyWord keyword_list[]; + bool error_set; + String error_str; + int error_line; + String code; + int char_idx; + int tk_line; + StringName current_function; - class Parser { + struct TkPos { + int char_idx; + int tk_line; + }; - Vector<Token> tokens; - int pos; - String error; - public: + TkPos _get_tkpos() { + TkPos tkp; + tkp.char_idx=char_idx; + tkp.tk_line=tk_line; + return tkp; + } - void set_error(const String& p_error) { error=p_error; } - void get_error(String *r_error, int *r_line, int *r_column) { + void _set_tkpos(TkPos p_pos) { + char_idx=p_pos.char_idx; + tk_line=p_pos.tk_line; + } - *r_error=error; - *r_line=get_token(pos).line; - *r_column=get_token(pos).col; - } + void _set_error(const String& p_str) { + if (error_set) + return; + error_line=tk_line; + error_set=true; + error_str=p_str; + } - Token get_token(int ofs=0) const { int idx=pos+ofs; if (idx<0 || idx>=tokens.size()) return Token(TK_ERROR); return tokens[idx]; } - TokenType get_token_type(int ofs=0) const { int idx=pos+ofs; if (idx<0 || idx>=tokens.size()) return TK_ERROR; return tokens[idx].type; } - void advance(int p_amount=1) { pos+=p_amount; } - bool is_at_end() const { return pos>=tokens.size(); } + static const char * token_names[TK_MAX]; - ProgramNode *program; - template<class T> - T* create_node(Node *p_parent) { T*n=memnew( T ); nodegc.push_back(n); n->parent=p_parent; return n; } - List<Node*> nodegc; - Parser(const Vector<Token>& p_tokens) { tokens=p_tokens; pos=0;} - }; - struct IntrinsicFuncDef { - enum { MAX_ARGS=5 }; - const char* name; - DataType rettype; - const DataType args[MAX_ARGS]; + Token _make_token(TokenType p_type, const StringName& p_text=StringName()); + Token _get_token(); + ShaderNode *shader; + + enum IdentifierType { + IDENTIFIER_FUNCTION, + IDENTIFIER_UNIFORM, + IDENTIFIER_VARYING, + IDENTIFIER_FUNCTION_ARGUMENT, + IDENTIFIER_LOCAL_VAR, + IDENTIFIER_BUILTIN_VAR, }; - static const IntrinsicFuncDef intrinsic_func_defs[]; + bool _find_identifier(const BlockNode* p_block,const Map<StringName, DataType> &p_builtin_types,const StringName& p_identifier, DataType *r_data_type=NULL, IdentifierType *r_type=NULL); - struct OperatorDef { + bool _validate_operator(OperatorNode *p_op,DataType *r_ret_type=NULL); - enum { MAX_ARGS=2 }; - Operator op; + + struct BuiltinFuncDef { + + enum { MAX_ARGS=5 }; + const char* name; DataType rettype; const DataType args[MAX_ARGS]; + }; - static const OperatorDef operator_defs[]; + CompletionType completion_type; + int completion_line; + BlockNode *completion_block; + DataType completion_base; + StringName completion_function; + int completion_argument; - struct BuiltinsDef { - const char* name; - DataType type; - }; + bool _get_completable_identifier(BlockNode *p_block, CompletionType p_type, StringName& identifier); - static const BuiltinsDef vertex_builtins_defs[]; - static const BuiltinsDef fragment_builtins_defs[]; - static const BuiltinsDef light_builtins_defs[]; + static const BuiltinFuncDef builtin_func_defs[]; + bool _validate_function_call(BlockNode* p_block, OperatorNode *p_func,DataType *r_ret_type); - static const BuiltinsDef ci_vertex_builtins_defs[]; - static const BuiltinsDef ci_fragment_builtins_defs[]; - static const BuiltinsDef ci_light_builtins_defs[]; + bool _parse_function_arguments(BlockNode *p_block, const Map<StringName,DataType> &p_builtin_types, OperatorNode* p_func, int *r_complete_arg=NULL); + Node* _parse_expression(BlockNode *p_block, const Map<StringName,DataType> &p_builtin_types); - static const BuiltinsDef postprocess_fragment_builtins_defs[]; + ShaderLanguage::Node* _reduce_expression(BlockNode *p_block, ShaderLanguage::Node *p_node); + Node* _parse_and_reduce_expression(BlockNode *p_block,const Map<StringName,DataType> &p_builtin_types); - static DataType get_token_datatype(TokenType p_type); - static String get_datatype_name(DataType p_type); - static bool is_token_datatype(TokenType p_type); - static bool is_token_nonvoid_datatype(TokenType p_type); + Error _parse_block(BlockNode *p_block, const Map<StringName, DataType> &p_builtin_types, bool p_just_one=false, bool p_can_break=false, bool p_can_continue=false); - static bool test_existing_identifier(Node *p_node,const StringName p_identifier,bool p_func=true,bool p_var=true,bool p_builtin=true); + Error _parse_shader(const Map< StringName, Map<StringName,DataType> > &p_functions, const Set<String> &p_render_modes); - static bool parser_is_at_function(Parser& parser); - static DataType compute_node_type(Node *p_node); - static Node* validate_function_call(Parser&parser, OperatorNode *p_func); - static Node* validate_operator(Parser& parser,OperatorNode *p_func); - static bool is_token_operator(TokenType p_type); - static Operator get_token_operator(TokenType p_type); +public: - static Error parse_expression(Parser& parser,Node *p_parent,Node **r_expr); + //static void get_keyword_list(ShaderType p_type,List<String> *p_keywords); - static Error parse_variable_declaration(Parser& parser,BlockNode *p_block); - static Error parse_function(Parser& parser,BlockNode *p_block); - static Error parse_flow_if(Parser& parser,Node *p_parent,Node **r_statement); - static Error parse_flow_return(Parser& parser,Node *p_parent,Node **r_statement); - static Error parse_statement(Parser& parser,Node *p_parent,Node **r_statement); - static Error parse_block(Parser& parser,BlockNode *p_block); + void clear(); + Error compile(const String& p_code,const Map< StringName, Map<StringName,DataType> > &p_functions,const Set<String>& p_render_modes); + Error complete(const String& p_code,const Map< StringName, Map<StringName,DataType> > &p_functions,const Set<String>& p_render_modes,List<String>* r_options,String& r_call_hint); - static Error parse(const Vector<Token> &p_tokens,ShaderType p_type,CompileFunc p_compile_func,void *p_userdata,String *r_error,int *r_err_line,int *r_err_column); -; -public: + String get_error_text(); + int get_error_line(); - static void get_keyword_list(ShaderType p_type,List<String> *p_keywords); + ShaderNode *get_shader(); - static Error compile(const String& p_code,ShaderType p_type, CompileFunc p_compile_func,void *p_userdata,String *r_error,int *r_err_line,int *r_err_column); - static String lex_debug(const String& p_code); + String token_debug(const String& p_code); + ShaderLanguage(); + ~ShaderLanguage(); }; diff --git a/servers/visual/shader_types.cpp b/servers/visual/shader_types.cpp new file mode 100644 index 0000000000..0eb3e0fc5a --- /dev/null +++ b/servers/visual/shader_types.cpp @@ -0,0 +1,182 @@ +#include "shader_types.h" + + +const Map< StringName, Map<StringName,ShaderLanguage::DataType> >& ShaderTypes::get_functions(VS::ShaderMode p_mode) { + + return shader_modes[p_mode].functions; +} + +const Set<String>& ShaderTypes::get_modes(VS::ShaderMode p_mode) { + + return shader_modes[p_mode].modes; +} + + +ShaderTypes *ShaderTypes::singleton=NULL; + +ShaderTypes::ShaderTypes() +{ + singleton=this; + + /*************** SPATIAL ***********************/ + + shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["SRC_VERTEX"]=ShaderLanguage::TYPE_VEC3; + shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["SRC_NORMAL"]=ShaderLanguage::TYPE_VEC3; + shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["SRC_TANGENT"]=ShaderLanguage::TYPE_VEC4; + shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["SRC_BONES"]=ShaderLanguage::TYPE_IVEC4; + shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["SRC_WEIGHTS"]=ShaderLanguage::TYPE_VEC4; + + shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["POSITION"]=ShaderLanguage::TYPE_VEC4 ; + shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["VERTEX"]=ShaderLanguage::TYPE_VEC3; + shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["NORMAL"]=ShaderLanguage::TYPE_VEC3; + shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["TANGENT"]=ShaderLanguage::TYPE_VEC3; + shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["BINORMAL"]=ShaderLanguage::TYPE_VEC3; + shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["UV"]=ShaderLanguage::TYPE_VEC2; + shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["UV2"]=ShaderLanguage::TYPE_VEC2; + shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["COLOR"]=ShaderLanguage::TYPE_VEC4; + shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["POINT_SIZE"]=ShaderLanguage::TYPE_FLOAT; + shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["INSTANCE_ID"]=ShaderLanguage::TYPE_INT; + + //builtins + shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["WORLD_MATRIX"]=ShaderLanguage::TYPE_MAT4; + shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["INV_CAMERA_MATRIX"]=ShaderLanguage::TYPE_MAT4; + shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["PROJECTION_MATRIX"]=ShaderLanguage::TYPE_MAT4; + shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["TIME"]=ShaderLanguage::TYPE_FLOAT; + shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["VIEWPORT_SIZE"]=ShaderLanguage::TYPE_VEC2; + + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["VERTEX"]=ShaderLanguage::TYPE_VEC3; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["FRAGCOORD"]=ShaderLanguage::TYPE_VEC4; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["FRONT_FACING"]=ShaderLanguage::TYPE_BOOL; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["NORMAL"]=ShaderLanguage::TYPE_VEC3; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["TANGENT"]=ShaderLanguage::TYPE_VEC3; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["BINORMAL"]=ShaderLanguage::TYPE_VEC3; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["NORMALMAP"]=ShaderLanguage::TYPE_VEC3; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["NORMALMAP_DEPTH"]=ShaderLanguage::TYPE_FLOAT; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["UV"]=ShaderLanguage::TYPE_VEC2; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["UV2"]=ShaderLanguage::TYPE_VEC2; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["COLOR"]=ShaderLanguage::TYPE_VEC4; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["NORMAL"]=ShaderLanguage::TYPE_VEC3; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["ALBEDO"]=ShaderLanguage::TYPE_VEC3; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["ALPHA"]=ShaderLanguage::TYPE_FLOAT; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["SPECULAR"]=ShaderLanguage::TYPE_VEC3; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["ROUGHNESS"]=ShaderLanguage::TYPE_FLOAT; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["RIM"]=ShaderLanguage::TYPE_FLOAT; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["RIM_TINT"]=ShaderLanguage::TYPE_FLOAT; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["CLEARCOAT"]=ShaderLanguage::TYPE_FLOAT; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["CLEARCOAT_GLOSS"]=ShaderLanguage::TYPE_FLOAT; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["ANISOTROPY"]=ShaderLanguage::TYPE_FLOAT; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["ANISOTROPY_FLOW"]=ShaderLanguage::TYPE_VEC2; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["SSS_STRENGTH"]=ShaderLanguage::TYPE_FLOAT; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["AO"]=ShaderLanguage::TYPE_FLOAT; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["EMISSION"]=ShaderLanguage::TYPE_VEC3; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["SPECIAL"]=ShaderLanguage::TYPE_FLOAT; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["DISCARD"]=ShaderLanguage::TYPE_BOOL; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["SCREEN_UV"]=ShaderLanguage::TYPE_VEC2; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["POINT_COORD"]=ShaderLanguage::TYPE_VEC2; + + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["WORLD_MATRIX"]=ShaderLanguage::TYPE_MAT4; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["INV_CAMERA_MATRIX"]=ShaderLanguage::TYPE_MAT4; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["PROJECTION_MATRIX"]=ShaderLanguage::TYPE_MAT4; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["TIME"]=ShaderLanguage::TYPE_FLOAT; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["VIEWPORT_SIZE"]=ShaderLanguage::TYPE_VEC2; + + shader_modes[VS::SHADER_SPATIAL].modes.insert("blend_mix"); + shader_modes[VS::SHADER_SPATIAL].modes.insert("blend_add"); + shader_modes[VS::SHADER_SPATIAL].modes.insert("blend_sub"); + shader_modes[VS::SHADER_SPATIAL].modes.insert("blend_mul"); + + shader_modes[VS::SHADER_SPATIAL].modes.insert("depth_draw_opaque"); + shader_modes[VS::SHADER_SPATIAL].modes.insert("depth_draw_always"); + shader_modes[VS::SHADER_SPATIAL].modes.insert("depth_draw_never"); + shader_modes[VS::SHADER_SPATIAL].modes.insert("depth_draw_alpha_prepass"); + + shader_modes[VS::SHADER_SPATIAL].modes.insert("cull_front"); + shader_modes[VS::SHADER_SPATIAL].modes.insert("cull_back"); + shader_modes[VS::SHADER_SPATIAL].modes.insert("cull_disabled"); + + shader_modes[VS::SHADER_SPATIAL].modes.insert("unshaded"); + shader_modes[VS::SHADER_SPATIAL].modes.insert("ontop"); + + shader_modes[VS::SHADER_SPATIAL].modes.insert("skip_transform"); + + /************ CANVAS ITEM **************************/ + + shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"]["SRC_VERTEX"]=ShaderLanguage::TYPE_VEC2; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"]["VERTEX"]=ShaderLanguage::TYPE_VEC2; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"]["UV"]=ShaderLanguage::TYPE_VEC2; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"]["VERTEX_COLOR"]=ShaderLanguage::TYPE_VEC4; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"]["POINT_SIZE"]=ShaderLanguage::TYPE_FLOAT; + + shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"]["WORLD_MATRIX"]=ShaderLanguage::TYPE_MAT4; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"]["PROJECTION_MATRIX"]=ShaderLanguage::TYPE_MAT4; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"]["EXTRA_MATRIX"]=ShaderLanguage::TYPE_MAT4; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"]["TIME"]=ShaderLanguage::TYPE_FLOAT; + + shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["SRC_COLOR"]=ShaderLanguage::TYPE_VEC4; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["POSITION"]=ShaderLanguage::TYPE_VEC4; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["NORMAL"]=ShaderLanguage::TYPE_VEC3; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["NORMALMAP"]=ShaderLanguage::TYPE_VEC3; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["NORMALMAP_DEPTH"]=ShaderLanguage::TYPE_FLOAT; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["UV"]=ShaderLanguage::TYPE_VEC2; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["COLOR"]=ShaderLanguage::TYPE_VEC4; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["TEXTURE"]=ShaderLanguage::TYPE_SAMPLER2D; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["TEXTURE_PIXEL_SIZE"]=ShaderLanguage::TYPE_VEC2; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["SCREEN_UV"]=ShaderLanguage::TYPE_VEC2; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["POINT_COORD"]=ShaderLanguage::TYPE_VEC2; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["TIME"]=ShaderLanguage::TYPE_FLOAT; + + shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["POSITION"]=ShaderLanguage::TYPE_VEC4; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["NORMAL"]=ShaderLanguage::TYPE_VEC3; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["UV"]=ShaderLanguage::TYPE_VEC2; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["COLOR"]=ShaderLanguage::TYPE_VEC4; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["TEXTURE"]=ShaderLanguage::TYPE_SAMPLER2D; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["TEXTURE_PIXEL_SIZE"]=ShaderLanguage::TYPE_VEC2; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["VAR1"]=ShaderLanguage::TYPE_VEC4; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["VAR2"]=ShaderLanguage::TYPE_VEC4; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["SCREEN_UV"]=ShaderLanguage::TYPE_VEC2; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["LIGHT_VEC"]=ShaderLanguage::TYPE_VEC2; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["LIGHT_HEIGHT"]=ShaderLanguage::TYPE_FLOAT; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["LIGHT_COLOR"]=ShaderLanguage::TYPE_VEC4; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["LIGHT_UV"]=ShaderLanguage::TYPE_VEC2; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["LIGHT_SHADOW"]=ShaderLanguage::TYPE_VEC4; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["LIGHT"]=ShaderLanguage::TYPE_VEC4; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["SHADOW"]=ShaderLanguage::TYPE_VEC4; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["POINT_COORD"]=ShaderLanguage::TYPE_VEC2; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["TIME"]=ShaderLanguage::TYPE_FLOAT; + + shader_modes[VS::SHADER_CANVAS_ITEM].modes.insert("skip_transform"); + + shader_modes[VS::SHADER_CANVAS_ITEM].modes.insert("blend_mix"); + shader_modes[VS::SHADER_CANVAS_ITEM].modes.insert("blend_add"); + shader_modes[VS::SHADER_CANVAS_ITEM].modes.insert("blend_sub"); + shader_modes[VS::SHADER_CANVAS_ITEM].modes.insert("blend_mul"); + shader_modes[VS::SHADER_CANVAS_ITEM].modes.insert("blend_premul_alpha"); + + shader_modes[VS::SHADER_CANVAS_ITEM].modes.insert("unshaded"); + shader_modes[VS::SHADER_CANVAS_ITEM].modes.insert("light_only"); + + + /************ PARTICLES **************************/ + + shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["COLOR"]=ShaderLanguage::TYPE_VEC4; + shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["VELOCITY"]=ShaderLanguage::TYPE_VEC3; + shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["MASS"]=ShaderLanguage::TYPE_FLOAT; + shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["ACTIVE"]=ShaderLanguage::TYPE_BOOL; + shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["RESTART"]=ShaderLanguage::TYPE_BOOL; + shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["CUSTOM"]=ShaderLanguage::TYPE_VEC4; + shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["TRANSFORM"]=ShaderLanguage::TYPE_MAT4; + shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["TIME"]=ShaderLanguage::TYPE_FLOAT; + shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["LIFETIME"]=ShaderLanguage::TYPE_FLOAT; + shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["DELTA"]=ShaderLanguage::TYPE_FLOAT; + shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["SEED"]=ShaderLanguage::TYPE_BOOL; + shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["ORIGIN"]=ShaderLanguage::TYPE_MAT4; + shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["INDEX"]=ShaderLanguage::TYPE_INT; + + shader_modes[VS::SHADER_PARTICLES].modes.insert("billboard"); + shader_modes[VS::SHADER_PARTICLES].modes.insert("disable_force"); + shader_modes[VS::SHADER_PARTICLES].modes.insert("disable_velocity"); + + + + +} diff --git a/servers/visual/shader_types.h b/servers/visual/shader_types.h new file mode 100644 index 0000000000..411d5790a9 --- /dev/null +++ b/servers/visual/shader_types.h @@ -0,0 +1,27 @@ +#ifndef SHADERTYPES_H +#define SHADERTYPES_H + +#include "shader_language.h" +#include "servers/visual_server.h" +class ShaderTypes { + + + struct Type { + + Map< StringName, Map<StringName,ShaderLanguage::DataType> > functions; + Set<String> modes; + }; + + Map<VS::ShaderMode,Type> shader_modes; + + static ShaderTypes *singleton; +public: + static ShaderTypes *get_singleton() { return singleton; } + + const Map< StringName, Map<StringName,ShaderLanguage::DataType> >& get_functions(VS::ShaderMode p_mode); + const Set<String>& get_modes(VS::ShaderMode p_mode); + + ShaderTypes(); +}; + +#endif // SHADERTYPES_H diff --git a/servers/visual/visual_server_canvas.cpp b/servers/visual/visual_server_canvas.cpp new file mode 100644 index 0000000000..f4031b711d --- /dev/null +++ b/servers/visual/visual_server_canvas.cpp @@ -0,0 +1,1270 @@ +#include "visual_server_canvas.h" +#include "visual_server_global.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; + RasterizerCanvas::Item *z_list[z_range]; + RasterizerCanvas::Item *z_last_list[z_range]; + + for(int i=0;i<z_range;i++) { + z_list[i]=NULL; + z_last_list[i]=NULL; + } + + + _render_canvas_item(p_canvas_item,p_transform,p_clip_rect,Color(1,1,1,1),0,z_list,z_last_list,NULL,NULL); + + for(int i=0;i<z_range;i++) { + if (!z_list[i]) + continue; + VSG::canvas_render->canvas_render_items(z_list[i],VS::CANVAS_ITEM_Z_MIN+i,p_modulate,p_lights); + } + +} + +void VisualServerCanvas::_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) { + + Item *ci = p_canvas_item; + + if (!ci->visible) + return; + + Rect2 rect = ci->get_rect(); + Transform2D xform = p_transform * ci->xform; + Rect2 global_rect = xform.xform(rect); + global_rect.pos+=p_clip_rect.pos; + + + if (ci->use_parent_material && p_material_owner) + ci->material_owner=p_material_owner; + else { + p_material_owner=ci; + ci->material_owner=NULL; + } + + + Color modulate( ci->modulate.r * p_modulate.r, ci->modulate.g * p_modulate.g,ci->modulate.b * p_modulate.b,ci->modulate.a * p_modulate.a); + + if (modulate.a<0.007) + return; + + + int child_item_count=ci->child_items.size(); + Item **child_items=(Item**)alloca(child_item_count*sizeof(Item*)); + copymem(child_items,ci->child_items.ptr(),child_item_count*sizeof(Item*)); + + if (ci->clip) { + if (p_canvas_clip != NULL) { + ci->final_clip_rect=p_canvas_clip->final_clip_rect.clip(global_rect); + } else { + ci->final_clip_rect=global_rect; + } + ci->final_clip_owner=ci; + + } else { + ci->final_clip_owner=p_canvas_clip; + } + + if (ci->sort_y) { + + SortArray<Item*,ItemPtrSort> sorter; + sorter.sort(child_items,child_item_count); + } + + if (ci->z_relative) + p_z=CLAMP(p_z+ci->z,VS::CANVAS_ITEM_Z_MIN,VS::CANVAS_ITEM_Z_MAX); + else + p_z=ci->z; + + for(int i=0;i<child_item_count;i++) { + + if (!child_items[i]->behind) + continue; + _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); + } + + if (ci->copy_back_buffer) { + + ci->copy_back_buffer->screen_rect = xform.xform(ci->copy_back_buffer->rect).clip(p_clip_rect); + } + + if ((!ci->commands.empty() && p_clip_rect.intersects(global_rect)) || ci->vp_render || ci->copy_back_buffer) { + //something to draw? + ci->final_transform=xform; + ci->final_modulate=Color(modulate.r*ci->self_modulate.r, modulate.g*ci->self_modulate.g, modulate.b*ci->self_modulate.b, modulate.a*ci->self_modulate.a ); + ci->global_rect_cache=global_rect; + ci->global_rect_cache.pos-=p_clip_rect.pos; + ci->light_masked=false; + + int zidx = p_z-VS::CANVAS_ITEM_Z_MIN; + + if (z_last_list[zidx]) { + z_last_list[zidx]->next=ci; + z_last_list[zidx]=ci; + + } else { + z_list[zidx]=ci; + z_last_list[zidx]=ci; + } + + ci->next=NULL; + + } + + for(int i=0;i<child_item_count;i++) { + + if (child_items[i]->behind) + continue; + _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); + } + +} + +void VisualServerCanvas::_light_mask_canvas_items(int p_z,RasterizerCanvas::Item *p_canvas_item,RasterizerCanvas::Light *p_masked_lights) { + + if (!p_masked_lights) + return; + + RasterizerCanvas::Item *ci=p_canvas_item; + + while(ci) { + + RasterizerCanvas::Light *light=p_masked_lights; + while(light) { + + if (ci->light_mask&light->item_mask && p_z>=light->z_min && p_z<=light->z_max && ci->global_rect_cache.intersects_transformed(light->xform_cache,light->rect_cache)) { + ci->light_masked=true; + } + + light=light->mask_next_ptr; + } + + ci=ci->next; + } + + + + +} + +void VisualServerCanvas::render_canvas(Canvas *p_canvas, const Transform2D &p_transform, RasterizerCanvas::Light *p_lights, RasterizerCanvas::Light *p_masked_lights, const Rect2 &p_clip_rect) { + + VSG::canvas_render->canvas_begin(); + + int l = p_canvas->child_items.size(); + Canvas::ChildItem *ci=p_canvas->child_items.ptr(); + + bool has_mirror=false; + for(int i=0;i<l;i++) { + if (ci[i].mirror.x || ci[i].mirror.y) { + has_mirror=true; + break; + } + } + + + if (!has_mirror) { + + 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]; + + for(int i=0;i<z_range;i++) { + z_list[i]=NULL; + z_last_list[i]=NULL; + } + for(int i=0;i<l;i++) { + _render_canvas_item(ci[i].item,p_transform,p_clip_rect,Color(1,1,1,1),0,z_list,z_last_list,NULL,NULL); + } + + for(int i=0;i<z_range;i++) { + if (!z_list[i]) + continue; + + if (p_masked_lights) { + _light_mask_canvas_items(VS::CANVAS_ITEM_Z_MIN+i,z_list[i],p_masked_lights); + } + + VSG::canvas_render->canvas_render_items(z_list[i],VS::CANVAS_ITEM_Z_MIN+i,p_canvas->modulate,p_lights); + } + } else { + + for(int i=0;i<l;i++) { + + Canvas::ChildItem& ci=p_canvas->child_items[i]; + _render_canvas_item_tree(ci.item,p_transform,p_clip_rect,p_canvas->modulate,p_lights); + + //mirroring (useful for scrolling backgrounds) + if (ci.mirror.x!=0) { + + Transform2D xform2 = p_transform * Transform2D(0,Vector2(ci.mirror.x,0)); + _render_canvas_item_tree(ci.item,xform2,p_clip_rect,p_canvas->modulate,p_lights); + } + if (ci.mirror.y!=0) { + + Transform2D xform2 = p_transform * Transform2D(0,Vector2(0,ci.mirror.y)); + _render_canvas_item_tree(ci.item,xform2,p_clip_rect,p_canvas->modulate,p_lights); + } + if (ci.mirror.y!=0 && ci.mirror.x!=0) { + + Transform2D xform2 = p_transform * Transform2D(0,ci.mirror); + _render_canvas_item_tree(ci.item,xform2,p_clip_rect,p_canvas->modulate,p_lights); + } + + } + } + +} + + +RID VisualServerCanvas::canvas_create() { + + Canvas * canvas = memnew( Canvas ); + ERR_FAIL_COND_V(!canvas,RID()); + RID rid = canvas_owner.make_rid( canvas ); + + return rid; +} + +void VisualServerCanvas::canvas_set_item_mirroring(RID p_canvas,RID p_item,const Point2& p_mirroring) { + + Canvas * canvas = canvas_owner.getornull(p_canvas); + ERR_FAIL_COND(!canvas); + Item *canvas_item = canvas_item_owner.getornull(p_item); + ERR_FAIL_COND(!canvas_item); + + int idx = canvas->find_item(canvas_item); + ERR_FAIL_COND(idx==-1); + canvas->child_items[idx].mirror=p_mirroring; + +} +void VisualServerCanvas::canvas_set_modulate(RID p_canvas,const Color& p_color) { + + Canvas * canvas = canvas_owner.get(p_canvas); + ERR_FAIL_COND(!canvas); + canvas->modulate=p_color; +} + + +RID VisualServerCanvas::canvas_item_create() { + + Item *canvas_item = memnew( Item ); + ERR_FAIL_COND_V(!canvas_item,RID()); + + return canvas_item_owner.make_rid( canvas_item ); +} + +void VisualServerCanvas::canvas_item_set_parent(RID p_item,RID p_parent) { + + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + + if (canvas_item->parent.is_valid()) { + + if (canvas_owner.owns(canvas_item->parent)) { + + Canvas *canvas = canvas_owner.get(canvas_item->parent); + canvas->erase_item(canvas_item); + } else if (canvas_item_owner.owns(canvas_item->parent)) { + + Item *item_owner = canvas_item_owner.get(canvas_item->parent); + item_owner->child_items.erase(canvas_item); + } + + canvas_item->parent=RID(); + } + + + if (p_parent.is_valid()) { + if (canvas_owner.owns(p_parent)) { + + Canvas *canvas = canvas_owner.get(p_parent); + Canvas::ChildItem ci; + ci.item=canvas_item; + canvas->child_items.push_back(ci); + canvas->children_order_dirty=true; + } else if (canvas_item_owner.owns(p_parent)) { + + Item *item_owner = canvas_item_owner.get(p_parent); + item_owner->child_items.push_back(canvas_item); + item_owner->children_order_dirty=true; + + } else { + + ERR_EXPLAIN("Invalid parent"); + ERR_FAIL(); + } + + + } + + canvas_item->parent=p_parent; + + +} +void VisualServerCanvas::canvas_item_set_visible(RID p_item,bool p_visible){ + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + + canvas_item->visible=p_visible; + +} +void VisualServerCanvas::canvas_item_set_light_mask(RID p_item,int p_mask){ + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + + canvas_item->light_mask=p_mask; + +} + +void VisualServerCanvas::canvas_item_set_transform(RID p_item, const Transform2D& p_transform){ + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + + canvas_item->xform=p_transform; + +} +void VisualServerCanvas::canvas_item_set_clip(RID p_item, bool p_clip){ + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + + canvas_item->clip=p_clip; + +} +void VisualServerCanvas::canvas_item_set_distance_field_mode(RID p_item, bool p_enable){ + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + + canvas_item->distance_field=p_enable; + + +} +void VisualServerCanvas::canvas_item_set_custom_rect(RID p_item, bool p_custom_rect,const Rect2& p_rect){ + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + + canvas_item->custom_rect=p_custom_rect; + canvas_item->rect=p_rect; + +} +void VisualServerCanvas::canvas_item_set_modulate(RID p_item, const Color& p_color) { + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + + canvas_item->modulate=p_color; + +} +void VisualServerCanvas::canvas_item_set_self_modulate(RID p_item, const Color& p_color){ + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + + canvas_item->self_modulate=p_color; + +} + +void VisualServerCanvas::canvas_item_set_draw_behind_parent(RID p_item, bool p_enable){ + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + + canvas_item->behind=p_enable; + +} + + +void VisualServerCanvas::canvas_item_add_line(RID p_item, const Point2& p_from, const Point2& p_to,const Color& p_color,float p_width,bool p_antialiased) { + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + + Item::CommandLine * line = memnew( Item::CommandLine ); + ERR_FAIL_COND(!line); + line->color=p_color; + line->from=p_from; + line->to=p_to; + line->width=p_width; + line->antialiased=p_antialiased; + canvas_item->rect_dirty=true; + + + canvas_item->commands.push_back(line); +} + +void VisualServerCanvas::canvas_item_add_rect(RID p_item, const Rect2& p_rect, const Color& p_color) { + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + + Item::CommandRect * rect = memnew( Item::CommandRect ); + ERR_FAIL_COND(!rect); + rect->modulate=p_color; + rect->rect=p_rect; + canvas_item->rect_dirty=true; + + canvas_item->commands.push_back(rect); +} + +void VisualServerCanvas::canvas_item_add_circle(RID p_item, const Point2& p_pos, float p_radius,const Color& p_color) { + + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + + Item::CommandCircle * circle = memnew( Item::CommandCircle ); + ERR_FAIL_COND(!circle); + circle->color=p_color; + circle->pos=p_pos; + circle->radius=p_radius; + + canvas_item->commands.push_back(circle); + +} + +void VisualServerCanvas::canvas_item_add_texture_rect(RID p_item, const Rect2& p_rect, RID p_texture,bool p_tile,const Color& p_modulate,bool p_transpose) { + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + + Item::CommandRect * rect = memnew( Item::CommandRect ); + ERR_FAIL_COND(!rect); + rect->modulate=p_modulate; + rect->rect=p_rect; + rect->flags=0; + 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); + } + + if (p_rect.size.x<0) { + + rect->flags|=RasterizerCanvas::CANVAS_RECT_FLIP_H; + rect->rect.size.x = -rect->rect.size.x; + } + if (p_rect.size.y<0) { + + rect->flags|=RasterizerCanvas::CANVAS_RECT_FLIP_V; + rect->rect.size.y = -rect->rect.size.y; + } + if (p_transpose) { + rect->flags|=RasterizerCanvas::CANVAS_RECT_TRANSPOSE; + SWAP(rect->rect.size.x, rect->rect.size.y); + } + rect->texture=p_texture; + canvas_item->rect_dirty=true; + canvas_item->commands.push_back(rect); +} + +void VisualServerCanvas::canvas_item_add_texture_rect_region(RID p_item, const Rect2& p_rect, RID p_texture,const Rect2& p_src_rect,const Color& p_modulate,bool p_transpose) { + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + + Item::CommandRect * rect = memnew( Item::CommandRect ); + ERR_FAIL_COND(!rect); + rect->modulate=p_modulate; + rect->rect=p_rect; + rect->texture=p_texture; + rect->source=p_src_rect; + rect->flags=RasterizerCanvas::CANVAS_RECT_REGION; + + if (p_rect.size.x<0) { + + rect->flags|=RasterizerCanvas::CANVAS_RECT_FLIP_H; + rect->rect.size.x = -rect->rect.size.x; + } + if (p_rect.size.y<0) { + + rect->flags|=RasterizerCanvas::CANVAS_RECT_FLIP_V; + rect->rect.size.y = -rect->rect.size.y; + } + if (p_transpose) { + rect->flags|=RasterizerCanvas::CANVAS_RECT_TRANSPOSE; + SWAP(rect->rect.size.x, rect->rect.size.y); + } + + canvas_item->rect_dirty=true; + + canvas_item->commands.push_back(rect); + +} + +void VisualServerCanvas::canvas_item_add_nine_patch(RID p_item, const Rect2& p_rect, const Rect2& p_source, RID p_texture,const Vector2& p_topleft, const Vector2& p_bottomright,VS::NinePatchAxisMode p_x_axis_mode, VS::NinePatchAxisMode p_y_axis_mode,bool p_draw_center,const Color& p_modulate) { + + + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + + Item::CommandNinePatch * style = memnew( Item::CommandNinePatch ); + ERR_FAIL_COND(!style); + style->texture=p_texture; + style->rect=p_rect; + style->source=p_source; + style->draw_center=p_draw_center; + style->color=p_modulate; + style->margin[MARGIN_LEFT]=p_topleft.x; + style->margin[MARGIN_TOP]=p_topleft.y; + style->margin[MARGIN_RIGHT]=p_bottomright.x; + style->margin[MARGIN_BOTTOM]=p_bottomright.y; + style->axis_x=p_x_axis_mode; + style->axis_y=p_y_axis_mode; + canvas_item->rect_dirty=true; + + canvas_item->commands.push_back(style); +} +void VisualServerCanvas::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) { + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + + Item::CommandPrimitive * prim = memnew( Item::CommandPrimitive ); + ERR_FAIL_COND(!prim); + prim->texture=p_texture; + prim->points=p_points; + prim->uvs=p_uvs; + prim->colors=p_colors; + prim->width=p_width; + canvas_item->rect_dirty=true; + + canvas_item->commands.push_back(prim); +} + +void VisualServerCanvas::canvas_item_add_polygon(RID p_item, const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs, RID p_texture) { + + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); +#ifdef DEBUG_ENABLED + int pointcount = p_points.size(); + ERR_FAIL_COND(pointcount<3); + int color_size=p_colors.size(); + int uv_size=p_uvs.size(); + ERR_FAIL_COND(color_size!=0 && color_size!=1 && color_size!=pointcount); + ERR_FAIL_COND(uv_size!=0 && (uv_size!=pointcount || !p_texture.is_valid())); +#endif + Vector<int> indices = Geometry::triangulate_polygon(p_points); + + if (indices.empty()) { + + ERR_EXPLAIN("Bad Polygon!"); + ERR_FAIL_V(); + } + + Item::CommandPolygon * polygon = memnew( Item::CommandPolygon ); + ERR_FAIL_COND(!polygon); + polygon->texture=p_texture; + polygon->points=p_points; + polygon->uvs=p_uvs; + polygon->colors=p_colors; + polygon->indices=indices; + polygon->count=indices.size(); + canvas_item->rect_dirty=true; + + canvas_item->commands.push_back(polygon); + +} + + +void VisualServerCanvas::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, RID p_texture, int p_count) { + + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + + int ps = p_points.size(); + ERR_FAIL_COND(!p_colors.empty() && p_colors.size()!=ps && p_colors.size()!=1); + ERR_FAIL_COND(!p_uvs.empty() && p_uvs.size()!=ps); + + Vector<int> indices = p_indices; + + int count = p_count * 3; + + if (indices.empty()) { + + ERR_FAIL_COND( ps % 3 != 0 ); + if (p_count == -1) + count = ps; + } else { + + ERR_FAIL_COND( indices.size() % 3 != 0 ); + if (p_count == -1) + count = indices.size(); + } + + Item::CommandPolygon * polygon = memnew( Item::CommandPolygon ); + ERR_FAIL_COND(!polygon); + polygon->texture=p_texture; + polygon->points=p_points; + polygon->uvs=p_uvs; + polygon->colors=p_colors; + polygon->indices=indices; + polygon->count = count; + canvas_item->rect_dirty=true; + + canvas_item->commands.push_back(polygon); +} + + +void VisualServerCanvas::canvas_item_add_set_transform(RID p_item,const Transform2D& p_transform) { + + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + + Item::CommandTransform * tr = memnew( Item::CommandTransform ); + ERR_FAIL_COND(!tr); + tr->xform=p_transform; + + canvas_item->commands.push_back(tr); + +} + +void VisualServerCanvas::canvas_item_add_mesh(RID p_item, const RID& p_mesh,RID p_skeleton){ + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + + Item::CommandMesh * m = memnew( Item::CommandMesh ); + ERR_FAIL_COND(!m); + m->mesh=p_mesh; + m->skeleton=p_skeleton; + + canvas_item->commands.push_back(m); +} +void VisualServerCanvas::canvas_item_add_multimesh(RID p_item, RID p_mesh,RID p_skeleton){ + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + + Item::CommandMultiMesh * mm = memnew( Item::CommandMultiMesh ); + ERR_FAIL_COND(!mm); + mm->multimesh=p_mesh; + mm->skeleton=p_skeleton; + + canvas_item->commands.push_back(mm); + +} + +void VisualServerCanvas::canvas_item_add_clip_ignore(RID p_item, bool p_ignore){ + + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + + Item::CommandClipIgnore * ci = memnew( Item::CommandClipIgnore); + ERR_FAIL_COND(!ci); + ci->ignore=p_ignore; + + canvas_item->commands.push_back(ci); +} +void VisualServerCanvas::canvas_item_set_sort_children_by_y(RID p_item, bool p_enable){ + + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + + canvas_item->sort_y=p_enable; +} +void VisualServerCanvas::canvas_item_set_z(RID p_item, int p_z){ + + ERR_FAIL_COND(p_z<VS::CANVAS_ITEM_Z_MIN || p_z>VS::CANVAS_ITEM_Z_MAX); + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + + canvas_item->z=p_z; +} +void VisualServerCanvas::canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable){ + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + + canvas_item->z_relative=p_enable; + +} +void VisualServerCanvas::canvas_item_set_copy_to_backbuffer(RID p_item, bool p_enable,const Rect2& p_rect){ + + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + if (bool(canvas_item->copy_back_buffer!=NULL) !=p_enable) { + if (p_enable) { + canvas_item->copy_back_buffer = memnew( RasterizerCanvas::Item::CopyBackBuffer ); + } else { + memdelete(canvas_item->copy_back_buffer); + canvas_item->copy_back_buffer=NULL; + } + } + + if (p_enable) { + canvas_item->copy_back_buffer->rect=p_rect; + canvas_item->copy_back_buffer->full=p_rect==Rect2(); + } + +} + +void VisualServerCanvas::canvas_item_clear(RID p_item){ + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + + canvas_item->clear(); +} +void VisualServerCanvas::canvas_item_set_draw_index(RID p_item,int p_index){ + + Item *canvas_item = canvas_item_owner.getornull( p_item ); + ERR_FAIL_COND(!canvas_item); + + canvas_item->index=p_index; + + if (canvas_item_owner.owns( canvas_item->parent)) { + Item *canvas_item_parent = canvas_item_owner.getornull( canvas_item->parent ); + canvas_item_parent->children_order_dirty=true; + return; + } + + Canvas* canvas = canvas_owner.getornull( canvas_item->parent ); + if (canvas) { + canvas->children_order_dirty=true; + return; + } + +} + +void VisualServerCanvas::canvas_item_set_material(RID p_item, RID p_material){ + + Item *canvas_item = canvas_item_owner.get( p_item ); + ERR_FAIL_COND(!canvas_item); + + canvas_item->material=p_material; +} + +void VisualServerCanvas::canvas_item_set_use_parent_material(RID p_item, bool p_enable){ + + Item *canvas_item = canvas_item_owner.get( p_item ); + ERR_FAIL_COND(!canvas_item); + + canvas_item->use_parent_material=p_enable; + +} + +RID VisualServerCanvas::canvas_light_create(){ + + RasterizerCanvas::Light *clight = memnew( RasterizerCanvas::Light ); + clight->light_internal = VSG::canvas_render->light_internal_create(); + return canvas_light_owner.make_rid(clight); + +} +void VisualServerCanvas::canvas_light_attach_to_canvas(RID p_light,RID p_canvas){ + + RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + + if (clight->canvas.is_valid()) { + + Canvas *canvas = canvas_owner.getornull(clight->canvas); + canvas->lights.erase(clight); + } + + if (!canvas_owner.owns(p_canvas)) + p_canvas=RID(); + + clight->canvas=p_canvas; + + if (clight->canvas.is_valid()) { + + Canvas *canvas = canvas_owner.get(clight->canvas); + canvas->lights.insert(clight); + } +} + + +void VisualServerCanvas::canvas_light_set_enabled(RID p_light, bool p_enabled){ + + RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + + clight->enabled=p_enabled; + +} +void VisualServerCanvas::canvas_light_set_scale(RID p_light, float p_scale){ + + + RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + + clight->scale=p_scale; + +} +void VisualServerCanvas::canvas_light_set_transform(RID p_light, const Transform2D& p_transform){ + + + RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + + clight->xform=p_transform; + +} +void VisualServerCanvas::canvas_light_set_texture(RID p_light, RID p_texture){ + + + RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + + clight->texture=p_texture; + +} +void VisualServerCanvas::canvas_light_set_texture_offset(RID p_light, const Vector2& p_offset){ + + + RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + + clight->texture_offset=p_offset; + +} +void VisualServerCanvas::canvas_light_set_color(RID p_light, const Color& p_color){ + + + + RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + + clight->color=p_color; +} +void VisualServerCanvas::canvas_light_set_height(RID p_light, float p_height){ + + + RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + + clight->height=p_height; + +} +void VisualServerCanvas::canvas_light_set_energy(RID p_light, float p_energy){ + + + RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + + clight->energy=p_energy; + +} +void VisualServerCanvas::canvas_light_set_z_range(RID p_light, int p_min_z,int p_max_z){ + + + RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + + clight->z_min=p_min_z; + clight->z_max=p_max_z; + +} +void VisualServerCanvas::canvas_light_set_layer_range(RID p_light, int p_min_layer,int p_max_layer){ + + + RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + + + clight->layer_max=p_max_layer; + clight->layer_min=p_min_layer; + + +} +void VisualServerCanvas::canvas_light_set_item_cull_mask(RID p_light, int p_mask){ + + + RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + + clight->item_mask=p_mask; + +} +void VisualServerCanvas::canvas_light_set_item_shadow_cull_mask(RID p_light, int p_mask){ + + RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + + clight->item_shadow_mask=p_mask; + +} +void VisualServerCanvas::canvas_light_set_mode(RID p_light, VS::CanvasLightMode p_mode){ + + RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + + clight->mode=p_mode; + +} + + +void VisualServerCanvas::canvas_light_set_shadow_enabled(RID p_light, bool p_enabled){ + + RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + + if (clight->shadow_buffer.is_valid()==p_enabled) + return; + if (p_enabled) { + clight->shadow_buffer=VSG::storage->canvas_light_shadow_buffer_create(clight->shadow_buffer_size); + } else { + VSG::storage->free(clight->shadow_buffer); + clight->shadow_buffer=RID(); + } + +} +void VisualServerCanvas::canvas_light_set_shadow_buffer_size(RID p_light, int p_size){ + + ERR_FAIL_COND(p_size<32 || p_size>16384); + + RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + + int new_size = nearest_power_of_2(p_size); + if (new_size==clight->shadow_buffer_size) + return; + + clight->shadow_buffer_size=nearest_power_of_2(p_size); + + if (clight->shadow_buffer.is_valid()) { + VSG::storage->free(clight->shadow_buffer); + clight->shadow_buffer=VSG::storage->canvas_light_shadow_buffer_create(clight->shadow_buffer_size); + } +} + +void VisualServerCanvas::canvas_light_set_shadow_gradient_length(RID p_light, float p_length) { + + ERR_FAIL_COND(p_length<0); + + RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + + clight->shadow_gradient_length=p_length; + +} +void VisualServerCanvas::canvas_light_set_shadow_filter(RID p_light, VS::CanvasLightShadowFilter p_filter) { + + RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + + clight->shadow_filter=p_filter; + +} +void VisualServerCanvas::canvas_light_set_shadow_color(RID p_light, const Color& p_color) { + + RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + + clight->shadow_color=p_color; +} + + + +RID VisualServerCanvas::canvas_light_occluder_create() { + + RasterizerCanvas::LightOccluderInstance *occluder = memnew( RasterizerCanvas::LightOccluderInstance ); + + return canvas_light_occluder_owner.make_rid(occluder); +} +void VisualServerCanvas::canvas_light_occluder_attach_to_canvas(RID p_occluder,RID p_canvas){ + + RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_occluder); + ERR_FAIL_COND(!occluder); + + if (occluder->canvas.is_valid()) { + + Canvas *canvas = canvas_owner.get(occluder->canvas); + canvas->occluders.erase(occluder); + } + + if (!canvas_owner.owns(p_canvas)) + p_canvas=RID(); + + occluder->canvas=p_canvas; + + if (occluder->canvas.is_valid()) { + + Canvas *canvas = canvas_owner.get(occluder->canvas); + canvas->occluders.insert(occluder); + } +} +void VisualServerCanvas::canvas_light_occluder_set_enabled(RID p_occluder,bool p_enabled) { + + RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_occluder); + ERR_FAIL_COND(!occluder); + + occluder->enabled=p_enabled; +} +void VisualServerCanvas::canvas_light_occluder_set_polygon(RID p_occluder,RID p_polygon) { + + RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_occluder); + ERR_FAIL_COND(!occluder); + + if (occluder->polygon.is_valid()) { + LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get(p_polygon); + if (occluder_poly) { + occluder_poly->owners.erase(occluder); + } + } + + occluder->polygon=p_polygon; + occluder->polygon_buffer=RID(); + + if (occluder->polygon.is_valid()) { + LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get(p_polygon); + if (!occluder_poly) + occluder->polygon=RID(); + ERR_FAIL_COND(!occluder_poly); + occluder_poly->owners.insert(occluder); + occluder->polygon_buffer=occluder_poly->occluder; + occluder->aabb_cache=occluder_poly->aabb; + occluder->cull_cache=occluder_poly->cull_mode; + } + +} +void VisualServerCanvas::canvas_light_occluder_set_transform(RID p_occluder,const Transform2D& p_xform) { + + RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_occluder); + ERR_FAIL_COND(!occluder); + + occluder->xform=p_xform; +} +void VisualServerCanvas::canvas_light_occluder_set_light_mask(RID p_occluder,int p_mask) { + + RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_occluder); + ERR_FAIL_COND(!occluder); + + occluder->light_mask=p_mask; +} + +RID VisualServerCanvas::canvas_occluder_polygon_create() { + + LightOccluderPolygon * occluder_poly = memnew( LightOccluderPolygon ); + occluder_poly->occluder=VSG::storage->canvas_light_occluder_create(); + return canvas_light_occluder_polygon_owner.make_rid(occluder_poly); + +} +void VisualServerCanvas::canvas_occluder_polygon_set_shape(RID p_occluder_polygon,const PoolVector<Vector2>& p_shape,bool p_closed) { + + if (p_shape.size()<3) { + canvas_occluder_polygon_set_shape_as_lines(p_occluder_polygon,p_shape); + return; + } + + PoolVector<Vector2> lines; + int lc = p_shape.size()*2; + + lines.resize(lc-(p_closed?0:2)); + { + PoolVector<Vector2>::Write w = lines.write(); + PoolVector<Vector2>::Read r = p_shape.read(); + + int max=lc/2; + if (!p_closed) { + max--; + } + for(int i=0;i<max;i++) { + + Vector2 a = r[i]; + Vector2 b = r[(i+1)%(lc/2)]; + w[i*2+0]=a; + w[i*2+1]=b; + } + + } + + canvas_occluder_polygon_set_shape_as_lines(p_occluder_polygon,lines); +} +void VisualServerCanvas::canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon,const PoolVector<Vector2>& p_shape) { + + LightOccluderPolygon * occluder_poly = canvas_light_occluder_polygon_owner.get(p_occluder_polygon); + ERR_FAIL_COND(!occluder_poly); + ERR_FAIL_COND(p_shape.size()&1); + + int lc = p_shape.size(); + occluder_poly->aabb=Rect2(); + { + PoolVector<Vector2>::Read r = p_shape.read(); + for(int i=0;i<lc;i++) { + if (i==0) + occluder_poly->aabb.pos=r[i]; + else + occluder_poly->aabb.expand_to(r[i]); + } + } + + VSG::storage->canvas_light_occluder_set_polylines(occluder_poly->occluder,p_shape); + for( Set<RasterizerCanvas::LightOccluderInstance*>::Element *E=occluder_poly->owners.front();E;E=E->next()) { + E->get()->aabb_cache=occluder_poly->aabb; + } +} + + +void VisualServerCanvas::canvas_occluder_polygon_set_cull_mode(RID p_occluder_polygon,VS::CanvasOccluderPolygonCullMode p_mode) { + + LightOccluderPolygon * occluder_poly = canvas_light_occluder_polygon_owner.get(p_occluder_polygon); + ERR_FAIL_COND(!occluder_poly); + occluder_poly->cull_mode=p_mode; + for( Set<RasterizerCanvas::LightOccluderInstance*>::Element *E=occluder_poly->owners.front();E;E=E->next()) { + E->get()->cull_cache=p_mode; + } +} + + + +bool VisualServerCanvas::free(RID p_rid) { + + if (canvas_owner.owns(p_rid)) { + + Canvas *canvas = canvas_owner.get(p_rid); + ERR_FAIL_COND_V(!canvas,false); + + while(canvas->viewports.size()) { + + VisualServerViewport::Viewport *vp = VSG::viewport->viewport_owner.get(canvas->viewports.front()->get()); + ERR_FAIL_COND_V(!vp,true); + + Map<RID,VisualServerViewport::Viewport::CanvasData>::Element *E=vp->canvas_map.find(p_rid); + ERR_FAIL_COND_V(!E,true); + vp->canvas_map.erase(p_rid); + + canvas->viewports.erase( canvas->viewports.front() ); + } + + for (int i=0;i<canvas->child_items.size();i++) { + + canvas->child_items[i].item->parent=RID(); + } + + for (Set<RasterizerCanvas::Light*>::Element *E=canvas->lights.front();E;E=E->next()) { + + E->get()->canvas=RID(); + } + + for (Set<RasterizerCanvas::LightOccluderInstance*>::Element *E=canvas->occluders.front();E;E=E->next()) { + + E->get()->canvas=RID(); + } + + canvas_owner.free( p_rid ); + + memdelete( canvas ); + + } else if (canvas_item_owner.owns(p_rid)) { + + Item *canvas_item = canvas_item_owner.get(p_rid); + ERR_FAIL_COND_V(!canvas_item,true); + + if (canvas_item->parent.is_valid()) { + + if (canvas_owner.owns(canvas_item->parent)) { + + Canvas *canvas = canvas_owner.get(canvas_item->parent); + canvas->erase_item(canvas_item); + } else if (canvas_item_owner.owns(canvas_item->parent)) { + + Item *item_owner = canvas_item_owner.get(canvas_item->parent); + item_owner->child_items.erase(canvas_item); + + } + } + + for (int i=0;i<canvas_item->child_items.size();i++) { + + canvas_item->child_items[i]->parent=RID(); + } + + /* + if (canvas_item->material) { + canvas_item->material->owners.erase(canvas_item); + } + */ + + canvas_item_owner.free( p_rid ); + + memdelete( canvas_item ); + + } else if (canvas_light_owner.owns(p_rid)) { + + RasterizerCanvas::Light *canvas_light = canvas_light_owner.get(p_rid); + ERR_FAIL_COND_V(!canvas_light,true); + + if (canvas_light->canvas.is_valid()) { + Canvas* canvas = canvas_owner.get(canvas_light->canvas); + if (canvas) + canvas->lights.erase(canvas_light); + } + + if (canvas_light->shadow_buffer.is_valid()) + VSG::storage->free(canvas_light->shadow_buffer); + + VSG::canvas_render->light_internal_free(canvas_light->light_internal); + + canvas_light_owner.free( p_rid ); + memdelete( canvas_light ); + + } else if (canvas_light_occluder_owner.owns(p_rid)) { + + RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_rid); + ERR_FAIL_COND_V(!occluder,true); + + if (occluder->polygon.is_valid()) { + + LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get(occluder->polygon); + if (occluder_poly) { + occluder_poly->owners.erase(occluder); + } + + } + + if (occluder->canvas.is_valid() && canvas_owner.owns(occluder->canvas)) { + + Canvas *canvas = canvas_owner.get(occluder->canvas); + canvas->occluders.erase(occluder); + + } + + canvas_light_occluder_owner.free( p_rid ); + memdelete(occluder); + + } else if (canvas_light_occluder_polygon_owner.owns(p_rid)) { + + LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get(p_rid); + ERR_FAIL_COND_V(!occluder_poly,true); + VSG::storage->free(occluder_poly->occluder); + + while(occluder_poly->owners.size()) { + + occluder_poly->owners.front()->get()->polygon=RID(); + occluder_poly->owners.erase( occluder_poly->owners.front() ); + } + + canvas_light_occluder_polygon_owner.free( p_rid ); + memdelete(occluder_poly); + } else { + return false; + } + + return true; +} + + + +VisualServerCanvas::VisualServerCanvas() +{ + +} diff --git a/servers/visual/visual_server_canvas.h b/servers/visual/visual_server_canvas.h new file mode 100644 index 0000000000..035c48d9ef --- /dev/null +++ b/servers/visual/visual_server_canvas.h @@ -0,0 +1,217 @@ +#ifndef VISUALSERVERCANVAS_H +#define VISUALSERVERCANVAS_H + +#include "rasterizer.h" +#include "visual_server_viewport.h" + +class VisualServerCanvas { +public: + + + struct Item : public RasterizerCanvas::Item { + + + RID parent; // canvas it belongs to + List<Item*>::Element *E; + int z; + bool z_relative; + bool sort_y; + Color modulate; + Color self_modulate; + bool use_parent_material; + int index; + bool children_order_dirty; + + + Vector<Item*> child_items; + + + Item() { + children_order_dirty=true; + E=NULL; + z=0; + modulate=Color(1,1,1,1); + self_modulate=Color(1,1,1,1); + sort_y=false; + use_parent_material=false; + z_relative=true; + index=0; + } + }; + + + struct ItemPtrSort { + + _FORCE_INLINE_ bool operator()(const Item* p_left,const Item* p_right) const { + + if(Math::abs(p_left->xform.elements[2].y - p_right->xform.elements[2].y) < CMP_EPSILON ) + return p_left->xform.elements[2].x < p_right->xform.elements[2].x; + else + return p_left->xform.elements[2].y < p_right->xform.elements[2].y; + } + }; + + struct LightOccluderPolygon : RID_Data { + + bool active; + Rect2 aabb; + VS::CanvasOccluderPolygonCullMode cull_mode; + RID occluder; + Set<RasterizerCanvas::LightOccluderInstance*> owners; + + LightOccluderPolygon() { active=false; cull_mode=VS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED; } + }; + + + RID_Owner<LightOccluderPolygon> canvas_light_occluder_polygon_owner; + + RID_Owner<RasterizerCanvas::LightOccluderInstance> canvas_light_occluder_owner; + + struct Canvas : public VisualServerViewport::CanvasBase { + + Set<RID> viewports; + struct ChildItem { + + Point2 mirror; + Item *item; + bool operator<(const ChildItem& p_item) const { + return item->index < p_item.item->index; + } + }; + + + + Set<RasterizerCanvas::Light*> lights; + + Set<RasterizerCanvas::LightOccluderInstance*> occluders; + + bool children_order_dirty; + Vector<ChildItem> child_items; + Color modulate; + + int find_item(Item *p_item) { + for(int i=0;i<child_items.size();i++) { + if (child_items[i].item==p_item) + return i; + } + return -1; + } + void erase_item(Item *p_item) { + int idx=find_item(p_item); + if (idx>=0) + child_items.remove(idx); + } + + + Canvas() { modulate=Color(1,1,1,1); children_order_dirty=true; } + + }; + + + RID_Owner<Canvas> canvas_owner; + RID_Owner<Item> canvas_item_owner; + RID_Owner<RasterizerCanvas::Light> canvas_light_owner; + +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); +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); + + + RID canvas_item_create(); + void canvas_item_set_parent(RID p_item,RID p_parent); + + void canvas_item_set_visible(RID p_item,bool p_visible); + void canvas_item_set_light_mask(RID p_item,int p_mask); + + void canvas_item_set_transform(RID p_item, const Transform2D& p_transform); + void canvas_item_set_clip(RID p_item, bool p_clip); + void canvas_item_set_distance_field_mode(RID p_item, bool p_enable); + void canvas_item_set_custom_rect(RID p_item, bool p_custom_rect,const Rect2& p_rect=Rect2()); + void canvas_item_set_modulate(RID p_item, const Color& p_color); + void canvas_item_set_self_modulate(RID p_item, const Color& p_color); + + void canvas_item_set_draw_behind_parent(RID p_item, bool p_enable); + + + void canvas_item_add_line(RID p_item, const Point2& p_from, const Point2& p_to,const Color& p_color,float p_width=1.0,bool p_antialiased=false); + void canvas_item_add_rect(RID p_item, const Rect2& p_rect, const Color& p_color); + void canvas_item_add_circle(RID p_item, const Point2& p_pos, float p_radius,const Color& p_color); + void canvas_item_add_texture_rect(RID p_item, const Rect2& p_rect, RID p_texture,bool p_tile=false,const Color& p_modulate=Color(1,1,1),bool p_transpose=false); + void canvas_item_add_texture_rect_region(RID p_item, const Rect2& p_rect, RID p_texture,const Rect2& p_src_rect,const Color& p_modulate=Color(1,1,1),bool p_transpose=false); + void canvas_item_add_nine_patch(RID p_item, const Rect2& p_rect, const Rect2& p_source, RID p_texture,const Vector2& p_topleft, const Vector2& p_bottomright,VS::NinePatchAxisMode p_x_axis_mode=VS::NINE_PATCH_STRETCH, VS::NinePatchAxisMode p_y_axis_mode=VS::NINE_PATCH_STRETCH,bool p_draw_center=true,const Color& p_modulate=Color(1,1,1)); + 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); + 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()); + 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>(), RID p_texture=RID(), int p_count=-1); + void canvas_item_add_mesh(RID p_item, const RID& p_mesh,RID p_skeleton=RID()); + void canvas_item_add_multimesh(RID p_item, RID p_mesh,RID p_skeleton=RID()); + void canvas_item_add_set_transform(RID p_item,const Transform2D& p_transform); + void canvas_item_add_clip_ignore(RID p_item, bool p_ignore); + void canvas_item_set_sort_children_by_y(RID p_item, bool p_enable); + void canvas_item_set_z(RID p_item, int p_z); + void canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable); + void canvas_item_set_copy_to_backbuffer(RID p_item, bool p_enable,const Rect2& p_rect); + + void canvas_item_clear(RID p_item); + void canvas_item_set_draw_index(RID p_item, int p_index); + + void canvas_item_set_material(RID p_item, RID p_material); + + void canvas_item_set_use_parent_material(RID p_item, bool p_enable); + + RID canvas_light_create(); + void canvas_light_attach_to_canvas(RID p_light,RID p_canvas); + void canvas_light_set_enabled(RID p_light, bool p_enabled); + void canvas_light_set_scale(RID p_light, float p_scale); + void canvas_light_set_transform(RID p_light, const Transform2D& p_transform); + void canvas_light_set_texture(RID p_light, RID p_texture); + void canvas_light_set_texture_offset(RID p_light, const Vector2& p_offset); + void canvas_light_set_color(RID p_light, const Color& p_color); + void canvas_light_set_height(RID p_light, float p_height); + void canvas_light_set_energy(RID p_light, float p_energy); + void canvas_light_set_z_range(RID p_light, int p_min_z,int p_max_z); + void canvas_light_set_layer_range(RID p_light, int p_min_layer,int p_max_layer); + void canvas_light_set_item_cull_mask(RID p_light, int p_mask); + void canvas_light_set_item_shadow_cull_mask(RID p_light, int p_mask); + + void canvas_light_set_mode(RID p_light, VS::CanvasLightMode p_mode); + + + void canvas_light_set_shadow_enabled(RID p_light, bool p_enabled); + void canvas_light_set_shadow_buffer_size(RID p_light, int p_size); + void canvas_light_set_shadow_gradient_length(RID p_light, float p_length); + void canvas_light_set_shadow_filter(RID p_light, VS::CanvasLightShadowFilter p_filter); + void canvas_light_set_shadow_color(RID p_light, const Color& p_color); + + + + RID canvas_light_occluder_create(); + void canvas_light_occluder_attach_to_canvas(RID p_occluder,RID p_canvas); + void canvas_light_occluder_set_enabled(RID p_occluder,bool p_enabled); + void canvas_light_occluder_set_polygon(RID p_occluder,RID p_polygon); + void canvas_light_occluder_set_transform(RID p_occluder,const Transform2D& p_xform); + void canvas_light_occluder_set_light_mask(RID p_occluder,int p_mask); + + RID canvas_occluder_polygon_create(); + void canvas_occluder_polygon_set_shape(RID p_occluder_polygon,const PoolVector<Vector2>& p_shape,bool p_closed); + void canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon,const PoolVector<Vector2>& p_shape); + + + void canvas_occluder_polygon_set_cull_mode(RID p_occluder_polygon,VS::CanvasOccluderPolygonCullMode p_mode); + + + bool free(RID p_rid); + VisualServerCanvas(); + + +}; + +#endif // VISUALSERVERCANVAS_H diff --git a/servers/visual/visual_server_global.cpp b/servers/visual/visual_server_global.cpp new file mode 100644 index 0000000000..32b9710f42 --- /dev/null +++ b/servers/visual/visual_server_global.cpp @@ -0,0 +1,10 @@ +#include "visual_server_global.h" + +RasterizerStorage *VisualServerGlobals::storage=NULL; +RasterizerCanvas *VisualServerGlobals::canvas_render=NULL; +RasterizerScene *VisualServerGlobals::scene_render=NULL; +Rasterizer *VisualServerGlobals::rasterizer=NULL; + +VisualServerCanvas *VisualServerGlobals::canvas=NULL; +VisualServerViewport *VisualServerGlobals::viewport=NULL; +VisualServerScene *VisualServerGlobals::scene=NULL; diff --git a/servers/visual/visual_server_global.h b/servers/visual/visual_server_global.h new file mode 100644 index 0000000000..d413334ac4 --- /dev/null +++ b/servers/visual/visual_server_global.h @@ -0,0 +1,26 @@ +#ifndef VISUALSERVERGLOBAL_H +#define VISUALSERVERGLOBAL_H + +#include "rasterizer.h" + +class VisualServerCanvas; +class VisualServerViewport; +class VisualServerScene; + +class VisualServerGlobals +{ +public: + + static RasterizerStorage *storage; + static RasterizerCanvas *canvas_render; + static RasterizerScene *scene_render; + static Rasterizer *rasterizer; + + static VisualServerCanvas *canvas; + static VisualServerViewport *viewport; + static VisualServerScene *scene; +}; + +#define VSG VisualServerGlobals + +#endif // VISUALSERVERGLOBAL_H diff --git a/servers/visual/visual_server_light_baker.cpp b/servers/visual/visual_server_light_baker.cpp new file mode 100644 index 0000000000..4956d78ab0 --- /dev/null +++ b/servers/visual/visual_server_light_baker.cpp @@ -0,0 +1,6 @@ +#include "visual_server_light_baker.h" + +VisualServerLightBaker::VisualServerLightBaker() +{ + +} diff --git a/servers/visual/visual_server_light_baker.h b/servers/visual/visual_server_light_baker.h new file mode 100644 index 0000000000..42f016f614 --- /dev/null +++ b/servers/visual/visual_server_light_baker.h @@ -0,0 +1,29 @@ +#ifndef VISUALSERVERLIGHTBAKER_H +#define VISUALSERVERLIGHTBAKER_H + +#include "servers/visual_server.h" + +class VisualServerLightBaker { +public: + + struct BakeCell { + + uint32_t cells[8]; + uint32_t neighbours[7]; //one unused + uint32_t albedo; //albedo in RGBE + uint32_t emission; //emissive light in RGBE + uint32_t light[4]; //accumulated light in 16:16 fixed point (needs to be integer for moving lights fast) + float alpha; //used for upsampling + uint32_t directional_pass; //used for baking directional + + }; + + + + + + + VisualServerLightBaker(); +}; + +#endif // VISUALSERVERLIGHTBAKER_H diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp index f7614ac080..3a5ffda8f5 100644 --- a/servers/visual/visual_server_raster.cpp +++ b/servers/visual/visual_server_raster.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -28,18 +28,169 @@ /*************************************************************************/ #include "visual_server_raster.h" #include "os/os.h" -#include "globals.h" +#include "global_config.h" #include "default_mouse_cursor.xpm" #include "sort.h" #include "io/marshalls.h" +#include "visual_server_canvas.h" +#include "visual_server_global.h" +#include "visual_server_scene.h" + // careful, these may run in different threads than the visual server + + + +/* CURSOR */ +void VisualServerRaster::cursor_set_rotation(float p_rotation, int p_cursor ){ + +} +void VisualServerRaster::cursor_set_texture(RID p_texture, const Point2 &p_center_offset, int p_cursor, const Rect2 &p_region){ + +} +void VisualServerRaster::cursor_set_visible(bool p_visible, int p_cursor ){ + +} +void VisualServerRaster::cursor_set_pos(const Point2& p_pos, int p_cursor ){ + +} + +/* BLACK BARS */ + + +void VisualServerRaster::black_bars_set_margins(int p_left, int p_top, int p_right, int p_bottom){ + +} +void VisualServerRaster::black_bars_set_images(RID p_left, RID p_top, RID p_right, RID p_bottom){ + +} + + +/* FREE */ + +void VisualServerRaster::free( RID p_rid ){ + + if (VSG::storage->free(p_rid)) + return; + if (VSG::canvas->free(p_rid)) + return; + if (VSG::viewport->free(p_rid)) + return; + if (VSG::scene->free(p_rid)) + return; + +} + +/* EVENT QUEUING */ + +void VisualServerRaster::draw(){ + + /* + if (changes) + print_line("changes: "+itos(changes)); + */ + + changes=0; + + VSG::rasterizer->begin_frame(); + + VSG::scene->update_dirty_instances(); //update scene stuff + + VSG::viewport->draw_viewports(); + VSG::scene->render_probes(); + //_draw_cursors_and_margins(); + VSG::rasterizer->end_frame(); + //draw_extra_frame=VS:rasterizer->needs_to_draw_next_frame(); +} +void VisualServerRaster::sync(){ + +} +bool VisualServerRaster::has_changed() const{ + + return changes>0; +} +void VisualServerRaster::init(){ + + VSG::rasterizer->initialize(); + +} +void VisualServerRaster::finish(){ + + if (test_cube.is_valid()) { + free(test_cube); + } + + VSG::rasterizer->finalize(); +} + + +/* STATUS INFORMATION */ + + +int VisualServerRaster::get_render_info(RenderInfo p_info){ + + return 0; +} + + + +/* TESTING */ + + + +void VisualServerRaster::set_boot_image(const Image& p_image, const Color& p_color,bool p_scale){ + +} +void VisualServerRaster::set_default_clear_color(const Color& p_color){ + +} + +bool VisualServerRaster::has_feature(Features p_feature) const { + + return false; +} + +RID VisualServerRaster::get_test_cube() { + if (!test_cube.is_valid()) { + test_cube=_make_test_cube(); + } + return test_cube; +} + + +bool VisualServerRaster::has_os_feature(const String& p_feature) const { + + return VSG::storage->has_os_feature(p_feature); +} + +VisualServerRaster::VisualServerRaster() { + + VSG::canvas = memnew( VisualServerCanvas); + VSG::viewport = memnew( VisualServerViewport); + VSG::scene = memnew( VisualServerScene ); + VSG::rasterizer = Rasterizer::create(); + VSG::storage=VSG::rasterizer->get_storage(); + VSG::canvas_render=VSG::rasterizer->get_canvas(); + VSG::scene_render=VSG::rasterizer->get_scene(); + +} + +VisualServerRaster::~VisualServerRaster() { + + memdelete(VSG::canvas); + memdelete(VSG::viewport); + memdelete(VSG::rasterizer); +} + + +#if 0 + BalloonAllocator<> *VisualServerRaster::OctreeAllocator::allocator=NULL; #define VS_CHANGED\ changes++;\ -// print_line(__FUNCTION__); + //print_line(__FUNCTION__); @@ -265,33 +416,33 @@ RID VisualServerRaster::fixed_material_create() { return rasterizer->fixed_material_create(); } -void VisualServerRaster::fixed_material_set_flag(RID p_material, FixedMaterialFlags p_flag, bool p_enabled) { +void VisualServerRaster::fixed_material_set_flag(RID p_material, FixedSpatialMaterialFlags p_flag, bool p_enabled) { rasterizer->fixed_material_set_flag(p_material,p_flag,p_enabled); } -bool VisualServerRaster::fixed_material_get_flag(RID p_material, FixedMaterialFlags p_flag) const { +bool VisualServerRaster::fixed_material_get_flag(RID p_material, FixedSpatialMaterialFlags p_flag) const { return rasterizer->fixed_material_get_flag(p_material,p_flag); } -void VisualServerRaster::fixed_material_set_param(RID p_material, FixedMaterialParam p_parameter, const Variant& p_value) { +void VisualServerRaster::fixed_material_set_param(RID p_material, FixedSpatialMaterialParam p_parameter, const Variant& p_value) { VS_CHANGED; rasterizer->fixed_material_set_parameter(p_material,p_parameter,p_value); } -Variant VisualServerRaster::fixed_material_get_param(RID p_material,FixedMaterialParam p_parameter) const { +Variant VisualServerRaster::fixed_material_get_param(RID p_material,FixedSpatialMaterialParam p_parameter) const { return rasterizer->fixed_material_get_parameter(p_material,p_parameter); } -void VisualServerRaster::fixed_material_set_texture(RID p_material,FixedMaterialParam p_parameter, RID p_texture) { +void VisualServerRaster::fixed_material_set_texture(RID p_material,FixedSpatialMaterialParam p_parameter, RID p_texture) { VS_CHANGED; rasterizer->fixed_material_set_texture(p_material,p_parameter,p_texture); } -RID VisualServerRaster::fixed_material_get_texture(RID p_material,FixedMaterialParam p_parameter) const { +RID VisualServerRaster::fixed_material_get_texture(RID p_material,FixedSpatialMaterialParam p_parameter) const { return rasterizer->fixed_material_get_texture(p_material,p_parameter); } @@ -299,12 +450,12 @@ RID VisualServerRaster::fixed_material_get_texture(RID p_material,FixedMaterialP -void VisualServerRaster::fixed_material_set_texcoord_mode(RID p_material,FixedMaterialParam p_parameter, FixedMaterialTexCoordMode p_mode) { +void VisualServerRaster::fixed_material_set_texcoord_mode(RID p_material,FixedSpatialMaterialParam p_parameter, FixedSpatialMaterialTexCoordMode p_mode) { VS_CHANGED; rasterizer->fixed_material_set_texcoord_mode(p_material,p_parameter,p_mode); } -VS::FixedMaterialTexCoordMode VisualServerRaster::fixed_material_get_texcoord_mode(RID p_material,FixedMaterialParam p_parameter) const { +VS::FixedSpatialMaterialTexCoordMode VisualServerRaster::fixed_material_get_texcoord_mode(RID p_material,FixedSpatialMaterialParam p_parameter) const { return rasterizer->fixed_material_get_texcoord_mode(p_material,p_parameter); } @@ -331,14 +482,14 @@ Transform VisualServerRaster::fixed_material_get_uv_transform(RID p_material) co return rasterizer->fixed_material_get_uv_transform(p_material); } -void VisualServerRaster::fixed_material_set_light_shader(RID p_material,FixedMaterialLightShader p_shader) { +void VisualServerRaster::fixed_material_set_light_shader(RID p_material,FixedSpatialMaterialLightShader p_shader) { VS_CHANGED; rasterizer->fixed_material_set_light_shader(p_material,p_shader); } -VisualServerRaster::FixedMaterialLightShader VisualServerRaster::fixed_material_get_light_shader(RID p_material) const{ +VisualServerRaster::FixedSpatialMaterialLightShader VisualServerRaster::fixed_material_get_light_shader(RID p_material) const{ return rasterizer->fixed_material_get_light_shader(p_material); } @@ -677,13 +828,13 @@ Vector3 VisualServerRaster::particles_get_emission_base_velocity(RID p_particles return rasterizer->particles_get_emission_base_velocity(p_particles); } -void VisualServerRaster::particles_set_emission_points(RID p_particles, const DVector<Vector3>& p_points) { +void VisualServerRaster::particles_set_emission_points(RID p_particles, const PoolVector<Vector3>& p_points) { VS_CHANGED; rasterizer->particles_set_emission_points(p_particles,p_points); } -DVector<Vector3> VisualServerRaster::particles_get_emission_points(RID p_particles) const { +PoolVector<Vector3> VisualServerRaster::particles_get_emission_points(RID p_particles) const { return rasterizer->particles_get_emission_points(p_particles); } @@ -1137,7 +1288,7 @@ float VisualServerRaster::baked_light_get_lightmap_multiplier(RID p_baked_light) } -void VisualServerRaster::baked_light_set_octree(RID p_baked_light,const DVector<uint8_t> p_octree){ +void VisualServerRaster::baked_light_set_octree(RID p_baked_light,const PoolVector<uint8_t> p_octree){ VS_CHANGED; BakedLight *baked_light = baked_light_owner.get(p_baked_light); @@ -1146,7 +1297,7 @@ void VisualServerRaster::baked_light_set_octree(RID p_baked_light,const DVector< if (p_octree.size()==0) { if (baked_light->data.octree_texture.is_valid()) rasterizer->free(baked_light->data.octree_texture); - baked_light->data.octree_texture=RID(); + baked_light->data.octree_texture; baked_light->octree_aabb=AABB(); baked_light->octree_tex_size=Size2(); } else { @@ -1159,7 +1310,7 @@ void VisualServerRaster::baked_light_set_octree(RID p_baked_light,const DVector< bool has_light_tex=false; { - DVector<uint8_t>::Read r=p_octree.read(); + PoolVector<uint8_t>::Read r=p_octree.read(); tex_w = decode_uint32(&r[0]); tex_h = decode_uint32(&r[4]); print_line("TEX W: "+itos(tex_w)+" TEX H:"+itos(tex_h)+" LEN: "+itos(p_octree.size())); @@ -1203,7 +1354,7 @@ void VisualServerRaster::baked_light_set_octree(RID p_baked_light,const DVector< if (tex_w!=baked_light->octree_tex_size.x || tex_h!=baked_light->octree_tex_size.y) { rasterizer->free(baked_light->data.octree_texture); - baked_light->data.octree_texture=RID(); + baked_light->data.octree_texture; baked_light->octree_tex_size.x=0; baked_light->octree_tex_size.y=0; } @@ -1212,7 +1363,7 @@ void VisualServerRaster::baked_light_set_octree(RID p_baked_light,const DVector< if (baked_light->data.light_texture.is_valid()) { if (!has_light_tex || light_tex_w!=baked_light->light_tex_size.x || light_tex_h!=baked_light->light_tex_size.y) { rasterizer->free(baked_light->data.light_texture); - baked_light->data.light_texture=RID(); + baked_light->data.light_texture; baked_light->light_tex_size.x=0; baked_light->light_tex_size.y=0; } @@ -1220,20 +1371,20 @@ void VisualServerRaster::baked_light_set_octree(RID p_baked_light,const DVector< if (!baked_light->data.octree_texture.is_valid()) { baked_light->data.octree_texture=rasterizer->texture_create(); - rasterizer->texture_allocate(baked_light->data.octree_texture,tex_w,tex_h,Image::FORMAT_RGBA,TEXTURE_FLAG_FILTER); + rasterizer->texture_allocate(baked_light->data.octree_texture,tex_w,tex_h,Image::FORMAT_RGBA8,TEXTURE_FLAG_FILTER); baked_light->octree_tex_size.x=tex_w; baked_light->octree_tex_size.y=tex_h; } if (!baked_light->data.light_texture.is_valid() && has_light_tex) { baked_light->data.light_texture=rasterizer->texture_create(); - rasterizer->texture_allocate(baked_light->data.light_texture,light_tex_w,light_tex_h,Image::FORMAT_RGBA,TEXTURE_FLAG_FILTER); + rasterizer->texture_allocate(baked_light->data.light_texture,light_tex_w,light_tex_h,Image::FORMAT_RGBA8,TEXTURE_FLAG_FILTER); baked_light->light_tex_size.x=light_tex_w; baked_light->light_tex_size.y=light_tex_h; } - Image img(tex_w,tex_h,0,Image::FORMAT_RGBA,p_octree); + Image img(tex_w,tex_h,0,Image::FORMAT_RGBA8,p_octree); rasterizer->texture_set_data(baked_light->data.octree_texture,img); } @@ -1244,22 +1395,22 @@ void VisualServerRaster::baked_light_set_octree(RID p_baked_light,const DVector< } -DVector<uint8_t> VisualServerRaster::baked_light_get_octree(RID p_baked_light) const{ +PoolVector<uint8_t> VisualServerRaster::baked_light_get_octree(RID p_baked_light) const{ BakedLight *baked_light = baked_light_owner.get(p_baked_light); - ERR_FAIL_COND_V(!baked_light,DVector<uint8_t>()); + ERR_FAIL_COND_V(!baked_light,PoolVector<uint8_t>()); if (rasterizer->is_texture(baked_light->data.octree_texture)) { Image img = rasterizer->texture_get_data(baked_light->data.octree_texture); return img.get_data(); } else { - return DVector<uint8_t>(); + return PoolVector<uint8_t>(); } } -void VisualServerRaster::baked_light_set_light(RID p_baked_light,const DVector<uint8_t> p_light) { +void VisualServerRaster::baked_light_set_light(RID p_baked_light,const PoolVector<uint8_t> p_light) { VS_CHANGED; BakedLight *baked_light = baked_light_owner.get(p_baked_light); @@ -1276,30 +1427,30 @@ void VisualServerRaster::baked_light_set_light(RID p_baked_light,const DVector<u print_line("w: "+itos(tex_w)+" h: "+itos(tex_h)+" lightsize: "+itos(p_light.size())); - Image img(tex_w,tex_h,0,Image::FORMAT_RGBA,p_light); + Image img(tex_w,tex_h,0,Image::FORMAT_RGBA8,p_light); rasterizer->texture_set_data(baked_light->data.light_texture,img); } -DVector<uint8_t> VisualServerRaster::baked_light_get_light(RID p_baked_light) const{ +PoolVector<uint8_t> VisualServerRaster::baked_light_get_light(RID p_baked_light) const{ BakedLight *baked_light = baked_light_owner.get(p_baked_light); - ERR_FAIL_COND_V(!baked_light,DVector<uint8_t>()); + ERR_FAIL_COND_V(!baked_light,PoolVector<uint8_t>()); if (rasterizer->is_texture(baked_light->data.light_texture)) { Image img = rasterizer->texture_get_data(baked_light->data.light_texture); return img.get_data(); } else { - return DVector<uint8_t>(); + return PoolVector<uint8_t>(); } } -void VisualServerRaster::baked_light_set_sampler_octree(RID p_baked_light, const DVector<int> &p_sampler) { +void VisualServerRaster::baked_light_set_sampler_octree(RID p_baked_light, const PoolVector<int> &p_sampler) { BakedLight *baked_light = baked_light_owner.get(p_baked_light); ERR_FAIL_COND(!baked_light); @@ -1310,10 +1461,10 @@ void VisualServerRaster::baked_light_set_sampler_octree(RID p_baked_light, const } -DVector<int> VisualServerRaster::baked_light_get_sampler_octree(RID p_baked_light) const { +PoolVector<int> VisualServerRaster::baked_light_get_sampler_octree(RID p_baked_light) const { BakedLight *baked_light = baked_light_owner.get(p_baked_light); - ERR_FAIL_COND_V(!baked_light,DVector<int>()); + ERR_FAIL_COND_V(!baked_light,PoolVector<int>()); return baked_light->sampler; @@ -1611,8 +1762,8 @@ void VisualServerRaster::viewport_set_as_render_target(RID p_viewport,bool p_ena if (!p_enable) { rasterizer->free(viewport->render_target); - viewport->render_target=RID(); - viewport->render_target_texture=RID(); + viewport->render_target; + viewport->render_target_texture; if (viewport->update_list.in_list()) viewport_update_list.remove(&viewport->update_list); @@ -1811,7 +1962,7 @@ void VisualServerRaster::viewport_attach_camera(RID p_viewport,RID p_camera) { // a camera viewport->camera=p_camera; } else { - viewport->camera=RID(); + viewport->camera; } } @@ -1830,7 +1981,7 @@ void VisualServerRaster::viewport_set_scenario(RID p_viewport,RID p_scenario) { // a camera viewport->scenario=p_scenario; } else { - viewport->scenario=RID(); + viewport->scenario; } } @@ -2284,7 +2435,7 @@ void VisualServerRaster::instance_set_base(RID p_instance, RID p_base) { instance->base_type=INSTANCE_NONE; - instance->base_rid=RID(); + instance->base_rid; if (p_base.is_valid()) { @@ -2786,7 +2937,7 @@ void VisualServerRaster::instance_geometry_set_flag(RID p_instance,InstanceFlags Instance *instance = instance_owner.get( p_instance ); ERR_FAIL_COND( !instance ); -// ERR_FAIL_COND( ! ( (1<<instance->base_type) & INSTANCE_GEOMETRY_MASK) ); + //ERR_FAIL_COND( ! ( (1<<instance->base_type) & INSTANCE_GEOMETRY_MASK) ); switch(p_flags) { @@ -2838,7 +2989,7 @@ bool VisualServerRaster::instance_geometry_get_flag(RID p_instance,InstanceFlags const Instance *instance = instance_owner.get( p_instance ); ERR_FAIL_COND_V( !instance, false ); -// ERR_FAIL_COND_V( ! ( (1<<instance->base_type) & INSTANCE_GEOMETRY_MASK), false ); + //ERR_FAIL_COND_V( ! ( (1<<instance->base_type) & INSTANCE_GEOMETRY_MASK), false ); switch(p_flags) { @@ -3003,7 +3154,7 @@ void VisualServerRaster::instance_geometry_set_baked_light_sampler(RID p_instanc if (instance->sampled_light) { instance->sampled_light->baked_light_sampler_info->owned_instances.erase(instance); - instance->data.sampled_light=RID(); + instance->data.sampled_light; } if(p_baked_light_sampler.is_valid()) { @@ -3016,7 +3167,7 @@ void VisualServerRaster::instance_geometry_set_baked_light_sampler(RID p_instanc instance->sampled_light=NULL; } - instance->data.sampled_light=RID(); + instance->data.sampled_light; } @@ -3193,8 +3344,10 @@ void VisualServerRaster::_update_instance(Instance *p_instance) { } else { - // if (new_aabb==p_instance->data.transformed_aabb) - // return; + /* + if (new_aabb==p_instance->data.transformed_aabb) + return; + */ p_instance->scenario->octree.move(p_instance->octree_id,new_aabb); } @@ -3432,7 +3585,7 @@ void VisualServerRaster::canvas_item_set_parent(RID p_item,RID p_parent) { item_owner->child_items.erase(canvas_item); } - canvas_item->parent=RID(); + canvas_item->parent; } @@ -4057,7 +4210,7 @@ void VisualServerRaster::canvas_light_attach_to_canvas(RID p_light,RID p_canvas) } if (!canvas_owner.owns(p_canvas)) - p_canvas=RID(); + p_canvas; clight->canvas=p_canvas; if (clight->canvas.is_valid()) { @@ -4184,7 +4337,7 @@ void VisualServerRaster::canvas_light_set_shadow_enabled(RID p_light, bool p_ena clight->shadow_buffer=rasterizer->canvas_light_shadow_buffer_create(clight->shadow_buffer_size); } else { rasterizer->free(clight->shadow_buffer); - clight->shadow_buffer=RID(); + clight->shadow_buffer; } @@ -4246,7 +4399,7 @@ void VisualServerRaster::canvas_light_occluder_attach_to_canvas(RID p_occluder,R } if (!canvas_owner.owns(p_canvas)) - p_canvas=RID(); + p_canvas; occluder->canvas=p_canvas; @@ -4279,12 +4432,12 @@ void VisualServerRaster::canvas_light_occluder_set_polygon(RID p_occluder,RID p_ } occluder->polygon=p_polygon; - occluder->polygon_buffer=RID(); + occluder->polygon_buffer; if (occluder->polygon.is_valid()) { CanvasLightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get(p_polygon); if (!occluder_poly) - occluder->polygon=RID(); + occluder->polygon; ERR_FAIL_COND(!occluder_poly); occluder_poly->owners.insert(occluder); occluder->polygon_buffer=occluder_poly->occluder; @@ -4324,20 +4477,20 @@ RID VisualServerRaster::canvas_occluder_polygon_create() { } -void VisualServerRaster::canvas_occluder_polygon_set_shape(RID p_occluder_polygon, const DVector<Vector2>& p_shape, bool p_close){ +void VisualServerRaster::canvas_occluder_polygon_set_shape(RID p_occluder_polygon, const PoolVector<Vector2>& p_shape, bool p_close){ if (p_shape.size()<3) { canvas_occluder_polygon_set_shape_as_lines(p_occluder_polygon,p_shape); return; } - DVector<Vector2> lines; + PoolVector<Vector2> lines; int lc = p_shape.size()*2; lines.resize(lc-(p_close?0:2)); { - DVector<Vector2>::Write w = lines.write(); - DVector<Vector2>::Read r = p_shape.read(); + PoolVector<Vector2>::Write w = lines.write(); + PoolVector<Vector2>::Read r = p_shape.read(); int max=lc/2; if (!p_close) { @@ -4356,7 +4509,7 @@ void VisualServerRaster::canvas_occluder_polygon_set_shape(RID p_occluder_polygo canvas_occluder_polygon_set_shape_as_lines(p_occluder_polygon,lines); } -void VisualServerRaster::canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon,const DVector<Vector2>& p_shape) { +void VisualServerRaster::canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon,const PoolVector<Vector2>& p_shape) { CanvasLightOccluderPolygon * occluder_poly = canvas_light_occluder_polygon_owner.get(p_occluder_polygon); ERR_FAIL_COND(!occluder_poly); @@ -4365,7 +4518,7 @@ void VisualServerRaster::canvas_occluder_polygon_set_shape_as_lines(RID p_occlud int lc = p_shape.size(); occluder_poly->aabb=Rect2(); { - DVector<Vector2>::Read r = p_shape.read(); + PoolVector<Vector2>::Read r = p_shape.read(); for(int i=0;i<lc;i++) { if (i==0) occluder_poly->aabb.pos=r[i]; @@ -4514,7 +4667,7 @@ void VisualServerRaster::_free_attached_instances(RID p_rid,bool p_free_scenario void VisualServerRaster::custom_shade_model_set_shader(int p_model, RID p_shader) { VS_CHANGED; -// rasterizer->custom_shade_model_set_shader(p_model,p_shader); + //rasterizer->custom_shade_model_set_shader(p_model,p_shader); } RID VisualServerRaster::custom_shade_model_get_shader(int p_model) const { @@ -4558,7 +4711,7 @@ void VisualServerRaster::free( RID p_rid ) { //detach skeletons for (Set<Instance*>::Element *F=E->get().front();F;F=F->next()) { - F->get()->data.skeleton=RID(); + F->get()->data.skeleton; } skeleton_dependency_map.erase(E); } @@ -4604,8 +4757,10 @@ void VisualServerRaster::free( RID p_rid ) { BakedLightSampler *baked_light_sampler = baked_light_sampler_owner.get(p_rid); ERR_FAIL_COND(!baked_light_sampler); - //if (baked_light->data.octree_texture.is_valid()) - // rasterizer->free(baked_light->data.octree_texture); + /* + if (baked_light->data.octree_texture.is_valid()) + rasterizer->free(baked_light->data.octree_texture); + */ baked_light_sampler_owner.free(p_rid); memdelete(baked_light_sampler); @@ -4624,7 +4779,7 @@ void VisualServerRaster::free( RID p_rid ) { Viewport *viewport = viewport_owner.get( p_rid ); ERR_FAIL_COND(!viewport); -// Viewport *parent=NULL; + //Viewport *parent=NULL; rasterizer->free(viewport->viewport_data); if (viewport->render_target.is_valid()) { @@ -4688,17 +4843,17 @@ void VisualServerRaster::free( RID p_rid ) { for (int i=0;i<canvas->child_items.size();i++) { - canvas->child_items[i].item->parent=RID(); + canvas->child_items[i].item->parent; } for (Set<Rasterizer::CanvasLight*>::Element *E=canvas->lights.front();E;E=E->next()) { - E->get()->canvas=RID(); + E->get()->canvas; } for (Set<Rasterizer::CanvasLightOccluderInstance*>::Element *E=canvas->occluders.front();E;E=E->next()) { - E->get()->canvas=RID(); + E->get()->canvas; } canvas_owner.free( p_rid ); @@ -4726,7 +4881,7 @@ void VisualServerRaster::free( RID p_rid ) { for (int i=0;i<canvas_item->child_items.size();i++) { - canvas_item->child_items[i]->parent=RID(); + canvas_item->child_items[i]->parent; } if (canvas_item->material) { @@ -4798,7 +4953,7 @@ void VisualServerRaster::free( RID p_rid ) { while(occluder_poly->owners.size()) { - occluder_poly->owners.front()->get()->polygon=RID(); + occluder_poly->owners.front()->get()->polygon; occluder_poly->owners.erase( occluder_poly->owners.front() ); } @@ -4963,7 +5118,7 @@ void VisualServerRaster::_light_instance_update_pssm_shadow(Instance *p_light,Sc float distances[5]; float texsize=rasterizer->light_instance_get_shadow_size( p_light->light_info->instance ); -// float cull_min=p_cull_range.min; + //float cull_min=p_cull_range.min; //float cull_max=p_cull_range.max; @@ -6196,7 +6351,7 @@ void VisualServerRaster::_process_sampled_light(const Transform& p_camera,Instan AABB sample_aabb= bl->data.transform.affine_inverse().xform(AABB(Vector3(-r,-r,-r)+p_sampled_light->data.transform.origin,Vector3(r*2,r*2,r*2))); //ok got octree local AABB - DVector<int>::Read rp = bl->baked_light_info->baked_light->sampler.read(); + PoolVector<int>::Read rp = bl->baked_light_info->baked_light->sampler.read(); const int *rptr = rp.ptr(); int first = rptr[1]; @@ -6417,7 +6572,7 @@ void VisualServerRaster::_process_sampled_light(const Transform& p_camera,Instan for(Set<Instance*>::Element *F=p_sampled_light->baked_light_sampler_info->owned_instances.front();F;F=F->next()) { - F->get()->data.sampled_light=RID(); //do not use because nothing close + F->get()->data.sampled_light; //do not use because nothing close } } @@ -6515,7 +6670,7 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S /* print_line("OT: "+rtos( (OS::get_singleton()->get_ticks_usec()-t)/1000.0)); print_line("OTO: "+itos(p_scenario->octree.get_octant_count())); -// print_line("OTE: "+itos(p_scenario->octree.get_elem_count())); + //print_line("OTE: "+itos(p_scenario->octree.get_elem_count())); print_line("OTP: "+itos(p_scenario->octree.get_pair_count())); */ @@ -6619,7 +6774,7 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S if (light_cull_count<MAX_LIGHTS_CULLED) { light_cull_result[light_cull_count++]=ins; -// rasterizer->light_instance_set_active_hint(ins->light_info->instance); + //rasterizer->light_instance_set_active_hint(ins->light_info->instance); { //compute distance to camera using aabb support Vector3 n = ins->data.transform.basis.xform_inv(cull_range.nearp.normal).normalized(); @@ -7142,7 +7297,7 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_ ViewportRect desired_rect=p_viewport->rect; ViewportRect old_rect = viewport_rect; -// bool vpchanged=false; + //bool vpchanged=false; // convert default expanding viewports to actual size //if (desired_rect.x==0 && desired_rect.y==0 && desired_rect.width==0 && desired_rect.height==0) { if (p_parent_w != 0 && p_parent_h != 0) { @@ -7334,7 +7489,7 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_ for (Map<Viewport::CanvasKey,Viewport::CanvasData*>::Element *E=canvas_map.front();E;E=E->next()) { - // print_line("canvas "+itos(i)+" size: "+itos(I->get()->canvas->child_items.size())); + //print_line("canvas "+itos(i)+" size: "+itos(I->get()->canvas->child_items.size())); //print_line("GT "+p_viewport->global_transform+". CT: "+E->get()->transform); Matrix32 xform = p_viewport->global_transform * E->get()->transform; @@ -7366,7 +7521,7 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_ } -// rasterizer->canvas_debug_viewport_shadows(lights_with_shadow); + //rasterizer->canvas_debug_viewport_shadows(lights_with_shadow); } //capture @@ -7534,10 +7689,10 @@ void VisualServerRaster::_draw_cursors_and_margins() { ERR_CONTINUE( !tex ); if (cursors[i].region.has_no_area()) { Point2 size(texture_get_width(tex), texture_get_height(tex)); - rasterizer->canvas_draw_rect(Rect2(cursors[i].pos, size), 0, Rect2(), tex, Color(1, 1, 1, 1)); + rasterizer->canvas_draw_rect(Rect2(cursors[i].pos-cursors[i].center, size), 0, Rect2(), tex, Color(1, 1, 1, 1)); } else { Point2 size = cursors[i].region.size; - rasterizer->canvas_draw_rect(Rect2(cursors[i].pos, size), Rasterizer::CANVAS_RECT_REGION, cursors[i].region, tex, Color(1, 1, 1, 1)); + rasterizer->canvas_draw_rect(Rect2(cursors[i].pos-cursors[i].center, size), Rasterizer::CANVAS_RECT_REGION, cursors[i].region, tex, Color(1, 1, 1, 1)); } }; @@ -7579,8 +7734,10 @@ void VisualServerRaster::sync() { } void VisualServerRaster::draw() { - //if (changes) - // print_line("changes: "+itos(changes)); + /* + if (changes) + print_line("changes: "+itos(changes)); + */ changes=0; shadows_enabled=GLOBAL_DEF("render/shadows_enabled",true); room_cull_enabled = GLOBAL_DEF("render/room_cull_enabled",true); @@ -7679,7 +7836,7 @@ void VisualServerRaster::init() { Image img; img.create(default_mouse_cursor_xpm); - //img.convert(Image::FORMAT_RGB); + //img.convert(Image::FORMAT_RGB8); default_cursor_texture = texture_create_from_image(img, 0); aabb_random_points.resize( GLOBAL_DEF("render/aabb_random_points",16) ); @@ -7766,3 +7923,4 @@ VisualServerRaster::VisualServerRaster(Rasterizer *p_rasterizer) { VisualServerRaster::~VisualServerRaster() { } +#endif diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h index 496820f4a8..7d547e1862 100644 --- a/servers/visual/visual_server_raster.h +++ b/servers/visual/visual_server_raster.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -34,12 +34,17 @@ #include "servers/visual/rasterizer.h" #include "allocators.h" #include "octree.h" - +#include "visual_server_global.h" +#include "visual_server_viewport.h" +#include "visual_server_canvas.h" +#include "visual_server_scene.h" /** @author Juan Linietsky <reduzio@gmail.com> */ + + class VisualServerRaster : public VisualServer { @@ -57,6 +62,12 @@ class VisualServerRaster : public VisualServer { }; + int changes; + bool draw_extra_frame; + RID test_cube; + + + #if 0 struct Room { bool occlude_exterior; @@ -92,8 +103,8 @@ class VisualServerRaster : public VisualServer { struct BakedLight { Rasterizer::BakedLightData data; - DVector<int> sampler; - AABB octree_aabb; + PoolVector<int> sampler; + Rect3 octree_aabb; Size2i octree_tex_size; Size2i light_tex_size; @@ -131,7 +142,7 @@ class VisualServerRaster : public VisualServer { Transform transform; - Camera() { + Camera() { visible_layers=0xFFFFFFFF; fov=60; @@ -140,8 +151,8 @@ class VisualServerRaster : public VisualServer { size=1.0; vaspect=false; - } - }; + } + }; struct Instance; @@ -166,8 +177,8 @@ class VisualServerRaster : public VisualServer { RID base_rid; - AABB aabb; - AABB transformed_aabb; + Rect3 aabb; + Rect3 transformed_aabb; uint32_t object_ID; bool visible; bool visible_in_all_rooms; @@ -374,97 +385,6 @@ class VisualServerRaster : public VisualServer { mutable RID_Owner<Rasterizer::CanvasItemMaterial> canvas_item_material_owner; - struct CanvasItem : public Rasterizer::CanvasItem { - - - RID parent; // canvas it belongs to - List<CanvasItem*>::Element *E; - RID viewport; - int z; - bool z_relative; - bool sort_y; - float opacity; - float self_opacity; - bool use_parent_material; - - - Vector<CanvasItem*> child_items; - - - CanvasItem() { - E=NULL; - z=0; - opacity=1; - self_opacity=1; - sort_y=false; - use_parent_material=false; - z_relative=true; - } - }; - - - struct CanvasItemPtrSort { - - _FORCE_INLINE_ bool operator()(const CanvasItem* p_left,const CanvasItem* p_right) const { - - return p_left->xform.elements[2].y < p_right->xform.elements[2].y; - } - }; - - struct CanvasLightOccluder; - - struct CanvasLightOccluderPolygon { - - bool active; - Rect2 aabb; - CanvasOccluderPolygonCullMode cull_mode; - RID occluder; - Set<Rasterizer::CanvasLightOccluderInstance*> owners; - - CanvasLightOccluderPolygon() { active=false; cull_mode=CANVAS_OCCLUDER_POLYGON_CULL_DISABLED; } - }; - - - RID_Owner<CanvasLightOccluderPolygon> canvas_light_occluder_polygon_owner; - - RID_Owner<Rasterizer::CanvasLightOccluderInstance> canvas_light_occluder_owner; - - struct CanvasLight; - - struct Canvas { - - Set<RID> viewports; - struct ChildItem { - - Point2 mirror; - CanvasItem *item; - }; - - Set<Rasterizer::CanvasLight*> lights; - Set<Rasterizer::CanvasLightOccluderInstance*> occluders; - - Vector<ChildItem> child_items; - Color modulate; - - int find_item(CanvasItem *p_item) { - for(int i=0;i<child_items.size();i++) { - if (child_items[i].item==p_item) - return i; - } - return -1; - } - void erase_item(CanvasItem *p_item) { - int idx=find_item(p_item); - if (idx>=0) - child_items.remove(idx); - } - - Canvas() { modulate=Color(1,1,1,1); } - - }; - - - RID_Owner<Rasterizer::CanvasLight> canvas_light_owner; struct Viewport { @@ -508,11 +428,11 @@ class VisualServerRaster : public VisualServer { struct CanvasData { Canvas *canvas; - Matrix32 transform; + Transform2D transform; int layer; }; - Matrix32 global_transform; + Transform2D global_transform; Map<RID,CanvasData> canvas_map; @@ -531,7 +451,7 @@ class VisualServerRaster : public VisualServer { float min,max; float z_near,z_far; - void add_aabb(const AABB& p_aabb) { + void add_aabb(const Rect3& p_aabb) { } @@ -634,9 +554,9 @@ class VisualServerRaster : public VisualServer { void _render_no_camera(Viewport *p_viewport,Camera *p_camera, Scenario *p_scenario); void _render_camera(Viewport *p_viewport,Camera *p_camera, Scenario *p_scenario); static void _render_canvas_item_viewport(VisualServer* p_self,void *p_vp,const Rect2& p_rect); - void _render_canvas_item_tree(CanvasItem *p_canvas_item, const Matrix32& p_transform, const Rect2& p_clip_rect, const Color &p_modulate, Rasterizer::CanvasLight *p_lights); - void _render_canvas_item(CanvasItem *p_canvas_item, const Matrix32& p_transform, const Rect2& p_clip_rect, float p_opacity, int p_z, Rasterizer::CanvasItem **z_list, Rasterizer::CanvasItem **z_last_list, CanvasItem *p_canvas_clip, CanvasItem *p_material_owner); - void _render_canvas(Canvas *p_canvas, const Matrix32 &p_transform, Rasterizer::CanvasLight *p_lights, Rasterizer::CanvasLight *p_masked_lights); + void _render_canvas_item_tree(CanvasItem *p_canvas_item, const Transform2D& p_transform, const Rect2& p_clip_rect, const Color &p_modulate, Rasterizer::CanvasLight *p_lights); + void _render_canvas_item(CanvasItem *p_canvas_item, const Transform2D& p_transform, const Rect2& p_clip_rect, float p_opacity, int p_z, Rasterizer::CanvasItem **z_list, Rasterizer::CanvasItem **z_last_list, CanvasItem *p_canvas_clip, CanvasItem *p_material_owner); + void _render_canvas(Canvas *p_canvas, const Transform2D &p_transform, Rasterizer::CanvasLight *p_lights, Rasterizer::CanvasLight *p_masked_lights); void _light_mask_canvas_items(int p_z,Rasterizer::CanvasItem *p_canvas_item,Rasterizer::CanvasLight *p_masked_lights); Vector<Vector3> _camera_generate_endpoints(Instance *p_light,Camera *p_camera,float p_range_min, float p_range_max); @@ -658,635 +578,595 @@ class VisualServerRaster : public VisualServer { Rasterizer *rasterizer; -public: - virtual RID texture_create(); - virtual void texture_allocate(RID p_texture,int p_width, int p_height,Image::Format p_format,uint32_t p_flags=TEXTURE_FLAGS_DEFAULT); - virtual void texture_set_data(RID p_texture,const Image& p_image,CubeMapSide p_cube_side=CUBEMAP_LEFT); - virtual Image texture_get_data(RID p_texture,CubeMapSide p_cube_side=CUBEMAP_LEFT) const; - virtual void texture_set_flags(RID p_texture,uint32_t p_flags) ; - virtual uint32_t texture_get_flags(RID p_texture) const; - virtual Image::Format texture_get_format(RID p_texture) const; - virtual uint32_t texture_get_width(RID p_texture) const; - virtual uint32_t texture_get_height(RID p_texture) const; - virtual void texture_set_size_override(RID p_texture,int p_width, int p_height); - virtual bool texture_can_stream(RID p_texture) const; - virtual void texture_set_reload_hook(RID p_texture,ObjectID p_owner,const StringName& p_function) const; - - virtual void texture_set_path(RID p_texture,const String& p_path); - virtual String texture_get_path(RID p_texture) const; - - virtual void texture_debug_usage(List<TextureInfo> *r_info); - - virtual void texture_set_shrink_all_x2_on_set_data(bool p_enable); - - - /* SHADER API */ - - virtual RID shader_create(ShaderMode p_mode=SHADER_MATERIAL); - - virtual void shader_set_mode(RID p_shader,ShaderMode p_mode); - virtual ShaderMode shader_get_mode(RID p_shader) const; - - virtual void shader_set_code(RID p_shader, const String& p_vertex, const String& p_fragment,const String& p_light,int p_vertex_ofs=0,int p_fragment_ofs=0,int p_light_ofs=0); - virtual String shader_get_vertex_code(RID p_shader) const; - virtual String shader_get_fragment_code(RID p_shader) const; - virtual String shader_get_light_code(RID p_shader) const; - - virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const; - - virtual void shader_set_default_texture_param(RID p_shader, const StringName& p_name, RID p_texture); - virtual RID shader_get_default_texture_param(RID p_shader, const StringName& p_name) const; - - - /* COMMON MATERIAL API */ +#endif - virtual RID material_create(); +public: - virtual void material_set_shader(RID p_shader_material, RID p_shader); - virtual RID material_get_shader(RID p_shader_material) const; +#define DISPLAY_CHANGED changes++; - virtual void material_set_param(RID p_material, const StringName& p_param, const Variant& p_value); - virtual Variant material_get_param(RID p_material, const StringName& p_param) const; +#define BIND0R(m_r,m_name) m_r m_name() { return BINDBASE->m_name(); } +#define BIND1R(m_r,m_name,m_type1) m_r m_name(m_type1 arg1) { return BINDBASE->m_name(arg1); } +#define BIND1RC(m_r,m_name,m_type1) m_r m_name(m_type1 arg1) const { return BINDBASE->m_name(arg1); } +#define BIND2RC(m_r,m_name,m_type1,m_type2) m_r m_name(m_type1 arg1,m_type2 arg2) const { return BINDBASE->m_name(arg1,arg2); } +#define BIND3RC(m_r,m_name,m_type1,m_type2,m_type3) m_r m_name(m_type1 arg1,m_type2 arg2,m_type3 arg3) const { return BINDBASE->m_name(arg1,arg2,arg3); } +#define BIND4RC(m_r,m_name,m_type1,m_type2,m_type3,m_type4) m_r m_name(m_type1 arg1,m_type2 arg2,m_type3 arg3,m_type4 arg4) const { return BINDBASE->m_name(arg1,arg2,arg3,arg4); } - virtual void material_set_flag(RID p_material, MaterialFlag p_flag,bool p_enabled); - virtual bool material_get_flag(RID p_material,MaterialFlag p_flag) const; +#define BIND1(m_name,m_type1) void m_name(m_type1 arg1) { DISPLAY_CHANGED BINDBASE->m_name(arg1); } +#define BIND2(m_name,m_type1,m_type2) void m_name(m_type1 arg1,m_type2 arg2) { DISPLAY_CHANGED BINDBASE->m_name(arg1,arg2); } +#define BIND2C(m_name,m_type1,m_type2) void m_name(m_type1 arg1,m_type2 arg2) const { BINDBASE->m_name(arg1,arg2); } +#define BIND3(m_name,m_type1,m_type2,m_type3) void m_name(m_type1 arg1,m_type2 arg2,m_type3 arg3) { DISPLAY_CHANGED BINDBASE->m_name(arg1,arg2,arg3); } +#define BIND4(m_name,m_type1,m_type2,m_type3,m_type4) void m_name(m_type1 arg1,m_type2 arg2,m_type3 arg3,m_type4 arg4) { DISPLAY_CHANGED BINDBASE->m_name(arg1,arg2,arg3,arg4); } +#define BIND5(m_name,m_type1,m_type2,m_type3,m_type4,m_type5) void m_name(m_type1 arg1,m_type2 arg2,m_type3 arg3,m_type4 arg4,m_type5 arg5) { DISPLAY_CHANGED BINDBASE->m_name(arg1,arg2,arg3,arg4,arg5); } +#define BIND6(m_name,m_type1,m_type2,m_type3,m_type4,m_type5,m_type6) void m_name(m_type1 arg1,m_type2 arg2,m_type3 arg3,m_type4 arg4,m_type5 arg5,m_type6 arg6) { DISPLAY_CHANGED BINDBASE->m_name(arg1,arg2,arg3,arg4,arg5,arg6); } +#define BIND7(m_name,m_type1,m_type2,m_type3,m_type4,m_type5,m_type6,m_type7) void m_name(m_type1 arg1,m_type2 arg2,m_type3 arg3,m_type4 arg4,m_type5 arg5,m_type6 arg6,m_type7 arg7) { DISPLAY_CHANGED BINDBASE->m_name(arg1,arg2,arg3,arg4,arg5,arg6,arg7); } +#define BIND8(m_name,m_type1,m_type2,m_type3,m_type4,m_type5,m_type6,m_type7,m_type8) void m_name(m_type1 arg1,m_type2 arg2,m_type3 arg3,m_type4 arg4,m_type5 arg5,m_type6 arg6,m_type7 arg7,m_type8 arg8) { DISPLAY_CHANGED BINDBASE->m_name(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8); } +#define BIND9(m_name,m_type1,m_type2,m_type3,m_type4,m_type5,m_type6,m_type7,m_type8,m_type9) void m_name(m_type1 arg1,m_type2 arg2,m_type3 arg3,m_type4 arg4,m_type5 arg5,m_type6 arg6,m_type7 arg7,m_type8 arg8,m_type9 arg9) { DISPLAY_CHANGED BINDBASE->m_name(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9); } +#define BIND10(m_name,m_type1,m_type2,m_type3,m_type4,m_type5,m_type6,m_type7,m_type8,m_type9,m_type10) void m_name(m_type1 arg1,m_type2 arg2,m_type3 arg3,m_type4 arg4,m_type5 arg5,m_type6 arg6,m_type7 arg7,m_type8 arg8,m_type9 arg9,m_type10 arg10) { DISPLAY_CHANGED BINDBASE->m_name(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10); } - virtual void material_set_depth_draw_mode(RID p_material, MaterialDepthDrawMode p_mode); - virtual MaterialDepthDrawMode material_get_depth_draw_mode(RID p_material) const; +//from now on, calls forwarded to this singleton +#define BINDBASE VSG::storage - virtual void material_set_blend_mode(RID p_material,MaterialBlendMode p_mode); - virtual MaterialBlendMode material_get_blend_mode(RID p_material) const; + /* TEXTURE API */ - virtual void material_set_line_width(RID p_material,float p_line_width); - virtual float material_get_line_width(RID p_material) const; - /* FIXED MATERIAL */ + BIND0R(RID,texture_create) + BIND5(texture_allocate,RID,int,int,Image::Format,uint32_t) + BIND3(texture_set_data,RID,const Image&,CubeMapSide) + BIND2RC(Image,texture_get_data,RID,CubeMapSide) + BIND2(texture_set_flags,RID,uint32_t) + BIND1RC(uint32_t,texture_get_flags,RID) + BIND1RC(Image::Format,texture_get_format,RID) + BIND1RC(uint32_t,texture_get_width,RID) + BIND1RC(uint32_t,texture_get_height,RID) + BIND3(texture_set_size_override,RID,int,int) + BIND2RC(RID,texture_create_radiance_cubemap,RID,int) + BIND3(texture_set_detect_3d_callback,RID,TextureDetectCallback,void*) + BIND3(texture_set_detect_srgb_callback,RID,TextureDetectCallback,void*) - virtual RID fixed_material_create(); + BIND2(texture_set_path,RID,const String&) + BIND1RC(String,texture_get_path,RID) + BIND1(texture_set_shrink_all_x2_on_set_data,bool) + BIND1(texture_debug_usage,List<TextureInfo>*) - virtual void fixed_material_set_flag(RID p_material, FixedMaterialFlags p_flag, bool p_enabled); - virtual bool fixed_material_get_flag(RID p_material, FixedMaterialFlags p_flag) const; + BIND1(textures_keep_original,bool) - virtual void fixed_material_set_param(RID p_material, FixedMaterialParam p_parameter, const Variant& p_value); - virtual Variant fixed_material_get_param(RID p_material,FixedMaterialParam p_parameter) const; + /* SKYBOX API */ - virtual void fixed_material_set_texture(RID p_material,FixedMaterialParam p_parameter, RID p_texture); - virtual RID fixed_material_get_texture(RID p_material,FixedMaterialParam p_parameter) const; + BIND0R(RID,skybox_create) + BIND3(skybox_set_texture,RID,RID,int) - virtual void fixed_material_set_texcoord_mode(RID p_material,FixedMaterialParam p_parameter, FixedMaterialTexCoordMode p_mode); - virtual FixedMaterialTexCoordMode fixed_material_get_texcoord_mode(RID p_material,FixedMaterialParam p_parameter) const; + /* SHADER API */ + BIND1R(RID,shader_create,ShaderMode) - virtual void fixed_material_set_uv_transform(RID p_material,const Transform& p_transform); - virtual Transform fixed_material_get_uv_transform(RID p_material) const; - virtual void fixed_material_set_light_shader(RID p_material,FixedMaterialLightShader p_shader); - virtual FixedMaterialLightShader fixed_material_get_light_shader(RID p_material) const; + BIND2(shader_set_mode,RID,ShaderMode) + BIND1RC(ShaderMode,shader_get_mode,RID) - virtual void fixed_material_set_point_size(RID p_material,float p_size); - virtual float fixed_material_get_point_size(RID p_material) const; + BIND2(shader_set_code,RID,const String&) + BIND1RC(String,shader_get_code,RID) - /* SURFACE API */ - virtual RID mesh_create(); + BIND2C(shader_get_param_list,RID, List<PropertyInfo> *) - virtual void mesh_set_morph_target_count(RID p_mesh,int p_amount); - virtual int mesh_get_morph_target_count(RID p_mesh) const; + BIND3(shader_set_default_texture_param,RID,const StringName&,RID) + BIND2RC(RID,shader_get_default_texture_param,RID,const StringName&) - virtual void mesh_set_morph_target_mode(RID p_mesh,MorphTargetMode p_mode); - virtual MorphTargetMode mesh_get_morph_target_mode(RID p_mesh) const; - virtual void mesh_add_custom_surface(RID p_mesh,const Variant& p_dat); //this is used by each platform in a different way + /* COMMON MATERIAL API */ - virtual void mesh_add_surface(RID p_mesh,PrimitiveType p_primitive,const Array& p_arrays,const Array& p_blend_shapes=Array(),bool p_alpha_sort=false); - virtual Array mesh_get_surface_arrays(RID p_mesh,int p_surface) const; - virtual Array mesh_get_surface_morph_arrays(RID p_mesh,int p_surface) const; + BIND0R(RID,material_create) - virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material,bool p_owned=false); - virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const; + BIND2(material_set_shader,RID,RID) + BIND1RC(RID,material_get_shader,RID) - virtual int mesh_surface_get_array_len(RID p_mesh, int p_surface) const; - virtual int mesh_surface_get_array_index_len(RID p_mesh, int p_surface) const; - virtual uint32_t mesh_surface_get_format(RID p_mesh, int p_surface) const; - virtual PrimitiveType mesh_surface_get_primitive_type(RID p_mesh, int p_surface) const; + BIND3(material_set_param,RID, const StringName&, const Variant& ) + BIND2RC(Variant,material_get_param,RID, const StringName& ) - virtual void mesh_remove_surface(RID p_mesh,int p_index); - virtual int mesh_get_surface_count(RID p_mesh) const; + BIND2(material_set_line_width,RID, float ) - virtual void mesh_set_custom_aabb(RID p_mesh,const AABB& p_aabb); - virtual AABB mesh_get_custom_aabb(RID p_mesh) const; - virtual void mesh_clear(RID p_mesh); - /* MULTIMESH API */ + /* MESH API */ - virtual RID multimesh_create(); - virtual void multimesh_set_instance_count(RID p_multimesh,int p_count); - virtual int multimesh_get_instance_count(RID p_multimesh) const; + BIND0R(RID,mesh_create) - virtual void multimesh_set_mesh(RID p_multimesh,RID p_mesh); - virtual void multimesh_set_aabb(RID p_multimesh,const AABB& p_aabb); - virtual void multimesh_instance_set_transform(RID p_multimesh,int p_index,const Transform& p_transform); - virtual void multimesh_instance_set_color(RID p_multimesh,int p_index,const Color& p_color); + BIND10(mesh_add_surface,RID,uint32_t,PrimitiveType,const PoolVector<uint8_t>&,int ,const PoolVector<uint8_t>& ,int ,const Rect3&,const Vector<PoolVector<uint8_t> >&,const Vector<Rect3>& ) - virtual RID multimesh_get_mesh(RID p_multimesh) const; - virtual AABB multimesh_get_aabb(RID p_multimesh,const AABB& p_aabb) const; - virtual Transform multimesh_instance_get_transform(RID p_multimesh,int p_index) const; - virtual Color multimesh_instance_get_color(RID p_multimesh,int p_index) const; + BIND2(mesh_set_blend_shape_count,RID,int) + BIND1RC(int,mesh_get_blend_shape_count,RID) - virtual void multimesh_set_visible_instances(RID p_multimesh,int p_visible); - virtual int multimesh_get_visible_instances(RID p_multimesh) const; - /* IMMEDIATE API */ + BIND2(mesh_set_blend_shape_mode,RID,BlendShapeMode) + BIND1RC(BlendShapeMode, mesh_get_blend_shape_mode,RID ) - virtual RID immediate_create(); - virtual void immediate_begin(RID p_immediate,PrimitiveType p_rimitive,RID p_texture=RID()); - virtual void immediate_vertex(RID p_immediate,const Vector3& p_vertex); - virtual void immediate_normal(RID p_immediate,const Vector3& p_normal); - virtual void immediate_tangent(RID p_immediate,const Plane& p_tangent); - virtual void immediate_color(RID p_immediate,const Color& p_color); - virtual void immediate_uv(RID p_immediate, const Vector2& p_uv); - virtual void immediate_uv2(RID p_immediate,const Vector2& tex_uv); - virtual void immediate_end(RID p_immediate); - virtual void immediate_clear(RID p_immediate); - virtual void immediate_set_material(RID p_immediate,RID p_material); - virtual RID immediate_get_material(RID p_immediate) const; + BIND3(mesh_surface_set_material,RID, int , RID ) + BIND2RC(RID,mesh_surface_get_material,RID, int ) + BIND2RC(int,mesh_surface_get_array_len,RID,int) + BIND2RC(int,mesh_surface_get_array_index_len,RID,int) - /* PARTICLES API */ + BIND2RC(PoolVector<uint8_t>,mesh_surface_get_array,RID,int) + BIND2RC(PoolVector<uint8_t>,mesh_surface_get_index_array,RID, int) - virtual RID particles_create(); + BIND2RC(uint32_t,mesh_surface_get_format,RID,int) + BIND2RC(PrimitiveType,mesh_surface_get_primitive_type,RID,int) - virtual void particles_set_amount(RID p_particles, int p_amount); - virtual int particles_get_amount(RID p_particles) const; + BIND2RC(Rect3,mesh_surface_get_aabb,RID,int) + BIND2RC(Vector<PoolVector<uint8_t> >,mesh_surface_get_blend_shapes,RID,int) + BIND2RC(Vector<Rect3>,mesh_surface_get_skeleton_aabb,RID,int) - virtual void particles_set_emitting(RID p_particles, bool p_emitting); - virtual bool particles_is_emitting(RID p_particles) const; + BIND2(mesh_remove_surface,RID,int) + BIND1RC(int,mesh_get_surface_count,RID) - virtual void particles_set_visibility_aabb(RID p_particles, const AABB& p_visibility); - virtual AABB particles_get_visibility_aabb(RID p_particles) const; + BIND2(mesh_set_custom_aabb,RID,const Rect3&) + BIND1RC(Rect3,mesh_get_custom_aabb,RID) - virtual void particles_set_emission_half_extents(RID p_particles, const Vector3& p_half_extents); - virtual Vector3 particles_get_emission_half_extents(RID p_particles) const; + BIND1(mesh_clear,RID) - virtual void particles_set_emission_base_velocity(RID p_particles, const Vector3& p_base_velocity); - virtual Vector3 particles_get_emission_base_velocity(RID p_particles) const; - - virtual void particles_set_emission_points(RID p_particles, const DVector<Vector3>& p_points); - virtual DVector<Vector3> particles_get_emission_points(RID p_particles) const; - - virtual void particles_set_gravity_normal(RID p_particles, const Vector3& p_normal); - virtual Vector3 particles_get_gravity_normal(RID p_particles) const; + /* MULTIMESH API */ - virtual void particles_set_variable(RID p_particles, ParticleVariable p_variable,float p_value); - virtual float particles_get_variable(RID p_particles, ParticleVariable p_variable) const; - virtual void particles_set_randomness(RID p_particles, ParticleVariable p_variable,float p_randomness); - virtual float particles_get_randomness(RID p_particles, ParticleVariable p_variable) const; + BIND0R(RID,multimesh_create) - virtual void particles_set_color_phase_pos(RID p_particles, int p_phase, float p_pos); - virtual float particles_get_color_phase_pos(RID p_particles, int p_phase) const; + BIND4(multimesh_allocate,RID,int,MultimeshTransformFormat,MultimeshColorFormat) + BIND1RC(int,multimesh_get_instance_count,RID) - virtual void particles_set_color_phases(RID p_particles, int p_phases); - virtual int particles_get_color_phases(RID p_particles) const; + BIND2(multimesh_set_mesh,RID,RID) + BIND3(multimesh_instance_set_transform,RID,int,const Transform&) + BIND3(multimesh_instance_set_transform_2d,RID,int,const Transform2D& ) + BIND3(multimesh_instance_set_color,RID,int,const Color&) - virtual void particles_set_color_phase_color(RID p_particles, int p_phase, const Color& p_color); - virtual Color particles_get_color_phase_color(RID p_particles, int p_phase) const; + BIND1RC(RID,multimesh_get_mesh,RID) + BIND1RC(Rect3,multimesh_get_aabb,RID) - virtual void particles_set_attractors(RID p_particles, int p_attractors); - virtual int particles_get_attractors(RID p_particles) const; + BIND2RC(Transform,multimesh_instance_get_transform,RID,int ) + BIND2RC(Transform2D,multimesh_instance_get_transform_2d,RID,int) + BIND2RC(Color,multimesh_instance_get_color,RID,int) - virtual void particles_set_attractor_pos(RID p_particles, int p_attractor, const Vector3& p_pos); - virtual Vector3 particles_get_attractor_pos(RID p_particles,int p_attractor) const; + BIND2(multimesh_set_visible_instances,RID,int) + BIND1RC(int,multimesh_get_visible_instances,RID) - virtual void particles_set_attractor_strength(RID p_particles, int p_attractor, float p_force); - virtual float particles_get_attractor_strength(RID p_particles,int p_attractor) const; - virtual void particles_set_material(RID p_particles, RID p_material,bool p_owned=false); - virtual RID particles_get_material(RID p_particles) const; + /* IMMEDIATE API */ - virtual void particles_set_height_from_velocity(RID p_particles, bool p_enable); - virtual bool particles_has_height_from_velocity(RID p_particles) const; + BIND0R(RID,immediate_create) + BIND3(immediate_begin,RID,PrimitiveType,RID) + BIND2(immediate_vertex,RID,const Vector3&) + BIND2(immediate_normal,RID,const Vector3&) + BIND2(immediate_tangent,RID,const Plane&) + BIND2(immediate_color,RID,const Color&) + BIND2(immediate_uv,RID,const Vector2& ) + BIND2(immediate_uv2,RID,const Vector2&) + BIND1(immediate_end,RID) + BIND1(immediate_clear,RID) + BIND2(immediate_set_material,RID ,RID ) + BIND1RC(RID,immediate_get_material,RID) - virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable); - virtual bool particles_is_using_local_coordinates(RID p_particles) const; + /* SKELETON API */ + BIND0R(RID,skeleton_create) + BIND3(skeleton_allocate,RID,int,bool) + BIND1RC(int,skeleton_get_bone_count,RID) + BIND3(skeleton_bone_set_transform,RID,int,const Transform&) + BIND2RC(Transform,skeleton_bone_get_transform,RID,int) + BIND3(skeleton_bone_set_transform_2d,RID,int, const Transform2D& ) + BIND2RC(Transform2D,skeleton_bone_get_transform_2d,RID,int) /* Light API */ - virtual RID light_create(LightType p_type); - virtual LightType light_get_type(RID p_light) const; - - virtual void light_set_color(RID p_light,LightColor p_type, const Color& p_color); - virtual Color light_get_color(RID p_light,LightColor p_type) const; - + BIND1R(RID,light_create,LightType) - virtual void light_set_shadow(RID p_light,bool p_enabled); - virtual bool light_has_shadow(RID p_light) const; + BIND2(light_set_color,RID,const Color&) + BIND3(light_set_param,RID ,LightParam ,float ) + BIND2(light_set_shadow,RID ,bool ) + BIND2(light_set_shadow_color,RID ,const Color& ) + BIND2(light_set_projector,RID,RID ) + BIND2(light_set_negative,RID,bool ) + BIND2(light_set_cull_mask,RID ,uint32_t ) - virtual void light_set_volumetric(RID p_light,bool p_enabled); - virtual bool light_is_volumetric(RID p_light) const; + BIND2(light_omni_set_shadow_mode,RID,LightOmniShadowMode) + BIND2(light_omni_set_shadow_detail,RID,LightOmniShadowDetail) - virtual void light_set_projector(RID p_light,RID p_texture); - virtual RID light_get_projector(RID p_light) const; + BIND2(light_directional_set_shadow_mode,RID,LightDirectionalShadowMode) + BIND2(light_directional_set_blend_splits,RID,bool) - virtual void light_set_param(RID p_light, LightParam p_var, float p_value); - virtual float light_get_param(RID p_light, LightParam p_var) const; + /* PROBE API */ - virtual void light_set_operator(RID p_light,LightOp p_op); - virtual LightOp light_get_operator(RID p_light) const; + BIND0R(RID,reflection_probe_create) - virtual void light_omni_set_shadow_mode(RID p_light,LightOmniShadowMode p_mode); - virtual LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) const; - - virtual void light_directional_set_shadow_mode(RID p_light,LightDirectionalShadowMode p_mode); - virtual LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) const; - virtual void light_directional_set_shadow_param(RID p_light,LightDirectionalShadowParam p_param, float p_value); - virtual float light_directional_get_shadow_param(RID p_light,LightDirectionalShadowParam p_param) const; - - - /* SKELETON API */ - - virtual RID skeleton_create(); - virtual void skeleton_resize(RID p_skeleton,int p_bones); - virtual int skeleton_get_bone_count(RID p_skeleton) const; - virtual void skeleton_bone_set_transform(RID p_skeleton,int p_bone, const Transform& p_transform); - virtual Transform skeleton_bone_get_transform(RID p_skeleton,int p_bone); + BIND2(reflection_probe_set_update_mode,RID, ReflectionProbeUpdateMode ) + BIND2(reflection_probe_set_intensity,RID, float ) + BIND2(reflection_probe_set_interior_ambient,RID, const Color& ) + BIND2(reflection_probe_set_interior_ambient_energy,RID, float ) + BIND2(reflection_probe_set_interior_ambient_probe_contribution,RID, float ) + BIND2(reflection_probe_set_max_distance,RID, float ) + BIND2(reflection_probe_set_extents,RID, const Vector3& ) + BIND2(reflection_probe_set_origin_offset,RID, const Vector3& ) + BIND2(reflection_probe_set_as_interior,RID, bool ) + BIND2(reflection_probe_set_enable_box_projection,RID, bool ) + BIND2(reflection_probe_set_enable_shadows,RID, bool ) + BIND2(reflection_probe_set_cull_mask,RID, uint32_t ) /* ROOM API */ - virtual RID room_create(); - virtual void room_set_bounds(RID p_room, const BSP_Tree& p_bounds); - virtual BSP_Tree room_get_bounds(RID p_room) const; + BIND0R(RID,room_create) + BIND4(room_add_bounds,RID, const PoolVector<Vector2>& ,float ,const Transform& ) + BIND1(room_clear_bounds,RID) /* PORTAL API */ - virtual RID portal_create(); - virtual void portal_set_shape(RID p_portal, const Vector<Point2>& p_shape); - virtual Vector<Point2> portal_get_shape(RID p_portal) const; - virtual void portal_set_enabled(RID p_portal, bool p_enabled); - virtual bool portal_is_enabled(RID p_portal) const; - virtual void portal_set_disable_distance(RID p_portal, float p_distance); - virtual float portal_get_disable_distance(RID p_portal) const; - virtual void portal_set_disabled_color(RID p_portal, const Color& p_color); - virtual Color portal_get_disabled_color(RID p_portal) const; - virtual void portal_set_connect_range(RID p_portal, float p_range); - virtual float portal_get_connect_range(RID p_portal) const; - - /* BAKED LIGHT */ + // portals are only (x/y) points, forming a convex shape, which its clockwise + // order points outside. (z is 0); - virtual RID baked_light_create(); + BIND0R(RID,portal_create) + BIND2(portal_set_shape,RID , const Vector<Point2>& ) + BIND2(portal_set_enabled,RID , bool ) + BIND2(portal_set_disable_distance,RID , float ) + BIND2(portal_set_disabled_color,RID , const Color& ) - virtual void baked_light_set_mode(RID p_baked_light,BakedLightMode p_mode); - virtual BakedLightMode baked_light_get_mode(RID p_baked_light) const; + /* BAKED LIGHT API */ - virtual void baked_light_set_octree(RID p_baked_light,const DVector<uint8_t> p_octree); - virtual DVector<uint8_t> baked_light_get_octree(RID p_baked_light) const; + BIND0R(RID, gi_probe_create) - virtual void baked_light_set_light(RID p_baked_light,const DVector<uint8_t> p_light); - virtual DVector<uint8_t> baked_light_get_light(RID p_baked_light) const; + BIND2(gi_probe_set_bounds,RID,const Rect3&) + BIND1RC(Rect3,gi_probe_get_bounds,RID) - virtual void baked_light_set_sampler_octree(RID p_baked_light,const DVector<int> &p_sampler); - virtual DVector<int> baked_light_get_sampler_octree(RID p_baked_light) const; + BIND2(gi_probe_set_cell_size,RID,float) + BIND1RC(float,gi_probe_get_cell_size,RID) - virtual void baked_light_set_lightmap_multiplier(RID p_baked_light,float p_multiplier); - virtual float baked_light_get_lightmap_multiplier(RID p_baked_light) const; + BIND2(gi_probe_set_to_cell_xform,RID,const Transform&) + BIND1RC(Transform,gi_probe_get_to_cell_xform,RID) - virtual void baked_light_add_lightmap(RID p_baked_light,const RID p_texture,int p_id); - virtual void baked_light_clear_lightmaps(RID p_baked_light); + BIND2(gi_probe_set_dynamic_range,RID,int) + BIND1RC(int,gi_probe_get_dynamic_range,RID) - virtual void baked_light_set_realtime_color_enabled(RID p_baked_light, const bool p_enabled); - virtual bool baked_light_get_realtime_color_enabled(RID p_baked_light) const; + BIND2(gi_probe_set_energy,RID,float) + BIND1RC(float,gi_probe_get_energy,RID) - virtual void baked_light_set_realtime_color(RID p_baked_light, const Color& p_color); - virtual Color baked_light_get_realtime_color(RID p_baked_light) const; + BIND2(gi_probe_set_bias,RID,float) + BIND1RC(float,gi_probe_get_bias,RID) - virtual void baked_light_set_realtime_energy(RID p_baked_light, const float p_energy); - virtual float baked_light_get_realtime_energy(RID p_baked_light) const; + BIND2(gi_probe_set_propagation,RID,float) + BIND1RC(float,gi_probe_get_propagation,RID) - /* BAKED LIGHT SAMPLER */ + BIND2(gi_probe_set_interior,RID,bool) + BIND1RC(bool,gi_probe_is_interior,RID) - virtual RID baked_light_sampler_create(); + BIND2(gi_probe_set_compress,RID,bool) + BIND1RC(bool,gi_probe_is_compressed,RID) - virtual void baked_light_sampler_set_param(RID p_baked_light_sampler,BakedLightSamplerParam p_param,float p_value); - virtual float baked_light_sampler_get_param(RID p_baked_light_sampler,BakedLightSamplerParam p_param) const; + BIND2(gi_probe_set_dynamic_data,RID,const PoolVector<int>& ) + BIND1RC( PoolVector<int>,gi_probe_get_dynamic_data,RID) - virtual void baked_light_sampler_set_resolution(RID p_baked_light_sampler,int p_resolution); - virtual int baked_light_sampler_get_resolution(RID p_baked_light_sampler) const; + /* PARTICLES */ - /* CAMERA API */ + BIND0R(RID, particles_create) - 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_transform(RID p_camera,const Transform& p_transform); + BIND2(particles_set_emitting,RID,bool) + BIND2(particles_set_amount,RID,int ) + BIND2(particles_set_lifetime,RID,float ) + BIND2(particles_set_pre_process_time,RID,float ) + BIND2(particles_set_explosiveness_ratio,RID,float ) + BIND2(particles_set_randomness_ratio,RID,float ) + BIND2(particles_set_custom_aabb,RID,const Rect3& ) + BIND2(particles_set_gravity,RID,const Vector3& ) + BIND2(particles_set_use_local_coordinates,RID,bool ) + BIND2(particles_set_process_material,RID,RID ) - virtual void camera_set_visible_layers(RID p_camera,uint32_t p_layers); - virtual uint32_t camera_get_visible_layers(RID p_camera) const; + BIND2(particles_set_emission_shape,RID,VS::ParticlesEmissionShape ) + BIND2(particles_set_emission_sphere_radius,RID,float ) + BIND2(particles_set_emission_box_extents,RID,const Vector3& ) + BIND2(particles_set_emission_points,RID,const PoolVector<Vector3>& ) - virtual void camera_set_environment(RID p_camera,RID p_env); - virtual RID camera_get_environment(RID p_camera) const; - virtual void camera_set_use_vertical_aspect(RID p_camera,bool p_enable); - virtual bool camera_is_using_vertical_aspect(RID p_camera,bool p_enable) const; + BIND2(particles_set_draw_order,RID,VS::ParticlesDrawOrder ) - /* VIEWPORT API */ + BIND2(particles_set_draw_passes,RID,int ) + BIND3(particles_set_draw_pass_material,RID,int , RID ) + BIND3(particles_set_draw_pass_mesh,RID,int , RID ) - virtual RID viewport_create(); + BIND1R(Rect3,particles_get_current_aabb,RID); - virtual void viewport_attach_to_screen(RID p_viewport,int p_screen=0); - virtual void viewport_detach(RID p_viewport); - virtual void viewport_set_as_render_target(RID p_viewport,bool p_enable); - virtual void viewport_set_render_target_update_mode(RID p_viewport,RenderTargetUpdateMode p_mode); - virtual RenderTargetUpdateMode viewport_get_render_target_update_mode(RID p_viewport) const; - virtual RID viewport_get_render_target_texture(RID p_viewport) const; - virtual void viewport_set_render_target_vflip(RID p_viewport,bool p_enable); - virtual bool viewport_get_render_target_vflip(RID p_viewport) const; - virtual void viewport_set_render_target_clear_on_new_frame(RID p_viewport,bool p_enable); - virtual bool viewport_get_render_target_clear_on_new_frame(RID p_viewport) const; - virtual void viewport_render_target_clear(RID p_viewport); - virtual void viewport_set_render_target_to_screen_rect(RID p_viewport,const Rect2& p_rect); +#undef BINDBASE +//from now on, calls forwarded to this singleton +#define BINDBASE VSG::scene + /* CAMERA API */ - virtual void viewport_queue_screen_capture(RID p_viewport); - virtual Image viewport_get_screen_capture(RID p_viewport) const; - virtual void viewport_set_rect(RID p_viewport,const ViewportRect& p_rect); - virtual ViewportRect viewport_get_rect(RID p_viewport) const; + BIND0R(RID, camera_create) + BIND4(camera_set_perspective,RID,float, float , float ) + BIND4(camera_set_orthogonal,RID,float , float , float ) + BIND2(camera_set_transform,RID,const Transform&) + BIND2(camera_set_cull_mask,RID,uint32_t ) + BIND2(camera_set_environment,RID ,RID ) + BIND2(camera_set_use_vertical_aspect,RID,bool) - virtual void viewport_set_hide_scenario(RID p_viewport,bool p_hide); - virtual void viewport_set_hide_canvas(RID p_viewport,bool p_hide); - virtual void viewport_set_disable_environment(RID p_viewport,bool p_disable); - virtual void viewport_attach_camera(RID p_viewport,RID p_camera); - virtual void viewport_set_scenario(RID p_viewport,RID p_scenario); +#undef BINDBASE +//from now on, calls forwarded to this singleton +#define BINDBASE VSG::viewport - virtual RID viewport_get_attached_camera(RID p_viewport) const; - virtual RID viewport_get_scenario(RID p_viewport) const; - virtual void viewport_attach_canvas(RID p_viewport,RID p_canvas); - virtual void viewport_remove_canvas(RID p_viewport,RID p_canvas); - virtual void viewport_set_canvas_transform(RID p_viewport,RID p_canvas,const Matrix32& p_offset); - virtual Matrix32 viewport_get_canvas_transform(RID p_viewport,RID p_canvas) const; - virtual void viewport_set_global_canvas_transform(RID p_viewport,const Matrix32& p_transform); - virtual Matrix32 viewport_get_global_canvas_transform(RID p_viewport) const; - virtual void viewport_set_canvas_layer(RID p_viewport,RID p_canvas,int p_layer); - virtual void viewport_set_transparent_background(RID p_viewport,bool p_enabled); - virtual bool viewport_has_transparent_background(RID p_viewport) const; + /* VIEWPORT TARGET API */ + BIND0R(RID,viewport_create) - /* ENVIRONMENT API */ + BIND3(viewport_set_size,RID,int ,int ) - virtual RID environment_create(); + BIND2(viewport_set_active,RID ,bool ) + BIND2(viewport_set_parent_viewport,RID,RID) - virtual void environment_set_background(RID p_env,EnvironmentBG p_bg); - virtual EnvironmentBG environment_get_background(RID p_env) const; + BIND2(viewport_set_clear_mode,RID,ViewportClearMode ) - virtual void environment_set_background_param(RID p_env,EnvironmentBGParam p_param, const Variant& p_value); - virtual Variant environment_get_background_param(RID p_env,EnvironmentBGParam p_param) const; + BIND3(viewport_attach_to_screen,RID ,const Rect2& ,int ) + BIND1(viewport_detach,RID) - virtual void environment_set_enable_fx(RID p_env,EnvironmentFx p_effect,bool p_enabled); - virtual bool environment_is_fx_enabled(RID p_env,EnvironmentFx p_effect) const; + BIND2(viewport_set_update_mode,RID,ViewportUpdateMode ) + BIND2(viewport_set_vflip,RID,bool) - virtual void environment_fx_set_param(RID p_env,EnvironmentFxParam p_effect,const Variant& p_param); - virtual Variant environment_fx_get_param(RID p_env,EnvironmentFxParam p_effect) const; + BIND1RC(RID,viewport_get_texture,RID ) + BIND2(viewport_set_hide_scenario,RID,bool ) + BIND2(viewport_set_hide_canvas,RID,bool ) + BIND2(viewport_set_disable_environment,RID,bool ) + BIND2(viewport_set_disable_3d,RID,bool ) - /* SCENARIO API */ + BIND2(viewport_attach_camera,RID,RID ) + BIND2(viewport_set_scenario,RID,RID ) + BIND2(viewport_attach_canvas,RID,RID ) - virtual RID scenario_create(); + BIND2(viewport_remove_canvas,RID,RID ) + BIND3(viewport_set_canvas_transform,RID ,RID ,const Transform2D& ) + BIND2(viewport_set_transparent_background,RID ,bool ) - virtual void scenario_set_debug(RID p_scenario,ScenarioDebugMode p_debug_mode); - virtual void scenario_set_environment(RID p_scenario, RID p_environment); - virtual RID scenario_get_environment(RID p_scenario, RID p_environment) const; - virtual void scenario_set_fallback_environment(RID p_scenario, RID p_environment); + BIND2(viewport_set_global_canvas_transform,RID,const Transform2D& ) + BIND3(viewport_set_canvas_layer,RID ,RID ,int ) + BIND2(viewport_set_shadow_atlas_size,RID ,int ) + BIND3(viewport_set_shadow_atlas_quadrant_subdivision,RID ,int, int ) + BIND2(viewport_set_msaa,RID ,ViewportMSAA ) + BIND2(viewport_set_hdr,RID ,bool ) + /* ENVIRONMENT API */ - /* INSTANCING API */ - - virtual RID instance_create(); - - virtual void instance_set_base(RID p_instance, RID p_base); - virtual RID instance_get_base(RID p_instance) const; +#undef BINDBASE +//from now on, calls forwarded to this singleton +#define BINDBASE VSG::scene_render - virtual void instance_set_scenario(RID p_instance, RID p_scenario); - virtual RID instance_get_scenario(RID p_instance) const; + BIND0R(RID,environment_create) - virtual void instance_set_layer_mask(RID p_instance, uint32_t p_mask); - virtual uint32_t instance_get_layer_mask(RID p_instance) const; + BIND2(environment_set_background,RID ,EnvironmentBG ) + BIND2(environment_set_skybox,RID,RID ) + BIND2(environment_set_skybox_scale,RID,float) + BIND2(environment_set_bg_color,RID,const Color& ) + BIND2(environment_set_bg_energy,RID,float ) + BIND2(environment_set_canvas_max_layer,RID,int ) + BIND4(environment_set_ambient_light,RID,const Color& ,float,float ) + BIND8(environment_set_ssr,RID,bool,int,float,float,float,bool,bool ) + BIND10(environment_set_ssao,RID ,bool , float , float , float,float,float , float ,const Color &,bool ) - virtual AABB instance_get_base_aabb(RID p_instance) const; - virtual void instance_attach_object_instance_ID(RID p_instance,uint32_t p_ID); - virtual uint32_t instance_get_object_instance_ID(RID p_instance) const; - virtual void instance_attach_skeleton(RID p_instance,RID p_skeleton); - virtual RID instance_get_skeleton(RID p_instance) const; + BIND6(environment_set_dof_blur_near,RID,bool ,float,float,float,EnvironmentDOFBlurQuality) + BIND6(environment_set_dof_blur_far,RID,bool ,float,float,float,EnvironmentDOFBlurQuality) + BIND10(environment_set_glow,RID,bool ,int ,float ,float ,float ,EnvironmentGlowBlendMode,float,float,bool ) + BIND5(environment_set_fog,RID,bool ,float ,float ,RID ) - virtual void instance_set_morph_target_weight(RID p_instance,int p_shape, float p_weight); - virtual float instance_get_morph_target_weight(RID p_instance,int p_shape) const; + BIND9(environment_set_tonemap,RID,EnvironmentToneMapper, float ,float ,bool, float ,float ,float,float ) - virtual void instance_set_surface_material(RID p_instance,int p_surface, RID p_material); + BIND6(environment_set_adjustment,RID,bool ,float ,float ,float ,RID ) - virtual void instance_set_transform(RID p_instance, const Transform& p_transform); - virtual Transform instance_get_transform(RID p_instance) const; + /* SCENARIO API */ - virtual void instance_set_exterior( RID p_instance, bool p_enabled ); - virtual bool instance_is_exterior( RID p_instance) const; - virtual void instance_set_room( RID p_instance, RID p_room ); - virtual RID instance_get_room( RID p_instance ) const ; +#undef BINDBASE +#define BINDBASE VSG::scene - virtual void instance_set_extra_visibility_margin( RID p_instance, real_t p_margin ); - virtual real_t instance_get_extra_visibility_margin( RID p_instance ) const; + BIND0R(RID,scenario_create) - virtual Vector<RID> instances_cull_aabb(const AABB& p_aabb, RID p_scenario=RID()) const; - virtual Vector<RID> instances_cull_ray(const Vector3& p_from, const Vector3& p_to, RID p_scenario=RID()) const; - virtual Vector<RID> instances_cull_convex(const Vector<Plane>& p_convex, RID p_scenario=RID()) const; + BIND2(scenario_set_debug,RID,ScenarioDebugMode ) + BIND2(scenario_set_environment,RID, RID ) + BIND3(scenario_set_reflection_atlas_size,RID, int,int ) + BIND2(scenario_set_fallback_environment,RID, RID ) - virtual void instance_geometry_set_flag(RID p_instance,InstanceFlags p_flags,bool p_enabled); - virtual bool instance_geometry_get_flag(RID p_instance,InstanceFlags p_flags) const; - virtual void instance_geometry_set_cast_shadows_setting(RID p_instance, VS::ShadowCastingSetting p_shadow_casting_setting); - virtual VS::ShadowCastingSetting instance_geometry_get_cast_shadows_setting(RID p_instance) const; + /* INSTANCING API */ + // from can be mesh, light, area and portal so far. + BIND0R(RID,instance_create) - virtual void instance_geometry_set_material_override(RID p_instance, RID p_material); - virtual RID instance_geometry_get_material_override(RID p_instance) const; + BIND2(instance_set_base,RID, RID ) // from can be mesh, light, poly, area and portal so far. + BIND2(instance_set_scenario,RID, RID ) // from can be mesh, light, poly, area and portal so far. + BIND2(instance_set_layer_mask,RID, uint32_t ) + BIND2(instance_set_transform,RID, const Transform& ) + BIND2(instance_attach_object_instance_ID,RID,ObjectID ) + BIND3(instance_set_blend_shape_weight,RID,int , float ) + BIND3(instance_set_surface_material,RID,int , RID ) + BIND2(instance_set_visible,RID ,bool) - virtual void instance_geometry_set_draw_range(RID p_instance,float p_min,float p_max); - virtual float instance_geometry_get_draw_range_max(RID p_instance) const; - virtual float instance_geometry_get_draw_range_min(RID p_instance) const; - virtual void instance_geometry_set_baked_light(RID p_instance,RID p_baked_light); - virtual RID instance_geometry_get_baked_light(RID p_instance) const; + BIND2(instance_attach_skeleton,RID,RID ) + BIND2(instance_set_exterior, RID, bool ) + BIND2(instance_set_room, RID, RID ) - virtual void instance_geometry_set_baked_light_sampler(RID p_instance,RID p_baked_light_sampler); - virtual RID instance_geometry_get_baked_light_sampler(RID p_instance) const; + BIND2(instance_set_extra_visibility_margin, RID, real_t ) - virtual void instance_geometry_set_baked_light_texture_index(RID p_instance,int p_tex_id); - virtual int instance_geometry_get_baked_light_texture_index(RID p_instance) const; + // don't use these in a game! + BIND2RC(Vector<ObjectID>,instances_cull_aabb,const Rect3& , RID) + BIND3RC(Vector<ObjectID>,instances_cull_ray,const Vector3& , const Vector3& , RID ) + BIND2RC(Vector<ObjectID>,instances_cull_convex,const Vector<Plane>& , RID) - virtual void instance_light_set_enabled(RID p_instance,bool p_enabled); - virtual bool instance_light_is_enabled(RID p_instance) const; - /* CANVAS (2D) */ + BIND3(instance_geometry_set_flag,RID,InstanceFlags ,bool ) + BIND2(instance_geometry_set_cast_shadows_setting,RID, ShadowCastingSetting ) + BIND2(instance_geometry_set_material_override,RID, RID ) - virtual RID canvas_create(); - virtual void canvas_set_item_mirroring(RID p_canvas,RID p_item,const Point2& p_mirroring); - virtual Point2 canvas_get_item_mirroring(RID p_canvas,RID p_item) const; - virtual void canvas_set_modulate(RID p_canvas,const Color& p_color); + BIND5(instance_geometry_set_draw_range,RID,float ,float ,float ,float ) + BIND2(instance_geometry_set_as_instance_lod,RID,RID ) - virtual RID canvas_item_create(); +#undef BINDBASE +//from now on, calls forwarded to this singleton +#define BINDBASE VSG::canvas - virtual void canvas_item_set_parent(RID p_item,RID p_parent_item); - virtual RID canvas_item_get_parent(RID p_canvas_item) const; + /* CANVAS (2D) */ - virtual void canvas_item_set_visible(RID p_item,bool p_visible); - virtual bool canvas_item_is_visible(RID p_item) const; + BIND0R(RID,canvas_create) + BIND3(canvas_set_item_mirroring,RID ,RID ,const Point2& ) + BIND2(canvas_set_modulate,RID,const Color&) - virtual void canvas_item_set_blend_mode(RID p_canvas_item,MaterialBlendMode p_blend); - virtual void canvas_item_set_light_mask(RID p_canvas_item,int p_mask); + BIND0R(RID,canvas_item_create) + BIND2(canvas_item_set_parent,RID ,RID) + BIND2(canvas_item_set_visible,RID,bool ) + BIND2(canvas_item_set_light_mask,RID,int ) - //virtual void canvas_item_set_rect(RID p_item, const Rect2& p_rect); - virtual void canvas_item_set_transform(RID p_item, const Matrix32& p_transform); - virtual void canvas_item_set_clip(RID p_item, bool p_clip); - virtual void canvas_item_set_distance_field_mode(RID p_item, bool p_enable); - virtual void canvas_item_set_custom_rect(RID p_item, bool p_custom_rect,const Rect2& p_rect=Rect2()); - virtual void canvas_item_set_opacity(RID p_item, float p_opacity); - virtual float canvas_item_get_opacity(RID p_item, float p_opacity) const; - virtual void canvas_item_set_on_top(RID p_item, bool p_on_top); - virtual bool canvas_item_is_on_top(RID p_item) const; + BIND2(canvas_item_set_transform,RID, const Transform2D& ) + BIND2(canvas_item_set_clip,RID, bool ) + BIND2(canvas_item_set_distance_field_mode,RID, bool ) + BIND3(canvas_item_set_custom_rect,RID, bool ,const Rect2& ) + BIND2(canvas_item_set_modulate,RID, const Color& ) + BIND2(canvas_item_set_self_modulate,RID, const Color& ) - virtual void canvas_item_set_self_opacity(RID p_item, float p_self_opacity); - virtual float canvas_item_get_self_opacity(RID p_item, float p_self_opacity) const; + BIND2(canvas_item_set_draw_behind_parent,RID, bool ) - virtual void canvas_item_attach_viewport(RID p_item, RID p_viewport); - virtual void canvas_item_add_line(RID p_item, const Point2& p_from, const Point2& p_to, const Color& p_color, float p_width=1.0, bool p_antialiased=false); - virtual void canvas_item_add_rect(RID p_item, const Rect2& p_rect, const Color& p_color); - virtual void canvas_item_add_circle(RID p_item, const Point2& p_pos, float p_radius,const Color& p_color); - virtual void canvas_item_add_texture_rect(RID p_item, const Rect2& p_rect, RID p_texture,bool p_tile=false,const Color& p_modulate=Color(1,1,1),bool p_transpose=false); - virtual void canvas_item_add_texture_rect_region(RID p_item, const Rect2& p_rect, RID p_texture,const Rect2& p_src_rect,const Color& p_modulate=Color(1,1,1),bool p_transpose=false); - virtual void canvas_item_add_style_box(RID p_item, const Rect2& p_rect, const Rect2& p_source, RID p_texture,const Vector2& p_topleft, const Vector2& p_bottomright, bool p_draw_center=true,const Color& p_modulate=Color(1,1,1)); - 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); - 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()); - 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>(), RID p_texture=RID(), int p_count=-1); - virtual void canvas_item_add_triangle_array_ptr(RID p_item, int p_count, const int* p_indices, const Point2* p_points, const Color* p_colors,const Point2* p_uvs=NULL, RID p_texture=RID()); - virtual void canvas_item_add_set_transform(RID p_item,const Matrix32& p_transform); - virtual void canvas_item_add_set_blend_mode(RID p_item, MaterialBlendMode p_blend); - virtual void canvas_item_add_clip_ignore(RID p_item, bool p_ignore); - virtual void canvas_item_set_sort_children_by_y(RID p_item, bool p_enable); - virtual void canvas_item_set_z(RID p_item, int p_z); - virtual void canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable); - virtual void canvas_item_set_copy_to_backbuffer(RID p_item, bool p_enable,const Rect2& p_rect); + BIND6(canvas_item_add_line,RID, const Point2& , const Point2& ,const Color& ,float ,bool ) + BIND3(canvas_item_add_rect,RID, const Rect2& , const Color& ) + BIND4(canvas_item_add_circle,RID, const Point2& , float ,const Color& ) + BIND6(canvas_item_add_texture_rect,RID, const Rect2& , RID ,bool ,const Color& ,bool ) + BIND6(canvas_item_add_texture_rect_region,RID, const Rect2& , RID ,const Rect2& ,const Color& ,bool ) + BIND10(canvas_item_add_nine_patch,RID, const Rect2& , const Rect2& , RID ,const Vector2& , const Vector2& ,NinePatchAxisMode , NinePatchAxisMode,bool ,const Color& ) + BIND6(canvas_item_add_primitive,RID, const Vector<Point2>& , const Vector<Color>& ,const Vector<Point2>& , RID ,float ) + BIND5(canvas_item_add_polygon,RID, const Vector<Point2>& , const Vector<Color>& ,const Vector<Point2>& , RID ) + BIND7(canvas_item_add_triangle_array,RID, const Vector<int>& , const Vector<Point2>& , const Vector<Color>& ,const Vector<Point2>& , RID , int) + BIND3(canvas_item_add_mesh,RID, const RID& ,RID ) + BIND3(canvas_item_add_multimesh,RID, RID ,RID ) + BIND2(canvas_item_add_set_transform,RID,const Transform2D& ) + BIND2(canvas_item_add_clip_ignore,RID, bool ) + BIND2(canvas_item_set_sort_children_by_y,RID, bool ) + BIND2(canvas_item_set_z,RID, int ) + BIND2(canvas_item_set_z_as_relative_to_parent,RID, bool ) + BIND3(canvas_item_set_copy_to_backbuffer,RID, bool ,const Rect2& ) - virtual void canvas_item_set_material(RID p_item, RID p_material); - virtual void canvas_item_set_use_parent_material(RID p_item, bool p_enable); + BIND1(canvas_item_clear,RID ) + BIND2(canvas_item_set_draw_index,RID,int) - virtual RID canvas_light_create(); - virtual void canvas_light_attach_to_canvas(RID p_light,RID p_canvas); - virtual void canvas_light_set_enabled(RID p_light, bool p_enabled); - virtual void canvas_light_set_transform(RID p_light, const Matrix32& p_transform); - virtual void canvas_light_set_scale(RID p_light, float p_scale); - virtual void canvas_light_set_texture(RID p_light, RID p_texture); - virtual void canvas_light_set_texture_offset(RID p_light, const Vector2& p_offset); - virtual void canvas_light_set_color(RID p_light, const Color& p_color); - virtual void canvas_light_set_height(RID p_light, float p_height); - virtual void canvas_light_set_energy(RID p_light, float p_energy); - virtual void canvas_light_set_z_range(RID p_light, int p_min_z,int p_max_z); - virtual void canvas_light_set_layer_range(RID p_light, int p_min_layer,int p_max_layer); - virtual void canvas_light_set_item_mask(RID p_light, int p_mask); - virtual void canvas_light_set_item_shadow_mask(RID p_light, int p_mask); + BIND2(canvas_item_set_material,RID, RID ) - virtual void canvas_light_set_mode(RID p_light, CanvasLightMode p_mode); - virtual void canvas_light_set_shadow_enabled(RID p_light, bool p_enabled); - virtual void canvas_light_set_shadow_buffer_size(RID p_light, int p_size); - virtual void canvas_light_set_shadow_esm_multiplier(RID p_light, float p_multiplier); - virtual void canvas_light_set_shadow_color(RID p_light, const Color& p_color); + BIND2(canvas_item_set_use_parent_material,RID, bool ) + BIND0R(RID,canvas_light_create) + BIND2(canvas_light_attach_to_canvas,RID,RID ) + BIND2(canvas_light_set_enabled,RID, bool ) + BIND2(canvas_light_set_scale,RID, float ) + BIND2(canvas_light_set_transform,RID, const Transform2D& ) + BIND2(canvas_light_set_texture,RID, RID ) + BIND2(canvas_light_set_texture_offset,RID, const Vector2& ) + BIND2(canvas_light_set_color,RID, const Color& ) + BIND2(canvas_light_set_height,RID, float ) + BIND2(canvas_light_set_energy,RID, float ) + BIND3(canvas_light_set_z_range,RID, int ,int ) + BIND3(canvas_light_set_layer_range,RID, int ,int ) + BIND2(canvas_light_set_item_cull_mask,RID, int ) + BIND2(canvas_light_set_item_shadow_cull_mask,RID, int ) - virtual RID canvas_light_occluder_create(); - virtual void canvas_light_occluder_attach_to_canvas(RID p_occluder,RID p_canvas); - virtual void canvas_light_occluder_set_enabled(RID p_occluder,bool p_enabled); - virtual void canvas_light_occluder_set_polygon(RID p_occluder,RID p_polygon); - virtual void canvas_light_occluder_set_transform(RID p_occluder,const Matrix32& p_xform); - virtual void canvas_light_occluder_set_light_mask(RID p_occluder,int p_mask); + BIND2(canvas_light_set_mode,RID, CanvasLightMode ) + BIND2(canvas_light_set_shadow_enabled,RID, bool ) + BIND2(canvas_light_set_shadow_buffer_size,RID, int ) + BIND2(canvas_light_set_shadow_gradient_length,RID, float ) + BIND2(canvas_light_set_shadow_filter,RID, CanvasLightShadowFilter ) + BIND2(canvas_light_set_shadow_color,RID, const Color& ) - virtual RID canvas_occluder_polygon_create(); - virtual void canvas_occluder_polygon_set_shape(RID p_occluder_polygon,const DVector<Vector2>& p_shape,bool p_close); - virtual void canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon,const DVector<Vector2>& p_shape); - virtual void canvas_occluder_polygon_set_cull_mode(RID p_occluder_polygon,CanvasOccluderPolygonCullMode p_mode); + BIND0R(RID,canvas_light_occluder_create) + BIND2(canvas_light_occluder_attach_to_canvas,RID,RID ) + BIND2(canvas_light_occluder_set_enabled,RID,bool ) + BIND2(canvas_light_occluder_set_polygon,RID,RID ) + BIND2(canvas_light_occluder_set_transform,RID,const Transform2D& ) + BIND2(canvas_light_occluder_set_light_mask,RID,int ) - virtual void canvas_item_clear(RID p_item); - virtual void canvas_item_raise(RID p_item); - /* CANVAS ITEM MATERIAL */ + BIND0R(RID,canvas_occluder_polygon_create) + BIND3(canvas_occluder_polygon_set_shape,RID,const PoolVector<Vector2>& ,bool) + BIND2(canvas_occluder_polygon_set_shape_as_lines,RID ,const PoolVector<Vector2>&) - virtual RID canvas_item_material_create(); - virtual void canvas_item_material_set_shader(RID p_material, RID p_shader); - virtual void canvas_item_material_set_shader_param(RID p_material, const StringName& p_param, const Variant& p_value); - virtual Variant canvas_item_material_get_shader_param(RID p_material, const StringName& p_param) const; - virtual void canvas_item_material_set_shading_mode(RID p_material, CanvasItemShadingMode p_mode); + BIND2(canvas_occluder_polygon_set_cull_mode,RID,CanvasOccluderPolygonCullMode) /* CURSOR */ virtual void cursor_set_rotation(float p_rotation, int p_cursor = 0); // radians - virtual void cursor_set_texture(RID p_texture, const Point2 &p_center_offset, int p_cursor=0, const Rect2 &p_region=Rect2()); + virtual void cursor_set_texture(RID p_texture, const Point2 &p_center_offset = Point2(0, 0), int p_cursor=0, const Rect2 &p_region=Rect2()); virtual void cursor_set_visible(bool p_visible, int p_cursor = 0); virtual void cursor_set_pos(const Point2& p_pos, int p_cursor = 0); /* BLACK BARS */ + virtual void black_bars_set_margins(int p_left, int p_top, int p_right, int p_bottom); virtual void black_bars_set_images(RID p_left, RID p_top, RID p_right, RID p_bottom); - /* FREE */ - virtual void free( RID p_rid ); - - /* CUSTOM SHADE MODEL */ + /* FREE */ - virtual void custom_shade_model_set_shader(int p_model, RID p_shader); - virtual RID custom_shade_model_get_shader(int p_model) const; - virtual void custom_shade_model_set_name(int p_model, const String& p_name); - virtual String custom_shade_model_get_name(int p_model) const; - virtual void custom_shade_model_set_param_info(int p_model, const List<PropertyInfo>& p_info); - virtual void custom_shade_model_get_param_info(int p_model, List<PropertyInfo>* p_info) const; + virtual void free( RID p_rid ); ///< free RIDs associated with the visual server /* EVENT QUEUING */ virtual void draw(); virtual void sync(); - + virtual bool has_changed() const; virtual void init(); virtual void finish(); - virtual bool has_changed() const; + /* STATUS INFORMATION */ - /* RENDER INFO */ virtual int get_render_info(RenderInfo p_info); - virtual bool has_feature(Features p_feature) const; - RID get_test_cube(); + virtual RID get_test_cube(); + - virtual void set_boot_image(const Image& p_image, const Color& p_color, bool p_scale); + /* TESTING */ + + virtual void set_boot_image(const Image& p_image, const Color& p_color,bool p_scale); virtual void set_default_clear_color(const Color& p_color); - VisualServerRaster(Rasterizer *p_rasterizer); + virtual bool has_feature(Features p_feature) const; + + virtual bool has_os_feature(const String& p_feature) const; + + + VisualServerRaster(); ~VisualServerRaster(); +#undef DISPLAY_CHANGED + +#undef BIND0R +#undef BIND1RC +#undef BIND2RC +#undef BIND3RC +#undef BIND4RC + +#undef BIND1 +#undef BIND2 +#undef BIND3 +#undef BIND4 +#undef BIND5 +#undef BIND6 +#undef BIND7 +#undef BIND8 +#undef BIND9 +#undef BIND10 + }; #endif diff --git a/servers/visual/visual_server_scene.cpp b/servers/visual/visual_server_scene.cpp new file mode 100644 index 0000000000..6f7b2e3aed --- /dev/null +++ b/servers/visual/visual_server_scene.cpp @@ -0,0 +1,3629 @@ +#include "visual_server_scene.h" +#include "visual_server_global.h" +#include "os/os.h" +/* CAMERA API */ + + + + + +RID VisualServerScene::camera_create() { + + Camera * camera = memnew( Camera ); + return camera_owner.make_rid( camera ); + +} + +void VisualServerScene::camera_set_perspective(RID p_camera,float p_fovy_degrees, float p_z_near, float p_z_far) { + + Camera *camera = camera_owner.get( p_camera ); + ERR_FAIL_COND(!camera); + camera->type=Camera::PERSPECTIVE; + camera->fov=p_fovy_degrees; + camera->znear=p_z_near; + camera->zfar=p_z_far; + +} + +void VisualServerScene::camera_set_orthogonal(RID p_camera,float p_size, float p_z_near, float p_z_far) { + + Camera *camera = camera_owner.get( p_camera ); + ERR_FAIL_COND(!camera); + camera->type=Camera::ORTHOGONAL; + camera->size=p_size; + 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 ); + ERR_FAIL_COND(!camera); + camera->transform=p_transform.orthonormalized(); + + +} + +void VisualServerScene::camera_set_cull_mask(RID p_camera,uint32_t p_layers) { + + + Camera *camera = camera_owner.get( p_camera ); + ERR_FAIL_COND(!camera); + + camera->visible_layers=p_layers; + +} + +void VisualServerScene::camera_set_environment(RID p_camera,RID p_env) { + + Camera *camera = camera_owner.get( p_camera ); + ERR_FAIL_COND(!camera); + camera->env=p_env; + +} + + +void VisualServerScene::camera_set_use_vertical_aspect(RID p_camera,bool p_enable) { + + Camera *camera = camera_owner.get( p_camera ); + ERR_FAIL_COND(!camera); + camera->vaspect=p_enable; + +} + + +/* SCENARIO API */ + + + +void* VisualServerScene::_instance_pair(void *p_self, OctreeElementID, Instance *p_A,int, OctreeElementID, Instance *p_B,int) { + + //VisualServerScene *self = (VisualServerScene*)p_self; + Instance *A = p_A; + Instance *B = p_B; + + //instance indices are designed so greater always contains lesser + if (A->base_type > B->base_type) { + SWAP(A,B); //lesser always first + } + + if (B->base_type==VS::INSTANCE_LIGHT && (1<<A->base_type)&VS::INSTANCE_GEOMETRY_MASK) { + + InstanceLightData * light = static_cast<InstanceLightData*>(B->base_data); + InstanceGeometryData * geom = static_cast<InstanceGeometryData*>(A->base_data); + + + InstanceLightData::PairInfo pinfo; + pinfo.geometry=A; + pinfo.L = geom->lighting.push_back(B); + + List<InstanceLightData::PairInfo>::Element *E = light->geometries.push_back(pinfo); + + if (geom->can_cast_shadows) { + + light->shadow_dirty=true; + } + geom->lighting_dirty=true; + + return E; //this element should make freeing faster + } else if (B->base_type==VS::INSTANCE_REFLECTION_PROBE && (1<<A->base_type)&VS::INSTANCE_GEOMETRY_MASK) { + + InstanceReflectionProbeData * reflection_probe = static_cast<InstanceReflectionProbeData*>(B->base_data); + InstanceGeometryData * geom = static_cast<InstanceGeometryData*>(A->base_data); + + + InstanceReflectionProbeData::PairInfo pinfo; + pinfo.geometry=A; + pinfo.L = geom->reflection_probes.push_back(B); + + List<InstanceReflectionProbeData::PairInfo>::Element *E = reflection_probe->geometries.push_back(pinfo); + + geom->reflection_dirty=true; + + return E; //this element should make freeing faster + } else if (B->base_type==VS::INSTANCE_GI_PROBE && (1<<A->base_type)&VS::INSTANCE_GEOMETRY_MASK) { + + InstanceGIProbeData * gi_probe = static_cast<InstanceGIProbeData*>(B->base_data); + InstanceGeometryData * geom = static_cast<InstanceGeometryData*>(A->base_data); + + + InstanceGIProbeData::PairInfo pinfo; + pinfo.geometry=A; + pinfo.L = geom->gi_probes.push_back(B); + + List<InstanceGIProbeData::PairInfo>::Element *E = gi_probe->geometries.push_back(pinfo); + + geom->gi_probes_dirty=true; + + return E; //this element should make freeing faster + + } else if (B->base_type==VS::INSTANCE_GI_PROBE && A->base_type==VS::INSTANCE_LIGHT) { + + InstanceGIProbeData * gi_probe = static_cast<InstanceGIProbeData*>(B->base_data); + InstanceLightData * light = static_cast<InstanceLightData*>(A->base_data); + + return gi_probe->lights.insert(A); + } + + + +#if 0 + if (A->base_type==INSTANCE_PORTAL) { + + ERR_FAIL_COND_V( B->base_type!=INSTANCE_PORTAL,NULL ); + + A->portal_info->candidate_set.insert(B); + B->portal_info->candidate_set.insert(A); + + self->_portal_attempt_connect(A); + //attempt to conncet portal A (will go through B anyway) + //this is a little hackish, but works fine in practice + + } else if (A->base_type==INSTANCE_GI_PROBE || B->base_type==INSTANCE_GI_PROBE) { + + if (B->base_type==INSTANCE_GI_PROBE) { + SWAP(A,B); + } + + ERR_FAIL_COND_V(B->base_type!=INSTANCE_GI_PROBE_SAMPLER,NULL); + B->gi_probe_sampler_info->gi_probes.insert(A); + + } else if (A->base_type==INSTANCE_ROOM || B->base_type==INSTANCE_ROOM) { + + if (B->base_type==INSTANCE_ROOM) + SWAP(A,B); + + ERR_FAIL_COND_V(! ((1<<B->base_type)&INSTANCE_GEOMETRY_MASK ),NULL); + + B->auto_rooms.insert(A); + A->room_info->owned_autoroom_geometry.insert(B); + + self->_instance_validate_autorooms(B); + + + } else { + + if (B->base_type==INSTANCE_LIGHT) { + + SWAP(A,B); + } else if (A->base_type!=INSTANCE_LIGHT) { + return NULL; + } + + + A->light_info->affected.insert(B); + B->lights.insert(A); + B->light_cache_dirty=true; + + + } +#endif + + return NULL; + +} +void VisualServerScene::_instance_unpair(void *p_self, OctreeElementID, Instance *p_A,int, OctreeElementID, Instance *p_B,int,void* udata) { + + //VisualServerScene *self = (VisualServerScene*)p_self; + Instance *A = p_A; + Instance *B = p_B; + + //instance indices are designed so greater always contains lesser + if (A->base_type > B->base_type) { + SWAP(A,B); //lesser always first + } + + + + if (B->base_type==VS::INSTANCE_LIGHT && (1<<A->base_type)&VS::INSTANCE_GEOMETRY_MASK) { + + InstanceLightData * light = static_cast<InstanceLightData*>(B->base_data); + InstanceGeometryData * geom = static_cast<InstanceGeometryData*>(A->base_data); + + List<InstanceLightData::PairInfo>::Element *E = reinterpret_cast<List<InstanceLightData::PairInfo>::Element*>(udata); + + geom->lighting.erase(E->get().L); + light->geometries.erase(E); + + if (geom->can_cast_shadows) { + light->shadow_dirty=true; + } + geom->lighting_dirty=true; + + + } else if (B->base_type==VS::INSTANCE_REFLECTION_PROBE && (1<<A->base_type)&VS::INSTANCE_GEOMETRY_MASK) { + + InstanceReflectionProbeData * reflection_probe = static_cast<InstanceReflectionProbeData*>(B->base_data); + InstanceGeometryData * geom = static_cast<InstanceGeometryData*>(A->base_data); + + List<InstanceReflectionProbeData::PairInfo>::Element *E = reinterpret_cast<List<InstanceReflectionProbeData::PairInfo>::Element*>(udata); + + geom->reflection_probes.erase(E->get().L); + reflection_probe->geometries.erase(E); + + geom->reflection_dirty=true; + + } else if (B->base_type==VS::INSTANCE_GI_PROBE && (1<<A->base_type)&VS::INSTANCE_GEOMETRY_MASK) { + + InstanceGIProbeData * gi_probe = static_cast<InstanceGIProbeData*>(B->base_data); + InstanceGeometryData * geom = static_cast<InstanceGeometryData*>(A->base_data); + + List<InstanceGIProbeData::PairInfo>::Element *E = reinterpret_cast<List<InstanceGIProbeData::PairInfo>::Element*>(udata); + + geom->gi_probes.erase(E->get().L); + gi_probe->geometries.erase(E); + + geom->gi_probes_dirty=true; + + + } else if (B->base_type==VS::INSTANCE_GI_PROBE && A->base_type==VS::INSTANCE_LIGHT) { + + InstanceGIProbeData * gi_probe = static_cast<InstanceGIProbeData*>(B->base_data); + InstanceLightData * light = static_cast<InstanceLightData*>(A->base_data); + + + Set<Instance*>::Element *E = reinterpret_cast<Set<Instance*>::Element*>(udata); + + gi_probe->lights.erase(E); + } +#if 0 + if (A->base_type==INSTANCE_PORTAL) { + + ERR_FAIL_COND( B->base_type!=INSTANCE_PORTAL ); + + + A->portal_info->candidate_set.erase(B); + B->portal_info->candidate_set.erase(A); + + //after disconnecting them, see if they can connect again + self->_portal_attempt_connect(A); + self->_portal_attempt_connect(B); + + } else if (A->base_type==INSTANCE_GI_PROBE || B->base_type==INSTANCE_GI_PROBE) { + + if (B->base_type==INSTANCE_GI_PROBE) { + SWAP(A,B); + } + + ERR_FAIL_COND(B->base_type!=INSTANCE_GI_PROBE_SAMPLER); + B->gi_probe_sampler_info->gi_probes.erase(A); + + } else if (A->base_type==INSTANCE_ROOM || B->base_type==INSTANCE_ROOM) { + + if (B->base_type==INSTANCE_ROOM) + SWAP(A,B); + + ERR_FAIL_COND(! ((1<<B->base_type)&INSTANCE_GEOMETRY_MASK )); + + B->auto_rooms.erase(A); + B->valid_auto_rooms.erase(A); + A->room_info->owned_autoroom_geometry.erase(B); + + }else { + + + + if (B->base_type==INSTANCE_LIGHT) { + + SWAP(A,B); + } else if (A->base_type!=INSTANCE_LIGHT) { + return; + } + + + A->light_info->affected.erase(B); + B->lights.erase(A); + B->light_cache_dirty=true; + + } +#endif +} + +RID VisualServerScene::scenario_create() { + + Scenario *scenario = memnew( Scenario ); + ERR_FAIL_COND_V(!scenario,RID()); + RID scenario_rid = scenario_owner.make_rid( scenario ); + scenario->self=scenario_rid; + + scenario->octree.set_pair_callback(_instance_pair,this); + scenario->octree.set_unpair_callback(_instance_unpair,this); + scenario->reflection_probe_shadow_atlas=VSG::scene_render->shadow_atlas_create(); + VSG::scene_render->shadow_atlas_set_size(scenario->reflection_probe_shadow_atlas,1024); //make enough shadows for close distance, don't bother with rest + VSG::scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas,0,4); + VSG::scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas,1,4); + VSG::scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas,2,4); + VSG::scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas,3,8); + scenario->reflection_atlas=VSG::scene_render->reflection_atlas_create(); + + return scenario_rid; +} + +void VisualServerScene::scenario_set_debug(RID p_scenario,VS::ScenarioDebugMode p_debug_mode) { + + Scenario *scenario = scenario_owner.get(p_scenario); + ERR_FAIL_COND(!scenario); + scenario->debug=p_debug_mode; +} + +void VisualServerScene::scenario_set_environment(RID p_scenario, RID p_environment) { + + Scenario *scenario = scenario_owner.get(p_scenario); + ERR_FAIL_COND(!scenario); + scenario->environment=p_environment; + +} + +void VisualServerScene::scenario_set_fallback_environment(RID p_scenario, RID p_environment) { + + + Scenario *scenario = scenario_owner.get(p_scenario); + ERR_FAIL_COND(!scenario); + scenario->fallback_environment=p_environment; + + +} + +void VisualServerScene::scenario_set_reflection_atlas_size(RID p_scenario, int p_size,int p_subdiv) { + + Scenario *scenario = scenario_owner.get(p_scenario); + ERR_FAIL_COND(!scenario); + VSG::scene_render->reflection_atlas_set_size(scenario->reflection_atlas,p_size); + VSG::scene_render->reflection_atlas_set_subdivision(scenario->reflection_atlas,p_subdiv); + + +} + + + +/* INSTANCING API */ + +void VisualServerScene::_instance_queue_update(Instance *p_instance,bool p_update_aabb,bool p_update_materials) { + + if (p_update_aabb) + p_instance->update_aabb=true; + if (p_update_materials) + p_instance->update_materials=true; + + if (p_instance->update_item.in_list()) + return; + + _instance_update_list.add(&p_instance->update_item); + + +} + +// from can be mesh, light, area and portal so far. +RID VisualServerScene::instance_create(){ + + Instance *instance = memnew( Instance ); + ERR_FAIL_COND_V(!instance,RID()); + + RID instance_rid = instance_owner.make_rid(instance); + instance->self=instance_rid; + + + return instance_rid; + + +} + +void VisualServerScene::instance_set_base(RID p_instance, RID p_base){ + + Instance *instance = instance_owner.get( p_instance ); + ERR_FAIL_COND( !instance ); + + Scenario *scenario = instance->scenario; + + if (instance->base_type!=VS::INSTANCE_NONE) { + //free anything related to that base + + VSG::storage->instance_remove_dependency(instance->base,instance); + + if (scenario && instance->octree_id) { + scenario->octree.erase(instance->octree_id); //make dependencies generated by the octree go away + instance->octree_id=0; + } + + switch(instance->base_type) { + case VS::INSTANCE_LIGHT: { + + InstanceLightData *light = static_cast<InstanceLightData*>(instance->base_data); + + if (instance->scenario && light->D) { + instance->scenario->directional_lights.erase( light->D ); + light->D=NULL; + } + VSG::scene_render->free(light->instance); + } break; + case VS::INSTANCE_REFLECTION_PROBE: { + + InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData*>(instance->base_data); + VSG::scene_render->free(reflection_probe->instance); + if (reflection_probe->update_list.in_list()) { + reflection_probe_render_list.remove(&reflection_probe->update_list); + } + } break; + case VS::INSTANCE_GI_PROBE: { + + InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData*>(instance->base_data); + + while(gi_probe->dynamic.updating_stage==GI_UPDATE_STAGE_LIGHTING) { + //wait until bake is done if it's baking + OS::get_singleton()->delay_usec(1); + } + if (gi_probe->update_element.in_list()) { + gi_probe_update_list.remove(&gi_probe->update_element); + } + if (gi_probe->dynamic.probe_data.is_valid()) { + VSG::storage->free(gi_probe->dynamic.probe_data); + } + + VSG::scene_render->free(gi_probe->probe_instance); + + } break; + + } + + if (instance->base_data) { + memdelete( instance->base_data ); + instance->base_data=NULL; + } + + instance->blend_values.clear(); + + for(int i=0;i<instance->materials.size();i++) { + if (instance->materials[i].is_valid()) { + VSG::storage->material_remove_instance_owner(instance->materials[i],instance); + } + } + instance->materials.clear(); + +#if 0 + if (instance->light_info) { + + if (instance->scenario && instance->light_info->D) + instance->scenario->directional_lights.erase( instance->light_info->D ); + rasterizer->free(instance->light_info->instance); + memdelete(instance->light_info); + instance->light_info=NULL; + } + + + + if ( instance->room ) { + + instance_set_room(p_instance,RID()); + /* + if((1<<instance->base_type)&INSTANCE_GEOMETRY_MASK) + instance->room->room_info->owned_geometry_instances.erase(instance->RE); + else if (instance->base_type==INSTANCE_PORTAL) { + print_line("freeing portal, is it there? "+itos(instance->room->room_info->owned_portal_instances.(instance->RE))); + instance->room->room_info->owned_portal_instances.erase(instance->RE); + } else if (instance->base_type==INSTANCE_ROOM) + instance->room->room_info->owned_room_instances.erase(instance->RE); + else if (instance->base_type==INSTANCE_LIGHT) + instance->room->room_info->owned_light_instances.erase(instance->RE); + + instance->RE=NULL;*/ + } + + + + + + + if (instance->portal_info) { + + _portal_disconnect(instance,true); + memdelete(instance->portal_info); + instance->portal_info=NULL; + + } + + if (instance->gi_probe_info) { + + while(instance->gi_probe_info->owned_instances.size()) { + + Instance *owned=instance->gi_probe_info->owned_instances.front()->get(); + owned->gi_probe=NULL; + owned->data.gi_probe=NULL; + owned->data.gi_probe_octree_xform=NULL; + owned->BLE=NULL; + instance->gi_probe_info->owned_instances.pop_front(); + } + + memdelete(instance->gi_probe_info); + instance->gi_probe_info=NULL; + + } + + if (instance->scenario && instance->octree_id) { + instance->scenario->octree.erase( instance->octree_id ); + instance->octree_id=0; + } + + + if (instance->room_info) { + + for(List<Instance*>::Element *E=instance->room_info->owned_geometry_instances.front();E;E=E->next()) { + + Instance *owned = E->get(); + owned->room=NULL; + owned->RE=NULL; + } + for(List<Instance*>::Element *E=instance->room_info->owned_portal_instances.front();E;E=E->next()) { + + _portal_disconnect(E->get(),true); + Instance *owned = E->get(); + owned->room=NULL; + owned->RE=NULL; + } + + for(List<Instance*>::Element *E=instance->room_info->owned_room_instances.front();E;E=E->next()) { + + Instance *owned = E->get(); + owned->room=NULL; + owned->RE=NULL; + } + + if (instance->room_info->disconnected_child_portals.size()) { + ERR_PRINT("BUG: Disconnected portals remain!"); + } + memdelete(instance->room_info); + instance->room_info=NULL; + + } + + if (instance->particles_info) { + + rasterizer->free( instance->particles_info->instance ); + memdelete(instance->particles_info); + instance->particles_info=NULL; + + } + + if (instance->gi_probe_sampler_info) { + + while (instance->gi_probe_sampler_info->owned_instances.size()) { + + instance_geometry_set_gi_probe_sampler(instance->gi_probe_sampler_info->owned_instances.front()->get()->self,RID()); + } + + if (instance->gi_probe_sampler_info->sampled_light.is_valid()) { + rasterizer->free(instance->gi_probe_sampler_info->sampled_light); + } + memdelete( instance->gi_probe_sampler_info ); + instance->gi_probe_sampler_info=NULL; + } +#endif + + } + + + instance->base_type=VS::INSTANCE_NONE; + instance->base=RID(); + + + if (p_base.is_valid()) { + + instance->base_type=VSG::storage->get_base_type(p_base); + ERR_FAIL_COND(instance->base_type==VS::INSTANCE_NONE); + + switch(instance->base_type) { + case VS::INSTANCE_LIGHT: { + + InstanceLightData *light = memnew( InstanceLightData ); + + if (scenario && VSG::storage->light_get_type(p_base)==VS::LIGHT_DIRECTIONAL) { + light->D = scenario->directional_lights.push_back(instance); + } + + light->instance = VSG::scene_render->light_instance_create(p_base); + + instance->base_data=light; + } break; + case VS::INSTANCE_MESH: + case VS::INSTANCE_MULTIMESH: + case VS::INSTANCE_IMMEDIATE: { + + InstanceGeometryData *geom = memnew( InstanceGeometryData ); + instance->base_data=geom; + } break; + case VS::INSTANCE_REFLECTION_PROBE: { + + InstanceReflectionProbeData *reflection_probe = memnew( InstanceReflectionProbeData ); + reflection_probe->owner=instance; + instance->base_data=reflection_probe; + + reflection_probe->instance=VSG::scene_render->reflection_probe_instance_create(p_base); + } break; + case VS::INSTANCE_GI_PROBE: { + + InstanceGIProbeData *gi_probe = memnew( InstanceGIProbeData ); + instance->base_data=gi_probe; + gi_probe->owner=instance; + + if (scenario && !gi_probe->update_element.in_list()) { + gi_probe_update_list.add(&gi_probe->update_element); + } + + gi_probe->probe_instance=VSG::scene_render->gi_probe_instance_create(); + + } break; + + } + + VSG::storage->instance_add_dependency(p_base,instance); + + instance->base=p_base; + + if (scenario) + _instance_queue_update(instance,true,true); + + +#if 0 + if (rasterizer->is_mesh(p_base)) { + instance->base_type=INSTANCE_MESH; + instance->data.morph_values.resize( rasterizer->mesh_get_morph_target_count(p_base)); + instance->data.materials.resize( rasterizer->mesh_get_surface_count(p_base)); + } else if (rasterizer->is_multimesh(p_base)) { + instance->base_type=INSTANCE_MULTIMESH; + } else if (rasterizer->is_immediate(p_base)) { + instance->base_type=INSTANCE_IMMEDIATE; + } else if (rasterizer->is_particles(p_base)) { + instance->base_type=INSTANCE_PARTICLES; + instance->particles_info=memnew( Instance::ParticlesInfo ); + instance->particles_info->instance = rasterizer->particles_instance_create( p_base ); + } else if (rasterizer->is_light(p_base)) { + + instance->base_type=INSTANCE_LIGHT; + instance->light_info = memnew( Instance::LightInfo ); + instance->light_info->instance = rasterizer->light_instance_create(p_base); + if (instance->scenario && rasterizer->light_get_type(p_base)==LIGHT_DIRECTIONAL) { + + instance->light_info->D = instance->scenario->directional_lights.push_back(instance->self); + } + + } else if (room_owner.owns(p_base)) { + instance->base_type=INSTANCE_ROOM; + instance->room_info = memnew( Instance::RoomInfo ); + instance->room_info->room=room_owner.get(p_base); + } else if (portal_owner.owns(p_base)) { + + instance->base_type=INSTANCE_PORTAL; + instance->portal_info = memnew(Instance::PortalInfo); + instance->portal_info->portal=portal_owner.get(p_base); + } else if (gi_probe_owner.owns(p_base)) { + + instance->base_type=INSTANCE_GI_PROBE; + instance->gi_probe_info=memnew(Instance::BakedLightInfo); + instance->gi_probe_info->gi_probe=gi_probe_owner.get(p_base); + + //instance->portal_info = memnew(Instance::PortalInfo); + //instance->portal_info->portal=portal_owner.get(p_base); + } else if (gi_probe_sampler_owner.owns(p_base)) { + + + instance->base_type=INSTANCE_GI_PROBE_SAMPLER; + instance->gi_probe_sampler_info=memnew( Instance::BakedLightSamplerInfo); + instance->gi_probe_sampler_info->sampler=gi_probe_sampler_owner.get(p_base); + + //instance->portal_info = memnew(Instance::PortalInfo); + //instance->portal_info->portal=portal_owner.get(p_base); + + } else { + ERR_EXPLAIN("Invalid base RID for instance!") + ERR_FAIL(); + } + + instance_dependency_map[ p_base ].insert( instance->self ); +#endif + + + } +} +void VisualServerScene::instance_set_scenario(RID p_instance, RID p_scenario){ + + Instance *instance = instance_owner.get( p_instance ); + ERR_FAIL_COND( !instance ); + + if (instance->scenario) { + + instance->scenario->instances.remove( &instance->scenario_item ); + + if (instance->octree_id) { + instance->scenario->octree.erase(instance->octree_id); //make dependencies generated by the octree go away + instance->octree_id=0; + } + + + switch(instance->base_type) { + + case VS::INSTANCE_LIGHT: { + + + InstanceLightData *light = static_cast<InstanceLightData*>(instance->base_data); + + if (light->D) { + instance->scenario->directional_lights.erase( light->D ); + light->D=NULL; + } + } break; + case VS::INSTANCE_REFLECTION_PROBE: { + + InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData*>(instance->base_data); + VSG::scene_render->reflection_probe_release_atlas_index(reflection_probe->instance); + } break; + case VS::INSTANCE_GI_PROBE: { + + InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData*>(instance->base_data); + if (gi_probe->update_element.in_list()) { + gi_probe_update_list.remove(&gi_probe->update_element); + } + } break; + + } + + instance->scenario=NULL; + } + + + if (p_scenario.is_valid()) { + + Scenario *scenario = scenario_owner.get( p_scenario ); + ERR_FAIL_COND(!scenario); + + instance->scenario=scenario; + + scenario->instances.add( &instance->scenario_item ); + + + switch(instance->base_type) { + + case VS::INSTANCE_LIGHT: { + + + InstanceLightData *light = static_cast<InstanceLightData*>(instance->base_data); + + if (VSG::storage->light_get_type(instance->base)==VS::LIGHT_DIRECTIONAL) { + light->D = scenario->directional_lights.push_back(instance); + } + } break; + case VS::INSTANCE_GI_PROBE: { + + InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData*>(instance->base_data); + if (!gi_probe->update_element.in_list()) { + gi_probe_update_list.add(&gi_probe->update_element); + } + } break; + } + + _instance_queue_update(instance,true,true); + } +} +void VisualServerScene::instance_set_layer_mask(RID p_instance, uint32_t p_mask){ + + + Instance *instance = instance_owner.get( p_instance ); + ERR_FAIL_COND( !instance ); + + instance->layer_mask=p_mask; +} +void VisualServerScene::instance_set_transform(RID p_instance, const Transform& p_transform){ + + Instance *instance = instance_owner.get( p_instance ); + ERR_FAIL_COND( !instance ); + + if (instance->transform==p_transform) + return; //must be checked to avoid worst evil + + instance->transform=p_transform; + _instance_queue_update(instance,true); +} +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; + +} +void VisualServerScene::instance_set_blend_shape_weight(RID p_instance,int p_shape, float p_weight){ + + Instance *instance = instance_owner.get( p_instance ); + ERR_FAIL_COND( !instance ); + + if (instance->update_item.in_list()) { + _update_dirty_instance(instance); + } + + ERR_FAIL_INDEX(p_shape,instance->blend_values.size()); + instance->blend_values[p_shape]=p_weight; +} + +void VisualServerScene::instance_set_surface_material(RID p_instance,int p_surface, RID p_material){ + + Instance *instance = instance_owner.get( p_instance ); + ERR_FAIL_COND( !instance ); + + if (instance->update_item.in_list()) { + _update_dirty_instance(instance); + } + + ERR_FAIL_INDEX(p_surface,instance->materials.size()); + + if (instance->materials[p_surface].is_valid()) { + VSG::storage->material_remove_instance_owner(instance->materials[p_surface],instance); + } + instance->materials[p_surface]=p_material; + instance->base_material_changed(); + + if (instance->materials[p_surface].is_valid()) { + VSG::storage->material_add_instance_owner(instance->materials[p_surface],instance); + } + + +} + +void VisualServerScene::instance_set_visible(RID p_instance,bool p_visible) { + + Instance *instance = instance_owner.get( p_instance ); + ERR_FAIL_COND( !instance ); + + if (instance->visible==p_visible) + return; + + instance->visible=p_visible; + + + switch(instance->base_type) { + case VS::INSTANCE_LIGHT: { + if (VSG::storage->light_get_type(instance->base)!=VS::LIGHT_DIRECTIONAL && instance->octree_id && instance->scenario) { + instance->scenario->octree.set_pairable(instance->octree_id,p_visible,1<<VS::INSTANCE_LIGHT,p_visible?VS::INSTANCE_GEOMETRY_MASK:0); + } + + } break; + case VS::INSTANCE_REFLECTION_PROBE: { + if (instance->octree_id && instance->scenario) { + instance->scenario->octree.set_pairable(instance->octree_id,p_visible,1<<VS::INSTANCE_REFLECTION_PROBE,p_visible?VS::INSTANCE_GEOMETRY_MASK:0); + } + + } break; + case VS::INSTANCE_GI_PROBE: { + if (instance->octree_id && instance->scenario) { + instance->scenario->octree.set_pairable(instance->octree_id,p_visible,1<<VS::INSTANCE_GI_PROBE,p_visible?(VS::INSTANCE_GEOMETRY_MASK|(1<<VS::INSTANCE_LIGHT)):0); + } + + } break; + + } + +} + +void VisualServerScene::instance_attach_skeleton(RID p_instance,RID p_skeleton){ + + Instance *instance = instance_owner.get( p_instance ); + ERR_FAIL_COND( !instance ); + + if (instance->skeleton==p_skeleton) + return; + + if (instance->skeleton.is_valid()) { + VSG::storage->instance_remove_skeleton(p_skeleton,instance); + } + + instance->skeleton=p_skeleton; + + if (instance->skeleton.is_valid()) { + VSG::storage->instance_add_skeleton(p_skeleton,instance); + } + + _instance_queue_update(instance,true); +} + +void VisualServerScene::instance_set_exterior( RID p_instance, bool p_enabled ){ + +} +void VisualServerScene::instance_set_room( RID p_instance, RID p_room ){ + +} + +void VisualServerScene::instance_set_extra_visibility_margin( RID p_instance, real_t p_margin ){ + +} + +Vector<ObjectID> VisualServerScene::instances_cull_aabb(const Rect3& p_aabb, RID p_scenario) const { + + + Vector<ObjectID> instances; + Scenario *scenario=scenario_owner.get(p_scenario); + ERR_FAIL_COND_V(!scenario,instances); + + const_cast<VisualServerScene*>(this)->update_dirty_instances(); // check dirty instances before culling + + int culled=0; + Instance *cull[1024]; + culled=scenario->octree.cull_AABB(p_aabb,cull,1024); + + for (int i=0;i<culled;i++) { + + Instance *instance=cull[i]; + ERR_CONTINUE(!instance); + if (instance->object_ID==0) + continue; + + instances.push_back(instance->object_ID); + } + + return instances; +} +Vector<ObjectID> VisualServerScene::instances_cull_ray(const Vector3& p_from, const Vector3& p_to, RID p_scenario) const{ + + Vector<ObjectID> instances; + Scenario *scenario=scenario_owner.get(p_scenario); + ERR_FAIL_COND_V(!scenario,instances); + const_cast<VisualServerScene*>(this)->update_dirty_instances(); // check dirty instances before culling + + int culled=0; + Instance *cull[1024]; + culled=scenario->octree.cull_segment(p_from,p_to*10000,cull,1024); + + + for (int i=0;i<culled;i++) { + Instance *instance=cull[i]; + ERR_CONTINUE(!instance); + if (instance->object_ID==0) + continue; + + instances.push_back(instance->object_ID); + } + + return instances; + +} +Vector<ObjectID> VisualServerScene::instances_cull_convex(const Vector<Plane>& p_convex, RID p_scenario) const{ + + Vector<ObjectID> instances; + Scenario *scenario=scenario_owner.get(p_scenario); + ERR_FAIL_COND_V(!scenario,instances); + const_cast<VisualServerScene*>(this)->update_dirty_instances(); // check dirty instances before culling + + int culled=0; + Instance *cull[1024]; + + + culled=scenario->octree.cull_convex(p_convex,cull,1024); + + for (int i=0;i<culled;i++) { + + Instance *instance=cull[i]; + ERR_CONTINUE(!instance); + if (instance->object_ID==0) + continue; + + instances.push_back(instance->object_ID); + } + + return instances; + +} + +void VisualServerScene::instance_geometry_set_flag(RID p_instance,VS::InstanceFlags p_flags,bool p_enabled){ + + Instance *instance = instance_owner.get( p_instance ); + ERR_FAIL_COND( !instance ); + + switch(p_flags) { + + case VS::INSTANCE_FLAG_BILLBOARD: { + + instance->billboard=p_enabled; + + } break; + case VS::INSTANCE_FLAG_BILLBOARD_FIX_Y: { + + instance->billboard_y=p_enabled; + + } break; + case VS::INSTANCE_FLAG_CAST_SHADOW: { + if (p_enabled == true) { + instance->cast_shadows = VS::SHADOW_CASTING_SETTING_ON; + } + else { + instance->cast_shadows = VS::SHADOW_CASTING_SETTING_OFF; + } + + instance->base_material_changed(); // to actually compute if shadows are visible or not + + } break; + case VS::INSTANCE_FLAG_DEPH_SCALE: { + + instance->depth_scale=p_enabled; + + } break; + case VS::INSTANCE_FLAG_VISIBLE_IN_ALL_ROOMS: { + + instance->visible_in_all_rooms=p_enabled; + + } break; + + } +} +void VisualServerScene::instance_geometry_set_cast_shadows_setting(RID p_instance, VS::ShadowCastingSetting p_shadow_casting_setting) { + +} +void VisualServerScene::instance_geometry_set_material_override(RID p_instance, RID p_material){ + + Instance *instance = instance_owner.get( p_instance ); + ERR_FAIL_COND( !instance ); + + if (instance->material_override.is_valid()) { + VSG::storage->material_remove_instance_owner(instance->material_override,instance); + } + instance->material_override=p_material; + instance->base_material_changed(); + + if (instance->material_override.is_valid()) { + VSG::storage->material_add_instance_owner(instance->material_override,instance); + } + +} + + +void VisualServerScene::instance_geometry_set_draw_range(RID p_instance,float p_min,float p_max,float p_min_margin,float p_max_margin){ + +} +void VisualServerScene::instance_geometry_set_as_instance_lod(RID p_instance,RID p_as_lod_of_instance){ + +} + + +void VisualServerScene::_update_instance(Instance *p_instance) { + + p_instance->version++; + + if (p_instance->base_type == VS::INSTANCE_LIGHT) { + + InstanceLightData *light = static_cast<InstanceLightData*>(p_instance->base_data); + + VSG::scene_render->light_instance_set_transform( light->instance, p_instance->transform ); + light->shadow_dirty=true; + + } + + if (p_instance->base_type == VS::INSTANCE_REFLECTION_PROBE) { + + InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData*>(p_instance->base_data); + + VSG::scene_render->reflection_probe_instance_set_transform( reflection_probe->instance, p_instance->transform ); + reflection_probe->reflection_dirty=true; + + } + + + if (p_instance->aabb.has_no_surface()) + return; + +#if 0 + if (p_instance->base_type == VS::INSTANCE_PARTICLES) { + + rasterizer->particles_instance_set_transform( p_instance->particles_info->instance, p_instance->data.transform ); + } + +#endif + if ((1<<p_instance->base_type)&VS::INSTANCE_GEOMETRY_MASK) { + + InstanceGeometryData *geom = static_cast<InstanceGeometryData*>(p_instance->base_data); + //make sure lights are updated if it casts shadow + + if (geom->can_cast_shadows) { + for (List<Instance*>::Element *E=geom->lighting.front();E;E=E->next()) { + InstanceLightData *light = static_cast<InstanceLightData*>(E->get()->base_data); + light->shadow_dirty=true; + } + } + + } +#if 0 + else if (p_instance->base_type == INSTANCE_ROOM) { + + p_instance->room_info->affine_inverse=p_instance->data.transform.affine_inverse(); + } else if (p_instance->base_type == INSTANCE_GI_PROBE) { + + Transform scale; + scale.basis.scale(p_instance->gi_probe_info->gi_probe->octree_aabb.size); + scale.origin=p_instance->gi_probe_info->gi_probe->octree_aabb.pos; + //print_line("scale: "+scale); + p_instance->gi_probe_info->affine_inverse=(p_instance->data.transform*scale).affine_inverse(); + } + + +#endif + + p_instance->mirror = p_instance->transform.basis.determinant() < 0.0; + + Rect3 new_aabb; +#if 0 + if (p_instance->base_type==INSTANCE_PORTAL) { + + //portals need to be transformed in a special way, so they don't become too wide if they have scale.. + Transform portal_xform = p_instance->data.transform; + portal_xform.basis.set_axis(2,portal_xform.basis.get_axis(2).normalized()); + + p_instance->portal_info->plane_cache=Plane( p_instance->data.transform.origin, portal_xform.basis.get_axis(2)); + int point_count=p_instance->portal_info->portal->shape.size(); + p_instance->portal_info->transformed_point_cache.resize(point_count); + + AABB portal_aabb; + + for(int i=0;i<point_count;i++) { + + Point2 src = p_instance->portal_info->portal->shape[i]; + Vector3 point = portal_xform.xform(Vector3(src.x,src.y,0)); + p_instance->portal_info->transformed_point_cache[i]=point; + if (i==0) + portal_aabb.pos=point; + else + portal_aabb.expand_to(point); + } + + portal_aabb.grow_by(p_instance->portal_info->portal->connect_range); + + new_aabb = portal_aabb; + + } else { +#endif + new_aabb = p_instance->transform.xform(p_instance->aabb); +#if 0 + } +#endif + + + p_instance->transformed_aabb=new_aabb; + + if (!p_instance->scenario) { + + return; + } + + + + if (p_instance->octree_id==0) { + + uint32_t base_type = 1<<p_instance->base_type; + uint32_t pairable_mask=0; + bool pairable=false; + + if (p_instance->base_type == VS::INSTANCE_LIGHT || p_instance->base_type==VS::INSTANCE_REFLECTION_PROBE) { + + pairable_mask=p_instance->visible?VS::INSTANCE_GEOMETRY_MASK:0; + pairable=true; + } + + if (p_instance->base_type == VS::INSTANCE_GI_PROBE) { + //lights and geometries + pairable_mask=p_instance->visible?VS::INSTANCE_GEOMETRY_MASK|(1<<VS::INSTANCE_LIGHT):0; + pairable=true; + } + +#if 0 + + if (p_instance->base_type == VS::INSTANCE_PORTAL) { + + pairable_mask=(1<<INSTANCE_PORTAL); + pairable=true; + } + + if (p_instance->base_type == VS::INSTANCE_GI_PROBE_SAMPLER) { + + pairable_mask=(1<<INSTANCE_GI_PROBE); + pairable=true; + } + + + if (!p_instance->room && (1<<p_instance->base_type)&VS::INSTANCE_GEOMETRY_MASK) { + + base_type|=VS::INSTANCE_ROOMLESS_MASK; + } + + if (p_instance->base_type == VS::INSTANCE_ROOM) { + + pairable_mask=INSTANCE_ROOMLESS_MASK; + pairable=true; + } +#endif + + // not inside octree + p_instance->octree_id = p_instance->scenario->octree.create(p_instance,new_aabb,0,pairable,base_type,pairable_mask); + + } else { + + /* + if (new_aabb==p_instance->data.transformed_aabb) + return; + */ + + p_instance->scenario->octree.move(p_instance->octree_id,new_aabb); + } +#if 0 + if (p_instance->base_type==INSTANCE_PORTAL) { + + _portal_attempt_connect(p_instance); + } + + if (!p_instance->room && (1<<p_instance->base_type)&INSTANCE_GEOMETRY_MASK) { + + _instance_validate_autorooms(p_instance); + } + + if (p_instance->base_type == INSTANCE_ROOM) { + + for(Set<Instance*>::Element *E=p_instance->room_info->owned_autoroom_geometry.front();E;E=E->next()) + _instance_validate_autorooms(E->get()); + } +#endif + +} + +void VisualServerScene::_update_instance_aabb(Instance *p_instance) { + + Rect3 new_aabb; + + ERR_FAIL_COND(p_instance->base_type!=VS::INSTANCE_NONE && !p_instance->base.is_valid()); + + switch(p_instance->base_type) { + case VisualServer::INSTANCE_NONE: { + + // do nothing + } break; + case VisualServer::INSTANCE_MESH: { + + new_aabb = VSG::storage->mesh_get_aabb(p_instance->base,p_instance->skeleton); + + } break; + + case VisualServer::INSTANCE_MULTIMESH: { + + new_aabb = VSG::storage->multimesh_get_aabb(p_instance->base); + + } break; + case VisualServer::INSTANCE_IMMEDIATE: { + + new_aabb = VSG::storage->immediate_get_aabb(p_instance->base); + + + } break; +#if 0 + + case VisualServer::INSTANCE_PARTICLES: { + + new_aabb = rasterizer->particles_get_aabb(p_instance->base); + + + } break; +#endif + case VisualServer::INSTANCE_LIGHT: { + + new_aabb = VSG::storage->light_get_aabb(p_instance->base); + + } break; + case VisualServer::INSTANCE_REFLECTION_PROBE: { + + new_aabb = VSG::storage->reflection_probe_get_aabb(p_instance->base); + + } break; + case VisualServer::INSTANCE_GI_PROBE: { + + new_aabb = VSG::storage->gi_probe_get_bounds(p_instance->base); + + } break; + +#if 0 + case VisualServer::INSTANCE_ROOM: { + + Room *room = room_owner.get( p_instance->base ); + ERR_FAIL_COND(!room); + new_aabb=room->bounds.get_aabb(); + + } break; + case VisualServer::INSTANCE_PORTAL: { + + Portal *portal = portal_owner.get( p_instance->base ); + ERR_FAIL_COND(!portal); + for (int i=0;i<portal->shape.size();i++) { + + Vector3 point( portal->shape[i].x, portal->shape[i].y, 0 ); + if (i==0) { + + new_aabb.pos=point; + new_aabb.size.z=0.01; // make it not flat for octree + } else { + + new_aabb.expand_to(point); + } + } + + } break; + case VisualServer::INSTANCE_GI_PROBE: { + + BakedLight *gi_probe = gi_probe_owner.get( p_instance->base ); + ERR_FAIL_COND(!gi_probe); + new_aabb=gi_probe->octree_aabb; + + } break; + case VisualServer::INSTANCE_GI_PROBE_SAMPLER: { + + BakedLightSampler *gi_probe_sampler = gi_probe_sampler_owner.get( p_instance->base ); + ERR_FAIL_COND(!gi_probe_sampler); + float radius = gi_probe_sampler->params[VS::BAKED_LIGHT_SAMPLER_RADIUS]; + + new_aabb=AABB(Vector3(-radius,-radius,-radius),Vector3(radius*2,radius*2,radius*2)); + + } break; +#endif + default: {} + } + + if (p_instance->extra_margin) + new_aabb.grow_by(p_instance->extra_margin); + + p_instance->aabb=new_aabb; + +} + + + + + +void VisualServerScene::_light_instance_update_shadow(Instance *p_instance,const Transform p_cam_transform,const CameraMatrix& p_cam_projection,bool p_cam_orthogonal,RID p_shadow_atlas,Scenario* p_scenario) { + + + InstanceLightData * light = static_cast<InstanceLightData*>(p_instance->base_data); + + switch(VSG::storage->light_get_type(p_instance->base)) { + + case VS::LIGHT_DIRECTIONAL: { + + float max_distance =p_cam_projection.get_z_far(); + float shadow_max = VSG::storage->light_get_param(p_instance->base,VS::LIGHT_PARAM_SHADOW_MAX_DISTANCE); + if (shadow_max>0) { + max_distance=MIN(shadow_max,max_distance); + } + max_distance=MAX(max_distance,p_cam_projection.get_z_near()+0.001); + + float range = max_distance-p_cam_projection.get_z_near(); + + int splits=0; + switch(VSG::storage->light_directional_get_shadow_mode(p_instance->base)) { + case VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL: splits=1; break; + case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: splits=2; break; + case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: splits=4; break; + } + + float distances[5]; + + distances[0]=p_cam_projection.get_z_near(); + for(int i=0;i<splits;i++) { + distances[i+1]=p_cam_projection.get_z_near()+VSG::storage->light_get_param(p_instance->base,VS::LightParam(VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET+i))*range; + }; + + distances[splits]=max_distance; + + float texture_size=VSG::scene_render->get_directional_light_shadow_size(light->instance); + + bool overlap = VSG::storage->light_directional_get_blend_splits(p_instance->base); + + for (int i=0;i<splits;i++) { + + // setup a camera matrix for that range! + CameraMatrix camera_matrix; + + float aspect = p_cam_projection.get_aspect(); + + + if (p_cam_orthogonal) { + + float w,h; + p_cam_projection.get_viewport_size(w,h); + camera_matrix.set_orthogonal(w,aspect,distances[(i==0 || !overlap )?i:i-1],distances[i+1],false); + } else { + + float fov = p_cam_projection.get_fov(); + camera_matrix.set_perspective(fov,aspect,distances[(i==0 || !overlap )?i:i-1],distances[i+1],false); + } + + //obtain the frustum endpoints + + Vector3 endpoints[8]; // frustum plane endpoints + bool res = camera_matrix.get_endpoints(p_cam_transform,endpoints); + ERR_CONTINUE(!res); + + // obtain the light frustm ranges (given endpoints) + + Vector3 x_vec=p_instance->transform.basis.get_axis( Vector3::AXIS_X ).normalized(); + Vector3 y_vec=p_instance->transform.basis.get_axis( Vector3::AXIS_Y ).normalized(); + Vector3 z_vec=p_instance->transform.basis.get_axis( Vector3::AXIS_Z ).normalized(); + //z_vec points agsint the camera, like in default opengl + + float x_min,x_max; + float y_min,y_max; + float z_min,z_max; + + float x_min_cam,x_max_cam; + float y_min_cam,y_max_cam; + float z_min_cam,z_max_cam; + + + //used for culling + for(int j=0;j<8;j++) { + + float d_x=x_vec.dot(endpoints[j]); + float d_y=y_vec.dot(endpoints[j]); + float d_z=z_vec.dot(endpoints[j]); + + if (j==0 || d_x<x_min) + x_min=d_x; + if (j==0 || d_x>x_max) + x_max=d_x; + + if (j==0 || d_y<y_min) + y_min=d_y; + if (j==0 || d_y>y_max) + y_max=d_y; + + if (j==0 || d_z<z_min) + z_min=d_z; + if (j==0 || d_z>z_max) + z_max=d_z; + + + } + + + + + + { + //camera viewport stuff + //this trick here is what stabilizes the shadow (make potential jaggies to not move) + //at the cost of some wasted resolution. Still the quality increase is very well worth it + + + Vector3 center; + + for(int j=0;j<8;j++) { + + center+=endpoints[j]; + } + center/=8.0; + + //center=x_vec*(x_max-x_min)*0.5 + y_vec*(y_max-y_min)*0.5 + z_vec*(z_max-z_min)*0.5; + + float radius=0; + + for(int j=0;j<8;j++) { + + float d = center.distance_to(endpoints[j]); + if (d>radius) + radius=d; + } + + + radius *= texture_size/(texture_size-2.0); //add a texel by each side, so stepified texture will always fit + + x_max_cam=x_vec.dot(center)+radius; + x_min_cam=x_vec.dot(center)-radius; + y_max_cam=y_vec.dot(center)+radius; + y_min_cam=y_vec.dot(center)-radius; + z_max_cam=z_vec.dot(center)+radius; + z_min_cam=z_vec.dot(center)-radius; + + float unit = radius*2.0/texture_size; + + x_max_cam=Math::stepify(x_max_cam,unit); + x_min_cam=Math::stepify(x_min_cam,unit); + y_max_cam=Math::stepify(y_max_cam,unit); + y_min_cam=Math::stepify(y_min_cam,unit); + + } + + //now that we now all ranges, we can proceed to make the light frustum planes, for culling octree + + Vector<Plane> light_frustum_planes; + light_frustum_planes.resize(6); + + //right/left + light_frustum_planes[0]=Plane( x_vec, x_max ); + light_frustum_planes[1]=Plane( -x_vec, -x_min ); + //top/bottom + light_frustum_planes[2]=Plane( y_vec, y_max ); + light_frustum_planes[3]=Plane( -y_vec, -y_min ); + //near/far + light_frustum_planes[4]=Plane( z_vec, z_max+1e6 ); + light_frustum_planes[5]=Plane( -z_vec, -z_min ); // z_min is ok, since casters further than far-light plane are not needed + + int cull_count = p_scenario->octree.cull_convex(light_frustum_planes,instance_shadow_cull_result,MAX_INSTANCE_CULL,VS::INSTANCE_GEOMETRY_MASK); + + // a pre pass will need to be needed to determine the actual z-near to be used + + + for (int j=0;j<cull_count;j++) { + + float min,max; + Instance *instance = instance_shadow_cull_result[j]; + if (!instance->visible || !((1<<instance->base_type)&VS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData*>(instance->base_data)->can_cast_shadows) { + cull_count--; + SWAP(instance_shadow_cull_result[j],instance_shadow_cull_result[cull_count]); + j--; + continue; + + } + + + instance->transformed_aabb.project_range_in_plane(Plane(z_vec,0),min,max); + if (max>z_max) + z_max=max; + } + + { + CameraMatrix ortho_camera; + real_t half_x = (x_max_cam-x_min_cam) * 0.5; + real_t half_y = (y_max_cam-y_min_cam) * 0.5; + + + ortho_camera.set_orthogonal( -half_x, half_x,-half_y,half_y, 0, (z_max-z_min_cam) ); + + Transform ortho_transform; + ortho_transform.basis=p_instance->transform.basis; + ortho_transform.origin=x_vec*(x_min_cam+half_x)+y_vec*(y_min_cam+half_y)+z_vec*z_max; + + VSG::scene_render->light_instance_set_shadow_transform(light->instance,ortho_camera,ortho_transform,0,distances[i+1],i); + } + + + + VSG::scene_render->render_shadow(light->instance,p_shadow_atlas,i,(RasterizerScene::InstanceBase**)instance_shadow_cull_result,cull_count); + + } + + } break; + case VS::LIGHT_OMNI: { + + VS::LightOmniShadowMode shadow_mode = VSG::storage->light_omni_get_shadow_mode(p_instance->base); + + switch(shadow_mode) { + case VS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID: { + + for(int i=0;i<2;i++) { + + //using this one ensures that raster deferred will have it + + float radius = VSG::storage->light_get_param( p_instance->base, VS::LIGHT_PARAM_RANGE); + + float z =i==0?-1:1; + Vector<Plane> planes; + planes.resize(5); + planes[0]=p_instance->transform.xform(Plane(Vector3(0,0,z),radius)); + planes[1]=p_instance->transform.xform(Plane(Vector3(1,0,z).normalized(),radius)); + planes[2]=p_instance->transform.xform(Plane(Vector3(-1,0,z).normalized(),radius)); + planes[3]=p_instance->transform.xform(Plane(Vector3(0,1,z).normalized(),radius)); + planes[4]=p_instance->transform.xform(Plane(Vector3(0,-1,z).normalized(),radius)); + + + int cull_count = p_scenario->octree.cull_convex(planes,instance_shadow_cull_result,MAX_INSTANCE_CULL,VS::INSTANCE_GEOMETRY_MASK); + + for (int j=0;j<cull_count;j++) { + + Instance *instance = instance_shadow_cull_result[j]; + if (!instance->visible || !((1<<instance->base_type)&VS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData*>(instance->base_data)->can_cast_shadows) { + cull_count--; + SWAP(instance_shadow_cull_result[j],instance_shadow_cull_result[cull_count]); + j--; + + } + } + + VSG::scene_render->light_instance_set_shadow_transform(light->instance,CameraMatrix(),p_instance->transform,radius,0,i); + VSG::scene_render->render_shadow(light->instance,p_shadow_atlas,i,(RasterizerScene::InstanceBase**)instance_shadow_cull_result,cull_count); + } + } break; + case VS::LIGHT_OMNI_SHADOW_CUBE: { + + float radius = VSG::storage->light_get_param( p_instance->base, VS::LIGHT_PARAM_RANGE); + CameraMatrix cm; + cm.set_perspective(90,1,0.01,radius); + + for(int i=0;i<6;i++) { + + //using this one ensures that raster deferred will have it + + + + static const Vector3 view_normals[6]={ + Vector3(-1, 0, 0), + Vector3(+1, 0, 0), + Vector3( 0,-1, 0), + Vector3( 0,+1, 0), + Vector3( 0, 0,-1), + Vector3( 0, 0,+1) + }; + static const Vector3 view_up[6]={ + Vector3( 0,-1, 0), + Vector3( 0,-1, 0), + Vector3( 0, 0,-1), + Vector3( 0, 0,+1), + Vector3( 0,-1, 0), + Vector3( 0,-1, 0) + }; + + Transform xform = p_instance->transform * Transform().looking_at(view_normals[i],view_up[i]); + + + Vector<Plane> planes = cm.get_projection_planes(xform); + + int cull_count = p_scenario->octree.cull_convex(planes,instance_shadow_cull_result,MAX_INSTANCE_CULL,VS::INSTANCE_GEOMETRY_MASK); + + for (int j=0;j<cull_count;j++) { + + Instance *instance = instance_shadow_cull_result[j]; + if (!instance->visible || !((1<<instance->base_type)&VS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData*>(instance->base_data)->can_cast_shadows) { + cull_count--; + SWAP(instance_shadow_cull_result[j],instance_shadow_cull_result[cull_count]); + j--; + + } + } + + + VSG::scene_render->light_instance_set_shadow_transform(light->instance,cm,xform,radius,0,i); + VSG::scene_render->render_shadow(light->instance,p_shadow_atlas,i,(RasterizerScene::InstanceBase**)instance_shadow_cull_result,cull_count); + } + + //restore the regular DP matrix + VSG::scene_render->light_instance_set_shadow_transform(light->instance,CameraMatrix(),p_instance->transform,radius,0,0); + + } break; + } + + + } break; + case VS::LIGHT_SPOT: { + + + float radius = VSG::storage->light_get_param( p_instance->base, VS::LIGHT_PARAM_RANGE); + float angle = VSG::storage->light_get_param( p_instance->base, VS::LIGHT_PARAM_SPOT_ANGLE); + + CameraMatrix cm; + cm.set_perspective( angle*2.0, 1.0, 0.01, radius ); + + + Vector<Plane> planes = cm.get_projection_planes(p_instance->transform); + int cull_count = p_scenario->octree.cull_convex(planes,instance_shadow_cull_result,MAX_INSTANCE_CULL,VS::INSTANCE_GEOMETRY_MASK); + + for (int j=0;j<cull_count;j++) { + + Instance *instance = instance_shadow_cull_result[j]; + if (!instance->visible || !((1<<instance->base_type)&VS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData*>(instance->base_data)->can_cast_shadows) { + cull_count--; + SWAP(instance_shadow_cull_result[j],instance_shadow_cull_result[cull_count]); + j--; + + } + } + + + VSG::scene_render->light_instance_set_shadow_transform(light->instance,cm,p_instance->transform,radius,0,0); + VSG::scene_render->render_shadow(light->instance,p_shadow_atlas,0,(RasterizerScene::InstanceBase**)instance_shadow_cull_result,cull_count); + + } break; + } + +} + + +void VisualServerScene::render_camera(RID p_camera, RID p_scenario,Size2 p_viewport_size,RID p_shadow_atlas) { + + Camera *camera = camera_owner.getornull(p_camera); + ERR_FAIL_COND(!camera); + + /* STEP 1 - SETUP CAMERA */ + CameraMatrix camera_matrix; + bool ortho=false; + + + switch(camera->type) { + case Camera::ORTHOGONAL: { + + camera_matrix.set_orthogonal( + camera->size, + p_viewport_size.width / (float)p_viewport_size.height, + camera->znear, + camera->zfar, + camera->vaspect + + ); + ortho=true; + } break; + case Camera::PERSPECTIVE: { + + camera_matrix.set_perspective( + camera->fov, + p_viewport_size.width / (float)p_viewport_size.height, + camera->znear, + camera->zfar, + camera->vaspect + + ); + ortho=false; + + } break; + } + + _render_scene(camera->transform,camera_matrix,ortho,camera->env,camera->visible_layers,p_scenario,p_shadow_atlas,RID(),-1); + +} + + +void VisualServerScene::_render_scene(const Transform p_cam_transform,const CameraMatrix& p_cam_projection,bool p_cam_orthogonal,RID p_force_environment,uint32_t p_visible_layers, RID p_scenario,RID p_shadow_atlas,RID p_reflection_probe,int p_reflection_probe_pass) { + + + + Scenario *scenario = scenario_owner.getornull(p_scenario); + + render_pass++; + uint32_t camera_layer_mask=p_visible_layers; + + VSG::scene_render->set_scene_pass(render_pass); + + + //rasterizer->set_camera(camera->transform, camera_matrix,ortho); + + Vector<Plane> planes = p_cam_projection.get_projection_planes(p_cam_transform); + + Plane near_plane(p_cam_transform.origin,-p_cam_transform.basis.get_axis(2).normalized()); + float z_far = p_cam_projection.get_z_far(); + + /* STEP 2 - CULL */ + int cull_count = scenario->octree.cull_convex(planes,instance_cull_result,MAX_INSTANCE_CULL); + light_cull_count=0; + + reflection_probe_cull_count=0; + + //light_samplers_culled=0; + +/* print_line("OT: "+rtos( (OS::get_singleton()->get_ticks_usec()-t)/1000.0)); + print_line("OTO: "+itos(p_scenario->octree.get_octant_count())); + //print_line("OTE: "+itos(p_scenario->octree.get_elem_count())); + print_line("OTP: "+itos(p_scenario->octree.get_pair_count())); +*/ + + /* STEP 3 - PROCESS PORTALS, VALIDATE ROOMS */ + + + // compute portals +#if 0 + exterior_visited=false; + exterior_portal_cull_count=0; + + if (room_cull_enabled) { + for(int i=0;i<cull_count;i++) { + + Instance *ins = instance_cull_result[i]; + ins->last_render_pass=render_pass; + + if (ins->base_type!=INSTANCE_PORTAL) + continue; + + if (ins->room) + continue; + + ERR_CONTINUE(exterior_portal_cull_count>=MAX_EXTERIOR_PORTALS); + exterior_portal_cull_result[exterior_portal_cull_count++]=ins; + + } + + room_cull_count = p_scenario->octree.cull_point(camera->transform.origin,room_cull_result,MAX_ROOM_CULL,NULL,(1<<INSTANCE_ROOM)|(1<<INSTANCE_PORTAL)); + + + Set<Instance*> current_rooms; + Set<Instance*> portal_rooms; + //add to set + for(int i=0;i<room_cull_count;i++) { + + if (room_cull_result[i]->base_type==INSTANCE_ROOM) { + current_rooms.insert(room_cull_result[i]); + } + if (room_cull_result[i]->base_type==INSTANCE_PORTAL) { + //assume inside that room if also inside the portal.. + if (room_cull_result[i]->room) { + portal_rooms.insert(room_cull_result[i]->room); + } + + SWAP(room_cull_result[i],room_cull_result[room_cull_count-1]); + room_cull_count--; + i--; + } + } + + //remove from set if it has a parent room or BSP doesn't contain + for(int i=0;i<room_cull_count;i++) { + Instance *r = room_cull_result[i]; + + //check inside BSP + Vector3 room_local_point = r->room_info->affine_inverse.xform( camera->transform.origin ); + + if (!portal_rooms.has(r) && !r->room_info->room->bounds.point_is_inside(room_local_point)) { + + current_rooms.erase(r); + continue; + } + + //check parent + while (r->room) {// has parent room + + current_rooms.erase(r); + r=r->room; + } + + } + + if (current_rooms.size()) { + //camera is inside a room + // go through rooms + for(Set<Instance*>::Element *E=current_rooms.front();E;E=E->next()) { + _cull_room(camera,E->get()); + } + + } else { + //start from exterior + _cull_room(camera,NULL); + + } + } + +#endif + /* STEP 4 - REMOVE FURTHER CULLED OBJECTS, ADD LIGHTS */ + + for(int i=0;i<cull_count;i++) { + + Instance *ins = instance_cull_result[i]; + + bool keep=false; + + if ((camera_layer_mask&ins->layer_mask)==0) { + + //failure + } else if (ins->base_type==VS::INSTANCE_LIGHT && ins->visible) { + + + if (ins->visible && light_cull_count<MAX_LIGHTS_CULLED) { + + InstanceLightData * light = static_cast<InstanceLightData*>(ins->base_data); + + if (!light->geometries.empty()) { + //do not add this light if no geometry is affected by it.. + light_cull_result[light_cull_count]=ins; + light_instance_cull_result[light_cull_count]=light->instance; + if (p_shadow_atlas.is_valid() && VSG::storage->light_has_shadow(ins->base)) { + VSG::scene_render->light_instance_mark_visible(light->instance); //mark it visible for shadow allocation later + } + + light_cull_count++; + } + + + } + } else if (ins->base_type==VS::INSTANCE_REFLECTION_PROBE && ins->visible) { + + + if (ins->visible && reflection_probe_cull_count<MAX_REFLECTION_PROBES_CULLED) { + + InstanceReflectionProbeData * reflection_probe = static_cast<InstanceReflectionProbeData*>(ins->base_data); + + if (p_reflection_probe!=reflection_probe->instance) { + //avoid entering The Matrix + + if (!reflection_probe->geometries.empty()) { + //do not add this light if no geometry is affected by it.. + + if (reflection_probe->reflection_dirty || VSG::scene_render->reflection_probe_instance_needs_redraw(reflection_probe->instance)) { + if (!reflection_probe->update_list.in_list()) { + reflection_probe->render_step=0; + reflection_probe_render_list.add(&reflection_probe->update_list); + } + + reflection_probe->reflection_dirty=false; + } + + if (VSG::scene_render->reflection_probe_instance_has_reflection(reflection_probe->instance)) { + reflection_probe_instance_cull_result[reflection_probe_cull_count]=reflection_probe->instance; + reflection_probe_cull_count++; + } + + } + } + } + + } else if (ins->base_type==VS::INSTANCE_GI_PROBE && ins->visible) { + + InstanceGIProbeData * gi_probe = static_cast<InstanceGIProbeData*>(ins->base_data); + if (!gi_probe->update_element.in_list()) { + gi_probe_update_list.add(&gi_probe->update_element); + } + + } else if ((1<<ins->base_type)&VS::INSTANCE_GEOMETRY_MASK && ins->visible && ins->cast_shadows!=VS::SHADOW_CASTING_SETTING_SHADOWS_ONLY) { + + keep=true; +#if 0 + bool discarded=false; + + if (ins->draw_range_end>0) { + + float d = cull_range.nearp.distance_to(ins->data.transform.origin); + if (d<0) + d=0; + discarded=(d<ins->draw_range_begin || d>=ins->draw_range_end); + + + } + + if (!discarded) { + + // test if this geometry should be visible + + if (room_cull_enabled) { + + + if (ins->visible_in_all_rooms) { + keep=true; + } else if (ins->room) { + + if (ins->room->room_info->last_visited_pass==render_pass) + keep=true; + } else if (ins->auto_rooms.size()) { + + + for(Set<Instance*>::Element *E=ins->auto_rooms.front();E;E=E->next()) { + + if (E->get()->room_info->last_visited_pass==render_pass) { + keep=true; + break; + } + } + } else if(exterior_visited) + keep=true; + } else { + + keep=true; + } + + + } + + + if (keep) { + // update cull range + float min,max; + ins->transformed_aabb.project_range_in_plane(cull_range.nearp,min,max); + + if (min<cull_range.min) + cull_range.min=min; + if (max>cull_range.max) + cull_range.max=max; + + if (ins->sampled_light && ins->sampled_light->gi_probe_sampler_info->last_pass!=render_pass) { + if (light_samplers_culled<MAX_LIGHT_SAMPLERS) { + light_sampler_cull_result[light_samplers_culled++]=ins->sampled_light; + ins->sampled_light->gi_probe_sampler_info->last_pass=render_pass; + } + } + } +#endif + + + InstanceGeometryData * geom = static_cast<InstanceGeometryData*>(ins->base_data); + + + if (geom->lighting_dirty) { + int l=0; + //only called when lights AABB enter/exit this geometry + ins->light_instances.resize(geom->lighting.size()); + + for (List<Instance*>::Element *E=geom->lighting.front();E;E=E->next()) { + + InstanceLightData * light = static_cast<InstanceLightData*>(E->get()->base_data); + + ins->light_instances[l++]=light->instance; + } + + geom->lighting_dirty=false; + } + + if (geom->reflection_dirty) { + int l=0; + //only called when reflection probe AABB enter/exit this geometry + ins->reflection_probe_instances.resize(geom->reflection_probes.size()); + + for (List<Instance*>::Element *E=geom->reflection_probes.front();E;E=E->next()) { + + InstanceReflectionProbeData * reflection_probe = static_cast<InstanceReflectionProbeData*>(E->get()->base_data); + + ins->reflection_probe_instances[l++]=reflection_probe->instance; + } + + geom->reflection_dirty=false; + } + + if (geom->gi_probes_dirty) { + int l=0; + //only called when reflection probe AABB enter/exit this geometry + ins->gi_probe_instances.resize(geom->gi_probes.size()); + + for (List<Instance*>::Element *E=geom->gi_probes.front();E;E=E->next()) { + + InstanceGIProbeData * gi_probe = static_cast<InstanceGIProbeData*>(E->get()->base_data); + + ins->gi_probe_instances[l++]=gi_probe->probe_instance; + } + + geom->gi_probes_dirty=false; + } + + ins->depth = near_plane.distance_to(ins->transform.origin); + ins->depth_layer=CLAMP(int(ins->depth*8/z_far),0,7); + + } + + if (!keep) { + // remove, no reason to keep + cull_count--; + SWAP( instance_cull_result[i], instance_cull_result[ cull_count ] ); + i--; + ins->last_render_pass=0; // make invalid + } else { + + ins->last_render_pass=render_pass; + } + } + + /* STEP 5 - PROCESS LIGHTS */ + + RID *directional_light_ptr=&light_instance_cull_result[light_cull_count]; + int directional_light_count=0; + + // directional lights + { + + Instance** lights_with_shadow = (Instance**)alloca(sizeof(Instance*)*scenario->directional_lights.size()); + int directional_shadow_count=0; + + for (List<Instance*>::Element *E=scenario->directional_lights.front();E;E=E->next()) { + + if (light_cull_count+directional_light_count>=MAX_LIGHTS_CULLED) { + break; + } + + if (!E->get()->visible) + continue; + + InstanceLightData * light = static_cast<InstanceLightData*>(E->get()->base_data); + + + //check shadow.. + + + if (light && p_shadow_atlas.is_valid() && VSG::storage->light_has_shadow(E->get()->base)) { + lights_with_shadow[directional_shadow_count++]=E->get(); + + } + + //add to list + + directional_light_ptr[directional_light_count++]=light->instance; + } + + VSG::scene_render->set_directional_shadow_count(directional_shadow_count); + + for(int i=0;i<directional_shadow_count;i++) { + + _light_instance_update_shadow(lights_with_shadow[i],p_cam_transform,p_cam_projection,p_cam_orthogonal,p_shadow_atlas,scenario); + + } + } + + + { //setup shadow maps + + //SortArray<Instance*,_InstanceLightsort> sorter; + //sorter.sort(light_cull_result,light_cull_count); + for (int i=0;i<light_cull_count;i++) { + + Instance *ins = light_cull_result[i]; + + if (!p_shadow_atlas.is_valid() || !VSG::storage->light_has_shadow(ins->base)) + continue; + + InstanceLightData * light = static_cast<InstanceLightData*>(ins->base_data); + + float coverage; + + { //compute coverage + + + Transform cam_xf = p_cam_transform; + float zn = p_cam_projection.get_z_near(); + Plane p (cam_xf.origin + cam_xf.basis.get_axis(2) * -zn, -cam_xf.basis.get_axis(2) ); //camera near plane + + float vp_w,vp_h; //near plane size in screen coordinates + p_cam_projection.get_viewport_size(vp_w,vp_h); + + + switch(VSG::storage->light_get_type(ins->base)) { + + case VS::LIGHT_OMNI: { + + float radius = VSG::storage->light_get_param(ins->base,VS::LIGHT_PARAM_RANGE); + + //get two points parallel to near plane + Vector3 points[2]={ + ins->transform.origin, + ins->transform.origin+cam_xf.basis.get_axis(0)*radius + }; + + if (!p_cam_orthogonal) { + //if using perspetive, map them to near plane + for(int j=0;j<2;j++) { + if (p.distance_to(points[j]) < 0 ) { + points[j].z=-zn; //small hack to keep size constant when hitting the screen + + } + + p.intersects_segment(cam_xf.origin,points[j],&points[j]); //map to plane + } + + + } + + float screen_diameter = points[0].distance_to(points[1])*2; + coverage = screen_diameter / (vp_w+vp_h); + } break; + case VS::LIGHT_SPOT: { + + float radius = VSG::storage->light_get_param(ins->base,VS::LIGHT_PARAM_RANGE); + float angle = VSG::storage->light_get_param(ins->base,VS::LIGHT_PARAM_SPOT_ANGLE); + + + float w = radius*Math::sin(Math::deg2rad(angle)); + float d = radius*Math::cos(Math::deg2rad(angle)); + + + Vector3 base = ins->transform.origin-ins->transform.basis.get_axis(2).normalized()*d; + + Vector3 points[2]={ + base, + base+cam_xf.basis.get_axis(0)*w + }; + + if (!p_cam_orthogonal) { + //if using perspetive, map them to near plane + for(int j=0;j<2;j++) { + if (p.distance_to(points[j]) < 0 ) { + points[j].z=-zn; //small hack to keep size constant when hitting the screen + + } + + p.intersects_segment(cam_xf.origin,points[j],&points[j]); //map to plane + } + + + } + + float screen_diameter = points[0].distance_to(points[1])*2; + coverage = screen_diameter / (vp_w+vp_h); + + + } break; + default: { + ERR_PRINT("Invalid Light Type"); + } + } + + } + + + if (light->shadow_dirty) { + light->last_version++; + light->shadow_dirty=false; + } + + + bool redraw = VSG::scene_render->shadow_atlas_update_light(p_shadow_atlas,light->instance,coverage,light->last_version); + + if (redraw) { + //must redraw! + _light_instance_update_shadow(ins,p_cam_transform,p_cam_projection,p_cam_orthogonal,p_shadow_atlas,scenario); + } + + } + } + + /* ENVIRONMENT */ + + RID environment; + if (p_force_environment.is_valid()) //camera has more environment priority + environment=p_force_environment; + else if (scenario->environment.is_valid()) + environment=scenario->environment; + else + environment=scenario->fallback_environment; + +#if 0 + /* STEP 6 - SAMPLE BAKED LIGHT */ + + bool islinear =false; + if (environment.is_valid()) { + islinear = rasterizer->environment_is_fx_enabled(environment,VS::ENV_FX_SRGB); + } + + for(int i=0;i<light_samplers_culled;i++) { + + _process_sampled_light(camera->transform,light_sampler_cull_result[i],islinear); + } +#endif + /* STEP 7 - PROCESS GEOMETRY AND DRAW SCENE*/ + + VSG::scene_render->render_scene(p_cam_transform, p_cam_projection,p_cam_orthogonal,(RasterizerScene::InstanceBase**)instance_cull_result,cull_count,light_instance_cull_result,light_cull_count+directional_light_count,reflection_probe_instance_cull_result,reflection_probe_cull_count,environment,p_shadow_atlas,scenario->reflection_atlas,p_reflection_probe,p_reflection_probe_pass); + + +} + +bool VisualServerScene::_render_reflection_probe_step(Instance* p_instance,int p_step) { + + InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData*>(p_instance->base_data); + Scenario *scenario = p_instance->scenario; + ERR_FAIL_COND_V(!scenario,true); + + if (p_step==0) { + + if (!VSG::scene_render->reflection_probe_instance_begin_render(reflection_probe->instance,scenario->reflection_atlas)) { + return true; //sorry, all full :( + } + } + + if (p_step>=0 && p_step<6) { + + static const Vector3 view_normals[6]={ + Vector3(-1, 0, 0), + Vector3(+1, 0, 0), + Vector3( 0,-1, 0), + Vector3( 0,+1, 0), + Vector3( 0, 0,-1), + Vector3( 0, 0,+1) + }; + + Vector3 extents = VSG::storage->reflection_probe_get_extents(p_instance->base); + Vector3 origin_offset = VSG::storage->reflection_probe_get_origin_offset(p_instance->base); + float max_distance = VSG::storage->reflection_probe_get_origin_max_distance(p_instance->base); + + + Vector3 edge = view_normals[p_step]*extents; + float distance = ABS(view_normals[p_step].dot(edge)-view_normals[p_step].dot(origin_offset)); //distance from origin offset to actual view distance limit + + max_distance = MAX(max_distance,distance); + + + //render cubemap side + CameraMatrix cm; + cm.set_perspective(90,1,0.01,max_distance); + + + static const Vector3 view_up[6]={ + Vector3( 0,-1, 0), + Vector3( 0,-1, 0), + Vector3( 0, 0,-1), + Vector3( 0, 0,+1), + Vector3( 0,-1, 0), + Vector3( 0,-1, 0) + }; + + Transform local_view; + local_view.set_look_at(origin_offset,origin_offset+view_normals[p_step],view_up[p_step]); + + Transform xform = p_instance->transform * local_view; + + RID shadow_atlas; + + if (VSG::storage->reflection_probe_renders_shadows(p_instance->base)) { + + shadow_atlas=scenario->reflection_probe_shadow_atlas; + } + + _render_scene(xform,cm,false,RID(),VSG::storage->reflection_probe_get_cull_mask(p_instance->base),p_instance->scenario->self,shadow_atlas,reflection_probe->instance,p_step); + + } else { + //do roughness postprocess step until it belives it's done + return VSG::scene_render->reflection_probe_instance_postprocess_step(reflection_probe->instance); + } + + return false; +} + +void VisualServerScene::_gi_probe_fill_local_data(int p_idx, int p_level, int p_x, int p_y, int p_z, const GIProbeDataCell* p_cell, const GIProbeDataHeader *p_header, InstanceGIProbeData::LocalData *p_local_data, Vector<uint32_t> *prev_cell) { + + if (p_level==p_header->cell_subdiv-1) { + + Vector3 emission; + emission.x=(p_cell[p_idx].emission>>24)/255.0; + emission.y=((p_cell[p_idx].emission>>16)&0xFF)/255.0; + emission.z=((p_cell[p_idx].emission>>8)&0xFF)/255.0; + float l = (p_cell[p_idx].emission&0xFF)/255.0; + l*=8.0; + + emission*=l; + + p_local_data[p_idx].energy[0]=uint16_t(emission.x*1024); //go from 0 to 1024 for light + p_local_data[p_idx].energy[1]=uint16_t(emission.y*1024); //go from 0 to 1024 for light + p_local_data[p_idx].energy[2]=uint16_t(emission.z*1024); //go from 0 to 1024 for light + } else { + + p_local_data[p_idx].energy[0]=0; + p_local_data[p_idx].energy[1]=0; + p_local_data[p_idx].energy[2]=0; + + int half=(1<<(p_header->cell_subdiv-1))>>(p_level+1); + + for(int i=0;i<8;i++) { + + uint32_t child = p_cell[p_idx].children[i]; + + if (child==0xFFFFFFFF) + continue; + + int x = p_x; + int y = p_y; + int z = p_z; + + if (i&1) + x+=half; + if (i&2) + y+=half; + if (i&4) + z+=half; + + _gi_probe_fill_local_data(child,p_level+1,x,y,z,p_cell,p_header,p_local_data,prev_cell); + } + } + + //position for each part of the mipmaped texture + p_local_data[p_idx].pos[0]=p_x>>(p_header->cell_subdiv-p_level-1); + p_local_data[p_idx].pos[1]=p_y>>(p_header->cell_subdiv-p_level-1); + p_local_data[p_idx].pos[2]=p_z>>(p_header->cell_subdiv-p_level-1); + + prev_cell[p_level].push_back(p_idx); + +} + + +void VisualServerScene::_gi_probe_bake_threads(void* self) { + + VisualServerScene* vss = (VisualServerScene*)self; + vss->_gi_probe_bake_thread(); +} + +void VisualServerScene::_setup_gi_probe(Instance *p_instance) { + + + InstanceGIProbeData *probe = static_cast<InstanceGIProbeData*>(p_instance->base_data); + + if (probe->dynamic.probe_data.is_valid()) { + VSG::storage->free(probe->dynamic.probe_data); + probe->dynamic.probe_data=RID(); + } + + probe->dynamic.light_data=VSG::storage->gi_probe_get_dynamic_data(p_instance->base); + + if (probe->dynamic.light_data.size()==0) + return; + //using dynamic data + PoolVector<int>::Read r=probe->dynamic.light_data.read(); + + const GIProbeDataHeader *header = (GIProbeDataHeader *)r.ptr(); + + probe->dynamic.local_data.resize(header->cell_count); + + int cell_count = probe->dynamic.local_data.size(); + PoolVector<InstanceGIProbeData::LocalData>::Write ldw = probe->dynamic.local_data.write(); + const GIProbeDataCell *cells = (GIProbeDataCell*)&r[16]; + + probe->dynamic.level_cell_lists.resize(header->cell_subdiv); + + _gi_probe_fill_local_data(0,0,0,0,0,cells,header,ldw.ptr(),probe->dynamic.level_cell_lists.ptr()); + + bool compress = VSG::storage->gi_probe_is_compressed(p_instance->base); + + probe->dynamic.compression = compress ? VSG::storage->gi_probe_get_dynamic_data_get_preferred_compression() : RasterizerStorage::GI_PROBE_UNCOMPRESSED; + + probe->dynamic.probe_data=VSG::storage->gi_probe_dynamic_data_create(header->width,header->height,header->depth,probe->dynamic.compression); + + probe->dynamic.bake_dynamic_range=VSG::storage->gi_probe_get_dynamic_range(p_instance->base); + + probe->dynamic.mipmaps_3d.clear(); + probe->dynamic.propagate=VSG::storage->gi_probe_get_propagation(p_instance->base); + + probe->dynamic.grid_size[0]=header->width; + probe->dynamic.grid_size[1]=header->height; + probe->dynamic.grid_size[2]=header->depth; + + int size_limit = 1; + int size_divisor = 1; + + if (probe->dynamic.compression==RasterizerStorage::GI_PROBE_S3TC) { + print_line("S3TC"); + size_limit=4; + size_divisor=4; + } + for(int i=0;i<(int)header->cell_subdiv;i++) { + + uint32_t x = header->width >> i; + uint32_t y = header->height >> i; + uint32_t z = header->depth >> i; + + //create and clear mipmap + PoolVector<uint8_t> mipmap; + int size = x*y*z*4; + size/=size_divisor; + mipmap.resize(size); + PoolVector<uint8_t>::Write w = mipmap.write(); + zeromem(w.ptr(),size); + w = PoolVector<uint8_t>::Write(); + + probe->dynamic.mipmaps_3d.push_back(mipmap); + + if (x<=size_limit || y<=size_limit || z<=size_limit) + break; + } + + probe->dynamic.updating_stage=GI_UPDATE_STAGE_CHECK; + probe->invalid=false; + probe->dynamic.enabled=true; + + Transform cell_to_xform = VSG::storage->gi_probe_get_to_cell_xform(p_instance->base); + Rect3 bounds = VSG::storage->gi_probe_get_bounds(p_instance->base); + float cell_size = VSG::storage->gi_probe_get_cell_size(p_instance->base); + + probe->dynamic.light_to_cell_xform=cell_to_xform * p_instance->transform.affine_inverse(); + + VSG::scene_render->gi_probe_instance_set_light_data(probe->probe_instance,p_instance->base,probe->dynamic.probe_data); + VSG::scene_render->gi_probe_instance_set_transform_to_data(probe->probe_instance,probe->dynamic.light_to_cell_xform); + + VSG::scene_render->gi_probe_instance_set_bounds(probe->probe_instance,bounds.size/cell_size); + + probe->base_version=VSG::storage->gi_probe_get_version(p_instance->base); + + //if compression is S3TC, fill it up + if (probe->dynamic.compression==RasterizerStorage::GI_PROBE_S3TC) { + + //create all blocks + Vector<Map<uint32_t,InstanceGIProbeData::CompBlockS3TC> > comp_blocks; + int mipmap_count = probe->dynamic.mipmaps_3d.size(); + comp_blocks.resize(mipmap_count); + + for(int i=0;i<cell_count;i++) { + + const GIProbeDataCell &c = cells[i]; + const InstanceGIProbeData::LocalData &ld = ldw[i]; + int level = c.level_alpha>>16; + int mipmap = header->cell_subdiv - level -1; + if (mipmap >= mipmap_count) + continue;//uninteresting + + + int blockx = (ld.pos[0]>>2); + int blocky = (ld.pos[1]>>2); + int blockz = (ld.pos[2]); //compression is x/y only + + int blockw = (header->width >> mipmap) >> 2; + int blockh = (header->height >> mipmap) >> 2; + + //print_line("cell "+itos(i)+" level "+itos(level)+"mipmap: "+itos(mipmap)+" pos: "+Vector3(blockx,blocky,blockz)+" size "+Vector2(blockw,blockh)); + + uint32_t key = blockz * blockw*blockh + blocky * blockw + blockx; + + Map<uint32_t,InstanceGIProbeData::CompBlockS3TC> & cmap = comp_blocks[mipmap]; + + if (!cmap.has(key)) { + + InstanceGIProbeData::CompBlockS3TC k; + k.offset=key; //use offset as counter first + k.source_count=0; + cmap[key]=k; + } + + InstanceGIProbeData::CompBlockS3TC &k=cmap[key]; + ERR_CONTINUE(k.source_count==16); + k.sources[k.source_count++]=i; + } + + //fix the blocks, precomputing what is needed + probe->dynamic.mipmaps_s3tc.resize(mipmap_count); + + for(int i=0;i<mipmap_count;i++) { + print_line("S3TC level: "+itos(i)+" blocks: "+itos(comp_blocks[i].size())); + probe->dynamic.mipmaps_s3tc[i].resize(comp_blocks[i].size()); + PoolVector<InstanceGIProbeData::CompBlockS3TC>::Write w = probe->dynamic.mipmaps_s3tc[i].write(); + int block_idx=0; + + for (Map<uint32_t,InstanceGIProbeData::CompBlockS3TC>::Element *E=comp_blocks[i].front();E;E=E->next()) { + + InstanceGIProbeData::CompBlockS3TC k = E->get(); + + //PRECOMPUTE ALPHA + int max_alpha=-100000; + int min_alpha=k.source_count==16 ?100000 :0; //if the block is not completely full, minimum is always 0, (and those blocks will map to 1, which will be zero) + + uint8_t alpha_block[4][4]={ {0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0} }; + + for(int j=0;j<k.source_count;j++) { + + int alpha = (cells[k.sources[j]].level_alpha>>8)&0xFF; + if (alpha<min_alpha) + min_alpha=alpha; + if (alpha>max_alpha) + max_alpha=alpha; + //fill up alpha block + alpha_block[ldw[k.sources[j]].pos[0]%4][ldw[k.sources[j]].pos[1]%4]=alpha; + + } + + //use the first mode (8 adjustable levels) + k.alpha[0]=max_alpha; + k.alpha[1]=min_alpha; + + uint64_t alpha_bits=0; + + if (max_alpha!=min_alpha) { + + int idx=0; + + for(int y=0;y<4;y++) { + for(int x=0;x<4;x++) { + + //substract minimum + uint32_t a = uint32_t(alpha_block[x][y])-min_alpha; + //convert range to 3 bits + a =int((a * 7.0 / (max_alpha-min_alpha))+0.5); + a = CLAMP(a,0,7); //just to be sure + a = 7-a; //because range is inverted in this mode + if (a==0) { + //do none, remain + } else if (a==7) { + a=1; + } else { + a=a+1; + } + + alpha_bits|=uint64_t(a)<<(idx*3); + idx++; + } + } + } + + k.alpha[2]=(alpha_bits >> 0)&0xFF; + k.alpha[3]=(alpha_bits >> 8)&0xFF; + k.alpha[4]=(alpha_bits >> 16)&0xFF; + k.alpha[5]=(alpha_bits >> 24)&0xFF; + k.alpha[6]=(alpha_bits >> 32)&0xFF; + k.alpha[7]=(alpha_bits >> 40)&0xFF; + + w[block_idx++]=k; + + } + + } + } + +} + +void VisualServerScene::_gi_probe_bake_thread() { + + while(true) { + + probe_bake_sem->wait(); + if (probe_bake_thread_exit) { + break; + } + + Instance* to_bake=NULL; + + probe_bake_mutex->lock(); + + if (!probe_bake_list.empty()) { + to_bake=probe_bake_list.front()->get(); + probe_bake_list.pop_front(); + + } + probe_bake_mutex->unlock(); + + if (!to_bake) + continue; + + _bake_gi_probe(to_bake); + } +} + + + +uint32_t VisualServerScene::_gi_bake_find_cell(const GIProbeDataCell *cells,int x,int y, int z,int p_cell_subdiv) { + + + uint32_t cell=0; + + int ofs_x=0; + int ofs_y=0; + int ofs_z=0; + int size = 1<<(p_cell_subdiv-1); + int half=size/2; + + if (x<0 || x>=size) + return -1; + if (y<0 || y>=size) + return -1; + if (z<0 || z>=size) + return -1; + + for(int i=0;i<p_cell_subdiv-1;i++) { + + const GIProbeDataCell *bc = &cells[cell]; + + int child = 0; + if (x >= ofs_x + half) { + child|=1; + ofs_x+=half; + } + if (y >= ofs_y + half) { + child|=2; + ofs_y+=half; + } + if (z >= ofs_z + half) { + child|=4; + ofs_z+=half; + } + + cell = bc->children[child]; + if (cell==0xFFFFFFFF) + return 0xFFFFFFFF; + + half>>=1; + } + + return cell; + +} + +static float _get_normal_advance(const Vector3& p_normal ) { + + Vector3 normal = p_normal; + Vector3 unorm = normal.abs(); + + if ( (unorm.x >= unorm.y) && (unorm.x >= unorm.z) ) { + // x code + unorm = normal.x > 0.0 ? Vector3( 1.0, 0.0, 0.0 ) : Vector3( -1.0, 0.0, 0.0 ) ; + } else if ( (unorm.y > unorm.x) && (unorm.y >= unorm.z) ) { + // y code + unorm = normal.y > 0.0 ? Vector3( 0.0, 1.0, 0.0 ) : Vector3( 0.0, -1.0, 0.0 ) ; + } else if ( (unorm.z > unorm.x) && (unorm.z > unorm.y) ) { + // z code + unorm = normal.z > 0.0 ? Vector3( 0.0, 0.0, 1.0 ) : Vector3( 0.0, 0.0, -1.0 ) ; + } else { + // oh-no we messed up code + // has to be + unorm = Vector3( 1.0, 0.0, 0.0 ); + } + + return 1.0/normal.dot(unorm); + +} + +void VisualServerScene::_bake_gi_probe_light(const GIProbeDataHeader *header,const GIProbeDataCell *cells,InstanceGIProbeData::LocalData *local_data,const uint32_t *leaves,int leaf_count, const InstanceGIProbeData::LightCache& light_cache,int sign) { + + + int light_r = int(light_cache.color.r * light_cache.energy * 1024.0)*sign; + int light_g = int(light_cache.color.g * light_cache.energy * 1024.0)*sign; + int light_b = int(light_cache.color.b * light_cache.energy * 1024.0)*sign; + + float limits[3]={float(header->width),float(header->height),float(header->depth)}; + Plane clip[3]; + int clip_planes=0; + + + + switch(light_cache.type) { + + case VS::LIGHT_DIRECTIONAL: { + + float max_len = Vector3(limits[0],limits[1],limits[2]).length()*1.1; + + Vector3 light_axis = -light_cache.transform.basis.get_axis(2).normalized(); + + for(int i=0;i<3;i++) { + + if (ABS(light_axis[i])<CMP_EPSILON) + continue; + clip[clip_planes].normal[i]=1.0; + + if (light_axis[i]<0) { + + clip[clip_planes].d=limits[i]+1; + } else { + clip[clip_planes].d-=1.0; + } + + clip_planes++; + } + + float distance_adv = _get_normal_advance(light_axis); + + int success_count=0; + + uint64_t us = OS::get_singleton()->get_ticks_usec(); + + for(int i=0;i<leaf_count;i++) { + + uint32_t idx = leaves[i]; + + const GIProbeDataCell *cell = &cells[idx]; + InstanceGIProbeData::LocalData *light = &local_data[idx]; + + Vector3 to(light->pos[0]+0.5,light->pos[1]+0.5,light->pos[2]+0.5); + Vector3 norm ( + (((cells[idx].normal>>16)&0xFF)/255.0)*2.0-1.0, + (((cells[idx].normal>>8)&0xFF)/255.0)*2.0-1.0, + (((cells[idx].normal>>0)&0xFF)/255.0)*2.0-1.0 + ); + + + float att = norm.dot(-light_axis); + if (att<0.001) { + //not lighting towards this + continue; + } + + Vector3 from = to - max_len * light_axis; + + for(int j=0;j<clip_planes;j++) { + + clip[j].intersects_segment(from,to,&from); + } + + float distance = (to - from).length(); + distance+=distance_adv-Math::fmod(distance,distance_adv); //make it reach the center of the box always + from = to - light_axis * distance; + + uint32_t result=0xFFFFFFFF; + + while(distance>-distance_adv) { //use this to avoid precision errors + + result = _gi_bake_find_cell(cells,int(floor(from.x)),int(floor(from.y)),int(floor(from.z)),header->cell_subdiv); + if (result!=0xFFFFFFFF) { + break; + } + + from+=light_axis*distance_adv; + distance-=distance_adv; + } + + if (result==idx) { + //cell hit itself! hooray! + light->energy[0]+=int32_t(light_r*att*((cell->albedo>>16)&0xFF)/255.0); + light->energy[1]+=int32_t(light_g*att*((cell->albedo>>8)&0xFF)/255.0); + light->energy[2]+=int32_t(light_b*att*((cell->albedo)&0xFF)/255.0); + success_count++; + } + } + print_line("BAKE TIME: "+rtos((OS::get_singleton()->get_ticks_usec()-us)/1000000.0)); + print_line("valid cells: "+itos(success_count)); + + + } break; + case VS::LIGHT_OMNI: + case VS::LIGHT_SPOT: { + + + uint64_t us = OS::get_singleton()->get_ticks_usec(); + + Vector3 light_pos = light_cache.transform.origin; + Vector3 spot_axis = -light_cache.transform.basis.get_axis(2).normalized(); + + + float local_radius = light_cache.radius * light_cache.transform.basis.get_axis(2).length(); + + for(int i=0;i<leaf_count;i++) { + + uint32_t idx = leaves[i]; + + const GIProbeDataCell *cell = &cells[idx]; + InstanceGIProbeData::LocalData *light = &local_data[idx]; + + Vector3 to(light->pos[0]+0.5,light->pos[1]+0.5,light->pos[2]+0.5); + Vector3 norm ( + (((cells[idx].normal>>16)&0xFF)/255.0)*2.0-1.0, + (((cells[idx].normal>>8)&0xFF)/255.0)*2.0-1.0, + (((cells[idx].normal>>0)&0xFF)/255.0)*2.0-1.0 + ); + + Vector3 light_axis = (to - light_pos).normalized(); + float distance_adv = _get_normal_advance(light_axis); + + float att = norm.dot(-light_axis); + if (att<0.001) { + //not lighting towards this + continue; + } + + { + float d = light_pos.distance_to(to); + if (d+distance_adv > local_radius) + continue; // too far away + + float dt = CLAMP((d+distance_adv)/local_radius,0,1); + att*= powf(1.0-dt,light_cache.attenuation); + } + + + if (light_cache.type==VS::LIGHT_SPOT) { + + float angle = Math::rad2deg(acos(light_axis.dot(spot_axis))); + if (angle > light_cache.spot_angle) + continue; + + float d = CLAMP(angle/light_cache.spot_angle,1,0); + att*= powf(1.0-d,light_cache.spot_attenuation); + + } + + clip_planes=0; + + for(int c=0;c<3;c++) { + + if (ABS(light_axis[c])<CMP_EPSILON) + continue; + clip[clip_planes].normal[c]=1.0; + + if (light_axis[c]<0) { + + clip[clip_planes].d=limits[c]+1; + } else { + clip[clip_planes].d-=1.0; + } + + clip_planes++; + } + + Vector3 from = light_pos; + + for(int j=0;j<clip_planes;j++) { + + clip[j].intersects_segment(from,to,&from); + } + + float distance = (to - from).length(); + + + + distance-=Math::fmod(distance,distance_adv); //make it reach the center of the box always, but this tame make it closer + from = to - light_axis * distance; + + uint32_t result=0xFFFFFFFF; + + while(distance>-distance_adv) { //use this to avoid precision errors + + result = _gi_bake_find_cell(cells,int(floor(from.x)),int(floor(from.y)),int(floor(from.z)),header->cell_subdiv); + if (result!=0xFFFFFFFF) { + break; + } + + from+=light_axis*distance_adv; + distance-=distance_adv; + } + + if (result==idx) { + //cell hit itself! hooray! + + light->energy[0]+=int32_t(light_r*att*((cell->albedo>>16)&0xFF)/255.0); + light->energy[1]+=int32_t(light_g*att*((cell->albedo>>8)&0xFF)/255.0); + light->energy[2]+=int32_t(light_b*att*((cell->albedo)&0xFF)/255.0); + + } + } + print_line("BAKE TIME: "+rtos((OS::get_singleton()->get_ticks_usec()-us)/1000000.0)); + + + } break; + } +} + + +void VisualServerScene::_bake_gi_downscale_light(int p_idx, int p_level, const GIProbeDataCell* p_cells, const GIProbeDataHeader *p_header, InstanceGIProbeData::LocalData *p_local_data,float p_propagate) { + + //average light to upper level + + float divisor=0; + float sum[3]={0.0,0.0,0.0}; + + for(int i=0;i<8;i++) { + + uint32_t child = p_cells[p_idx].children[i]; + + if (child==0xFFFFFFFF) + continue; + + if (p_level+1 < (int)p_header->cell_subdiv-1) { + _bake_gi_downscale_light(child,p_level+1,p_cells,p_header,p_local_data,p_propagate); + } + + sum[0]+=p_local_data[child].energy[0]; + sum[1]+=p_local_data[child].energy[1]; + sum[2]+=p_local_data[child].energy[2]; + divisor+=1.0; + + } + + divisor=Math::lerp((float)8.0,divisor,p_propagate); + sum[0]/=divisor; + sum[1]/=divisor; + sum[2]/=divisor; + + //divide by eight for average + p_local_data[p_idx].energy[0]=Math::fast_ftoi(sum[0]); + p_local_data[p_idx].energy[1]=Math::fast_ftoi(sum[1]); + p_local_data[p_idx].energy[2]=Math::fast_ftoi(sum[2]); + +} + + +void VisualServerScene::_bake_gi_probe(Instance *p_gi_probe) { + + InstanceGIProbeData * probe_data = static_cast<InstanceGIProbeData*>(p_gi_probe->base_data); + + PoolVector<int>::Read r=probe_data->dynamic.light_data.read(); + + const GIProbeDataHeader *header = (const GIProbeDataHeader *)r.ptr(); + const GIProbeDataCell *cells = (const GIProbeDataCell*)&r[16]; + + int leaf_count = probe_data->dynamic.level_cell_lists[ header->cell_subdiv -1 ].size(); + const uint32_t *leaves = probe_data->dynamic.level_cell_lists[ header->cell_subdiv -1 ].ptr(); + + PoolVector<InstanceGIProbeData::LocalData>::Write ldw = probe_data->dynamic.local_data.write(); + + InstanceGIProbeData::LocalData *local_data = ldw.ptr(); + + + //remove what must be removed + for (Map<RID,InstanceGIProbeData::LightCache>::Element *E=probe_data->dynamic.light_cache.front();E;E=E->next()) { + + RID rid = E->key(); + const InstanceGIProbeData::LightCache& lc = E->get(); + + if (!probe_data->dynamic.light_cache_changes.has(rid) || !(probe_data->dynamic.light_cache_changes[rid]==lc)) { + //erase light data + + _bake_gi_probe_light(header,cells,local_data,leaves,leaf_count,lc,-1); + } + + } + + //add what must be added + for (Map<RID,InstanceGIProbeData::LightCache>::Element *E=probe_data->dynamic.light_cache_changes.front();E;E=E->next()) { + + RID rid = E->key(); + const InstanceGIProbeData::LightCache& lc = E->get(); + + if (!probe_data->dynamic.light_cache.has(rid) || !(probe_data->dynamic.light_cache[rid]==lc)) { + //add light data + + _bake_gi_probe_light(header,cells,local_data,leaves,leaf_count,lc,1); + } + } + + SWAP(probe_data->dynamic.light_cache_changes,probe_data->dynamic.light_cache); + + //downscale to lower res levels + _bake_gi_downscale_light(0,0,cells,header,local_data,probe_data->dynamic.propagate); + + //plot result to 3D texture! + + if (probe_data->dynamic.compression==RasterizerStorage::GI_PROBE_UNCOMPRESSED) { + + for(int i=0;i<(int)header->cell_subdiv;i++) { + + int stage = header->cell_subdiv - i -1; + + if (stage >= probe_data->dynamic.mipmaps_3d.size()) + continue; //no mipmap for this one + + print_line("generating mipmap stage: "+itos(stage)); + int level_cell_count = probe_data->dynamic.level_cell_lists[ i ].size(); + const uint32_t *level_cells = probe_data->dynamic.level_cell_lists[ i ].ptr(); + + PoolVector<uint8_t>::Write lw = probe_data->dynamic.mipmaps_3d[stage].write(); + uint8_t *mipmapw = lw.ptr(); + + uint32_t sizes[3]={header->width>>stage,header->height>>stage,header->depth>>stage}; + + for(int j=0;j<level_cell_count;j++) { + + uint32_t idx = level_cells[j]; + + uint32_t r = (uint32_t(local_data[idx].energy[0])/probe_data->dynamic.bake_dynamic_range)>>2; + uint32_t g = (uint32_t(local_data[idx].energy[1])/probe_data->dynamic.bake_dynamic_range)>>2; + uint32_t b = (uint32_t(local_data[idx].energy[2])/probe_data->dynamic.bake_dynamic_range)>>2; + uint32_t a = (cells[idx].level_alpha>>8)&0xFF; + + uint32_t mm_ofs = sizes[0]*sizes[1]*(local_data[idx].pos[2]) + sizes[0]*(local_data[idx].pos[1]) + (local_data[idx].pos[0]); + mm_ofs*=4; //for RGBA (4 bytes) + + mipmapw[mm_ofs+0]=uint8_t(CLAMP(r,0,255)); + mipmapw[mm_ofs+1]=uint8_t(CLAMP(g,0,255)); + mipmapw[mm_ofs+2]=uint8_t(CLAMP(b,0,255)); + mipmapw[mm_ofs+3]=uint8_t(CLAMP(a,0,255)); + + + } + } + } else if (probe_data->dynamic.compression==RasterizerStorage::GI_PROBE_S3TC) { + + + int mipmap_count = probe_data->dynamic.mipmaps_3d.size(); + + for(int mmi=0;mmi<mipmap_count;mmi++) { + + PoolVector<uint8_t>::Write mmw = probe_data->dynamic.mipmaps_3d[mmi].write(); + int block_count = probe_data->dynamic.mipmaps_s3tc[mmi].size(); + PoolVector<InstanceGIProbeData::CompBlockS3TC>::Read mmr = probe_data->dynamic.mipmaps_s3tc[mmi].read(); + + for(int i=0;i<block_count;i++) { + + const InstanceGIProbeData::CompBlockS3TC& b = mmr[i]; + + uint8_t *blockptr = &mmw[b.offset*16]; + copymem(blockptr,b.alpha,8); //copy alpha part, which is precomputed + + Vector3 colors[16]; + + for(int j=0;j<b.source_count;j++) { + + colors[j].x=(local_data[b.sources[j]].energy[0]/float(probe_data->dynamic.bake_dynamic_range))/1024.0; + colors[j].y=(local_data[b.sources[j]].energy[1]/float(probe_data->dynamic.bake_dynamic_range))/1024.0; + colors[j].z=(local_data[b.sources[j]].energy[2]/float(probe_data->dynamic.bake_dynamic_range))/1024.0; + } + //super quick and dirty compression + //find 2 most futher apart + float distance=0; + Vector3 from,to; + + if (b.source_count==16) { + //all cells are used so, find minmax between them + int further_apart[2]={0,0}; + for(int j=0;j<b.source_count;j++) { + for(int k=j+1;k<b.source_count;k++) { + float d = colors[j].distance_squared_to(colors[k]); + if (d>distance) { + distance=d; + further_apart[0]=j; + further_apart[1]=k; + } + } + } + + from = colors[further_apart[0]]; + to = colors[further_apart[1]]; + + } else { + //if a block is missing, the priority is that this block remains black, + //otherwise the geometry will appear deformed + //correct shape wins over correct color in this case + //average all colors first + Vector3 average; + + for(int j=0;j<b.source_count;j++) { + average+=colors[j]; + } + average.normalize(); + //find max distance in normal from average + for(int j=0;j<b.source_count;j++) { + float d = average.dot(colors[j]); + distance=MAX(d,distance); + } + + from = Vector3(); //from black + to = average * distance; + //find max distance + + } + + + int indices[16]; + uint16_t color_0=0; + color_0 = CLAMP(int(from.x*31),0,31)<<11; + color_0 |= CLAMP(int(from.y*63),0,63)<<5; + color_0 |= CLAMP(int(from.z*31),0,31); + + uint16_t color_1=0; + color_1 = CLAMP(int(to.x*31),0,31)<<11; + color_1 |= CLAMP(int(to.y*63),0,63)<<5; + color_1 |= CLAMP(int(to.z*31),0,31); + + if (color_1 > color_0) { + SWAP(color_1,color_0); + SWAP(from,to); + } + + + if (distance>0) { + + Vector3 dir = (to-from).normalized(); + + + for(int j=0;j<b.source_count;j++) { + + float d = (colors[j]-from).dot(dir) / distance; + indices[j]=int(d*3+0.5); + + static const int index_swap[4]={0,3,1,2}; + + indices[j]=index_swap[CLAMP(indices[j],0,3)]; + + + } + } else { + for(int j=0;j<b.source_count;j++) { + indices[j]=0; + } + } + + //by default, 1 is black, otherwise it will be overriden by source + + uint32_t index_block[16]={1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1 }; + + for(int j=0;j<b.source_count;j++) { + + int x=local_data[b.sources[j]].pos[0]%4; + int y=local_data[b.sources[j]].pos[1]%4; + + index_block[y*4+x]=indices[j]; + } + + uint32_t encode=0; + + for(int j=0;j<16;j++) { + encode|=index_block[j]<<(j*2); + } + + blockptr[8]=color_0&0xFF; + blockptr[9]=(color_0>>8)&0xFF; + blockptr[10]=color_1&0xFF; + blockptr[11]=(color_1>>8)&0xFF; + blockptr[12]=encode&0xFF; + blockptr[13]=(encode>>8)&0xFF; + blockptr[14]=(encode>>16)&0xFF; + blockptr[15]=(encode>>24)&0xFF; + + } + + + } + + } + + + //send back to main thread to update un little chunks + probe_data->dynamic.updating_stage=GI_UPDATE_STAGE_UPLOADING; + +} + +bool VisualServerScene::_check_gi_probe(Instance *p_gi_probe) { + + InstanceGIProbeData * probe_data = static_cast<InstanceGIProbeData*>(p_gi_probe->base_data); + + probe_data->dynamic.light_cache_changes.clear(); + + bool all_equal=true; + + + for (List<Instance*>::Element *E=p_gi_probe->scenario->directional_lights.front();E;E=E->next()) { + + InstanceGIProbeData::LightCache lc; + lc.type=VSG::storage->light_get_type(E->get()->base); + lc.color=VSG::storage->light_get_color(E->get()->base); + lc.energy=VSG::storage->light_get_param(E->get()->base,VS::LIGHT_PARAM_ENERGY); + lc.radius=VSG::storage->light_get_param(E->get()->base,VS::LIGHT_PARAM_RANGE); + lc.attenuation=VSG::storage->light_get_param(E->get()->base,VS::LIGHT_PARAM_ATTENUATION); + lc.spot_angle=VSG::storage->light_get_param(E->get()->base,VS::LIGHT_PARAM_SPOT_ANGLE); + lc.spot_attenuation=VSG::storage->light_get_param(E->get()->base,VS::LIGHT_PARAM_SPOT_ATTENUATION); + lc.transform = probe_data->dynamic.light_to_cell_xform * E->get()->transform; + + if (!probe_data->dynamic.light_cache.has(E->get()->self) || !(probe_data->dynamic.light_cache[E->get()->self]==lc)) { + all_equal=false; + } + + probe_data->dynamic.light_cache_changes[E->get()->self]=lc; + + } + + + for (Set<Instance*>::Element *E=probe_data->lights.front();E;E=E->next()) { + + InstanceGIProbeData::LightCache lc; + lc.type=VSG::storage->light_get_type(E->get()->base); + lc.color=VSG::storage->light_get_color(E->get()->base); + lc.energy=VSG::storage->light_get_param(E->get()->base,VS::LIGHT_PARAM_ENERGY); + lc.radius=VSG::storage->light_get_param(E->get()->base,VS::LIGHT_PARAM_RANGE); + lc.attenuation=VSG::storage->light_get_param(E->get()->base,VS::LIGHT_PARAM_ATTENUATION); + lc.spot_angle=VSG::storage->light_get_param(E->get()->base,VS::LIGHT_PARAM_SPOT_ANGLE); + lc.spot_attenuation=VSG::storage->light_get_param(E->get()->base,VS::LIGHT_PARAM_SPOT_ATTENUATION); + lc.transform = probe_data->dynamic.light_to_cell_xform * E->get()->transform; + + if (!probe_data->dynamic.light_cache.has(E->get()->self) || !(probe_data->dynamic.light_cache[E->get()->self]==lc)) { + all_equal=false; + } + + probe_data->dynamic.light_cache_changes[E->get()->self]=lc; + } + + //lighting changed from after to before, must do some updating + return !all_equal || probe_data->dynamic.light_cache_changes.size()!=probe_data->dynamic.light_cache.size(); + +} + +void VisualServerScene::render_probes() { + + /* REFLECTION PROBES */ + + SelfList<InstanceReflectionProbeData> *ref_probe = reflection_probe_render_list.first(); + + bool busy=false; + + while(ref_probe) { + + SelfList<InstanceReflectionProbeData> *next=ref_probe->next(); + RID base = ref_probe->self()->owner->base; + + switch(VSG::storage->reflection_probe_get_update_mode(base)) { + + case VS::REFLECTION_PROBE_UPDATE_ONCE: { + if (busy) //already rendering something + break; + + bool done = _render_reflection_probe_step(ref_probe->self()->owner,ref_probe->self()->render_step); + if (done) { + reflection_probe_render_list.remove(ref_probe); + } else { + ref_probe->self()->render_step++; + } + + busy=true; //do not render another one of this kind + } break; + case VS::REFLECTION_PROBE_UPDATE_ALWAYS: { + + int step=0; + bool done=false; + while(!done) { + done = _render_reflection_probe_step(ref_probe->self()->owner,step); + step++; + } + + reflection_probe_render_list.remove(ref_probe); + } break; + + } + + ref_probe=next; + } + + /* GI PROBES */ + + SelfList<InstanceGIProbeData> *gi_probe = gi_probe_update_list.first(); + + while(gi_probe) { + + SelfList<InstanceGIProbeData> *next=gi_probe->next(); + + InstanceGIProbeData *probe = gi_probe->self(); + Instance *instance_probe = probe->owner; + + //check if probe must be setup, but don't do if on the lighting thread + + bool force_lighting=false; + + if (probe->invalid || (probe->dynamic.updating_stage==GI_UPDATE_STAGE_CHECK && probe->base_version!=VSG::storage->gi_probe_get_version(instance_probe->base))) { + + _setup_gi_probe(instance_probe); + force_lighting=true; + } + + float propagate = VSG::storage->gi_probe_get_propagation(instance_probe->base); + + if (probe->dynamic.propagate!=propagate) { + probe->dynamic.propagate=propagate; + force_lighting=true; + } + + + if (probe->invalid==false && probe->dynamic.enabled) { + + switch(probe->dynamic.updating_stage) { + case GI_UPDATE_STAGE_CHECK: { + + if (_check_gi_probe(instance_probe) || force_lighting) { + //send to lighting thread + probe->dynamic.updating_stage=GI_UPDATE_STAGE_LIGHTING; + +#ifndef NO_THREADS + probe_bake_mutex->lock(); + probe_bake_list.push_back(instance_probe); + probe_bake_mutex->unlock(); + probe_bake_sem->post(); + +#else + + _bake_gi_probe(instance_probe); +#endif + + } + } break; + case GI_UPDATE_STAGE_LIGHTING: { + //do none, wait til done! + + } break; + case GI_UPDATE_STAGE_UPLOADING: { + + uint64_t us = OS::get_singleton()->get_ticks_usec(); + + for(int i=0;i<(int)probe->dynamic.mipmaps_3d.size();i++) { + + int mmsize = probe->dynamic.mipmaps_3d[i].size(); + PoolVector<uint8_t>::Read r = probe->dynamic.mipmaps_3d[i].read(); + VSG::storage->gi_probe_dynamic_data_update(probe->dynamic.probe_data,0,probe->dynamic.grid_size[2]>>i,i,r.ptr()); + } + + + probe->dynamic.updating_stage=GI_UPDATE_STAGE_CHECK; + + //print_line("UPLOAD TIME: "+rtos((OS::get_singleton()->get_ticks_usec()-us)/1000000.0)); + } break; + + } + } + //_update_gi_probe(gi_probe->self()->owner); + + + gi_probe=next; + } + + + +} + +void VisualServerScene::_update_dirty_instance(Instance *p_instance) { + + if (p_instance->update_aabb) + _update_instance_aabb(p_instance); + + + if (p_instance->update_materials) { + + if (p_instance->base_type==VS::INSTANCE_MESH) { + //remove materials no longer used and un-own them + + int new_mat_count = VSG::storage->mesh_get_surface_count(p_instance->base); + for(int i=p_instance->materials.size()-1;i>=new_mat_count;i--) { + if (p_instance->materials[i].is_valid()) { + VSG::storage->material_remove_instance_owner(p_instance->materials[i],p_instance); + } + } + p_instance->materials.resize(new_mat_count); + + int new_blend_shape_count = VSG::storage->mesh_get_blend_shape_count(p_instance->base); + if (new_blend_shape_count!=p_instance->blend_values.size()) { + p_instance->blend_values.resize(new_blend_shape_count); + for(int i=0;i<new_blend_shape_count;i++) { + p_instance->blend_values[i]=0; + } + } + } + + if ((1<<p_instance->base_type)&VS::INSTANCE_GEOMETRY_MASK) { + + InstanceGeometryData *geom = static_cast<InstanceGeometryData*>(p_instance->base_data); + + bool can_cast_shadows=true; + + if (p_instance->cast_shadows==VS::SHADOW_CASTING_SETTING_OFF) { + can_cast_shadows=false; + } else if (p_instance->material_override.is_valid()) { + can_cast_shadows=VSG::storage->material_casts_shadows(p_instance->material_override); + } else { + + + + if (p_instance->base_type==VS::INSTANCE_MESH) { + RID mesh=p_instance->base; + + if (mesh.is_valid()) { + bool cast_shadows=false; + + for(int i=0;i<p_instance->materials.size();i++) { + + + RID mat = p_instance->materials[i].is_valid()?p_instance->materials[i]:VSG::storage->mesh_surface_get_material(mesh,i); + + if (!mat.is_valid()) { + cast_shadows=true; + break; + } + + if (VSG::storage->material_casts_shadows(mat)) { + cast_shadows=true; + break; + } + } + + if (!cast_shadows) { + can_cast_shadows=false; + } + } + + } else if (p_instance->base_type==VS::INSTANCE_MULTIMESH) { + RID mesh = VSG::storage->multimesh_get_mesh(p_instance->base); + if (mesh.is_valid()) { + + bool cast_shadows=false; + + int sc = VSG::storage->mesh_get_surface_count(mesh); + for(int i=0;i<sc;i++) { + + RID mat =VSG::storage->mesh_surface_get_material(mesh,i); + + if (!mat.is_valid()) { + cast_shadows=true; + break; + } + + if (VSG::storage->material_casts_shadows(mat)) { + cast_shadows=true; + break; + } + + } + + if (!cast_shadows) { + can_cast_shadows=false; + } + } + } else if (p_instance->base_type==VS::INSTANCE_IMMEDIATE) { + + RID mat = VSG::storage->immediate_get_material(p_instance->base); + + if (!mat.is_valid() || VSG::storage->material_casts_shadows(mat)) { + can_cast_shadows=true; + } else { + can_cast_shadows=false; + } + + + } + + + + } + + if (can_cast_shadows!=geom->can_cast_shadows) { + //ability to cast shadows change, let lights now + for (List<Instance*>::Element *E=geom->lighting.front();E;E=E->next()) { + InstanceLightData *light = static_cast<InstanceLightData*>(E->get()->base_data); + light->shadow_dirty=true; + } + + geom->can_cast_shadows=can_cast_shadows; + } + } + + } + + _update_instance(p_instance); + + p_instance->update_aabb=false; + p_instance->update_materials=false; + + _instance_update_list.remove( &p_instance->update_item ); +} + + +void VisualServerScene::update_dirty_instances() { + + VSG::storage->update_dirty_resources(); + + while(_instance_update_list.first()) { + + _update_dirty_instance( _instance_update_list.first()->self() ); + } +} + +bool VisualServerScene::free(RID p_rid) { + + if (camera_owner.owns(p_rid)) { + + Camera *camera = camera_owner.get( p_rid ); + + camera_owner.free(p_rid); + memdelete(camera); + + } else if (scenario_owner.owns(p_rid)) { + + Scenario *scenario = scenario_owner.get( p_rid ); + + while(scenario->instances.first()) { + instance_set_scenario(scenario->instances.first()->self()->self,RID()); + } + VSG::scene_render->free(scenario->reflection_probe_shadow_atlas); + VSG::scene_render->free(scenario->reflection_atlas); + scenario_owner.free(p_rid); + memdelete(scenario); + + } else if (instance_owner.owns(p_rid)) { + // delete the instance + + update_dirty_instances(); + + Instance *instance = instance_owner.get(p_rid); + + instance_set_room(p_rid,RID()); + instance_set_scenario(p_rid,RID()); + instance_set_base(p_rid,RID()); + instance_geometry_set_material_override(p_rid,RID()); + instance_attach_skeleton(p_rid,RID()); + + update_dirty_instances(); //in case something changed this + + instance_owner.free(p_rid); + memdelete(instance); + } else { + return false; + } + + + return true; +} + +VisualServerScene *VisualServerScene::singleton=NULL; + + +VisualServerScene::VisualServerScene() { + +#ifndef NO_THREADS + probe_bake_sem = Semaphore::create(); + probe_bake_mutex = Mutex::create(); + probe_bake_thread = Thread::create(_gi_probe_bake_threads,this); + probe_bake_thread_exit=false; +#endif + + + render_pass=1; + singleton=this; + +} + +VisualServerScene::~VisualServerScene() { + +#ifndef NO_THREADS + probe_bake_thread_exit=true; + Thread::wait_to_finish(probe_bake_thread); + memdelete(probe_bake_thread); + memdelete(probe_bake_sem); + memdelete(probe_bake_mutex); + +#endif + + +} diff --git a/servers/visual/visual_server_scene.h b/servers/visual/visual_server_scene.h new file mode 100644 index 0000000000..f9a5dde1ac --- /dev/null +++ b/servers/visual/visual_server_scene.h @@ -0,0 +1,589 @@ +#ifndef VISUALSERVERSCENE_H +#define VISUALSERVERSCENE_H + +#include "servers/visual/rasterizer.h" + +#include "geometry.h" +#include "allocators.h" +#include "octree.h" +#include "self_list.h" +#include "os/thread.h" +#include "os/semaphore.h" +#include "os/semaphore.h" + +class VisualServerScene { +public: + + + enum { + + MAX_INSTANCE_CULL=65536, + MAX_LIGHTS_CULLED=4096, + MAX_REFLECTION_PROBES_CULLED=4096, + MAX_ROOM_CULL=32, + MAX_EXTERIOR_PORTALS=128, + }; + + uint64_t render_pass; + + + static VisualServerScene *singleton; +#if 0 + struct Portal { + + bool enabled; + float disable_distance; + Color disable_color; + float connect_range; + Vector<Point2> shape; + Rect2 bounds; + + + Portal() { enabled=true; disable_distance=50; disable_color=Color(); connect_range=0.8; } + }; + + struct BakedLight { + + Rasterizer::BakedLightData data; + PoolVector<int> sampler; + AABB octree_aabb; + Size2i octree_tex_size; + Size2i light_tex_size; + + }; + + struct BakedLightSampler { + + float params[BAKED_LIGHT_SAMPLER_MAX]; + int resolution; + Vector<Vector3> dp_cache; + + BakedLightSampler() { + params[BAKED_LIGHT_SAMPLER_STRENGTH]=1.0; + params[BAKED_LIGHT_SAMPLER_ATTENUATION]=1.0; + params[BAKED_LIGHT_SAMPLER_RADIUS]=1.0; + params[BAKED_LIGHT_SAMPLER_DETAIL_RATIO]=0.1; + resolution=16; + } + }; + + void _update_baked_light_sampler_dp_cache(BakedLightSampler * blsamp); + +#endif + + + /* CAMERA API */ + + struct Camera : public RID_Data { + + enum Type { + PERSPECTIVE, + ORTHOGONAL + }; + Type type; + float fov; + float znear,zfar; + float size; + uint32_t visible_layers; + bool vaspect; + RID env; + + Transform transform; + + Camera() { + + visible_layers=0xFFFFFFFF; + fov=60; + type=PERSPECTIVE; + znear=0.1; zfar=100; + size=1.0; + vaspect=false; + + } + }; + + mutable RID_Owner<Camera> camera_owner; + + 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_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); + virtual void camera_set_use_vertical_aspect(RID p_camera,bool p_enable); + + + /* + + struct RoomInfo { + + Transform affine_inverse; + Room *room; + List<Instance*> owned_geometry_instances; + List<Instance*> owned_portal_instances; + List<Instance*> owned_room_instances; + List<Instance*> owned_light_instances; //not used, but just for the sake of it + Set<Instance*> disconnected_child_portals; + Set<Instance*> owned_autoroom_geometry; + uint64_t last_visited_pass; + RoomInfo() { last_visited_pass=0; } + + }; + + struct InstancePortal { + + Portal *portal; + Set<Instance*> candidate_set; + Instance *connected; + uint64_t last_visited_pass; + + Plane plane_cache; + Vector<Vector3> transformed_point_cache; + + + PortalInfo() { connected=NULL; last_visited_pass=0;} + }; +*/ + + + + /* SCENARIO API */ + + struct Instance; + + struct Scenario : RID_Data { + + + VS::ScenarioDebugMode debug; + RID self; + // well wtf, balloon allocator is slower? + + Octree<Instance,true> octree; + + List<Instance*> directional_lights; + RID environment; + RID fallback_environment; + RID reflection_probe_shadow_atlas; + RID reflection_atlas; + + + SelfList<Instance>::List instances; + + Scenario() { debug=VS::SCENARIO_DEBUG_DISABLED; } + }; + + mutable RID_Owner<Scenario> scenario_owner; + + static void* _instance_pair(void *p_self, OctreeElementID, Instance *p_A,int, OctreeElementID, Instance *p_B,int); + static void _instance_unpair(void *p_self, OctreeElementID, Instance *p_A,int, OctreeElementID, Instance *p_B,int,void*); + + virtual RID scenario_create(); + + virtual void scenario_set_debug(RID p_scenario,VS::ScenarioDebugMode p_debug_mode); + virtual void scenario_set_environment(RID p_scenario, RID p_environment); + virtual void scenario_set_fallback_environment(RID p_scenario, RID p_environment); + virtual void scenario_set_reflection_atlas_size(RID p_scenario, int p_size,int p_subdiv); + + + /* INSTANCING API */ + + struct InstanceBaseData { + + + virtual ~InstanceBaseData() {} + }; + + + + struct Instance : RasterizerScene::InstanceBase { + + RID self; + //scenario stuff + OctreeElementID octree_id; + Scenario *scenario; + SelfList<Instance> scenario_item; + + //aabb stuff + bool update_aabb; + bool update_materials; + + SelfList<Instance> update_item; + + + Rect3 aabb; + Rect3 transformed_aabb; + float extra_margin; + uint32_t object_ID; + + float lod_begin; + float lod_end; + float lod_begin_hysteresis; + float lod_end_hysteresis; + RID lod_instance; + + Instance *room; + SelfList<Instance> room_item; + bool visible_in_all_rooms; + + uint64_t last_render_pass; + uint64_t last_frame_pass; + + uint64_t version; // changes to this, and changes to base increase version + + InstanceBaseData *base_data; + + virtual void base_removed() { + + singleton->instance_set_base(self,RID()); + } + + virtual void base_changed() { + + singleton->_instance_queue_update(this,true,true); + } + + virtual void base_material_changed() { + + singleton->_instance_queue_update(this,false,true); + } + + + Instance() : scenario_item(this), update_item(this), room_item(this) { + + octree_id=0; + scenario=NULL; + + + update_aabb=false; + update_materials=false; + + extra_margin=0; + + + object_ID=0; + visible=true; + + lod_begin=0; + lod_end=0; + lod_begin_hysteresis=0; + lod_end_hysteresis=0; + + room=NULL; + visible_in_all_rooms=false; + + + + last_render_pass=0; + last_frame_pass=0; + version=1; + base_data=NULL; + + } + + ~Instance() { + + if (base_data) + memdelete(base_data); + + } + }; + + SelfList<Instance>::List _instance_update_list; + void _instance_queue_update(Instance *p_instance,bool p_update_aabb,bool p_update_materials=false); + + + struct InstanceGeometryData : public InstanceBaseData { + + List<Instance*> lighting; + bool lighting_dirty; + bool can_cast_shadows; + + List<Instance*> reflection_probes; + bool reflection_dirty; + + List<Instance*> gi_probes; + bool gi_probes_dirty; + + InstanceGeometryData() { + + lighting_dirty=false; + reflection_dirty=true; + can_cast_shadows=true; + gi_probes_dirty=true; + } + }; + + struct InstanceReflectionProbeData : public InstanceBaseData { + + + Instance *owner; + + struct PairInfo { + List<Instance*>::Element *L; //reflection iterator in geometry + Instance *geometry; + }; + List<PairInfo> geometries; + + + RID instance; + bool reflection_dirty; + SelfList<InstanceReflectionProbeData> update_list; + + int render_step; + + InstanceReflectionProbeData() : update_list(this) { + + reflection_dirty=true; + render_step=-1; + } + }; + + SelfList<InstanceReflectionProbeData>::List reflection_probe_render_list; + + struct InstanceLightData : public InstanceBaseData { + + struct PairInfo { + List<Instance*>::Element *L; //light iterator in geometry + Instance *geometry; + }; + + RID instance; + uint64_t last_version; + List<Instance*>::Element *D; // directional light in scenario + + bool shadow_dirty; + + List<PairInfo> geometries; + + Instance *baked_light; + + InstanceLightData() { + + shadow_dirty=true; + D=NULL; + last_version=0; + baked_light=NULL; + } + }; + + struct InstanceGIProbeData : public InstanceBaseData { + + + Instance *owner; + + struct PairInfo { + List<Instance*>::Element *L; //gi probe iterator in geometry + Instance *geometry; + }; + + List<PairInfo> geometries; + + Set<Instance*> lights; + + struct LightCache { + + VS::LightType type; + Transform transform; + Color color; + float energy; + float radius; + float attenuation; + float spot_angle; + float spot_attenuation; + + bool operator==(const LightCache& p_cache) { + + return (type==p_cache.type && + transform==p_cache.transform && + color==p_cache.color && + energy==p_cache.energy && + radius==p_cache.radius && + attenuation==p_cache.attenuation && + spot_angle==p_cache.spot_angle && + spot_attenuation==p_cache.spot_attenuation); + } + + LightCache() { + + type=VS::LIGHT_DIRECTIONAL; + energy=1.0; + radius=1.0; + attenuation=1.0; + spot_angle=1.0; + spot_attenuation=1.0; + + } + + }; + + struct LocalData { + uint16_t pos[3]; + uint16_t energy[3]; //using 0..1024 for float range 0..1. integer is needed for deterministic add/remove of lights + }; + + struct CompBlockS3TC { + uint32_t offset; //offset in mipmap + uint32_t source_count; //sources + uint32_t sources[16]; //id for each source + uint8_t alpha[8]; //alpha block is pre-computed + }; + + + struct Dynamic { + + Map<RID,LightCache> light_cache; + Map<RID,LightCache> light_cache_changes; + PoolVector<int> light_data; + PoolVector<LocalData> local_data; + Vector<Vector<uint32_t> > level_cell_lists; + RID probe_data; + bool enabled; + int bake_dynamic_range; + RasterizerStorage::GIProbeCompression compression; + + Vector< PoolVector<uint8_t> > mipmaps_3d; + Vector< PoolVector<CompBlockS3TC> > mipmaps_s3tc; //for s3tc + + int updating_stage; + float propagate; + + int grid_size[3]; + + Transform light_to_cell_xform; + + } dynamic; + + + RID probe_instance; + + + bool invalid; + uint32_t base_version; + + SelfList<InstanceGIProbeData> update_element; + + InstanceGIProbeData() : update_element(this) { + invalid=true; + base_version=0; + } + + }; + + + SelfList<InstanceGIProbeData>::List gi_probe_update_list; + + + Instance *instance_cull_result[MAX_INSTANCE_CULL]; + Instance *instance_shadow_cull_result[MAX_INSTANCE_CULL]; //used for generating shadowmaps + Instance *light_cull_result[MAX_LIGHTS_CULLED]; + RID light_instance_cull_result[MAX_LIGHTS_CULLED]; + int light_cull_count; + RID reflection_probe_instance_cull_result[MAX_REFLECTION_PROBES_CULLED]; + int reflection_probe_cull_count; + + + RID_Owner<Instance> instance_owner; + + // from can be mesh, light, area and portal so far. + virtual RID instance_create(); // from can be mesh, light, poly, area and portal so far. + + virtual void instance_set_base(RID p_instance, RID p_base); // from can be mesh, light, poly, area and portal so far. + 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_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); + + + virtual void instance_attach_skeleton(RID p_instance,RID p_skeleton); + virtual void instance_set_exterior( RID p_instance, bool p_enabled ); + virtual void instance_set_room( RID p_instance, RID p_room ); + + virtual void instance_set_extra_visibility_margin( RID p_instance, real_t p_margin ); + + + // don't use these in a game! + virtual Vector<ObjectID> instances_cull_aabb(const Rect3& p_aabb, RID p_scenario=RID()) const; + virtual Vector<ObjectID> instances_cull_ray(const Vector3& p_from, const Vector3& p_to, RID p_scenario=RID()) const; + virtual Vector<ObjectID> instances_cull_convex(const Vector<Plane>& p_convex, RID p_scenario=RID()) const; + + + virtual void instance_geometry_set_flag(RID p_instance,VS::InstanceFlags p_flags,bool p_enabled); + virtual void instance_geometry_set_cast_shadows_setting(RID p_instance, VS::ShadowCastingSetting p_shadow_casting_setting); + virtual void instance_geometry_set_material_override(RID p_instance, RID p_material); + + + virtual void instance_geometry_set_draw_range(RID p_instance,float p_min,float p_max,float p_min_margin,float p_max_margin); + virtual void instance_geometry_set_as_instance_lod(RID p_instance,RID p_as_lod_of_instance); + + + _FORCE_INLINE_ void _update_instance(Instance *p_instance); + _FORCE_INLINE_ void _update_instance_aabb(Instance *p_instance); + _FORCE_INLINE_ void _update_dirty_instance(Instance *p_instance); + + _FORCE_INLINE_ void _light_instance_update_shadow(Instance *p_instance,const Transform p_cam_transform,const CameraMatrix& p_cam_projection,bool p_cam_orthogonal,RID p_shadow_atlas,Scenario* p_scenario); + + void _render_scene(const Transform p_cam_transform, const CameraMatrix& p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass); + + void render_camera(RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas); + void update_dirty_instances(); + + //probes + struct GIProbeDataHeader { + + uint32_t version; + uint32_t cell_subdiv; + uint32_t width; + uint32_t height; + uint32_t depth; + uint32_t cell_count; + uint32_t leaf_cell_count; + }; + + + struct GIProbeDataCell { + + uint32_t children[8]; + uint32_t albedo; + uint32_t emission; + uint32_t normal; + uint32_t level_alpha; + }; + + enum { + GI_UPDATE_STAGE_CHECK, + GI_UPDATE_STAGE_LIGHTING, + GI_UPDATE_STAGE_UPLOADING, + }; + + void _gi_probe_bake_thread(); + static void _gi_probe_bake_threads(void*); + + volatile bool probe_bake_thread_exit; + Thread *probe_bake_thread; + Semaphore *probe_bake_sem; + Mutex *probe_bake_mutex; + List<Instance*> probe_bake_list; + + bool _render_reflection_probe_step(Instance* p_instance,int p_step); + void _gi_probe_fill_local_data(int p_idx,int p_level,int p_x,int p_y,int p_z,const GIProbeDataCell* p_cell,const GIProbeDataHeader *p_header,InstanceGIProbeData::LocalData *p_local_data,Vector<uint32_t> *prev_cell); + + _FORCE_INLINE_ uint32_t _gi_bake_find_cell(const GIProbeDataCell *cells,int x,int y, int z,int p_cell_subdiv); + void _bake_gi_downscale_light(int p_idx, int p_level, const GIProbeDataCell* p_cells, const GIProbeDataHeader *p_header, InstanceGIProbeData::LocalData *p_local_data, float p_propagate); + void _bake_gi_probe_light(const GIProbeDataHeader *header,const GIProbeDataCell *cells,InstanceGIProbeData::LocalData *local_data,const uint32_t *leaves,int p_leaf_count, const InstanceGIProbeData::LightCache& light_cache,int p_sign); + void _bake_gi_probe(Instance *p_probe); + bool _check_gi_probe(Instance *p_gi_probe); + void _setup_gi_probe(Instance *p_instance); + + void render_probes(); + + + bool free(RID p_rid); + + VisualServerScene(); + ~VisualServerScene(); +}; + +#endif // VISUALSERVERSCENE_H diff --git a/servers/visual/visual_server_viewport.cpp b/servers/visual/visual_server_viewport.cpp new file mode 100644 index 0000000000..d32c4dd6bf --- /dev/null +++ b/servers/visual/visual_server_viewport.cpp @@ -0,0 +1,568 @@ +#include "visual_server_viewport.h" +#include "visual_server_global.h" +#include "visual_server_canvas.h" +#include "visual_server_scene.h" +#include "global_config.h" + + + +void VisualServerViewport::_draw_viewport(Viewport *p_viewport) { + + /* Camera should always be BEFORE any other 3D */ +#if 0 + bool scenario_draw_canvas_bg=false; + int scenario_canvas_max_layer=0; + + if (!p_viewport->hide_canvas && !p_viewport->disable_environment && scenario_owner.owns(p_viewport->scenario)) { + + Scenario *scenario=scenario_owner.get(p_viewport->scenario); + if (scenario->environment.is_valid()) { + if (rasterizer->is_environment(scenario->environment)) { + scenario_draw_canvas_bg=rasterizer->environment_get_background(scenario->environment)==VS::ENV_BG_CANVAS; + scenario_canvas_max_layer=rasterizer->environment_get_background_param(scenario->environment,VS::ENV_BG_PARAM_CANVAS_MAX_LAYER); + } + } + } + + bool can_draw_3d=!p_viewport->hide_scenario && camera_owner.owns(p_viewport->camera) && scenario_owner.owns(p_viewport->scenario); + + + if (scenario_draw_canvas_bg) { + + rasterizer->begin_canvas_bg(); + } + + if (!scenario_draw_canvas_bg && can_draw_3d) { + + _draw_viewport_camera(p_viewport,false); + + } else if (true /*|| !p_viewport->canvas_list.empty()*/){ + + //clear the viewport black because of no camera? i seriously should.. + if (p_viewport->render_target_clear_on_new_frame || p_viewport->render_target_clear) { + if (p_viewport->transparent_bg) { + rasterizer->clear_viewport(Color(0,0,0,0)); + } + else { + Color cc=clear_color; + if (scenario_draw_canvas_bg) + cc.a=0; + rasterizer->clear_viewport(cc); + } + p_viewport->render_target_clear=false; + } + } +#endif + + if (p_viewport->clear_mode!=VS::VIEWPORT_CLEAR_NEVER) { + VSG::rasterizer->clear_render_target(clear_color); + if (p_viewport->clear_mode==VS::VIEWPORT_CLEAR_ONLY_NEXT_FRAME) { + p_viewport->clear_mode=VS::VIEWPORT_CLEAR_NEVER; + } + } + + + if (!p_viewport->disable_3d && p_viewport->camera.is_valid()) { + + VSG::scene->render_camera(p_viewport->camera,p_viewport->scenario,p_viewport->size,p_viewport->shadow_atlas); + } + + if (!p_viewport->hide_canvas) { + int i=0; + + Map<Viewport::CanvasKey,Viewport::CanvasData*> canvas_map; + + Rect2 clip_rect(0,0,p_viewport->size.x,p_viewport->size.y); + RasterizerCanvas::Light *lights=NULL; + RasterizerCanvas::Light *lights_with_shadow=NULL; + RasterizerCanvas::Light *lights_with_mask=NULL; + Rect2 shadow_rect; + + int light_count=0; + + 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); + + //find lights in canvas + + + for(Set<RasterizerCanvas::Light*>::Element *F=canvas->lights.front();F;F=F->next()) { + + + RasterizerCanvas::Light* cl=F->get(); + if (cl->enabled && cl->texture.is_valid()) { + //not super efficient.. + Size2 tsize(VSG::storage->texture_get_width(cl->texture),VSG::storage->texture_get_height(cl->texture)); + tsize*=cl->scale; + + Vector2 offset=tsize/2.0; + cl->rect_cache=Rect2(-offset+cl->texture_offset,tsize); + cl->xform_cache=xf * cl->xform; + + + if (clip_rect.intersects_transformed(cl->xform_cache,cl->rect_cache)) { + + cl->filter_next_ptr=lights; + lights=cl; + cl->texture_cache=NULL; + Transform2D scale; + scale.scale(cl->rect_cache.size); + scale.elements[2]=cl->rect_cache.pos; + cl->light_shader_xform = (cl->xform_cache * scale).affine_inverse(); + cl->light_shader_pos=cl->xform_cache[2]; + if (cl->shadow_buffer.is_valid()) { + + cl->shadows_next_ptr=lights_with_shadow; + if (lights_with_shadow==NULL) { + shadow_rect = cl->xform_cache.xform(cl->rect_cache); + } else { + shadow_rect=shadow_rect.merge( cl->xform_cache.xform(cl->rect_cache) ); + } + lights_with_shadow=cl; + cl->radius_cache=cl->rect_cache.size.length(); + + } + if (cl->mode==VS::CANVAS_LIGHT_MODE_MASK) { + cl->mask_next_ptr=lights_with_mask; + lights_with_mask=cl; + } + + light_count++; + } + + VSG::canvas_render->light_internal_update(cl->light_internal,cl); + + } + } + + //print_line("lights: "+itos(light_count)); + canvas_map[ Viewport::CanvasKey( E->key(), E->get().layer) ]=&E->get(); + + } + + if (lights_with_shadow) { + //update shadows if any + + RasterizerCanvas::LightOccluderInstance * occluders=NULL; + + //make list of occluders + for (Map<RID,Viewport::CanvasData>::Element *E=p_viewport->canvas_map.front();E;E=E->next()) { + + VisualServerCanvas::Canvas *canvas = static_cast<VisualServerCanvas::Canvas*>(E->get().canvas); + Transform2D xf = p_viewport->global_transform * E->get().transform; + + + for(Set<RasterizerCanvas::LightOccluderInstance*>::Element *F=canvas->occluders.front();F;F=F->next()) { + + if (!F->get()->enabled) + continue; + F->get()->xform_cache = xf * F->get()->xform; + if (shadow_rect.intersects_transformed(F->get()->xform_cache,F->get()->aabb_cache)) { + + F->get()->next=occluders; + occluders=F->get(); + + } + } + } + //update the light shadowmaps with them + RasterizerCanvas::Light *light=lights_with_shadow; + while(light) { + + VSG::canvas_render->canvas_light_shadow_buffer_update(light->shadow_buffer,light->xform_cache.affine_inverse(),light->item_mask,light->radius_cache/1000.0,light->radius_cache*1.1,occluders,&light->shadow_matrix_cache); + light=light->shadows_next_ptr; + } + + //VSG::canvas_render->reset_canvas(); + } + + VSG::rasterizer->restore_render_target(); + + +#if 0 + if (scenario_draw_canvas_bg && canvas_map.front() && canvas_map.front()->key().layer>scenario_canvas_max_layer) { + + _draw_viewport_camera(p_viewport,!can_draw_3d); + scenario_draw_canvas_bg=false; + + } +#endif + + + for (Map<Viewport::CanvasKey,Viewport::CanvasData*>::Element *E=canvas_map.front();E;E=E->next()) { + + VisualServerCanvas::Canvas *canvas = static_cast<VisualServerCanvas::Canvas*>(E->get()->canvas); + + //print_line("canvas "+itos(i)+" size: "+itos(I->get()->canvas->child_items.size())); + //print_line("GT "+p_viewport->global_transform+". CT: "+E->get()->transform); + Transform2D xform = p_viewport->global_transform * E->get()->transform; + + RasterizerCanvas::Light *canvas_lights=NULL; + + RasterizerCanvas::Light *ptr=lights; + while(ptr) { + if (E->get()->layer>=ptr->layer_min && E->get()->layer<=ptr->layer_max) { + ptr->next_ptr=canvas_lights; + canvas_lights=ptr; + } + ptr=ptr->filter_next_ptr; + } + + VSG::canvas->render_canvas( canvas,xform,canvas_lights,lights_with_mask,clip_rect ); + i++; +#if 0 + if (scenario_draw_canvas_bg && E->key().layer>=scenario_canvas_max_layer) { + _draw_viewport_camera(p_viewport,!can_draw_3d); + scenario_draw_canvas_bg=false; + } +#endif + + + } +#if 0 + if (scenario_draw_canvas_bg) { + _draw_viewport_camera(p_viewport,!can_draw_3d); + scenario_draw_canvas_bg=false; + } +#endif + + //VSG::canvas_render->canvas_debug_viewport_shadows(lights_with_shadow); + } + + + +} + +void VisualServerViewport::draw_viewports() { + + //sort viewports + + + //draw viewports + + clear_color=GLOBAL_GET("rendering/viewport/default_clear_color"); + + + active_viewports.sort_custom<ViewportSort>(); + + for(int i=0;i<active_viewports.size();i++) { + + Viewport *vp = active_viewports[i]; + + if (vp->update_mode==VS::VIEWPORT_UPDATE_DISABLED) + continue; + + ERR_CONTINUE( !vp->render_target.is_valid() ); + + bool visible = vp->viewport_to_screen_rect!=Rect2() || vp->update_mode==VS::VIEWPORT_UPDATE_ALWAYS || vp->update_mode==VS::VIEWPORT_UPDATE_ONCE; + + if (!visible) + continue; + + VSG::rasterizer->set_current_render_target(vp->render_target); + _draw_viewport(vp); + + if (vp->viewport_to_screen_rect!=Rect2()) { + //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); + } + + if (vp->update_mode==VS::VIEWPORT_UPDATE_ONCE) { + vp->update_mode=VS::VIEWPORT_UPDATE_DISABLED; + } + } +} + + +RID VisualServerViewport::viewport_create() { + + Viewport * viewport = memnew( Viewport ); + + RID rid = viewport_owner.make_rid(viewport); + + viewport->self=rid; + viewport->hide_scenario=false; + viewport->hide_canvas=false; + viewport->render_target=VSG::storage->render_target_create(); + viewport->shadow_atlas=VSG::scene_render->shadow_atlas_create(); + + return rid; + +} + +void VisualServerViewport::viewport_set_size(RID p_viewport,int p_width,int p_height){ + + ERR_FAIL_COND(p_width<0 && p_height<0); + + Viewport * viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + + + viewport->size=Size2(p_width,p_height); + VSG::storage->render_target_set_size(viewport->render_target,p_width,p_height); + + +} + +void VisualServerViewport::viewport_set_active(RID p_viewport,bool p_active) { + + Viewport * viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + if (p_active) { + ERR_FAIL_COND(active_viewports.find(viewport)!=-1);//already active + active_viewports.push_back(viewport); + } else { + active_viewports.erase(viewport); + } + + +} + +void VisualServerViewport::viewport_set_parent_viewport(RID p_viewport,RID p_parent_viewport) { + + Viewport * viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + viewport->parent=p_parent_viewport; +} + +void VisualServerViewport::viewport_set_clear_mode(RID p_viewport,VS::ViewportClearMode p_clear_mode) { + + Viewport * viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + viewport->clear_mode=p_clear_mode; + +} + + +void VisualServerViewport::viewport_attach_to_screen(RID p_viewport,const Rect2& p_rect,int p_screen){ + + Viewport * viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + viewport->viewport_to_screen_rect=p_rect; + viewport->viewport_to_screen=p_screen; +} +void VisualServerViewport::viewport_detach(RID p_viewport){ + + Viewport * viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + viewport->viewport_to_screen_rect=Rect2(); + viewport->viewport_to_screen=0; + +} + +void VisualServerViewport::viewport_set_update_mode(RID p_viewport,VS::ViewportUpdateMode p_mode){ + + Viewport * viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + viewport->update_mode=p_mode; + +} +void VisualServerViewport::viewport_set_vflip(RID p_viewport,bool p_enable){ + + Viewport * viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + VSG::storage->render_target_set_flag(viewport->render_target,RasterizerStorage::RENDER_TARGET_VFLIP,p_enable); + +} + +RID VisualServerViewport::viewport_get_texture(RID p_viewport) const{ + + const Viewport * viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND_V(!viewport,RID()); + + return VSG::storage->render_target_get_texture(viewport->render_target); + +} + +void VisualServerViewport::viewport_set_hide_scenario(RID p_viewport,bool p_hide){ + + Viewport * viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + viewport->hide_scenario=p_hide; +} +void VisualServerViewport::viewport_set_hide_canvas(RID p_viewport,bool p_hide){ + + Viewport * viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + viewport->hide_canvas=p_hide; +} +void VisualServerViewport::viewport_set_disable_environment(RID p_viewport,bool p_disable){ + + Viewport * viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + + viewport->disable_environment=p_disable; +} + +void VisualServerViewport::viewport_set_disable_3d(RID p_viewport,bool p_disable){ + + Viewport * viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + + viewport->disable_3d=p_disable; + VSG::storage->render_target_set_flag(viewport->render_target,RasterizerStorage::RENDER_TARGET_NO_3D,p_disable); +} + +void VisualServerViewport::viewport_attach_camera(RID p_viewport,RID p_camera){ + + Viewport * viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + viewport->camera=p_camera; +} +void VisualServerViewport::viewport_set_scenario(RID p_viewport,RID p_scenario){ + + Viewport * viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + viewport->scenario=p_scenario; +} +void VisualServerViewport::viewport_attach_canvas(RID p_viewport,RID p_canvas){ + + Viewport * viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + ERR_FAIL_COND(viewport->canvas_map.has(p_canvas)); + VisualServerCanvas::Canvas *canvas = VSG::canvas->canvas_owner.getornull(p_canvas); + ERR_FAIL_COND(!canvas); + + canvas->viewports.insert(p_viewport); + viewport->canvas_map[p_canvas]=Viewport::CanvasData(); + viewport->canvas_map[p_canvas].layer=0; + viewport->canvas_map[p_canvas].canvas=canvas; + +} + +void VisualServerViewport::viewport_remove_canvas(RID p_viewport,RID p_canvas){ + + Viewport * viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + VisualServerCanvas::Canvas *canvas = VSG::canvas->canvas_owner.getornull(p_canvas); + ERR_FAIL_COND(!canvas); + + viewport->canvas_map.erase(p_canvas); + canvas->viewports.erase(p_viewport); + +} +void VisualServerViewport::viewport_set_canvas_transform(RID p_viewport,RID p_canvas,const Transform2D& p_offset){ + + Viewport * viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + ERR_FAIL_COND(!viewport->canvas_map.has(p_canvas)); + viewport->canvas_map[p_canvas].transform=p_offset; + +} +void VisualServerViewport::viewport_set_transparent_background(RID p_viewport,bool p_enabled){ + + Viewport * viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + VSG::storage->render_target_set_flag(viewport->render_target,RasterizerStorage::RENDER_TARGET_TRANSPARENT,p_enabled); + +} + +void VisualServerViewport::viewport_set_global_canvas_transform(RID p_viewport,const Transform2D& p_transform){ + + Viewport * viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + viewport->global_transform=p_transform; + +} +void VisualServerViewport::viewport_set_canvas_layer(RID p_viewport,RID p_canvas,int p_layer){ + + Viewport * viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + ERR_FAIL_COND(!viewport->canvas_map.has(p_canvas)); + viewport->canvas_map[p_canvas].layer=p_layer; + +} + +void VisualServerViewport::viewport_set_shadow_atlas_size(RID p_viewport,int p_size) { + + Viewport * viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + viewport->shadow_atlas_size=p_size; + + VSG::scene_render->shadow_atlas_set_size( viewport->shadow_atlas, viewport->shadow_atlas_size); + +} + +void VisualServerViewport::viewport_set_shadow_atlas_quadrant_subdivision(RID p_viewport,int p_quadrant,int p_subdiv) { + + Viewport * viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + VSG::scene_render->shadow_atlas_set_quadrant_subdivision( viewport->shadow_atlas, p_quadrant, p_subdiv); + +} + +void VisualServerViewport::viewport_set_msaa(RID p_viewport,VS::ViewportMSAA p_msaa) { + + Viewport * viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + VSG::storage->render_target_set_msaa(viewport->render_target,p_msaa); +} + +void VisualServerViewport::viewport_set_hdr(RID p_viewport,bool p_enabled) { + + Viewport * viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + VSG::storage->render_target_set_flag(viewport->render_target,RasterizerStorage::RENDER_TARGET_HDR,p_enabled); + +} + +bool VisualServerViewport::free(RID p_rid) { + + if (viewport_owner.owns(p_rid)) { + + Viewport * viewport = viewport_owner.getornull(p_rid); + + + VSG::storage->free( viewport->render_target ); + VSG::scene_render->free( viewport->shadow_atlas ); + + while(viewport->canvas_map.front()) { + viewport_remove_canvas(p_rid,viewport->canvas_map.front()->key()); + } + + viewport_set_scenario(p_rid,RID()); + active_viewports.erase(viewport); + + viewport_owner.free(p_rid); + memdelete(viewport); + + + return true; + } + + return false; + +} + +VisualServerViewport::VisualServerViewport() +{ + +} diff --git a/servers/visual/visual_server_viewport.h b/servers/visual/visual_server_viewport.h new file mode 100644 index 0000000000..ff4bc2601d --- /dev/null +++ b/servers/visual/visual_server_viewport.h @@ -0,0 +1,150 @@ +#ifndef VISUALSERVERVIEWPORT_H +#define VISUALSERVERVIEWPORT_H + +#include "servers/visual_server.h" +#include "rasterizer.h" +#include "self_list.h" + +class VisualServerViewport { +public: + + struct CanvasBase : public RID_Data { + + + }; + + + + struct Viewport : public RID_Data { + + RID self; + RID parent; + + Size2i size; + RID camera; + RID scenario; + + VS::ViewportUpdateMode update_mode; + RID render_target; + RID render_target_texture; + + int viewport_to_screen; + Rect2 viewport_to_screen_rect; + + bool hide_scenario; + bool hide_canvas; + bool disable_environment; + bool disable_3d; + + RID shadow_atlas; + int shadow_atlas_size; + + + VS::ViewportClearMode clear_mode; + + bool rendered_in_prev_frame; + + struct CanvasKey { + + int layer; + RID canvas; + bool operator<(const CanvasKey& p_canvas) const { if (layer==p_canvas.layer) return canvas < p_canvas.canvas; return layer<p_canvas.layer; } + CanvasKey() { layer=0; } + CanvasKey(const RID& p_canvas, int p_layer) { canvas=p_canvas; layer=p_layer; } + }; + + struct CanvasData { + + CanvasBase *canvas; + Transform2D transform; + int layer; + }; + + Transform2D global_transform; + + Map<RID,CanvasData> canvas_map; + + Viewport() { + update_mode=VS::VIEWPORT_UPDATE_WHEN_VISIBLE; + clear_mode=VS::VIEWPORT_CLEAR_ALWAYS; + rendered_in_prev_frame=false; + disable_environment=false; + viewport_to_screen=0; + shadow_atlas_size=0; + disable_3d=false; + + } + }; + + mutable RID_Owner<Viewport> viewport_owner; + + + struct ViewportSort { + _FORCE_INLINE_ bool operator()(const Viewport*p_left,const Viewport* p_right) const { + + bool left_to_screen = p_left->viewport_to_screen_rect.size!=Size2(); + bool right_to_screen = p_right->viewport_to_screen_rect.size!=Size2(); + + if (left_to_screen==right_to_screen) { + + return p_left->parent==p_right->self; + } else { + return right_to_screen; + } + } + }; + + + Vector<Viewport*> active_viewports; +private: + Color clear_color; + void _draw_viewport(Viewport *p_viewport); +public: + + + RID viewport_create(); + + 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_detach(RID p_viewport); + + void viewport_set_active(RID p_viewport,bool p_active); + void viewport_set_parent_viewport(RID p_viewport,RID p_parent_viewport); + void viewport_set_update_mode(RID p_viewport,VS::ViewportUpdateMode p_mode); + void viewport_set_vflip(RID p_viewport,bool p_enable); + + + void viewport_set_clear_mode(RID p_viewport,VS::ViewportClearMode p_clear_mode); + + RID viewport_get_texture(RID p_viewport) const; + + void viewport_set_hide_scenario(RID p_viewport,bool p_hide); + void viewport_set_hide_canvas(RID p_viewport,bool p_hide); + void viewport_set_disable_environment(RID p_viewport,bool p_disable); + void viewport_set_disable_3d(RID p_viewport,bool p_disable); + + void viewport_attach_camera(RID p_viewport,RID p_camera); + void viewport_set_scenario(RID p_viewport,RID p_scenario); + void viewport_attach_canvas(RID p_viewport,RID p_canvas); + void viewport_remove_canvas(RID p_viewport,RID p_canvas); + void viewport_set_canvas_transform(RID p_viewport,RID p_canvas,const Transform2D& p_offset); + void viewport_set_transparent_background(RID p_viewport,bool p_enabled); + + void viewport_set_global_canvas_transform(RID p_viewport,const Transform2D& p_transform); + void viewport_set_canvas_layer(RID p_viewport,RID p_canvas,int p_layer); + + void viewport_set_shadow_atlas_size(RID p_viewport,int p_size); + void viewport_set_shadow_atlas_quadrant_subdivision(RID p_viewport,int p_quadrant,int p_subdiv); + + void viewport_set_msaa(RID p_viewport,VS::ViewportMSAA p_msaa); + void viewport_set_hdr(RID p_viewport,bool p_enabled); + + void draw_viewports(); + + bool free(RID p_rid); + + VisualServerViewport(); +}; + +#endif // VISUALSERVERVIEWPORT_H diff --git a/servers/visual/visual_server_wrap_mt.cpp b/servers/visual/visual_server_wrap_mt.cpp deleted file mode 100644 index 5ea4145342..0000000000 --- a/servers/visual/visual_server_wrap_mt.cpp +++ /dev/null @@ -1,212 +0,0 @@ -/*************************************************************************/ -/* visual_server_wrap_mt.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "visual_server_wrap_mt.h" -#include "os/os.h" -#include "globals.h" -void VisualServerWrapMT::thread_exit() { - - exit=true; -} - -void VisualServerWrapMT::thread_draw() { - - - draw_mutex->lock(); - - draw_pending--; - bool draw=(draw_pending==0);// only draw when no more flushes are pending - - draw_mutex->unlock(); - - if (draw) { - - visual_server->draw(); - } - -} - -void VisualServerWrapMT::thread_flush() { - - - draw_mutex->lock(); - - draw_pending--; - - draw_mutex->unlock(); - -} - - - -void VisualServerWrapMT::_thread_callback(void *_instance) { - - VisualServerWrapMT *vsmt = reinterpret_cast<VisualServerWrapMT*>(_instance); - - - vsmt->thread_loop(); -} - -void VisualServerWrapMT::thread_loop() { - - server_thread=Thread::get_caller_ID(); - - OS::get_singleton()->make_rendering_thread(); - - visual_server->init(); - - exit=false; - draw_thread_up=true; - while(!exit) { - // flush commands one by one, until exit is requested - command_queue.wait_and_flush_one(); - } - - command_queue.flush_all(); // flush all - - visual_server->finish(); - -} - - -/* EVENT QUEUING */ - -void VisualServerWrapMT::sync() { - - if (create_thread) { - - /* TODO: sync with the thread */ - - /* - ERR_FAIL_COND(!draw_mutex); - draw_mutex->lock(); - draw_pending++; //cambiar por un saferefcount - draw_mutex->unlock(); - */ - //command_queue.push( this, &VisualServerWrapMT::thread_flush); - } else { - - command_queue.flush_all(); //flush all pending from other threads - } - -} - -void VisualServerWrapMT::draw() { - - - if (create_thread) { - - /* TODO: Make it draw - ERR_FAIL_COND(!draw_mutex); - draw_mutex->lock(); - draw_pending++; //cambiar por un saferefcount - draw_mutex->unlock(); - - command_queue.push( this, &VisualServerWrapMT::thread_draw); - */ - } else { - - visual_server->draw(); - } -} - - -void VisualServerWrapMT::init() { - - if (create_thread) { - - draw_mutex = Mutex::create(); - print_line("CREATING RENDER THREAD"); - OS::get_singleton()->release_rendering_thread(); - if (create_thread) { - thread = Thread::create( _thread_callback, this ); - print_line("STARTING RENDER THREAD"); - } - while(!draw_thread_up) { - OS::get_singleton()->delay_usec(1000); - } - print_line("DONE RENDER THREAD"); - } else { - - visual_server->init(); - } - -} - -void VisualServerWrapMT::finish() { - - - if (thread) { - - command_queue.push( this, &VisualServerWrapMT::thread_exit); - Thread::wait_to_finish( thread ); - memdelete(thread); - - - texture_free_cached_ids(); - mesh_free_cached_ids(); - - thread=NULL; - } else { - visual_server->finish(); - } - - if (draw_mutex) - memdelete(draw_mutex); - -} - - -VisualServerWrapMT::VisualServerWrapMT(VisualServer* p_contained,bool p_create_thread) : command_queue(p_create_thread) { - - visual_server=p_contained; - create_thread=p_create_thread; - thread=NULL; - draw_mutex=NULL; - draw_pending=0; - draw_thread_up=false; - alloc_mutex=Mutex::create(); - texture_pool_max_size=GLOBAL_DEF("render/thread_textures_prealloc",5); - mesh_pool_max_size=GLOBAL_DEF("core/rid_pool_prealloc",20); - if (!p_create_thread) { - server_thread=Thread::get_caller_ID(); - } else { - server_thread=0; - } -} - - -VisualServerWrapMT::~VisualServerWrapMT() { - - memdelete(visual_server); - memdelete(alloc_mutex); - //finish(); - -} - - diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h deleted file mode 100644 index b4e374dd6f..0000000000 --- a/servers/visual/visual_server_wrap_mt.h +++ /dev/null @@ -1,739 +0,0 @@ -/*************************************************************************/ -/* visual_server_wrap_mt.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#ifndef VISUAL_SERVER_WRAP_MT_H -#define VISUAL_SERVER_WRAP_MT_H - - -#include "servers/visual_server.h" -#include "command_queue_mt.h" -#include "os/thread.h" - -/** - @author Juan Linietsky <reduzio@gmail.com> -*/ -class VisualServerWrapMT : public VisualServer { - - // the real visual server - mutable VisualServer *visual_server; - - mutable CommandQueueMT command_queue; - - static void _thread_callback(void *_instance); - void thread_loop(); - - Thread::ID server_thread; - volatile bool exit; - Thread *thread; - volatile bool draw_thread_up; - bool create_thread; - - Mutex *draw_mutex; - int draw_pending; - void thread_draw(); - void thread_flush(); - - void thread_exit(); - - Mutex*alloc_mutex; - - - int texture_pool_max_size; - List<RID> texture_id_pool; - - int mesh_pool_max_size; - List<RID> mesh_id_pool; - -//#define DEBUG_SYNC - -#ifdef DEBUG_SYNC -#define SYNC_DEBUG print_line("sync on: "+String(__FUNCTION__)); -#else -#define SYNC_DEBUG -#endif - -public: - -#define ServerName VisualServer -#define ServerNameWrapMT VisualServerWrapMT -#define server_name visual_server -#include "servers/server_wrap_mt_common.h" - - //FUNC0R(RID,texture_create); - FUNCRID(texture); - FUNC5(texture_allocate,RID,int,int,Image::Format,uint32_t); - FUNC3(texture_set_data,RID,const Image&,CubeMapSide); - FUNC2RC(Image,texture_get_data,RID,CubeMapSide); - FUNC2(texture_set_flags,RID,uint32_t); - FUNC1RC(Image::Format,texture_get_format,RID); - FUNC1RC(uint32_t,texture_get_flags,RID); - FUNC1RC(uint32_t,texture_get_width,RID); - FUNC1RC(uint32_t,texture_get_height,RID); - FUNC3(texture_set_size_override,RID,int,int); - FUNC1RC(bool,texture_can_stream,RID); - FUNC3C(texture_set_reload_hook,RID,ObjectID,const StringName&); - - FUNC2(texture_set_path,RID,const String&); - FUNC1RC(String,texture_get_path,RID); - - FUNC1(texture_set_shrink_all_x2_on_set_data,bool); - - virtual void texture_debug_usage(List<TextureInfo> *r_info) { - //pass directly, should lock the server anyway - visual_server->texture_debug_usage(r_info); - } - - - /* SHADER API */ - - FUNC1R(RID,shader_create,ShaderMode); - FUNC2(shader_set_mode,RID,ShaderMode); - FUNC1RC(ShaderMode,shader_get_mode,RID); - FUNC7(shader_set_code,RID,const String&,const String&,const String&,int,int,int); - FUNC1RC(String,shader_get_vertex_code,RID); - FUNC1RC(String,shader_get_fragment_code,RID); - FUNC1RC(String,shader_get_light_code,RID); - FUNC2SC(shader_get_param_list,RID,List<PropertyInfo>*); - - FUNC3(shader_set_default_texture_param,RID,const StringName&,RID); - FUNC2RC(RID,shader_get_default_texture_param,RID,const StringName&); - - - /*virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) { - if (Thread::get_caller_ID()!=server_thread) { - command_queue.push_and_sync( visual_server, &VisualServer::shader_get_param_list,p_shader,p_param_list); - } else { - visual_server->m_type(p1, p2, p3, p4, p5); - } - }*/ - -// virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list); - - - /* COMMON MATERIAL API */ - - FUNC0R(RID,material_create); - FUNC2(material_set_shader,RID,RID); - FUNC1RC(RID,material_get_shader,RID); - - FUNC3(material_set_param,RID,const StringName&,const Variant&); - FUNC2RC(Variant,material_get_param,RID,const StringName&); - - FUNC3(material_set_flag,RID,MaterialFlag,bool); - FUNC2RC(bool,material_get_flag,RID,MaterialFlag); - - FUNC2(material_set_depth_draw_mode,RID,MaterialDepthDrawMode); - FUNC1RC(MaterialDepthDrawMode,material_get_depth_draw_mode,RID); - - FUNC2(material_set_blend_mode,RID,MaterialBlendMode); - FUNC1RC(MaterialBlendMode,material_get_blend_mode,RID); - - FUNC2(material_set_line_width,RID,float); - FUNC1RC(float,material_get_line_width,RID); - - /* FIXED MATERIAL */ - - - FUNC0R(RID,fixed_material_create); - - FUNC3(fixed_material_set_flag,RID, FixedMaterialFlags , bool ); - FUNC2RC(bool, fixed_material_get_flag,RID, FixedMaterialFlags); - - FUNC3(fixed_material_set_param,RID, FixedMaterialParam, const Variant& ); - FUNC2RC(Variant, fixed_material_get_param,RID ,FixedMaterialParam); - - FUNC3(fixed_material_set_texture,RID ,FixedMaterialParam, RID ); - FUNC2RC(RID, fixed_material_get_texture,RID,FixedMaterialParam); - - - - FUNC3(fixed_material_set_texcoord_mode,RID,FixedMaterialParam, FixedMaterialTexCoordMode ); - FUNC2RC(FixedMaterialTexCoordMode, fixed_material_get_texcoord_mode,RID,FixedMaterialParam); - - FUNC2(fixed_material_set_light_shader,RID,FixedMaterialLightShader); - FUNC1RC(FixedMaterialLightShader, fixed_material_get_light_shader,RID); - - FUNC2(fixed_material_set_uv_transform,RID,const Transform&); - FUNC1RC(Transform, fixed_material_get_uv_transform,RID); - - FUNC2(fixed_material_set_point_size,RID ,float); - FUNC1RC(float,fixed_material_get_point_size,RID); - - /* SURFACE API */ - FUNCRID(mesh); - - FUNC2(mesh_set_morph_target_count,RID,int); - FUNC1RC(int,mesh_get_morph_target_count,RID); - - - FUNC2(mesh_set_morph_target_mode,RID,MorphTargetMode); - FUNC1RC(MorphTargetMode,mesh_get_morph_target_mode,RID); - - FUNC2(mesh_add_custom_surface,RID,const Variant&); //this is used by each platform in a different way - - FUNC5(mesh_add_surface,RID,PrimitiveType,const Array&,const Array&,bool); - FUNC2RC(Array,mesh_get_surface_arrays,RID,int); - FUNC2RC(Array,mesh_get_surface_morph_arrays,RID,int); - - FUNC4(mesh_surface_set_material,RID, int, RID,bool); - FUNC2RC(RID,mesh_surface_get_material,RID, int); - - FUNC2RC(int,mesh_surface_get_array_len,RID, int); - FUNC2RC(int,mesh_surface_get_array_index_len,RID, int); - FUNC2RC(uint32_t,mesh_surface_get_format,RID, int); - FUNC2RC(PrimitiveType,mesh_surface_get_primitive_type,RID, int); - - FUNC2(mesh_remove_surface,RID,int); - FUNC1RC(int,mesh_get_surface_count,RID); - FUNC1(mesh_clear,RID); - - - FUNC2(mesh_set_custom_aabb,RID,const AABB&); - FUNC1RC(AABB,mesh_get_custom_aabb,RID); - - - /* MULTIMESH API */ - - FUNC0R(RID,multimesh_create); - FUNC2(multimesh_set_instance_count,RID,int); - FUNC1RC(int,multimesh_get_instance_count,RID); - - FUNC2(multimesh_set_mesh,RID,RID); - FUNC2(multimesh_set_aabb,RID,const AABB&); - FUNC3(multimesh_instance_set_transform,RID,int,const Transform&); - FUNC3(multimesh_instance_set_color,RID,int,const Color&); - - FUNC1RC(RID,multimesh_get_mesh,RID); - FUNC2RC(AABB,multimesh_get_aabb,RID,const AABB&); - FUNC2RC(Transform,multimesh_instance_get_transform,RID,int); - FUNC2RC(Color,multimesh_instance_get_color,RID,int); - - FUNC2(multimesh_set_visible_instances,RID,int); - FUNC1RC(int,multimesh_get_visible_instances,RID); - - /* IMMEDIATE API */ - - - FUNC0R(RID,immediate_create); - FUNC3(immediate_begin,RID,PrimitiveType,RID); - FUNC2(immediate_vertex,RID,const Vector3&); - FUNC2(immediate_normal,RID,const Vector3&); - FUNC2(immediate_tangent,RID,const Plane&); - FUNC2(immediate_color,RID,const Color&); - FUNC2(immediate_uv,RID,const Vector2&); - FUNC2(immediate_uv2,RID,const Vector2&); - FUNC1(immediate_end,RID); - FUNC1(immediate_clear,RID); - FUNC2(immediate_set_material,RID,RID); - FUNC1RC(RID,immediate_get_material,RID); - - - /* PARTICLES API */ - - FUNC0R(RID,particles_create); - - FUNC2(particles_set_amount,RID, int ); - FUNC1RC(int,particles_get_amount,RID); - - FUNC2(particles_set_emitting,RID, bool ); - FUNC1RC(bool,particles_is_emitting,RID); - - FUNC2(particles_set_visibility_aabb,RID, const AABB&); - FUNC1RC(AABB,particles_get_visibility_aabb,RID); - - FUNC2(particles_set_emission_half_extents,RID, const Vector3&); - FUNC1RC(Vector3,particles_get_emission_half_extents,RID); - - FUNC2(particles_set_emission_base_velocity,RID, const Vector3&); - FUNC1RC(Vector3,particles_get_emission_base_velocity,RID); - - FUNC2(particles_set_emission_points,RID, const DVector<Vector3>& ); - FUNC1RC(DVector<Vector3>,particles_get_emission_points,RID); - - FUNC2(particles_set_gravity_normal,RID, const Vector3& ); - FUNC1RC(Vector3,particles_get_gravity_normal,RID); - - FUNC3(particles_set_variable,RID, ParticleVariable ,float); - FUNC2RC(float,particles_get_variable,RID, ParticleVariable ); - - FUNC3(particles_set_randomness,RID, ParticleVariable ,float); - FUNC2RC(float,particles_get_randomness,RID, ParticleVariable ); - - FUNC3(particles_set_color_phase_pos,RID, int , float); - FUNC2RC(float,particles_get_color_phase_pos,RID, int ); - - FUNC2(particles_set_color_phases,RID, int ); - FUNC1RC(int,particles_get_color_phases,RID); - - FUNC3(particles_set_color_phase_color,RID, int , const Color& ); - FUNC2RC(Color,particles_get_color_phase_color,RID, int ); - - FUNC2(particles_set_attractors,RID, int); - FUNC1RC(int,particles_get_attractors,RID); - - FUNC3(particles_set_attractor_pos,RID, int, const Vector3&); - FUNC2RC(Vector3,particles_get_attractor_pos,RID,int); - - FUNC3(particles_set_attractor_strength,RID, int, float); - FUNC2RC(float,particles_get_attractor_strength,RID,int); - - FUNC3(particles_set_material,RID, RID,bool); - FUNC1RC(RID,particles_get_material,RID); - - FUNC2(particles_set_height_from_velocity,RID, bool); - FUNC1RC(bool,particles_has_height_from_velocity,RID); - - FUNC2(particles_set_use_local_coordinates,RID, bool); - FUNC1RC(bool,particles_is_using_local_coordinates,RID); - - - /* Light API */ - - FUNC1R(RID,light_create,LightType); - FUNC1RC(LightType,light_get_type,RID); - - FUNC3(light_set_color,RID,LightColor , const Color& ); - FUNC2RC(Color,light_get_color,RID,LightColor ); - - - FUNC2(light_set_shadow,RID,bool ); - FUNC1RC(bool,light_has_shadow,RID); - - FUNC2(light_set_volumetric,RID,bool ); - FUNC1RC(bool,light_is_volumetric,RID); - - FUNC2(light_set_projector,RID,RID ); - FUNC1RC(RID,light_get_projector,RID); - - FUNC3(light_set_param,RID, LightParam , float ); - FUNC2RC(float,light_get_param,RID, LightParam ); - - FUNC2(light_set_operator,RID,LightOp); - FUNC1RC(LightOp,light_get_operator,RID); - - FUNC2(light_omni_set_shadow_mode,RID,LightOmniShadowMode); - FUNC1RC(LightOmniShadowMode,light_omni_get_shadow_mode,RID); - - FUNC2(light_directional_set_shadow_mode,RID,LightDirectionalShadowMode); - FUNC1RC(LightDirectionalShadowMode,light_directional_get_shadow_mode,RID); - FUNC3(light_directional_set_shadow_param,RID,LightDirectionalShadowParam, float ); - FUNC2RC(float,light_directional_get_shadow_param,RID,LightDirectionalShadowParam ); - - - /* SKELETON API */ - - FUNC0R(RID,skeleton_create); - FUNC2(skeleton_resize,RID,int ); - FUNC1RC(int,skeleton_get_bone_count,RID) ; - FUNC3(skeleton_bone_set_transform,RID,int, const Transform&); - FUNC2R(Transform,skeleton_bone_get_transform,RID,int ); - - /* ROOM API */ - - FUNC0R(RID,room_create); - FUNC2(room_set_bounds,RID, const BSP_Tree&); - FUNC1RC(BSP_Tree,room_get_bounds,RID); - - /* PORTAL API */ - - FUNC0R(RID,portal_create); - FUNC2(portal_set_shape,RID,const Vector<Point2>&); - FUNC1RC(Vector<Point2>,portal_get_shape,RID); - FUNC2(portal_set_enabled,RID, bool); - FUNC1RC(bool,portal_is_enabled,RID); - FUNC2(portal_set_disable_distance,RID, float); - FUNC1RC(float,portal_get_disable_distance,RID); - FUNC2(portal_set_disabled_color,RID, const Color&); - FUNC1RC(Color,portal_get_disabled_color,RID); - FUNC2(portal_set_connect_range,RID, float); - FUNC1RC(float,portal_get_connect_range,RID); - - - FUNC0R(RID,baked_light_create); - FUNC2(baked_light_set_mode,RID,BakedLightMode); - FUNC1RC(BakedLightMode,baked_light_get_mode,RID); - - FUNC2(baked_light_set_octree,RID,DVector<uint8_t>); - FUNC1RC(DVector<uint8_t>,baked_light_get_octree,RID); - - FUNC2(baked_light_set_light,RID,DVector<uint8_t>); - FUNC1RC(DVector<uint8_t>,baked_light_get_light,RID); - - FUNC2(baked_light_set_sampler_octree,RID,const DVector<int>&); - FUNC1RC(DVector<int>,baked_light_get_sampler_octree,RID); - - FUNC2(baked_light_set_lightmap_multiplier,RID,float); - FUNC1RC(float,baked_light_get_lightmap_multiplier,RID); - - FUNC3(baked_light_add_lightmap,RID,RID,int); - FUNC1(baked_light_clear_lightmaps,RID); - - FUNC2(baked_light_set_realtime_color_enabled, RID, const bool); - FUNC1RC(bool, baked_light_get_realtime_color_enabled, RID); - - FUNC2(baked_light_set_realtime_color, RID, const Color&); - FUNC1RC(Color, baked_light_get_realtime_color, RID); - - FUNC2(baked_light_set_realtime_energy, RID, const float); - FUNC1RC(float, baked_light_get_realtime_energy, RID); - - FUNC0R(RID,baked_light_sampler_create); - - FUNC3(baked_light_sampler_set_param,RID, BakedLightSamplerParam , float ); - FUNC2RC(float,baked_light_sampler_get_param,RID, BakedLightSamplerParam ); - - FUNC2(baked_light_sampler_set_resolution,RID,int); - FUNC1RC(int,baked_light_sampler_get_resolution,RID); - - /* CAMERA API */ - - FUNC0R(RID,camera_create); - FUNC4(camera_set_perspective,RID,float , float , float ); - FUNC4(camera_set_orthogonal,RID,float, float , float ); - FUNC2(camera_set_transform,RID,const Transform& ); - - FUNC2(camera_set_visible_layers,RID,uint32_t); - FUNC1RC(uint32_t,camera_get_visible_layers,RID); - - FUNC2(camera_set_environment,RID,RID); - FUNC1RC(RID,camera_get_environment,RID); - - - FUNC2(camera_set_use_vertical_aspect,RID,bool); - FUNC2RC(bool,camera_is_using_vertical_aspect,RID,bool); - - - /* VIEWPORT API */ - - FUNC0R(RID,viewport_create); - - FUNC2(viewport_attach_to_screen,RID,int ); - FUNC1(viewport_detach,RID); - - FUNC2(viewport_set_as_render_target,RID,bool); - FUNC2(viewport_set_render_target_update_mode,RID,RenderTargetUpdateMode); - FUNC1RC(RenderTargetUpdateMode,viewport_get_render_target_update_mode,RID); - FUNC1RC(RID,viewport_get_render_target_texture,RID); - - FUNC2(viewport_set_render_target_vflip,RID,bool); - FUNC1RC(bool,viewport_get_render_target_vflip,RID); - FUNC2(viewport_set_render_target_to_screen_rect,RID,const Rect2&); - - FUNC2(viewport_set_render_target_clear_on_new_frame,RID,bool); - FUNC1RC(bool,viewport_get_render_target_clear_on_new_frame,RID); - FUNC1(viewport_render_target_clear,RID); - - FUNC1(viewport_queue_screen_capture,RID); - FUNC1RC(Image,viewport_get_screen_capture,RID); - - FUNC2(viewport_set_rect,RID,const ViewportRect&); - FUNC1RC(ViewportRect,viewport_get_rect,RID); - - FUNC2(viewport_set_hide_scenario,RID,bool ); - FUNC2(viewport_set_hide_canvas,RID,bool ); - FUNC2(viewport_attach_camera,RID,RID ); - FUNC2(viewport_set_scenario,RID,RID ); - FUNC2(viewport_set_disable_environment,RID,bool ); - - FUNC1RC(RID,viewport_get_attached_camera,RID); - FUNC1RC(RID,viewport_get_scenario,RID ); - FUNC2(viewport_attach_canvas,RID,RID); - FUNC2(viewport_remove_canvas,RID,RID); - FUNC3(viewport_set_canvas_transform,RID,RID,const Matrix32&); - FUNC2RC(Matrix32,viewport_get_canvas_transform,RID,RID); - FUNC2(viewport_set_global_canvas_transform,RID,const Matrix32&); - FUNC1RC(Matrix32,viewport_get_global_canvas_transform,RID); - FUNC3(viewport_set_canvas_layer,RID,RID ,int); - FUNC2(viewport_set_transparent_background,RID,bool); - FUNC1RC(bool,viewport_has_transparent_background,RID); - - - /* ENVIRONMENT API */ - - FUNC0R(RID,environment_create); - - FUNC2(environment_set_background,RID,EnvironmentBG); - FUNC1RC(EnvironmentBG,environment_get_background,RID); - - FUNC3(environment_set_background_param,RID,EnvironmentBGParam, const Variant&); - FUNC2RC(Variant,environment_get_background_param,RID,EnvironmentBGParam ); - - FUNC3(environment_set_enable_fx,RID,EnvironmentFx,bool); - FUNC2RC(bool,environment_is_fx_enabled,RID,EnvironmentFx); - - - FUNC3(environment_fx_set_param,RID,EnvironmentFxParam,const Variant&); - FUNC2RC(Variant,environment_fx_get_param,RID,EnvironmentFxParam); - - - /* SCENARIO API */ - - FUNC0R(RID,scenario_create); - - FUNC2(scenario_set_debug,RID,ScenarioDebugMode); - FUNC2(scenario_set_environment,RID, RID); - FUNC2RC(RID,scenario_get_environment,RID, RID); - FUNC2(scenario_set_fallback_environment,RID, RID); - - - /* INSTANCING API */ - - FUNC0R(RID,instance_create); - - FUNC2(instance_set_base,RID, RID); - FUNC1RC(RID,instance_get_base,RID); - - FUNC2(instance_set_scenario,RID, RID); - FUNC1RC(RID,instance_get_scenario,RID); - - FUNC2(instance_set_layer_mask,RID, uint32_t); - FUNC1RC(uint32_t,instance_get_layer_mask,RID); - - FUNC1RC(AABB,instance_get_base_aabb,RID); - - FUNC2(instance_attach_object_instance_ID,RID,uint32_t); - FUNC1RC(uint32_t,instance_get_object_instance_ID,RID); - - FUNC2(instance_attach_skeleton,RID,RID); - FUNC1RC(RID,instance_get_skeleton,RID); - - FUNC3(instance_set_morph_target_weight,RID,int, float); - FUNC2RC(float,instance_get_morph_target_weight,RID,int); - - FUNC3(instance_set_surface_material,RID,int, RID); - - FUNC2(instance_set_transform,RID, const Transform&); - FUNC1RC(Transform,instance_get_transform,RID); - - FUNC2(instance_set_exterior,RID, bool ); - FUNC1RC(bool,instance_is_exterior,RID); - - FUNC2(instance_set_room,RID, RID ); - FUNC1RC(RID,instance_get_room,RID ) ; - - FUNC2(instance_set_extra_visibility_margin,RID, real_t ); - FUNC1RC(real_t,instance_get_extra_visibility_margin,RID ); - - FUNC2RC(Vector<RID>,instances_cull_aabb,const AABB& , RID ); - FUNC3RC(Vector<RID>,instances_cull_ray,const Vector3& ,const Vector3&, RID ); - FUNC2RC(Vector<RID>,instances_cull_convex,const Vector<Plane>& , RID ); - - FUNC3(instance_geometry_set_flag,RID,InstanceFlags ,bool ); - FUNC2RC(bool,instance_geometry_get_flag,RID,InstanceFlags ); - - FUNC2(instance_geometry_set_cast_shadows_setting, RID, ShadowCastingSetting); - FUNC1RC(ShadowCastingSetting, instance_geometry_get_cast_shadows_setting, RID); - - FUNC2(instance_geometry_set_material_override,RID, RID ); - FUNC1RC(RID,instance_geometry_get_material_override,RID); - - FUNC3(instance_geometry_set_draw_range,RID,float ,float); - FUNC1RC(float,instance_geometry_get_draw_range_max,RID); - FUNC1RC(float,instance_geometry_get_draw_range_min,RID); - - FUNC2(instance_geometry_set_baked_light,RID, RID ); - FUNC1RC(RID,instance_geometry_get_baked_light,RID); - - FUNC2(instance_geometry_set_baked_light_sampler,RID, RID ); - FUNC1RC(RID,instance_geometry_get_baked_light_sampler,RID); - - FUNC2(instance_geometry_set_baked_light_texture_index,RID, int); - FUNC1RC(int,instance_geometry_get_baked_light_texture_index,RID); - - FUNC2(instance_light_set_enabled,RID,bool); - FUNC1RC(bool,instance_light_is_enabled,RID); - - /* CANVAS (2D) */ - - FUNC0R(RID,canvas_create); - FUNC3(canvas_set_item_mirroring,RID,RID,const Point2&); - FUNC2RC(Point2,canvas_get_item_mirroring,RID,RID); - FUNC2(canvas_set_modulate,RID,const Color&); - - - FUNC0R(RID,canvas_item_create); - - FUNC2(canvas_item_set_parent,RID,RID ); - FUNC1RC(RID,canvas_item_get_parent,RID); - - FUNC2(canvas_item_set_visible,RID,bool ); - FUNC1RC(bool,canvas_item_is_visible,RID); - - FUNC2(canvas_item_set_blend_mode,RID,MaterialBlendMode ); - FUNC2(canvas_item_set_light_mask,RID,int ); - - //FUNC(canvas_item_set_rect,RID, const Rect2& p_rect); - FUNC2(canvas_item_set_transform,RID, const Matrix32& ); - FUNC2(canvas_item_set_clip,RID, bool ); - FUNC2(canvas_item_set_distance_field_mode,RID, bool ); - FUNC3(canvas_item_set_custom_rect,RID, bool ,const Rect2&); - FUNC2(canvas_item_set_opacity,RID, float ); - FUNC2RC(float,canvas_item_get_opacity,RID, float ); - FUNC2(canvas_item_set_on_top,RID, bool ); - FUNC1RC(bool,canvas_item_is_on_top,RID); - - FUNC2(canvas_item_set_self_opacity,RID, float ); - FUNC2RC(float,canvas_item_get_self_opacity,RID, float ); - - FUNC2(canvas_item_attach_viewport,RID, RID ); - - FUNC6(canvas_item_add_line,RID, const Point2& , const Point2& ,const Color& ,float,bool); - FUNC3(canvas_item_add_rect,RID, const Rect2& , const Color& ); - FUNC4(canvas_item_add_circle,RID, const Point2& , float ,const Color& ); - FUNC6(canvas_item_add_texture_rect,RID, const Rect2& , RID ,bool ,const Color&,bool ); - FUNC6(canvas_item_add_texture_rect_region,RID, const Rect2& , RID ,const Rect2& ,const Color&,bool ); - FUNC8(canvas_item_add_style_box,RID, const Rect2& , const Rect2&, RID ,const Vector2& ,const Vector2&, bool ,const Color& ); - FUNC6(canvas_item_add_primitive,RID, const Vector<Point2>& , const Vector<Color>& ,const Vector<Point2>& , RID ,float ); - FUNC5(canvas_item_add_polygon,RID, const Vector<Point2>& , const Vector<Color>& ,const Vector<Point2>& , RID ); - FUNC7(canvas_item_add_triangle_array,RID, const Vector<int>& , const Vector<Point2>& , const Vector<Color>& ,const Vector<Point2>& , RID , int ); - FUNC7(canvas_item_add_triangle_array_ptr,RID, int , const int* , const Point2* , const Color* ,const Point2* , RID ); - - - FUNC2(canvas_item_add_set_transform,RID,const Matrix32& ); - FUNC2(canvas_item_add_set_blend_mode,RID, MaterialBlendMode ); - FUNC2(canvas_item_add_clip_ignore,RID, bool ); - - FUNC2(canvas_item_set_sort_children_by_y,RID,bool); - FUNC2(canvas_item_set_z,RID,int); - FUNC2(canvas_item_set_z_as_relative_to_parent,RID,bool); - FUNC3(canvas_item_set_copy_to_backbuffer,RID,bool,const Rect2&); - - - FUNC2(canvas_item_set_material,RID, RID ); - - FUNC2(canvas_item_set_use_parent_material,RID, bool ); - - FUNC1(canvas_item_clear,RID); - FUNC1(canvas_item_raise,RID); - - /* CANVAS LIGHT */ - FUNC0R(RID,canvas_light_create); - FUNC2(canvas_light_attach_to_canvas,RID,RID); - FUNC2(canvas_light_set_enabled,RID,bool); - FUNC2(canvas_light_set_transform,RID,const Matrix32&); - FUNC2(canvas_light_set_scale,RID,float); - FUNC2(canvas_light_set_texture,RID,RID); - FUNC2(canvas_light_set_texture_offset,RID,const Vector2&); - FUNC2(canvas_light_set_color,RID,const Color&); - FUNC2(canvas_light_set_height,RID,float); - FUNC2(canvas_light_set_energy,RID,float); - FUNC3(canvas_light_set_layer_range,RID,int,int); - FUNC3(canvas_light_set_z_range,RID,int,int); - FUNC2(canvas_light_set_item_mask,RID,int); - FUNC2(canvas_light_set_item_shadow_mask,RID,int); - - FUNC2(canvas_light_set_mode,RID,CanvasLightMode); - FUNC2(canvas_light_set_shadow_enabled,RID,bool); - FUNC2(canvas_light_set_shadow_buffer_size,RID,int); - FUNC2(canvas_light_set_shadow_esm_multiplier,RID,float); - FUNC2(canvas_light_set_shadow_color,RID,const Color&); - - - - /* CANVAS OCCLUDER */ - - FUNC0R(RID,canvas_light_occluder_create); - FUNC2(canvas_light_occluder_attach_to_canvas,RID,RID); - FUNC2(canvas_light_occluder_set_enabled,RID,bool); - FUNC2(canvas_light_occluder_set_polygon,RID,RID); - FUNC2(canvas_light_occluder_set_transform,RID,const Matrix32&); - FUNC2(canvas_light_occluder_set_light_mask,RID,int); - - - FUNC0R(RID,canvas_occluder_polygon_create); - FUNC3(canvas_occluder_polygon_set_shape,RID,const DVector<Vector2>&,bool); - FUNC2(canvas_occluder_polygon_set_shape_as_lines,RID,const DVector<Vector2>&); - FUNC2(canvas_occluder_polygon_set_cull_mode,RID,CanvasOccluderPolygonCullMode); - - /* CANVAS MATERIAL */ - - FUNC0R(RID,canvas_item_material_create); - FUNC2(canvas_item_material_set_shader,RID,RID); - FUNC3(canvas_item_material_set_shader_param,RID,const StringName&,const Variant&); - FUNC2RC(Variant,canvas_item_material_get_shader_param,RID,const StringName&); - FUNC2(canvas_item_material_set_shading_mode,RID,CanvasItemShadingMode); - - /* CURSOR */ - FUNC2(cursor_set_rotation,float , int ); // radians - FUNC4(cursor_set_texture,RID , const Point2 &, int, const Rect2 &); - FUNC2(cursor_set_visible,bool , int ); - FUNC2(cursor_set_pos,const Point2& , int ); - - /* BLACK BARS */ - - FUNC4(black_bars_set_margins,int , int , int , int ); - FUNC4(black_bars_set_images,RID , RID , RID , RID ); - - /* FREE */ - - FUNC1(free,RID); - - /* CUSTOM SHADE MODEL */ - - FUNC2(custom_shade_model_set_shader,int , RID ); - FUNC1RC(RID,custom_shade_model_get_shader,int ); - FUNC2(custom_shade_model_set_name,int , const String& ); - FUNC1RC(String,custom_shade_model_get_name,int ); - FUNC2(custom_shade_model_set_param_info,int , const List<PropertyInfo>& ); - FUNC2SC(custom_shade_model_get_param_info,int , List<PropertyInfo>* ); - - /* EVENT QUEUING */ - - - virtual void init(); - virtual void finish(); - virtual void draw(); - virtual void sync(); - FUNC0RC(bool,has_changed); - - /* RENDER INFO */ - - FUNC1R(int,get_render_info,RenderInfo ); - virtual bool has_feature(Features p_feature) const { return visual_server->has_feature(p_feature); } - - FUNC3(set_boot_image,const Image& , const Color&,bool ); - FUNC1(set_default_clear_color,const Color& ); - - FUNC0R(RID,get_test_cube ); - - - VisualServerWrapMT(VisualServer* p_contained,bool p_create_thread); - ~VisualServerWrapMT(); - -#undef ServerName -#undef ServerNameWrapMT -#undef server_name - -}; - -#ifdef DEBUG_SYNC -#undef DEBUG_SYNC -#endif -#undef SYNC_DEBUG - -#endif diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp index f69580254c..5d231d208e 100644 --- a/servers/visual_server.cpp +++ b/servers/visual_server.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -27,7 +27,7 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "visual_server.h" -#include "globals.h" +#include "global_config.h" #include "method_bind_ext.inc" VisualServer *VisualServer::singleton=NULL; @@ -39,22 +39,12 @@ VisualServer *VisualServer::get_singleton() { } -void VisualServer::set_mipmap_policy(MipMapPolicy p_policy) { - mm_policy=p_policy; -} - -VisualServer::MipMapPolicy VisualServer::get_mipmap_policy() const { - - return (VisualServer::MipMapPolicy)mm_policy; -} - - -DVector<String> VisualServer::_shader_get_param_list(RID p_shader) const { +PoolVector<String> VisualServer::_shader_get_param_list(RID p_shader) const { //remove at some point - DVector<String> pl; + PoolVector<String> pl; #if 0 @@ -93,38 +83,48 @@ RID VisualServer::texture_create_from_image(const Image& p_image,uint32_t p_flag RID VisualServer::get_test_texture() { - if (test_texture) { + if (test_texture.is_valid()) { return test_texture; }; #define TEST_TEXTURE_SIZE 256 - Image data(TEST_TEXTURE_SIZE,TEST_TEXTURE_SIZE,0,Image::FORMAT_RGB); - for (int x=0;x<TEST_TEXTURE_SIZE;x++) { + PoolVector<uint8_t> test_data; + test_data.resize(TEST_TEXTURE_SIZE*TEST_TEXTURE_SIZE*3); - for (int y=0;y<TEST_TEXTURE_SIZE;y++) { + { + PoolVector<uint8_t>::Write w=test_data.write(); - Color c; - int r=255-(x+y)/2; + for (int x=0;x<TEST_TEXTURE_SIZE;x++) { - if ((x%(TEST_TEXTURE_SIZE/8))<2 ||(y%(TEST_TEXTURE_SIZE/8))<2) { + for (int y=0;y<TEST_TEXTURE_SIZE;y++) { - c.r=y; - c.g=r; - c.b=x; + Color c; + int r=255-(x+y)/2; - } else { + if ((x%(TEST_TEXTURE_SIZE/8))<2 ||(y%(TEST_TEXTURE_SIZE/8))<2) { - c.r=r; - c.g=x; - c.b=y; - } + c.r=y; + c.g=r; + c.b=x; - data.put_pixel(x, y, c); + } else { + + c.r=r; + c.g=x; + c.b=y; + } + + w[(y*TEST_TEXTURE_SIZE+x)*3+0]=uint8_t(CLAMP(c.r*255,0,255)); + w[(y*TEST_TEXTURE_SIZE+x)*3+1]=uint8_t(CLAMP(c.g*255,0,255)); + w[(y*TEST_TEXTURE_SIZE+x)*3+2]=uint8_t(CLAMP(c.b*255,0,255)); + } } } + Image data(TEST_TEXTURE_SIZE,TEST_TEXTURE_SIZE,false,Image::FORMAT_RGB8,test_data); + test_texture = texture_create_from_image(data); return test_texture; @@ -150,13 +150,13 @@ void VisualServer::_free_internal_rids() { RID VisualServer::_make_test_cube() { - DVector<Vector3> vertices; - DVector<Vector3> normals; - DVector<float> tangents; - DVector<Vector3> uvs; + PoolVector<Vector3> vertices; + PoolVector<Vector3> normals; + PoolVector<float> tangents; + PoolVector<Vector3> uvs; int vtx_idx=0; -#define ADD_VTX(m_idx);\ +#define ADD_VTX(m_idx) \ vertices.push_back( face_points[m_idx] );\ normals.push_back( normal_points[m_idx] );\ tangents.push_back( normal_points[m_idx][1] );\ @@ -211,16 +211,16 @@ RID VisualServer::_make_test_cube() { d[VisualServer::ARRAY_TEX_UV]= uvs ; d[VisualServer::ARRAY_VERTEX]= vertices ; - DVector<int> indices; + PoolVector<int> indices; indices.resize(vertices.size()); for(int i=0;i<vertices.size();i++) indices.set(i,i); d[VisualServer::ARRAY_INDEX]=indices; - mesh_add_surface( test_cube, PRIMITIVE_TRIANGLES,d ); - + mesh_add_surface_from_arrays( test_cube, PRIMITIVE_TRIANGLES,d ); +/* test_material = fixed_material_create(); //material_set_flag(material, MATERIAL_FLAG_BILLBOARD_TOGGLE,true); fixed_material_set_texture( test_material, FIXED_MATERIAL_PARAM_DIFFUSE, get_test_texture() ); @@ -229,7 +229,7 @@ RID VisualServer::_make_test_cube() { fixed_material_set_param( test_material, FIXED_MATERIAL_PARAM_DIFFUSE, Color(1, 1, 1) ); fixed_material_set_param( test_material, FIXED_MATERIAL_PARAM_SPECULAR, Color(1,1,1) ); - +*/ mesh_surface_set_material(test_cube, 0, test_material ); return test_cube; @@ -238,8 +238,8 @@ RID VisualServer::_make_test_cube() { RID VisualServer::make_sphere_mesh(int p_lats,int p_lons,float p_radius) { - DVector<Vector3> vertices; - DVector<Vector3> normals; + PoolVector<Vector3> vertices; + PoolVector<Vector3> normals; for(int i = 1; i <= p_lats; i++) { double lat0 = Math_PI * (-0.5 + (double) (i - 1) / p_lats); @@ -289,7 +289,7 @@ RID VisualServer::make_sphere_mesh(int p_lats,int p_lons,float p_radius) { d[ARRAY_VERTEX]=vertices; d[ARRAY_NORMAL]=normals; - mesh_add_surface(mesh,PRIMITIVE_TRIANGLES,d); + mesh_add_surface_from_arrays(mesh,PRIMITIVE_TRIANGLES,d); return mesh; } @@ -311,7 +311,7 @@ RID VisualServer::material_2d_get(bool p_shaded, bool p_transparent, bool p_cut_ //not valid, make - material_2d[version]=fixed_material_create(); +/* material_2d[version]=fixed_material_create(); fixed_material_set_flag(material_2d[version],FIXED_MATERIAL_FLAG_USE_ALPHA,p_transparent); fixed_material_set_flag(material_2d[version],FIXED_MATERIAL_FLAG_USE_COLOR_ARRAY,true); fixed_material_set_flag(material_2d[version],FIXED_MATERIAL_FLAG_DISCARD_ALPHA,p_cut_alpha); @@ -319,7 +319,8 @@ RID VisualServer::material_2d_get(bool p_shaded, bool p_transparent, bool p_cut_ material_set_flag(material_2d[version],MATERIAL_FLAG_DOUBLE_SIDED,true); material_set_depth_draw_mode(material_2d[version],p_opaque_prepass?MATERIAL_DEPTH_DRAW_OPAQUE_PRE_PASS_ALPHA:MATERIAL_DEPTH_DRAW_OPAQUE_ONLY); fixed_material_set_texture(material_2d[version],FIXED_MATERIAL_PARAM_DIFFUSE,get_white_texture()); - //material cut alpha? + //material cut alpha?*/ + return material_2d[version]; } @@ -328,407 +329,1269 @@ RID VisualServer::get_white_texture() { if (white_texture.is_valid()) return white_texture; - DVector<uint8_t> wt; + PoolVector<uint8_t> wt; wt.resize(16*3); { - DVector<uint8_t>::Write w =wt.write(); + PoolVector<uint8_t>::Write w =wt.write(); for(int i=0;i<16*3;i++) w[i]=255; } - Image white(4,4,0,Image::FORMAT_RGB,wt); + Image white(4,4,0,Image::FORMAT_RGB8,wt); white_texture=texture_create(); - texture_allocate(white_texture,4,4,Image::FORMAT_RGB); + texture_allocate(white_texture,4,4,Image::FORMAT_RGB8); texture_set_data(white_texture,white); return white_texture; } -void VisualServer::_bind_methods() { +Error VisualServer::_surface_set_data(Array p_arrays,uint32_t p_format,uint32_t *p_offsets,uint32_t p_stride,PoolVector<uint8_t> &r_vertex_array,int p_vertex_array_len,PoolVector<uint8_t> &r_index_array,int p_index_array_len,Rect3 &r_aabb,Vector<Rect3> r_bone_aabb) { - ObjectTypeDB::bind_method(_MD("texture_create"),&VisualServer::texture_create); - ObjectTypeDB::bind_method(_MD("texture_create_from_image"),&VisualServer::texture_create_from_image,DEFVAL( TEXTURE_FLAGS_DEFAULT ) ); - //ObjectTypeDB::bind_method(_MD("texture_allocate"),&VisualServer::texture_allocate,DEFVAL( TEXTURE_FLAGS_DEFAULT ) ); - //ObjectTypeDB::bind_method(_MD("texture_set_data"),&VisualServer::texture_blit_rect,DEFVAL( CUBEMAP_LEFT ) ); - //ObjectTypeDB::bind_method(_MD("texture_get_rect"),&VisualServer::texture_get_rect ); - ObjectTypeDB::bind_method(_MD("texture_set_flags"),&VisualServer::texture_set_flags ); - ObjectTypeDB::bind_method(_MD("texture_get_flags"),&VisualServer::texture_get_flags ); - ObjectTypeDB::bind_method(_MD("texture_get_width"),&VisualServer::texture_get_width ); - ObjectTypeDB::bind_method(_MD("texture_get_height"),&VisualServer::texture_get_height ); - - ObjectTypeDB::bind_method(_MD("texture_set_shrink_all_x2_on_set_data","shrink"),&VisualServer::texture_set_shrink_all_x2_on_set_data ); - -#ifndef _3D_DISABLED - - - ObjectTypeDB::bind_method(_MD("shader_create","mode"),&VisualServer::shader_create,DEFVAL(SHADER_MATERIAL)); - ObjectTypeDB::bind_method(_MD("shader_set_mode","shader","mode"),&VisualServer::shader_set_mode); - - - - ObjectTypeDB::bind_method(_MD("material_create"),&VisualServer::material_create); - - ObjectTypeDB::bind_method(_MD("material_set_shader","shader"),&VisualServer::material_set_shader); - ObjectTypeDB::bind_method(_MD("material_get_shader"),&VisualServer::material_get_shader); - - ObjectTypeDB::bind_method(_MD("material_set_param"),&VisualServer::material_set_param); - ObjectTypeDB::bind_method(_MD("material_get_param"),&VisualServer::material_get_param); - ObjectTypeDB::bind_method(_MD("material_set_flag"),&VisualServer::material_set_flag); - ObjectTypeDB::bind_method(_MD("material_get_flag"),&VisualServer::material_get_flag); - ObjectTypeDB::bind_method(_MD("material_set_blend_mode"),&VisualServer::material_set_blend_mode); - ObjectTypeDB::bind_method(_MD("material_get_blend_mode"),&VisualServer::material_get_blend_mode); - ObjectTypeDB::bind_method(_MD("material_set_line_width"),&VisualServer::material_set_line_width); - ObjectTypeDB::bind_method(_MD("material_get_line_width"),&VisualServer::material_get_line_width); - - - ObjectTypeDB::bind_method(_MD("mesh_create"),&VisualServer::mesh_create); - ObjectTypeDB::bind_method(_MD("mesh_add_surface"),&VisualServer::mesh_add_surface, DEFVAL(NO_INDEX_ARRAY)); - ObjectTypeDB::bind_method(_MD("mesh_surface_set_material"),&VisualServer::mesh_surface_set_material,DEFVAL(false)); - ObjectTypeDB::bind_method(_MD("mesh_surface_get_material"),&VisualServer::mesh_surface_get_material); - - ObjectTypeDB::bind_method(_MD("mesh_surface_get_array_len"),&VisualServer::mesh_surface_get_array_len); - ObjectTypeDB::bind_method(_MD("mesh_surface_get_array_index_len"),&VisualServer::mesh_surface_get_array_index_len); - ObjectTypeDB::bind_method(_MD("mesh_surface_get_format"),&VisualServer::mesh_surface_get_format); - ObjectTypeDB::bind_method(_MD("mesh_surface_get_primitive_type"),&VisualServer::mesh_surface_get_primitive_type); - - ObjectTypeDB::bind_method(_MD("mesh_remove_surface"),&VisualServer::mesh_remove_surface); - ObjectTypeDB::bind_method(_MD("mesh_get_surface_count"),&VisualServer::mesh_get_surface_count); - - - ObjectTypeDB::bind_method(_MD("multimesh_create"),&VisualServer::multimesh_create); - ObjectTypeDB::bind_method(_MD("multimesh_set_mesh"),&VisualServer::multimesh_set_mesh); - ObjectTypeDB::bind_method(_MD("multimesh_set_aabb"),&VisualServer::multimesh_set_aabb); - ObjectTypeDB::bind_method(_MD("multimesh_instance_set_transform"),&VisualServer::multimesh_instance_set_transform); - ObjectTypeDB::bind_method(_MD("multimesh_instance_set_color"),&VisualServer::multimesh_instance_set_color); - ObjectTypeDB::bind_method(_MD("multimesh_get_mesh"),&VisualServer::multimesh_get_mesh); - ObjectTypeDB::bind_method(_MD("multimesh_get_aabb"),&VisualServer::multimesh_get_aabb); - ObjectTypeDB::bind_method(_MD("multimesh_instance_get_transform"),&VisualServer::multimesh_instance_get_transform); - ObjectTypeDB::bind_method(_MD("multimesh_instance_get_color"),&VisualServer::multimesh_instance_get_color); - - - - ObjectTypeDB::bind_method(_MD("particles_create"),&VisualServer::particles_create); - ObjectTypeDB::bind_method(_MD("particles_set_amount"),&VisualServer::particles_set_amount); - ObjectTypeDB::bind_method(_MD("particles_get_amount"),&VisualServer::particles_get_amount); - ObjectTypeDB::bind_method(_MD("particles_set_emitting"),&VisualServer::particles_set_emitting); - ObjectTypeDB::bind_method(_MD("particles_is_emitting"),&VisualServer::particles_is_emitting); - ObjectTypeDB::bind_method(_MD("particles_set_visibility_aabb"),&VisualServer::particles_set_visibility_aabb); - ObjectTypeDB::bind_method(_MD("particles_get_visibility_aabb"),&VisualServer::particles_get_visibility_aabb); - ObjectTypeDB::bind_method(_MD("particles_set_variable"),&VisualServer::particles_set_variable); - ObjectTypeDB::bind_method(_MD("particles_get_variable"),&VisualServer::particles_get_variable); - ObjectTypeDB::bind_method(_MD("particles_set_randomness"),&VisualServer::particles_set_randomness); - ObjectTypeDB::bind_method(_MD("particles_get_randomness"),&VisualServer::particles_get_randomness); - ObjectTypeDB::bind_method(_MD("particles_set_color_phases"),&VisualServer::particles_set_color_phases); - ObjectTypeDB::bind_method(_MD("particles_get_color_phases"),&VisualServer::particles_get_color_phases); - ObjectTypeDB::bind_method(_MD("particles_set_color_phase_pos"),&VisualServer::particles_set_color_phase_pos); - ObjectTypeDB::bind_method(_MD("particles_get_color_phase_pos"),&VisualServer::particles_get_color_phase_pos); - ObjectTypeDB::bind_method(_MD("particles_set_color_phase_color"),&VisualServer::particles_set_color_phase_color); - ObjectTypeDB::bind_method(_MD("particles_get_color_phase_color"),&VisualServer::particles_get_color_phase_color); - ObjectTypeDB::bind_method(_MD("particles_set_attractors"),&VisualServer::particles_set_attractors); - ObjectTypeDB::bind_method(_MD("particles_get_attractors"),&VisualServer::particles_get_attractors); - ObjectTypeDB::bind_method(_MD("particles_set_attractor_pos"),&VisualServer::particles_set_attractor_pos); - ObjectTypeDB::bind_method(_MD("particles_get_attractor_pos"),&VisualServer::particles_get_attractor_pos); - ObjectTypeDB::bind_method(_MD("particles_set_attractor_strength"),&VisualServer::particles_set_attractor_strength); - ObjectTypeDB::bind_method(_MD("particles_get_attractor_strength"),&VisualServer::particles_get_attractor_strength); - ObjectTypeDB::bind_method(_MD("particles_set_material"),&VisualServer::particles_set_material,DEFVAL(false)); - ObjectTypeDB::bind_method(_MD("particles_set_height_from_velocity"),&VisualServer::particles_set_height_from_velocity); - ObjectTypeDB::bind_method(_MD("particles_has_height_from_velocity"),&VisualServer::particles_has_height_from_velocity); - - - - ObjectTypeDB::bind_method(_MD("light_create"),&VisualServer::light_create); - ObjectTypeDB::bind_method(_MD("light_get_type"),&VisualServer::light_get_type); - ObjectTypeDB::bind_method(_MD("light_set_color"),&VisualServer::light_set_color); - ObjectTypeDB::bind_method(_MD("light_get_color"),&VisualServer::light_get_color); - ObjectTypeDB::bind_method(_MD("light_set_shadow"),&VisualServer::light_set_shadow); - ObjectTypeDB::bind_method(_MD("light_has_shadow"),&VisualServer::light_has_shadow); - ObjectTypeDB::bind_method(_MD("light_set_volumetric"),&VisualServer::light_set_volumetric); - ObjectTypeDB::bind_method(_MD("light_is_volumetric"),&VisualServer::light_is_volumetric); - ObjectTypeDB::bind_method(_MD("light_set_projector"),&VisualServer::light_set_projector); - ObjectTypeDB::bind_method(_MD("light_get_projector"),&VisualServer::light_get_projector); - ObjectTypeDB::bind_method(_MD("light_set_var"),&VisualServer::light_set_param); - ObjectTypeDB::bind_method(_MD("light_get_var"),&VisualServer::light_get_param); - - ObjectTypeDB::bind_method(_MD("skeleton_create"),&VisualServer::skeleton_create); - ObjectTypeDB::bind_method(_MD("skeleton_resize"),&VisualServer::skeleton_resize); - ObjectTypeDB::bind_method(_MD("skeleton_get_bone_count"),&VisualServer::skeleton_get_bone_count); - ObjectTypeDB::bind_method(_MD("skeleton_bone_set_transform"),&VisualServer::skeleton_bone_set_transform); - ObjectTypeDB::bind_method(_MD("skeleton_bone_get_transform"),&VisualServer::skeleton_bone_get_transform); - + PoolVector<uint8_t>::Write vw = r_vertex_array.write(); + PoolVector<uint8_t>::Write iw; + if (r_index_array.size()) { + print_line("elements: "+itos(r_index_array.size())); - ObjectTypeDB::bind_method(_MD("room_create"),&VisualServer::room_create); - ObjectTypeDB::bind_method(_MD("room_set_bounds"),&VisualServer::room_set_bounds); - ObjectTypeDB::bind_method(_MD("room_get_bounds"),&VisualServer::room_get_bounds); - - ObjectTypeDB::bind_method(_MD("portal_create"),&VisualServer::portal_create); - ObjectTypeDB::bind_method(_MD("portal_set_shape"),&VisualServer::portal_set_shape); - ObjectTypeDB::bind_method(_MD("portal_get_shape"),&VisualServer::portal_get_shape); - ObjectTypeDB::bind_method(_MD("portal_set_enabled"),&VisualServer::portal_set_enabled); - ObjectTypeDB::bind_method(_MD("portal_is_enabled"),&VisualServer::portal_is_enabled); - ObjectTypeDB::bind_method(_MD("portal_set_disable_distance"),&VisualServer::portal_set_disable_distance); - ObjectTypeDB::bind_method(_MD("portal_get_disable_distance"),&VisualServer::portal_get_disable_distance); - ObjectTypeDB::bind_method(_MD("portal_set_disabled_color"),&VisualServer::portal_set_disabled_color); - ObjectTypeDB::bind_method(_MD("portal_get_disabled_color"),&VisualServer::portal_get_disabled_color); - - - ObjectTypeDB::bind_method(_MD("camera_create"),&VisualServer::camera_create); - ObjectTypeDB::bind_method(_MD("camera_set_perspective"),&VisualServer::camera_set_perspective); - ObjectTypeDB::bind_method(_MD("camera_set_orthogonal"),&VisualServer::_camera_set_orthogonal); - ObjectTypeDB::bind_method(_MD("camera_set_transform"),&VisualServer::camera_set_transform); - - - ObjectTypeDB::bind_method(_MD("viewport_create"),&VisualServer::viewport_create); - ObjectTypeDB::bind_method(_MD("viewport_set_rect"),&VisualServer::_viewport_set_rect); - ObjectTypeDB::bind_method(_MD("viewport_get_rect"),&VisualServer::_viewport_get_rect); - ObjectTypeDB::bind_method(_MD("viewport_attach_camera"),&VisualServer::viewport_attach_camera,DEFVAL(RID())); - ObjectTypeDB::bind_method(_MD("viewport_get_attached_camera"),&VisualServer::viewport_get_attached_camera); - ObjectTypeDB::bind_method(_MD("viewport_get_scenario"),&VisualServer::viewport_get_scenario); - ObjectTypeDB::bind_method(_MD("viewport_attach_canvas"),&VisualServer::viewport_attach_canvas); - ObjectTypeDB::bind_method(_MD("viewport_remove_canvas"),&VisualServer::viewport_remove_canvas); - ObjectTypeDB::bind_method(_MD("viewport_set_global_canvas_transform"),&VisualServer::viewport_set_global_canvas_transform); - - ObjectTypeDB::bind_method(_MD("scenario_create"),&VisualServer::scenario_create); - ObjectTypeDB::bind_method(_MD("scenario_set_debug"),&VisualServer::scenario_set_debug); - - - ObjectTypeDB::bind_method(_MD("instance_create"),&VisualServer::instance_create,DEFVAL(RID())); - ObjectTypeDB::bind_method(_MD("instance_get_base"),&VisualServer::instance_get_base); - ObjectTypeDB::bind_method(_MD("instance_get_base_aabb"),&VisualServer::instance_get_base); - ObjectTypeDB::bind_method(_MD("instance_set_transform"),&VisualServer::instance_set_transform); - ObjectTypeDB::bind_method(_MD("instance_get_transform"),&VisualServer::instance_get_transform); - ObjectTypeDB::bind_method(_MD("instance_attach_object_instance_ID"),&VisualServer::instance_attach_object_instance_ID); - ObjectTypeDB::bind_method(_MD("instance_get_object_instance_ID"),&VisualServer::instance_get_object_instance_ID); - ObjectTypeDB::bind_method(_MD("instance_attach_skeleton"),&VisualServer::instance_attach_skeleton); - ObjectTypeDB::bind_method(_MD("instance_get_skeleton"),&VisualServer::instance_get_skeleton); - ObjectTypeDB::bind_method(_MD("instance_set_room"),&VisualServer::instance_set_room); - ObjectTypeDB::bind_method(_MD("instance_get_room"),&VisualServer::instance_get_room); - - ObjectTypeDB::bind_method(_MD("instance_set_exterior"),&VisualServer::instance_set_exterior); - ObjectTypeDB::bind_method(_MD("instance_is_exterior"),&VisualServer::instance_is_exterior); - - ObjectTypeDB::bind_method(_MD("instances_cull_aabb"),&VisualServer::instances_cull_aabb); - ObjectTypeDB::bind_method(_MD("instances_cull_ray"),&VisualServer::instances_cull_ray); - ObjectTypeDB::bind_method(_MD("instances_cull_convex"),&VisualServer::instances_cull_convex); - - - - ObjectTypeDB::bind_method(_MD("instance_geometry_override_material_param"),&VisualServer::instance_get_room); - ObjectTypeDB::bind_method(_MD("instance_geometry_get_material_param"),&VisualServer::instance_get_room); - - ObjectTypeDB::bind_method(_MD("get_test_cube"),&VisualServer::get_test_cube); - -#endif - ObjectTypeDB::bind_method(_MD("canvas_create"),&VisualServer::canvas_create); - ObjectTypeDB::bind_method(_MD("canvas_item_create"),&VisualServer::canvas_item_create); - ObjectTypeDB::bind_method(_MD("canvas_item_set_parent"),&VisualServer::canvas_item_set_parent); - ObjectTypeDB::bind_method(_MD("canvas_item_get_parent"),&VisualServer::canvas_item_get_parent); - ObjectTypeDB::bind_method(_MD("canvas_item_set_transform"),&VisualServer::canvas_item_set_transform); - ObjectTypeDB::bind_method(_MD("canvas_item_set_custom_rect"),&VisualServer::canvas_item_set_custom_rect); - ObjectTypeDB::bind_method(_MD("canvas_item_set_clip"),&VisualServer::canvas_item_set_clip); - ObjectTypeDB::bind_method(_MD("canvas_item_set_opacity"),&VisualServer::canvas_item_set_opacity); - ObjectTypeDB::bind_method(_MD("canvas_item_get_opacity"),&VisualServer::canvas_item_get_opacity); - ObjectTypeDB::bind_method(_MD("canvas_item_set_self_opacity"),&VisualServer::canvas_item_set_self_opacity); - ObjectTypeDB::bind_method(_MD("canvas_item_get_self_opacity"),&VisualServer::canvas_item_get_self_opacity); - ObjectTypeDB::bind_method(_MD("canvas_item_set_z"),&VisualServer::canvas_item_set_z); - - ObjectTypeDB::bind_method(_MD("canvas_item_add_line"),&VisualServer::canvas_item_add_line, DEFVAL(1.0), DEFVAL(false)); - ObjectTypeDB::bind_method(_MD("canvas_item_add_rect"),&VisualServer::canvas_item_add_rect); - ObjectTypeDB::bind_method(_MD("canvas_item_add_texture_rect"),&VisualServer::canvas_item_add_texture_rect, DEFVAL(Color(1,1,1)), DEFVAL(false)); - ObjectTypeDB::bind_method(_MD("canvas_item_add_texture_rect_region"),&VisualServer::canvas_item_add_texture_rect_region, DEFVAL(Color(1,1,1)), DEFVAL(false)); - - ObjectTypeDB::bind_method(_MD("canvas_item_add_style_box"),&VisualServer::_canvas_item_add_style_box, DEFVAL(Color(1,1,1))); -// ObjectTypeDB::bind_method(_MD("canvas_item_add_primitive"),&VisualServer::canvas_item_add_primitive,DEFVAL(Vector<Vector2>()),DEFVAL(RID())); - ObjectTypeDB::bind_method(_MD("canvas_item_add_circle"),&VisualServer::canvas_item_add_circle); - - ObjectTypeDB::bind_method(_MD("viewport_set_canvas_transform"),&VisualServer::viewport_set_canvas_transform); - - ObjectTypeDB::bind_method(_MD("canvas_item_clear"),&VisualServer::canvas_item_clear); - ObjectTypeDB::bind_method(_MD("canvas_item_raise"),&VisualServer::canvas_item_raise); - - - ObjectTypeDB::bind_method(_MD("cursor_set_rotation"),&VisualServer::cursor_set_rotation); - ObjectTypeDB::bind_method(_MD("cursor_set_texture"),&VisualServer::cursor_set_texture); - ObjectTypeDB::bind_method(_MD("cursor_set_visible"),&VisualServer::cursor_set_visible); - ObjectTypeDB::bind_method(_MD("cursor_set_pos"),&VisualServer::cursor_set_pos); - - ObjectTypeDB::bind_method(_MD("black_bars_set_margins","left","top","right","bottom"),&VisualServer::black_bars_set_margins); - ObjectTypeDB::bind_method(_MD("black_bars_set_images","left","top","right","bottom"),&VisualServer::black_bars_set_images); - - ObjectTypeDB::bind_method(_MD("make_sphere_mesh"),&VisualServer::make_sphere_mesh); - ObjectTypeDB::bind_method(_MD("mesh_add_surface_from_planes"),&VisualServer::mesh_add_surface_from_planes); - - ObjectTypeDB::bind_method(_MD("draw"),&VisualServer::draw); - ObjectTypeDB::bind_method(_MD("sync"),&VisualServer::sync); - ObjectTypeDB::bind_method(_MD("free_rid"),&VisualServer::free); - - ObjectTypeDB::bind_method(_MD("set_default_clear_color"),&VisualServer::set_default_clear_color); - - ObjectTypeDB::bind_method(_MD("get_render_info"),&VisualServer::get_render_info); - - BIND_CONSTANT( NO_INDEX_ARRAY ); - BIND_CONSTANT( CUSTOM_ARRAY_SIZE ); - BIND_CONSTANT( ARRAY_WEIGHTS_SIZE ); - BIND_CONSTANT( MAX_PARTICLE_COLOR_PHASES ); - BIND_CONSTANT( MAX_PARTICLE_ATTRACTORS ); - BIND_CONSTANT( MAX_CURSORS ); - - BIND_CONSTANT( TEXTURE_FLAG_MIPMAPS ); - BIND_CONSTANT( TEXTURE_FLAG_REPEAT ); - BIND_CONSTANT( TEXTURE_FLAG_FILTER ); - BIND_CONSTANT( TEXTURE_FLAG_CUBEMAP ); - BIND_CONSTANT( TEXTURE_FLAGS_DEFAULT ); - - BIND_CONSTANT( CUBEMAP_LEFT ); - BIND_CONSTANT( CUBEMAP_RIGHT ); - BIND_CONSTANT( CUBEMAP_BOTTOM ); - BIND_CONSTANT( CUBEMAP_TOP ); - BIND_CONSTANT( CUBEMAP_FRONT ); - BIND_CONSTANT( CUBEMAP_BACK ); - - BIND_CONSTANT( SHADER_MATERIAL ); ///< param 0: name - BIND_CONSTANT( SHADER_POST_PROCESS ); ///< param 0: name - - BIND_CONSTANT( MATERIAL_FLAG_VISIBLE ); - BIND_CONSTANT( MATERIAL_FLAG_DOUBLE_SIDED ); - BIND_CONSTANT( MATERIAL_FLAG_INVERT_FACES ); - BIND_CONSTANT( MATERIAL_FLAG_UNSHADED ); - BIND_CONSTANT( MATERIAL_FLAG_ONTOP ); - BIND_CONSTANT( MATERIAL_FLAG_MAX ); - - BIND_CONSTANT( MATERIAL_BLEND_MODE_MIX ); - BIND_CONSTANT( MATERIAL_BLEND_MODE_ADD ); - BIND_CONSTANT( MATERIAL_BLEND_MODE_SUB ); - BIND_CONSTANT( MATERIAL_BLEND_MODE_MUL ); - - BIND_CONSTANT( FIXED_MATERIAL_PARAM_DIFFUSE ); - BIND_CONSTANT( FIXED_MATERIAL_PARAM_DETAIL ); - BIND_CONSTANT( FIXED_MATERIAL_PARAM_SPECULAR ); - BIND_CONSTANT( FIXED_MATERIAL_PARAM_EMISSION ); - BIND_CONSTANT( FIXED_MATERIAL_PARAM_SPECULAR_EXP ); - BIND_CONSTANT( FIXED_MATERIAL_PARAM_GLOW ); - BIND_CONSTANT( FIXED_MATERIAL_PARAM_NORMAL ); - BIND_CONSTANT( FIXED_MATERIAL_PARAM_SHADE_PARAM ); - BIND_CONSTANT( FIXED_MATERIAL_PARAM_MAX ); - - - - BIND_CONSTANT( FIXED_MATERIAL_TEXCOORD_SPHERE ); - BIND_CONSTANT( FIXED_MATERIAL_TEXCOORD_UV ); - BIND_CONSTANT( FIXED_MATERIAL_TEXCOORD_UV_TRANSFORM ); - BIND_CONSTANT( FIXED_MATERIAL_TEXCOORD_UV2 ); - - - BIND_CONSTANT( ARRAY_VERTEX ); - BIND_CONSTANT( ARRAY_NORMAL ); - BIND_CONSTANT( ARRAY_TANGENT ); - BIND_CONSTANT( ARRAY_COLOR ); - BIND_CONSTANT( ARRAY_TEX_UV ); - BIND_CONSTANT( ARRAY_BONES ); - BIND_CONSTANT( ARRAY_WEIGHTS ); - BIND_CONSTANT( ARRAY_INDEX ); - BIND_CONSTANT( ARRAY_MAX ); - - BIND_CONSTANT( ARRAY_FORMAT_VERTEX ); - BIND_CONSTANT( ARRAY_FORMAT_NORMAL ); - BIND_CONSTANT( ARRAY_FORMAT_TANGENT ); - BIND_CONSTANT( ARRAY_FORMAT_COLOR ); - BIND_CONSTANT( ARRAY_FORMAT_TEX_UV ); - BIND_CONSTANT( ARRAY_FORMAT_BONES ); - BIND_CONSTANT( ARRAY_FORMAT_WEIGHTS ); - BIND_CONSTANT( ARRAY_FORMAT_INDEX ); - - BIND_CONSTANT( PRIMITIVE_POINTS ); - BIND_CONSTANT( PRIMITIVE_LINES ); - BIND_CONSTANT( PRIMITIVE_LINE_STRIP ); - BIND_CONSTANT( PRIMITIVE_LINE_LOOP ); - BIND_CONSTANT( PRIMITIVE_TRIANGLES ); - BIND_CONSTANT( PRIMITIVE_TRIANGLE_STRIP ); - BIND_CONSTANT( PRIMITIVE_TRIANGLE_FAN ); - BIND_CONSTANT( PRIMITIVE_MAX ); - - BIND_CONSTANT( PARTICLE_LIFETIME ); - BIND_CONSTANT( PARTICLE_SPREAD ); - BIND_CONSTANT( PARTICLE_GRAVITY ); - BIND_CONSTANT( PARTICLE_LINEAR_VELOCITY ); - BIND_CONSTANT( PARTICLE_ANGULAR_VELOCITY ); - BIND_CONSTANT( PARTICLE_LINEAR_ACCELERATION ); - BIND_CONSTANT( PARTICLE_RADIAL_ACCELERATION ); - BIND_CONSTANT( PARTICLE_TANGENTIAL_ACCELERATION ); - BIND_CONSTANT( PARTICLE_INITIAL_SIZE ); - BIND_CONSTANT( PARTICLE_FINAL_SIZE ); - BIND_CONSTANT( PARTICLE_INITIAL_ANGLE ); - BIND_CONSTANT( PARTICLE_HEIGHT ); - BIND_CONSTANT( PARTICLE_HEIGHT_SPEED_SCALE ); - BIND_CONSTANT( PARTICLE_VAR_MAX ); - - BIND_CONSTANT( LIGHT_DIRECTIONAL ); - BIND_CONSTANT( LIGHT_OMNI ); - BIND_CONSTANT( LIGHT_SPOT ); - - - BIND_CONSTANT( LIGHT_COLOR_DIFFUSE ); - BIND_CONSTANT( LIGHT_COLOR_SPECULAR ); - - BIND_CONSTANT( LIGHT_PARAM_SPOT_ATTENUATION ); - BIND_CONSTANT( LIGHT_PARAM_SPOT_ANGLE ); - BIND_CONSTANT( LIGHT_PARAM_RADIUS ); - BIND_CONSTANT( LIGHT_PARAM_ENERGY ); - BIND_CONSTANT( LIGHT_PARAM_ATTENUATION ); - BIND_CONSTANT( LIGHT_PARAM_MAX ); - - BIND_CONSTANT( SCENARIO_DEBUG_DISABLED ); - BIND_CONSTANT( SCENARIO_DEBUG_WIREFRAME ); - BIND_CONSTANT( SCENARIO_DEBUG_OVERDRAW ); - - BIND_CONSTANT( INSTANCE_MESH ); - BIND_CONSTANT( INSTANCE_MULTIMESH ); - - BIND_CONSTANT( INSTANCE_PARTICLES ); - BIND_CONSTANT( INSTANCE_LIGHT ); - BIND_CONSTANT( INSTANCE_ROOM ); - BIND_CONSTANT( INSTANCE_PORTAL ); - BIND_CONSTANT( INSTANCE_GEOMETRY_MASK ); - - - BIND_CONSTANT( INFO_OBJECTS_IN_FRAME ); - BIND_CONSTANT( INFO_VERTICES_IN_FRAME ); - BIND_CONSTANT( INFO_MATERIAL_CHANGES_IN_FRAME ); - BIND_CONSTANT( INFO_SHADER_CHANGES_IN_FRAME ); - BIND_CONSTANT( INFO_SURFACE_CHANGES_IN_FRAME ); - BIND_CONSTANT( INFO_DRAW_CALLS_IN_FRAME ); - BIND_CONSTANT( INFO_USAGE_VIDEO_MEM_TOTAL ); - BIND_CONSTANT( INFO_VIDEO_MEM_USED ); - BIND_CONSTANT( INFO_TEXTURE_MEM_USED ); - BIND_CONSTANT( INFO_VERTEX_MEM_USED ); + iw=r_index_array.write(); + + } + + int max_bone=0; + + + for(int ai=0;ai<VS::ARRAY_MAX;ai++) { + + if (!(p_format&(1<<ai))) // no array + continue; + + + switch(ai) { + + case VS::ARRAY_VERTEX: { + + if (p_format& VS::ARRAY_FLAG_USE_2D_VERTICES) { + + PoolVector<Vector2> array = p_arrays[ai]; + ERR_FAIL_COND_V( array.size() != p_vertex_array_len, ERR_INVALID_PARAMETER ); + + + PoolVector<Vector2>::Read read = array.read(); + const Vector2* src=read.ptr(); + + // setting vertices means regenerating the AABB + Rect2 aabb; + + + if (p_format&ARRAY_COMPRESS_VERTEX) { + + for (int i=0;i<p_vertex_array_len;i++) { + + + uint16_t vector[2]={ Math::make_half_float(src[i].x), Math::make_half_float(src[i].y) }; + + copymem(&vw[p_offsets[ai]+i*p_stride], vector, sizeof(uint16_t)*2); + + if (i==0) { + + aabb=Rect2(src[i],Vector2()); + } else { + + aabb.expand_to( src[i] ); + } + } + + + } else { + for (int i=0;i<p_vertex_array_len;i++) { + + + float vector[2]={ src[i].x, src[i].y }; + + copymem(&vw[p_offsets[ai]+i*p_stride], vector, sizeof(float)*2); + + if (i==0) { + + aabb=Rect2(src[i],Vector2()); + } else { + + aabb.expand_to( src[i] ); + } + } + } + + r_aabb=Rect3(Vector3(aabb.pos.x,aabb.pos.y,0),Vector3(aabb.size.x,aabb.size.y,0)); + + + } else { + PoolVector<Vector3> array = p_arrays[ai]; + ERR_FAIL_COND_V( array.size() != p_vertex_array_len, ERR_INVALID_PARAMETER ); + + + PoolVector<Vector3>::Read read = array.read(); + const Vector3* src=read.ptr(); + + // setting vertices means regenerating the AABB + Rect3 aabb; + + + if (p_format&ARRAY_COMPRESS_VERTEX) { + + for (int i=0;i<p_vertex_array_len;i++) { + + + uint16_t vector[4]={ Math::make_half_float(src[i].x), Math::make_half_float(src[i].y), Math::make_half_float(src[i].z), Math::make_half_float(1.0) }; + + copymem(&vw[p_offsets[ai]+i*p_stride], vector, sizeof(uint16_t)*4); + + if (i==0) { + + aabb=Rect3(src[i],Vector3()); + } else { + + aabb.expand_to( src[i] ); + } + } + + + } else { + for (int i=0;i<p_vertex_array_len;i++) { + + + float vector[3]={ src[i].x, src[i].y, src[i].z }; + + copymem(&vw[p_offsets[ai]+i*p_stride], vector, sizeof(float)*3); + + if (i==0) { + + aabb=Rect3(src[i],Vector3()); + } else { + + aabb.expand_to( src[i] ); + } + } + } + + r_aabb=aabb; + + } + + + } break; + case VS::ARRAY_NORMAL: { + + ERR_FAIL_COND_V( p_arrays[ai].get_type() != Variant::POOL_VECTOR3_ARRAY, ERR_INVALID_PARAMETER ); + + PoolVector<Vector3> array = p_arrays[ai]; + ERR_FAIL_COND_V( array.size() != p_vertex_array_len, ERR_INVALID_PARAMETER ); + + + PoolVector<Vector3>::Read read = array.read(); + const Vector3* src=read.ptr(); + + // setting vertices means regenerating the AABB + + if (p_format&ARRAY_COMPRESS_NORMAL) { + + for (int i=0;i<p_vertex_array_len;i++) { + + uint8_t vector[4]={ + CLAMP(src[i].x*127,-128,127), + CLAMP(src[i].y*127,-128,127), + CLAMP(src[i].z*127,-128,127), + 0, + }; + + copymem(&vw[p_offsets[ai]+i*p_stride], vector, 4); + + } + + } else { + for (int i=0;i<p_vertex_array_len;i++) { + + + float vector[3]={ src[i].x, src[i].y, src[i].z }; + copymem(&vw[p_offsets[ai]+i*p_stride], vector, 3*4); + + } + } + + } break; + + case VS::ARRAY_TANGENT: { + + ERR_FAIL_COND_V( p_arrays[ai].get_type() != Variant::POOL_REAL_ARRAY, ERR_INVALID_PARAMETER ); + + PoolVector<real_t> array = p_arrays[ai]; + + ERR_FAIL_COND_V( array.size() != p_vertex_array_len*4, ERR_INVALID_PARAMETER ); + + + PoolVector<real_t>::Read read = array.read(); + const real_t* src = read.ptr(); + + if (p_format&ARRAY_COMPRESS_TANGENT) { + + for (int i=0;i<p_vertex_array_len;i++) { + + uint8_t xyzw[4]={ + CLAMP(src[i*4+0]*127,-128,127), + CLAMP(src[i*4+1]*127,-128,127), + CLAMP(src[i*4+2]*127,-128,127), + CLAMP(src[i*4+3]*127,-128,127) + }; + + copymem(&vw[p_offsets[ai]+i*p_stride], xyzw, 4); + + } + + + } else { + for (int i=0;i<p_vertex_array_len;i++) { + + float xyzw[4]={ + src[i*4+0], + src[i*4+1], + src[i*4+2], + src[i*4+3] + }; + + copymem(&vw[p_offsets[ai]+i*p_stride], xyzw, 4*4); + + } + } + + } break; + case VS::ARRAY_COLOR: { + + ERR_FAIL_COND_V( p_arrays[ai].get_type() != Variant::POOL_COLOR_ARRAY, ERR_INVALID_PARAMETER ); + + + PoolVector<Color> array = p_arrays[ai]; + + ERR_FAIL_COND_V( array.size() != p_vertex_array_len, ERR_INVALID_PARAMETER ); + + + PoolVector<Color>::Read read = array.read(); + const Color* src = read.ptr(); + if (p_format&ARRAY_COMPRESS_COLOR) { + for (int i=0;i<p_vertex_array_len;i++) { + + + uint8_t colors[4]; + + for(int j=0;j<4;j++) { + + colors[j]=CLAMP( int((src[i][j])*255.0), 0,255 ); + } + + copymem(&vw[p_offsets[ai]+i*p_stride], colors, 4); + + } + } else { + + for (int i=0;i<p_vertex_array_len;i++) { + + + copymem(&vw[p_offsets[ai]+i*p_stride], &src[i], 4*4); + } + + } + + + } break; + case VS::ARRAY_TEX_UV: { + + ERR_FAIL_COND_V( p_arrays[ai].get_type() != Variant::POOL_VECTOR3_ARRAY && p_arrays[ai].get_type() != Variant::POOL_VECTOR2_ARRAY, ERR_INVALID_PARAMETER ); + + PoolVector<Vector2> array = p_arrays[ai]; + + ERR_FAIL_COND_V( array.size() != p_vertex_array_len , ERR_INVALID_PARAMETER); + + PoolVector<Vector2>::Read read = array.read(); + + const Vector2 * src=read.ptr(); + + + + if (p_format&ARRAY_COMPRESS_TEX_UV) { + + for (int i=0;i<p_vertex_array_len;i++) { + + uint16_t uv[2]={ Math::make_half_float(src[i].x) , Math::make_half_float(src[i].y) }; + copymem(&vw[p_offsets[ai]+i*p_stride], uv, 2*2); + } + + } else { + for (int i=0;i<p_vertex_array_len;i++) { + + float uv[2]={ src[i].x , src[i].y }; + + copymem(&vw[p_offsets[ai]+i*p_stride], uv, 2*4); + + } + } + + + } break; + + case VS::ARRAY_TEX_UV2: { + + + ERR_FAIL_COND_V( p_arrays[ai].get_type() != Variant::POOL_VECTOR3_ARRAY && p_arrays[ai].get_type() != Variant::POOL_VECTOR2_ARRAY, ERR_INVALID_PARAMETER ); + + PoolVector<Vector2> array = p_arrays[ai]; + + ERR_FAIL_COND_V( array.size() != p_vertex_array_len , ERR_INVALID_PARAMETER); + + PoolVector<Vector2>::Read read = array.read(); + + const Vector2 * src=read.ptr(); + + + + if (p_format&ARRAY_COMPRESS_TEX_UV2) { + + for (int i=0;i<p_vertex_array_len;i++) { + + uint16_t uv[2]={ Math::make_half_float(src[i].x) , Math::make_half_float(src[i].y) }; + copymem(&vw[p_offsets[ai]+i*p_stride], uv, 2*2); + } + + } else { + for (int i=0;i<p_vertex_array_len;i++) { + + float uv[2]={ src[i].x , src[i].y }; + + copymem(&vw[p_offsets[ai]+i*p_stride], uv, 2*4); + + } + } + } break; + case VS::ARRAY_WEIGHTS: { + + ERR_FAIL_COND_V( p_arrays[ai].get_type() != Variant::POOL_REAL_ARRAY, ERR_INVALID_PARAMETER ); + + PoolVector<real_t> array = p_arrays[ai]; + + ERR_FAIL_COND_V( array.size() != p_vertex_array_len*VS::ARRAY_WEIGHTS_SIZE, ERR_INVALID_PARAMETER ); + + + PoolVector<real_t>::Read read = array.read(); + + const real_t * src = read.ptr(); + + if (p_format&ARRAY_COMPRESS_WEIGHTS) { + + for (int i=0;i<p_vertex_array_len;i++) { + + uint16_t data[VS::ARRAY_WEIGHTS_SIZE]; + for (int j=0;j<VS::ARRAY_WEIGHTS_SIZE;j++) { + data[j]=CLAMP(src[i*VS::ARRAY_WEIGHTS_SIZE+j]*65535,0,65535); + } + + copymem(&vw[p_offsets[ai]+i*p_stride], data, 2*4); + } + } else { + + for (int i=0;i<p_vertex_array_len;i++) { + + float data[VS::ARRAY_WEIGHTS_SIZE]; + for (int j=0;j<VS::ARRAY_WEIGHTS_SIZE;j++) { + data[j]=src[i*VS::ARRAY_WEIGHTS_SIZE+j]; + } + + copymem(&vw[p_offsets[ai]+i*p_stride], data, 4*4); + + + } + } + + } break; + case VS::ARRAY_BONES: { + + ERR_FAIL_COND_V( p_arrays[ai].get_type() != Variant::POOL_INT_ARRAY && p_arrays[ai].get_type() != Variant::POOL_REAL_ARRAY, ERR_INVALID_PARAMETER ); + + PoolVector<int> array = p_arrays[ai]; + + ERR_FAIL_COND_V( array.size() != p_vertex_array_len*VS::ARRAY_WEIGHTS_SIZE, ERR_INVALID_PARAMETER ); + + + PoolVector<int>::Read read = array.read(); + + const int * src = read.ptr(); + + + if (!(p_format&ARRAY_FLAG_USE_16_BIT_BONES)) { + + for (int i=0;i<p_vertex_array_len;i++) { + + uint8_t data[VS::ARRAY_WEIGHTS_SIZE]; + for (int j=0;j<VS::ARRAY_WEIGHTS_SIZE;j++) { + data[j]=CLAMP(src[i*VS::ARRAY_WEIGHTS_SIZE+j],0,255); + max_bone=MAX(data[j],max_bone); + + } + + copymem(&vw[p_offsets[ai]+i*p_stride], data, 4); + + + } + + } else { + for (int i=0;i<p_vertex_array_len;i++) { + + uint16_t data[VS::ARRAY_WEIGHTS_SIZE]; + for (int j=0;j<VS::ARRAY_WEIGHTS_SIZE;j++) { + data[j]=src[i*VS::ARRAY_WEIGHTS_SIZE+j]; + max_bone=MAX(data[j],max_bone); + + } + + copymem(&vw[p_offsets[ai]+i*p_stride], data, 2*4); + + + } + } + + + } break; + case VS::ARRAY_INDEX: { + + + ERR_FAIL_COND_V( p_index_array_len<=0, ERR_INVALID_DATA ); + ERR_FAIL_COND_V( p_arrays[ai].get_type() != Variant::POOL_INT_ARRAY, ERR_INVALID_PARAMETER ); + + PoolVector<int> indices = p_arrays[ai]; + ERR_FAIL_COND_V( indices.size() == 0, ERR_INVALID_PARAMETER ); + ERR_FAIL_COND_V( indices.size() != p_index_array_len, ERR_INVALID_PARAMETER ); + + /* determine wether using 16 or 32 bits indices */ + + PoolVector<int>::Read read = indices.read(); + const int *src=read.ptr(); + + for (int i=0;i<p_index_array_len;i++) { + + + if (p_vertex_array_len<(1<<16)) { + uint16_t v=src[i]; + + copymem(&iw[i*2], &v, 2); + } else { + uint32_t v=src[i]; + + copymem(&iw[i*4], &v, 4); + } + } + } break; + default: { + ERR_FAIL_V( ERR_INVALID_DATA ); + } + } + } + + + if (p_format&VS::ARRAY_FORMAT_BONES) { + //create AABBs for each detected bone + int total_bones = max_bone+1; + + bool first = r_bone_aabb.size()==0; + + r_bone_aabb.resize(total_bones); + + if (first) { + for(int i=0;i<total_bones;i++) { + r_bone_aabb[i].size==Vector3(-1,-1,-1); //negative means unused + } + } + + PoolVector<Vector3> vertices = p_arrays[VS::ARRAY_VERTEX]; + PoolVector<int> bones = p_arrays[VS::ARRAY_BONES]; + PoolVector<float> weights = p_arrays[VS::ARRAY_WEIGHTS]; + + bool any_valid=false; + + if (vertices.size() && bones.size()==vertices.size()*4 && weights.size()==bones.size()) { + + int vs = vertices.size(); + PoolVector<Vector3>::Read rv =vertices.read(); + PoolVector<int>::Read rb=bones.read(); + PoolVector<float>::Read rw=weights.read(); + + Rect3 *bptr = r_bone_aabb.ptr(); + + for(int i=0;i<vs;i++) { + + Vector3 v = rv[i]; + for(int j=0;j<4;j++) { + + int idx = rb[i*4+j]; + float w = rw[i*4+j]; + if (w==0) + continue;//break; + ERR_FAIL_INDEX_V(idx,total_bones,ERR_INVALID_DATA); + + if (bptr->size.x<0) { + //first + bptr[idx]=Rect3(); + bptr[idx].pos=v; + any_valid=true; + } else { + bptr[idx].expand_to(v); + } + } + } + } + + if (!any_valid && first) { + + r_bone_aabb.clear(); + } + } + return OK; } -void VisualServer::_canvas_item_add_style_box(RID p_item, const Rect2& p_rect, const Rect2& p_source, RID p_texture,const Vector<float>& p_margins, const Color& p_modulate) { - ERR_FAIL_COND(p_margins.size()!=4); - canvas_item_add_style_box(p_item,p_rect,p_source,p_texture,Vector2(p_margins[0],p_margins[1]),Vector2(p_margins[2],p_margins[3]),true,p_modulate); +void VisualServer::mesh_add_surface_from_arrays(RID p_mesh,PrimitiveType p_primitive,const Array& p_arrays,const Array& p_blend_shapes,uint32_t p_compress_format) { + + ERR_FAIL_INDEX( p_primitive, VS::PRIMITIVE_MAX ); + ERR_FAIL_COND(p_arrays.size()!=VS::ARRAY_MAX); + + uint32_t format=0; + + // validation + int index_array_len=0; + int array_len=0; + + for(int i=0;i<p_arrays.size();i++) { + + if (p_arrays[i].get_type()==Variant::NIL) + continue; + + format|=(1<<i); + + if (i==VS::ARRAY_VERTEX) { + + Variant var = p_arrays[i]; + switch(var.get_type()) { + case Variant::POOL_VECTOR2_ARRAY: { + PoolVector<Vector2> v2 = var; + array_len=v2.size(); + } break; + case Variant::POOL_VECTOR3_ARRAY: { + PoolVector<Vector3> v3 = var; + array_len=v3.size(); + } break; + default: { + Array v = var; + array_len=v.size(); + } break; + } + + array_len=PoolVector3Array(p_arrays[i]).size(); + ERR_FAIL_COND(array_len==0); + } else if (i==VS::ARRAY_INDEX) { + + index_array_len=PoolIntArray(p_arrays[i]).size(); + } + } + + ERR_FAIL_COND((format&VS::ARRAY_FORMAT_VERTEX)==0); // mandatory + + + if (p_blend_shapes.size()) { + //validate format for morphs + for(int i=0;i<p_blend_shapes.size();i++) { + + uint32_t bsformat=0; + Array arr = p_blend_shapes[i]; + for(int j=0;j<arr.size();j++) { + + + if (arr[j].get_type()!=Variant::NIL) + bsformat|=(1<<j); + } + + ERR_FAIL_COND( (bsformat)!=(format&(VS::ARRAY_FORMAT_INDEX-1))); + } + } + + uint32_t offsets[VS::ARRAY_MAX]; + + int total_elem_size=0; + + for (int i=0;i<VS::ARRAY_MAX;i++) { + + + offsets[i]=0; //reset + + if (!(format&(1<<i))) // no array + continue; + + + int elem_size=0; + + switch(i) { + + case VS::ARRAY_VERTEX: { + + Variant arr = p_arrays[0]; + if (arr.get_type()==Variant::POOL_VECTOR2_ARRAY) { + elem_size=2; + p_compress_format|=ARRAY_FLAG_USE_2D_VERTICES; + } else if (arr.get_type()==Variant::POOL_VECTOR3_ARRAY) { + p_compress_format&=~ARRAY_FLAG_USE_2D_VERTICES; + elem_size=3; + } else { + elem_size=(p_compress_format&ARRAY_FLAG_USE_2D_VERTICES)?2:3; + } + + if (p_compress_format&ARRAY_COMPRESS_VERTEX) { + elem_size*=sizeof(int16_t); + } else { + elem_size*=sizeof(float); + } + + if (elem_size==6) { + //had to pad + elem_size=8; + } + + } break; + case VS::ARRAY_NORMAL: { + + if (p_compress_format&ARRAY_COMPRESS_NORMAL) { + elem_size=sizeof(uint32_t); + } else { + elem_size=sizeof(float)*3; + } + + } break; + + case VS::ARRAY_TANGENT: { + if (p_compress_format&ARRAY_COMPRESS_TANGENT) { + elem_size=sizeof(uint32_t); + } else { + elem_size=sizeof(float)*4; + } + + } break; + case VS::ARRAY_COLOR: { + + if (p_compress_format&ARRAY_COMPRESS_COLOR) { + elem_size=sizeof(uint32_t); + } else { + elem_size=sizeof(float)*4; + } + } break; + case VS::ARRAY_TEX_UV: { + if (p_compress_format&ARRAY_COMPRESS_TEX_UV) { + elem_size=sizeof(uint32_t); + } else { + elem_size=sizeof(float)*2; + } + + } break; + + case VS::ARRAY_TEX_UV2: { + if (p_compress_format&ARRAY_COMPRESS_TEX_UV2) { + elem_size=sizeof(uint32_t); + } else { + elem_size=sizeof(float)*2; + } + + } break; + case VS::ARRAY_WEIGHTS: { + + if (p_compress_format&ARRAY_COMPRESS_WEIGHTS) { + elem_size=sizeof(uint16_t)*4; + } else { + elem_size=sizeof(float)*4; + } + + } break; + case VS::ARRAY_BONES: { + + PoolVector<int> bones = p_arrays[VS::ARRAY_BONES]; + int max_bone=0; + + { + int bc = bones.size(); + PoolVector<int>::Read r=bones.read(); + for(int j=0;j<bc;j++) { + max_bone=MAX(r[j],max_bone); + } + } + + if (max_bone > 255) { + p_compress_format|=ARRAY_FLAG_USE_16_BIT_BONES; + elem_size=sizeof(uint16_t)*4; + } else { + p_compress_format&=~ARRAY_FLAG_USE_16_BIT_BONES; + elem_size=sizeof(uint32_t); + } + + + } break; + case VS::ARRAY_INDEX: { + + if (index_array_len<=0) { + ERR_PRINT("index_array_len==NO_INDEX_ARRAY"); + break; + } + /* determine wether using 16 or 32 bits indices */ + if (array_len>=(1<<16)) { + + elem_size=4; + + } else { + elem_size=2; + } + offsets[i]=elem_size; + continue; + } break; + default: { + ERR_FAIL( ); + } + } + + offsets[i]=total_elem_size; + total_elem_size+=elem_size; + + + } + + uint32_t mask = (1<<ARRAY_MAX)-1; + format|=(~mask)&p_compress_format; //make the full format + + + int array_size = total_elem_size * array_len; + + PoolVector<uint8_t> vertex_array; + vertex_array.resize(array_size); + + int index_array_size = offsets[VS::ARRAY_INDEX]*index_array_len; + + PoolVector<uint8_t> index_array; + index_array.resize(index_array_size); + + Rect3 aabb; + Vector<Rect3> bone_aabb; + + Error err = _surface_set_data(p_arrays,format,offsets,total_elem_size,vertex_array,array_len,index_array,index_array_len,aabb,bone_aabb); + + if (err) { + ERR_EXPLAIN("Invalid array format for surface"); + ERR_FAIL_COND(err!=OK); + } + + Vector<PoolVector<uint8_t> > blend_shape_data; + + for(int i=0;i<p_blend_shapes.size();i++) { + + PoolVector<uint8_t> vertex_array_shape; + vertex_array_shape.resize(array_size); + PoolVector<uint8_t> noindex; + + Rect3 laabb; + Error err = _surface_set_data(p_blend_shapes[i],format&~ARRAY_FORMAT_INDEX,offsets,total_elem_size,vertex_array_shape,array_len,noindex,0,laabb,bone_aabb); + aabb.merge_with(laabb); + if (err) { + ERR_EXPLAIN("Invalid blend shape array format for surface"); + ERR_FAIL_COND(err!=OK); + } + + blend_shape_data.push_back(vertex_array_shape); + } + + mesh_add_surface(p_mesh,format,p_primitive,vertex_array,array_len,index_array,index_array_len,aabb,blend_shape_data,bone_aabb); + } -void VisualServer::_camera_set_orthogonal(RID p_camera,float p_size,float p_z_near,float p_z_far) { +Array VisualServer::_get_array_from_surface(uint32_t p_format,PoolVector<uint8_t> p_vertex_data,int p_vertex_len,PoolVector<uint8_t> p_index_data,int p_index_len) const { + + + uint32_t offsets[ARRAY_MAX]; + + int total_elem_size=0; + + for (int i=0;i<VS::ARRAY_MAX;i++) { + + + offsets[i]=0; //reset + + if (!(p_format&(1<<i))) // no array + continue; + + + int elem_size=0; + + switch(i) { + + case VS::ARRAY_VERTEX: { + + + if (p_format&ARRAY_FLAG_USE_2D_VERTICES) { + elem_size=2; + } else { + elem_size=3; + } + + if (p_format&ARRAY_COMPRESS_VERTEX) { + elem_size*=sizeof(int16_t); + } else { + elem_size*=sizeof(float); + } + + if (elem_size==6) { + elem_size=8; + } + + } break; + case VS::ARRAY_NORMAL: { + + if (p_format&ARRAY_COMPRESS_NORMAL) { + elem_size=sizeof(uint32_t); + } else { + elem_size=sizeof(float)*3; + } + + } break; + + case VS::ARRAY_TANGENT: { + if (p_format&ARRAY_COMPRESS_TANGENT) { + elem_size=sizeof(uint32_t); + } else { + elem_size=sizeof(float)*4; + } + + } break; + case VS::ARRAY_COLOR: { + + if (p_format&ARRAY_COMPRESS_COLOR) { + elem_size=sizeof(uint32_t); + } else { + elem_size=sizeof(float)*4; + } + } break; + case VS::ARRAY_TEX_UV: { + if (p_format&ARRAY_COMPRESS_TEX_UV) { + elem_size=sizeof(uint32_t); + } else { + elem_size=sizeof(float)*2; + } + + } break; + + case VS::ARRAY_TEX_UV2: { + if (p_format&ARRAY_COMPRESS_TEX_UV2) { + elem_size=sizeof(uint32_t); + } else { + elem_size=sizeof(float)*2; + } + + } break; + case VS::ARRAY_WEIGHTS: { + + if (p_format&ARRAY_COMPRESS_WEIGHTS) { + elem_size=sizeof(uint16_t)*4; + } else { + elem_size=sizeof(float)*4; + } + + } break; + case VS::ARRAY_BONES: { + + if (p_format&ARRAY_FLAG_USE_16_BIT_BONES) { + elem_size=sizeof(uint16_t)*4; + } else { + elem_size=sizeof(uint32_t); + } + + } break; + case VS::ARRAY_INDEX: { + + if (p_index_len<=0) { + ERR_PRINT("index_array_len==NO_INDEX_ARRAY"); + break; + } + /* determine wether using 16 or 32 bits indices */ + if (p_vertex_len>=(1<<16)) { + + elem_size=4; + + } else { + elem_size=2; + } + offsets[i]=elem_size; + continue; + } break; + default: { + ERR_FAIL_V( Array() ); + } + } + + offsets[i]=total_elem_size; + total_elem_size+=elem_size; + + + } + + Array ret; + ret.resize(VS::ARRAY_MAX); + + PoolVector<uint8_t>::Read r = p_vertex_data.read(); + + for(int i=0;i<VS::ARRAY_MAX;i++) { + + if (!(p_format&(1<<i))) + continue; + + + switch(i) { + + case VS::ARRAY_VERTEX: { + + + if (p_format&ARRAY_FLAG_USE_2D_VERTICES) { + + PoolVector<Vector2> arr_2d; + arr_2d.resize(p_vertex_len); + + if (p_format&ARRAY_COMPRESS_VERTEX) { + + PoolVector<Vector2>::Write w = arr_2d.write(); + + for(int j=0;j<p_vertex_len;j++) { + + const uint16_t *v = (const uint16_t*)&r[j*total_elem_size+offsets[i]]; + w[j]=Vector2(Math::halfptr_to_float(&v[0]),Math::halfptr_to_float(&v[1])); + } + } else { + + PoolVector<Vector2>::Write w = arr_2d.write(); + + for(int j=0;j<p_vertex_len;j++) { + + const float *v = (const float*)&r[j*total_elem_size+offsets[i]]; + w[j]=Vector2(v[0],v[1]); + } + } + + ret[i]=arr_2d; + } else { + + PoolVector<Vector3> arr_3d; + arr_3d.resize(p_vertex_len); + + if (p_format&ARRAY_COMPRESS_VERTEX) { + + PoolVector<Vector3>::Write w = arr_3d.write(); + + for(int j=0;j<p_vertex_len;j++) { + + const uint16_t *v = (const uint16_t*)&r[j*total_elem_size+offsets[i]]; + w[j]=Vector3(Math::halfptr_to_float(&v[0]),Math::halfptr_to_float(&v[1]),Math::halfptr_to_float(&v[2])); + } + } else { + + PoolVector<Vector3>::Write w = arr_3d.write(); + + for(int j=0;j<p_vertex_len;j++) { + + const float *v = (const float*)&r[j*total_elem_size+offsets[i]]; + w[j]=Vector3(v[0],v[1],v[2]); + } + } + + ret[i]=arr_3d; + } + + + } break; + case VS::ARRAY_NORMAL: { + PoolVector<Vector3> arr; + arr.resize(p_vertex_len); + + if (p_format&ARRAY_COMPRESS_NORMAL) { + + PoolVector<Vector3>::Write w = arr.write(); + + for(int j=0;j<p_vertex_len;j++) { + + const uint8_t *v = (const uint8_t*)&r[j*total_elem_size+offsets[i]]; + w[j]=Vector3( float(v[0]/255.0)*2.0-1.0, float(v[1]/255.0)*2.0-1.0, float(v[2]/255.0)*2.0-1.0 ); + } + } else { + PoolVector<Vector3>::Write w = arr.write(); + + for(int j=0;j<p_vertex_len;j++) { + + const float *v = (const float*)&r[j*total_elem_size+offsets[i]]; + w[j]=Vector3(v[0],v[1],v[2]); + } + } + + ret[i]=arr; + + } break; + + case VS::ARRAY_TANGENT: { + PoolVector<float> arr; + arr.resize(p_vertex_len*4); + if (p_format&ARRAY_COMPRESS_TANGENT) { + PoolVector<float>::Write w = arr.write(); + + for(int j=0;j<p_vertex_len;j++) { + + const uint8_t *v = (const uint8_t*)&r[j*total_elem_size+offsets[i]]; + for(int k=0;k<4;k++) { + w[j*4+k]=float(v[k]/255.0)*2.0-1.0; + } + } + } else { + + PoolVector<float>::Write w = arr.write(); + + for(int j=0;j<p_vertex_len;j++) { + const float *v = (const float*)&r[j*total_elem_size+offsets[i]]; + for(int k=0;k<4;k++) { + w[j*4+k]=v[k]; + } + } + + } + + ret[i]=arr; + + } break; + case VS::ARRAY_COLOR: { + + PoolVector<Color> arr; + arr.resize(p_vertex_len); + + if (p_format&ARRAY_COMPRESS_COLOR) { + + PoolVector<Color>::Write w = arr.write(); + + for(int j=0;j<p_vertex_len;j++) { + + const uint8_t *v = (const uint8_t*)&r[j*total_elem_size+offsets[i]]; + w[j]=Color( float(v[0]/255.0)*2.0-1.0, float(v[1]/255.0)*2.0-1.0, float(v[2]/255.0)*2.0-1.0, float(v[3]/255.0)*2.0-1.0 ); + } + } else { + PoolVector<Color>::Write w = arr.write(); + + for(int j=0;j<p_vertex_len;j++) { + + const float *v = (const float*)&r[j*total_elem_size+offsets[i]]; + w[j]=Color(v[0],v[1],v[2],v[3]); + } + } + + ret[i]=arr; + } break; + case VS::ARRAY_TEX_UV: { + + PoolVector<Vector2> arr; + arr.resize(p_vertex_len); + + if (p_format&ARRAY_COMPRESS_TEX_UV) { + + PoolVector<Vector2>::Write w = arr.write(); + + for(int j=0;j<p_vertex_len;j++) { + + const uint16_t *v = (const uint16_t*)&r[j*total_elem_size+offsets[i]]; + w[j]=Vector2(Math::halfptr_to_float(&v[0]),Math::halfptr_to_float(&v[1])); + } + } else { + + PoolVector<Vector2>::Write w = arr.write(); + + for(int j=0;j<p_vertex_len;j++) { + + const float *v = (const float*)&r[j*total_elem_size+offsets[i]]; + w[j]=Vector2(v[0],v[1]); + } + } + + ret[i]=arr; + } break; + + case VS::ARRAY_TEX_UV2: { + PoolVector<Vector2> arr; + arr.resize(p_vertex_len); + + if (p_format&ARRAY_COMPRESS_TEX_UV2) { + + PoolVector<Vector2>::Write w = arr.write(); + + for(int j=0;j<p_vertex_len;j++) { + + const uint16_t *v = (const uint16_t*)&r[j*total_elem_size+offsets[i]]; + w[j]=Vector2(Math::halfptr_to_float(&v[0]),Math::halfptr_to_float(&v[1])); + } + } else { + + PoolVector<Vector2>::Write w = arr.write(); + + for(int j=0;j<p_vertex_len;j++) { + + const float *v = (const float*)&r[j*total_elem_size+offsets[i]]; + w[j]=Vector2(v[0],v[1]); + } + } + + ret[i]=arr; + + } break; + case VS::ARRAY_WEIGHTS: { + + PoolVector<float> arr; + arr.resize(p_vertex_len*4); + if (p_format&ARRAY_COMPRESS_WEIGHTS) { + PoolVector<float>::Write w = arr.write(); + + for(int j=0;j<p_vertex_len;j++) { + + const uint16_t *v = (const uint16_t*)&r[j*total_elem_size+offsets[i]]; + for(int k=0;k<4;k++) { + w[j*4+k]=float(v[k]/65535.0)*2.0-1.0; + } + } + } else { + + PoolVector<float>::Write w = arr.write(); + + for(int j=0;j<p_vertex_len;j++) { + const float *v = (const float*)&r[j*total_elem_size+offsets[i]]; + for(int k=0;k<4;k++) { + w[j*4+k]=v[k]; + } + } + + } + + ret[i]=arr; + + } break; + case VS::ARRAY_BONES: { + + PoolVector<int> arr; + arr.resize(p_vertex_len*4); + if (p_format&ARRAY_FLAG_USE_16_BIT_BONES) { + + PoolVector<int>::Write w = arr.write(); + + for(int j=0;j<p_vertex_len;j++) { + + const uint16_t *v = (const uint16_t*)&r[j*total_elem_size+offsets[i]]; + for(int k=0;k<4;k++) { + w[j*4+k]=v[k]; + } + } + } else { + + PoolVector<int>::Write w = arr.write(); + + for(int j=0;j<p_vertex_len;j++) { + const uint8_t *v = (const uint8_t*)&r[j*total_elem_size+offsets[i]]; + for(int k=0;k<4;k++) { + w[j*4+k]=v[k]; + } + } + + } + + ret[i]=arr; + + } break; + case VS::ARRAY_INDEX: { + /* determine wether using 16 or 32 bits indices */ + + PoolVector<uint8_t>::Read ir = p_index_data.read(); + + PoolVector<int> arr; + arr.resize(p_index_len); + if (p_vertex_len<(1<<16)) { + + PoolVector<int>::Write w = arr.write(); + + for(int j=0;j<p_index_len;j++) { + + const uint16_t *v = (const uint16_t*)&ir[j*2]; + w[j]=*v; + } + } else { + + PoolVector<int>::Write w = arr.write(); + + for(int j=0;j<p_index_len;j++) { + const int *v = (const int*)&ir[j*4]; + w[j]=*v; + } + + } + ret[i]=arr; + } break; + default: { + ERR_FAIL_V( ret ); + } + } + } + + return ret; +} + +Array VisualServer::mesh_surface_get_arrays(RID p_mesh,int p_surface) const { + + PoolVector<uint8_t> vertex_data = mesh_surface_get_array(p_mesh,p_surface); + ERR_FAIL_COND_V(vertex_data.size()==0,Array()); + int vertex_len = mesh_surface_get_array_len(p_mesh,p_surface); + + PoolVector<uint8_t> index_data = mesh_surface_get_index_array(p_mesh,p_surface); + int index_len = mesh_surface_get_array_index_len(p_mesh,p_surface); + + uint32_t format = mesh_surface_get_format(p_mesh,p_surface); + + + return _get_array_from_surface(format,vertex_data,vertex_len,index_data,index_len); + +} + +void VisualServer::_bind_methods() { + + + ClassDB::bind_method(D_METHOD("texture_create"),&VisualServer::texture_create); + ClassDB::bind_method(D_METHOD("texture_create_from_image"),&VisualServer::texture_create_from_image,DEFVAL( TEXTURE_FLAGS_DEFAULT ) ); + //ClassDB::bind_method(D_METHOD("texture_allocate"),&VisualServer::texture_allocate,DEFVAL( TEXTURE_FLAGS_DEFAULT ) ); + //ClassDB::bind_method(D_METHOD("texture_set_data"),&VisualServer::texture_blit_rect,DEFVAL( CUBEMAP_LEFT ) ); + //ClassDB::bind_method(D_METHOD("texture_get_rect"),&VisualServer::texture_get_rect ); + ClassDB::bind_method(D_METHOD("texture_set_flags"),&VisualServer::texture_set_flags ); + ClassDB::bind_method(D_METHOD("texture_get_flags"),&VisualServer::texture_get_flags ); + ClassDB::bind_method(D_METHOD("texture_get_width"),&VisualServer::texture_get_width ); + ClassDB::bind_method(D_METHOD("texture_get_height"),&VisualServer::texture_get_height ); + + ClassDB::bind_method(D_METHOD("texture_set_shrink_all_x2_on_set_data","shrink"),&VisualServer::texture_set_shrink_all_x2_on_set_data ); + + + - camera_set_orthogonal(p_camera,p_size,p_z_near,p_z_far); } -void VisualServer::_viewport_set_rect(RID p_viewport,const Rect2& p_rect) { +void VisualServer::_canvas_item_add_style_box(RID p_item, const Rect2& p_rect, const Rect2& p_source, RID p_texture,const Vector<float>& p_margins, const Color& p_modulate) { - ViewportRect r; - r.x=p_rect.pos.x; - r.y=p_rect.pos.y; - r.width=p_rect.size.x; - r.height=p_rect.size.y; - viewport_set_rect(p_viewport,r); + ERR_FAIL_COND(p_margins.size()!=4); + //canvas_item_add_style_box(p_item,p_rect,p_source,p_texture,Vector2(p_margins[0],p_margins[1]),Vector2(p_margins[2],p_margins[3]),true,p_modulate); } -Rect2 VisualServer::_viewport_get_rect(RID p_viewport) const { - ViewportRect r=viewport_get_rect(p_viewport); - return Rect2(r.x,r.y,r.width,r.height); +void VisualServer::_camera_set_orthogonal(RID p_camera,float p_size,float p_z_near,float p_z_far) { + + camera_set_orthogonal(p_camera,p_size,p_z_near,p_z_far); } @@ -738,8 +1601,8 @@ Rect2 VisualServer::_viewport_get_rect(RID p_viewport) const { void VisualServer::mesh_add_surface_from_mesh_data( RID p_mesh, const Geometry::MeshData& p_mesh_data) { #if 1 - DVector<Vector3> vertices; - DVector<Vector3> normals; + PoolVector<Vector3> vertices; + PoolVector<Vector3> normals; for (int i=0;i<p_mesh_data.faces.size();i++) { @@ -761,12 +1624,12 @@ void VisualServer::mesh_add_surface_from_mesh_data( RID p_mesh, const Geometry:: d.resize(VS::ARRAY_MAX); d[ARRAY_VERTEX]=vertices; d[ARRAY_NORMAL]=normals; - mesh_add_surface(p_mesh,PRIMITIVE_TRIANGLES, d); + mesh_add_surface_from_arrays(p_mesh,PRIMITIVE_TRIANGLES, d); #else - DVector<Vector3> vertices; + PoolVector<Vector3> vertices; @@ -789,7 +1652,7 @@ void VisualServer::mesh_add_surface_from_mesh_data( RID p_mesh, const Geometry:: } -void VisualServer::mesh_add_surface_from_planes( RID p_mesh, const DVector<Plane>& p_planes) { +void VisualServer::mesh_add_surface_from_planes( RID p_mesh, const PoolVector<Plane>& p_planes) { Geometry::MeshData mdata = Geometry::build_convex_mesh(p_planes); @@ -797,6 +1660,10 @@ void VisualServer::mesh_add_surface_from_planes( RID p_mesh, const DVector<Plane } +void VisualServer::immediate_vertex_2d(RID p_immediate,const Vector2& p_vertex) { + immediate_vertex(p_immediate,Vector3(p_vertex.x,p_vertex.y,0)); +} + RID VisualServer::instance_create2(RID p_base, RID p_scenario) { RID instance = instance_create(); @@ -808,11 +1675,8 @@ RID VisualServer::instance_create2(RID p_base, RID p_scenario) { VisualServer::VisualServer() { -// ERR_FAIL_COND(singleton); + //ERR_FAIL_COND(singleton); singleton=this; - mm_policy=GLOBAL_DEF("render/mipmap_policy",0); - if (mm_policy<0 || mm_policy>2) - mm_policy=0; } diff --git a/servers/visual_server.h b/servers/visual_server.h index 2f3d8371f6..08cf34a653 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -42,17 +42,17 @@ */ class VisualServer : public Object { - OBJ_TYPE( VisualServer, Object ); + GDCLASS( VisualServer, Object ); static VisualServer *singleton; int mm_policy; - DVector<String> _shader_get_param_list(RID p_shader) const; + PoolVector<String> _shader_get_param_list(RID p_shader) const; void _camera_set_orthogonal(RID p_camera,float p_size,float p_z_near,float p_z_far); - void _viewport_set_rect(RID p_viewport,const Rect2& p_rect); - Rect2 _viewport_get_rect(RID p_viewport) const; void _canvas_item_add_style_box(RID p_item, const Rect2& p_rect, const Rect2& p_source, RID p_texture,const Vector<float>& p_margins, const Color& p_modulate=Color(1,1,1)); + Array _get_array_from_surface(uint32_t p_format,PoolVector<uint8_t> p_vertex_data,int p_vertex_len,PoolVector<uint8_t> p_index_data,int p_index_len) const; + protected: RID _make_test_cube(); void _free_internal_rids(); @@ -61,6 +61,9 @@ protected: RID test_material; RID material_2d[16]; + + Error _surface_set_data(Array p_arrays,uint32_t p_format,uint32_t *p_offsets,uint32_t p_stride,PoolVector<uint8_t> &r_vertex_array,int p_vertex_array_len,PoolVector<uint8_t> &r_index_array,int p_index_array_len,Rect3 &r_aabb,Vector<Rect3> r_bone_aabb); + static VisualServer* (*create_func)(); static void _bind_methods(); public: @@ -68,28 +71,16 @@ public: static VisualServer *get_singleton(); static VisualServer *create(); - enum MipMapPolicy { - - MIPMAPS_ENABLED, - MIPMAPS_ENABLED_FOR_PO2, - MIPMAPS_DISABLED - }; - - - virtual void set_mipmap_policy(MipMapPolicy p_policy); - virtual MipMapPolicy get_mipmap_policy() const; - enum { NO_INDEX_ARRAY=-1, - CUSTOM_ARRAY_SIZE=8, ARRAY_WEIGHTS_SIZE=4, - MAX_PARTICLE_COLOR_PHASES=4, - MAX_PARTICLE_ATTRACTORS=4, CANVAS_ITEM_Z_MIN=-4096, CANVAS_ITEM_Z_MAX=4096, + MAX_GLOW_LEVELS=7, + @@ -106,7 +97,7 @@ public: TEXTURE_FLAG_CONVERT_TO_LINEAR=16, TEXTURE_FLAG_MIRRORED_REPEAT=32, /// Repeat texture, with alternate sections mirrored TEXTURE_FLAG_CUBEMAP=2048, - TEXTURE_FLAG_VIDEO_SURFACE=4096, + TEXTURE_FLAG_USED_FOR_STREAMING=4096, TEXTURE_FLAGS_DEFAULT=TEXTURE_FLAG_REPEAT|TEXTURE_FLAG_MIPMAPS|TEXTURE_FLAG_FILTER }; @@ -132,14 +123,17 @@ public: virtual uint32_t texture_get_width(RID p_texture) const=0; virtual uint32_t texture_get_height(RID p_texture) const=0; virtual void texture_set_size_override(RID p_texture,int p_width, int p_height)=0; - virtual bool texture_can_stream(RID p_texture) const=0; - virtual void texture_set_reload_hook(RID p_texture,ObjectID p_owner,const StringName& p_function) const=0; virtual void texture_set_path(RID p_texture,const String& p_path)=0; virtual String texture_get_path(RID p_texture) const=0; virtual void texture_set_shrink_all_x2_on_set_data(bool p_enable)=0; + typedef void (*TextureDetectCallback)(void*); + + virtual void texture_set_detect_3d_callback(RID p_texture,TextureDetectCallback p_callback,void* p_userdata)=0; + virtual void texture_set_detect_srgb_callback(RID p_texture,TextureDetectCallback p_callback,void* p_userdata)=0; + struct TextureInfo { RID texture; Size2 size; @@ -150,26 +144,31 @@ public: virtual void texture_debug_usage(List<TextureInfo> *r_info)=0; + virtual void textures_keep_original(bool p_enable)=0; + + /* SKYBOX API */ + + virtual RID skybox_create()=0; + virtual void skybox_set_texture(RID p_skybox,RID p_cube_map,int p_radiance_size)=0; /* SHADER API */ enum ShaderMode { - SHADER_MATERIAL, + SHADER_SPATIAL, SHADER_CANVAS_ITEM, - SHADER_POST_PROCESS, + SHADER_PARTICLES, + SHADER_MAX }; - virtual RID shader_create(ShaderMode p_mode=SHADER_MATERIAL)=0; + virtual RID shader_create(ShaderMode p_mode=SHADER_SPATIAL)=0; virtual void shader_set_mode(RID p_shader,ShaderMode p_mode)=0; virtual ShaderMode shader_get_mode(RID p_shader) const=0; - virtual void shader_set_code(RID p_shader, const String& p_vertex, const String& p_fragment,const String& p_light, int p_vertex_ofs=0,int p_fragment_ofs=0,int p_light_ofs=0)=0; - virtual String shader_get_fragment_code(RID p_shader) const=0; - virtual String shader_get_vertex_code(RID p_shader) const=0; - virtual String shader_get_light_code(RID p_shader) const=0; + virtual void shader_set_code(RID p_shader, const String& p_code)=0; + virtual String shader_get_code(RID p_shader) const=0; virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const=0; virtual void shader_set_default_texture_param(RID p_shader, const StringName& p_name, RID p_texture)=0; @@ -186,113 +185,7 @@ public: virtual void material_set_param(RID p_material, const StringName& p_param, const Variant& p_value)=0; virtual Variant material_get_param(RID p_material, const StringName& p_param) const=0; - enum MaterialFlag { - MATERIAL_FLAG_VISIBLE, - MATERIAL_FLAG_DOUBLE_SIDED, - MATERIAL_FLAG_INVERT_FACES, ///< Invert front/back of the object - MATERIAL_FLAG_UNSHADED, - MATERIAL_FLAG_ONTOP, - MATERIAL_FLAG_LIGHTMAP_ON_UV2, - MATERIAL_FLAG_COLOR_ARRAY_SRGB, - MATERIAL_FLAG_MAX, - }; - - virtual void material_set_flag(RID p_material, MaterialFlag p_flag,bool p_enabled)=0; - virtual bool material_get_flag(RID p_material,MaterialFlag p_flag) const=0; - - enum MaterialDepthDrawMode { - MATERIAL_DEPTH_DRAW_ALWAYS, - MATERIAL_DEPTH_DRAW_OPAQUE_ONLY, - MATERIAL_DEPTH_DRAW_OPAQUE_PRE_PASS_ALPHA, - MATERIAL_DEPTH_DRAW_NEVER - }; - - virtual void material_set_depth_draw_mode(RID p_material, MaterialDepthDrawMode p_mode)=0; - virtual MaterialDepthDrawMode material_get_depth_draw_mode(RID p_material) const=0; - - enum MaterialBlendMode { - MATERIAL_BLEND_MODE_MIX, //default - MATERIAL_BLEND_MODE_ADD, - MATERIAL_BLEND_MODE_SUB, - MATERIAL_BLEND_MODE_MUL, - MATERIAL_BLEND_MODE_PREMULT_ALPHA - }; - - - virtual void material_set_blend_mode(RID p_material,MaterialBlendMode p_mode)=0; - virtual MaterialBlendMode material_get_blend_mode(RID p_material) const=0; - - virtual void material_set_line_width(RID p_material,float p_line_width)=0; - virtual float material_get_line_width(RID p_material) const=0; - - - //fixed material api - - virtual RID fixed_material_create()=0; - - enum FixedMaterialParam { - - FIXED_MATERIAL_PARAM_DIFFUSE, - FIXED_MATERIAL_PARAM_DETAIL, - FIXED_MATERIAL_PARAM_SPECULAR, - FIXED_MATERIAL_PARAM_EMISSION, - FIXED_MATERIAL_PARAM_SPECULAR_EXP, - FIXED_MATERIAL_PARAM_GLOW, - FIXED_MATERIAL_PARAM_NORMAL, - FIXED_MATERIAL_PARAM_SHADE_PARAM, - FIXED_MATERIAL_PARAM_MAX - }; - - enum FixedMaterialTexCoordMode { - - FIXED_MATERIAL_TEXCOORD_UV, - FIXED_MATERIAL_TEXCOORD_UV_TRANSFORM, - FIXED_MATERIAL_TEXCOORD_UV2, - FIXED_MATERIAL_TEXCOORD_SPHERE - }; - - enum FixedMaterialFlags { - - FIXED_MATERIAL_FLAG_USE_ALPHA, - FIXED_MATERIAL_FLAG_USE_COLOR_ARRAY, - FIXED_MATERIAL_FLAG_USE_POINT_SIZE, - FIXED_MATERIAL_FLAG_DISCARD_ALPHA, - FIXED_MATERIAL_FLAG_USE_XY_NORMALMAP, - FIXED_MATERIAL_FLAG_MAX, - }; - - - virtual void fixed_material_set_flag(RID p_material, FixedMaterialFlags p_flag, bool p_enabled)=0; - virtual bool fixed_material_get_flag(RID p_material, FixedMaterialFlags p_flag) const=0; - - virtual void fixed_material_set_param(RID p_material, FixedMaterialParam p_parameter, const Variant& p_value)=0; - virtual Variant fixed_material_get_param(RID p_material,FixedMaterialParam p_parameter) const=0; - - virtual void fixed_material_set_texture(RID p_material,FixedMaterialParam p_parameter, RID p_texture)=0; - virtual RID fixed_material_get_texture(RID p_material,FixedMaterialParam p_parameter) const=0; - - - enum FixedMaterialLightShader { - - FIXED_MATERIAL_LIGHT_SHADER_LAMBERT, - FIXED_MATERIAL_LIGHT_SHADER_WRAP, - FIXED_MATERIAL_LIGHT_SHADER_VELVET, - FIXED_MATERIAL_LIGHT_SHADER_TOON, - - }; - - - virtual void fixed_material_set_light_shader(RID p_material,FixedMaterialLightShader p_shader)=0; - virtual FixedMaterialLightShader fixed_material_get_light_shader(RID p_material) const=0; - - virtual void fixed_material_set_texcoord_mode(RID p_material,FixedMaterialParam p_parameter, FixedMaterialTexCoordMode p_mode)=0; - virtual FixedMaterialTexCoordMode fixed_material_get_texcoord_mode(RID p_material,FixedMaterialParam p_parameter) const=0; - - virtual void fixed_material_set_uv_transform(RID p_material,const Transform& p_transform)=0; - virtual Transform fixed_material_get_uv_transform(RID p_material) const=0; - - virtual void fixed_material_set_point_size(RID p_material,float p_size)=0; - virtual float fixed_material_get_point_size(RID p_material) const=0; + virtual void material_set_line_width(RID p_material, float p_width)=0; /* MESH API */ @@ -321,8 +214,26 @@ public: ARRAY_FORMAT_BONES=1<<ARRAY_BONES, ARRAY_FORMAT_WEIGHTS=1<<ARRAY_WEIGHTS, ARRAY_FORMAT_INDEX=1<<ARRAY_INDEX, + + ARRAY_COMPRESS_BASE=(ARRAY_INDEX+1), + ARRAY_COMPRESS_VERTEX=1<<(ARRAY_VERTEX+ARRAY_COMPRESS_BASE), // mandatory + ARRAY_COMPRESS_NORMAL=1<<(ARRAY_NORMAL+ARRAY_COMPRESS_BASE), + ARRAY_COMPRESS_TANGENT=1<<(ARRAY_TANGENT+ARRAY_COMPRESS_BASE), + ARRAY_COMPRESS_COLOR=1<<(ARRAY_COLOR+ARRAY_COMPRESS_BASE), + ARRAY_COMPRESS_TEX_UV=1<<(ARRAY_TEX_UV+ARRAY_COMPRESS_BASE), + ARRAY_COMPRESS_TEX_UV2=1<<(ARRAY_TEX_UV2+ARRAY_COMPRESS_BASE), + ARRAY_COMPRESS_BONES=1<<(ARRAY_BONES+ARRAY_COMPRESS_BASE), + ARRAY_COMPRESS_WEIGHTS=1<<(ARRAY_WEIGHTS+ARRAY_COMPRESS_BASE), + ARRAY_COMPRESS_INDEX=1<<(ARRAY_INDEX+ARRAY_COMPRESS_BASE), + + ARRAY_FLAG_USE_2D_VERTICES=ARRAY_COMPRESS_INDEX<<1, + ARRAY_FLAG_USE_16_BIT_BONES=ARRAY_COMPRESS_INDEX<<2, + + ARRAY_COMPRESS_DEFAULT=ARRAY_COMPRESS_VERTEX|ARRAY_COMPRESS_NORMAL|ARRAY_COMPRESS_TANGENT|ARRAY_COMPRESS_COLOR|ARRAY_COMPRESS_TEX_UV|ARRAY_COMPRESS_TEX_UV2|ARRAY_COMPRESS_WEIGHTS + }; + enum PrimitiveType { PRIMITIVE_POINTS=0, PRIMITIVE_LINES=1, @@ -336,65 +247,88 @@ public: virtual RID mesh_create()=0; - virtual void mesh_add_surface(RID p_mesh,PrimitiveType p_primitive,const Array& p_arrays,const Array& p_blend_shapes=Array(),bool p_alpha_sort=false)=0; - virtual Array mesh_get_surface_arrays(RID p_mesh,int p_surface) const=0; - virtual Array mesh_get_surface_morph_arrays(RID p_mesh,int p_surface) const=0; + virtual void mesh_add_surface_from_arrays(RID p_mesh,PrimitiveType p_primitive,const Array& p_arrays,const Array& p_blend_shapes=Array(),uint32_t p_compress_format=ARRAY_COMPRESS_DEFAULT); + virtual void mesh_add_surface(RID p_mesh,uint32_t p_format,PrimitiveType p_primitive,const PoolVector<uint8_t>& p_array,int p_vertex_count,const PoolVector<uint8_t>& p_index_array,int p_index_count,const Rect3& p_aabb,const Vector<PoolVector<uint8_t> >& p_blend_shapes=Vector<PoolVector<uint8_t> >(),const Vector<Rect3>& p_bone_aabbs=Vector<Rect3>())=0; - virtual void mesh_add_custom_surface(RID p_mesh,const Variant& p_dat)=0; //this is used by each platform in a different way - virtual void mesh_set_morph_target_count(RID p_mesh,int p_amount)=0; - virtual int mesh_get_morph_target_count(RID p_mesh) const=0; + virtual void mesh_set_blend_shape_count(RID p_mesh,int p_amount)=0; + virtual int mesh_get_blend_shape_count(RID p_mesh) const=0; - enum MorphTargetMode { - MORPH_MODE_NORMALIZED, - MORPH_MODE_RELATIVE, + enum BlendShapeMode { + BLEND_SHAPE_MODE_NORMALIZED, + BLEND_SHAPE_MODE_RELATIVE, }; - virtual void mesh_set_morph_target_mode(RID p_mesh,MorphTargetMode p_mode)=0; - virtual MorphTargetMode mesh_get_morph_target_mode(RID p_mesh) const=0; + virtual void mesh_set_blend_shape_mode(RID p_mesh,BlendShapeMode p_mode)=0; + virtual BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const=0; - virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material,bool p_owned=false)=0; + virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material)=0; virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const=0; virtual int mesh_surface_get_array_len(RID p_mesh, int p_surface) const=0; virtual int mesh_surface_get_array_index_len(RID p_mesh, int p_surface) const=0; + + virtual PoolVector<uint8_t> mesh_surface_get_array(RID p_mesh, int p_surface) const=0; + virtual PoolVector<uint8_t> mesh_surface_get_index_array(RID p_mesh, int p_surface) const=0; + + virtual Array mesh_surface_get_arrays(RID p_mesh,int p_surface) const; + virtual uint32_t mesh_surface_get_format(RID p_mesh, int p_surface) const=0; virtual PrimitiveType mesh_surface_get_primitive_type(RID p_mesh, int p_surface) const=0; + virtual Rect3 mesh_surface_get_aabb(RID p_mesh, int p_surface) const=0; + virtual Vector<PoolVector<uint8_t> > mesh_surface_get_blend_shapes(RID p_mesh, int p_surface) const=0; + virtual Vector<Rect3> mesh_surface_get_skeleton_aabb(RID p_mesh, int p_surface) const=0; + virtual void mesh_remove_surface(RID p_mesh,int p_index)=0; virtual int mesh_get_surface_count(RID p_mesh) const=0; - virtual void mesh_set_custom_aabb(RID p_mesh,const AABB& p_aabb)=0; - virtual AABB mesh_get_custom_aabb(RID p_mesh) const=0; + virtual void mesh_set_custom_aabb(RID p_mesh,const Rect3& p_aabb)=0; + virtual Rect3 mesh_get_custom_aabb(RID p_mesh) const=0; virtual void mesh_clear(RID p_mesh)=0; /* MULTIMESH API */ + virtual RID multimesh_create()=0; - virtual void multimesh_set_instance_count(RID p_multimesh,int p_count)=0; + enum MultimeshTransformFormat { + MULTIMESH_TRANSFORM_2D, + MULTIMESH_TRANSFORM_3D, + }; + + enum MultimeshColorFormat { + MULTIMESH_COLOR_NONE, + MULTIMESH_COLOR_8BIT, + MULTIMESH_COLOR_FLOAT, + }; + + virtual void multimesh_allocate(RID p_multimesh,int p_instances,MultimeshTransformFormat p_transform_format,MultimeshColorFormat p_color_format)=0; virtual int multimesh_get_instance_count(RID p_multimesh) const=0; virtual void multimesh_set_mesh(RID p_multimesh,RID p_mesh)=0; - virtual void multimesh_set_aabb(RID p_multimesh,const AABB& p_aabb)=0; virtual void multimesh_instance_set_transform(RID p_multimesh,int p_index,const Transform& p_transform)=0; + virtual void multimesh_instance_set_transform_2d(RID p_multimesh,int p_index,const Transform2D& p_transform)=0; virtual void multimesh_instance_set_color(RID p_multimesh,int p_index,const Color& p_color)=0; virtual RID multimesh_get_mesh(RID p_multimesh) const=0; - virtual AABB multimesh_get_aabb(RID p_multimesh,const AABB& p_aabb) const=0;; + virtual Rect3 multimesh_get_aabb(RID p_multimesh) const=0; virtual Transform multimesh_instance_get_transform(RID p_multimesh,int p_index) const=0; + virtual Transform2D multimesh_instance_get_transform_2d(RID p_multimesh,int p_index) const=0; virtual Color multimesh_instance_get_color(RID p_multimesh,int p_index) const=0; virtual void multimesh_set_visible_instances(RID p_multimesh,int p_visible)=0; virtual int multimesh_get_visible_instances(RID p_multimesh) const=0; + /* IMMEDIATE API */ virtual RID immediate_create()=0; virtual void immediate_begin(RID p_immediate,PrimitiveType p_rimitive,RID p_texture=RID())=0; virtual void immediate_vertex(RID p_immediate,const Vector3& p_vertex)=0; + virtual void immediate_vertex_2d(RID p_immediate,const Vector2& p_vertex); virtual void immediate_normal(RID p_immediate,const Vector3& p_normal)=0; virtual void immediate_tangent(RID p_immediate,const Plane& p_tangent)=0; virtual void immediate_color(RID p_immediate,const Color& p_color)=0; @@ -405,82 +339,15 @@ public: virtual void immediate_set_material(RID p_immediate,RID p_material)=0; virtual RID immediate_get_material(RID p_immediate) const=0; + /* SKELETON API */ - /* PARTICLES API */ - - virtual RID particles_create()=0; - - enum ParticleVariable { - PARTICLE_LIFETIME, - PARTICLE_SPREAD, - PARTICLE_GRAVITY, - PARTICLE_LINEAR_VELOCITY, - PARTICLE_ANGULAR_VELOCITY, - PARTICLE_LINEAR_ACCELERATION, - PARTICLE_RADIAL_ACCELERATION, - PARTICLE_TANGENTIAL_ACCELERATION, - PARTICLE_DAMPING, - PARTICLE_INITIAL_SIZE, - PARTICLE_FINAL_SIZE, - PARTICLE_INITIAL_ANGLE, - PARTICLE_HEIGHT, - PARTICLE_HEIGHT_SPEED_SCALE, - PARTICLE_VAR_MAX - }; - - virtual void particles_set_amount(RID p_particles, int p_amount)=0; - virtual int particles_get_amount(RID p_particles) const=0; - - virtual void particles_set_emitting(RID p_particles, bool p_emitting)=0; - virtual bool particles_is_emitting(RID p_particles) const=0; - - virtual void particles_set_visibility_aabb(RID p_particles, const AABB& p_visibility)=0; - virtual AABB particles_get_visibility_aabb(RID p_particles) const=0; - - virtual void particles_set_emission_half_extents(RID p_particles, const Vector3& p_half_extents)=0; - virtual Vector3 particles_get_emission_half_extents(RID p_particles) const=0; - - virtual void particles_set_emission_base_velocity(RID p_particles, const Vector3& p_base_velocity)=0; - virtual Vector3 particles_get_emission_base_velocity(RID p_particles) const=0; - - virtual void particles_set_emission_points(RID p_particles, const DVector<Vector3>& p_points)=0; - virtual DVector<Vector3> particles_get_emission_points(RID p_particles) const=0; - - virtual void particles_set_gravity_normal(RID p_particles, const Vector3& p_normal)=0; - virtual Vector3 particles_get_gravity_normal(RID p_particles) const=0; - - virtual void particles_set_variable(RID p_particles, ParticleVariable p_variable,float p_value)=0; - virtual float particles_get_variable(RID p_particles, ParticleVariable p_variable) const=0; - - virtual void particles_set_randomness(RID p_particles, ParticleVariable p_variable,float p_randomness)=0; - virtual float particles_get_randomness(RID p_particles, ParticleVariable p_variable) const=0; - - virtual void particles_set_color_phases(RID p_particles, int p_phases)=0; - virtual int particles_get_color_phases(RID p_particles) const=0; - - virtual void particles_set_color_phase_pos(RID p_particles, int p_phase, float p_pos)=0; - virtual float particles_get_color_phase_pos(RID p_particles, int p_phase) const=0; - - virtual void particles_set_color_phase_color(RID p_particles, int p_phase, const Color& p_color)=0; - virtual Color particles_get_color_phase_color(RID p_particles, int p_phase) const=0; - - virtual void particles_set_attractors(RID p_particles, int p_attractors)=0; - virtual int particles_get_attractors(RID p_particles) const=0; - - virtual void particles_set_attractor_pos(RID p_particles, int p_attractor, const Vector3& p_pos)=0; - virtual Vector3 particles_get_attractor_pos(RID p_particles,int p_attractor) const=0; - - virtual void particles_set_attractor_strength(RID p_particles, int p_attractor, float p_force)=0; - virtual float particles_get_attractor_strength(RID p_particles,int p_attractor) const=0; - - virtual void particles_set_material(RID p_particles, RID p_material,bool p_owned=false)=0; - virtual RID particles_get_material(RID p_particles) const=0; - - virtual void particles_set_height_from_velocity(RID p_particles, bool p_enable)=0; - virtual bool particles_has_height_from_velocity(RID p_particles) const=0; - - virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable)=0; - virtual bool particles_is_using_local_coordinates(RID p_particles) const=0; + virtual RID skeleton_create()=0; + virtual void skeleton_allocate(RID p_skeleton,int p_bones,bool p_2d_skeleton=false)=0; + virtual int skeleton_get_bone_count(RID p_skeleton) const=0; + virtual void skeleton_bone_set_transform(RID p_skeleton,int p_bone, const Transform& p_transform)=0; + virtual Transform skeleton_bone_get_transform(RID p_skeleton,int p_bone) const=0; + virtual void skeleton_bone_set_transform_2d(RID p_skeleton,int p_bone, const Transform2D& p_transform)=0; + virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton,int p_bone)const =0; /* Light API */ @@ -490,99 +357,90 @@ public: LIGHT_SPOT }; - enum LightColor { - LIGHT_COLOR_DIFFUSE, - LIGHT_COLOR_SPECULAR - }; - enum LightParam { - LIGHT_PARAM_SPOT_ATTENUATION, - LIGHT_PARAM_SPOT_ANGLE, - LIGHT_PARAM_RADIUS, LIGHT_PARAM_ENERGY, + LIGHT_PARAM_SPECULAR, + LIGHT_PARAM_RANGE, LIGHT_PARAM_ATTENUATION, - LIGHT_PARAM_SHADOW_DARKENING, - LIGHT_PARAM_SHADOW_Z_OFFSET, - LIGHT_PARAM_SHADOW_Z_SLOPE_SCALE, - LIGHT_PARAM_SHADOW_ESM_MULTIPLIER, - LIGHT_PARAM_SHADOW_BLUR_PASSES, + LIGHT_PARAM_SPOT_ANGLE, + LIGHT_PARAM_SPOT_ATTENUATION, + LIGHT_PARAM_CONTACT_SHADOW_SIZE, + LIGHT_PARAM_SHADOW_MAX_DISTANCE, + LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET, + LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET, + LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET, + LIGHT_PARAM_SHADOW_NORMAL_BIAS, + LIGHT_PARAM_SHADOW_BIAS, + LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE, LIGHT_PARAM_MAX }; virtual RID light_create(LightType p_type)=0; - virtual LightType light_get_type(RID p_light) const=0; - - virtual void light_set_color(RID p_light,LightColor p_type, const Color& p_color)=0; - virtual Color light_get_color(RID p_light,LightColor p_type) const=0; + virtual void light_set_color(RID p_light,const Color& p_color)=0; + virtual void light_set_param(RID p_light,LightParam p_param,float p_value)=0; virtual void light_set_shadow(RID p_light,bool p_enabled)=0; - virtual bool light_has_shadow(RID p_light) const=0; - - virtual void light_set_volumetric(RID p_light,bool p_enabled)=0; - virtual bool light_is_volumetric(RID p_light) const=0; - + virtual void light_set_shadow_color(RID p_light,const Color& p_color)=0; virtual void light_set_projector(RID p_light,RID p_texture)=0; - virtual RID light_get_projector(RID p_light) const=0; - - virtual void light_set_param(RID p_light, LightParam p_var, float p_value)=0; - virtual float light_get_param(RID p_light, LightParam p_var) const=0; - - enum LightOp { - - LIGHT_OPERATOR_ADD, - LIGHT_OPERATOR_SUB - }; - - virtual void light_set_operator(RID p_light,LightOp p_op)=0; - virtual LightOp light_get_operator(RID p_light) const=0; + 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; // omni light enum LightOmniShadowMode { - LIGHT_OMNI_SHADOW_DEFAULT, LIGHT_OMNI_SHADOW_DUAL_PARABOLOID, - LIGHT_OMNI_SHADOW_CUBEMAP + LIGHT_OMNI_SHADOW_CUBE, }; virtual void light_omni_set_shadow_mode(RID p_light,LightOmniShadowMode p_mode)=0; - virtual LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) const=0; + + // omni light + enum LightOmniShadowDetail { + LIGHT_OMNI_SHADOW_DETAIL_VERTICAL, + LIGHT_OMNI_SHADOW_DETAIL_HORIZONTAL + }; + + virtual void light_omni_set_shadow_detail(RID p_light,LightOmniShadowDetail p_detail)=0; // directional light enum LightDirectionalShadowMode { LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL, - LIGHT_DIRECTIONAL_SHADOW_PERSPECTIVE, LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS, LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS }; virtual void light_directional_set_shadow_mode(RID p_light,LightDirectionalShadowMode p_mode)=0; - virtual LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) const=0; + virtual void light_directional_set_blend_splits(RID p_light,bool p_enable)=0; - enum LightDirectionalShadowParam { + /* PROBE API */ - LIGHT_DIRECTIONAL_SHADOW_PARAM_MAX_DISTANCE, - LIGHT_DIRECTIONAL_SHADOW_PARAM_PSSM_SPLIT_WEIGHT, - LIGHT_DIRECTIONAL_SHADOW_PARAM_PSSM_ZOFFSET_SCALE, - }; + virtual RID reflection_probe_create()=0; - virtual void light_directional_set_shadow_param(RID p_light,LightDirectionalShadowParam p_param, float p_value)=0; - virtual float light_directional_get_shadow_param(RID p_light,LightDirectionalShadowParam p_param) const=0; + enum ReflectionProbeUpdateMode { + REFLECTION_PROBE_UPDATE_ONCE, + REFLECTION_PROBE_UPDATE_ALWAYS, + }; - //@TODO fallof model and all that stuff - /* SKELETON API */ + virtual void reflection_probe_set_update_mode(RID p_probe, ReflectionProbeUpdateMode p_mode)=0; + virtual void reflection_probe_set_intensity(RID p_probe, float p_intensity)=0; + virtual void reflection_probe_set_interior_ambient(RID p_probe, const Color& p_color)=0; + virtual void reflection_probe_set_interior_ambient_energy(RID p_probe, float p_energy)=0; + virtual void reflection_probe_set_interior_ambient_probe_contribution(RID p_probe, float p_contrib)=0; + virtual void reflection_probe_set_max_distance(RID p_probe, float p_distance)=0; + virtual void reflection_probe_set_extents(RID p_probe, const Vector3& p_extents)=0; + virtual void reflection_probe_set_origin_offset(RID p_probe, const Vector3& p_offset)=0; + virtual void reflection_probe_set_as_interior(RID p_probe, bool p_enable)=0; + virtual void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable)=0; + virtual void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable)=0; + virtual void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers)=0; - virtual RID skeleton_create()=0; - virtual void skeleton_resize(RID p_skeleton,int p_bones)=0; - virtual int skeleton_get_bone_count(RID p_skeleton) const=0; - virtual void skeleton_bone_set_transform(RID p_skeleton,int p_bone, const Transform& p_transform)=0; - virtual Transform skeleton_bone_get_transform(RID p_skeleton,int p_bone)=0; /* ROOM API */ virtual RID room_create()=0; - virtual void room_set_bounds(RID p_room, const BSP_Tree& p_bounds)=0; - virtual BSP_Tree room_get_bounds(RID p_room) const=0; + virtual void room_add_bounds(RID p_room, const PoolVector<Vector2>& p_convex_polygon,float p_height,const Transform& p_transform)=0; + virtual void room_clear_bounds(RID p_room)=0; /* PORTAL API */ @@ -591,69 +449,91 @@ public: virtual RID portal_create()=0; virtual void portal_set_shape(RID p_portal, const Vector<Point2>& p_shape)=0; - virtual Vector<Point2> portal_get_shape(RID p_portal) const=0; virtual void portal_set_enabled(RID p_portal, bool p_enabled)=0; - virtual bool portal_is_enabled(RID p_portal) const=0; virtual void portal_set_disable_distance(RID p_portal, float p_distance)=0; - virtual float portal_get_disable_distance(RID p_portal) const=0; virtual void portal_set_disabled_color(RID p_portal, const Color& p_color)=0; - virtual Color portal_get_disabled_color(RID p_portal) const=0; - virtual void portal_set_connect_range(RID p_portal, float p_range) =0; - virtual float portal_get_connect_range(RID p_portal) const =0; + /* GI PROBE API */ - /* BAKED LIGHT API */ + virtual RID gi_probe_create()=0; - virtual RID baked_light_create()=0; - enum BakedLightMode { - BAKED_LIGHT_OCTREE, - BAKED_LIGHT_LIGHTMAPS - }; + virtual void gi_probe_set_bounds(RID p_probe,const Rect3& p_bounds)=0; + virtual Rect3 gi_probe_get_bounds(RID p_probe) const=0; - virtual void baked_light_set_mode(RID p_baked_light,BakedLightMode p_mode)=0; - virtual BakedLightMode baked_light_get_mode(RID p_baked_light) const=0; + virtual void gi_probe_set_cell_size(RID p_probe,float p_range)=0; + virtual float gi_probe_get_cell_size(RID p_probe) const=0; - virtual void baked_light_set_octree(RID p_baked_light,const DVector<uint8_t> p_octree)=0; - virtual DVector<uint8_t> baked_light_get_octree(RID p_baked_light) const=0; + virtual void gi_probe_set_to_cell_xform(RID p_probe,const Transform& p_xform)=0; + virtual Transform gi_probe_get_to_cell_xform(RID p_probe) const=0; - virtual void baked_light_set_light(RID p_baked_light,const DVector<uint8_t> p_light)=0; - virtual DVector<uint8_t> baked_light_get_light(RID p_baked_light) const=0; + virtual void gi_probe_set_dynamic_data(RID p_probe,const PoolVector<int>& p_data)=0; + virtual PoolVector<int> gi_probe_get_dynamic_data(RID p_probe) const=0; - virtual void baked_light_set_sampler_octree(RID p_baked_light,const DVector<int> &p_sampler)=0; - virtual DVector<int> baked_light_get_sampler_octree(RID p_baked_light) const=0; + virtual void gi_probe_set_dynamic_range(RID p_probe,int p_range)=0; + virtual int gi_probe_get_dynamic_range(RID p_probe) const=0; - virtual void baked_light_set_lightmap_multiplier(RID p_baked_light,float p_multiplier)=0; - virtual float baked_light_get_lightmap_multiplier(RID p_baked_light) const=0; + virtual void gi_probe_set_energy(RID p_probe,float p_range)=0; + virtual float gi_probe_get_energy(RID p_probe) const=0; - virtual void baked_light_add_lightmap(RID p_baked_light,const RID p_texture,int p_id)=0; - virtual void baked_light_clear_lightmaps(RID p_baked_light)=0; + virtual void gi_probe_set_bias(RID p_probe,float p_range)=0; + virtual float gi_probe_get_bias(RID p_probe) const=0; - virtual void baked_light_set_realtime_color_enabled(RID p_baked_light, const bool p_enabled)=0; - virtual bool baked_light_get_realtime_color_enabled(RID p_baked_light) const=0; + virtual void gi_probe_set_propagation(RID p_probe,float p_range)=0; + virtual float gi_probe_get_propagation(RID p_probe) const=0; - virtual void baked_light_set_realtime_color(RID p_baked_light, const Color& p_color)=0; - virtual Color baked_light_get_realtime_color(RID p_baked_light) const=0; + virtual void gi_probe_set_interior(RID p_probe,bool p_enable)=0; + virtual bool gi_probe_is_interior(RID p_probe) const=0; - virtual void baked_light_set_realtime_energy(RID p_baked_light, const float p_energy) = 0; - virtual float baked_light_get_realtime_energy(RID p_baked_light) const = 0; + virtual void gi_probe_set_compress(RID p_probe,bool p_enable)=0; + virtual bool gi_probe_is_compressed(RID p_probe) const=0; - /* BAKED LIGHT SAMPLER */ + /* PARTICLES API */ - virtual RID baked_light_sampler_create()=0; + virtual RID particles_create()=0; - enum BakedLightSamplerParam { - BAKED_LIGHT_SAMPLER_RADIUS, - BAKED_LIGHT_SAMPLER_STRENGTH, - BAKED_LIGHT_SAMPLER_ATTENUATION, - BAKED_LIGHT_SAMPLER_DETAIL_RATIO, - BAKED_LIGHT_SAMPLER_MAX + virtual void particles_set_emitting(RID p_particles,bool p_emitting)=0; + virtual void particles_set_amount(RID p_particles,int p_amount)=0; + virtual void particles_set_lifetime(RID p_particles,float p_lifetime)=0; + virtual void particles_set_pre_process_time(RID p_particles,float p_time)=0; + virtual void particles_set_explosiveness_ratio(RID p_particles,float p_ratio)=0; + virtual void particles_set_randomness_ratio(RID p_particles,float p_ratio)=0; + virtual void particles_set_custom_aabb(RID p_particles,const Rect3& p_aabb)=0; + virtual void particles_set_gravity(RID p_particles,const Vector3& p_gravity)=0; + virtual void particles_set_use_local_coordinates(RID p_particles,bool p_enable)=0; + virtual void particles_set_process_material(RID p_particles,RID p_material)=0; + + enum ParticlesEmissionShape { + PARTICLES_EMSSION_POINT, + PARTICLES_EMSSION_SPHERE, + PARTICLES_EMSSION_BOX, + PARTICLES_EMSSION_POINTS, + PARTICLES_EMSSION_SEGMENTS, + }; + + virtual void particles_set_emission_shape(RID p_particles,ParticlesEmissionShape)=0; + virtual void particles_set_emission_sphere_radius(RID p_particles,float p_radius)=0; + virtual void particles_set_emission_box_extents(RID p_particles,const Vector3& p_extents)=0; + virtual void particles_set_emission_points(RID p_particles,const PoolVector<Vector3>& p_points)=0; + + enum ParticlesDrawOrder { + PARTICLES_DRAW_ORDER_INDEX, + PARTICLES_DRAW_ORDER_LIFETIME, + PARTICLES_DRAW_ORDER_VIEW_DEPTH, + }; + + virtual void particles_set_draw_order(RID p_particles,ParticlesDrawOrder p_order)=0; + + enum ParticlesDrawPassMode { + PARTICLES_DRAW_PASS_MODE_QUAD, + PARTICLES_DRAW_PASS_MODE_MESH }; - virtual void baked_light_sampler_set_param(RID p_baked_light_sampler,BakedLightSamplerParam p_param,float p_value)=0; - virtual float baked_light_sampler_get_param(RID p_baked_light_sampler,BakedLightSamplerParam p_param) const=0; - virtual void baked_light_sampler_set_resolution(RID p_baked_light_sampler,int p_resolution)=0; - virtual int baked_light_sampler_get_resolution(RID p_baked_light_sampler) const=0; + virtual void particles_set_draw_passes(RID p_particles,int p_count)=0; + virtual void particles_set_draw_pass_material(RID p_particles,int p_pass, RID p_material)=0; + virtual void particles_set_draw_pass_mesh(RID p_particles,int p_pass, RID p_mesh)=0; + + virtual Rect3 particles_get_current_aabb(RID p_particles)=0; /* CAMERA API */ @@ -661,96 +541,80 @@ public: 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_transform(RID p_camera,const Transform& p_transform)=0; - - virtual void camera_set_visible_layers(RID p_camera,uint32_t p_layers)=0; - virtual uint32_t camera_get_visible_layers(RID p_camera) const=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; - virtual RID camera_get_environment(RID p_camera) const=0; - virtual void camera_set_use_vertical_aspect(RID p_camera,bool p_enable)=0; - virtual bool camera_is_using_vertical_aspect(RID p_camera,bool p_enable) const=0; /* - virtual void camera_add_layer(RID p_camera); - virtual void camera_layer_move_up(RID p_camera,int p_layer); - virtual void camera_layer_move_down(RID p_camera,int p_layer); - virtual void camera_layer_set_mask(RID p_camera,int p_layer,int p_mask); - virtual int camera_layer_get_mask(RID p_camera,int p_layer) const; - - enum CameraLayerFlag { - - FLAG_CLEAR_DEPTH, - FLAG_CLEAR_COLOR, - FLAG_IGNORE_FOG, + enum ParticlesCollisionMode { + PARTICLES_COLLISION_NONE, + PARTICLES_COLLISION_TEXTURE, + PARTICLES_COLLISION_CUBEMAP, }; - virtual void camera_layer_set_flag(RID p_camera,int p_layer,bool p_enable); - virtual bool camera_layer_get_flag(RID p_camera,int p_layer) const; + virtual void particles_set_collision(RID p_particles,ParticlesCollisionMode p_mode,const Transform&, p_xform,const RID p_depth_tex,const RID p_normal_tex)=0; */ - - - /* VIEWPORT API */ + /* VIEWPORT TARGET API */ virtual RID viewport_create()=0; - virtual void viewport_attach_to_screen(RID p_viewport,int p_screen=0)=0; + virtual void viewport_set_size(RID p_viewport,int p_width,int p_height)=0; + virtual void viewport_set_active(RID p_viewport,bool p_active)=0; + 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_detach(RID p_viewport)=0; - virtual void viewport_set_render_target_to_screen_rect(RID p_viewport,const Rect2& p_rect)=0; - enum RenderTargetUpdateMode { - RENDER_TARGET_UPDATE_DISABLED, - RENDER_TARGET_UPDATE_ONCE, //then goes to disabled - RENDER_TARGET_UPDATE_WHEN_VISIBLE, // default - RENDER_TARGET_UPDATE_ALWAYS + enum ViewportUpdateMode { + VIEWPORT_UPDATE_DISABLED, + VIEWPORT_UPDATE_ONCE, //then goes to disabled, must be manually updated + VIEWPORT_UPDATE_WHEN_VISIBLE, // default + VIEWPORT_UPDATE_ALWAYS }; - virtual void viewport_set_as_render_target(RID p_viewport,bool p_enable)=0; - virtual void viewport_set_render_target_update_mode(RID p_viewport,RenderTargetUpdateMode p_mode)=0; - virtual RenderTargetUpdateMode viewport_get_render_target_update_mode(RID p_viewport) const=0; - virtual RID viewport_get_render_target_texture(RID p_viewport) const=0; - virtual void viewport_set_render_target_vflip(RID p_viewport,bool p_enable)=0; - virtual bool viewport_get_render_target_vflip(RID p_viewport) const=0; - virtual void viewport_set_render_target_clear_on_new_frame(RID p_viewport,bool p_enable)=0; - virtual bool viewport_get_render_target_clear_on_new_frame(RID p_viewport) const=0; - virtual void viewport_render_target_clear(RID p_viewport)=0; - - virtual void viewport_queue_screen_capture(RID p_viewport)=0; - virtual Image viewport_get_screen_capture(RID p_viewport) const=0; - + virtual void viewport_set_update_mode(RID p_viewport,ViewportUpdateMode p_mode)=0; + virtual void viewport_set_vflip(RID p_viewport,bool p_enable)=0; + enum ViewportClearMode { - struct ViewportRect { - - int x,y,width,height; - ViewportRect() { x=y=width=height=0; } + VIEWPORT_CLEAR_ALWAYS, + VIEWPORT_CLEAR_NEVER, + VIEWPORT_CLEAR_ONLY_NEXT_FRAME }; - virtual void viewport_set_rect(RID p_viewport,const ViewportRect& p_rect)=0; - virtual ViewportRect viewport_get_rect(RID p_viewport) const=0; + virtual void viewport_set_clear_mode(RID p_viewport,ViewportClearMode p_clear_mode)=0; + + virtual RID viewport_get_texture(RID p_viewport) const=0; virtual void viewport_set_hide_scenario(RID p_viewport,bool p_hide)=0; virtual void viewport_set_hide_canvas(RID p_viewport,bool p_hide)=0; virtual void viewport_set_disable_environment(RID p_viewport,bool p_disable)=0; + virtual void viewport_set_disable_3d(RID p_viewport,bool p_disable)=0; virtual void viewport_attach_camera(RID p_viewport,RID p_camera)=0; virtual void viewport_set_scenario(RID p_viewport,RID p_scenario)=0; - virtual RID viewport_get_attached_camera(RID p_viewport) const=0; - virtual RID viewport_get_scenario(RID p_viewport) const=0; virtual void viewport_attach_canvas(RID p_viewport,RID p_canvas)=0; virtual void viewport_remove_canvas(RID p_viewport,RID p_canvas)=0; - virtual void viewport_set_canvas_transform(RID p_viewport,RID p_canvas,const Matrix32& p_offset)=0; - virtual Matrix32 viewport_get_canvas_transform(RID p_viewport,RID p_canvas) const=0; + virtual void viewport_set_canvas_transform(RID p_viewport,RID p_canvas,const Transform2D& p_offset)=0; virtual void viewport_set_transparent_background(RID p_viewport,bool p_enabled)=0; - virtual bool viewport_has_transparent_background(RID p_viewport) const=0; - - virtual void viewport_set_global_canvas_transform(RID p_viewport,const Matrix32& p_transform)=0; - virtual Matrix32 viewport_get_global_canvas_transform(RID p_viewport) const=0; + virtual void viewport_set_global_canvas_transform(RID p_viewport,const Transform2D& p_transform)=0; virtual void viewport_set_canvas_layer(RID p_viewport,RID p_canvas,int p_layer)=0; + virtual void viewport_set_shadow_atlas_size(RID p_viewport,int p_size)=0; + virtual void viewport_set_shadow_atlas_quadrant_subdivision(RID p_viewport,int p_quadrant,int p_subdiv)=0; + + enum ViewportMSAA { + VIEWPORT_MSAA_DISABLED, + VIEWPORT_MSAA_2X, + VIEWPORT_MSAA_4X, + VIEWPORT_MSAA_8X, + VIEWPORT_MSAA_16X, + }; + virtual void viewport_set_msaa(RID p_viewport,ViewportMSAA p_msaa)=0; + virtual void viewport_set_hdr(RID p_viewport,bool p_enabled)=0; /* ENVIRONMENT API */ @@ -758,104 +622,61 @@ public: enum EnvironmentBG { - ENV_BG_KEEP, - ENV_BG_DEFAULT_COLOR, + ENV_BG_CLEAR_COLOR, ENV_BG_COLOR, - ENV_BG_TEXTURE, - ENV_BG_CUBEMAP, + ENV_BG_SKYBOX, ENV_BG_CANVAS, + ENV_BG_KEEP, ENV_BG_MAX }; virtual void environment_set_background(RID p_env,EnvironmentBG p_bg)=0; - virtual EnvironmentBG environment_get_background(RID p_env) const=0; - - enum EnvironmentBGParam { - - ENV_BG_PARAM_CANVAS_MAX_LAYER, - ENV_BG_PARAM_COLOR, - ENV_BG_PARAM_TEXTURE, - ENV_BG_PARAM_CUBEMAP, - ENV_BG_PARAM_ENERGY, - ENV_BG_PARAM_SCALE, - ENV_BG_PARAM_GLOW, - ENV_BG_PARAM_MAX - }; + virtual void environment_set_skybox(RID p_env,RID p_skybox)=0; + virtual void environment_set_skybox_scale(RID p_env,float p_scale)=0; + virtual void environment_set_bg_color(RID p_env,const Color& p_color)=0; + virtual void environment_set_bg_energy(RID p_env,float p_energy)=0; + virtual void environment_set_canvas_max_layer(RID p_env,int p_max_layer)=0; + virtual void environment_set_ambient_light(RID p_env,const Color& p_color,float p_energy=1.0,float p_skybox_contribution=0.0)=0; + //set default SSAO options + //set default SSR options + //set default SSSSS options - virtual void environment_set_background_param(RID p_env,EnvironmentBGParam p_param, const Variant& p_value)=0; - virtual Variant environment_get_background_param(RID p_env,EnvironmentBGParam p_param) const=0; - - enum EnvironmentFx { - ENV_FX_AMBIENT_LIGHT, - ENV_FX_FXAA, - ENV_FX_GLOW, - ENV_FX_DOF_BLUR, - ENV_FX_HDR, - ENV_FX_FOG, - ENV_FX_BCS, - ENV_FX_SRGB, - ENV_FX_MAX + enum EnvironmentDOFBlurQuality { + ENV_DOF_BLUR_QUALITY_LOW, + ENV_DOF_BLUR_QUALITY_MEDIUM, + ENV_DOF_BLUR_QUALITY_HIGH, }; + virtual void environment_set_dof_blur_near(RID p_env,bool p_enable,float p_distance,float p_transition,float p_far_amount,EnvironmentDOFBlurQuality p_quality)=0; + virtual void environment_set_dof_blur_far(RID p_env,bool p_enable,float p_distance,float p_transition,float p_far_amount,EnvironmentDOFBlurQuality p_quality)=0; - - virtual void environment_set_enable_fx(RID p_env,EnvironmentFx p_effect,bool p_enabled)=0; - virtual bool environment_is_fx_enabled(RID p_env,EnvironmentFx p_mode) const=0; - - enum EnvironmentFxBlurBlendMode { - ENV_FX_BLUR_BLEND_MODE_ADDITIVE, - ENV_FX_BLUR_BLEND_MODE_SCREEN, - ENV_FX_BLUR_BLEND_MODE_SOFTLIGHT, + enum EnvironmentGlowBlendMode { + GLOW_BLEND_MODE_ADDITIVE, + GLOW_BLEND_MODE_SCREEN, + GLOW_BLEND_MODE_SOFTLIGHT, + GLOW_BLEND_MODE_REPLACE, }; + virtual void environment_set_glow(RID p_env,bool p_enable,int p_level_flags,float p_intensity,float p_strength,float p_bloom_treshold,EnvironmentGlowBlendMode p_blend_mode,float p_hdr_bleed_treshold,float p_hdr_bleed_scale,bool p_bicubic_upscale)=0; + virtual void environment_set_fog(RID p_env,bool p_enable,float p_begin,float p_end,RID p_gradient_texture)=0; - enum EnvironmentFxHDRToneMapper { - ENV_FX_HDR_TONE_MAPPER_LINEAR, - ENV_FX_HDR_TONE_MAPPER_LOG, - ENV_FX_HDR_TONE_MAPPER_REINHARDT, - ENV_FX_HDR_TONE_MAPPER_REINHARDT_AUTOWHITE, - }; - enum EnvironmentFxParam { - ENV_FX_PARAM_AMBIENT_LIGHT_COLOR, - ENV_FX_PARAM_AMBIENT_LIGHT_ENERGY, - ENV_FX_PARAM_GLOW_BLUR_PASSES, - ENV_FX_PARAM_GLOW_BLUR_SCALE, - ENV_FX_PARAM_GLOW_BLUR_STRENGTH, - ENV_FX_PARAM_GLOW_BLUR_BLEND_MODE, - ENV_FX_PARAM_GLOW_BLOOM, - ENV_FX_PARAM_GLOW_BLOOM_TRESHOLD, - ENV_FX_PARAM_DOF_BLUR_PASSES, - ENV_FX_PARAM_DOF_BLUR_BEGIN, - ENV_FX_PARAM_DOF_BLUR_RANGE, - ENV_FX_PARAM_HDR_TONEMAPPER, - ENV_FX_PARAM_HDR_EXPOSURE, - ENV_FX_PARAM_HDR_WHITE, - ENV_FX_PARAM_HDR_GLOW_TRESHOLD, - ENV_FX_PARAM_HDR_GLOW_SCALE, - ENV_FX_PARAM_HDR_MIN_LUMINANCE, - ENV_FX_PARAM_HDR_MAX_LUMINANCE, - ENV_FX_PARAM_HDR_EXPOSURE_ADJUST_SPEED, - ENV_FX_PARAM_FOG_BEGIN, - ENV_FX_PARAM_FOG_BEGIN_COLOR, - ENV_FX_PARAM_FOG_END_COLOR, - ENV_FX_PARAM_FOG_ATTENUATION, - ENV_FX_PARAM_FOG_BG, - ENV_FX_PARAM_BCS_BRIGHTNESS, - ENV_FX_PARAM_BCS_CONTRAST, - ENV_FX_PARAM_BCS_SATURATION, - ENV_FX_PARAM_MAX + enum EnvironmentToneMapper { + ENV_TONE_MAPPER_LINEAR, + ENV_TONE_MAPPER_REINHARDT, + ENV_TONE_MAPPER_FILMIC, + ENV_TONE_MAPPER_ACES }; - virtual void environment_fx_set_param(RID p_env,EnvironmentFxParam p_effect,const Variant& p_param)=0; - virtual Variant environment_fx_get_param(RID p_env,EnvironmentFxParam p_effect) const=0; + virtual void environment_set_tonemap(RID p_env,EnvironmentToneMapper p_tone_mapper,float p_exposure,float p_white,bool p_auto_exposure,float p_min_luminance,float p_max_luminance,float p_auto_exp_speed,float p_auto_exp_grey)=0; + virtual void environment_set_adjustment(RID p_env,bool p_enable,float p_brightness,float p_contrast,float p_saturation,RID p_ramp)=0; + virtual void environment_set_ssr(RID p_env,bool p_enable, int p_max_steps,float p_accel,float p_fade,float p_depth_tolerance,bool p_smooth,bool p_roughness)=0; + virtual void environment_set_ssao(RID p_env,bool p_enable, float p_radius, float p_intensity, float p_radius2, float p_intensity2, float p_bias, float p_light_affect,const Color &p_color,bool p_blur)=0; /* SCENARIO API */ - - virtual RID scenario_create()=0; enum ScenarioDebugMode { @@ -869,7 +690,7 @@ public: virtual void scenario_set_debug(RID p_scenario,ScenarioDebugMode p_debug_mode)=0; virtual void scenario_set_environment(RID p_scenario, RID p_environment)=0; - virtual RID scenario_get_environment(RID p_scenario, RID p_environment) const=0; + virtual void scenario_set_reflection_atlas_size(RID p_scenario, int p_size,int p_subdiv)=0; virtual void scenario_set_fallback_environment(RID p_scenario, RID p_environment)=0; @@ -883,67 +704,47 @@ public: INSTANCE_IMMEDIATE, INSTANCE_PARTICLES, INSTANCE_LIGHT, + INSTANCE_REFLECTION_PROBE, INSTANCE_ROOM, INSTANCE_PORTAL, - INSTANCE_BAKED_LIGHT, - INSTANCE_BAKED_LIGHT_SAMPLER, + INSTANCE_GI_PROBE, + INSTANCE_MAX, + /*INSTANCE_BAKED_LIGHT_SAMPLER,*/ - INSTANCE_GEOMETRY_MASK=(1<<INSTANCE_MESH)|(1<<INSTANCE_MULTIMESH)|(1<<INSTANCE_IMMEDIATE)|(1<<INSTANCE_PARTICLES) + INSTANCE_GEOMETRY_MASK=(1<<INSTANCE_MESH)|(1<<INSTANCE_MULTIMESH)|(1<<INSTANCE_IMMEDIATE) }; virtual RID instance_create2(RID p_base, RID p_scenario); -// virtual RID instance_create(RID p_base,RID p_scenario)=0; // from can be mesh, light, area and portal so far. + //virtual RID instance_create(RID p_base,RID p_scenario)=0; // from can be mesh, light, area and portal so far. virtual RID instance_create()=0; // from can be mesh, light, poly, area and portal so far. virtual void instance_set_base(RID p_instance, RID p_base)=0; // from can be mesh, light, poly, area and portal so far. - virtual RID instance_get_base(RID p_instance) const=0; - virtual void instance_set_scenario(RID p_instance, RID p_scenario)=0; // from can be mesh, light, poly, area and portal so far. - virtual RID instance_get_scenario(RID p_instance) const=0; - virtual void instance_set_layer_mask(RID p_instance, uint32_t p_mask)=0; - virtual uint32_t instance_get_layer_mask(RID p_instance) const=0; - - virtual AABB instance_get_base_aabb(RID p_instance) const=0; - virtual void instance_set_transform(RID p_instance, const Transform& p_transform)=0; - virtual Transform instance_get_transform(RID p_instance) const=0; - - - virtual void instance_attach_object_instance_ID(RID p_instance,uint32_t p_ID)=0; - virtual uint32_t instance_get_object_instance_ID(RID p_instance) const=0; - - virtual void instance_set_morph_target_weight(RID p_instance,int p_shape, float p_weight)=0; - virtual float instance_get_morph_target_weight(RID p_instance,int p_shape) const=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; virtual void instance_attach_skeleton(RID p_instance,RID p_skeleton)=0; - virtual RID instance_get_skeleton(RID p_instance) const=0; - virtual void instance_set_exterior( RID p_instance, bool p_enabled )=0; - virtual bool instance_is_exterior( RID p_instance) const=0; - virtual void instance_set_room( RID p_instance, RID p_room )=0; - virtual RID instance_get_room( RID p_instance ) const =0; virtual void instance_set_extra_visibility_margin( RID p_instance, real_t p_margin )=0; - virtual real_t instance_get_extra_visibility_margin( RID p_instance ) const =0; // don't use these in a game! - virtual Vector<RID> instances_cull_aabb(const AABB& p_aabb, RID p_scenario=RID()) const=0; - virtual Vector<RID> instances_cull_ray(const Vector3& p_from, const Vector3& p_to, RID p_scenario=RID()) const=0; - virtual Vector<RID> instances_cull_convex(const Vector<Plane>& p_convex, RID p_scenario=RID()) const=0; + virtual Vector<ObjectID> instances_cull_aabb(const Rect3& p_aabb, RID p_scenario=RID()) const=0; + virtual Vector<ObjectID> instances_cull_ray(const Vector3& p_from, const Vector3& p_to, RID p_scenario=RID()) const=0; + virtual Vector<ObjectID> instances_cull_convex(const Vector<Plane>& p_convex, RID p_scenario=RID()) const=0; enum InstanceFlags { - INSTANCE_FLAG_VISIBLE, INSTANCE_FLAG_BILLBOARD, INSTANCE_FLAG_BILLBOARD_FIX_Y, INSTANCE_FLAG_CAST_SHADOW, - INSTANCE_FLAG_RECEIVE_SHADOWS, INSTANCE_FLAG_DEPH_SCALE, INSTANCE_FLAG_VISIBLE_IN_ALL_ROOMS, INSTANCE_FLAG_USE_BAKED_LIGHT, @@ -958,80 +759,53 @@ public: }; virtual void instance_geometry_set_flag(RID p_instance,InstanceFlags p_flags,bool p_enabled)=0; - virtual bool instance_geometry_get_flag(RID p_instance,InstanceFlags p_flags) const=0; - virtual void instance_geometry_set_cast_shadows_setting(RID p_instance, ShadowCastingSetting p_shadow_casting_setting) = 0; - virtual ShadowCastingSetting instance_geometry_get_cast_shadows_setting(RID p_instance) const = 0; - virtual void instance_geometry_set_material_override(RID p_instance, RID p_material)=0; - virtual RID instance_geometry_get_material_override(RID p_instance) const=0; - - virtual void instance_geometry_set_draw_range(RID p_instance,float p_min,float p_max)=0; - virtual float instance_geometry_get_draw_range_max(RID p_instance) const=0; - virtual float instance_geometry_get_draw_range_min(RID p_instance) const=0; - - virtual void instance_geometry_set_baked_light(RID p_instance,RID p_baked_light)=0; - virtual RID instance_geometry_get_baked_light(RID p_instance) const=0; - virtual void instance_geometry_set_baked_light_sampler(RID p_instance,RID p_baked_light_sampler)=0; - virtual RID instance_geometry_get_baked_light_sampler(RID p_instance) const=0; - virtual void instance_geometry_set_baked_light_texture_index(RID p_instance,int p_tex_id)=0; - virtual int instance_geometry_get_baked_light_texture_index(RID p_instance) const=0; - - - virtual void instance_light_set_enabled(RID p_instance,bool p_enabled)=0; - virtual bool instance_light_is_enabled(RID p_instance) const=0; + virtual void instance_geometry_set_draw_range(RID p_instance,float p_min,float p_max,float p_min_margin,float p_max_margin)=0; + virtual void instance_geometry_set_as_instance_lod(RID p_instance,RID p_as_lod_of_instance)=0; /* CANVAS (2D) */ virtual RID canvas_create()=0; virtual void canvas_set_item_mirroring(RID p_canvas,RID p_item,const Point2& p_mirroring)=0; - virtual Point2 canvas_get_item_mirroring(RID p_canvas,RID p_item) const=0; virtual void canvas_set_modulate(RID p_canvas,const Color& p_color)=0; - virtual RID canvas_item_create()=0; virtual void canvas_item_set_parent(RID p_item,RID p_parent)=0; - virtual RID canvas_item_get_parent(RID p_canvas_item) const=0; virtual void canvas_item_set_visible(RID p_item,bool p_visible)=0; - virtual bool canvas_item_is_visible(RID p_item) const=0; - virtual void canvas_item_set_light_mask(RID p_item,int p_mask)=0; - virtual void canvas_item_set_blend_mode(RID p_canvas_item,MaterialBlendMode p_blend)=0; - - virtual void canvas_item_attach_viewport(RID p_item, RID p_viewport)=0; - - //virtual void canvas_item_set_rect(RID p_item, const Rect2& p_rect)=0; - - virtual void canvas_item_set_transform(RID p_item, const Matrix32& p_transform)=0; + virtual void canvas_item_set_transform(RID p_item, const Transform2D& p_transform)=0; virtual void canvas_item_set_clip(RID p_item, bool p_clip)=0; virtual void canvas_item_set_distance_field_mode(RID p_item, bool p_enable)=0; virtual void canvas_item_set_custom_rect(RID p_item, bool p_custom_rect,const Rect2& p_rect=Rect2())=0; - virtual void canvas_item_set_opacity(RID p_item, float p_opacity)=0; - virtual float canvas_item_get_opacity(RID p_item, float p_opacity) const=0; + virtual void canvas_item_set_modulate(RID p_item, const Color& p_color)=0; + virtual void canvas_item_set_self_modulate(RID p_item, const Color& p_color)=0; - virtual void canvas_item_set_self_opacity(RID p_item, float p_self_opacity)=0; - virtual float canvas_item_get_self_opacity(RID p_item, float p_self_opacity) const=0; + virtual void canvas_item_set_draw_behind_parent(RID p_item, bool p_enable)=0; - virtual void canvas_item_set_on_top(RID p_item, bool p_on_top)=0; - virtual bool canvas_item_is_on_top(RID p_item) const=0; + enum NinePatchAxisMode { + NINE_PATCH_STRETCH, + NINE_PATCH_TILE, + NINE_PATCH_TILE_FIT, + }; virtual void canvas_item_add_line(RID p_item, const Point2& p_from, const Point2& p_to,const Color& p_color,float p_width=1.0,bool p_antialiased=false)=0; virtual void canvas_item_add_rect(RID p_item, const Rect2& p_rect, const Color& p_color)=0; virtual void canvas_item_add_circle(RID p_item, const Point2& p_pos, float p_radius,const Color& p_color)=0; virtual void canvas_item_add_texture_rect(RID p_item, const Rect2& p_rect, RID p_texture,bool p_tile=false,const Color& p_modulate=Color(1,1,1),bool p_transpose=false)=0; virtual void canvas_item_add_texture_rect_region(RID p_item, const Rect2& p_rect, RID p_texture,const Rect2& p_src_rect,const Color& p_modulate=Color(1,1,1),bool p_transpose=false)=0; - virtual void canvas_item_add_style_box(RID p_item, const Rect2& p_rect, const Rect2& p_source, RID p_texture,const Vector2& p_topleft, const Vector2& p_bottomright, bool p_draw_center=true,const Color& p_modulate=Color(1,1,1))=0; + virtual void canvas_item_add_nine_patch(RID p_item, const Rect2& p_rect, const Rect2& p_source, RID p_texture,const Vector2& p_topleft, const Vector2& p_bottomright,NinePatchAxisMode p_x_axis_mode=NINE_PATCH_STRETCH, NinePatchAxisMode p_y_axis_mode=NINE_PATCH_STRETCH,bool p_draw_center=true,const Color& p_modulate=Color(1,1,1))=0; 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)=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())=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>(), RID p_texture=RID(), int p_count=-1)=0; - virtual void canvas_item_add_triangle_array_ptr(RID p_item, int p_count, const int* p_indices, const Point2* p_points, const Color* p_colors,const Point2* p_uvs=NULL, RID p_texture=RID())=0; - virtual void canvas_item_add_set_transform(RID p_item,const Matrix32& p_transform)=0; - virtual void canvas_item_add_set_blend_mode(RID p_item, MaterialBlendMode p_blend)=0; + virtual void canvas_item_add_mesh(RID p_item, const RID& p_mesh,RID p_skeleton=RID())=0; + virtual void canvas_item_add_multimesh(RID p_item, RID p_mesh,RID p_skeleton=RID())=0; + virtual void canvas_item_add_set_transform(RID p_item,const Transform2D& p_transform)=0; virtual void canvas_item_add_clip_ignore(RID p_item, bool p_ignore)=0; virtual void canvas_item_set_sort_children_by_y(RID p_item, bool p_enable)=0; virtual void canvas_item_set_z(RID p_item, int p_z)=0; @@ -1039,7 +813,7 @@ public: virtual void canvas_item_set_copy_to_backbuffer(RID p_item, bool p_enable,const Rect2& p_rect)=0; virtual void canvas_item_clear(RID p_item)=0; - virtual void canvas_item_raise(RID p_item)=0; + virtual void canvas_item_set_draw_index(RID p_item,int p_index)=0; virtual void canvas_item_set_material(RID p_item, RID p_material)=0; @@ -1049,7 +823,7 @@ public: virtual void canvas_light_attach_to_canvas(RID p_light,RID p_canvas)=0; virtual void canvas_light_set_enabled(RID p_light, bool p_enabled)=0; virtual void canvas_light_set_scale(RID p_light, float p_scale)=0; - virtual void canvas_light_set_transform(RID p_light, const Matrix32& p_transform)=0; + virtual void canvas_light_set_transform(RID p_light, const Transform2D& p_transform)=0; virtual void canvas_light_set_texture(RID p_light, RID p_texture)=0; virtual void canvas_light_set_texture_offset(RID p_light, const Vector2& p_offset)=0; virtual void canvas_light_set_color(RID p_light, const Color& p_color)=0; @@ -1057,8 +831,8 @@ public: virtual void canvas_light_set_energy(RID p_light, float p_energy)=0; virtual void canvas_light_set_z_range(RID p_light, int p_min_z,int p_max_z)=0; virtual void canvas_light_set_layer_range(RID p_light, int p_min_layer,int p_max_layer)=0; - virtual void canvas_light_set_item_mask(RID p_light, int p_mask)=0; - virtual void canvas_light_set_item_shadow_mask(RID p_light, int p_mask)=0; + virtual void canvas_light_set_item_cull_mask(RID p_light, int p_mask)=0; + virtual void canvas_light_set_item_shadow_cull_mask(RID p_light, int p_mask)=0; enum CanvasLightMode { CANVAS_LIGHT_MODE_ADD, @@ -1068,9 +842,20 @@ public: }; virtual void canvas_light_set_mode(RID p_light, CanvasLightMode p_mode)=0; + + + enum CanvasLightShadowFilter { + CANVAS_LIGHT_FILTER_NONE, + CANVAS_LIGHT_FILTER_PCF3, + CANVAS_LIGHT_FILTER_PCF5, + CANVAS_LIGHT_FILTER_PCF9, + CANVAS_LIGHT_FILTER_PCF13, + }; + virtual void canvas_light_set_shadow_enabled(RID p_light, bool p_enabled)=0; virtual void canvas_light_set_shadow_buffer_size(RID p_light, int p_size)=0; - virtual void canvas_light_set_shadow_esm_multiplier(RID p_light, float p_multiplier)=0; + virtual void canvas_light_set_shadow_gradient_length(RID p_light, float p_length)=0; + virtual void canvas_light_set_shadow_filter(RID p_light, CanvasLightShadowFilter p_filter)=0; virtual void canvas_light_set_shadow_color(RID p_light, const Color& p_color)=0; @@ -1079,12 +864,13 @@ public: virtual void canvas_light_occluder_attach_to_canvas(RID p_occluder,RID p_canvas)=0; virtual void canvas_light_occluder_set_enabled(RID p_occluder,bool p_enabled)=0; virtual void canvas_light_occluder_set_polygon(RID p_occluder,RID p_polygon)=0; - virtual void canvas_light_occluder_set_transform(RID p_occluder,const Matrix32& p_xform)=0; + virtual void canvas_light_occluder_set_transform(RID p_occluder,const Transform2D& p_xform)=0; virtual void canvas_light_occluder_set_light_mask(RID p_occluder,int p_mask)=0; virtual RID canvas_occluder_polygon_create()=0; - virtual void canvas_occluder_polygon_set_shape(RID p_occluder_polygon,const DVector<Vector2>& p_shape,bool p_closed)=0; - virtual void canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon,const DVector<Vector2>& p_shape)=0; + virtual void canvas_occluder_polygon_set_shape(RID p_occluder_polygon,const PoolVector<Vector2>& p_shape,bool p_closed)=0; + virtual void canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon,const PoolVector<Vector2>& p_shape)=0; + enum CanvasOccluderPolygonCullMode { CANVAS_OCCLUDER_POLYGON_CULL_DISABLED, CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE, @@ -1092,21 +878,6 @@ public: }; virtual void canvas_occluder_polygon_set_cull_mode(RID p_occluder_polygon,CanvasOccluderPolygonCullMode p_mode)=0; - /* CANVAS ITEM MATERIAL */ - - virtual RID canvas_item_material_create()=0; - virtual void canvas_item_material_set_shader(RID p_material, RID p_shader)=0; - virtual void canvas_item_material_set_shader_param(RID p_material, const StringName& p_param, const Variant& p_value)=0; - virtual Variant canvas_item_material_get_shader_param(RID p_material, const StringName& p_param) const=0; - - - enum CanvasItemShadingMode { - CANVAS_ITEM_SHADING_NORMAL, - CANVAS_ITEM_SHADING_UNSHADED, - CANVAS_ITEM_SHADING_ONLY_LIGHT, - }; - - virtual void canvas_item_material_set_shading_mode(RID p_material, CanvasItemShadingMode p_mode)=0; /* CURSOR */ virtual void cursor_set_rotation(float p_rotation, int p_cursor = 0)=0; // radians @@ -1125,15 +896,6 @@ public: virtual void free( RID p_rid )=0; ///< free RIDs associated with the visual server - /* CUSTOM SHADING */ - - virtual void custom_shade_model_set_shader(int p_model, RID p_shader)=0; - virtual RID custom_shade_model_get_shader(int p_model) const=0; - virtual void custom_shade_model_set_name(int p_model, const String& p_name)=0; - virtual String custom_shade_model_get_name(int p_model) const=0; - virtual void custom_shade_model_set_param_info(int p_model, const List<PropertyInfo>& p_info)=0; - virtual void custom_shade_model_get_param_info(int p_model, List<PropertyInfo>* p_info) const=0; - /* EVENT QUEUING */ virtual void draw()=0; @@ -1166,7 +928,6 @@ public: RID material_2d_get(bool p_shaded, bool p_transparent, bool p_cut_alpha,bool p_opaque_prepass); - /* TESTING */ virtual RID get_test_cube()=0; @@ -1177,7 +938,7 @@ public: virtual RID make_sphere_mesh(int p_lats,int p_lons,float p_radius); virtual void mesh_add_surface_from_mesh_data( RID p_mesh, const Geometry::MeshData& p_mesh_data); - virtual void mesh_add_surface_from_planes( RID p_mesh, const DVector<Plane>& p_planes); + virtual void mesh_add_surface_from_planes( RID p_mesh, const PoolVector<Plane>& p_planes); virtual void set_boot_image(const Image& p_image, const Color& p_color,bool p_scale)=0; virtual void set_default_clear_color(const Color& p_color)=0; @@ -1185,11 +946,12 @@ public: enum Features { FEATURE_SHADERS, FEATURE_MULTITHREADED, - FEATURE_NEEDS_RELOAD_HOOK, }; virtual bool has_feature(Features p_feature) const=0; + virtual bool has_os_feature(const String& p_feature) const=0; + VisualServer(); virtual ~VisualServer(); @@ -1200,19 +962,15 @@ public: VARIANT_ENUM_CAST( VisualServer::CubeMapSide ); VARIANT_ENUM_CAST( VisualServer::TextureFlags ); VARIANT_ENUM_CAST( VisualServer::ShaderMode ); -VARIANT_ENUM_CAST( VisualServer::MaterialFlag ); -VARIANT_ENUM_CAST( VisualServer::MaterialBlendMode ); -VARIANT_ENUM_CAST( VisualServer::ParticleVariable ); VARIANT_ENUM_CAST( VisualServer::ArrayType ); VARIANT_ENUM_CAST( VisualServer::ArrayFormat ); VARIANT_ENUM_CAST( VisualServer::PrimitiveType ); VARIANT_ENUM_CAST( VisualServer::LightType ); -VARIANT_ENUM_CAST( VisualServer::LightColor ); VARIANT_ENUM_CAST( VisualServer::LightParam ); VARIANT_ENUM_CAST( VisualServer::ScenarioDebugMode ); VARIANT_ENUM_CAST( VisualServer::InstanceType ); VARIANT_ENUM_CAST( VisualServer::RenderInfo ); -VARIANT_ENUM_CAST( VisualServer::MipMapPolicy ); + //typedef VisualServer VS; // makes it easier to use #define VS VisualServer |