diff options
author | Juan Linietsky <reduzio@gmail.com> | 2014-06-11 10:41:03 -0300 |
---|---|---|
committer | Juan Linietsky <reduzio@gmail.com> | 2014-06-11 10:41:03 -0300 |
commit | 9b8696d3dd92e2ed6f310ad0f0bf3c2182c9c6ae (patch) | |
tree | b2ed0515196bb774504b54aab0bf242992ac3d9f | |
parent | 6f0b4678e26c04abfc88c0226c803e78a108de98 (diff) |
Light Baker!
-=-=-=-=-=-=
-Support for lightmap baker, have fun figuring out how it works before tutorial is published.
61 files changed, 4245 insertions, 1423 deletions
diff --git a/SConstruct b/SConstruct index a5489d1534..19c5d8ce8a 100644 --- a/SConstruct +++ b/SConstruct @@ -169,6 +169,7 @@ if (env_base['target']=='debug'): env_base.platforms = {} + for p in platform_list: if env_base['platform'] != "" and env_base['platform'] != p: diff --git a/core/SCsub b/core/SCsub index 9a86c2943d..7eace22b73 100644 --- a/core/SCsub +++ b/core/SCsub @@ -19,9 +19,37 @@ f = open("global_defaults.cpp","wb") f.write(gd_cpp) f.close() +import os +txt = "0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0" +if ("SCRIPT_AES256_ENCRYPTION_KEY" in os.environ): + e=os.environ["SCRIPT_AES256_ENCRYPTION_KEY"] + txt = "" + ec_valid=True + if (len(e)!=64): + ec_valid=False + else: + + for i in range(len(e)>>1): + if (i>0): + txt+="," + txts="0x"+e[i*2:i*2+2] + try: + int(txts,16) + except: + ec_valid=False + txt+=txts + if (not ec_valid): + txt = "0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0" + print("Invalid AES256 encryption key, not 64 bits hex: "+e) + +f = open("script_encryption_key.cpp", "wb") +f.write("#include \"globals.h\"\nuint8_t script_encryption_key[32]={" + txt + "};\n") +f.close() + env.add_source_files(env.core_sources,"*.cpp") + Export('env') import make_binders diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp index 960cdbac20..8d6662157d 100644 --- a/core/bind/core_bind.cpp +++ b/core/bind/core_bind.cpp @@ -1418,7 +1418,7 @@ String _Marshalls::variant_to_base64(const Variant& p_var) { err = encode_variant(p_var,&w[0],len); ERR_FAIL_COND_V( err != OK, "" ); - int b64len = len / 3 * 4 + 4; + int b64len = len / 3 * 4 + 4 + 1; DVector<uint8_t> b64buff; b64buff.resize(b64len); DVector<uint8_t>::Write w64 = b64buff.write(); @@ -1437,7 +1437,7 @@ Variant _Marshalls::base64_to_variant(const String& p_str) { CharString cstr = p_str.ascii(); DVector<uint8_t> buf; - buf.resize(strlen / 4 * 3); + buf.resize(strlen / 4 * 3 + 1); DVector<uint8_t>::Write w = buf.write(); int len = base64_decode((char*)(&w[0]), (char*)cstr.get_data(), strlen); diff --git a/core/image.cpp b/core/image.cpp index db20862af5..b577117f1e 100644 --- a/core/image.cpp +++ b/core/image.cpp @@ -1399,14 +1399,17 @@ int Image::get_format_pallete_size(Format p_format) { } -void Image::decompress() { +Error Image::decompress() { if (format>=FORMAT_BC1 && format<=FORMAT_BC5 && _image_decompress_bc) _image_decompress_bc(this); - if (format>=FORMAT_PVRTC2 && format<=FORMAT_PVRTC4_ALPHA && _image_decompress_pvrtc) + else if (format>=FORMAT_PVRTC2 && format<=FORMAT_PVRTC4_ALPHA && _image_decompress_pvrtc) _image_decompress_pvrtc(this); - if (format==FORMAT_ETC && _image_decompress_etc) + else if (format==FORMAT_ETC && _image_decompress_etc) _image_decompress_etc(this); + else + return ERR_UNAVAILABLE; + return OK; } diff --git a/core/image.h b/core/image.h index 99300fc3af..87f851959c 100644 --- a/core/image.h +++ b/core/image.h @@ -45,8 +45,8 @@ class Image { enum { - MAX_WIDTH=4096, // force a limit somehow - MAX_HEIGHT=4096 // force a limit somehow + MAX_WIDTH=16384, // force a limit somehow + MAX_HEIGHT=16384// force a limit somehow }; public: @@ -317,7 +317,7 @@ public: Error compress(CompressMode p_mode=COMPRESS_BC); Image compressed(int p_mode); /* from the Image::CompressMode enum */ - void decompress(); + Error decompress(); void fix_alpha_edges(); void premultiply_alpha(); diff --git a/core/io/resource_format_xml.cpp b/core/io/resource_format_xml.cpp index f3c0f1cb8b..dae95097d3 100644 --- a/core/io/resource_format_xml.cpp +++ b/core/io/resource_format_xml.cpp @@ -193,7 +193,9 @@ Error ResourceInteractiveLoaderXML::close_tag(const String& p_name) { void ResourceInteractiveLoaderXML::unquote(String& p_str) { - p_str=p_str.strip_edges(); + p_str=p_str.strip_edges().replace("\"","").xml_unescape(); + + /*p_str=p_str.strip_edges(); p_str=p_str.replace("\"",""); p_str=p_str.replace(">","<"); p_str=p_str.replace("<",">"); @@ -205,7 +207,7 @@ void ResourceInteractiveLoaderXML::unquote(String& p_str) { p_str=p_str.replace("&#"+String::num(i)+";",chr); } p_str=p_str.replace("&","&"); - +*/ //p_str.parse_utf8( p_str.ascii(true).get_data() ); } @@ -652,11 +654,14 @@ Error ResourceInteractiveLoaderXML::parse_property(Variant& r_v, String &r_name) while( idx<len*2) { CharType c=get_char(); + if (c<=32) + continue; if (idx&1) { byte|=HEX2CHR(c); bytesptr[idx>>1]=byte; + //printf("%x\n",int(byte)); } else { byte=HEX2CHR(c)<<4; diff --git a/core/io/resource_format_xml.h b/core/io/resource_format_xml.h index 7874431a38..cfa4744915 100644 --- a/core/io/resource_format_xml.h +++ b/core/io/resource_format_xml.h @@ -68,7 +68,7 @@ friend class ResourceFormatLoaderXML; List<RES> resource_cache; Tag* parse_tag(bool* r_exit=NULL,bool p_printerr=true); Error close_tag(const String& p_name); - void unquote(String& p_str); + _FORCE_INLINE_ void unquote(String& p_str); Error goto_end_of_tag(); Error parse_property_data(String &r_data); Error parse_property(Variant& r_v, String &r_name); diff --git a/core/math/aabb.cpp b/core/math/aabb.cpp index 0d454cd07d..576e4fa928 100644 --- a/core/math/aabb.cpp +++ b/core/math/aabb.cpp @@ -335,15 +335,6 @@ AABB AABB::grow(real_t p_by) const { aabb.grow_by(p_by); return aabb; } -void AABB::grow_by(real_t p_amount) { - - pos.x-=p_amount; - pos.y-=p_amount; - pos.z-=p_amount; - size.x+=2.0*p_amount; - size.y+=2.0*p_amount; - size.z+=2.0*p_amount; -} void AABB::get_edge(int p_edge,Vector3& r_from,Vector3& r_to) const { diff --git a/core/math/aabb.h b/core/math/aabb.h index 87be03cf16..089d5d15f7 100644 --- a/core/math/aabb.h +++ b/core/math/aabb.h @@ -73,6 +73,8 @@ public: AABB intersection(const AABB& p_aabb) const; ///get box where two intersect, empty if no intersection occurs bool intersects_segment(const Vector3& p_from, const Vector3& p_to,Vector3* r_clip=NULL,Vector3* r_normal=NULL) const; bool intersects_ray(const Vector3& p_from, const Vector3& p_dir,Vector3* r_clip=NULL,Vector3* r_normal=NULL) const; + _FORCE_INLINE_ bool smits_intersect_ray(const Vector3 &from,const Vector3& p_dir, float t0, float t1) const; + _FORCE_INLINE_ bool intersects_convex_shape(const Plane *p_plane, int p_plane_count) const; bool intersects_plane(const Plane &p_plane) const; @@ -89,7 +91,7 @@ public: _FORCE_INLINE_ real_t get_shortest_axis_size() const; AABB grow(real_t p_by) const; - void grow_by(real_t p_amount); + _FORCE_INLINE_ void grow_by(real_t p_amount); void get_edge(int p_edge,Vector3& r_from,Vector3& r_to) const; _FORCE_INLINE_ Vector3 get_endpoint(int p_point) const; @@ -314,6 +316,63 @@ inline real_t AABB::get_shortest_axis_size() const { return max_size; } +bool AABB::smits_intersect_ray(const Vector3 &from,const Vector3& dir, float t0, float t1) const { + + float divx=1.0/dir.x; + float divy=1.0/dir.y; + float divz=1.0/dir.z; + + Vector3 upbound=pos+size; + float tmin, tmax, tymin, tymax, tzmin, tzmax; + if (dir.x >= 0) { + tmin = (pos.x - from.x) * divx; + tmax = (upbound.x - from.x) * divx; + } + else { + tmin = (upbound.x - from.x) * divx; + tmax = (pos.x - from.x) * divx; + } + if (dir.y >= 0) { + tymin = (pos.y - from.y) * divy; + tymax = (upbound.y - from.y) * divy; + } + else { + tymin = (upbound.y - from.y) * divy; + tymax = (pos.y - from.y) * divy; + } + if ( (tmin > tymax) || (tymin > tmax) ) + return false; + if (tymin > tmin) + tmin = tymin; + if (tymax < tmax) + tmax = tymax; + if (dir.z >= 0) { + tzmin = (pos.z - from.z) * divz; + tzmax = (upbound.z - from.z) * divz; + } + else { + tzmin = (upbound.z - from.z) * divz; + tzmax = (pos.z - from.z) * divz; + } + if ( (tmin > tzmax) || (tzmin > tmax) ) + return false; + if (tzmin > tmin) + tmin = tzmin; + if (tzmax < tmax) + tmax = tzmax; + return ( (tmin < t1) && (tmax > t0) ); +} + +void AABB::grow_by(real_t p_amount) { + + pos.x-=p_amount; + pos.y-=p_amount; + pos.z-=p_amount; + size.x+=2.0*p_amount; + size.y+=2.0*p_amount; + size.z+=2.0*p_amount; +} + typedef AABB Rect3; #endif // AABB_H diff --git a/core/math/face3.cpp b/core/math/face3.cpp index 9cdf31ed84..814f2d675d 100644 --- a/core/math/face3.cpp +++ b/core/math/face3.cpp @@ -247,7 +247,7 @@ bool Face3::intersects_aabb(const AABB& p_aabb) const { p_aabb.get_edge(i,from,to); Vector3 e1=from-to; for (int j=0;j<3;j++) { - Vector3 e2=edge_norms[i]; + Vector3 e2=edge_norms[j]; Vector3 axis=vec3_cross( e1, e2 ); diff --git a/core/math/face3.h b/core/math/face3.h index 3a62f7f812..630c408de3 100644 --- a/core/math/face3.h +++ b/core/math/face3.h @@ -86,6 +86,7 @@ public: } bool intersects_aabb(const AABB& p_aabb) const; + _FORCE_INLINE_ bool intersects_aabb2(const AABB& p_aabb) const; operator String() const; inline Face3() {} @@ -94,4 +95,172 @@ public: }; +bool Face3::intersects_aabb2(const AABB& p_aabb) const { + + Vector3 perp = (vertex[0]-vertex[2]).cross(vertex[0]-vertex[1]); + + Vector3 half_extents = p_aabb.size * 0.5; + Vector3 ofs = p_aabb.pos + half_extents; + + Vector3 sup =Vector3( + (perp.x>0) ? -half_extents.x : half_extents.x, + (perp.y>0) ? -half_extents.y : half_extents.y, + (perp.z>0) ? -half_extents.z : half_extents.z + ); + + float d = perp.dot(vertex[0]); + float dist_a = perp.dot(ofs+sup)-d; + float dist_b = perp.dot(ofs-sup)-d; + + if (dist_a*dist_b > 0) + return false; //does not intersect the plane + + +#define TEST_AXIS(m_ax)\ + {\ + float aabb_min=p_aabb.pos.m_ax;\ + float aabb_max=p_aabb.pos.m_ax+p_aabb.size.m_ax;\ + float tri_min,tri_max;\ + for (int i=0;i<3;i++) {\ + if (i==0 || vertex[i].m_ax > tri_max)\ + tri_max=vertex[i].m_ax;\ + if (i==0 || vertex[i].m_ax < tri_min)\ + tri_min=vertex[i].m_ax;\ + }\ +\ + if (tri_max<aabb_min || aabb_max<tri_min)\ + return false;\ + } + + TEST_AXIS(x); + TEST_AXIS(y); + TEST_AXIS(z); + +#undef TEST_AXIS + + + Vector3 edge_norms[3]={ + vertex[0]-vertex[1], + vertex[1]-vertex[2], + vertex[2]-vertex[0], + }; + + for (int i=0;i<12;i++) { + + Vector3 from,to; + switch(i) { + + case 0:{ + + from=Vector3( p_aabb.pos.x+p_aabb.size.x , p_aabb.pos.y , p_aabb.pos.z ); + to=Vector3( p_aabb.pos.x , p_aabb.pos.y , p_aabb.pos.z ); + } break; + case 1:{ + + from=Vector3( p_aabb.pos.x+p_aabb.size.x , p_aabb.pos.y , p_aabb.pos.z+p_aabb.size.z ); + to=Vector3( p_aabb.pos.x+p_aabb.size.x , p_aabb.pos.y , p_aabb.pos.z ); + } break; + case 2:{ + from=Vector3( p_aabb.pos.x , p_aabb.pos.y , p_aabb.pos.z+p_aabb.size.z ); + to=Vector3( p_aabb.pos.x+p_aabb.size.x , p_aabb.pos.y , p_aabb.pos.z+p_aabb.size.z ); + + } break; + case 3:{ + + from=Vector3( p_aabb.pos.x , p_aabb.pos.y , p_aabb.pos.z ); + to=Vector3( p_aabb.pos.x , p_aabb.pos.y , p_aabb.pos.z+p_aabb.size.z ); + + } break; + case 4:{ + + from=Vector3( p_aabb.pos.x , p_aabb.pos.y+p_aabb.size.y , p_aabb.pos.z ); + to=Vector3( p_aabb.pos.x+p_aabb.size.x , p_aabb.pos.y+p_aabb.size.y , p_aabb.pos.z ); + } break; + case 5:{ + + from=Vector3( p_aabb.pos.x+p_aabb.size.x , p_aabb.pos.y+p_aabb.size.y , p_aabb.pos.z ); + to=Vector3( p_aabb.pos.x+p_aabb.size.x , p_aabb.pos.y+p_aabb.size.y , p_aabb.pos.z+p_aabb.size.z ); + } break; + case 6:{ + from=Vector3( p_aabb.pos.x+p_aabb.size.x , p_aabb.pos.y+p_aabb.size.y , p_aabb.pos.z+p_aabb.size.z ); + to=Vector3( p_aabb.pos.x , p_aabb.pos.y+p_aabb.size.y , p_aabb.pos.z+p_aabb.size.z ); + + } break; + case 7:{ + + from=Vector3( p_aabb.pos.x , p_aabb.pos.y+p_aabb.size.y , p_aabb.pos.z+p_aabb.size.z ); + to=Vector3( p_aabb.pos.x , p_aabb.pos.y+p_aabb.size.y , p_aabb.pos.z ); + + } break; + case 8:{ + + from=Vector3( p_aabb.pos.x , p_aabb.pos.y , p_aabb.pos.z+p_aabb.size.z ); + to=Vector3( p_aabb.pos.x , p_aabb.pos.y+p_aabb.size.y , p_aabb.pos.z+p_aabb.size.z ); + + } break; + case 9:{ + + from=Vector3( p_aabb.pos.x , p_aabb.pos.y , p_aabb.pos.z ); + to=Vector3( p_aabb.pos.x , p_aabb.pos.y+p_aabb.size.y , p_aabb.pos.z ); + + } break; + case 10:{ + + from=Vector3( p_aabb.pos.x+p_aabb.size.x , p_aabb.pos.y , p_aabb.pos.z ); + to=Vector3( p_aabb.pos.x+p_aabb.size.x , p_aabb.pos.y+p_aabb.size.y , p_aabb.pos.z ); + + } break; + case 11:{ + + from=Vector3( p_aabb.pos.x+p_aabb.size.x , p_aabb.pos.y , p_aabb.pos.z+p_aabb.size.z ); + to=Vector3( p_aabb.pos.x+p_aabb.size.x , p_aabb.pos.y+p_aabb.size.y , p_aabb.pos.z+p_aabb.size.z ); + + } break; + + } + + Vector3 e1=from-to; + for (int j=0;j<3;j++) { + Vector3 e2=edge_norms[j]; + + Vector3 axis=vec3_cross( e1, e2 ); + + if (axis.length_squared()<0.0001) + continue; // coplanar + //axis.normalize(); + + Vector3 sup2 =Vector3( + (axis.x>0) ? -half_extents.x : half_extents.x, + (axis.y>0) ? -half_extents.y : half_extents.y, + (axis.z>0) ? -half_extents.z : half_extents.z + ); + + float maxB = axis.dot(ofs+sup2); + float minB = axis.dot(ofs-sup2); + if (minB>maxB) { + SWAP(maxB,minB); + } + + float minT=1e20,maxT=-1e20; + for (int k=0;k<3;k++) { + + float d=axis.dot(vertex[k]); + + if (d > maxT) + maxT=d; + + if (d < minT) + minT=d; + } + + if (maxB<minT || maxT<minB) + return false; + } + } + return true; + + +} + + #endif // FACE3_H diff --git a/core/packed_data_container.cpp b/core/packed_data_container.cpp index 31be886721..65a6433912 100644 --- a/core/packed_data_container.cpp +++ b/core/packed_data_container.cpp @@ -89,11 +89,13 @@ Variant PackedDataContainer::_iter_get_ofs(const Variant& p_iter,uint32_t p_offs bool err=false; if (type==TYPE_ARRAY) { - return _get_at_ofs(p_offset+8+pos*4,rd.ptr(),err); + uint32_t vpos = decode_uint32(rd.ptr() + p_offset+8+pos*4); + return _get_at_ofs(vpos,rd.ptr(),err); } else if (type==TYPE_DICT) { - return _get_at_ofs(p_offset+8+pos*12+8,rd.ptr(),err); + uint32_t vpos = decode_uint32(rd.ptr() + p_offset+8+pos*12+4); + return _get_at_ofs(vpos,rd.ptr(),err); } else { ERR_FAIL_V(Variant()); } @@ -127,6 +129,15 @@ Variant PackedDataContainer::_get_at_ofs(uint32_t p_ofs,const uint8_t *p_buf,boo } +uint32_t PackedDataContainer::_type_at_ofs(uint32_t p_ofs) const { + + DVector<uint8_t>::Read rd=data.read(); + const uint8_t *r=&rd[p_ofs]; + uint32_t type = decode_uint32(r); + + return type; +}; + int PackedDataContainer::_size(uint32_t p_ofs) const { DVector<uint8_t>::Read rd=data.read(); @@ -408,6 +419,10 @@ Variant PackedDataContainerRef::_iter_get(const Variant& p_iter){ return from->_iter_get_ofs(p_iter,offset); } +bool PackedDataContainerRef::_is_dictionary() const { + + return from->_type_at_ofs(offset) == PackedDataContainer::TYPE_DICT; +}; void PackedDataContainerRef::_bind_methods() { @@ -415,6 +430,7 @@ void PackedDataContainerRef::_bind_methods() { ObjectTypeDB::bind_method(_MD("_iter_init"),&PackedDataContainerRef::_iter_init); ObjectTypeDB::bind_method(_MD("_iter_get"),&PackedDataContainerRef::_iter_get); ObjectTypeDB::bind_method(_MD("_iter_next"),&PackedDataContainerRef::_iter_next); + ObjectTypeDB::bind_method(_MD("_is_dictionary"),&PackedDataContainerRef::_is_dictionary); } diff --git a/core/packed_data_container.h b/core/packed_data_container.h index dcbac447ba..b223d3bcfe 100644 --- a/core/packed_data_container.h +++ b/core/packed_data_container.h @@ -68,6 +68,7 @@ class PackedDataContainer : public Resource { friend class PackedDataContainerRef; Variant _key_at_ofs(uint32_t p_ofs,const Variant& p_key,bool &err) const; Variant _get_at_ofs(uint32_t p_ofs, const uint8_t *p_buf, bool &err) const; + uint32_t _type_at_ofs(uint32_t p_ofs) const; int _size(uint32_t p_ofs) const; protected: @@ -100,6 +101,7 @@ public: Variant _iter_init(const Array& p_iter); Variant _iter_next(const Array& p_iter); Variant _iter_get(const Variant& p_iter); + bool _is_dictionary() const; int size() const; virtual Variant getvar(const Variant& p_key, bool *r_valid=NULL) const; diff --git a/core/script_language.cpp b/core/script_language.cpp index 58d8bcf8ee..031fcb0c4c 100644 --- a/core/script_language.cpp +++ b/core/script_language.cpp @@ -229,8 +229,6 @@ ScriptDebugger::ScriptDebugger() { } - - bool PlaceHolderScriptInstance::set(const StringName& p_name, const Variant& p_value) { if (values.has(p_name)) { diff --git a/core/script_language.h b/core/script_language.h index 560de520ca..8c59a9e6b8 100644 --- a/core/script_language.h +++ b/core/script_language.h @@ -166,6 +166,7 @@ public: virtual ~ScriptLanguage() {}; }; +extern uint8_t script_encryption_key[32]; class PlaceHolderScriptInstance : public ScriptInstance { diff --git a/core/ustring.cpp b/core/ustring.cpp index 188818bc2a..00477e7570 100644 --- a/core/ustring.cpp +++ b/core/ustring.cpp @@ -1596,6 +1596,7 @@ bool String::is_numeric() const { }; #define IS_DIGIT(m_d) ( (m_d)>='0' && (m_d)<='9' ) +#define IS_HEX_DIGIT(m_d) ( ( (m_d)>='0' && (m_d)<='9' ) || ( (m_d)>='a' && (m_d)<='f' ) || ( (m_d)>='A' && (m_d)<='F' ) ) template<class C> static double built_in_strtod(const C *string, /* A decimal ASCII floating-point number, @@ -2891,23 +2892,107 @@ String String::xml_escape(bool p_escape_quotes) const { return str; } -String String::xml_unescape() const { +static _FORCE_INLINE_ int _xml_unescape(const CharType *p_src,int p_src_len,CharType *p_dst) { - String str=*this; - str=str.strip_edges(); - //str=str.replace("\"",""); - str=str.replace(">","<"); - str=str.replace("<",">"); - str=str.replace("'","'"); - str=str.replace(""","\""); - /* - for (int i=1;i<32;i++) { + int len=0; + while(p_src_len) { - char chr[2]={i,0}; - str=str.replace("&#"+String::num(i)+";",chr); - }*/ - str=str.replace("&","&"); + if (*p_src=='&') { + + int eat=0; + + if (p_src_len>=4 && p_src[1]=='#') { + + CharType c=0; + + for(int i=2;i<p_src_len;i++) { + + eat=i+1; + CharType ct=p_src[i]; + if (ct==';') { + break; + } else if (ct>='0' && ct<='9') { + ct=ct-'0'; + } else if (ct>='a' && ct<='f') { + ct=(ct-'a')+10; + } else if (ct>='A' && ct<='F') { + ct=(ct-'A')+10; + } else { + continue; + } + c<<=4; + c|=ct; + } + + if (p_dst) + *p_dst=c; + + } else if (p_src_len>=4 && p_src[1]=='g' && p_src[2]=='t' && p_src[3]==';') { + + if (p_dst) + *p_dst='<'; + eat=4; + } else if (p_src_len>=4 && p_src[1]=='l' && p_src[2]=='t' && p_src[3]==';') { + + if (p_dst) + *p_dst='>'; + eat=4; + } else if (p_src_len>=5 && p_src[1]=='a' && p_src[2]=='m' && p_src[3]=='p' && p_src[4]==';') { + + if (p_dst) + *p_dst='&'; + eat=5; + } else if (p_src_len>=6 && p_src[1]=='q' && p_src[2]=='u' && p_src[3]=='o' && p_src[4]=='t' && p_src[5]==';') { + + if (p_dst) + *p_dst='"'; + eat=6; + } else if (p_src_len>=6 && p_src[1]=='a' && p_src[2]=='p' && p_src[3]=='o' && p_src[4]=='s' && p_src[5]==';') { + + if (p_dst) + *p_dst='\''; + eat=6; + } else { + + if (p_dst) + *p_dst=*p_src; + eat=1; + + } + + if (p_dst) + p_dst++; + + len++; + p_src+=eat; + p_src_len-=eat; + } else { + + if (p_dst) { + *p_dst=*p_src; + p_dst++; + } + len++; + p_src++; + p_src_len--; + } + } + + return len; + +} +String String::xml_unescape() const { + + + String str; + int l = length(); + int len = _xml_unescape(c_str(),l,NULL); + if (len==0) + return String(); + str.resize(len+1); + _xml_unescape(c_str(),l,&str[0]); + str[len]=0; return str; } diff --git a/core/variant_op.cpp b/core/variant_op.cpp index 7f46f4c322..1f0f038d77 100644 --- a/core/variant_op.cpp +++ b/core/variant_op.cpp @@ -2907,7 +2907,7 @@ bool Variant::iter_init(Variant& r_iter,bool &valid) const { ref.push_back(r_iter); Variant vref=ref; const Variant *refp[]={&vref}; - Variant ret = _get_obj().obj->call(CoreStringNames::get_singleton()->_iter_next,refp,1,ce); + Variant ret = _get_obj().obj->call(CoreStringNames::get_singleton()->_iter_init,refp,1,ce); if (ref.size()!=1 || ce.error!=Variant::CallError::CALL_OK) { valid=false; diff --git a/demos/3d/platformer/stage2.xml b/demos/3d/platformer/stage2.xml deleted file mode 100644 index 3b9f5957e1..0000000000 --- a/demos/3d/platformer/stage2.xml +++ /dev/null @@ -1,336 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" ?> -<resource_file type="PackedScene" subresource_count="7" version="1.0" version_name="Godot Engine v1.0.3917-beta1"> - <ext_resource path="res://sb.cube" type="CubeMap"></ext_resource> - <ext_resource path="res://tiles.res" type="MeshLibrary"></ext_resource> - <ext_resource path="res://coin.scn" type="PackedScene"></ext_resource> - <ext_resource path="res://player.xml" type="PackedScene"></ext_resource> - <ext_resource path="res://enemy.scn" type="PackedScene"></ext_resource> - <resource type="Environment" path="local://1"> - <int name="background/mode"> 4 </int> - <color name="background/color"> 0, 0, 0, 1 </color> - <nil name="background/texture"> </nil> - <resource name="background/cubemap" resource_type="CubeMap" path="res://sb.cube"> </resource> - <real name="background/energy"> 1 </real> - <real name="background/scale"> 1 </real> - <bool name="glow/enabled"> True </bool> - <int name="glow/blur_passes"> 2 </int> - <real name="glow/bloom"> 0 </real> - <real name="glow/bloom_treshold"> 0.5 </real> - <bool name="dof_blur/enabled"> False </bool> - <int name="dof_blur/blur_passes"> 1 </int> - <real name="dof_blur/begin"> 100 </real> - <real name="dof_blur/range"> 10 </real> - <bool name="hdr/enabled"> True </bool> - <real name="hdr/exposure"> 0.4 </real> - <real name="hdr/scalar"> 1 </real> - <real name="hdr/glow_treshold"> 0.9 </real> - <real name="hdr/glow_scale"> 0.5 </real> - <real name="hdr/min_luminance"> 0.4 </real> - <real name="hdr/max_luminance"> 8 </real> - <real name="hdr/exposure_adj_speed"> 2 </real> - <bool name="fog/enabled"> True </bool> - <real name="fog/begin"> 10 </real> - <color name="fog/begin_color"> 0, 0.773632, 0.985852, 1 </color> - <color name="fog/end_color"> 0, 0, 0, 1 </color> - <real name="fog/attenuation"> 0.965936 </real> - <bool name="fog/bg"> True </bool> - <bool name="bcs/enabled"> False </bool> - <real name="bcs/brightness"> 1 </real> - <real name="bcs/contrast"> 1 </real> - <real name="bcs/saturation"> 1.608 </real> - <bool name="gamma/enabled"> False </bool> - <real name="gamma/gamma"> 1.414214 </real> - - </resource> - <main_resource> - <dictionary name="_bundled" shared="false"> - <string> "names" </string> - <string_array len="86"> - <string> "world" </string> - <string> "Spatial" </string> - <string> "__meta__" </string> - <string> "GridMap" </string> - <string> "theme/theme" </string> - <string> "theme/bake" </string> - <string> "cell/size" </string> - <string> "cell/octant_size" </string> - <string> "cell/center_x" </string> - <string> "cell/center_y" </string> - <string> "cell/center_z" </string> - <string> "cell/scale" </string> - <string> "data" </string> - <string> "DirectionalLight" </string> - <string> "transform/local" </string> - <string> "layers" </string> - <string> "params/energy" </string> - <string> "colors/ambient" </string> - <string> "colors/diffuse" </string> - <string> "colors/specular" </string> - <string> "shadow/shadow" </string> - <string> "shadow/darkening" </string> - <string> "shadow/z_offset" </string> - <string> "shadow/z_slope_scale" </string> - <string> "projector" </string> - <string> "operator" </string> - <string> "shadow/mode" </string> - <string> "shadow/max_distance" </string> - <string> "shadow/split_weight" </string> - <string> "shadow/zoffset_scale" </string> - <string> "environment" </string> - <string> "WorldEnvironment" </string> - <string> "coins" </string> - <string> "Node" </string> - <string> "coin" </string> - <string> "Area" </string> - <string> "coin 2" </string> - <string> "coin 3" </string> - <string> "coin 3 2" </string> - <string> "coin 4" </string> - <string> "coin 4 2" </string> - <string> "coin 4 3" </string> - <string> "coin 3 3" </string> - <string> "coin 5" </string> - <string> "coin 4 4" </string> - <string> "coin 3 4" </string> - <string> "coin 4 4 2" </string> - <string> "coin 6" </string> - <string> "coin 4 5" </string> - <string> "coin 3 5" </string> - <string> "coin 4 5 2" </string> - <string> "coin 4 4 3" </string> - <string> "coin 3 5 2" </string> - <string> "coin 6 2" </string> - <string> "coin 4 5 3" </string> - <string> "coin 7" </string> - <string> "coin 4 6" </string> - <string> "coin 6 3" </string> - <string> "coin 3 5 3" </string> - <string> "coin 4 4 4" </string> - <string> "coin 3 6" </string> - <string> "coin 4 5 4" </string> - <string> "coin 4 5 4 2" </string> - <string> "coin 8" </string> - <string> "coin 4 4 5" </string> - <string> "coin 4 7" </string> - <string> "coin 6 4" </string> - <string> "coin 3 5 4" </string> - <string> "coin 4 5 5" </string> - <string> "coin 3 7" </string> - <string> "coin 4 5 4 3" </string> - <string> "coin 9" </string> - <string> "coin 4 4 6" </string> - <string> "coin 4 8" </string> - <string> "coin 4 5 6" </string> - <string> "coin 3 5 5" </string> - <string> "coin 6 5" </string> - <string> "coin 3 8" </string> - <string> "coin 4 5 4 4" </string> - <string> "enemies" </string> - <string> "enemy" </string> - <string> "RigidBody" </string> - <string> "enemy 2" </string> - <string> "enemy 3" </string> - <string> "enemy 4" </string> - <string> "player" </string> - </string_array> - <string> "version" </string> - <int> 1 </int> - <string> "conn_count" </string> - <int> 0 </int> - <string> "node_count" </string> - <int> 55 </int> - <string> "variants" </string> - <array len="76" shared="false"> - <dictionary shared="false"> - <string> "__editor_plugin_states__" </string> - <dictionary shared="false"> - <string> "2D" </string> - <dictionary shared="false"> - <string> "pixel_snap" </string> - <bool> False </bool> - <string> "zoom" </string> - <real> 1 </real> - <string> "ofs" </string> - <vector2> 1, 1 </vector2> - </dictionary> - <string> "3D" </string> - <dictionary shared="false"> - <string> "zfar" </string> - <real> 500 </real> - <string> "fov" </string> - <real> 400 </real> - <string> "viewports" </string> - <array len="4" shared="false"> - <dictionary shared="false"> - <string> "distance" </string> - <real> 7.724576 </real> - <string> "x_rot" </string> - <real> 0.745795 </real> - <string> "y_rot" </string> - <real> 0.6875 </real> - <string> "use_orthogonal" </string> - <bool> False </bool> - <string> "use_environment" </string> - <bool> False </bool> - <string> "pos" </string> - <vector3> 8.30511, 0.427271, 15.7846 </vector3> - </dictionary> - <dictionary shared="false"> - <string> "distance" </string> - <real> 4 </real> - <string> "x_rot" </string> - <real> 0 </real> - <string> "y_rot" </string> - <real> 0 </real> - <string> "use_orthogonal" </string> - <bool> False </bool> - <string> "use_environment" </string> - <bool> False </bool> - <string> "pos" </string> - <vector3> 0, 0, 0 </vector3> - </dictionary> - <dictionary shared="false"> - <string> "distance" </string> - <real> 4 </real> - <string> "x_rot" </string> - <real> 0 </real> - <string> "y_rot" </string> - <real> 0 </real> - <string> "use_orthogonal" </string> - <bool> False </bool> - <string> "use_environment" </string> - <bool> False </bool> - <string> "pos" </string> - <vector3> 0, 0, 0 </vector3> - </dictionary> - <dictionary shared="false"> - <string> "distance" </string> - <real> 4 </real> - <string> "x_rot" </string> - <real> 0 </real> - <string> "y_rot" </string> - <real> 0 </real> - <string> "use_orthogonal" </string> - <bool> False </bool> - <string> "use_environment" </string> - <bool> False </bool> - <string> "pos" </string> - <vector3> 0, 0, 0 </vector3> - </dictionary> - </array> - <string> "viewport_mode" </string> - <int> 1 </int> - <string> "default_light" </string> - <bool> False </bool> - <string> "show_grid" </string> - <bool> True </bool> - <string> "show_origin" </string> - <bool> True </bool> - <string> "znear" </string> - <real> 0.1 </real> - </dictionary> - </dictionary> - <string> "__editor_run_settings__" </string> - <dictionary shared="false"> - <string> "custom_args" </string> - <string> "-l $scene" </string> - <string> "run_mode" </string> - <int> 0 </int> - </dictionary> - <string> "__editor_plugin_screen__" </string> - <string> "3D" </string> - </dictionary> - <resource resource_type="MeshLibrary" path="res://tiles.res"> </resource> - <bool> False </bool> - <real> 2 </real> - <int> 4 </int> - <bool> True </bool> - <real> 1.001 </real> - <dictionary shared="false"> - <string> "cells" </string> - <int_array len="5133"> 3, 0, 1048584, 12, 0, 1441800, 65539, 0, 1048584, 65548, 0, 1441800, 131075, 0, 1048578, 131084, 0, 1441800, 196611, 0, 1048578, 196620, 0, 1441800, 262147, 0, 1048578, 262156, 0, 1441800, 327683, 0, 1048584, 327692, 0, 1441794, 393219, 0, 1048584, 393228, 0, 1441794, 458752, 0, 655367, 458753, 0, 655367, 458754, 0, 655367, 458755, 0, 655367, 458764, 0, 1441794, 524286, 0, 655367, 524287, 0, 655367, 524300, 0, 1441798, -65533, 0, 1048579, -65532, 0, 1441799, -65531, 0, 1441799, -65530, 0, 1441799, -65529, 0, 1441799, -65528, 0, 1441799, -65527, 0, 1441799, -65526, 0, 1441799, -65525, 0, 1441799, -65524, 0, 1441800, 3, 1, 1048584, 12, 1, 1441800, 29, 1, 8, 30, 1, 8, 31, 1, 8, 65539, 1, 1048584, 65548, 1, 1441800, 65560, 1, 655366, 65561, 1, 655366, 65562, 1, 655366, 65563, 1, 655366, 65564, 1, 655365, 65565, 1, 6, 65566, 1, 6, 65567, 1, 6, 65568, 1, 655366, 65569, 1, 655365, 131075, 1, 1048578, 131084, 1, 1441800, 196611, 1, 1048578, 196620, 1, 1441800, 262147, 1, 1048578, 262156, 1, 1441800, 327683, 1, 1048584, 327692, 1, 1441794, 393219, 1, 1048584, 393228, 1, 1441794, 458752, 1, 655367, 458753, 1, 655367, 458754, 1, 655367, 458755, 1, 655367, 458764, 1, 1441794, 524285, 1, 655367, 524286, 1, 655367, 524287, 1, 655367, 524300, 1, 1441798, -65533, 1, 1048579, -65532, 1, 1441799, -65531, 1, 1441799, -65530, 1, 1441799, -65529, 1, 1441799, -65528, 1, 1441799, -65527, 1, 1441799, -65526, 1, 1441799, -65525, 1, 1441799, -65524, 1, 1441800, -65507, 1, 3, -65506, 1, 3, -65505, 1, 3, 3, 2, 1048584, 5, 2, 1441797, 6, 2, 655365, 8, 2, 1441801, 9, 2, 655368, 10, 2, 655368, 11, 2, 655368, 12, 2, 1441800, 28, 2, 1048584, 32, 2, 9, 65539, 2, 1048584, 65544, 2, 1441797, 65545, 2, 655366, 65546, 2, 655366, 65547, 2, 655366, 65548, 2, 1441800, 65564, 2, 655369, 65568, 2, 5, 65569, 2, 1048583, 65570, 2, 655365, 131075, 2, 1048578, 131084, 2, 1441800, 131100, 2, 655369, 196611, 2, 1048578, 196620, 2, 1441800, 196632, 2, 655366, 196633, 2, 655366, 196634, 2, 655366, 196635, 2, 655366, 196636, 2, 655365, 262147, 2, 1048578, 262156, 2, 1441800, 327683, 2, 1048584, 327692, 2, 1441794, 393219, 2, 1048584, 393228, 2, 1441794, 458752, 2, 655367, 458753, 2, 655367, 458754, 2, 655367, 458755, 2, 655367, 458764, 2, 1441794, 524285, 2, 655367, 524286, 2, 655367, 524287, 2, 655367, 524300, 2, 1441798, -65533, 2, 1048579, -65532, 2, 1048583, -65531, 2, 1441796, -65530, 2, 655364, -65529, 2, 1441799, -65528, 2, 1441796, -65527, 2, 655363, -65526, 2, 655363, -65525, 2, 655363, -65524, 2, 1441800, -65508, 2, 1048579, -65507, 2, 1441799, -65506, 2, 1441799, -65505, 2, 1441799, -65504, 2, 4, 3, 3, 1048584, 5, 3, 5, 6, 3, 1048581, 8, 3, 9, 9, 3, 8, 10, 3, 8, 11, 3, 8, 12, 3, 1441800, 28, 3, 1048585, 33, 3, 9, 65539, 3, 1048584, 65544, 3, 5, 65545, 3, 6, 65546, 3, 6, 65547, 3, 6, 65548, 3, 1441800, 65564, 3, 1048585, 65569, 3, 5, 65570, 3, 1048583, 65571, 3, 655365, 131075, 3, 1048578, 131084, 3, 1441800, 131100, 3, 1048585, 196611, 3, 1048578, 196620, 3, 1441800, 196632, 3, 655363, 196633, 3, 655363, 196634, 3, 655363, 196635, 3, 655364, 196636, 3, 1048581, 262147, 3, 1048578, 262156, 3, 1441800, 262168, 3, 655366, 262169, 3, 655366, 262170, 3, 655366, 262171, 3, 655365, 327683, 3, 1048584, 327692, 3, 1441794, 393219, 3, 1048584, 393228, 3, 1441794, 458752, 3, 655367, 458753, 3, 655366, 458754, 3, 655366, 458755, 3, 655367, 458764, 3, 1441794, 458771, 3, 1048578, 524284, 3, 655367, 524285, 3, 655367, 524286, 3, 655367, 524287, 3, 655367, 524300, 3, 1441798, -65533, 3, 1048579, -65532, 3, 1048583, -65531, 3, 4, -65530, 3, 1048580, -65529, 3, 1441799, -65528, 3, 4, -65527, 3, 3, -65526, 3, 3, -65525, 3, 3, -65524, 3, 1441800, -65508, 3, 1048580, -65507, 3, 1441799, -65506, 3, 1441799, -65505, 3, 1441799, -65504, 3, 1441799, -65503, 3, 4, 3, 4, 1048584, 12, 4, 1441800, 27, 4, 1048584, 34, 4, 1441800, 65539, 4, 1048584, 65548, 4, 1441800, 65563, 4, 1048584, 65570, 4, 1048583, 65571, 4, 1048582, 131075, 4, 1048578, 131084, 4, 9, 131085, 4, 3, 131086, 4, 3, 131087, 4, 3, 131088, 4, 3, 131089, 4, 3, 131090, 4, 3, 131099, 4, 1048584, 196611, 4, 1048578, 196620, 4, 9, 196621, 4, 8, 196622, 4, 8, 196623, 4, 8, 196624, 4, 8, 196625, 4, 8, 196626, 4, 8, 196635, 4, 1048584, 262147, 4, 1048578, 262156, 4, 1441800, 262168, 4, 655363, 262169, 4, 655363, 262170, 4, 655364, 262171, 4, 1048582, 327680, 4, 8, 327681, 4, 8, 327682, 4, 8, 327683, 4, 1048580, 327691, 4, 1441808, 327692, 4, 9, 327693, 4, 3, 327694, 4, 3, 327695, 4, 3, 327696, 4, 3, 327697, 4, 3, 393216, 4, 8, 393217, 4, 8, 393218, 4, 8, 393219, 4, 1048585, 393228, 4, 9, 393229, 4, 2, 393230, 4, 2, 393231, 4, 2, 393232, 4, 2, 393233, 4, 2, 458752, 4, 6, 458753, 4, 6, 458754, 4, 6, 458755, 4, 1048581, 458764, 4, 1441800, 458771, 4, 1048578, 458774, 4, 1048583, 458775, 4, 1048583, 458776, 4, 1048583, 458777, 4, 1048583, 458778, 4, 1048582, 524284, 4, 655367, 524285, 4, 655367, 524286, 4, 655367, 524287, 4, 1048583, 524300, 4, 1441798, 524307, 4, 1048582, -65533, 4, 1048579, -65532, 4, 7, -65531, 4, 7, -65530, 4, 7, -65529, 4, 7, -65528, 4, 1441799, -65527, 4, 1441799, -65526, 4, 1441799, -65525, 4, 1441799, -65524, 4, 1441800, -65509, 4, 1048579, -65508, 4, 1441799, -65507, 4, 1441799, -65506, 4, 1441799, -65505, 4, 1441799, -65504, 4, 1441799, -65503, 4, 1441799, -65502, 4, 1441795, 3, 5, 1048584, 11, 5, 1441801, 27, 5, 1048584, 34, 5, 9, 65538, 5, 3, 65539, 5, 1048580, 65547, 5, 1441801, 65563, 5, 1048584, 65570, 5, 5, 65571, 5, 1048582, 131074, 5, 2, 131075, 5, 1048585, 131083, 5, 1441797, 131084, 5, 7, 131085, 5, 7, 131086, 5, 7, 131087, 5, 7, 131088, 5, 7, 131089, 5, 7, 131090, 5, 7, 131091, 5, 1441795, 131099, 5, 1048584, 196610, 5, 2, 196611, 5, 1048585, 196627, 5, 1441800, 196635, 5, 1048584, 262146, 5, 2, 262147, 5, 1048585, 262156, 5, 1441806, 262157, 5, 1, 262158, 5, 1, 262159, 5, 1, 262160, 5, 1, 262161, 5, 655361, 262162, 5, 655361, 262170, 5, 1048584, 262171, 5, 1048582, 327680, 5, 655366, 327681, 5, 1441798, 327682, 5, 6, 327683, 5, 1048581, 327692, 5, 1441798, 327693, 5, 7, 327694, 5, 7, 327695, 5, 7, 327696, 5, 7, 327697, 5, 1048583, 327698, 5, 1441795, 393215, 5, 1048584, 393234, 5, 1441794, 458751, 5, 1048584, 458764, 5, 1441806, 458765, 5, 655361, 458766, 5, 655361, 458767, 5, 655361, 458768, 5, 655361, 458769, 5, 655361, 458771, 5, 1048578, 458773, 5, 1048583, 458774, 5, 1048583, 458775, 5, 1048583, 458776, 5, 1048583, 458777, 5, 1048583, 458778, 5, 1048582, 524283, 5, 655367, 524284, 5, 655367, 524285, 5, 655367, 524286, 5, 655367, 524287, 5, 1048582, 524300, 5, 1441798, 524301, 5, 1441799, 524302, 5, 1441799, 524303, 5, 1441799, 524304, 5, 1441799, 524305, 5, 1441799, 524306, 5, 1441799, 524307, 5, 1048582, -65533, 5, 1048579, -65532, 5, 7, -65531, 5, 7, -65530, 5, 7, -65529, 5, 1048583, -65528, 5, 1441799, -65527, 5, 1441799, -65526, 5, 1441799, -65525, 5, 1441801, -65509, 5, 1048579, -65508, 5, 1441799, -65507, 5, 1441799, -65506, 5, 1441799, -65505, 5, 1441799, -65504, 5, 1441799, -65503, 5, 1441799, -65502, 5, 4, 2, 6, 655368, 3, 6, 655368, 4, 6, 655369, 11, 6, 1441794, 27, 6, 1048584, 35, 6, 1441800, 65537, 6, 1048579, 65538, 6, 655366, 65539, 6, 655366, 65540, 6, 655365, 65547, 6, 1441794, 65563, 6, 1048584, 65571, 6, 1441798, 131073, 6, 1048584, 131083, 6, 1441798, 131084, 6, 7, 131085, 6, 7, 131086, 6, 7, 131087, 6, 7, 131088, 6, 7, 131089, 6, 7, 131090, 6, 7, 131091, 6, 1441795, 131099, 6, 1048584, 196609, 6, 1048584, 196627, 6, 1441800, 196635, 6, 1048584, 262145, 6, 1048584, 262156, 6, 1441806, 262157, 6, 1, 262158, 6, 1, 262159, 6, 1, 262160, 6, 1, 262161, 6, 655361, 262162, 6, 655361, 262170, 6, 1048584, 262171, 6, 1048582, 327680, 6, 1441799, 327681, 6, 1048582, 327692, 6, 1441798, 327693, 6, 7, 327694, 6, 7, 327695, 6, 7, 327696, 6, 7, 327697, 6, 1048583, 327698, 6, 1441795, 393215, 6, 1048584, 393234, 6, 1441794, 458751, 6, 1048584, 458764, 6, 1441806, 458765, 6, 655361, 458766, 6, 655361, 458767, 6, 655361, 458768, 6, 655361, 458769, 6, 655361, 458771, 6, 1048578, 458773, 6, 1048583, 458774, 6, 1048583, 458775, 6, 1048583, 458776, 6, 1048583, 458777, 6, 1048583, 458778, 6, 1048582, 524283, 6, 655367, 524284, 6, 655367, 524285, 6, 655367, 524286, 6, 655367, 524287, 6, 1048582, 524300, 6, 1441798, 524301, 6, 1441799, 524302, 6, 1441799, 524303, 6, 1441799, 524304, 6, 1441799, 524305, 6, 1441799, 524306, 6, 1441799, 524307, 6, 1048582, -65534, 6, 655363, -65533, 6, 655363, -65532, 6, 655364, -65531, 6, 655367, -65530, 6, 655367, -65529, 6, 1048583, -65528, 6, 7, -65527, 6, 1441799, -65526, 6, 1441799, -65525, 6, 1441795, -65509, 6, 1048579, -65508, 6, 1441799, -65507, 6, 1441799, -65506, 6, 1441799, -65505, 6, 1441799, -65504, 6, 1441799, -65503, 6, 1441799, -65502, 6, 1441799, -65501, 6, 1441800, 4, 7, 1048584, 6, 7, 11, 11, 7, 9, 27, 7, 1048584, 35, 7, 1441800, 65537, 7, 1048579, 65538, 7, 1441799, 65539, 7, 1441799, 65540, 7, 1048582, 65542, 7, 12, 65547, 7, 9, 65563, 7, 1048584, 65571, 7, 1441798, 131073, 7, 1048584, 131078, 7, 1441804, 131083, 7, 5, 131084, 7, 7, 131085, 7, 1441796, 131086, 7, 655363, 131087, 7, 655363, 131088, 7, 655364, 131089, 7, 7, 131090, 7, 7, 131091, 7, 1441795, 131099, 7, 1048584, 196609, 7, 1048584, 196614, 7, 13, 196621, 7, 1441801, 196622, 7, 655362, 196623, 7, 655362, 196624, 7, 655369, 196627, 7, 1441800, 196635, 7, 1048584, 262145, 7, 1048584, 262156, 7, 1441806, 262157, 7, 1441806, 262158, 7, 1, 262159, 7, 1, 262160, 7, 1, 262161, 7, 655361, 262162, 7, 655361, 262170, 7, 1048584, 262171, 7, 1048582, 327680, 7, 1441799, 327681, 7, 1048582, 327691, 7, 1441809, 327692, 7, 1441801, 327693, 7, 655363, 327694, 7, 655363, 327695, 7, 655363, 327696, 7, 655364, 327697, 7, 1048583, 327698, 7, 1441795, 393215, 7, 1048584, 393228, 7, 1441801, 393229, 7, 655368, 393230, 7, 655368, 393231, 7, 655368, 393232, 7, 655369, 393234, 7, 1441794, 458751, 7, 1048584, 458764, 7, 1441800, 458768, 7, 655361, 458769, 7, 655361, 458771, 7, 1048578, 458774, 7, 1048583, 458775, 7, 1048583, 458776, 7, 1048583, 458777, 7, 1048583, 458778, 7, 1048582, 524282, 7, 655367, 524283, 7, 655367, 524284, 7, 655367, 524285, 7, 655367, 524286, 7, 655367, 524287, 7, 1048582, 524300, 7, 1441798, 524301, 7, 1441799, 524302, 7, 1441799, 524303, 7, 1441799, 524304, 7, 1441799, 524305, 7, 1441799, 524306, 7, 1441799, 524307, 7, 1048582, -65532, 7, 1048579, -65531, 7, 1048583, -65530, 7, 10, -65529, 7, 1441799, -65528, 7, 1441799, -65527, 7, 1441799, -65526, 7, 1441799, -65525, 7, 4, -65509, 7, 1048579, -65508, 7, 1441799, -65507, 7, 1441799, -65506, 7, 1441799, -65505, 7, 1441799, -65504, 7, 1441799, -65503, 7, 1441799, -65502, 7, 1441799, -65501, 7, 1441800, 2, 8, 3, 3, 8, 3, 4, 8, 1048585, 12, 8, 1441800, 27, 8, 1048584, 35, 8, 1441800, 65537, 8, 1048579, 65538, 8, 6, 65539, 8, 6, 65540, 8, 1048581, 65548, 8, 1441800, 65563, 8, 1048584, 65571, 8, 1441798, 65572, 8, 655366, 65573, 8, 655366, 65574, 8, 655366, 65575, 8, 655366, 65576, 8, 655366, 65577, 8, 655365, 131073, 8, 1048584, 131084, 8, 1441796, 131088, 8, 1048579, 131089, 8, 7, 131090, 8, 7, 131091, 8, 1441795, 131099, 8, 1048584, 196609, 8, 1048584, 196620, 8, 1441801, 196624, 8, 1048584, 196627, 8, 1441800, 196635, 8, 1048584, 262145, 8, 1048584, 262156, 8, 1441800, 262161, 8, 655361, 262162, 8, 655361, 262170, 8, 1048584, 262171, 8, 1048582, 327680, 8, 1441799, 327681, 8, 1048581, 327692, 8, 1441800, 327695, 8, 3, 327696, 8, 1048580, 327697, 8, 1048583, 327698, 8, 1441795, 393215, 8, 1048584, 393228, 8, 1441800, 393231, 8, 8, 393232, 8, 1048585, 393234, 8, 1441794, 458751, 8, 1048584, 458764, 8, 9, 458769, 8, 655361, 458771, 8, 1048578, 458774, 8, 1048583, 458775, 8, 1048583, 458776, 8, 1048583, 458777, 8, 1048583, 458778, 8, 1048582, 524282, 8, 655367, 524283, 8, 655367, 524284, 8, 655367, 524285, 8, 655367, 524286, 8, 655367, 524287, 8, 1048582, 524300, 8, 5, 524301, 8, 1441799, 524302, 8, 1441799, 524303, 8, 1441799, 524304, 8, 1441799, 524305, 8, 1441799, 524306, 8, 1441799, 524307, 8, 1048582, -65534, 8, 3, -65533, 8, 3, -65532, 8, 1048580, -65531, 8, 655367, -65530, 8, 655367, -65529, 8, 655367, -65528, 8, 1441799, -65527, 8, 1441799, -65526, 8, 1441799, -65525, 8, 655367, -65524, 8, 1441800, -65509, 8, 1048579, -65508, 8, 1441799, -65507, 8, 1441799, -65506, 8, 1441799, -65505, 8, 1441799, -65504, 8, 1441799, -65503, 8, 1441799, -65502, 8, 1441799, -65501, 8, 1441800, 1, 9, 1048578, 2, 9, 5, 3, 9, 1048581, 8, 9, 11, 12, 9, 1441800, 27, 9, 1048584, 35, 9, 1441800, 65537, 9, 1048578, 65544, 9, 12, 65548, 9, 1441800, 65563, 9, 1048584, 65570, 9, 1441809, 65571, 9, 1441801, 65572, 9, 655363, 65573, 9, 655363, 65574, 9, 655363, 65575, 9, 655363, 65576, 9, 655363, 131073, 9, 1048578, 131080, 9, 1048588, 131084, 9, 1441800, 131088, 9, 1048579, 131089, 9, 7, 131090, 9, 7, 131091, 9, 1441795, 131099, 9, 1048584, 131107, 9, 1441797, 131108, 9, 655366, 131109, 9, 655366, 131110, 9, 655366, 131111, 9, 655366, 131112, 9, 655366, 131113, 9, 655365, 196609, 9, 1048578, 196616, 9, 1048588, 196620, 9, 1441800, 196624, 9, 1048584, 196627, 9, 1441800, 196635, 9, 1048584, 262145, 9, 1048578, 262152, 9, 1048589, 262156, 9, 1441800, 262161, 9, 655361, 262162, 9, 655361, 262169, 9, 3, 262170, 9, 1048580, 262171, 9, 1048582, 327680, 9, 655368, 327681, 9, 655369, 327682, 9, 1048592, 327692, 9, 1441800, 327694, 9, 1048579, 327695, 9, 1441799, 327696, 9, 1441799, 327697, 9, 1441799, 327698, 9, 1441795, 327705, 9, 8, 327706, 9, 1048585, 393216, 9, 655368, 393217, 9, 655369, 393228, 9, 1441800, 393230, 9, 1048584, 393234, 9, 1441794, 393241, 9, 8, 393242, 9, 1048585, 458752, 9, 655366, 458753, 9, 655365, 458764, 9, 1441798, 458765, 9, 1441795, 458767, 9, 655361, 458768, 9, 655361, 458769, 9, 655361, 458771, 9, 1048578, 458774, 9, 1048583, 458775, 9, 1048583, 458776, 9, 1048583, 458777, 9, 6, 458778, 9, 1048581, 524282, 9, 655367, 524283, 9, 655367, 524284, 9, 655367, 524285, 9, 655367, 524286, 9, 655367, 524287, 9, 655367, 524301, 9, 1441798, 524302, 9, 1441799, 524303, 9, 1441799, 524304, 9, 1441799, 524305, 9, 1441799, 524306, 9, 1441799, 524307, 9, 1048582, -65535, 9, 1048584, -65534, 9, 4, -65533, 9, 1048580, -65532, 9, 7, -65531, 9, 7, -65530, 9, 7, -65529, 9, 7, -65528, 9, 10, -65527, 9, 1441799, -65526, 9, 1441799, -65525, 9, 655367, -65524, 9, 1441800, -65509, 9, 1048579, -65508, 9, 1441799, -65507, 9, 1441799, -65506, 9, 1441799, -65505, 9, 1441799, -65504, 9, 1441799, -65503, 9, 1441799, -65502, 9, 1441799, -65501, 9, 1441800, 1, 10, 1048578, 12, 10, 1441800, 26, 10, 8, 27, 10, 1048585, 35, 10, 1441800, 65537, 10, 1048578, 65548, 10, 1441800, 65561, 10, 3, 65562, 10, 3, 65563, 10, 1048585, 65571, 10, 1441800, 131073, 10, 1048578, 131084, 10, 1441800, 131088, 10, 1048580, 131089, 10, 1048583, 131090, 10, 1048583, 131091, 10, 4, 131097, 10, 8, 131098, 10, 8, 131099, 10, 1048585, 131106, 10, 1441809, 131107, 10, 1441801, 131108, 10, 655363, 131109, 10, 655363, 131110, 10, 655363, 131111, 10, 655363, 131112, 10, 655364, 131113, 10, 1048582, 196609, 10, 1048578, 196620, 10, 1441800, 196624, 10, 1048585, 196627, 10, 9, 196633, 10, 8, 196634, 10, 8, 196635, 10, 1048585, 196643, 10, 1441797, 196644, 10, 655366, 196645, 10, 655366, 196646, 10, 655366, 196647, 10, 655366, 196648, 10, 655366, 196649, 10, 655365, 262145, 10, 1048578, 262156, 10, 1441800, 262161, 10, 1, 262162, 10, 1, 262168, 10, 1048579, 262169, 10, 6, 262170, 10, 6, 262171, 10, 1048581, 327681, 10, 1048578, 327685, 10, 655377, 327689, 10, 655376, 327692, 10, 1441800, 327694, 10, 1048579, 327695, 10, 1441799, 327696, 10, 1441796, 327697, 10, 655363, 327704, 10, 1048584, 393217, 10, 1048584, 393228, 10, 1441800, 393230, 10, 1048584, 393232, 10, 1441801, 393233, 10, 655362, 393240, 10, 1048584, 458752, 10, 6, 458753, 10, 1048582, 458764, 10, 1441798, 458765, 10, 4, 458766, 10, 3, 458767, 10, 14, 458768, 10, 3, 458769, 10, 8, 458770, 10, 8, 458771, 10, 1048585, 458774, 10, 1048583, 458775, 10, 1048583, 458776, 10, 1048582, 524282, 10, 655367, 524283, 10, 655367, 524284, 10, 655367, 524285, 10, 655367, 524286, 10, 655367, 524287, 10, 655367, 524301, 10, 5, 524302, 10, 6, 524303, 10, 6, 524304, 10, 6, 524305, 10, 6, 524306, 10, 6, 524307, 10, 1048581, -65535, 10, 1048584, -65534, 10, 1048583, -65533, 10, 7, -65532, 10, 7, -65531, 10, 7, -65530, 10, 7, -65529, 10, 7, -65528, 10, 655367, -65527, 10, 655367, -65526, 10, 655367, -65525, 10, 655367, -65524, 10, 1441800, -65511, 10, 3, -65510, 10, 3, -65509, 10, 1048580, -65508, 10, 7, -65507, 10, 7, -65506, 10, 7, -65505, 10, 7, -65504, 10, 7, -65503, 10, 7, -65502, 10, 1441799, -65501, 10, 1441795, 2, 11, 655368, 3, 11, 655368, 4, 11, 655368, 5, 11, 655368, 6, 11, 655368, 7, 11, 655368, 8, 11, 655368, 9, 11, 655368, 10, 11, 655368, 11, 11, 655368, 21, 11, 8, 22, 11, 8, 23, 11, 8, 24, 11, 1048585, 25, 11, 1441801, 26, 11, 655369, 35, 11, 1441800, 65538, 11, 655368, 65539, 11, 655368, 65540, 11, 655368, 65541, 11, 655368, 65542, 11, 655368, 65543, 11, 655368, 65544, 11, 655368, 65545, 11, 655368, 65546, 11, 655368, 65547, 11, 655368, 65549, 11, 8, 65550, 11, 8, 65551, 11, 8, 65552, 11, 8, 65553, 11, 8, 65554, 11, 8, 65555, 11, 8, 65556, 11, 8, 65557, 11, 8, 65558, 11, 8, 65559, 11, 8, 65560, 11, 1048585, 65561, 11, 1441797, 65562, 11, 655365, 65571, 11, 1441800, 131074, 11, 655368, 131075, 11, 655368, 131076, 11, 655368, 131077, 11, 655368, 131078, 11, 655368, 131079, 11, 655368, 131080, 11, 655368, 131081, 11, 655368, 131082, 11, 655368, 131083, 11, 655368, 131085, 11, 8, 131086, 11, 8, 131087, 11, 1048585, 131088, 11, 6, 131089, 11, 6, 131090, 11, 6, 131091, 11, 6, 131092, 11, 9, 131093, 11, 8, 131094, 11, 8, 131095, 11, 8, 131096, 11, 1048585, 131107, 11, 1441800, 196610, 11, 655368, 196611, 11, 655368, 196612, 11, 655368, 196613, 11, 655368, 196614, 11, 655368, 196615, 11, 655368, 196616, 11, 655368, 196617, 11, 655368, 196618, 11, 655368, 196619, 11, 655368, 196621, 11, 8, 196622, 11, 8, 196623, 11, 1048585, 196628, 11, 9, 196629, 11, 8, 196630, 11, 8, 196631, 11, 8, 196632, 11, 1048585, 196642, 11, 1441809, 196643, 11, 1441801, 196644, 11, 655363, 196645, 11, 655363, 196646, 11, 655363, 196647, 11, 655363, 196648, 11, 655364, 196649, 11, 1048582, 262146, 11, 655368, 262147, 11, 655368, 262148, 11, 655368, 262149, 11, 655368, 262150, 11, 655368, 262151, 11, 655368, 262152, 11, 655368, 262153, 11, 655368, 262154, 11, 655368, 262155, 11, 655368, 262157, 11, 8, 262158, 11, 8, 262159, 11, 8, 262160, 11, 14, 262161, 11, 14, 262162, 11, 14, 262163, 11, 14, 262164, 11, 8, 262165, 11, 8, 262166, 11, 8, 262167, 11, 8, 262168, 11, 1048585, 262179, 11, 1441797, 262180, 11, 655366, 262181, 11, 655366, 262182, 11, 655366, 262183, 11, 655366, 262184, 11, 655366, 262185, 11, 655365, 327682, 11, 655362, 327683, 11, 655362, 327684, 11, 655362, 327685, 11, 655369, 327686, 11, 655366, 327687, 11, 655366, 327688, 11, 655366, 327689, 11, 1441801, 327690, 11, 655368, 327691, 11, 655368, 327693, 11, 8, 327694, 11, 1048585, 327695, 11, 6, 327696, 11, 9, 327697, 11, 8, 327698, 11, 8, 327699, 11, 8, 327700, 11, 8, 327701, 11, 8, 327702, 11, 8, 327703, 11, 8, 327704, 11, 1048585, 393218, 11, 655362, 393219, 11, 655362, 393220, 11, 655362, 393221, 11, 655369, 393225, 11, 1441801, 393226, 11, 655368, 393227, 11, 655368, 393229, 11, 8, 393230, 11, 1048585, 393232, 11, 9, 393233, 11, 2, 393234, 11, 2, 393235, 11, 2, 393236, 11, 2, 393237, 11, 8, 393238, 11, 8, 393239, 11, 8, 393240, 11, 1048585, 458752, 11, 655367, 458753, 11, 655367, 458754, 11, 655366, 458755, 11, 655366, 458756, 11, 655366, 458757, 11, 655366, 458761, 11, 1441797, 458762, 11, 655366, 458763, 11, 655366, 458764, 11, 1441799, 458765, 11, 6, 458766, 11, 1048581, 458768, 11, 5, 458769, 11, 6, 458770, 11, 6, 458771, 11, 6, 458772, 11, 6, 458773, 11, 6, 458774, 11, 6, 458775, 11, 6, 458776, 11, 1048581, 524282, 11, 655367, 524283, 11, 655367, 524284, 11, 655367, 524285, 11, 655367, 524286, 11, 655367, 524287, 11, 655367, -65534, 11, 655363, -65533, 11, 655363, -65532, 11, 655363, -65531, 11, 655363, -65530, 11, 655363, -65529, 11, 655363, -65528, 11, 655363, -65527, 11, 655363, -65526, 11, 655363, -65525, 11, 655363, -65512, 11, 1048580, -65511, 11, 1441796, -65510, 11, 655364, -65509, 11, 7, -65508, 11, 7, -65507, 11, 7, -65506, 11, 7, -65505, 11, 7, -65504, 11, 7, -65503, 11, 7, -65502, 11, 7, -65501, 11, 1441795, 21, 12, 15, 23, 12, 1048582, 25, 12, 9, 26, 12, 1048585, 35, 12, 1441800, 65548, 12, 1048584, 65549, 12, 1048583, 65550, 12, 1048583, 65551, 12, 1048583, 65552, 12, 1048583, 65553, 12, 1048583, 65554, 12, 1048583, 65555, 12, 1048583, 65556, 12, 1048583, 65561, 12, 5, 65562, 12, 1048581, 65571, 12, 1441800, 131084, 12, 1048584, 131087, 12, 16, 131092, 12, 17, 131107, 12, 1441800, 196620, 12, 1048584, 196643, 12, 1441800, 262156, 12, 1048584, 262178, 12, 1441809, 262179, 12, 1441801, 262180, 12, 655363, 262181, 12, 655363, 262182, 12, 655363, 262183, 12, 655363, 262184, 12, 655364, 262185, 12, 1048582, 327686, 12, 655363, 327687, 12, 655363, 327688, 12, 655363, 327692, 12, 1048584, 327694, 12, 16, 327696, 12, 17, 327715, 12, 1441797, 327716, 12, 655366, 327717, 12, 655366, 327718, 12, 655366, 327719, 12, 655366, 327720, 12, 655365, 393222, 12, 655368, 393223, 12, 655368, 393224, 12, 655368, 393228, 12, 1048584, 458752, 12, 655367, 458753, 12, 655367, 458754, 12, 655367, 458755, 12, 655367, 458756, 12, 655367, 458757, 12, 655367, 458758, 12, 655366, 458759, 12, 655366, 458760, 12, 655366, 458761, 12, 1441799, 458762, 12, 1441799, 458763, 12, 1441799, 458764, 12, 655366, 524282, 12, 655367, 524283, 12, 655367, 524284, 12, 655367, 524285, 12, 655367, 524286, 12, 655367, 524287, 12, 655367, -65513, 12, 1048579, -65512, 12, 7, -65511, 12, 4, -65510, 12, 1048580, -65509, 12, 7, -65508, 12, 7, -65507, 12, 7, -65506, 12, 7, -65505, 12, 7, -65504, 12, 7, -65503, 12, 7, -65502, 12, 7, -65501, 12, 1441795, 21, 13, 15, 23, 13, 1048582, 28, 13, 1441801, 29, 13, 655369, 35, 13, 1441800, 65548, 13, 1048584, 65549, 13, 1048583, 65550, 13, 1048583, 65551, 13, 1048583, 65552, 13, 1048583, 65553, 13, 1048583, 65554, 13, 1048583, 65555, 13, 1048583, 65556, 13, 1048583, 65564, 13, 1441801, 65565, 13, 655369, 65571, 13, 1441800, 131084, 13, 1048584, 131100, 13, 1441797, 131101, 13, 655365, 131107, 13, 1441800, 196620, 13, 1048584, 196643, 13, 1441800, 262156, 13, 1048584, 262179, 13, 1441800, 327692, 13, 1048584, 327715, 13, 1441798, 393228, 13, 1048584, 458752, 13, 655367, 458753, 13, 655367, 458754, 13, 655367, 458755, 13, 655367, 458756, 13, 655367, 458757, 13, 655367, 458758, 13, 655367, 458759, 13, 655367, 458760, 13, 655367, 458761, 13, 655367, 458762, 13, 1441799, 458763, 13, 1441799, 458764, 13, 655366, 524282, 13, 655367, 524283, 13, 655367, 524284, 13, 655367, 524285, 13, 655367, 524286, 13, 655367, 524287, 13, 655367, -65513, 13, 1048579, -65512, 13, 7, -65511, 13, 7, -65510, 13, 7, -65509, 13, 7, -65508, 13, 1441796, -65507, 13, 655364, -65506, 13, 7, -65505, 13, 7, -65504, 13, 7, -65503, 13, 7, -65502, 13, 7, -65501, 13, 1441795, 21, 14, 15, 23, 14, 1048582, 28, 14, 9, 29, 14, 1048585, 35, 14, 1441800, 65548, 14, 1048584, 65549, 14, 1048583, 65550, 14, 1048583, 65551, 14, 1048583, 65552, 14, 1048583, 65553, 14, 655373, 65554, 14, 655373, 65555, 14, 1048583, 65556, 14, 1048583, 65564, 14, 9, 65565, 14, 1048585, 65571, 14, 1441800, 131084, 14, 1048584, 131090, 14, 655373, 131100, 14, 5, 131101, 14, 1048581, 131107, 14, 1441800, 196620, 14, 1048584, 196643, 14, 1441800, 262156, 14, 1048584, 262179, 14, 1441800, 327692, 14, 1048584, 327715, 14, 1441798, 393228, 14, 1048584, 458752, 14, 655367, 458753, 14, 655367, 458754, 14, 655367, 458755, 14, 655367, 458756, 14, 655367, 458757, 14, 655367, 458758, 14, 655367, 458759, 14, 655367, 458760, 14, 655367, 458761, 14, 655367, 458762, 14, 1441799, 458763, 14, 1441799, 458764, 14, 655366, 524282, 14, 655367, 524283, 14, 655367, 524284, 14, 655367, 524285, 14, 655367, 524286, 14, 655367, 524287, 14, 655367, -65513, 14, 1048579, -65512, 14, 7, -65511, 14, 7, -65510, 14, 7, -65509, 14, 7, -65508, 14, 4, -65507, 14, 1048580, -65506, 14, 7, -65505, 14, 7, -65504, 14, 7, -65503, 14, 7, -65502, 14, 7, -65501, 14, 1441795, 21, 15, 655368, 22, 15, 655368, 23, 15, 655368, 24, 15, 655369, 31, 15, 1441801, 32, 15, 655369, 35, 15, 1441800, 65548, 15, 1048584, 65549, 15, 655368, 65550, 15, 655368, 65551, 15, 655368, 65552, 15, 655368, 65553, 15, 655368, 65554, 15, 655368, 65555, 15, 655368, 65556, 15, 655368, 65557, 15, 655368, 65558, 15, 655368, 65559, 15, 655368, 65560, 15, 655369, 65567, 15, 1441801, 65568, 15, 655369, 65571, 15, 1441800, 131084, 15, 1048584, 131085, 15, 655368, 131086, 15, 655368, 131087, 15, 655368, 131088, 15, 655368, 131089, 15, 655368, 131090, 15, 655368, 131091, 15, 655368, 131092, 15, 655368, 131093, 15, 655368, 131094, 15, 655368, 131095, 15, 655368, 131096, 15, 655369, 131103, 15, 1441801, 131104, 15, 655369, 131107, 15, 1441800, 196620, 15, 1048584, 196621, 15, 655368, 196622, 15, 655368, 196623, 15, 655368, 196624, 15, 655368, 196625, 15, 655368, 196626, 15, 655368, 196627, 15, 655368, 196628, 15, 655368, 196629, 15, 655368, 196630, 15, 655368, 196631, 15, 655368, 196632, 15, 655369, 196639, 15, 1441797, 196640, 15, 655365, 196643, 15, 1441800, 262156, 15, 1048584, 262158, 15, 655368, 262159, 15, 655368, 262160, 15, 655368, 262161, 15, 655368, 262162, 15, 655368, 262163, 15, 655368, 262164, 15, 655368, 262165, 15, 655368, 262166, 15, 655368, 262167, 15, 655368, 262168, 15, 655369, 262179, 15, 1441800, 327692, 15, 1048584, 327693, 15, 655368, 327694, 15, 655368, 327695, 15, 655368, 327696, 15, 655368, 327697, 15, 655368, 327698, 15, 655368, 327699, 15, 655368, 327700, 15, 655366, 327701, 15, 655366, 327702, 15, 655366, 327703, 15, 655366, 327704, 15, 655365, 327715, 15, 1441798, 393228, 15, 1048584, 393229, 15, 655368, 393230, 15, 655368, 393231, 15, 655368, 393232, 15, 655368, 393233, 15, 655368, 393234, 15, 655368, 393235, 15, 655368, 458752, 15, 655367, 458753, 15, 655367, 458754, 15, 655367, 458755, 15, 655367, 458756, 15, 655367, 458757, 15, 655367, 458758, 15, 655367, 458759, 15, 655367, 458760, 15, 655367, 458761, 15, 655367, 458762, 15, 1441799, 458763, 15, 1441799, 458764, 15, 655366, 458765, 15, 655366, 458766, 15, 655366, 458767, 15, 655366, 458768, 15, 655366, 458769, 15, 655366, 458770, 15, 655366, 458771, 15, 655366, 524282, 15, 655367, 524284, 15, 655367, 524285, 15, 655367, 524286, 15, 655367, 524287, 15, 655367, -65512, 15, 655364, -65511, 15, 7, -65510, 15, 7, -65509, 15, 7, -65508, 15, 7, -65507, 15, 7, -65506, 15, 7, -65505, 15, 1441796, -65504, 15, 655364, -65503, 15, 7, -65502, 15, 7, -65501, 15, 1441795, 25, 16, 655369, 31, 16, 9, 32, 16, 1048585, 34, 16, 1441801, 65548, 16, 1048584, 65561, 16, 655369, 65567, 16, 9, 65568, 16, 1048585, 65570, 16, 1441801, 131084, 16, 1048584, 131097, 16, 655369, 131103, 16, 9, 131104, 16, 1048585, 131106, 16, 1441801, 196620, 16, 1048584, 196633, 16, 655369, 196639, 16, 5, 196640, 16, 1048581, 196642, 16, 1441801, 262156, 16, 1048584, 262169, 16, 655369, 262178, 16, 1441801, 327692, 16, 1048584, 327705, 16, 655365, 327714, 16, 1441797, 393228, 16, 1048584, 458752, 16, 655367, 458753, 16, 655367, 458754, 16, 655367, 458755, 16, 655367, 458756, 16, 655367, 458757, 16, 655367, 458758, 16, 655367, 458759, 16, 655367, 458760, 16, 655367, 458761, 16, 655367, 458762, 16, 1441799, 458763, 16, 1441799, 458764, 16, 655366, 524282, 16, 655367, 524284, 16, 655367, 524285, 16, 655367, 524286, 16, 655367, 524287, 16, 655367, -65511, 16, 655364, -65510, 16, 7, -65509, 16, 7, -65508, 16, 7, -65507, 16, 7, -65506, 16, 7, -65505, 16, 4, -65504, 16, 1048580, -65503, 16, 7, -65502, 16, 1441796, 25, 17, 1048584, 34, 17, 1441800, 65548, 17, 1048584, 65561, 17, 1048584, 65570, 17, 1441800, 131084, 17, 1048584, 131097, 17, 1048584, 131106, 17, 1441800, 196633, 17, 1048584, 196642, 17, 1441800, 262169, 17, 1048584, 262174, 17, 655377, 262177, 17, 655376, 262178, 17, 1441800, 327705, 17, 1048582, 327714, 17, 1441798, 458752, 17, 655367, 458753, 17, 655367, 458754, 17, 655367, 458755, 17, 655367, 458756, 17, 655367, 458757, 17, 655367, 458758, 17, 655367, 458759, 17, 655367, 458760, 17, 655367, 458761, 17, 655367, 458762, 17, 1441799, 458763, 17, 1441799, 458764, 17, 1441799, 524282, 17, 655367, 524283, 17, 655367, 524284, 17, 655367, 524285, 17, 655367, 524286, 17, 655367, 524287, 17, 655367, -65511, 17, 1048579, -65510, 17, 7, -65509, 17, 7, -65508, 17, 7, -65507, 17, 7, -65506, 17, 7, -65505, 17, 7, -65504, 17, 7, -65503, 17, 7, -65502, 17, 1441795, 26, 18, 655368, 27, 18, 655368, 28, 18, 655368, 29, 18, 655368, 30, 18, 655368, 31, 18, 655368, 32, 18, 655368, 33, 18, 655368, 65562, 18, 655368, 65563, 18, 655368, 65564, 18, 655368, 65565, 18, 655368, 65566, 18, 655368, 65567, 18, 655368, 65568, 18, 655368, 65569, 18, 655368, 131098, 18, 655368, 131099, 18, 655368, 131100, 18, 655368, 131101, 18, 655368, 131102, 18, 655368, 131103, 18, 655368, 131104, 18, 655368, 131105, 18, 655368, 196634, 18, 655368, 196635, 18, 655368, 196636, 18, 655368, 196637, 18, 655368, 196638, 18, 655368, 196639, 18, 655368, 196640, 18, 655368, 196641, 18, 655368, 262170, 18, 655368, 262171, 18, 655368, 262172, 18, 655368, 262173, 18, 655368, 262174, 18, 655369, 262175, 18, 655366, 262176, 18, 655366, 262177, 18, 1441801, 327706, 18, 655366, 327707, 18, 655366, 327708, 18, 655366, 327709, 18, 655366, 327710, 18, 655366, 327713, 18, 1441797, 458752, 18, 655367, 458753, 18, 655367, 458754, 18, 655367, 458755, 18, 655367, 458756, 18, 655367, 458757, 18, 655367, 458758, 18, 655367, 458759, 18, 655367, 458760, 18, 655367, 458762, 18, 1441799, 458763, 18, 1441799, 458764, 18, 1441799, 524283, 18, 655367, 524284, 18, 655367, 524285, 18, 655367, 524286, 18, 655367, 524287, 18, 655367, -65510, 18, 655363, -65509, 18, 655363, -65508, 18, 655363, -65507, 18, 655363, -65506, 18, 655363, -65505, 18, 655363, -65504, 18, 655363, -65503, 18, 655363, 524287, 19, 655367, 65540, 65533, 3, 131076, 65533, 2, 131077, 65533, 3, 196611, 65533, 1048579, 196612, 65533, 6, 196613, 65533, 6, 196614, 65533, 655366, 196615, 65533, 655366, 196616, 65533, 655366, 196617, 65533, 655366, 196618, 65533, 7, 196619, 65533, 655366, 196620, 65533, 1441801, 262147, 65533, 1048578, 262156, 65533, 1441801, 327683, 65533, 1048584, 327692, 65533, 1441801, 393219, 65533, 1048584, 393228, 65533, 1441801, 458764, 65533, 1441801, 524300, 65533, 1441797, 65539, 65534, 1048579, 65540, 65534, 1048583, 65541, 65534, 4, 131075, 65534, 1048578, 131077, 65534, 5, 131078, 65534, 4, 196611, 65534, 1048578, 196614, 65534, 5, 196615, 65534, 7, 196616, 65534, 655370, 196617, 65534, 7, 196618, 65534, 7, 196619, 65534, 7, 196620, 65534, 1441800, 262147, 65534, 1048578, 262152, 65534, 655372, 262156, 65534, 1441800, 327683, 65534, 1048584, 327688, 65534, 655373, 327692, 65534, 1441794, 393219, 65534, 1048584, 393228, 65534, 1441794, 458753, 65534, 655367, 458754, 65534, 655367, 458764, 65534, 1441794, 524300, 65534, 1441798, 4, 65535, 2, 5, 65535, 2, 6, 65535, 2, 7, 65535, 2, 8, 65535, 2, 9, 65535, 2, 10, 65535, 2, 11, 65535, 2, 65539, 65535, 1048579, 65540, 65535, 5, 65541, 65535, 1048581, 65542, 65535, 4, 65543, 65535, 2, 65544, 65535, 2, 65545, 65535, 2, 65546, 65535, 2, 65547, 65535, 2, 131075, 65535, 1048578, 131078, 65535, 5, 131079, 65535, 9, 131080, 65535, 2, 131081, 65535, 2, 131082, 65535, 2, 131083, 65535, 2, 196611, 65535, 1048578, 196615, 65535, 5, 196616, 65535, 6, 196617, 65535, 6, 196618, 65535, 6, 196619, 65535, 6, 196620, 65535, 1441800, 262147, 65535, 1048578, 262156, 65535, 1441800, 327683, 65535, 1048584, 327692, 65535, 1441794, 393219, 65535, 1048584, 393228, 65535, 1441794, 458752, 65535, 655367, 458753, 65535, 655367, 458754, 65535, 655367, 458755, 65535, 655367, 458764, 65535, 1441794, 524287, 65535, 655367, 524300, 65535, 1441798, -65532, 65535, 2, -65531, 65535, 2, -65530, 65535, 2, -65529, 65535, 2, -65528, 65535, 2, -65527, 65535, 2, -65526, 65535, 2, -65525, 65535, 2 </int_array> - </dictionary> - <dictionary shared="false"> - <string> "_editor_clip_" </string> - <int> 0 </int> - <string> "_editor_floor_" </string> - <vector3> 0, 2, 0 </vector3> - </dictionary> - <transform> 0.522923, 0.663002, -0.535706, -0.24539, 0.718971, 0.650281, 0.816294, -0.20859, 0.53866, 0, 0, 0 </transform> - <int> 1 </int> - <real> 1.5 </real> - <color> 0.159092, 0.219774, 0.52093, 1 </color> - <color> 1, 1, 1, 1 </color> - <real> 0 </real> - <real> 0.08 </real> - <real> 0.5 </real> - <resource name=""></resource> <int> 0 </int> - <int> 3 </int> - <real> 40 </real> - <real> 0.410558 </real> - <resource resource_type="Environment" path="local://1"> </resource> - <dictionary shared="false"> - <string> "_editor_collapsed" </string> - <bool> True </bool> - </dictionary> - <resource resource_type="PackedScene" path="res://coin.scn"> </resource> - <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 18.5311, 2.85075, 5.24675 </transform> - <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 18.5311, 2.85075, 7.24675 </transform> - <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 20.5311, 2.85075, 5.24675 </transform> - <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 20.5311, 2.85075, 7.24675 </transform> - <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 1.61344, 11.28, 11.0239 </transform> - <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 1.61344, 11.28, 13.0239 </transform> - <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 3.61344, 11.28, 11.0239 </transform> - <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 3.61344, 11.28, 13.0239 </transform> - <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 1.61344, 12.9027, 11.03 </transform> - <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 1.61344, 12.9027, 13.03 </transform> - <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 3.61344, 12.9027, 13.03 </transform> - <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 3.61344, 12.9027, 11.03 </transform> - <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 1.61344, 11.28, 15.0922 </transform> - <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 1.61344, 11.28, 17.0922 </transform> - <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 3.61344, 11.28, 17.0922 </transform> - <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 3.61344, 11.28, 15.0922 </transform> - <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 3.61344, 12.9027, 15.0983 </transform> - <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 3.61344, 12.9027, 17.0983 </transform> - <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 1.61344, 12.9027, 15.0983 </transform> - <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 1.61344, 12.9027, 17.0983 </transform> - <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 57.057, 4.14271, 26.9338 </transform> - <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 57.057, 4.14271, 28.9338 </transform> - <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 57.057, 5.76534, 26.9399 </transform> - <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 59.057, 5.76534, 28.9399 </transform> - <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 59.057, 5.76534, 26.9399 </transform> - <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 59.057, 4.14271, 28.9338 </transform> - <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 59.057, 4.14271, 26.9338 </transform> - <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 57.057, 5.76534, 28.9399 </transform> - <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 62.9108, 6.16547, 31.0899 </transform> - <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 64.9108, 7.7881, 31.096 </transform> - <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 62.9108, 6.16547, 33.0899 </transform> - <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 62.9108, 7.7881, 31.096 </transform> - <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 64.9108, 7.7881, 33.096 </transform> - <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 64.9108, 6.16547, 31.0899 </transform> - <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 64.9108, 6.16547, 33.0899 </transform> - <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 62.9108, 7.7881, 33.096 </transform> - <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 51.5614, 2.98252, 23.1775 </transform> - <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 53.5614, 4.60515, 23.1836 </transform> - <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 51.5614, 2.98252, 25.1775 </transform> - <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 53.5614, 2.98252, 23.1775 </transform> - <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 53.5614, 4.60515, 25.1836 </transform> - <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 51.5614, 4.60515, 23.1836 </transform> - <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 53.5614, 2.98252, 25.1775 </transform> - <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 51.5614, 4.60515, 25.1836 </transform> - <resource resource_type="PackedScene" path="res://enemy.scn"> </resource> - <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 18.3062, 5.40827, 5.96938 </transform> - <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 64.1292, 5.40827, 17.1396 </transform> - <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 64.1292, 5.40827, 32.6128 </transform> - <transform> 1, 0, 0, 0, 1, 0, 0, 0, 1, 55.5702, 5.40827, 32.6128 </transform> - <resource resource_type="PackedScene" path="res://player.xml"> </resource> - <transform> 0.0160676, 0, -0.999871, 0, 1, 0, 0.999871, 0, 0.0160676, 8.50167, 4.15811, 15.9334 </transform> - </array> - <string> "nodes" </string> - <int_array len="541"> -1, -1, 1, 0, -1, 1, 2, 0, 0, 0, 0, 3, 3, -1, 10, 4, 1, 5, 2, 6, 3, 7, 4, 8, 5, 9, 5, 10, 5, 11, 6, 12, 7, 2, 8, 0, 0, 0, 13, 13, -1, 16, 14, 9, 15, 10, 16, 11, 17, 12, 18, 13, 19, 13, 20, 5, 21, 14, 22, 15, 23, 16, 24, 17, 25, 18, 26, 19, 27, 20, 28, 21, 29, 3, 0, 0, 0, 31, 30, -1, 1, 30, 22, 0, 0, 0, 33, 32, -1, 1, 2, 23, 0, 4, 0, 35, 34, 24, 1, 14, 25, 0, 4, 0, 35, 36, 24, 1, 14, 26, 0, 4, 0, 35, 37, 24, 1, 14, 27, 0, 4, 0, 35, 38, 24, 1, 14, 28, 0, 4, 0, 35, 39, 24, 1, 14, 29, 0, 4, 0, 35, 40, 24, 1, 14, 30, 0, 4, 0, 35, 41, 24, 1, 14, 31, 0, 4, 0, 35, 42, 24, 1, 14, 32, 0, 4, 0, 35, 43, 24, 1, 14, 33, 0, 4, 0, 35, 44, 24, 1, 14, 34, 0, 4, 0, 35, 45, 24, 1, 14, 35, 0, 4, 0, 35, 46, 24, 1, 14, 36, 0, 4, 0, 35, 47, 24, 1, 14, 37, 0, 4, 0, 35, 48, 24, 1, 14, 38, 0, 4, 0, 35, 49, 24, 1, 14, 39, 0, 4, 0, 35, 50, 24, 1, 14, 40, 0, 4, 0, 35, 51, 24, 1, 14, 41, 0, 4, 0, 35, 52, 24, 1, 14, 42, 0, 4, 0, 35, 53, 24, 1, 14, 43, 0, 4, 0, 35, 54, 24, 1, 14, 44, 0, 4, 0, 35, 55, 24, 1, 14, 45, 0, 4, 0, 35, 56, 24, 1, 14, 46, 0, 4, 0, 35, 57, 24, 1, 14, 47, 0, 4, 0, 35, 58, 24, 1, 14, 48, 0, 4, 0, 35, 59, 24, 1, 14, 49, 0, 4, 0, 35, 60, 24, 1, 14, 50, 0, 4, 0, 35, 61, 24, 1, 14, 51, 0, 4, 0, 35, 62, 24, 1, 14, 52, 0, 4, 0, 35, 63, 24, 1, 14, 53, 0, 4, 0, 35, 64, 24, 1, 14, 54, 0, 4, 0, 35, 65, 24, 1, 14, 55, 0, 4, 0, 35, 66, 24, 1, 14, 56, 0, 4, 0, 35, 67, 24, 1, 14, 57, 0, 4, 0, 35, 68, 24, 1, 14, 58, 0, 4, 0, 35, 69, 24, 1, 14, 59, 0, 4, 0, 35, 70, 24, 1, 14, 60, 0, 4, 0, 35, 71, 24, 1, 14, 61, 0, 4, 0, 35, 72, 24, 1, 14, 62, 0, 4, 0, 35, 73, 24, 1, 14, 63, 0, 4, 0, 35, 74, 24, 1, 14, 64, 0, 4, 0, 35, 75, 24, 1, 14, 65, 0, 4, 0, 35, 76, 24, 1, 14, 66, 0, 4, 0, 35, 77, 24, 1, 14, 67, 0, 4, 0, 35, 78, 24, 1, 14, 68, 0, 0, 0, 33, 79, -1, 0, 0, 49, 0, 81, 80, 69, 1, 14, 70, 0, 49, 0, 81, 82, 69, 1, 14, 71, 0, 49, 0, 81, 83, 69, 1, 14, 72, 0, 49, 0, 81, 84, 69, 1, 14, 73, 0, 0, 0, 81, 85, 74, 1, 14, 75, 0 </int_array> - <string> "conns" </string> - <int_array len="0"> </int_array> - </dictionary> - - </main_resource> -</resource_file>
\ No newline at end of file diff --git a/demos/3d/platformer/tiles.res b/demos/3d/platformer/tiles.res Binary files differindex 0ab7c92ef6..e7e810f23f 100644 --- a/demos/3d/platformer/tiles.res +++ b/demos/3d/platformer/tiles.res diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp index 74a82e1a5c..91b82d1999 100644 --- a/drivers/gles2/rasterizer_gles2.cpp +++ b/drivers/gles2/rasterizer_gles2.cpp @@ -1042,8 +1042,8 @@ void RasterizerGLES2::texture_set_size_override(RID p_texture,int p_width, int p ERR_FAIL_COND(!texture); ERR_FAIL_COND(texture->render_target); - ERR_FAIL_COND(p_width<=0 || p_width>4096); - ERR_FAIL_COND(p_height<=0 || p_height>4096); + ERR_FAIL_COND(p_width<=0 || p_width>16384); + ERR_FAIL_COND(p_height<=0 || p_height>16384); //real texture size is in alloc width and height texture->width=p_width; texture->height=p_height; @@ -5471,6 +5471,7 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans const ParamOverrideMap* prev_overrides=NULL; // make it diferent than NULL const Skeleton *prev_skeleton =NULL; uint8_t prev_sort_flags=0xFF; + const BakedLightData *prev_baked_light=NULL; Geometry::Type prev_geometry_type=Geometry::GEOMETRY_INVALID; @@ -5486,6 +5487,9 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans material_shader.set_conditional(MaterialShaderGLES2::LIGHT_USE_PSSM,false); material_shader.set_conditional(MaterialShaderGLES2::LIGHT_USE_PSSM4,false); material_shader.set_conditional(MaterialShaderGLES2::SHADELESS,false); + material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_OCTREE,false); +// material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_TEXTURE,false); + } @@ -5503,8 +5507,10 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans uint8_t sort_flags= e->sort_flags; const Skeleton *skeleton = e->skeleton; const Geometry *geometry_cmp = e->geometry_cmp; + const BakedLightData *baked_light = e->instance->baked_light; bool rebind=false; + bool bind_baked_light_octree=false; bool additive=false; @@ -5622,6 +5628,32 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans current_blend_mode=desired_blend_mode; } + material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_OCTREE,false); +// material_shader.set_conditional(MaterialShaderGLES2::USE_AMBIENT_TEXTURE,false); + + if (!additive && baked_light) { + + if (baked_light->mode==VS::BAKED_LIGHT_OCTREE && baked_light->octree_texture.is_valid() && e->instance->baked_light_octree_xform) { + material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_OCTREE,true); + bind_baked_light_octree=true; + if (prev_baked_light!=baked_light) { + Texture *tex=texture_owner.get(baked_light->octree_texture); + if (tex) { + + glActiveTexture(GL_TEXTURE5); + glBindTexture(tex->target,tex->tex_id); //bind the texture + } + + } + } else if (baked_light->mode==VS::BAKED_LIGHT_LIGHTMAPS) { + + //material_shader.set_conditional(MaterialShaderGLES2::ENABLE_AMBIENT_TEXTURE,true); + } + } + + if (int(prev_baked_light!=NULL) ^ int(baked_light!=NULL)) { + rebind=true; + } } if (sort_flags!=prev_sort_flags) { @@ -5672,6 +5704,18 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans } } + if (bind_baked_light_octree && (baked_light!=prev_baked_light || rebind)) { + + material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_INVERSE_TRANSFORM, *e->instance->baked_light_octree_xform); + material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_LATTICE_SIZE, baked_light->octree_lattice_size); + material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_LATTICE_DIVIDE, baked_light->octree_lattice_divide); + material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_STEPS, baked_light->octree_steps); + material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_TEX,5); + material_shader.set_uniform(MaterialShaderGLES2::AMBIENT_OCTREE_PIX_SIZE,baked_light->octree_tex_pixel_size); + + + } + _set_cull(e->mirror,p_reverse_cull); @@ -5726,6 +5770,7 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans prev_light=e->light; prev_light_type=e->light_type; prev_sort_flags=sort_flags; + prev_baked_light=baked_light; // prev_geometry_type=geometry->type; } diff --git a/drivers/gles2/shaders/material.glsl b/drivers/gles2/shaders/material.glsl index a919e3b1e2..7ed59ae9cd 100644 --- a/drivers/gles2/shaders/material.glsl +++ b/drivers/gles2/shaders/material.glsl @@ -93,6 +93,13 @@ varying vec3 tangent_interp; varying vec3 binormal_interp; #endif +#ifdef ENABLE_AMBIENT_OCTREE + +uniform highp mat4 ambient_octree_inverse_transform; +varying highp vec3 ambient_octree_coords; + +#endif + #ifdef USE_FOG varying vec4 fog_interp; @@ -173,12 +180,19 @@ void main() { #ifdef USE_UNIFORM_INSTANCING highp mat4 modelview = (camera_inverse_transform * (world_transform * instance_transform)); +#ifdef ENABLE_AMBIENT_OCTREE + highp mat4 ambient_octree_transform = (ambient_octree_inverse_transform * (world_transform * instance_transform)); +#endif + #else #ifdef USE_ATTRIBUTE_INSTANCING highp mat4 minst=mat4(instance_row0,instance_row1,instance_row2,instance_row3); highp mat4 modelview = (camera_inverse_transform * (world_transform * minst)); +#ifdef ENABLE_AMBIENT_OCTREE + highp mat4 ambient_octree_transform = (ambient_octree_inverse_transform * (world_transform * minst)); +#endif #else @@ -201,9 +215,16 @@ void main() { );*/ highp mat4 modelview = (camera_inverse_transform * (world_transform * minst)); +#ifdef ENABLE_AMBIENT_OCTREE + highp mat4 ambient_octree_transform = (ambient_octree_inverse_transform * (world_transform * minst)); +#endif #else highp mat4 modelview = (camera_inverse_transform * world_transform); +#ifdef ENABLE_AMBIENT_OCTREE + highp mat4 ambient_octree_transform = (ambient_octree_inverse_transform * world_transform); +#endif + #endif #endif @@ -233,6 +254,11 @@ void main() { #endif +#ifdef ENABLE_AMBIENT_OCTREE + + ambient_octree_coords = (ambient_octree_transform * vertex_in).xyz; +#endif + vertex_interp = (modelview * vertex_in).xyz; normal_interp = normalize((modelview * vec4(normal_in,0.0)).xyz); @@ -515,6 +541,16 @@ vec3 process_shade(in vec3 normal, in vec3 light_dir, in vec3 eye_vec, in vec3 d uniform float const_light_mult; uniform float time; +#ifdef ENABLE_AMBIENT_OCTREE + +varying highp vec3 ambient_octree_coords; +uniform highp float ambient_octree_lattice_size; +uniform highp vec2 ambient_octree_pix_size; +uniform highp float ambient_octree_lattice_divide; +uniform highp sampler2D ambient_octree_tex; +uniform int ambient_octree_steps; + +#endif FRAGMENT_SHADER_GLOBALS @@ -745,10 +781,57 @@ FRAGMENT_SHADER_CODE } #endif +#ifdef ENABLE_AMBIENT_OCTREE + + vec3 ambientmap_color = vec3(0.0,0.0,0.0); + + + { + + //read position from initial lattice grid + highp vec3 lattice_pos = floor(ambient_octree_coords*ambient_octree_lattice_size); + highp vec2 octant_uv = highp vec2(lattice_pos.x+ambient_octree_lattice_size*lattice_pos.z,lattice_pos.y); + octant_uv=(octant_uv*highp vec2(2.0,4.0)+highp vec2(0.0,4.0)); + highp float ld = 1.0/ambient_octree_lattice_size; + + + //go down the octree + + for(int i=0;i<ambient_octree_steps;i++) { + + + highp vec3 sub=mod(ambient_octree_coords,ld); + ld*=0.5; + highp vec3 s = step(ld,sub); + octant_uv+=s.xy; + octant_uv.y+=s.z*2.0; + octant_uv=(octant_uv+0.5)*ambient_octree_pix_size; + highp vec4 new_uv = texture2D(ambient_octree_tex,octant_uv); + octant_uv=floor(highp vec2( dot(new_uv.xy,highp vec2(65280.0,255.0)), dot(new_uv.zw,highp vec2(65280.0,255.0)) )+0.5);//+ambient_octree_pix_size*0.5; + + } + + //sample color + octant_uv=(octant_uv+0.5)*ambient_octree_pix_size; + highp vec3 sub=(mod(ambient_octree_coords,ld)/ld); + octant_uv.xy+=sub.xy*ambient_octree_pix_size.xy; + vec3 col_up=texture2D(ambient_octree_tex,octant_uv).rgb; + octant_uv.y+=ambient_octree_pix_size.y*2.0; + vec3 col_down=texture2D(ambient_octree_tex,octant_uv).rgb; + ambientmap_color=mix(col_down,col_up,1.0-sub.z); + + ambientmap_color*=diffuse.rgb; + + } + +#endif float shadow_attenuation = 1.0; + + + #ifdef LIGHT_USE_SHADOW #ifdef LIGHT_TYPE_DIRECTIONAL @@ -921,6 +1004,8 @@ FRAGMENT_SHADER_CODE #endif + + #ifdef USE_VERTEX_LIGHTING vec3 ambient = light_ambient*diffuse.rgb; @@ -933,11 +1018,13 @@ FRAGMENT_SHADER_CODE diffuse.rgb=(diffuse.rgb * diffuse_interp.rgb + specular * specular_interp)*shadow_attenuation + ambient; diffuse.rgb+=emission * const_light_mult; - #endif +#ifdef ENABLE_AMBIENT_OCTREE + diffuse.rgb+=ambientmap_color; +#endif #ifdef USE_SHADOW_PASS diff --git a/drivers/unix/ip_unix.cpp b/drivers/unix/ip_unix.cpp index 18b19ca095..24b18a14f7 100644 --- a/drivers/unix/ip_unix.cpp +++ b/drivers/unix/ip_unix.cpp @@ -130,6 +130,8 @@ void IP_Unix::get_local_addresses(List<IP_Address> *r_addresses) const { getifaddrs(&ifAddrStruct); for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next) { + if (!ifa->ifa_addr) + continue; if (ifa ->ifa_addr->sa_family==AF_INET) { // check it is IP4 // is a valid IP4 Address diff --git a/modules/gdscript/gd_script.cpp b/modules/gdscript/gd_script.cpp index d183782864..2885b754be 100644 --- a/modules/gdscript/gd_script.cpp +++ b/modules/gdscript/gd_script.cpp @@ -31,6 +31,7 @@ #include "global_constants.h" #include "gd_compiler.h" #include "os/file_access.h" +#include "io/file_access_encrypted.h" /* TODO: @@ -1591,7 +1592,28 @@ void GDScript::_bind_methods() { Error GDScript::load_byte_code(const String& p_path) { - Vector<uint8_t> bytecode = FileAccess::get_file_as_array(p_path); + Vector<uint8_t> bytecode; + + if (p_path.ends_with("gde")) { + + FileAccess *fa = FileAccess::open(p_path,FileAccess::READ); + ERR_FAIL_COND_V(!fa,ERR_CANT_OPEN); + FileAccessEncrypted *fae = memnew( FileAccessEncrypted ); + ERR_FAIL_COND_V(!fae,ERR_CANT_OPEN); + Vector<uint8_t> key; + key.resize(32); + for(int i=0;i<key.size();i++) { + key[i]=script_encryption_key[i]; + } + Error err = fae->open_and_parse(fa,key,FileAccessEncrypted::MODE_READ); + ERR_FAIL_COND_V(err,err); + bytecode.resize(fae->get_len()); + fae->get_buffer(bytecode.ptr(),bytecode.size()); + memdelete(fae); + } else { + + bytecode = FileAccess::get_file_as_array(p_path); + } ERR_FAIL_COND_V(bytecode.size()==0,ERR_PARSE_ERROR); path=p_path; @@ -2225,7 +2247,7 @@ RES ResourceFormatLoaderGDScript::load(const String &p_path,const String& p_orig Ref<GDScript> scriptres(script); - if (p_path.ends_with(".gdc")) { + if (p_path.ends_with(".gde") || p_path.ends_with(".gdc")) { script->set_script_path(p_original_path); // script needs this. script->set_path(p_original_path); @@ -2258,6 +2280,7 @@ void ResourceFormatLoaderGDScript::get_recognized_extensions(List<String> *p_ext p_extensions->push_back("gd"); p_extensions->push_back("gdc"); + p_extensions->push_back("gde"); } bool ResourceFormatLoaderGDScript::handles_type(const String& p_type) const { @@ -2268,7 +2291,7 @@ bool ResourceFormatLoaderGDScript::handles_type(const String& p_type) const { String ResourceFormatLoaderGDScript::get_resource_type(const String &p_path) const { String el = p_path.extension().to_lower(); - if (el=="gd" || el=="gdc") + if (el=="gd" || el=="gdc" || el=="gde") return "GDScript"; return ""; } diff --git a/modules/gdscript/gd_tokenizer.cpp b/modules/gdscript/gd_tokenizer.cpp index aeee1f6667..a92e2f22ea 100644 --- a/modules/gdscript/gd_tokenizer.cpp +++ b/modules/gdscript/gd_tokenizer.cpp @@ -757,6 +757,7 @@ void GDTokenizerText::_advance() { {Variant::_RID,"RID"}, {Variant::OBJECT,"Object"}, {Variant::INPUT_EVENT,"InputEvent"}, + {Variant::NODE_PATH,"NodePath"}, {Variant::DICTIONARY,"dict"}, {Variant::DICTIONARY,"Dictionary"}, {Variant::ARRAY,"Array"}, diff --git a/modules/gdscript/register_types.cpp b/modules/gdscript/register_types.cpp index 6bcd12857b..abb3d5a946 100644 --- a/modules/gdscript/register_types.cpp +++ b/modules/gdscript/register_types.cpp @@ -14,6 +14,8 @@ #include "gd_script.h" #include "io/resource_loader.h" #include "os/file_access.h" +#include "io/file_access_encrypted.h" + GDScriptLanguage *script_language_gd=NULL; @@ -25,6 +27,7 @@ ResourceFormatSaverGDScript *resource_saver_gd=NULL; #include "tools/editor/editor_import_export.h" #include "gd_tokenizer.h" #include "tools/editor/editor_node.h" +#include "tools/editor/editor_settings.h" class EditorExportGDScript : public EditorExportPlugin { @@ -34,20 +37,69 @@ public: virtual Vector<uint8_t> custom_export(String& p_path,const Ref<EditorExportPlatform> &p_platform) { //compile gdscript to bytecode - if (p_path.ends_with(".gd")) { - Vector<uint8_t> file = FileAccess::get_file_as_array(p_path); - if (file.empty()) - return file; - String txt; - txt.parse_utf8((const char*)file.ptr(),file.size()); - file = GDTokenizerBuffer::parse_code_string(txt); - if (!file.empty()) { - print_line("PREV: "+p_path); - p_path=p_path.basename()+".gdc"; - print_line("NOW: "+p_path); - return file; - } + if (EditorImportExport::get_singleton()->script_get_action()!=EditorImportExport::SCRIPT_ACTION_NONE) { + + if (p_path.ends_with(".gd")) { + Vector<uint8_t> file = FileAccess::get_file_as_array(p_path); + if (file.empty()) + return file; + String txt; + txt.parse_utf8((const char*)file.ptr(),file.size()); + file = GDTokenizerBuffer::parse_code_string(txt); + + if (!file.empty()) { + + if (EditorImportExport::get_singleton()->script_get_action()==EditorImportExport::SCRIPT_ACTION_ENCRYPT) { + + String tmp_path=EditorSettings::get_singleton()->get_settings_path().plus_file("tmp/script.gde"); + FileAccess *fa = FileAccess::open(tmp_path,FileAccess::WRITE); + String skey=EditorImportExport::get_singleton()->script_get_encryption_key().to_lower(); + Vector<uint8_t> key; + key.resize(32); + for(int i=0;i<32;i++) { + int v=0; + if (i*2<skey.length()) { + CharType ct = skey[i*2]; + if (ct>='0' && ct<='9') + ct=ct-'0'; + else if (ct>='a' && ct<='f') + ct=10+ct-'a'; + v|=ct<<4; + } + + if (i*2+1<skey.length()) { + CharType ct = skey[i*2+1]; + if (ct>='0' && ct<='9') + ct=ct-'0'; + else if (ct>='a' && ct<='f') + ct=10+ct-'a'; + v|=ct; + } + key[i]=v; + } + FileAccessEncrypted *fae=memnew(FileAccessEncrypted); + Error err = fae->open_and_parse(fa,key,FileAccessEncrypted::MODE_WRITE_AES256); + if (err==OK) { + + fae->store_buffer(file.ptr(),file.size()); + p_path=p_path.basename()+".gde"; + } + + memdelete(fae); + + file=FileAccess::get_file_as_array(tmp_path); + return file; + + + } else { + + p_path=p_path.basename()+".gdc"; + return file; + } + } + + } } return Vector<uint8_t>(); diff --git a/modules/gridmap/grid_map.cpp b/modules/gridmap/grid_map.cpp index 7ccd85702d..d258e26a0e 100644 --- a/modules/gridmap/grid_map.cpp +++ b/modules/gridmap/grid_map.cpp @@ -31,7 +31,9 @@ #include "scene/resources/surface_tool.h" #include "message_queue.h" #include "scene/3d/light.h" +#include "scene/3d/baked_light_instance.h" #include "io/marshalls.h" +#include "scene/scene_string_names.h" bool GridMap::_set(const StringName& p_name, const Variant& p_value) { @@ -53,6 +55,8 @@ bool GridMap::_set(const StringName& p_name, const Variant& p_value) { set_center_z(p_value); } else if (name=="cell/scale") { set_cell_scale(p_value); + } else if (name=="lighting/bake") { + set_use_baked_light(p_value); } else if (name=="theme/bake") { set_bake(p_value); /* } else if (name=="cells") { @@ -120,6 +124,7 @@ bool GridMap::_set(const StringName& p_name, const Variant& p_value) { g.baked=b; g.bake_instance=VS::get_singleton()->instance_create();; VS::get_singleton()->instance_set_base(g.bake_instance,g.baked->get_rid()); + VS::get_singleton()->instance_geometry_set_baked_light(g.bake_instance,baked_light_instance?baked_light_instance->get_baked_light_instance():RID()); } } @@ -169,6 +174,8 @@ bool GridMap::_get(const StringName& p_name,Variant &r_ret) const { r_ret= get_center_z(); } else if (name=="cell/scale") { r_ret= cell_scale; + } else if (name=="lighting/bake") { + r_ret=is_using_baked_light(); } else if (name=="theme/bake") { r_ret= bake; } else if (name=="data") { @@ -231,6 +238,7 @@ void GridMap::_get_property_list( List<PropertyInfo> *p_list) const { p_list->push_back( PropertyInfo( Variant::OBJECT, "theme/theme", PROPERTY_HINT_RESOURCE_TYPE, "MeshLibrary")); p_list->push_back( PropertyInfo( Variant::BOOL, "theme/bake")); + p_list->push_back( PropertyInfo( Variant::BOOL, "lighting/bake")); p_list->push_back( PropertyInfo( Variant::REAL, "cell/size",PROPERTY_HINT_RANGE,"0.01,16384,0.01") ); p_list->push_back( PropertyInfo( Variant::INT, "cell/octant_size",PROPERTY_HINT_RANGE,"1,1024,1") ); p_list->push_back( PropertyInfo( Variant::BOOL, "cell/center_x") ); @@ -428,6 +436,8 @@ void GridMap::set_cell_item(int p_x,int p_y,int p_z, int p_item,int p_rot){ ii.multimesh->set_mesh(ii.mesh); ii.multimesh_instance = VS::get_singleton()->instance_create(); VS::get_singleton()->instance_set_base(ii.multimesh_instance,ii.multimesh->get_rid()); + VS::get_singleton()->instance_geometry_set_baked_light(ii.multimesh_instance,baked_light_instance?baked_light_instance->get_baked_light_instance():RID()); + if (!baked_lock) { //unbake just in case @@ -863,6 +873,12 @@ void GridMap::_notification(int p_what) { awaiting_update=false; last_transform=get_global_transform(); + + if (use_baked_light) { + + _find_baked_light(); + } + } break; case NOTIFICATION_TRANSFORM_CHANGED: { @@ -883,6 +899,17 @@ void GridMap::_notification(int p_what) { _octant_exit_world(E->key()); } + if (use_baked_light) { + + if (baked_light_instance) { + baked_light_instance->disconnect(SceneStringNames::get_singleton()->baked_light_changed,this,SceneStringNames::get_singleton()->_baked_light_changed); + baked_light_instance=NULL; + } + _baked_light_changed(); + + } + + //_queue_dirty_map(MAP_DIRTY_INSTANCES|MAP_DIRTY_TRANSFORMS); //_update_dirty_map_callback(); //_update_area_instances(); @@ -1028,6 +1055,14 @@ void GridMap::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_unused_area_id","area"),&GridMap::get_unused_area_id); ObjectTypeDB::bind_method(_MD("bake_geometry"),&GridMap::bake_geometry); + ObjectTypeDB::bind_method(_MD("_baked_light_changed"),&GridMap::_baked_light_changed); + ObjectTypeDB::bind_method(_MD("set_use_baked_light","use"),&GridMap::set_use_baked_light); + ObjectTypeDB::bind_method(_MD("is_using_baked_light","use"),&GridMap::is_using_baked_light); + + ObjectTypeDB::bind_method(_MD("_get_baked_light_meshes"),&GridMap::_get_baked_light_meshes); + + + ObjectTypeDB::set_method_flags("GridMap","bake_geometry",METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR); ObjectTypeDB::bind_method(_MD("clear"),&GridMap::clear); @@ -1496,6 +1531,108 @@ void GridMap::bake_geometry() { } +void GridMap::_baked_light_changed() { + +// if (!baked_light_instance) +// VS::get_singleton()->instance_geometry_set_baked_light(get_instance(),RID()); +// else +// VS::get_singleton()->instance_geometry_set_baked_light(get_instance(),baked_light_instance->get_baked_light_instance()); + for(Map<OctantKey,Octant*>::Element *E=octant_map.front();E;E=E->next()) { + + for(Map<int,Octant::ItemInstances>::Element *F=E->get()->items.front();F;F=F->next()) { + + VS::get_singleton()->instance_geometry_set_baked_light(F->get().multimesh_instance,baked_light_instance?baked_light_instance->get_baked_light_instance():RID()); + } + + } + +} + +void GridMap::_find_baked_light() { + + Node *n=get_parent(); + while(n) { + + BakedLightInstance *bl=n->cast_to<BakedLightInstance>(); + if (bl) { + + baked_light_instance=bl; + baked_light_instance->connect(SceneStringNames::get_singleton()->baked_light_changed,this,SceneStringNames::get_singleton()->_baked_light_changed); + _baked_light_changed(); + + return; + } + + n=n->get_parent(); + } + + _baked_light_changed(); +} + + +Array GridMap::_get_baked_light_meshes() { + + if (theme.is_null()) + return Array(); + + Vector3 ofs(cell_size*0.5*int(center_x),cell_size*0.5*int(center_y),cell_size*0.5*int(center_z)); + Array meshes; + + for (Map<IndexKey,Cell>::Element *E=cell_map.front();E;E=E->next()) { + + + int id = E->get().item; + if (!theme->has_item(id)) + continue; + Ref<Mesh> mesh=theme->get_item_mesh(id); + if (mesh.is_null()) + continue; + + IndexKey ik=E->key(); + + Vector3 cellpos = Vector3(ik.x,ik.y,ik.z ); + + Transform xform; + + xform.basis.set_orthogonal_index(E->get().rot); + + + xform.set_origin( cellpos*cell_size+ofs); + xform.basis.scale(Vector3(cell_scale,cell_scale,cell_scale)); + + meshes.push_back(xform); + meshes.push_back(mesh); + + } + + return meshes; +} + +void GridMap::set_use_baked_light(bool p_use) { + + if (use_baked_light==p_use) + return; + + use_baked_light=p_use; + + if (is_inside_world()) { + if (!p_use) { + if (baked_light_instance) { + baked_light_instance->disconnect(SceneStringNames::get_singleton()->baked_light_changed,this,SceneStringNames::get_singleton()->_baked_light_changed); + baked_light_instance=NULL; + } + _baked_light_changed(); + } else { + _find_baked_light(); + } + } + +} + +bool GridMap::is_using_baked_light() const{ + + return use_baked_light; +} GridMap::GridMap() { @@ -1516,7 +1653,8 @@ GridMap::GridMap() { bake=false; cell_scale=1.0; - + baked_light_instance=NULL; + use_baked_light=false; } diff --git a/modules/gridmap/grid_map.h b/modules/gridmap/grid_map.h index 7a13ace143..df805d99fa 100644 --- a/modules/gridmap/grid_map.h +++ b/modules/gridmap/grid_map.h @@ -38,6 +38,8 @@ //should scale better with hardware that supports instancing +class BakedLightInstance; + class GridMap : public Spatial { @@ -202,6 +204,14 @@ class GridMap : public Spatial { void _clear_internal(bool p_keep_areas=false); + BakedLightInstance *baked_light_instance; + bool use_baked_light; + void _find_baked_light(); + void _baked_light_changed(); + + + Array _get_baked_light_meshes(); + protected: bool _set(const StringName& p_name, const Variant& p_value); @@ -211,6 +221,7 @@ protected: void _notification(int p_what); static void _bind_methods(); + public: enum { @@ -262,6 +273,8 @@ public: void bake_geometry(); + void set_use_baked_light(bool p_use); + bool is_using_baked_light() const; void clear(); GridMap(); diff --git a/platform/javascript/detect.py b/platform/javascript/detect.py index da92c0869b..e4cdaad313 100644 --- a/platform/javascript/detect.py +++ b/platform/javascript/detect.py @@ -30,7 +30,7 @@ def get_flags(): ('theora', 'no'), ('tools', 'no'), ('nedmalloc', 'no'), - ('vorbis', 'yes'), + ('vorbis', 'no'), ('musepack', 'no'), ('squirrel', 'no'), ('squish', 'no'), diff --git a/scene/3d/baked_light.cpp b/scene/3d/baked_light.cpp deleted file mode 100644 index 55832b7c18..0000000000 --- a/scene/3d/baked_light.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include "baked_light.h" -#include "mesh_instance.h" - -BakedLight::BakedLight() { - - -} diff --git a/scene/3d/baked_light.h b/scene/3d/baked_light.h deleted file mode 100644 index a6f997afe9..0000000000 --- a/scene/3d/baked_light.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef BAKED_LIGHT_H -#define BAKED_LIGHT_H - -#include "scene/3d/spatial.h" -class BakedLightBaker; - - -class BakedLight : public Spatial { - OBJ_TYPE(BakedLight,Spatial); - -public: - BakedLight(); -}; - -#endif // BAKED_LIGHT_H diff --git a/scene/3d/baked_light_instance.cpp b/scene/3d/baked_light_instance.cpp new file mode 100644 index 0000000000..c1cc1f6b68 --- /dev/null +++ b/scene/3d/baked_light_instance.cpp @@ -0,0 +1,65 @@ +#include "baked_light_instance.h" +#include "scene/scene_string_names.h" + + +RID BakedLightInstance::get_baked_light_instance() const { + + if (baked_light.is_null()) + return RID(); + else + return get_instance(); + +} + +void BakedLightInstance::set_baked_light(const Ref<BakedLight>& p_baked_light) { + + baked_light=p_baked_light; + + RID base_rid; + + if (baked_light.is_valid()) + base_rid=baked_light->get_rid(); + else + base_rid=RID(); + + set_base(base_rid); + + if (is_inside_world()) { + + emit_signal(SceneStringNames::get_singleton()->baked_light_changed); + +// for (List<Node*>::Element *E=baked_geometry.front();E;E=E->next()) { +// VS::get_singleton()->instance_geometry_set_baked_light(E->get()->get_instance(),baked_light.is_valid()?get_instance():RID()); +// } + } +} + +Ref<BakedLight> BakedLightInstance::get_baked_light() const{ + + return baked_light; +} + +AABB BakedLightInstance::get_aabb() const { + + return AABB(Vector3(0,0,0),Vector3(1,1,1)); +} +DVector<Face3> BakedLightInstance::get_faces(uint32_t p_usage_flags) const { + + return DVector<Face3>(); +} + + +void BakedLightInstance::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("set_baked_light","baked_light"),&BakedLightInstance::set_baked_light); + ObjectTypeDB::bind_method(_MD("get_baked_light"),&BakedLightInstance::get_baked_light); + ObjectTypeDB::bind_method(_MD("get_baked_light_instance"),&BakedLightInstance::get_baked_light_instance); + + ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"baked_light",PROPERTY_HINT_RESOURCE_TYPE,"BakedLight"),_SCS("set_baked_light"),_SCS("get_baked_light")); + ADD_SIGNAL( MethodInfo("baked_light_changed")); +} + +BakedLightInstance::BakedLightInstance() { + + +} diff --git a/scene/3d/baked_light_instance.h b/scene/3d/baked_light_instance.h new file mode 100644 index 0000000000..b904ced9a7 --- /dev/null +++ b/scene/3d/baked_light_instance.h @@ -0,0 +1,33 @@ +#ifndef BAKED_LIGHT_INSTANCE_H +#define BAKED_LIGHT_INSTANCE_H + +#include "scene/3d/visual_instance.h" +#include "scene/resources/baked_light.h" + +class BakedLightBaker; + + +class BakedLightInstance : public VisualInstance { + OBJ_TYPE(BakedLightInstance,VisualInstance); + + Ref<BakedLight> baked_light; + + +protected: + + static void _bind_methods(); +public: + + + RID get_baked_light_instance() const; + + void set_baked_light(const Ref<BakedLight>& baked_light); + Ref<BakedLight> get_baked_light() const; + + virtual AABB get_aabb() const; + virtual DVector<Face3> get_faces(uint32_t p_usage_flags) const; + + BakedLightInstance(); +}; + +#endif // BAKED_LIGHT_H diff --git a/scene/3d/light.cpp b/scene/3d/light.cpp index b4b7b400c6..7cc1d12daa 100644 --- a/scene/3d/light.cpp +++ b/scene/3d/light.cpp @@ -351,6 +351,17 @@ void Light::set_operator(Operator p_op) { } +void Light::set_bake_mode(BakeMode p_bake_mode) { + + bake_mode=p_bake_mode; +} + +Light::BakeMode Light::get_bake_mode() const { + + return bake_mode; +} + + Light::Operator Light::get_operator() const { return op; @@ -416,6 +427,18 @@ void Light::approximate_opengl_attenuation(float p_constant, float p_linear, flo } +void Light::set_enabled(bool p_enabled) { + + enabled=p_enabled; + VS::get_singleton()->instance_light_set_enabled(get_instance(),enabled); +} + +bool Light::is_enabled() const{ + + return enabled; +} + + void Light::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_parameter","variable","value"), &Light::set_parameter ); @@ -428,8 +451,14 @@ void Light::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_projector:Texture"), &Light::get_projector ); ObjectTypeDB::bind_method(_MD("set_operator","operator"), &Light::set_operator ); ObjectTypeDB::bind_method(_MD("get_operator"), &Light::get_operator ); + ObjectTypeDB::bind_method(_MD("set_bake_mode","bake_mode"), &Light::set_bake_mode ); + ObjectTypeDB::bind_method(_MD("get_bake_mode"), &Light::get_bake_mode ); + ObjectTypeDB::bind_method(_MD("set_enabled","enabled"), &Light::set_enabled ); + ObjectTypeDB::bind_method(_MD("is_enabled"), &Light::is_enabled ); + ADD_PROPERTY( PropertyInfo( Variant::BOOL, "params/enabled"), _SCS("set_enabled"), _SCS("is_enabled")); + ADD_PROPERTY( PropertyInfo( Variant::INT, "params/bake_mode",PROPERTY_HINT_ENUM,"Disabled,Indirect,Full"), _SCS("set_bake_mode"), _SCS("get_bake_mode")); ADD_PROPERTYI( PropertyInfo( Variant::REAL, "params/energy", PROPERTY_HINT_EXP_RANGE, "0,64,0.01"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_ENERGY ); /* if (type == VisualServer::LIGHT_OMNI || type == VisualServer::LIGHT_SPOT) { @@ -490,6 +519,8 @@ Light::Light(VisualServer::LightType p_type) { op=OPERATOR_ADD; set_project_shadows( false ); set_base(light); + enabled=true; + bake_mode=BAKE_MODE_DISABLED; } @@ -563,6 +594,7 @@ DirectionalLight::DirectionalLight() : Light( VisualServer::LIGHT_DIRECTIONAL ) shadow_param[SHADOW_PARAM_PSSM_SPLIT_WEIGHT]=0.5; shadow_param[SHADOW_PARAM_PSSM_ZOFFSET_SCALE]=2.0; + } diff --git a/scene/3d/light.h b/scene/3d/light.h index dea7dbee6c..76b44c8712 100644 --- a/scene/3d/light.h +++ b/scene/3d/light.h @@ -64,6 +64,14 @@ public: COLOR_SPECULAR=VisualServer::LIGHT_COLOR_SPECULAR }; + enum BakeMode { + + BAKE_MODE_DISABLED, + BAKE_MODE_INDIRECT, + BAKE_MODE_FULL + + }; + enum Operator { @@ -78,8 +86,10 @@ private: Color colors[3]; + BakeMode bake_mode; VisualServer::LightType type; bool shadows; + bool enabled; Operator op; // bind helpers @@ -114,6 +124,12 @@ public: void set_operator(Operator p_op); Operator get_operator() const; + void set_bake_mode(BakeMode p_bake_mode); + BakeMode get_bake_mode() const; + + void set_enabled(bool p_enabled); + bool is_enabled() const; + virtual AABB get_aabb() const; virtual DVector<Face3> get_faces(uint32_t p_usage_flags) const; @@ -127,6 +143,7 @@ public: VARIANT_ENUM_CAST( Light::Parameter ); VARIANT_ENUM_CAST( Light::LightColor ); VARIANT_ENUM_CAST( Light::Operator ); +VARIANT_ENUM_CAST( Light::BakeMode); class DirectionalLight : public Light { diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp index 21fdb9abd3..49e593c1f5 100644 --- a/scene/3d/sprite_3d.cpp +++ b/scene/3d/sprite_3d.cpp @@ -479,6 +479,7 @@ void Sprite3D::set_frame(int p_frame) { if (frame != p_frame) frame=p_frame; + _queue_update(); } int Sprite3D::get_frame() const { diff --git a/scene/3d/sprite_3d.h b/scene/3d/sprite_3d.h index 1330cd1c30..fe8e1f6ebf 100644 --- a/scene/3d/sprite_3d.h +++ b/scene/3d/sprite_3d.h @@ -5,9 +5,9 @@ #include "scene/2d/animated_sprite.h" -class SpriteBase3D : public VisualInstance { +class SpriteBase3D : public GeometryInstance { - OBJ_TYPE(SpriteBase3D,VisualInstance); + OBJ_TYPE(SpriteBase3D,GeometryInstance); public: enum DrawFlags { diff --git a/scene/3d/visual_instance.cpp b/scene/3d/visual_instance.cpp index 96f16ab8c8..625da9b093 100644 --- a/scene/3d/visual_instance.cpp +++ b/scene/3d/visual_instance.cpp @@ -31,7 +31,7 @@ #include "servers/visual_server.h" #include "room_instance.h" #include "scene/scene_string_names.h" - +#include "baked_light_instance.h" #include "skeleton.h" AABB VisualInstance::get_transformed_aabb() const { @@ -186,6 +186,61 @@ float GeometryInstance::get_draw_range_end() const { return draw_end; } +void GeometryInstance::_notification(int p_what) { + + if (p_what==NOTIFICATION_ENTER_WORLD) { + + if (flags[FLAG_USE_BAKED_LIGHT]) { + + _find_baked_light(); + } + + + } else if (p_what==NOTIFICATION_EXIT_WORLD) { + + if (flags[FLAG_USE_BAKED_LIGHT]) { + + if (baked_light_instance) { + baked_light_instance->disconnect(SceneStringNames::get_singleton()->baked_light_changed,this,SceneStringNames::get_singleton()->_baked_light_changed); + baked_light_instance=NULL; + } + _baked_light_changed(); + + } + } + +} + +void GeometryInstance::_baked_light_changed() { + + if (!baked_light_instance) + VS::get_singleton()->instance_geometry_set_baked_light(get_instance(),RID()); + else + VS::get_singleton()->instance_geometry_set_baked_light(get_instance(),baked_light_instance->get_baked_light_instance()); + +} + +void GeometryInstance::_find_baked_light() { + + Node *n=get_parent(); + while(n) { + + BakedLightInstance *bl=n->cast_to<BakedLightInstance>(); + if (bl) { + + baked_light_instance=bl; + baked_light_instance->connect(SceneStringNames::get_singleton()->baked_light_changed,this,SceneStringNames::get_singleton()->_baked_light_changed); + _baked_light_changed(); + + return; + } + + n=n->get_parent(); + } + + _baked_light_changed(); +} + void GeometryInstance::set_flag(Flags p_flag,bool p_value) { ERR_FAIL_INDEX(p_flag,FLAG_MAX); @@ -198,8 +253,20 @@ void GeometryInstance::set_flag(Flags p_flag,bool p_value) { _change_notify("geometry/visible"); emit_signal(SceneStringNames::get_singleton()->visibility_changed); } - - + if (p_flag==FLAG_USE_BAKED_LIGHT) { + + if (is_inside_world()) { + if (!p_value) { + if (baked_light_instance) { + baked_light_instance->disconnect(SceneStringNames::get_singleton()->baked_light_changed,this,SceneStringNames::get_singleton()->_baked_light_changed); + baked_light_instance=NULL; + } + _baked_light_changed(); + } else { + _find_baked_light(); + } + } + } } bool GeometryInstance::get_flag(Flags p_flag) const{ @@ -224,6 +291,8 @@ void GeometryInstance::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_draw_range_end","mode"), &GeometryInstance::set_draw_range_end); ObjectTypeDB::bind_method(_MD("get_draw_range_end"), &GeometryInstance::get_draw_range_end); + ObjectTypeDB::bind_method(_MD("_baked_light_changed"), &GeometryInstance::_baked_light_changed); + ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "geometry/visible"), _SCS("set_flag"), _SCS("get_flag"),FLAG_VISIBLE); ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "geometry/material_override",PROPERTY_HINT_RESOURCE_TYPE,"Material"), _SCS("set_material_override"), _SCS("get_material_override")); ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "geometry/cast_shadow"), _SCS("set_flag"), _SCS("get_flag"),FLAG_CAST_SHADOW); @@ -234,6 +303,7 @@ void GeometryInstance::_bind_methods() { ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "geometry/billboard_y"), _SCS("set_flag"), _SCS("get_flag"),FLAG_BILLBOARD_FIX_Y); ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "geometry/depth_scale"), _SCS("set_flag"), _SCS("get_flag"),FLAG_DEPH_SCALE); ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "geometry/visible_in_all_rooms"), _SCS("set_flag"), _SCS("get_flag"),FLAG_VISIBLE_IN_ALL_ROOMS); + ADD_PROPERTYI( PropertyInfo( Variant::BOOL, "geometry/use_baked_light"), _SCS("set_flag"), _SCS("get_flag"),FLAG_USE_BAKED_LIGHT); ADD_SIGNAL( MethodInfo("visibility_changed")); @@ -258,5 +328,7 @@ GeometryInstance::GeometryInstance() { flags[FLAG_BILLBOARD_FIX_Y]=false; flags[FLAG_DEPH_SCALE]=false; flags[FLAG_VISIBLE_IN_ALL_ROOMS]=false; + baked_light_instance=NULL; + } diff --git a/scene/3d/visual_instance.h b/scene/3d/visual_instance.h index afb9ed70f8..1cf96d5d9e 100644 --- a/scene/3d/visual_instance.h +++ b/scene/3d/visual_instance.h @@ -78,6 +78,8 @@ public: }; +class BakedLightInstance; + class GeometryInstance : public VisualInstance { OBJ_TYPE( GeometryInstance, VisualInstance ); @@ -91,7 +93,7 @@ public: FLAG_BILLBOARD_FIX_Y=VS::INSTANCE_FLAG_BILLBOARD_FIX_Y, FLAG_DEPH_SCALE=VS::INSTANCE_FLAG_DEPH_SCALE, FLAG_VISIBLE_IN_ALL_ROOMS=VS::INSTANCE_FLAG_VISIBLE_IN_ALL_ROOMS, - FLAG_USE_BAKED_LIGHT_VOLUME=VS::INSTANCE_FLAG_USE_BAKED_LIGHT_VOLUME, + FLAG_USE_BAKED_LIGHT=VS::INSTANCE_FLAG_USE_BAKED_LIGHT, FLAG_MAX=VS::INSTANCE_FLAG_MAX, }; @@ -102,8 +104,13 @@ private: Ref<Material> material_override; float draw_begin; float draw_end; + void _find_baked_light(); + BakedLightInstance *baked_light_instance; + + void _baked_light_changed(); protected: + void _notification(int p_what); static void _bind_methods(); public: diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index f3d757b601..30e6e01842 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -187,7 +187,7 @@ #include "scene/3d/area.h" #include "scene/3d/physics_joint.h" #include "scene/3d/multimesh_instance.h" -#include "scene/3d/baked_light.h" +#include "scene/3d/baked_light_instance.h" #include "scene/3d/ray_cast.h" #include "scene/3d/immediate_geometry.h" #include "scene/3d/sprite_3d.h" @@ -407,7 +407,7 @@ void register_scene_types() { ObjectTypeDB::register_type<PathFollow>(); ObjectTypeDB::register_type<VisibilityNotifier>(); ObjectTypeDB::register_type<VisibilityEnabler>(); - ObjectTypeDB::register_type<BakedLight>(); + ObjectTypeDB::register_type<BakedLightInstance>(); ObjectTypeDB::register_type<WorldEnvironment>(); //scenariofx @@ -515,6 +515,7 @@ void register_scene_types() { ObjectTypeDB::register_type<SurfaceTool>(); ObjectTypeDB::register_type<MeshDataTool>(); + ObjectTypeDB::register_type<BakedLight>(); OS::get_singleton()->yield(); //may take time to init diff --git a/scene/resources/baked_light.cpp b/scene/resources/baked_light.cpp new file mode 100644 index 0000000000..b3de7143ee --- /dev/null +++ b/scene/resources/baked_light.cpp @@ -0,0 +1,308 @@ +#include "baked_light.h" +#include "servers/visual_server.h" + +void BakedLight::set_mode(Mode p_mode) { + + mode=p_mode; + VS::get_singleton()->baked_light_set_mode(baked_light,(VS::BakedLightMode(p_mode))); +} + +BakedLight::Mode BakedLight::get_mode() const{ + + return mode; +} + +void BakedLight::set_octree(const DVector<uint8_t>& p_octree) { + + VS::get_singleton()->baked_light_set_octree(baked_light,p_octree); +} + +DVector<uint8_t> BakedLight::get_octree() const { + + return VS::get_singleton()->baked_light_get_octree(baked_light); +} + + +void BakedLight::_update_lightmaps() { + + VS::get_singleton()->baked_light_clear_lightmaps(baked_light); + for(Map<int,Ref<Texture> >::Element *E=lightmaps.front();E;E=E->next()) { + + VS::get_singleton()->baked_light_add_lightmap(baked_light,E->get()->get_rid(),E->key()); + } + +} + +void BakedLight::add_lightmap(const Ref<Texture> p_texture,int p_id) { + + ERR_FAIL_COND(!p_texture.is_valid()); + ERR_FAIL_COND(p_id<0); + lightmaps[p_id]=p_texture; + VS::get_singleton()->baked_light_add_lightmap(baked_light,p_texture->get_rid(),p_id); +} + +void BakedLight::erase_lightmap(int p_id) { + + ERR_FAIL_COND(!lightmaps.has(p_id)); + lightmaps.erase(p_id); + _update_lightmaps(); +} + +void BakedLight::get_lightmaps(List<int> *r_lightmaps) { + + for(Map<int,Ref<Texture> >::Element *E=lightmaps.front();E;E=E->next()) { + + r_lightmaps->push_back(E->key()); + } + +} + +Ref<Texture> BakedLight::get_lightmap_texture(int p_id) { + + if (!lightmaps.has(p_id)) + return Ref<Texture>(); + + return lightmaps[p_id]; + + +} + +void BakedLight::clear_lightmaps() { + + lightmaps.clear(); + _update_lightmaps(); +} + +RID BakedLight::get_rid() const { + + return baked_light; +} + +Array BakedLight::_get_lightmap_data() const { + + Array ret; + ret.resize(lightmaps.size()*2); + + int idx=0; + for(Map<int,Ref<Texture> >::Element *E=lightmaps.front();E;E=E->next()) { + + ret[idx++]=E->key(); + ret[idx++]=E->get(); + } + + return ret; + +} + +void BakedLight::_set_lightmap_data(Array p_array){ + + lightmaps.clear(); + for(int i=0;i<p_array.size();i+=2) { + + int id = p_array[i]; + Ref<Texture> tex = p_array[i+1]; + ERR_CONTINUE(id<0); + ERR_CONTINUE(tex.is_null()); + lightmaps[id]=tex; + } + _update_lightmaps(); +} + + +void BakedLight::set_cell_subdivision(int p_subdiv) { + + cell_subdiv=p_subdiv; +} + +int BakedLight::get_cell_subdivision() const{ + + return cell_subdiv; +} + +void BakedLight::set_initial_lattice_subdiv(int p_size){ + + lattice_subdiv=p_size; +} +int BakedLight::get_initial_lattice_subdiv() const{ + + return lattice_subdiv; +} + +void BakedLight::set_plot_size(float p_size){ + + plot_size=p_size; +} +float BakedLight::get_plot_size() const{ + + return plot_size; +} + +void BakedLight::set_bounces(int p_size){ + + bounces=p_size; +} +int BakedLight::get_bounces() const{ + + return bounces; +} + +void BakedLight::set_cell_extra_margin(float p_margin) { + cell_extra_margin=p_margin; +} + +float BakedLight::get_cell_extra_margin() const { + + return cell_extra_margin; +} + +void BakedLight::set_edge_damp(float p_margin) { + edge_damp=p_margin; +} + +float BakedLight::get_edge_damp() const { + + return edge_damp; +} + + +void BakedLight::set_normal_damp(float p_margin) { + normal_damp=p_margin; +} + +float BakedLight::get_normal_damp() const { + + return normal_damp; +} + +void BakedLight::set_energy_multiplier(float p_multiplier){ + + energy_multiply=p_multiplier; +} +float BakedLight::get_energy_multiplier() const{ + + return energy_multiply; +} + +void BakedLight::set_gamma_adjust(float p_adjust){ + + gamma_adjust=p_adjust; +} +float BakedLight::get_gamma_adjust() const{ + + return gamma_adjust; +} + +void BakedLight::set_bake_flag(BakeFlags p_flags,bool p_enable){ + + flags[p_flags]=p_enable; +} +bool BakedLight::get_bake_flag(BakeFlags p_flags) const{ + + return flags[p_flags]; +} + + + +void BakedLight::_bind_methods(){ + + + ObjectTypeDB::bind_method(_MD("set_mode","mode"),&BakedLight::set_mode); + ObjectTypeDB::bind_method(_MD("get_mode"),&BakedLight::get_mode); + + ObjectTypeDB::bind_method(_MD("set_octree","octree"),&BakedLight::set_octree); + ObjectTypeDB::bind_method(_MD("get_octree"),&BakedLight::get_octree); + + ObjectTypeDB::bind_method(_MD("add_lightmap","texture:Texture","id"),&BakedLight::add_lightmap); + ObjectTypeDB::bind_method(_MD("erase_lightmap","id"),&BakedLight::erase_lightmap); + ObjectTypeDB::bind_method(_MD("clear_lightmaps"),&BakedLight::clear_lightmaps); + + ObjectTypeDB::bind_method(_MD("_set_lightmap_data","lightmap_data"),&BakedLight::_set_lightmap_data); + ObjectTypeDB::bind_method(_MD("_get_lightmap_data"),&BakedLight::_get_lightmap_data); + + ObjectTypeDB::bind_method(_MD("set_cell_subdivision","cell_subdivision"),&BakedLight::set_cell_subdivision); + ObjectTypeDB::bind_method(_MD("get_cell_subdivision"),&BakedLight::get_cell_subdivision); + + ObjectTypeDB::bind_method(_MD("set_initial_lattice_subdiv","cell_subdivision"),&BakedLight::set_initial_lattice_subdiv); + ObjectTypeDB::bind_method(_MD("get_initial_lattice_subdiv","cell_subdivision"),&BakedLight::get_initial_lattice_subdiv); + + ObjectTypeDB::bind_method(_MD("set_plot_size","plot_size"),&BakedLight::set_plot_size); + ObjectTypeDB::bind_method(_MD("get_plot_size"),&BakedLight::get_plot_size); + + ObjectTypeDB::bind_method(_MD("set_bounces","bounces"),&BakedLight::set_bounces); + ObjectTypeDB::bind_method(_MD("get_bounces"),&BakedLight::get_bounces); + + ObjectTypeDB::bind_method(_MD("set_cell_extra_margin","cell_extra_margin"),&BakedLight::set_cell_extra_margin); + ObjectTypeDB::bind_method(_MD("get_cell_extra_margin"),&BakedLight::get_cell_extra_margin); + + ObjectTypeDB::bind_method(_MD("set_edge_damp","edge_damp"),&BakedLight::set_edge_damp); + ObjectTypeDB::bind_method(_MD("get_edge_damp"),&BakedLight::get_edge_damp); + + ObjectTypeDB::bind_method(_MD("set_normal_damp","normal_damp"),&BakedLight::set_normal_damp); + ObjectTypeDB::bind_method(_MD("get_normal_damp"),&BakedLight::get_normal_damp); + + ObjectTypeDB::bind_method(_MD("set_energy_multiplier","energy_multiplier"),&BakedLight::set_energy_multiplier); + ObjectTypeDB::bind_method(_MD("get_energy_multiplier"),&BakedLight::get_energy_multiplier); + + ObjectTypeDB::bind_method(_MD("set_gamma_adjust","gamma_adjust"),&BakedLight::set_gamma_adjust); + ObjectTypeDB::bind_method(_MD("get_gamma_adjust"),&BakedLight::get_gamma_adjust); + + ObjectTypeDB::bind_method(_MD("set_bake_flag","flag","enabled"),&BakedLight::set_bake_flag); + ObjectTypeDB::bind_method(_MD("get_bake_flag","flag"),&BakedLight::get_bake_flag); + + ADD_PROPERTY( PropertyInfo(Variant::INT,"mode/mode",PROPERTY_HINT_ENUM,"Octree,Lightmaps"),_SCS("set_mode"),_SCS("get_mode")); + + ADD_PROPERTY( PropertyInfo(Variant::INT,"baking/cell_subdiv",PROPERTY_HINT_RANGE,"4,14,1"),_SCS("set_cell_subdivision"),_SCS("get_cell_subdivision")); + ADD_PROPERTY( PropertyInfo(Variant::INT,"baking/lattice_subdiv",PROPERTY_HINT_RANGE,"1,5,1"),_SCS("set_initial_lattice_subdiv"),_SCS("get_initial_lattice_subdiv")); + ADD_PROPERTY( PropertyInfo(Variant::INT,"baking/light_bounces",PROPERTY_HINT_RANGE,"0,3,1"),_SCS("set_bounces"),_SCS("get_bounces")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"baking/plot_size",PROPERTY_HINT_RANGE,"1.0,16.0,0.01"),_SCS("set_plot_size"),_SCS("get_plot_size")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"baking/energy_mult",PROPERTY_HINT_RANGE,"0.01,4096.0,0.01"),_SCS("set_energy_multiplier"),_SCS("get_energy_multiplier")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"baking/gamma_adjust",PROPERTY_HINT_EXP_EASING),_SCS("set_gamma_adjust"),_SCS("get_gamma_adjust")); + ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"baking_flags/diffuse"),_SCS("set_bake_flag"),_SCS("get_bake_flag"),BAKE_DIFFUSE); + ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"baking_flags/specular"),_SCS("set_bake_flag"),_SCS("get_bake_flag"),BAKE_SPECULAR); + ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"baking_flags/translucent"),_SCS("set_bake_flag"),_SCS("get_bake_flag"),BAKE_TRANSLUCENT); + ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"baking_flags/conserve_energy"),_SCS("set_bake_flag"),_SCS("get_bake_flag"),BAKE_CONSERVE_ENERGY); + + ADD_PROPERTY( PropertyInfo(Variant::RAW_ARRAY,"octree",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("set_octree"),_SCS("get_octree")); + ADD_PROPERTY( PropertyInfo(Variant::ARRAY,"lightmaps",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_lightmap_data"),_SCS("_get_lightmap_data")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"advanced/cell_margin",PROPERTY_HINT_RANGE,"0.01,0.8,0.01"),_SCS("set_cell_extra_margin"),_SCS("get_cell_extra_margin")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"advanced/edge_damp",PROPERTY_HINT_RANGE,"0.0,8.0,0.1"),_SCS("set_edge_damp"),_SCS("get_edge_damp")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"advanced/normal_damp",PROPERTY_HINT_RANGE,"0.0,1.0,0.01"),_SCS("set_normal_damp"),_SCS("get_normal_damp")); + + BIND_CONSTANT( MODE_OCTREE ); + BIND_CONSTANT( MODE_LIGHTMAPS ); + + BIND_CONSTANT( BAKE_DIFFUSE ); + BIND_CONSTANT( BAKE_SPECULAR ); + BIND_CONSTANT( BAKE_TRANSLUCENT ); + BIND_CONSTANT( BAKE_CONSERVE_ENERGY ); + BIND_CONSTANT( BAKE_MAX ); + + +} + + +BakedLight::BakedLight() { + + cell_subdiv=8; + lattice_subdiv=4; + plot_size=2.5; + bounces=1; + energy_multiply=1.0; + gamma_adjust=1.0; + cell_extra_margin=0.05; + edge_damp=0.0; + normal_damp=0.0; + + flags[BAKE_DIFFUSE]=true; + flags[BAKE_SPECULAR]=false; + flags[BAKE_TRANSLUCENT]=true; + flags[BAKE_CONSERVE_ENERGY]=false; + + mode=MODE_OCTREE; + baked_light=VS::get_singleton()->baked_light_create(); +} + +BakedLight::~BakedLight() { + + VS::get_singleton()->free(baked_light); +} diff --git a/scene/resources/baked_light.h b/scene/resources/baked_light.h new file mode 100644 index 0000000000..8b50f6e0d3 --- /dev/null +++ b/scene/resources/baked_light.h @@ -0,0 +1,106 @@ +#ifndef BAKED_LIGHT_H +#define BAKED_LIGHT_H + +#include "resource.h" +#include "scene/resources/texture.h" + +class BakedLight : public Resource { + + OBJ_TYPE( BakedLight, Resource); +public: + enum Mode { + + MODE_OCTREE, + MODE_LIGHTMAPS + }; + + enum BakeFlags { + BAKE_DIFFUSE, + BAKE_SPECULAR, + BAKE_TRANSLUCENT, + BAKE_CONSERVE_ENERGY, + BAKE_MAX + }; + +private: + + RID baked_light; + Mode mode; + Map<int,Ref<Texture> > lightmaps; + + //bake vars + int cell_subdiv; + int lattice_subdiv; + float plot_size; + float energy_multiply; + float gamma_adjust; + float cell_extra_margin; + float edge_damp; + float normal_damp; + int bounces; + bool flags[BAKE_MAX]; + + + + void _update_lightmaps(); + + Array _get_lightmap_data() const; + void _set_lightmap_data(Array p_array); + static void _bind_methods(); + +public: + + void set_cell_subdivision(int p_subdiv); + int get_cell_subdivision() const; + + void set_initial_lattice_subdiv(int p_size); + int get_initial_lattice_subdiv() const; + + void set_plot_size(float p_size); + float get_plot_size() const; + + void set_bounces(int p_size); + int get_bounces() const; + + void set_energy_multiplier(float p_multiplier); + float get_energy_multiplier() const; + + void set_gamma_adjust(float p_adjust); + float get_gamma_adjust() const; + + void set_cell_extra_margin(float p_margin); + float get_cell_extra_margin() const; + + void set_edge_damp(float p_margin); + float get_edge_damp() const; + + void set_normal_damp(float p_margin); + float get_normal_damp() const; + + void set_bake_flag(BakeFlags p_flags,bool p_enable); + bool get_bake_flag(BakeFlags p_flags) const; + + + void set_mode(Mode p_mode); + Mode get_mode() const; + + void set_octree(const DVector<uint8_t>& p_octree); + DVector<uint8_t> get_octree() const; + + void add_lightmap(const Ref<Texture> p_texture,int p_id); + void erase_lightmap(int p_id); + void get_lightmaps(List<int> *r_lightmaps); + Ref<Texture> get_lightmap_texture(int p_id); + void clear_lightmaps(); + + virtual RID get_rid() const; + + BakedLight(); + ~BakedLight(); +}; + + +VARIANT_ENUM_CAST(BakedLight::Mode); +VARIANT_ENUM_CAST(BakedLight::BakeFlags); + +#endif // BAKED_LIGHT_H diff --git a/scene/scene_string_names.cpp b/scene/scene_string_names.cpp index a8e4c80f89..40792f5139 100644 --- a/scene/scene_string_names.cpp +++ b/scene/scene_string_names.cpp @@ -140,4 +140,8 @@ SceneStringNames::SceneStringNames() { _im_update = StaticCString::create("_im_update"); _queue_update = StaticCString::create("_queue_update"); + baked_light_changed = StaticCString::create("baked_light_changed"); + _baked_light_changed = StaticCString::create("_baked_light_changed"); + + } diff --git a/scene/scene_string_names.h b/scene/scene_string_names.h index 2286712250..866c0ea387 100644 --- a/scene/scene_string_names.h +++ b/scene/scene_string_names.h @@ -148,6 +148,9 @@ public: StringName _im_update; StringName _queue_update; + StringName baked_light_changed; + StringName _baked_light_changed; + }; diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h index a3cdff9859..0aa7fc2650 100644 --- a/servers/visual/rasterizer.h +++ b/servers/visual/rasterizer.h @@ -302,6 +302,11 @@ public: virtual void multimesh_set_visible_instances(RID p_multimesh,int p_visible)=0; virtual int multimesh_get_visible_instances(RID p_multimesh) const=0; + /* BAKED LIGHT */ + + + + /* IMMEDIATE API */ virtual RID immediate_create()=0; @@ -490,6 +495,20 @@ public: typedef Map<StringName,Variant> ParamOverrideMap; + struct BakedLightData { + + VS::BakedLightMode mode; + RID octree_texture; + float color_multiplier; //used for both lightmaps and octree + Transform octree_transform; + Map<int,RID> lightmaps; + //cache + + float octree_lattice_size; + float octree_lattice_divide; + int octree_steps; + Vector2 octree_tex_pixel_size; + }; struct InstanceData { @@ -498,6 +517,8 @@ public: RID material_override; Vector<RID> light_instances; Vector<float> morph_values; + BakedLightData *baked_light; + Transform *baked_light_octree_xform; bool mirror :8; bool depth_scale :8; bool billboard :8; diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp index bffc1c43fe..519e697ab2 100644 --- a/servers/visual/visual_server_raster.cpp +++ b/servers/visual/visual_server_raster.cpp @@ -31,6 +31,7 @@ #include "globals.h" #include "default_mouse_cursor.xpm" #include "sort.h" +#include "io/marshalls.h" // careful, these may run in different threads than the visual server BalloonAllocator<> *VisualServerRaster::OctreeAllocator::allocator=NULL; @@ -921,6 +922,7 @@ void VisualServerRaster::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; + _dependency_queue_update(p_room,true); } @@ -1032,6 +1034,138 @@ float VisualServerRaster::portal_get_connect_range(RID p_portal) const { } +RID VisualServerRaster::baked_light_create() { + + BakedLight *baked_light = memnew( BakedLight ); + ERR_FAIL_COND_V(!baked_light,RID()); + baked_light->data.mode=BAKED_LIGHT_OCTREE; + + baked_light->data.octree_lattice_size=0; + baked_light->data.octree_lattice_divide=0; + baked_light->data.octree_steps=1; + + return baked_light_owner.make_rid( baked_light ); + +} + +void VisualServerRaster::baked_light_set_mode(RID p_baked_light,BakedLightMode p_mode){ + + VS_CHANGED; + BakedLight *baked_light = baked_light_owner.get(p_baked_light); + ERR_FAIL_COND(!baked_light); + baked_light->data.mode=p_mode; + baked_light->data.color_multiplier=1.0; + _dependency_queue_update(p_baked_light,true); + + +} + +VisualServer::BakedLightMode VisualServerRaster::baked_light_get_mode(RID p_baked_light) const{ + + const BakedLight *baked_light = baked_light_owner.get(p_baked_light); + ERR_FAIL_COND_V(!baked_light,BAKED_LIGHT_OCTREE); + return baked_light->data.mode; + +} + +void VisualServerRaster::baked_light_set_octree(RID p_baked_light,const DVector<uint8_t> p_octree){ + + VS_CHANGED; + BakedLight *baked_light = baked_light_owner.get(p_baked_light); + ERR_FAIL_COND(!baked_light); + + 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->octree_aabb=AABB(); + baked_light->octree_tex_size=Size2(); + } else { + + int tex_w; + int tex_h; + bool is16; + { + DVector<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())); + is16=decode_uint32(&r[8]); + baked_light->data.octree_lattice_size=decode_float(&r[12]); + baked_light->data.octree_lattice_divide=tex_w/4.0; + print_line("LATTICE SIZE: "+rtos(baked_light->data.octree_lattice_size)); + print_line("LATTICE DIVIDE: "+rtos(baked_light->data.octree_lattice_divide)); + baked_light->data.octree_steps=decode_uint32(&r[16]); + baked_light->data.octree_tex_pixel_size.x=1.0/tex_w; + baked_light->data.octree_tex_pixel_size.y=1.0/tex_h; + + + baked_light->octree_aabb.pos.x=decode_float(&r[32]); + baked_light->octree_aabb.pos.y=decode_float(&r[36]); + baked_light->octree_aabb.pos.z=decode_float(&r[40]); + baked_light->octree_aabb.size.x=decode_float(&r[44]); + baked_light->octree_aabb.size.y=decode_float(&r[48]); + baked_light->octree_aabb.size.z=decode_float(&r[52]); + + + } + + if (baked_light->data.octree_texture.is_valid()) { + 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(); + } + } + + 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); + } + + Image img(tex_w,tex_h,0,Image::FORMAT_RGBA,p_octree); + rasterizer->texture_set_data(baked_light->data.octree_texture,img); + + } + + + _dependency_queue_update(p_baked_light,true); + +} + +DVector<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>()); + + 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>(); + } +} + +void VisualServerRaster::baked_light_add_lightmap(RID p_baked_light,const RID p_texture,int p_id){ + + VS_CHANGED; + BakedLight *baked_light = baked_light_owner.get(p_baked_light); + ERR_FAIL_COND(!baked_light); + baked_light->data.lightmaps.insert(p_id,p_texture); + +} +void VisualServerRaster::baked_light_clear_lightmaps(RID p_baked_light){ + + VS_CHANGED; + BakedLight *baked_light = baked_light_owner.get(p_baked_light); + ERR_FAIL_COND(!baked_light); + baked_light->data.lightmaps.clear(); + +} + + /* CAMERA API */ RID VisualServerRaster::camera_create() { @@ -1710,6 +1844,23 @@ void VisualServerRaster::instance_set_base(RID p_instance, RID p_base) { } + if (instance->baked_light_info) { + + while(instance->baked_light_info->owned_instances.size()) { + + Instance *owned=instance->baked_light_info->owned_instances.front()->get(); + owned->baked_light=NULL; + owned->data.baked_light=NULL; + owned->data.baked_light_octree_xform=NULL; + owned->BLE=NULL; + instance->baked_light_info->owned_instances.pop_front(); + } + + memdelete(instance->baked_light_info); + instance->baked_light_info=NULL; + + } + if (instance->scenario && instance->octree_id) { instance->scenario->octree.erase( instance->octree_id ); instance->octree_id=0; @@ -1796,6 +1947,14 @@ void VisualServerRaster::instance_set_base(RID p_instance, RID p_base) { instance->base_type=INSTANCE_PORTAL; instance->portal_info = memnew(Instance::PortalInfo); instance->portal_info->portal=portal_owner.get(p_base); + } else if (baked_light_owner.owns(p_base)) { + + instance->base_type=INSTANCE_BAKED_LIGHT; + instance->baked_light_info=memnew(Instance::BakedLightInfo); + instance->baked_light_info->baked_light=baked_light_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(); @@ -2365,6 +2524,68 @@ float VisualServerRaster::instance_geometry_get_draw_range_max(RID p_instance) c } + +void VisualServerRaster::instance_geometry_set_baked_light(RID p_instance,RID p_baked_light) { + + VS_CHANGED; + Instance *instance = instance_owner.get( p_instance ); + ERR_FAIL_COND( !instance ); + + + if (instance->baked_light) { + + + instance->baked_light->baked_light_info->owned_instances.erase(instance->BLE); + instance->BLE=NULL; + instance->baked_light=NULL; + instance->data.baked_light=NULL; + instance->data.baked_light_octree_xform=NULL; + + } + + if (!p_baked_light.is_valid()) + return; + Instance *bl_instance = instance_owner.get( p_baked_light ); + ERR_FAIL_COND( !bl_instance ); + ERR_FAIL_COND( bl_instance->base_type!=INSTANCE_BAKED_LIGHT ); + + instance->baked_light=bl_instance; + instance->BLE=bl_instance->baked_light_info->owned_instances.push_back(instance); + instance->data.baked_light=&bl_instance->baked_light_info->baked_light->data; + instance->data.baked_light_octree_xform=&bl_instance->baked_light_info->affine_inverse; + +} + +RID VisualServerRaster::instance_geometry_get_baked_light(RID p_instance) const{ + + const Instance *instance = instance_owner.get( p_instance ); + ERR_FAIL_COND_V( !instance,RID() ); + if (instance->baked_light) + instance->baked_light->self; + return RID(); + +} + +void VisualServerRaster::instance_geometry_set_baked_light_texture_index(RID p_instance,int p_tex_id){ + + VS_CHANGED; + Instance *instance = instance_owner.get( p_instance ); + ERR_FAIL_COND( !instance ); + + instance->lightmap_texture_index=p_tex_id; + + +} +int VisualServerRaster::instance_geometry_get_baked_light_texture_index(RID p_instance) const{ + + const Instance *instance = instance_owner.get( p_instance ); + ERR_FAIL_COND_V( !instance,0 ); + + return instance->lightmap_texture_index; + +} + + void VisualServerRaster::_update_instance(Instance *p_instance) { p_instance->version++; @@ -2385,7 +2606,7 @@ void VisualServerRaster::_update_instance(Instance *p_instance) { } - if (p_instance->base_type&INSTANCE_GEOMETRY_MASK) { + if ((1<<p_instance->base_type)&INSTANCE_GEOMETRY_MASK) { //make sure lights are updated InstanceSet::Element *E=p_instance->lights.front(); @@ -2395,13 +2616,20 @@ void VisualServerRaster::_update_instance(Instance *p_instance) { E=E->next(); } - } - - if (p_instance->base_type == INSTANCE_ROOM) { + } 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_BAKED_LIGHT) { + + Transform scale; + scale.basis.scale(p_instance->baked_light_info->baked_light->octree_aabb.size); + scale.origin=p_instance->baked_light_info->baked_light->octree_aabb.pos; + //print_line("scale: "+scale); + p_instance->baked_light_info->affine_inverse=(p_instance->data.transform*scale).affine_inverse(); } + + p_instance->data.mirror = p_instance->data.transform.basis.determinant() < 0.0; AABB new_aabb; @@ -2463,7 +2691,7 @@ void VisualServerRaster::_update_instance(Instance *p_instance) { if (p_instance->base_type == INSTANCE_LIGHT) { - pairable_mask=INSTANCE_GEOMETRY_MASK; + pairable_mask=p_instance->light_info->enabled?INSTANCE_GEOMETRY_MASK:0; pairable=true; } @@ -2578,6 +2806,13 @@ void VisualServerRaster::_update_instance_aabb(Instance *p_instance) { } } break; + case VisualServer::INSTANCE_BAKED_LIGHT: { + + BakedLight *baked_light = baked_light_owner.get( p_instance->base_rid ); + ERR_FAIL_COND(!baked_light); + new_aabb=baked_light->octree_aabb; + + } break; default: {} } @@ -2607,6 +2842,33 @@ void VisualServerRaster::_update_instances() { } } +void VisualServerRaster::instance_light_set_enabled(RID p_instance,bool p_enabled) { + + VS_CHANGED; + Instance *instance = instance_owner.get( p_instance ); + ERR_FAIL_COND( !instance ); + ERR_FAIL_COND( instance->base_type!=INSTANCE_LIGHT ); + + if (p_enabled==instance->light_info->enabled) + return; + + instance->light_info->enabled=p_enabled; + if (light_get_type(instance->base_rid)!=VS::LIGHT_DIRECTIONAL && instance->octree_id && instance->scenario) + instance->scenario->octree.set_pairable(instance->octree_id,p_enabled,1<<INSTANCE_LIGHT,p_enabled?INSTANCE_GEOMETRY_MASK:0); + + //_instance_queue_update( instance , true ); + +} + +bool VisualServerRaster::instance_light_is_enabled(RID p_instance) const { + + const Instance *instance = instance_owner.get( p_instance ); + ERR_FAIL_COND_V( !instance,false ); + ERR_FAIL_COND_V( instance->base_type!=INSTANCE_LIGHT,false ); + + return instance->light_info->enabled; +} + /****** CANVAS *********/ RID VisualServerRaster::canvas_create() { @@ -3330,6 +3592,13 @@ void VisualServerRaster::black_bars_set_margins(int p_left, int p_top, int p_rig black_margin[MARGIN_BOTTOM]=p_bottom; } +void VisualServerRaster::black_bars_set_images(RID p_left, RID p_top, RID p_right, RID p_bottom) { + + black_image[MARGIN_LEFT]=p_left; + black_image[MARGIN_TOP]=p_top; + black_image[MARGIN_RIGHT]=p_right; + black_image[MARGIN_BOTTOM]=p_bottom; +} void VisualServerRaster::_free_attached_instances(RID p_rid,bool p_free_scenario) { @@ -3414,6 +3683,17 @@ void VisualServerRaster::free( RID p_rid ) { portal_owner.free(p_rid); memdelete(portal); + } else if (baked_light_owner.owns(p_rid)) { + + _free_attached_instances(p_rid); + + BakedLight *baked_light = baked_light_owner.get(p_rid); + ERR_FAIL_COND(!baked_light); + if (baked_light->data.octree_texture.is_valid()) + rasterizer->free(baked_light->data.octree_texture); + baked_light_owner.free(p_rid); + memdelete(baked_light); + } else if (camera_owner.owns(p_rid)) { // delete te camera @@ -3464,8 +3744,9 @@ void VisualServerRaster::free( RID p_rid ) { instance_set_room(p_rid,RID()); instance_set_scenario(p_rid,RID()); + instance_geometry_set_baked_light(p_rid,RID()); instance_set_base(p_rid,RID()); - + instance_owner.free(p_rid); memdelete(instance); @@ -5101,7 +5382,7 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S Instance *light = E->get().is_valid()?instance_owner.get(E->get()):NULL; - if (rasterizer->light_has_shadow(light->base_rid)) { + if (light && light->light_info->enabled && rasterizer->light_has_shadow(light->base_rid)) { //rasterizer->light_instance_set_active_hint(light->light_info->instance); _light_instance_update_shadow(light,p_scenario,p_camera,cull_range); } @@ -5190,6 +5471,9 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S Instance *light = E->get().is_valid()?instance_owner.get(E->get()):NULL; ERR_CONTINUE(!light); + if (!light->light_info->enabled) + continue; + rasterizer->add_light(light->light_info->instance); light->light_info->last_add_pass=render_pass; } @@ -5694,9 +5978,16 @@ void VisualServerRaster::_draw_cursors_and_margins() { rasterizer->canvas_draw_rect(Rect2(cursors[i].pos, size), 0, Rect2(), tex, Color(1, 1, 1, 1)); }; - if (black_margin[MARGIN_LEFT]) + if (black_image[MARGIN_LEFT].is_valid()) { + Size2 sz(rasterizer->texture_get_width(black_image[MARGIN_LEFT]),rasterizer->texture_get_height(black_image[MARGIN_LEFT])); + rasterizer->canvas_draw_rect(Rect2(0,0,black_margin[MARGIN_LEFT],window_h),0,Rect2(0,0,sz.x,sz.y),black_image[MARGIN_LEFT],Color(1,1,1)); + } else if (black_margin[MARGIN_LEFT]) rasterizer->canvas_draw_rect(Rect2(0,0,black_margin[MARGIN_LEFT],window_h),0,Rect2(0,0,1,1),RID(),Color(0,0,0)); - if (black_margin[MARGIN_RIGHT]) + + if (black_image[MARGIN_RIGHT].is_valid()) { + Size2 sz(rasterizer->texture_get_width(black_image[MARGIN_RIGHT]),rasterizer->texture_get_height(black_image[MARGIN_RIGHT])); + rasterizer->canvas_draw_rect(Rect2(window_w-black_margin[MARGIN_RIGHT],0,black_margin[MARGIN_RIGHT],window_h),0,Rect2(0,0,sz.x,sz.y),black_image[MARGIN_RIGHT],Color(1,1,1)); + } else if (black_margin[MARGIN_RIGHT]) rasterizer->canvas_draw_rect(Rect2(window_w-black_margin[MARGIN_RIGHT],0,black_margin[MARGIN_RIGHT],window_h),0,Rect2(0,0,1,1),RID(),Color(0,0,0)); if (black_margin[MARGIN_TOP]) rasterizer->canvas_draw_rect(Rect2(0,0,window_w,black_margin[MARGIN_TOP]),0,Rect2(0,0,1,1),RID(),Color(0,0,0)); diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h index f6ef4ba6d5..ddc30bb2ee 100644 --- a/servers/visual/visual_server_raster.h +++ b/servers/visual/visual_server_raster.h @@ -87,6 +87,14 @@ class VisualServerRaster : public VisualServer { Portal() { enabled=true; disable_distance=50; disable_color=Color(); connect_range=0.8; } }; + struct BakedLight { + + Rasterizer::BakedLightData data; + AABB octree_aabb; + Size2i octree_tex_size; + + }; + struct Camera { @@ -149,6 +157,7 @@ class VisualServerRaster : public VisualServer { float draw_range_begin; float draw_range_end; float extra_margin; + int lightmap_texture_index; Rasterizer::InstanceData data; @@ -158,6 +167,8 @@ class VisualServerRaster : public VisualServer { Set<Instance*> valid_auto_rooms; Instance *room; List<Instance*>::Element *RE; + Instance *baked_light; + List<Instance*>::Element *BLE; bool exterior; uint64_t last_render_pass; @@ -205,6 +216,7 @@ class VisualServerRaster : public VisualServer { uint64_t last_add_pass; List<RID>::Element *D; // directional light in scenario InstanceSet affected; + bool enabled; float dtc; //distance to camera, used for sorting @@ -213,8 +225,16 @@ class VisualServerRaster : public VisualServer { D=NULL; light_set_index=-1; last_add_pass=0; + enabled=true; } }; + + struct BakedLightInfo { + + BakedLight *baked_light; + Transform affine_inverse; + List<Instance*> owned_instances; + }; struct ParticlesInfo { @@ -226,6 +246,7 @@ class VisualServerRaster : public VisualServer { LightInfo *light_info; ParticlesInfo *particles_info; PortalInfo * portal_info; + BakedLightInfo * baked_light_info; Instance() { @@ -244,6 +265,8 @@ class VisualServerRaster : public VisualServer { data.depth_scale=false; data.billboard=false; data.billboard_y=false; + data.baked_light=NULL; + data.baked_light_octree_xform=NULL; version=1; room_info=NULL; room=NULL; @@ -255,6 +278,10 @@ class VisualServerRaster : public VisualServer { draw_range_end=0; extra_margin=0; visible_in_all_rooms=false; + lightmap_texture_index=-1; + baked_light=NULL; + baked_light_info=NULL; + BLE=NULL; light_cache_dirty=true; @@ -270,6 +297,8 @@ class VisualServerRaster : public VisualServer { memdelete(room_info); if (portal_info) memdelete(portal_info); + if (baked_light_info) + memdelete(baked_light_info); }; }; @@ -570,6 +599,7 @@ class VisualServerRaster : public VisualServer { bool light_discard_enabled; bool shadows_enabled; int black_margin[4]; + RID black_image[4]; Vector<Vector3> aabb_random_points; Vector<Vector3> transformed_aabb_random_points; @@ -596,7 +626,9 @@ class VisualServerRaster : public VisualServer { mutable RID_Owner<Room> room_owner; mutable RID_Owner<Portal> portal_owner; - + + mutable RID_Owner<BakedLight> baked_light_owner; + mutable RID_Owner<Camera> camera_owner; mutable RID_Owner<Viewport> viewport_owner; @@ -902,8 +934,19 @@ public: virtual void portal_set_connect_range(RID p_portal, float p_range); virtual float portal_get_connect_range(RID p_portal) const; + /* BAKED LIGHT */ + + virtual RID baked_light_create(); + + virtual void baked_light_set_mode(RID p_baked_light,BakedLightMode p_mode); + virtual BakedLightMode baked_light_get_mode(RID p_baked_light) const; + + 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; + + 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); - /* CAMERA API */ virtual RID camera_create(); @@ -1036,6 +1079,15 @@ public: 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; + + 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; + + virtual void instance_light_set_enabled(RID p_instance,bool p_enabled); + virtual bool instance_light_is_enabled(RID p_instance) const; + /* CANVAS (2D) */ virtual RID canvas_create(); @@ -1093,6 +1145,7 @@ public: /* 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 */ diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h index cfc4bd8605..0b7721cf8b 100644 --- a/servers/visual/visual_server_wrap_mt.h +++ b/servers/visual/visual_server_wrap_mt.h @@ -879,6 +879,17 @@ public: 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); + + + FUNC3(baked_light_add_lightmap,RID,RID,int); + FUNC1(baked_light_clear_lightmaps,RID); + /* CAMERA API */ @@ -1014,6 +1025,14 @@ public: 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_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) */ @@ -1076,6 +1095,7 @@ public: /* BLACK BARS */ FUNC4(black_bars_set_margins,int , int , int , int ); + FUNC4(black_bars_set_images,RID , RID , RID , RID ); /* FREE */ diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp index 08cc57e307..d2b55092d6 100644 --- a/servers/visual_server.cpp +++ b/servers/visual_server.cpp @@ -145,6 +145,7 @@ RID VisualServer::_make_test_cube() { tangents.push_back( normal_points[m_idx][0] );\ tangents.push_back( 1.0 );\ uvs.push_back( Vector3(uv_points[m_idx*2+0],uv_points[m_idx*2+1],0) );\ + print_line(itos( (face_points[m_idx][0]>0?1:0)|(face_points[m_idx][1]>0?2:0)|(face_points[m_idx][2]>0?4:0)));\ vtx_idx++;\ for (int i=0;i<6;i++) { @@ -527,6 +528,7 @@ void VisualServer::_bind_methods() { 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); diff --git a/servers/visual_server.h b/servers/visual_server.h index e5d1e75702..f01685890f 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -576,6 +576,23 @@ public: virtual float portal_get_connect_range(RID p_portal) const =0; + /* BAKED LIGHT API */ + + virtual RID baked_light_create()=0; + enum BakedLightMode { + BAKED_LIGHT_OCTREE, + BAKED_LIGHT_LIGHTMAPS + }; + + 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 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 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; + /* CAMERA API */ @@ -792,6 +809,7 @@ public: INSTANCE_LIGHT, INSTANCE_ROOM, INSTANCE_PORTAL, + INSTANCE_BAKED_LIGHT, INSTANCE_GEOMETRY_MASK=(1<<INSTANCE_MESH)|(1<<INSTANCE_MULTIMESH)|(1<<INSTANCE_IMMEDIATE)|(1<<INSTANCE_PARTICLES) }; @@ -849,7 +867,7 @@ public: INSTANCE_FLAG_RECEIVE_SHADOWS, INSTANCE_FLAG_DEPH_SCALE, INSTANCE_FLAG_VISIBLE_IN_ALL_ROOMS, - INSTANCE_FLAG_USE_BAKED_LIGHT_VOLUME, + INSTANCE_FLAG_USE_BAKED_LIGHT, INSTANCE_FLAG_MAX }; @@ -863,6 +881,14 @@ public: 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_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; /* CANVAS (2D) */ @@ -923,6 +949,7 @@ public: virtual void black_bars_set_margins(int p_left, int p_top, int p_right, int p_bottom)=0; + virtual void black_bars_set_images(RID p_left, RID p_top, RID p_right, RID p_bottom)=0; /* FREE */ diff --git a/tools/editor/editor_import_export.cpp b/tools/editor/editor_import_export.cpp index 9c921df5c6..649db5fc45 100644 --- a/tools/editor/editor_import_export.cpp +++ b/tools/editor/editor_import_export.cpp @@ -704,11 +704,11 @@ Error EditorExportPlatform::export_project_files(EditorExportSaveFunction p_func int flags=0; - if (Globals::get_singleton()->get("texture_import/filter")) + if (Globals::get_singleton()->get("image_loader/filter")) flags|=EditorTextureImportPlugin::IMAGE_FLAG_FILTER; - if (!Globals::get_singleton()->get("texture_import/gen_mipmaps")) + if (!Globals::get_singleton()->get("image_loader/gen_mipmaps")) flags|=EditorTextureImportPlugin::IMAGE_FLAG_NO_MIPMAPS; - if (!Globals::get_singleton()->get("texture_import/repeat")) + if (!Globals::get_singleton()->get("image_loader/repeat")) flags|=EditorTextureImportPlugin::IMAGE_FLAG_REPEAT; flags|=EditorTextureImportPlugin::IMAGE_FLAG_FIX_BORDER_ALPHA; @@ -1533,6 +1533,26 @@ void EditorImportExport::load_config() { } + if (cf->has_section("script")) { + + if (cf->has_section_key("script","action")) { + + String action = cf->get_value("script","action"); + if (action=="compile") + script_action=SCRIPT_ACTION_COMPILE; + else if (action=="encrypt") + script_action=SCRIPT_ACTION_ENCRYPT; + else + script_action=SCRIPT_ACTION_NONE; + + } + + if (cf->has_section_key("script","encrypt_key")) { + + script_key = cf->get_value("script","encrypt_key"); + } + } + } @@ -1634,10 +1654,39 @@ void EditorImportExport::save_config() { cf->set_value("image_group_files","files",igfsave); } + switch(script_action) { + case SCRIPT_ACTION_NONE: cf->set_value("script","action","none"); break; + case SCRIPT_ACTION_COMPILE: cf->set_value("script","action","compile"); break; + case SCRIPT_ACTION_ENCRYPT: cf->set_value("script","action","encrypt"); break; + } + + cf->set_value("script","encrypt_key",script_key); + cf->save("res://export.cfg"); } + +void EditorImportExport::script_set_action(ScriptAction p_action) { + + script_action=p_action; +} + +EditorImportExport::ScriptAction EditorImportExport::script_get_action() const{ + + return script_action; +} + +void EditorImportExport::script_set_encryption_key(const String& p_key){ + + script_key=p_key; +} +String EditorImportExport::script_get_encryption_key() const{ + + return script_key; +} + + void EditorImportExport::_bind_methods() { ObjectTypeDB::bind_method(_MD("image_export_group_create"),&EditorImportExport::image_export_group_create); @@ -1649,6 +1698,11 @@ void EditorImportExport::_bind_methods() { ObjectTypeDB::bind_method(_MD("image_export_group_get_make_atlas"),&EditorImportExport::image_export_group_get_make_atlas); ObjectTypeDB::bind_method(_MD("image_export_group_get_shrink"),&EditorImportExport::image_export_group_get_shrink); ObjectTypeDB::bind_method(_MD("image_add_to_export_group"),&EditorImportExport::image_add_to_export_group); + ObjectTypeDB::bind_method(_MD("script_set_action"),&EditorImportExport::script_set_action); + ObjectTypeDB::bind_method(_MD("script_set_encryption_key"),&EditorImportExport::script_set_encryption_key); + ObjectTypeDB::bind_method(_MD("script_get_action"),&EditorImportExport::script_get_action); + ObjectTypeDB::bind_method(_MD("script_get_encryption_key"),&EditorImportExport::script_get_encryption_key); + } EditorImportExport::EditorImportExport() { @@ -1659,6 +1713,9 @@ EditorImportExport::EditorImportExport() { image_action_compress_quality=0.7; image_formats.insert("png"); image_shrink=1; + + script_action=SCRIPT_ACTION_COMPILE; + } diff --git a/tools/editor/editor_import_export.h b/tools/editor/editor_import_export.h index 0f9068f8b3..8305e3c88c 100644 --- a/tools/editor/editor_import_export.h +++ b/tools/editor/editor_import_export.h @@ -227,6 +227,11 @@ public: IMAGE_ACTION_COMPRESS_RAM, }; + enum ScriptAction { + SCRIPT_ACTION_NONE, + SCRIPT_ACTION_COMPILE, + SCRIPT_ACTION_ENCRYPT + }; protected: @@ -254,6 +259,9 @@ protected: Map<StringName,StringName> image_group_files; Vector<String> diff_packs; + ScriptAction script_action; + String script_key; + static EditorImportExport* singleton; static void _bind_methods(); @@ -316,6 +324,11 @@ public: Set<String>& get_image_formats() { return image_formats; } + void script_set_action(ScriptAction p_action); + ScriptAction script_get_action() const; + + void script_set_encryption_key(const String& p_key); + String script_get_encryption_key() const; void load_config(); void save_config(); @@ -324,5 +337,6 @@ public: }; VARIANT_ENUM_CAST(EditorImportExport::ImageAction); +VARIANT_ENUM_CAST(EditorImportExport::ScriptAction); #endif // EDITOR_IMPORT_EXPORT_H diff --git a/tools/editor/icons/icon_bake.png b/tools/editor/icons/icon_bake.png Binary files differnew file mode 100644 index 0000000000..b1b0f941da --- /dev/null +++ b/tools/editor/icons/icon_bake.png diff --git a/tools/editor/icons/icon_reload.png b/tools/editor/icons/icon_reload.png Binary files differindex a79cd11546..07f53efb56 100644 --- a/tools/editor/icons/icon_reload.png +++ b/tools/editor/icons/icon_reload.png diff --git a/tools/editor/io_plugins/editor_import_collada.cpp b/tools/editor/io_plugins/editor_import_collada.cpp index 7e46a02c86..6cd6170bb6 100644 --- a/tools/editor/io_plugins/editor_import_collada.cpp +++ b/tools/editor/io_plugins/editor_import_collada.cpp @@ -290,6 +290,7 @@ Error ColladaImport::_create_scene(Collada::Node *p_node, Spatial *p_parent) { } else { //mesh since nothing else node = memnew( MeshInstance ); + node->cast_to<MeshInstance>()->set_flag(GeometryInstance::FLAG_USE_BAKED_LIGHT,true); } } break; case Collada::Node::TYPE_SKELETON: { diff --git a/tools/editor/io_plugins/editor_texture_import_plugin.cpp b/tools/editor/io_plugins/editor_texture_import_plugin.cpp index 4da712c7b3..5d45594246 100644 --- a/tools/editor/io_plugins/editor_texture_import_plugin.cpp +++ b/tools/editor/io_plugins/editor_texture_import_plugin.cpp @@ -732,6 +732,7 @@ Error EditorTextureImportPlugin::import2(const String& p_path, const Ref<Resourc if (!(flags&EditorTextureImportPlugin::IMAGE_FLAG_NO_MIPMAPS)) tex_flags|=Texture::FLAG_MIPMAPS; + print_line("path: "+p_path+" flags: "+itos(tex_flags)); int shrink=1; if (from->has_option("shrink")) shrink=from->get_option("shrink"); @@ -1073,11 +1074,11 @@ Vector<uint8_t> EditorTextureImportPlugin::custom_export(const String& p_path, c int flags=0; - if (Globals::get_singleton()->get("texture_import/filter")) + if (Globals::get_singleton()->get("image_loader/filter")) flags|=IMAGE_FLAG_FILTER; - if (!Globals::get_singleton()->get("texture_import/gen_mipmaps")) + if (!Globals::get_singleton()->get("image_loader/gen_mipmaps")) flags|=IMAGE_FLAG_NO_MIPMAPS; - if (!Globals::get_singleton()->get("texture_import/repeat")) + if (!Globals::get_singleton()->get("image_loader/repeat")) flags|=IMAGE_FLAG_REPEAT; flags|=IMAGE_FLAG_FIX_BORDER_ALPHA; @@ -1102,11 +1103,11 @@ Vector<uint8_t> EditorTextureImportPlugin::custom_export(const String& p_path, c int flags=0; - if (Globals::get_singleton()->get("texture_import/filter")) + if (Globals::get_singleton()->get("image_loader/filter")) flags|=IMAGE_FLAG_FILTER; - if (!Globals::get_singleton()->get("texture_import/gen_mipmaps")) + if (!Globals::get_singleton()->get("image_loader/gen_mipmaps")) flags|=IMAGE_FLAG_NO_MIPMAPS; - if (!Globals::get_singleton()->get("texture_import/repeat")) + if (!Globals::get_singleton()->get("image_loader/repeat")) flags|=IMAGE_FLAG_REPEAT; flags|=IMAGE_FLAG_FIX_BORDER_ALPHA; @@ -1147,10 +1148,13 @@ Vector<uint8_t> EditorTextureImportPlugin::custom_export(const String& p_path, c MD5Update(&ctx,&shrink,1); MD5Final(&ctx); + + uint64_t sd=0; String smd5; String md5 = String::md5(ctx.digest); + print_line(p_path+" MD5: "+md5+" FLAGS: "+itos(flags)); String tmp_path = EditorSettings::get_singleton()->get_settings_path().plus_file("tmp/"); diff --git a/tools/editor/plugins/baked_light_baker.cpp b/tools/editor/plugins/baked_light_baker.cpp new file mode 100644 index 0000000000..ae5746321a --- /dev/null +++ b/tools/editor/plugins/baked_light_baker.cpp @@ -0,0 +1,1765 @@ + +#include "baked_light_baker.h" +#include <stdlib.h> +#include <cmath> +#include "io/marshalls.h" +#include "tools/editor/editor_node.h" + + +BakedLightBaker::MeshTexture* BakedLightBaker::_get_mat_tex(const Ref<Texture>& p_tex) { + + if (!tex_map.has(p_tex)) { + + Ref<ImageTexture> imgtex=p_tex; + if (imgtex.is_null()) + return NULL; + Image image=imgtex->get_data(); + if (image.empty()) + return NULL; + + if (image.get_format()!=Image::FORMAT_RGBA) { + if (image.get_format()>Image::FORMAT_INDEXED_ALPHA) { + Error err = image.decompress(); + if (err) + return NULL; + } + + if (image.get_format()!=Image::FORMAT_RGBA) + image.convert(Image::FORMAT_RGBA); + } + + DVector<uint8_t> dvt=image.get_data(); + DVector<uint8_t>::Read r=dvt.read(); + MeshTexture mt; + mt.tex_w=image.get_width(); + mt.tex_h=image.get_height(); + int len = image.get_width()*image.get_height()*4; + mt.tex.resize(len); + copymem(mt.tex.ptr(),r.ptr(),len); + + textures.push_back(mt); + tex_map[p_tex]=&textures.back()->get(); + } + + return tex_map[p_tex]; +} + + +void BakedLightBaker::_add_mesh(const Ref<Mesh>& p_mesh,const Ref<Material>& p_mat_override,const Transform& p_xform) { + + + for(int i=0;i<p_mesh->get_surface_count();i++) { + + if (p_mesh->surface_get_primitive_type(i)!=Mesh::PRIMITIVE_TRIANGLES) + continue; + Ref<Material> mat = p_mat_override.is_valid()?p_mat_override:p_mesh->surface_get_material(i); + + MeshMaterial *matptr=NULL; + + if (mat.is_valid()) { + + if (!mat_map.has(mat)) { + + MeshMaterial mm; + + Ref<FixedMaterial> fm = mat; + if (fm.is_valid()) { + //fixed route + mm.diffuse.color=fm->get_parameter(FixedMaterial::PARAM_DIFFUSE); + mm.diffuse.tex=_get_mat_tex(fm->get_texture(FixedMaterial::PARAM_DIFFUSE)); + mm.specular.color=fm->get_parameter(FixedMaterial::PARAM_SPECULAR); + mm.specular.tex=_get_mat_tex(fm->get_texture(FixedMaterial::PARAM_SPECULAR)); + } else { + + mm.diffuse.color=Color(1,1,1,1); + mm.diffuse.tex=NULL; + mm.specular.color=Color(0,0,0,1); + mm.specular.tex=NULL; + } + + materials.push_back(mm); + mat_map[mat]=&materials.back()->get(); + + } + + matptr=mat_map[mat]; + + } + + + int facecount=0; + + + if (p_mesh->surface_get_format(i)&Mesh::ARRAY_FORMAT_INDEX) { + + facecount=p_mesh->surface_get_array_index_len(i); + } else { + + facecount=p_mesh->surface_get_array_len(i); + } + + ERR_CONTINUE((facecount==0 || (facecount%3)!=0)); + + facecount/=3; + + int tbase=triangles.size(); + triangles.resize(facecount+tbase); + + + Array a = p_mesh->surface_get_arrays(i); + + DVector<Vector3> vertices = a[Mesh::ARRAY_VERTEX]; + DVector<Vector3>::Read vr=vertices.read(); + DVector<Vector2> uv; + DVector<Vector2>::Read uvr; + DVector<Vector3> normal; + DVector<Vector3>::Read normalr; + bool read_uv=false; + bool read_normal=false; + + if (p_mesh->surface_get_format(i)&Mesh::ARRAY_FORMAT_TEX_UV) { + + uv=a[Mesh::ARRAY_TEX_UV]; + uvr=uv.read(); + read_uv=true; + } + + if (p_mesh->surface_get_format(i)&Mesh::ARRAY_FORMAT_NORMAL) { + + normal=a[Mesh::ARRAY_NORMAL]; + normalr=normal.read(); + read_normal=true; + } + + Matrix3 normal_xform = p_xform.basis.inverse().transposed(); + + + if (p_mesh->surface_get_format(i)&Mesh::ARRAY_FORMAT_INDEX) { + + DVector<int> indices = a[Mesh::ARRAY_INDEX]; + DVector<int>::Read ir = indices.read(); + + for(int i=0;i<facecount;i++) { + Triangle &t=triangles[tbase+i]; + t.vertices[0]=p_xform.xform(vr[ ir[i*3+0] ]); + t.vertices[1]=p_xform.xform(vr[ ir[i*3+1] ]); + t.vertices[2]=p_xform.xform(vr[ ir[i*3+2] ]); + t.material=matptr; + if (read_uv) { + + t.uvs[0]=uvr[ ir[i*3+0] ]; + t.uvs[1]=uvr[ ir[i*3+1] ]; + t.uvs[2]=uvr[ ir[i*3+2] ]; + } + if (read_normal) { + + t.normals[0]=normal_xform.xform(normalr[ ir[i*3+0] ]).normalized(); + t.normals[1]=normal_xform.xform(normalr[ ir[i*3+1] ]).normalized(); + t.normals[2]=normal_xform.xform(normalr[ ir[i*3+2] ]).normalized(); + } + } + + } else { + + for(int i=0;i<facecount;i++) { + Triangle &t=triangles[tbase+i]; + t.vertices[0]=p_xform.xform(vr[ i*3+0 ]); + t.vertices[1]=p_xform.xform(vr[ i*3+1 ]); + t.vertices[2]=p_xform.xform(vr[ i*3+2 ]); + t.material=matptr; + if (read_uv) { + + t.uvs[0]=uvr[ i*3+0 ]; + t.uvs[1]=uvr[ i*3+1 ]; + t.uvs[2]=uvr[ i*3+2 ]; + } + if (read_normal) { + + t.normals[0]=normal_xform.xform(normalr[ i*3+0 ]).normalized(); + t.normals[1]=normal_xform.xform(normalr[ i*3+1 ]).normalized(); + t.normals[2]=normal_xform.xform(normalr[ i*3+2 ]).normalized(); + } + } + } + } + +} + + +void BakedLightBaker::_parse_geometry(Node* p_node) { + + if (p_node->cast_to<MeshInstance>()) { + + MeshInstance *meshi=p_node->cast_to<MeshInstance>(); + Ref<Mesh> mesh=meshi->get_mesh(); + if (mesh.is_valid()) { + _add_mesh(mesh,meshi->get_material_override(),base_inv * meshi->get_global_transform()); + } + } else if (p_node->cast_to<Light>()) { + + Light *dl=p_node->cast_to<Light>(); + + if (dl->get_bake_mode()!=Light::BAKE_MODE_DISABLED) { + + + LightData dirl; + dirl.type=VS::LightType(dl->get_light_type()); + dirl.diffuse=dl->get_color(DirectionalLight::COLOR_DIFFUSE); + dirl.specular=dl->get_color(DirectionalLight::COLOR_SPECULAR); + dirl.energy=dl->get_parameter(DirectionalLight::PARAM_ENERGY); + dirl.pos=dl->get_global_transform().origin; + dirl.up=dl->get_global_transform().basis.get_axis(1).normalized(); + dirl.left=dl->get_global_transform().basis.get_axis(0).normalized(); + dirl.dir=-dl->get_global_transform().basis.get_axis(2).normalized(); + dirl.spot_angle=dl->get_parameter(DirectionalLight::PARAM_SPOT_ANGLE); + dirl.spot_attenuation=dl->get_parameter(DirectionalLight::PARAM_SPOT_ATTENUATION); + dirl.attenuation=dl->get_parameter(DirectionalLight::PARAM_ATTENUATION); + dirl.radius=dl->get_parameter(DirectionalLight::PARAM_RADIUS); + dirl.bake_direct=dl->get_bake_mode()==Light::BAKE_MODE_FULL; + dirl.rays_thrown=0; + lights.push_back(dirl); + } + + } else if (p_node->cast_to<Spatial>()){ + + Spatial *sp = p_node->cast_to<Spatial>(); + + Array arr = p_node->call("_get_baked_light_meshes"); + for(int i=0;i<arr.size();i+=2) { + + Transform xform=arr[i]; + Ref<Mesh> mesh=arr[i+1]; + _add_mesh(mesh,Ref<Material>(),base_inv * (sp->get_global_transform() * xform)); + } + } + + for(int i=0;i<p_node->get_child_count();i++) { + + _parse_geometry(p_node->get_child(i)); + } +} + + +void BakedLightBaker::_fix_lights() { + + + total_light_area=0; + for(int i=0;i<lights.size();i++) { + + LightData &dl=lights[i]; + + switch(dl.type) { + case VS::LIGHT_DIRECTIONAL: { + + float up_max=-1e10; + float dir_max=-1e10; + float left_max=-1e10; + float up_min=1e10; + float dir_min=1e10; + float left_min=1e10; + + for(int j=0;j<triangles.size();j++) { + + for(int k=0;k<3;k++) { + + Vector3 v = triangles[j].vertices[k]; + + float up_d = dl.up.dot(v); + float dir_d = dl.dir.dot(v); + float left_d = dl.left.dot(v); + + if (up_d>up_max) + up_max=up_d; + if (up_d<up_min) + up_min=up_d; + + if (left_d>left_max) + left_max=left_d; + if (left_d<left_min) + left_min=left_d; + + if (dir_d>dir_max) + dir_max=dir_d; + if (dir_d<dir_min) + dir_min=dir_d; + + } + } + + //make a center point, then the upvector and leftvector + dl.pos = dl.left*( left_max+left_min )*0.5 + dl.up*( up_max+up_min )*0.5 + dl.dir*(dir_min-(dir_max-dir_min)); + dl.left*=(left_max-left_min)*0.5; + dl.up*=(up_max-up_min)*0.5; + dl.length = (dir_max - dir_min)*10; //arbitrary number to keep it in scale + dl.area=dl.left.length()*2*dl.up.length()*2; + dl.constant=1.0/dl.area; + } break; + case VS::LIGHT_OMNI: + case VS::LIGHT_SPOT: { + + dl.attenuation_table.resize(ATTENUATION_CURVE_LEN); + for(int j=0;j<ATTENUATION_CURVE_LEN;j++) { + dl.attenuation_table[j]=1.0-Math::pow(j/float(ATTENUATION_CURVE_LEN),dl.attenuation); + float falloff=j*dl.radius/float(ATTENUATION_CURVE_LEN); + if (falloff==0) + falloff=0.000001; + float intensity=4*Math_PI*(falloff*falloff); + //dl.attenuation_table[j]*=falloff*falloff; + dl.attenuation_table[j]*=1.0/(3.0/intensity); + + } + if (dl.type==VS::LIGHT_OMNI) { + + dl.area=4.0*Math_PI*pow(dl.radius,2.0); + dl.constant=1.0/3.5; + } else { + + + float r = Math::tan(Math::deg2rad(dl.spot_angle))*dl.radius; + float c = 1.0-(Math::deg2rad(dl.spot_angle)*0.5+0.5); + dl.constant=1.0/3.5; + dl.constant*=1.0/c; + + dl.area=Math_PI*r*r*c; + } + + } break; + + + } + + total_light_area+=dl.area; + } +} + +BakedLightBaker::BVH* BakedLightBaker::_parse_bvh(BVH** p_children, int p_size, int p_depth, int &max_depth) { + + if (p_depth>max_depth) { + max_depth=p_depth; + } + + if (p_size==1) { + + return p_children[0]; + } else if (p_size==0) { + + return NULL; + } + + + AABB aabb; + aabb=p_children[0]->aabb; + for(int i=1;i<p_size;i++) { + + aabb.merge_with(p_children[i]->aabb); + } + + int li=aabb.get_longest_axis_index(); + + switch(li) { + + case Vector3::AXIS_X: { + SortArray<BVH*,BVHCmpX> sort_x; + sort_x.nth_element(0,p_size,p_size/2,p_children); + //sort_x.sort(&p_bb[p_from],p_size); + } break; + case Vector3::AXIS_Y: { + SortArray<BVH*,BVHCmpY> sort_y; + sort_y.nth_element(0,p_size,p_size/2,p_children); + //sort_y.sort(&p_bb[p_from],p_size); + } break; + case Vector3::AXIS_Z: { + SortArray<BVH*,BVHCmpZ> sort_z; + sort_z.nth_element(0,p_size,p_size/2,p_children); + //sort_z.sort(&p_bb[p_from],p_size); + + } break; + } + + + BVH* left = _parse_bvh(p_children,p_size/2,p_depth+1,max_depth); + BVH* right = _parse_bvh(&p_children[p_size/2],p_size-p_size/2,p_depth+1,max_depth); + + BVH *_new = memnew(BVH); + _new->aabb=aabb; + _new->center=aabb.pos+aabb.size*0.5; + _new->children[0]=left; + _new->children[1]=right; + _new->leaf=NULL; + + return _new; +} + +void BakedLightBaker::_make_bvh() { + + Vector<BVH*> bases; + bases.resize(triangles.size()); + int max_depth=0; + for(int i=0;i<triangles.size();i++) { + bases[i]=memnew( BVH ); + bases[i]->leaf=&triangles[i]; + bases[i]->aabb.pos=triangles[i].vertices[0]; + bases[i]->aabb.expand_to(triangles[i].vertices[1]); + bases[i]->aabb.expand_to(triangles[i].vertices[2]); + triangles[i].aabb=bases[i]->aabb; + bases[i]->center=bases[i]->aabb.pos+bases[i]->aabb.size*0.5; + } + + bvh=_parse_bvh(bases.ptr(),bases.size(),1,max_depth); + ray_stack = memnew_arr(uint32_t,max_depth); + bvh_stack = memnew_arr(BVH*,max_depth); +} + +void BakedLightBaker::_octree_insert(int p_octant,Triangle* p_triangle, int p_depth) { + + + + + uint32_t *stack=octant_stack; + uint32_t *ptr_stack=octantptr_stack; + Octant *octants=octant_pool.ptr(); + + stack[0]=0; + ptr_stack[0]=0; + + int stack_pos=0; + + + while(true) { + + Octant *octant=&octants[ptr_stack[stack_pos]]; + if (stack[stack_pos]<8) { + + int i = stack[stack_pos]; + stack[stack_pos]++; + + + + //fit_aabb=fit_aabb.grow(bvh->aabb.size.x*0.0001); + + int child_idx =octant->children[i]; + bool encloses; + if (!child_idx) { + + AABB aabb=octant->aabb; + aabb.size*=0.5; + if (i&1) + aabb.pos.x+=aabb.size.x; + if (i&2) + aabb.pos.y+=aabb.size.y; + if (i&4) + aabb.pos.z+=aabb.size.z; + + aabb.grow_by(cell_size*octree_extra_margin); + if (!aabb.intersects(p_triangle->aabb)) + continue; + encloses=aabb.grow(cell_size*-octree_extra_margin*2.0).encloses(p_triangle->aabb); + if (!encloses && !Face3(p_triangle->vertices[0],p_triangle->vertices[1],p_triangle->vertices[2]).intersects_aabb2(aabb)) + continue; + } else { + + Octant *child=&octants[child_idx]; + AABB aabb=child->aabb; + aabb.grow_by(cell_size*octree_extra_margin); + if (!aabb.intersects(p_triangle->aabb)) + continue; + encloses=aabb.grow(cell_size*-octree_extra_margin*2.0).encloses(p_triangle->aabb); + if (!encloses && !Face3(p_triangle->vertices[0],p_triangle->vertices[1],p_triangle->vertices[2]).intersects_aabb2(aabb)) + continue; + + } + + if (encloses) + stack[stack_pos]=8; // quick and dirty opt + + if (!child_idx) { + + + if (octant_pool_size==octant_pool.size()) { + octant_pool.resize(octant_pool_size+OCTANT_POOL_CHUNK); + octants=octant_pool.ptr(); + octant=&octants[ptr_stack[stack_pos]]; + } + child_idx=octant_pool_size++; + octant->children[i]=child_idx; + Octant *child=&octants[child_idx]; + + child->aabb=octant->aabb; + child->texture_x=0; + child->texture_y=0; + + child->aabb.size*=0.5; + if (i&1) + child->aabb.pos.x+=child->aabb.size.x; + if (i&2) + child->aabb.pos.y+=child->aabb.size.y; + if (i&4) + child->aabb.pos.z+=child->aabb.size.z; + + + + if (stack_pos==octree_depth-1) { + child->leaf=true; + child->offset[0]=child->aabb.pos.x+child->aabb.size.x*0.5; + child->offset[1]=child->aabb.pos.y+child->aabb.size.y*0.5; + child->offset[2]=child->aabb.pos.z+child->aabb.size.z*0.5; + child->next_leaf=leaf_list; + + for(int ci=0;ci<8;ci++) { + child->normal_accum[ci][0]=0; + child->normal_accum[ci][1]=0; + child->normal_accum[ci][2]=0; + } + + child->bake_neighbour=0; + child->first_neighbour=true; + leaf_list=child_idx; + cell_count++; + + int lz = lights.size(); + child->light = memnew_arr(OctantLight,lz); + + for(int li=0;li<lz;li++) { + for(int ci=0;ci<8;ci++) { + child->light[li].accum[ci][0]=0; + child->light[li].accum[ci][1]=0; + child->light[li].accum[ci][2]=0; + } + } + + child->parent=ptr_stack[stack_pos]; + + } else { + + child->leaf=false; + for(int j=0;j<8;j++) { + child->children[j]=0; + } + } + } + + if (!octants[child_idx].leaf) { + stack_pos++; + stack[stack_pos]=0; + ptr_stack[stack_pos]=child_idx; + } else { + + Octant *child=&octants[child_idx]; + + Vector3 n = Plane(p_triangle->vertices[0],p_triangle->vertices[1],p_triangle->vertices[2]).normal; + + + for(int ci=0;ci<8;ci++) { + + Vector3 pos = child->aabb.pos; + + if (ci&1) + pos.x+=child->aabb.size.x; + if (ci&2) + pos.y+=child->aabb.size.y; + if (ci&4) + pos.z+=child->aabb.size.z; + + + pos.x=floor((pos.x+cell_size*0.5)/cell_size); + pos.y=floor((pos.y+cell_size*0.5)/cell_size); + pos.z=floor((pos.z+cell_size*0.5)/cell_size); + + Map<Vector3,Vector3>::Element *E=endpoint_normal.find(pos); + if (!E) { + endpoint_normal[pos]=n; + } else { + E->get()+=n; + } + + } + + } + + + } else { + stack_pos--; + if (stack_pos<0) + break; + } + } + + +} + + +void BakedLightBaker::_make_octree() { + + + AABB base = bvh->aabb; + float lal=base.get_longest_axis_size(); + //must be square because we want square blocks + base.size.x=lal; + base.size.y=lal; + base.size.z=lal; + base.grow_by(lal*0.001); //for precision + octree_aabb=base; + + cell_size=base.size.x; + for(int i=0;i<octree_depth;i++) + cell_size/=2.0; + octant_stack = memnew_arr(uint32_t,octree_depth*2 ); + octantptr_stack = memnew_arr(uint32_t,octree_depth*2 ); + + octant_pool.resize(OCTANT_POOL_CHUNK); + octant_pool_size=1; + Octant *root=octant_pool.ptr(); + root->leaf=false; + root->aabb=octree_aabb; + root->parent=-1; + for(int i=0;i<8;i++) + root->children[i]=0; + + EditorProgress ep("bake_octree","Parsing "+itos(triangles.size())+" Triangles:",triangles.size()); + + for(int i=0;i<triangles.size();i++) { + + _octree_insert(0,&triangles[i],octree_depth-1); + if ((i%1000)==0) { + + ep.step("Triangle# "+itos(i),i); + } + } + + { + uint32_t oct_idx=leaf_list; + Octant *octants=octant_pool.ptr(); + while(oct_idx) { + + BakedLightBaker::Octant *oct = &octants[oct_idx]; + for(int ci=0;ci<8;ci++) { + + + Vector3 pos = oct->aabb.pos; + + if (ci&1) + pos.x+=oct->aabb.size.x; + if (ci&2) + pos.y+=oct->aabb.size.y; + if (ci&4) + pos.z+=oct->aabb.size.z; + + + pos.x=floor((pos.x+cell_size*0.5)/cell_size); + pos.y=floor((pos.y+cell_size*0.5)/cell_size); + pos.z=floor((pos.z+cell_size*0.5)/cell_size); + + Map<Vector3,Vector3>::Element *E=endpoint_normal.find(pos); + if (!E) { + //? + print_line("lolwut?"); + } else { + Vector3 n = E->get().normalized(); + oct->normal_accum[ci][0]=n.x; + oct->normal_accum[ci][1]=n.y; + oct->normal_accum[ci][2]=n.z; + + } + + } + + oct_idx=oct->next_leaf; + } + } + + +} + + + + + +void BakedLightBaker::_plot_light(int p_light_index, const Vector3& p_plot_pos, const AABB& p_plot_aabb, const Color& p_light, const Plane& p_plane) { + + //stackless version + + uint32_t *stack=octant_stack; + uint32_t *ptr_stack=octantptr_stack; + Octant *octants=octant_pool.ptr(); + + stack[0]=0; + ptr_stack[0]=0; + + int stack_pos=0; + + + while(true) { + + Octant &octant=octants[ptr_stack[stack_pos]]; + + if (octant.leaf) { + + + + //if (p_plane.normal.dot(octant.aabb.get_support(p_plane.normal)) < p_plane.d-CMP_EPSILON) { //octants behind are no go + + + + float r=cell_size*plot_size; + for(int i=0;i<8;i++) { + Vector3 pos=octant.aabb.pos; + if (i&1) + pos.x+=octant.aabb.size.x; + if (i&2) + pos.y+=octant.aabb.size.y; + if (i&4) + pos.z+=octant.aabb.size.z; + + + + float d = p_plot_pos.distance_to(pos); + + if (d<=r) { + + + float intensity = 1.0 - (d/r)*(d/r); //not gauss but.. + float damp = Math::abs(p_plane.normal.dot(Vector3(octant.normal_accum[i][0],octant.normal_accum[i][1],octant.normal_accum[i][2]))); + intensity*=pow(damp,edge_damp); + //intensity*=1.0-Math::abs(p_plane.distance_to(pos))/(plot_size*cell_size); + octant.light[p_light_index].accum[i][0]+=p_light.r*intensity; + octant.light[p_light_index].accum[i][1]+=p_light.g*intensity; + octant.light[p_light_index].accum[i][2]+=p_light.b*intensity; + } + } + + stack_pos--; + } else if (stack[stack_pos]<8) { + + int i = stack[stack_pos]; + stack[stack_pos]++; + + if (!octant.children[i]) { + continue; + } + + Octant &child=octants[octant.children[i]]; + + if (!child.aabb.intersects(p_plot_aabb)) + continue; + + if (child.aabb.encloses(p_plot_aabb)) { + stack[stack_pos]=8; //don't test the rest + } + + stack_pos++; + stack[stack_pos]=0; + ptr_stack[stack_pos]=octant.children[i]; + } else { + stack_pos--; + if (stack_pos<0) + break; + } + } + + +} + + +float BakedLightBaker::_throw_ray(int p_light_index,const Vector3& p_begin, const Vector3& p_end,float p_rest,const Color& p_light,float *p_att_curve,float p_att_pos,int p_att_curve_len,int p_bounces,bool p_first_bounce) { + + + uint32_t* stack = ray_stack; + BVH **bstack = bvh_stack; + + enum { + TEST_AABB_BIT=0, + VISIT_LEFT_BIT=1, + VISIT_RIGHT_BIT=2, + VISIT_DONE_BIT=3, + + + }; + + Vector3 n = (p_end-p_begin); + float len=n.length(); + if (len==0) + return 0; + n/=len; + + + real_t d=1e10; + bool inters=false; + Vector3 r_normal; + Vector3 r_point; + Vector3 end=p_end; + + Triangle *triangle=NULL; + + //for(int i=0;i<max_depth;i++) + // stack[i]=0; + + int level=0; + //AABB ray_aabb; + //ray_aabb.pos=p_begin; + //ray_aabb.expand_to(p_end); + + + const BVH *bvhptr = bvh; + + bstack[0]=bvh; + stack[0]=TEST_AABB_BIT; + + + while(true) { + + uint32_t mode = stack[level]; + const BVH &b = *bstack[level]; + bool done=false; + + switch(mode) { + case TEST_AABB_BIT: { + + if (b.leaf) { + + + Face3 f3(b.leaf->vertices[0],b.leaf->vertices[1],b.leaf->vertices[2]); + + + Vector3 res; + + if (f3.intersects_segment(p_begin,end,&res)) { + + + float nd = n.dot(res); + if (nd<d) { + + d=nd; + r_point=res; + end=res; + len=(p_begin-end).length(); + r_normal=f3.get_plane().get_normal(); + triangle=b.leaf; + inters=true; + } + + } + + stack[level]=VISIT_DONE_BIT; + } else { + + + bool valid = b.aabb.smits_intersect_ray(p_begin,n,0,len); + //bool valid = b.aabb.intersects_segment(p_begin,p_end); + // bool valid = b.aabb.intersects(ray_aabb); + + if (!valid) { + + stack[level]=VISIT_DONE_BIT; + + } else { + + stack[level]=VISIT_LEFT_BIT; + } + } + + } continue; + case VISIT_LEFT_BIT: { + + stack[level]=VISIT_RIGHT_BIT; + bstack[level+1]=b.children[0]; + stack[level+1]=TEST_AABB_BIT; + level++; + + } continue; + case VISIT_RIGHT_BIT: { + + stack[level]=VISIT_DONE_BIT; + bstack[level+1]=b.children[1]; + stack[level+1]=TEST_AABB_BIT; + level++; + } continue; + case VISIT_DONE_BIT: { + + if (level==0) { + done=true; + break; + } else + level--; + + } continue; + } + + + if (done) + break; + } + + + if (inters) { + + + + //should check if there is normals first + Vector2 uv; + if (true) { + + triangle->get_uv_and_normal(r_point,uv,r_normal); + + } else { + + } + + if (n.dot(r_normal)>0) + r_normal=-r_normal; + + + //ok... + Color diffuse_at_point(0.8,0.8,0.8); + Color specular_at_point(0.0,0.0,0.0); + + if (triangle->material) { + + //triangle->get_uv(r_point); + diffuse_at_point=triangle->material->diffuse.get_color(uv); + specular_at_point=triangle->material->specular.get_color(uv); + } + + float dist = p_begin.distance_to(r_point); + + AABB aabb; + aabb.pos=r_point; + aabb.pos-=Vector3(1,1,1)*cell_size*plot_size; + aabb.size=Vector3(2,2,2)*cell_size*plot_size; + + Color res_light=p_light; + float att=1.0; + float dp=(1.0-normal_damp)*n.dot(-r_normal)+normal_damp; + + if (p_att_curve) { + + p_att_pos+=dist; + int cpos = Math::fast_ftoi((p_att_pos/p_att_curve_len)*ATTENUATION_CURVE_LEN); + cpos=CLAMP(cpos,0,ATTENUATION_CURVE_LEN-1); + att=p_att_curve[cpos]; + } + + + res_light.r*=dp; + res_light.g*=dp; + res_light.b*=dp; + + //light is plotted before multiplication with diffuse, this way + //the multiplication can happen with more detail in the shader + + + float ret=1e6; + + if (p_bounces>0) { + + + p_rest-=dist; + if (p_rest<CMP_EPSILON) + return 0; + + if (r_normal==-n) + return 0; //todo change a little + + r_point+=r_normal*0.01; + + + + + diffuse_at_point.r=res_light.r*diffuse_at_point.r; + diffuse_at_point.g=res_light.g*diffuse_at_point.g; + diffuse_at_point.b=res_light.b*diffuse_at_point.b; + + specular_at_point.r=res_light.r*specular_at_point.r; + specular_at_point.g=res_light.g*specular_at_point.g; + specular_at_point.b=res_light.b*specular_at_point.b; + + + + if (use_diffuse && (diffuse_at_point.r>CMP_EPSILON || diffuse_at_point.g>CMP_EPSILON || diffuse_at_point.b>CMP_EPSILON)) { + //diffuse bounce + + Vector3 c1=r_normal.cross(n).normalized(); + Vector3 c2=r_normal.cross(c1).normalized(); + double r1 = double(rand())/RAND_MAX; + double r2 = double(rand())/RAND_MAX; + double r3 = double(rand())/RAND_MAX; +#if 0 + Vector3 next = - ((c1*(r1-0.5)) + (c2*(r2-0.5)) + (r_normal*(r3-0.5))).normalized()*0.5 + r_normal*0.5; + + if (next==Vector3()) + next=r_normal; + Vector3 rn=next.normalized(); + +#else + Vector3 rn = ((c1*(r1-0.5)) + (c2*(r2-0.5)) + (r_normal*r3*0.5)).normalized(); +#endif + + + ret=_throw_ray(p_light_index,r_point,r_point+rn*p_rest,p_rest,diffuse_at_point,p_att_curve,p_att_pos,p_att_curve_len,p_bounces-1); + } + + if (use_specular && (specular_at_point.r>CMP_EPSILON || specular_at_point.g>CMP_EPSILON || specular_at_point.b>CMP_EPSILON)) { + //specular bounce + + //Vector3 c1=r_normal.cross(n).normalized(); + //Vector3 c2=r_normal.cross(c1).normalized(); + + Vector3 rn = n - r_normal *r_normal.dot(n) * 2.0; + + _throw_ray(p_light_index,r_point,r_point+rn*p_rest,p_rest,specular_at_point,p_att_curve,p_att_pos,p_att_curve_len,p_bounces-1); + } + } + + //specular later +// _plot_light_point(r_point,octree,octree_aabb,p_light); + + + Color plot_light=res_light; + plot_light.r*=att; + plot_light.g*=att; + plot_light.b*=att; + + if (!p_first_bounce) { + + + float r = plot_size * cell_size; + if (ret<r) { + //avoid accumulaiton of light on corners + //plot_light=plot_light.linear_interpolate(Color(0,0,0,0),1.0-sd/plot_size*plot_size); + plot_light=Color(0,0,0,0); + } + } + + + if (!p_first_bounce || lights[p_light_index].bake_direct) { + Plane plane(r_point,r_normal); + //print_line(String(plot_light)+String(" ")+rtos(att)); + _plot_light(p_light_index,r_point,aabb,plot_light,plane); + } + + + return dist; + } + + return 0; + +} + + + + +void BakedLightBaker::_make_octree_texture() { + + + BakedLightBaker::Octant *octants=octant_pool.ptr(); + + //find neighbours first, to have a better idea of what amount of space is needed + { + + Vector<OctantHash> octant_hashing; + octant_hashing.resize(octant_pool_size); + Vector<uint32_t> hash_table; + int hash_table_size=Math::larger_prime(16384); + hash_table.resize(hash_table_size); + uint32_t*hashptr = hash_table.ptr(); + OctantHash*octhashptr = octant_hashing.ptr(); + + for(int i=0;i<hash_table_size;i++) + hashptr[i]=0; + + + //step 1 add to hash table + + uint32_t oct_idx=leaf_list; + + + while(oct_idx) { + + BakedLightBaker::Octant *oct = &octants[oct_idx]; + uint64_t base=0; + Vector3 pos = oct->aabb.pos - octree_aabb.pos; //make sure is always positive + base=int((pos.x+cell_size*0.5)/cell_size); + base<<=16; + base|=int((pos.y+cell_size*0.5)/cell_size); + base<<=16; + base|=int((pos.z+cell_size*0.5)/cell_size); + + uint32_t hash = HashMapHahserDefault::hash(base); + uint32_t idx = hash % hash_table_size; + octhashptr[oct_idx].next=hashptr[idx]; + octhashptr[oct_idx].hash=hash; + octhashptr[oct_idx].value=base; + hashptr[idx]=oct_idx; + + oct_idx=oct->next_leaf; + + } + + //step 2 find neighbours + oct_idx=leaf_list; + int neighbours=0; + + + while(oct_idx) { + + BakedLightBaker::Octant *oct = &octants[oct_idx]; + Vector3 pos = oct->aabb.pos - octree_aabb.pos; //make sure is always positive + pos.x+=cell_size; + uint64_t base=0; + base=int((pos.x+cell_size*0.5)/cell_size); + base<<=16; + base|=int((pos.y+cell_size*0.5)/cell_size); + base<<=16; + base|=int((pos.z+cell_size*0.5)/cell_size); + + uint32_t hash = HashMapHahserDefault::hash(base); + uint32_t idx = hash % hash_table_size; + + uint32_t bucket = hashptr[idx]; + + while(bucket) { + + if (octhashptr[bucket].value==base) { + + oct->bake_neighbour=bucket; + octants[bucket].first_neighbour=false; + neighbours++; + break; + } + + bucket = octhashptr[bucket].next; + } + + oct_idx=oct->next_leaf; + + } + + print_line("octant with neighbour: "+itos(neighbours)); + + } + + + //ok let's try to just create a texture + + { + + int otex_w=(1<<lattice_size)*(1<<lattice_size)*2; //make sure lattice fits horizontally + Vector3 lattice_cell_size=octree_aabb.size; + for(int i=0;i<lattice_size;i++) { + + lattice_cell_size*=0.5; + } + + + + while(true) { + + //let's plot the leafs first, given the octree is not so obvious which size it will have + int row=4+4*(1<<lattice_size); + + + uint32_t oct_idx=leaf_list; + + //untag + while(oct_idx) { + + BakedLightBaker::Octant *oct = &octants[oct_idx]; + //0,0 also means unprocessed + oct->texture_x=0; + oct->texture_y=0; + oct_idx=oct->next_leaf; + + } + + oct_idx=leaf_list; + + + print_line("begin at row "+itos(row)); + int longest_line_reused=0; + int col=0; + int processed=0; + + while(oct_idx) { + + BakedLightBaker::Octant *oct = &octants[oct_idx]; + if (oct->first_neighbour && oct->texture_x==0 && oct->texture_y==0) { + //was not processed + uint32_t current_idx=oct_idx; + int reused=0; + + while(current_idx) { + BakedLightBaker::Octant *o = &octants[current_idx]; + if (col+1 >= otex_w) { + col=0; + row+=4; + } + o->texture_x=col; + o->texture_y=row; + processed++; + + if (o->bake_neighbour) { + reused++; + } + col+=o->bake_neighbour ? 1 : 2; //reuse neighbour + current_idx=o->bake_neighbour; + } + + if (reused>longest_line_reused) { + longest_line_reused=reused; + } + } + oct_idx=oct->next_leaf; + } + + print_line("processed "+itos(processed)); + + print_line("longest reused: "+itos(longest_line_reused)); + + col=0; + row+=4; + print_line("end at row "+itos(row)); + + //put octree, no need for recursion, just loop backwards. + int regular_octants=0; + for(int i=octant_pool_size-1;i>=0;i--) { + + BakedLightBaker::Octant *oct = &octants[i]; + if (oct->leaf) //ignore leaf + continue; + if (oct->aabb.size.x>lattice_cell_size.x*1.1) { //bigger than latice, skip + oct->texture_x=0; + oct->texture_y=0; + } else if (oct->aabb.size.x>lattice_cell_size.x*0.8) { + //this is the initial lattice + Vector3 pos = oct->aabb.pos - octree_aabb.pos; //make sure is always positive + int x = int((pos.x+lattice_cell_size.x*0.5)/lattice_cell_size.x); + int y = int((pos.y+lattice_cell_size.y*0.5)/lattice_cell_size.y); + int z = int((pos.z+lattice_cell_size.z*0.5)/lattice_cell_size.z); + //bug net + ERR_FAIL_INDEX(x,(1<<lattice_size)); + ERR_FAIL_INDEX(y,(1<<lattice_size)); + ERR_FAIL_INDEX(z,(1<<lattice_size)); + + /*int ofs = z*(1<<lattice_size)*(1<<lattice_size)+y*(1<<lattice_size)+x; + ofs*=4; + oct->texture_x=ofs%otex_w; + oct->texture_y=(ofs/otex_w)*4+4; + */ + + oct->texture_x=(x+(1<<lattice_size)*z)*2; + oct->texture_y=4+y*4; + //print_line("pos: "+itos(x)+","+itos(y)+","+itos(z)+" - ofs"+itos(oct->texture_x)+","+itos(oct->texture_y)); + + + } else { + //an everyday regular octant + + if (col+2 > otex_w) { + col=0; + row+=4; + } + + oct->texture_x=col; + oct->texture_y=row; + col+=2; + regular_octants++; + + + } + } + print_line("octants end at row "+itos(row)+" totalling"+itos(regular_octants)); + + //ok evaluation. + + if (otex_w<=2048 && row>2048) { //too big upwards, try bigger texture + otex_w*=2; + continue; + } else { + baked_octree_texture_w=otex_w; + baked_octree_texture_h=row+4; + break; + } + + } + + + } + + + baked_octree_texture_h=nearest_power_of_2(baked_octree_texture_h); + print_line("RESULT! "+itos(baked_octree_texture_w)+","+itos(baked_octree_texture_h)); + +} + + + + + + + + +double BakedLightBaker::get_normalization(int p_light_idx) const { + + double nrg=0; + + const LightData &dl=lights[p_light_idx]; + double cell_area = cell_size*cell_size;; + //nrg+= /*dl.energy */ (dl.rays_thrown * cell_area / dl.area); + nrg=dl.rays_thrown * cell_area; + nrg*=(Math_PI*plot_size*plot_size)*0.5; // damping of radial linear gradient kernel + nrg*=dl.constant; + //nrg*=5; + print_line("CS: "+rtos(cell_size)); + + return nrg; +} + +void BakedLightBaker::throw_rays(int p_amount) { + + + + for(int i=0;i<lights.size();i++) { + + LightData &dl=lights[i]; + + + int amount = p_amount * total_light_area / dl.area; + + switch(dl.type) { + + case VS::LIGHT_DIRECTIONAL: { + + + for(int j=0;j<amount;j++) { + Vector3 from = dl.pos; + double r1 = double(rand())/RAND_MAX; + double r2 = double(rand())/RAND_MAX; + from+=dl.up*(r1*2.0-1.0); + from+=dl.left*(r2*2.0-1.0); + Vector3 to = from+dl.dir*dl.length; + Color col=dl.diffuse; + col.r*=dl.energy; + col.g*=dl.energy; + col.b*=dl.energy; + dl.rays_thrown++; + total_rays++; + _throw_ray(i,from,to,dl.length,col,NULL,0,0,max_bounces,true); + } + } break; + case VS::LIGHT_OMNI: { + + + for(int j=0;j<amount;j++) { + Vector3 from = dl.pos; + + double r1 = double(rand())/RAND_MAX; + double r2 = double(rand())/RAND_MAX; + double r3 = double(rand())/RAND_MAX; + +#if 0 + //crap is not uniform.. + Vector3 dir = Vector3(r1*2.0-1.0,r2*2.0-1.0,r3*2.0-1.0).normalized(); + +#else + + double phi = r1*Math_PI*2.0; + double costheta = r2*2.0-1.0; + double u = r3; + + double theta = acos( costheta ); + double r = 1.0 * pow( u,1/3.0 ); + + Vector3 dir( + r * sin( theta) * cos( phi ), + r * sin( theta) * sin( phi ), + r * cos( theta ) + ); + dir.normalize(); + +#endif + Vector3 to = dl.pos+dir*dl.radius; + Color col=dl.diffuse; + col.r*=dl.energy; + col.g*=dl.energy; + col.b*=dl.energy; + + dl.rays_thrown++; + total_rays++; + _throw_ray(i,from,to,dl.radius,col,dl.attenuation_table.ptr(),0,dl.radius,max_bounces,true); +// _throw_ray(i,from,to,dl.radius,col,NULL,0,dl.radius,max_bounces,true); + } + + } break; + case VS::LIGHT_SPOT: { + + for(int j=0;j<amount;j++) { + Vector3 from = dl.pos; + + double r1 = double(rand())/RAND_MAX; + double r2 = double(rand())/RAND_MAX; + double r3 = double(rand())/RAND_MAX; + + float d=Math::tan(Math::deg2rad(dl.spot_angle)); + + float x = sin(r1*Math_PI*2.0)*d; + float y = cos(r1*Math_PI*2.0)*d; + + Vector3 dir = r3*(dl.dir + dl.up*y + dl.left*x) + (1.0-r3)*dl.dir; + dir.normalize(); + + + Vector3 to = dl.pos+dir*dl.radius; + Color col=dl.diffuse; + col.r*=dl.energy; + col.g*=dl.energy; + col.b*=dl.energy; + + dl.rays_thrown++; + total_rays++; + _throw_ray(i,from,to,dl.radius,col,dl.attenuation_table.ptr(),0,dl.radius,max_bounces,true); + // _throw_ray(i,from,to,dl.radius,col,NULL,0,dl.radius,max_bounces,true); + } + + } break; + + } + } +} + + + + + + + + + + + + + +void BakedLightBaker::bake(const Ref<BakedLight> &p_light, Node* p_node) { + + if (baking) + return; + cell_count=0; + + base_inv=p_node->cast_to<Spatial>()->get_global_transform().affine_inverse(); + EditorProgress ep("bake","Light Baker Setup:",5); + baked_light=p_light; + lattice_size=baked_light->get_initial_lattice_subdiv(); + octree_depth=baked_light->get_cell_subdivision(); + plot_size=baked_light->get_plot_size(); + max_bounces=baked_light->get_bounces(); + use_diffuse=baked_light->get_bake_flag(BakedLight::BAKE_DIFFUSE); + use_specular=baked_light->get_bake_flag(BakedLight::BAKE_SPECULAR); + use_translucency=baked_light->get_bake_flag(BakedLight::BAKE_TRANSLUCENT); + + edge_damp=baked_light->get_edge_damp(); + normal_damp=baked_light->get_normal_damp(); + octree_extra_margin=baked_light->get_cell_extra_margin(); + + + + ep.step("Parsing Geometry",0); + _parse_geometry(p_node); + mat_map.clear(); + tex_map.clear(); + print_line("\ttotal triangles: "+itos(triangles.size())); + ep.step("Fixing Lights",1); + _fix_lights(); + ep.step("Making BVH",2); + _make_bvh(); + ep.step("Creating Light Octree",3); + _make_octree(); + ep.step("Creating Octree Texture",4); + _make_octree_texture(); + baking=true; + _start_thread(); + +} + + +void BakedLightBaker::update_octree_image(DVector<uint8_t> &p_image) { + + + int len = baked_octree_texture_w*baked_octree_texture_h*4; + p_image.resize(len); + DVector<uint8_t>::Write w = p_image.write(); + zeromem(w.ptr(),len); + float gamma = baked_light->get_gamma_adjust(); + float mult = baked_light->get_energy_multiplier(); + + for(int i=0;i<len;i+=4) { + w[i+0]=0xFF; + w[i+1]=0; + w[i+2]=0xFF; + w[i+3]=0xFF; + } + + encode_uint32(baked_octree_texture_w,&w[0]); + encode_uint32(baked_octree_texture_h,&w[4]); + encode_uint32(0,&w[8]); + encode_float(1<<lattice_size,&w[12]); + encode_uint32(octree_depth-lattice_size,&w[16]); + + encode_float(octree_aabb.pos.x,&w[32]); + encode_float(octree_aabb.pos.y,&w[36]); + encode_float(octree_aabb.pos.z,&w[40]); + encode_float(octree_aabb.size.x,&w[44]); + encode_float(octree_aabb.size.y,&w[48]); + encode_float(octree_aabb.size.z,&w[52]); + + + BakedLightBaker::Octant *octants=octant_pool.ptr(); + int octant_count=octant_pool_size; + uint8_t *ptr = w.ptr(); + + + int child_offsets[8]={ + 0, + 4, + baked_octree_texture_w*4, + baked_octree_texture_w*4+4, + baked_octree_texture_w*8+0, + baked_octree_texture_w*8+4, + baked_octree_texture_w*8+baked_octree_texture_w*4, + baked_octree_texture_w*8+baked_octree_texture_w*4+4, + }; + + Vector<double> norm_arr; + norm_arr.resize(lights.size()); + + for(int i=0;i<lights.size();i++) { + norm_arr[i] = 1.0/get_normalization(i); + } + + const double *normptr=norm_arr.ptr(); + + int lz=lights.size(); + + for(int i=0;i<octant_count;i++) { + + Octant &oct=octants[i]; + if (oct.texture_x==0 && oct.texture_y==0) + continue; + int ofs = (oct.texture_y * baked_octree_texture_w + oct.texture_x)<<2; + + if (oct.leaf) { + + //write colors + for(int j=0;j<8;j++) { + + //if (!oct.children[j]) + // continue; + uint8_t *iptr=&ptr[ofs+child_offsets[j]]; + float r=0; + float g=0; + float b=0; + + for(int k=0;k<lz;k++) { + r+=oct.light[k].accum[j][0]*normptr[k]; + g+=oct.light[k].accum[j][1]*normptr[k]; + b+=oct.light[k].accum[j][2]*normptr[k]; + } + + r=pow(r*mult,gamma); + g=pow(g*mult,gamma); + b=pow(b*mult,gamma); + + float ic[3]={ + r, + g, + b, + }; + iptr[0]=CLAMP(ic[0]*255.0,0,255); + iptr[1]=CLAMP(ic[1]*255.0,0,255); + iptr[2]=CLAMP(ic[2]*255.0,0,255); + iptr[3]=255; + } + + } else { + + + //write indices + for(int j=0;j<8;j++) { + + if (!oct.children[j]) + continue; + Octant&choct=octants[oct.children[j]]; + uint8_t *iptr=&ptr[ofs+child_offsets[j]]; + + iptr[0]=choct.texture_x>>8; + iptr[1]=choct.texture_x&0xFF; + iptr[2]=choct.texture_y>>8; + iptr[3]=choct.texture_y&0xFF; + + } + } + + } + + +} + + +void BakedLightBaker::_free_bvh(BVH* p_bvh) { + + if (!p_bvh->leaf) { + if (p_bvh->children[0]) + _free_bvh(p_bvh->children[0]); + if (p_bvh->children[1]) + _free_bvh(p_bvh->children[1]); + } + + memdelete(p_bvh); + +} + + +bool BakedLightBaker::is_baking() { + + return baking; +} + +void BakedLightBaker::set_pause(bool p_pause){ + + if (paused==p_pause) + return; + + paused=p_pause; + + if (paused) { + _stop_thread(); + } else { + _start_thread(); + } +} +bool BakedLightBaker::is_paused() { + + return paused; + +} + +void BakedLightBaker::_bake_thread_func(void *arg) { + + BakedLightBaker *ble = (BakedLightBaker*)arg; + + ble->rays_at_snap_time=ble->total_rays; + ble->snap_time=OS::get_singleton()->get_ticks_usec(); + + while(!ble->bake_thread_exit) { + + ble->throw_rays(1000); + uint64_t t=OS::get_singleton()->get_ticks_usec(); + if (t-ble->snap_time>1000000) { + + double time = (t-ble->snap_time)/1000000.0; + + int rays=ble->total_rays-ble->rays_at_snap_time; + ble->rays_sec=int(rays/time); + ble->snap_time=OS::get_singleton()->get_ticks_usec(); + ble->rays_at_snap_time=ble->total_rays; + } + } + +} + +void BakedLightBaker::_start_thread() { + + if (thread!=NULL) + return; + bake_thread_exit=false; + thread=Thread::create(_bake_thread_func,this); + +} + +void BakedLightBaker::_stop_thread() { + + if (thread==NULL) + return; + bake_thread_exit=true; + Thread::wait_to_finish(thread); + thread=NULL; +} + +void BakedLightBaker::clear() { + + + + _stop_thread(); + + if (bvh) + _free_bvh(bvh); + + if (ray_stack) + memdelete_arr(ray_stack); + if (octant_stack) + memdelete_arr(octant_stack); + if (octantptr_stack) + memdelete_arr(octantptr_stack); + if (bvh_stack) + memdelete_arr(bvh_stack); + + for(int i=0;i<octant_pool.size();i++) { + if (octant_pool[i].leaf) { + memdelete_arr( octant_pool[i].light ); + } + } + octant_pool.clear(); + octant_pool_size=0; + bvh=NULL; + leaf_list=0; + cell_count=0; + ray_stack=NULL; + octant_stack=NULL; + octantptr_stack=NULL; + bvh_stack=NULL; + materials.clear(); + materials.clear(); + textures.clear(); + lights.clear(); + triangles.clear();; + endpoint_normal.clear(); + baked_octree_texture_w=0; + baked_octree_texture_h=0; + paused=false; + baking=false; + thread=NULL; + bake_thread_exit=false; + baked_light=Ref<BakedLight>(); + total_rays=0; + +} + +BakedLightBaker::BakedLightBaker() { + octree_depth=9; + lattice_size=4; + octant_pool.clear(); + octant_pool_size=0; + bvh=NULL; + leaf_list=0; + cell_count=0; + ray_stack=NULL; + bvh_stack=NULL; + octant_stack=NULL; + octantptr_stack=NULL; + plot_size=2.5; + max_bounces=2; + materials.clear(); + baked_octree_texture_w=0; + baked_octree_texture_h=0; + paused=false; + baking=false; + thread=NULL; + bake_thread_exit=false; + rays_at_snap_time=0; + snap_time=0; + rays_sec=0; + total_rays=0; + +} + +BakedLightBaker::~BakedLightBaker() { + + clear(); +} diff --git a/tools/editor/plugins/baked_light_baker.h b/tools/editor/plugins/baked_light_baker.h new file mode 100644 index 0000000000..99c8211eed --- /dev/null +++ b/tools/editor/plugins/baked_light_baker.h @@ -0,0 +1,316 @@ +#ifndef BAKED_LIGHT_BAKER_H +#define BAKED_LIGHT_BAKER_H + +#include "scene/3d/baked_light_instance.h" +#include "scene/3d/light.h" +#include "scene/3d/mesh_instance.h" +#include "os/thread.h" + +class BakedLightBaker { +public: + + enum { + + ATTENUATION_CURVE_LEN=256, + OCTANT_POOL_CHUNK=1000000 + }; + + struct OctantLight { + + double accum[8][3]; + }; + + struct Octant { + bool leaf; + AABB aabb; + uint16_t texture_x; + uint16_t texture_y; + float normal_accum[8][3]; + int parent; + union { + struct { + int next_leaf; + float offset[3]; + int bake_neighbour; + bool first_neighbour; + OctantLight *light; + }; + int children[8]; + }; + }; + + struct OctantHash { + + int next; + uint32_t hash; + uint64_t value; + + }; + + struct MeshTexture { + + Vector<uint8_t> tex; + int tex_w,tex_h; + + _FORCE_INLINE_ void get_color(const Vector2& p_uv,Color& ret) { + + if (tex_w && tex_h) { + + int x = Math::fast_ftoi(Math::fposmod(p_uv.x,1.0)*tex_w); + int y = Math::fast_ftoi(Math::fposmod(p_uv.y,1.0)*tex_w); + x=CLAMP(x,0,tex_w-1); + y=CLAMP(y,0,tex_h-1); + const uint8_t*ptr = &tex[(y*tex_w+x)*4]; + ret.r*=ptr[0]/255.0; + ret.g*=ptr[1]/255.0; + ret.b*=ptr[2]/255.0; + ret.a*=ptr[3]/255.0; + } + } + + }; + + struct Param { + + Color color; + MeshTexture*tex; + _FORCE_INLINE_ Color get_color(const Vector2& p_uv) { + + Color ret=color; + if (tex) + tex->get_color(p_uv,ret); + return ret; + + } + + }; + + struct MeshMaterial { + + Param diffuse; + Param specular; + Param emission; + }; + + struct Triangle { + + AABB aabb; + Vector3 vertices[3]; + Vector2 uvs[3]; + Vector3 normals[3]; + MeshMaterial *material; + + _FORCE_INLINE_ Vector2 get_uv(const Vector3& p_pos) { + + Vector3 v0 = vertices[1] - vertices[0]; + Vector3 v1 = vertices[2] - vertices[0]; + Vector3 v2 = p_pos - vertices[0]; + + float d00 = v0.dot( v0); + float d01 = v0.dot( v1); + float d11 = v1.dot( v1); + float d20 = v2.dot( v0); + float d21 = v2.dot( v1); + float denom = (d00 * d11 - d01 * d01); + if (denom==0) + return uvs[0]; + float v = (d11 * d20 - d01 * d21) / denom; + float w = (d00 * d21 - d01 * d20) / denom; + float u = 1.0f - v - w; + + return uvs[0]*u + uvs[1]*v + uvs[2]*w; + } + + _FORCE_INLINE_ void get_uv_and_normal(const Vector3& p_pos,Vector2& r_uv,Vector3& r_normal) { + + Vector3 v0 = vertices[1] - vertices[0]; + Vector3 v1 = vertices[2] - vertices[0]; + Vector3 v2 = p_pos - vertices[0]; + + float d00 = v0.dot( v0); + float d01 = v0.dot( v1); + float d11 = v1.dot( v1); + float d20 = v2.dot( v0); + float d21 = v2.dot( v1); + float denom = (d00 * d11 - d01 * d01); + if (denom==0) { + r_normal=normals[0]; + r_uv=uvs[0]; + return; + } + float v = (d11 * d20 - d01 * d21) / denom; + float w = (d00 * d21 - d01 * d20) / denom; + float u = 1.0f - v - w; + + r_uv=uvs[0]*u + uvs[1]*v + uvs[2]*w; + r_normal=(normals[0]*u+normals[1]*v+normals[2]*w).normalized(); + } + }; + + + struct BVH { + + AABB aabb; + Vector3 center; + Triangle *leaf; + BVH*children[2]; + }; + + + struct BVHCmpX { + + bool operator()(const BVH* p_left, const BVH* p_right) const { + + return p_left->center.x < p_right->center.x; + } + }; + + struct BVHCmpY { + + bool operator()(const BVH* p_left, const BVH* p_right) const { + + return p_left->center.y < p_right->center.y; + } + }; + struct BVHCmpZ { + + bool operator()(const BVH* p_left, const BVH* p_right) const { + + return p_left->center.z < p_right->center.z; + } + }; + + + struct LightData { + + VS::LightType type; + + Vector3 pos; + Vector3 up; + Vector3 left; + Vector3 dir; + Color diffuse; + Color specular; + float energy; + float length; + int rays_thrown; + + float radius; + float attenuation; + float spot_angle; + float spot_attenuation; + float area; + + float constant; + + bool bake_direct; + + Vector<float> attenuation_table; + + }; + + + Vector<LightData> lights; + + List<MeshMaterial> materials; + List<MeshTexture> textures; + + AABB octree_aabb; + Vector<Octant> octant_pool; + int octant_pool_size; + BVH*bvh; + Vector<Triangle> triangles; + Transform base_inv; + int leaf_list; + int octree_depth; + int cell_count; + uint32_t *ray_stack; + uint32_t *octant_stack; + uint32_t *octantptr_stack; + Map<Vector3,Vector3> endpoint_normal; + BVH **bvh_stack; + float cell_size; + float plot_size; //multiplied by cell size + float octree_extra_margin; + + int max_bounces; + uint64_t total_rays; + bool use_diffuse; + bool use_specular; + bool use_translucency; + + + int baked_octree_texture_w; + int baked_octree_texture_h; + int lattice_size; + float edge_damp; + float normal_damp; + + bool paused; + bool baking; + + Map<Ref<Material>,MeshMaterial*> mat_map; + Map<Ref<Texture>,MeshTexture*> tex_map; + + + + MeshTexture* _get_mat_tex(const Ref<Texture>& p_tex); + void _add_mesh(const Ref<Mesh>& p_mesh,const Ref<Material>& p_mat_override,const Transform& p_xform); + void _parse_geometry(Node* p_node); + BVH* _parse_bvh(BVH** p_children,int p_size,int p_depth,int& max_depth); + void _make_bvh(); + void _make_octree(); + void _make_octree_texture(); + void _octree_insert(int p_octant, Triangle* p_triangle, int p_depth); + + + void _free_bvh(BVH* p_bvh); + + void _fix_lights(); + + Ref<BakedLight> baked_light; + + + //void _plot_light(const Vector3& p_plot_pos,const AABB& p_plot_aabb,const Color& p_light,int p_octant=0); + void _plot_light(int p_light_index,const Vector3& p_plot_pos,const AABB& p_plot_aabb,const Color& p_light,const Plane& p_plane); + //void _plot_light_point(const Vector3& p_plot_pos, Octant *p_octant, const AABB& p_aabb,const Color& p_light); + + float _throw_ray(int p_light_index,const Vector3& p_begin, const Vector3& p_end,float p_rest,const Color& p_light,float *p_att_curve,float p_att_pos,int p_att_curve_len,int p_bounces,bool p_first_bounce=false); + + + float total_light_area; + uint64_t rays_at_snap_time; + uint64_t snap_time; + int rays_sec; + + + Thread *thread; + bool bake_thread_exit; + static void _bake_thread_func(void *arg); + + void _start_thread(); + void _stop_thread(); +public: + + + void throw_rays(int p_amount); + double get_normalization(int p_light_idx) const; + + void bake(const Ref<BakedLight>& p_light,Node *p_base); + bool is_baking(); + void set_pause(bool p_pause); + bool is_paused(); + int get_rays_sec() { return rays_sec; } + + void update_octree_image(DVector<uint8_t> &p_image); + + Ref<BakedLight> get_baked_light() { return baked_light; } + + void clear(); + + BakedLightBaker(); + ~BakedLightBaker(); + +}; + +#endif // BAKED_LIGHT_BAKER_H diff --git a/tools/editor/plugins/baked_light_editor_plugin.cpp b/tools/editor/plugins/baked_light_editor_plugin.cpp index 77f9d1ed78..4d84b95900 100644 --- a/tools/editor/plugins/baked_light_editor_plugin.cpp +++ b/tools/editor/plugins/baked_light_editor_plugin.cpp @@ -1,831 +1,19 @@ #include "baked_light_editor_plugin.h" #include "scene/gui/box_container.h" #include "scene/3d/mesh_instance.h" -#include "scene/3d/light.h" +#include "io/marshalls.h" +#include "io/resource_saver.h" -class BakedLightBaker { -public: - - enum { - - ATTENUATION_CURVE_LEN=256 - }; - - struct Octant { - bool leaf; - union { - struct { - float light_accum[3]; - float surface_area; - Octant *next_leaf; - float offset[3]; - }; - Octant* children[8]; - }; - }; - - struct Triangle { - - Vector3 vertices[3]; - Vector2 uv[3]; - }; - - - struct BVH { - - AABB aabb; - Vector3 center; - Triangle *leaf; - BVH*children[2]; - }; - - - struct BVHCmpX { - - bool operator()(const BVH* p_left, const BVH* p_right) const { - - return p_left->center.x < p_right->center.x; - } - }; - - struct BVHCmpY { - - bool operator()(const BVH* p_left, const BVH* p_right) const { - - return p_left->center.y < p_right->center.y; - } - }; - struct BVHCmpZ { - - bool operator()(const BVH* p_left, const BVH* p_right) const { - - return p_left->center.z < p_right->center.z; - } - }; - - - struct DirLight { - - - Vector3 pos; - Vector3 up; - Vector3 left; - Vector3 dir; - Color diffuse; - Color specular; - float energy; - float length; - int rays_thrown; - - }; - - AABB octree_aabb; - Octant *octree; - BVH*bvh; - Vector<Triangle> triangles; - Transform base_inv; - Octant *leaf_list; - int octree_depth; - int cell_count; - uint32_t *ray_stack; - BVH **bvh_stack; - float cell_size; - float plot_size; //multiplied by cell size - Vector<DirLight> directional_lights; - int max_bounces; - - - - void _add_mesh(const Ref<Mesh>& p_mesh,const Ref<Material>& p_mat_override,const Transform& p_xform); - void _parse_geometry(Node* p_node); - BVH* _parse_bvh(BVH** p_children,int p_size,int p_depth,int& max_depth); - void _make_bvh(); - void _make_octree(); - void _octree_insert(const AABB& p_aabb,Octant *p_octant,Triangle* p_triangle, int p_depth); - - void _free_octree(Octant *p_octant) { - - if (!p_octant->leaf) { - - for(int i=0;i<8;i++) { - if (p_octant->children[i]) - _free_octree(p_octant->children[i]); - } - } - - memdelete(p_octant); - } - - void _free_bvh(BVH* p_bvh) { - - if (!p_bvh->leaf) { - if (p_bvh->children[0]) - _free_bvh(p_bvh->children[0]); - if (p_bvh->children[1]) - _free_bvh(p_bvh->children[1]); - } - - memdelete(p_bvh); - - } - - void _fix_lights(); - - - void _plot_light(const Vector3& p_plot_pos,const AABB& p_plot_aabb, Octant *p_octant, const AABB& p_aabb,const Color& p_light); - void _plot_light_point(const Vector3& p_plot_pos, Octant *p_octant, const AABB& p_aabb,const Color& p_light); - - void _throw_ray(const Vector3& p_from, const Vector3& p_to,const Color& p_light,float *p_att_curve,float p_att_curve_len,int p_bounces); - - - void throw_rays(int p_amount); - float get_normalization() const; - - - void bake(Node *p_base); - - - void clear() { - - if (octree) - _free_octree(octree); - if (bvh) - _free_bvh(bvh); - - if (ray_stack) - memdelete_arr(ray_stack); - if (bvh_stack) - memdelete_arr(bvh_stack); - - octree=NULL; - bvh=NULL; - leaf_list=NULL; - cell_count=0; - ray_stack=NULL; - bvh_stack=NULL; - } - - BakedLightBaker() { - octree_depth=6; - octree=NULL; - bvh=NULL; - leaf_list=NULL; - cell_count=0; - ray_stack=NULL; - bvh_stack=NULL; - plot_size=2; - max_bounces=3; - } - - ~BakedLightBaker() { - - clear(); - } - -}; - - -void BakedLightBaker::_add_mesh(const Ref<Mesh>& p_mesh,const Ref<Material>& p_mat_override,const Transform& p_xform) { - - - for(int i=0;i<p_mesh->get_surface_count();i++) { - - if (p_mesh->surface_get_primitive_type(i)!=Mesh::PRIMITIVE_TRIANGLES) - continue; - Ref<Material> mat = p_mat_override.is_valid()?p_mat_override:p_mesh->surface_get_material(i); - - int facecount=0; - - - if (p_mesh->surface_get_format(i)&Mesh::ARRAY_FORMAT_INDEX) { - - facecount=p_mesh->surface_get_array_index_len(i); - } else { - - facecount=p_mesh->surface_get_array_len(i); - } - - ERR_CONTINUE((facecount==0 || (facecount%3)!=0)); - - facecount/=3; - - int tbase=triangles.size(); - triangles.resize(facecount+tbase); - - - Array a = p_mesh->surface_get_arrays(i); - - DVector<Vector3> vertices = a[Mesh::ARRAY_VERTEX]; - DVector<Vector3>::Read vr=vertices.read(); - - if (p_mesh->surface_get_format(i)&Mesh::ARRAY_FORMAT_INDEX) { - - DVector<int> indices = a[Mesh::ARRAY_INDEX]; - DVector<int>::Read ir = indices.read(); - - for(int i=0;i<facecount;i++) { - Triangle &t=triangles[tbase+i]; - t.vertices[0]=p_xform.xform(vr[ ir[i*3+0] ]); - t.vertices[1]=p_xform.xform(vr[ ir[i*3+1] ]); - t.vertices[2]=p_xform.xform(vr[ ir[i*3+2] ]); - } - - } else { - - for(int i=0;i<facecount;i++) { - Triangle &t=triangles[tbase+i]; - t.vertices[0]=p_xform.xform(vr[ i*3+0 ]); - t.vertices[1]=p_xform.xform(vr[ i*3+1 ]); - t.vertices[2]=p_xform.xform(vr[ i*3+2 ]); - } - } - } - -} - - -void BakedLightBaker::_parse_geometry(Node* p_node) { - - if (p_node->cast_to<MeshInstance>()) { - - MeshInstance *meshi=p_node->cast_to<MeshInstance>(); - Ref<Mesh> mesh=meshi->get_mesh(); - if (mesh.is_valid()) { - _add_mesh(mesh,meshi->get_material_override(),base_inv * meshi->get_global_transform()); - } - } - - if (p_node->cast_to<DirectionalLight>()) { - - DirectionalLight *dl=p_node->cast_to<DirectionalLight>(); - - DirLight dirl; - dirl.diffuse=dl->get_color(DirectionalLight::COLOR_DIFFUSE); - dirl.specular=dl->get_color(DirectionalLight::COLOR_SPECULAR); - dirl.energy=dl->get_parameter(DirectionalLight::PARAM_ENERGY); - dirl.pos=dl->get_global_transform().origin; - dirl.up=dl->get_global_transform().basis.get_axis(1).normalized(); - dirl.left=dl->get_global_transform().basis.get_axis(0).normalized(); - dirl.dir=-dl->get_global_transform().basis.get_axis(2).normalized(); - dirl.rays_thrown=0; - directional_lights.push_back(dirl); - - } - - for(int i=0;i<p_node->get_child_count();i++) { - - _parse_geometry(p_node->get_child(i)); - } -} - - -void BakedLightBaker::_fix_lights() { - - - for(int i=0;i<directional_lights.size();i++) { - - DirLight &dl=directional_lights[i]; - float up_max=-1e10; - float dir_max=-1e10; - float left_max=-1e10; - float up_min=1e10; - float dir_min=1e10; - float left_min=1e10; - - for(int j=0;j<triangles.size();j++) { - - for(int k=0;k<3;k++) { - - Vector3 v = triangles[j].vertices[j]; - - float up_d = dl.up.dot(v); - float dir_d = dl.dir.dot(v); - float left_d = dl.left.dot(v); - - if (up_d>up_max) - up_max=up_d; - if (up_d<up_min) - up_min=up_d; - - if (left_d>left_max) - left_max=left_d; - if (left_d<left_min) - left_min=left_d; - - if (dir_d>dir_max) - dir_max=dir_d; - if (dir_d<dir_min) - dir_min=dir_d; - - } - } - - //make a center point, then the upvector and leftvector - dl.pos = dl.left*( left_max+left_min )*0.5 + dl.up*( up_max+up_min )*0.5 + dl.dir*(dir_min-(dir_max-dir_min)); - dl.left*=(left_max-left_min)*0.5; - dl.up*=(up_max-up_min)*0.5; - dl.length = (dir_max - dir_min)*10; //arbitrary number to keep it in scale - - } -} - -BakedLightBaker::BVH* BakedLightBaker::_parse_bvh(BVH** p_children, int p_size, int p_depth, int &max_depth) { - - if (p_depth>max_depth) { - max_depth=p_depth; - } - - if (p_size==1) { - - return p_children[0]; - } else if (p_size==0) { - - return NULL; - } - - - AABB aabb; - aabb=p_children[0]->aabb; - for(int i=1;i<p_size;i++) { - - aabb.merge_with(p_children[i]->aabb); - } - - int li=aabb.get_longest_axis_index(); - - switch(li) { - - case Vector3::AXIS_X: { - SortArray<BVH*,BVHCmpX> sort_x; - sort_x.nth_element(0,p_size,p_size/2,p_children); - //sort_x.sort(&p_bb[p_from],p_size); - } break; - case Vector3::AXIS_Y: { - SortArray<BVH*,BVHCmpY> sort_y; - sort_y.nth_element(0,p_size,p_size/2,p_children); - //sort_y.sort(&p_bb[p_from],p_size); - } break; - case Vector3::AXIS_Z: { - SortArray<BVH*,BVHCmpZ> sort_z; - sort_z.nth_element(0,p_size,p_size/2,p_children); - //sort_z.sort(&p_bb[p_from],p_size); - - } break; - } - - - BVH* left = _parse_bvh(p_children,p_size/2,p_depth+1,max_depth); - BVH* right = _parse_bvh(&p_children[p_size/2],p_size-p_size/2,p_depth+1,max_depth); - - BVH *_new = memnew(BVH); - _new->aabb=aabb; - _new->center=aabb.pos+aabb.size*0.5; - _new->children[0]=left; - _new->children[1]=right; - _new->leaf=NULL; - - return _new; -} - -void BakedLightBaker::_make_bvh() { - - Vector<BVH*> bases; - bases.resize(triangles.size()); - int max_depth=0; - for(int i=0;i<triangles.size();i++) { - bases[i]=memnew( BVH ); - bases[i]->leaf=&triangles[i]; - bases[i]->aabb.pos=triangles[i].vertices[0]; - bases[i]->aabb.expand_to(triangles[i].vertices[1]); - bases[i]->aabb.expand_to(triangles[i].vertices[2]); - bases[i]->center=bases[i]->aabb.pos+bases[i]->aabb.size*0.5; - } - - bvh=_parse_bvh(bases.ptr(),bases.size(),1,max_depth); - ray_stack = memnew_arr(uint32_t,max_depth); - bvh_stack = memnew_arr(BVH*,max_depth); -} - -void BakedLightBaker::_octree_insert(const AABB& p_aabb,Octant *p_octant,Triangle* p_triangle, int p_depth) { - - if (p_octant->leaf) { -#if 0 - if (p_aabb.has_point(p_triangle->vertices[0]) && p_aabb.has_point(p_triangle->vertices[1]) &&p_aabb.has_point(p_triangle->vertices[2])) { - //face is completely enclosed, add area - p_octant->surface_area+=Face3(p_triangle->vertices[0],p_triangle->vertices[1],p_triangle->vertices[2]).get_area(); - } else { - //not completely enclosed, will need to be clipped.. - Vector<Vector3> poly; - poly.push_back(p_triangle->vertices[0]); - poly.push_back(p_triangle->vertices[1]); - poly.push_back(p_triangle->vertices[2]); - - //clip - for(int i=0;i<3;i++) { - - //top plane - Plane p(0,0,0,0); - p.normal[i]=1.0; - p.d=p_aabb.pos[i]+p_aabb.size[i]; - poly=Geometry::clip_polygon(poly,p); - - //bottom plane - p.normal[i]=-1.0; - p.d=-p_aabb.pos[i]; - poly=Geometry::clip_polygon(poly,p); - } - - - //calculate area - float clipped_area=0; - for(int i=2;i<poly.size();i++) { - clipped_area+=Face3(poly[0],poly[i-1],poly[i]).get_area(); - } - - print_line(itos(poly.size())+" Base: "+rtos(Face3(p_triangle->vertices[0],p_triangle->vertices[1],p_triangle->vertices[2]).get_area())+" clipped: "+rtos(clipped_area)); - p_octant->surface_area+=clipped_area; - } -#endif - } else { - - - for(int i=0;i<8;i++) { - - AABB aabb=p_aabb; - aabb.size*=0.5; - if (i&1) - aabb.pos.x+=aabb.size.x; - if (i&2) - aabb.pos.y+=aabb.size.y; - if (i&4) - aabb.pos.z+=aabb.size.z; - - AABB fit_aabb=aabb; - //fit_aabb=fit_aabb.grow(bvh->aabb.size.x*0.0001); - - if (!Face3(p_triangle->vertices[0],p_triangle->vertices[1],p_triangle->vertices[2]).intersects_aabb(fit_aabb)) - continue; - - if (!p_octant->children[i]) { - p_octant->children[i]=memnew(Octant); - if (p_depth==0) { - p_octant->children[i]->leaf=true; - p_octant->children[i]->light_accum[0]=0; - p_octant->children[i]->light_accum[1]=0; - p_octant->children[i]->light_accum[2]=0; - p_octant->children[i]->offset[0]=aabb.pos.x+aabb.size.x*0.5; - p_octant->children[i]->offset[1]=aabb.pos.y+aabb.size.y*0.5; - p_octant->children[i]->offset[2]=aabb.pos.z+aabb.size.z*0.5; - p_octant->children[i]->surface_area=0; - p_octant->children[i]->next_leaf=leaf_list; - leaf_list=p_octant->children[i]; - cell_count++; - } else { - - p_octant->children[i]->leaf=false; - for(int j=0;j<8;j++) { - p_octant->children[i]->children[j]=0; - } - } - } - - _octree_insert(aabb,p_octant->children[i],p_triangle,p_depth-1); - } - } -} - - -void BakedLightBaker::_make_octree() { - - AABB base = bvh->aabb; - float lal=base.get_longest_axis_size(); - //must be square because we want square blocks - base.size.x=lal; - base.size.y=lal; - base.size.z=lal; - base.grow_by(lal*0.001); //for precision - octree_aabb=base; - - cell_size=base.size.x; - for(int i=0;i<octree_depth;i++) - cell_size/=2.0; - - octree = memnew( Octant ); - octree->leaf=false; - for(int i=0;i<8;i++) - octree->children[i]=NULL; - - for(int i=0;i<triangles.size();i++) { - - _octree_insert(octree_aabb,octree,&triangles[i],octree_depth-1); - } - -} - - -void BakedLightBaker::_plot_light(const Vector3& p_plot_pos,const AABB& p_plot_aabb, Octant *p_octant, const AABB& p_aabb,const Color& p_light) { - - - if (p_octant->leaf) { - - float r=cell_size*plot_size; - Vector3 center=p_aabb.pos+p_aabb.size*0.5; - float d = p_plot_pos.distance_to(center); - if (d>r) - return; //oh crap! outside radius - float intensity = 1.0;// - (d/r)*(d/r); //not gauss but.. - p_octant->light_accum[0]+=p_light.r*intensity; - p_octant->light_accum[1]+=p_light.g*intensity; - p_octant->light_accum[2]+=p_light.b*intensity; - - } else { - - for(int i=0;i<8;i++) { - - if (!p_octant->children[i]) - continue; - - AABB aabb=p_aabb; - aabb.size*=0.5; - if (i&1) - aabb.pos.x+=aabb.size.x; - if (i&2) - aabb.pos.y+=aabb.size.y; - if (i&4) - aabb.pos.z+=aabb.size.z; - - - if (!aabb.intersects(p_plot_aabb)) - continue; - - _plot_light(p_plot_pos,p_plot_aabb,p_octant->children[i],aabb,p_light); - - } - - } -} - -void BakedLightBaker::_plot_light_point(const Vector3& p_plot_pos, Octant *p_octant, const AABB& p_aabb,const Color& p_light) { - - - if (p_octant->leaf) { - - p_octant->light_accum[0]+=p_light.r; - p_octant->light_accum[1]+=p_light.g; - p_octant->light_accum[2]+=p_light.b; - - } else { - - for(int i=0;i<8;i++) { - - if (!p_octant->children[i]) - continue; - - AABB aabb=p_aabb; - aabb.size*=0.5; - if (i&1) - aabb.pos.x+=aabb.size.x; - if (i&2) - aabb.pos.y+=aabb.size.y; - if (i&4) - aabb.pos.z+=aabb.size.z; - - - if (!aabb.has_point(p_plot_pos)) - continue; - - _plot_light_point(p_plot_pos,p_octant->children[i],aabb,p_light); - - } - - } -} - - -void BakedLightBaker::_throw_ray(const Vector3& p_begin, const Vector3& p_end,const Color& p_light,float *p_att_curve,float p_att_curve_len,int p_bounces) { - - - uint32_t* stack = ray_stack; - BVH **bstack = bvh_stack; - - enum { - TEST_AABB_BIT=0, - VISIT_LEFT_BIT=1, - VISIT_RIGHT_BIT=2, - VISIT_DONE_BIT=3, - - - }; - - Vector3 n = (p_end-p_begin).normalized(); - real_t d=1e10; - bool inters=false; - Vector3 r_normal; - Vector3 r_point; - - //for(int i=0;i<max_depth;i++) - // stack[i]=0; - - int level=0; - //AABB ray_aabb; - //ray_aabb.pos=p_begin; - //ray_aabb.expand_to(p_end); - - - const BVH *bvhptr = bvh; - - bstack[0]=bvh; - stack[0]=TEST_AABB_BIT; - - - while(true) { - - uint32_t mode = stack[level]; - const BVH &b = *bstack[level]; - bool done=false; - - switch(mode) { - case TEST_AABB_BIT: { - - if (b.leaf) { - - - Face3 f3(b.leaf->vertices[0],b.leaf->vertices[1],b.leaf->vertices[2]); - - - Vector3 res; - - if (f3.intersects_segment(p_begin,p_end,&res)) { - - - float nd = n.dot(res); - if (nd<d) { - - d=nd; - r_point=res; - r_normal=f3.get_plane().get_normal(); - inters=true; - } - - } - - stack[level]=VISIT_DONE_BIT; - } else { - - - bool valid = b.aabb.intersects_segment(p_begin,p_end); - // bool valid = b.aabb.intersects(ray_aabb); - - if (!valid) { - - stack[level]=VISIT_DONE_BIT; - - } else { - - stack[level]=VISIT_LEFT_BIT; - } - } - - } continue; - case VISIT_LEFT_BIT: { - - stack[level]=VISIT_RIGHT_BIT; - bstack[level+1]=b.children[0]; - stack[level+1]=TEST_AABB_BIT; - level++; - - } continue; - case VISIT_RIGHT_BIT: { - - stack[level]=VISIT_DONE_BIT; - bstack[level+1]=b.children[1]; - stack[level+1]=TEST_AABB_BIT; - level++; - } continue; - case VISIT_DONE_BIT: { - - if (level==0) { - done=true; - break; - } else - level--; - - } continue; - } - - - if (done) - break; - } - - - if (inters) { - - //print_line("collision!"); - if (n.dot(r_normal)>0) - r_normal=-r_normal; - - //ok... - Color diffuse_at_point(0.8,0.8,0.8); - Color specular_at_point(0.8,0.8,0.8); - - AABB aabb; - aabb.pos=r_point; - aabb.pos-=Vector3(1,1,1)*cell_size*plot_size; - aabb.size=Vector3(2,2,2)*cell_size*plot_size; - - _plot_light(r_point,aabb,octree,octree_aabb,p_light); -// _plot_light_point(r_point,octree,octree_aabb,p_light); - - } - -} - - - - - - -float BakedLightBaker::get_normalization() const { - - float nrg=0; - for(int i=0;i<directional_lights.size();i++) { - - const DirLight &dl=directional_lights[i]; - float total_area = dl.left.length()*2*dl.up.length()*2; - float cell_area = cell_size*cell_size;; - nrg+= dl.energy * (dl.rays_thrown * cell_area / total_area); - nrg*=5; - } - - return nrg; -} - -void BakedLightBaker::throw_rays(int p_amount) { - - - - for(int i=0;i<directional_lights.size();i++) { - - DirLight &dl=directional_lights[i]; - - float sr = Math::sqrt(p_amount); - float aspect = dl.up.length()/dl.left.length(); - - - for(int j=0;j<p_amount;j++) { - Vector3 from = dl.pos; - from+=dl.up*(Math::randf()*2.0-1.0); - from+=dl.left*(Math::randf()*2.0-1.0); - Vector3 to = from+dl.dir*dl.length; - Color col=dl.diffuse; - col.r*=dl.energy; - col.g*=dl.energy; - col.b*=dl.energy; - dl.rays_thrown++; - _throw_ray(from,to,col,NULL,0,max_bounces); - } - - - } -} - - - - - - - - - - - - - -void BakedLightBaker::bake(Node* p_node) { - - cell_count=0; - - _parse_geometry(p_node); - _fix_lights(); - _make_bvh(); - _make_octree(); - -} - void BakedLightEditor::_end_baking() { - if (!bake_thread) - return; - - bake_thread_exit=true; - Thread::wait_to_finish(bake_thread); - bake_thread=NULL; - bake_thread_exit=false; + baker->clear(); + set_process(false); + button_bake->set_pressed(false); + bake_info->set_text(""); } void BakedLightEditor::_node_removed(Node *p_node) { @@ -833,71 +21,83 @@ void BakedLightEditor::_node_removed(Node *p_node) { if(p_node==node) { _end_baking(); node=NULL; - p_node->remove_child(preview); - preview->set_mesh(Ref<Mesh>()); + hide(); } } -void BakedLightEditor::_bake_thread_func(void *arg) { - BakedLightEditor *ble = (BakedLightEditor*)arg; - - while(!ble->bake_thread_exit) { - - ble->baker->throw_rays(1000); - } -} +void BakedLightEditor::_notification(int p_option) { -void BakedLightEditor::_notification(int p_option) { + if (p_option==NOTIFICATION_ENTER_SCENE) { + button_bake->set_icon(get_icon("Bake","EditorIcons")); + button_reset->set_icon(get_icon("Reload","EditorIcons")); + } if (p_option==NOTIFICATION_PROCESS) { - if (bake_thread) { + if (baker->is_baking() && !baker->is_paused()) { update_timeout-=get_process_delta_time(); if (update_timeout<0) { + if (baker->get_baked_light()!=node->get_baked_light()) { + _end_baking(); + return; + } + uint64_t t = OS::get_singleton()->get_ticks_msec(); - float norm = baker->get_normalization(); +#ifdef DEBUG_CUBES + double norm = baker->get_normalization(); float max_lum=0; + { DVector<Color>::Write cw=colors.write(); - BakedLightBaker::Octant *oct = baker->leaf_list; + BakedLightBaker::Octant *octants=baker->octant_pool.ptr(); + BakedLightBaker::Octant *oct = &octants[baker->leaf_list]; int vert_idx=0; while(oct) { - Color color; - color.r=oct->light_accum[0]/norm; - color.g=oct->light_accum[1]/norm; - color.b=oct->light_accum[2]/norm; - float lum = color.get_v(); - //if (lum<0.05) - // color.a=0; - if (lum>max_lum) - max_lum=lum; + Color colors[8]; + for(int i=0;i<8;i++) { + colors[i].r=oct->light_accum[i][0]/norm; + colors[i].g=oct->light_accum[i][1]/norm; + colors[i].b=oct->light_accum[i][2]/norm; + + float lum = colors[i].get_v(); + //if (lum<0.05) + // color.a=0; + if (lum>max_lum) + max_lum=lum; + + } + static const int vert2cub[36]={7,3,1,1,5,7,7,6,2,2,3,7,7,5,4,4,6,7,2,6,4,4,0,2,4,5,1,1,0,4,1,3,2,2,0,1}; for (int i=0;i<36;i++) { - cw[vert_idx++]=color; + cw[vert_idx++]=colors[vert2cub[i]]; } - oct=oct->next_leaf; + if (oct->next_leaf) + oct=&octants[oct->next_leaf]; + else + oct=NULL; } } - + print_line("MSCOL: "+itos(OS::get_singleton()->get_ticks_msec()-t)); + t = OS::get_singleton()->get_ticks_msec(); Array a; a.resize(Mesh::ARRAY_MAX); @@ -907,8 +107,28 @@ void BakedLightEditor::_notification(int p_option) { mesh->surface_remove(0); mesh->add_surface(Mesh::PRIMITIVE_TRIANGLES,a); mesh->surface_set_material(0,material); +#endif + ERR_FAIL_COND(node->get_baked_light().is_null()); + + baker->update_octree_image(octree_texture); +#if 0 +//debug + Image img(baker->baked_octree_texture_w,baker->baked_octree_texture_h,0,Image::FORMAT_RGBA,octree_texture); + Ref<ImageTexture> it = memnew( ImageTexture ); + it->create_from_image(img); + ResourceSaver::save("baked_octree.png",it); + + +#endif + bake_info->set_text("rays/s: "+itos(baker->get_rays_sec())); + update_timeout=1; + print_line("MSUPDATE: "+itos(OS::get_singleton()->get_ticks_msec()-t)); + t=OS::get_singleton()->get_ticks_msec(); + node->get_baked_light()->set_octree(octree_texture); + print_line("MSSET: "+itos(OS::get_singleton()->get_ticks_msec()-t)); + + - update_timeout=1; } } } @@ -924,115 +144,73 @@ void BakedLightEditor::_menu_option(int p_option) { case MENU_OPTION_BAKE: { ERR_FAIL_COND(!node); - preview->set_mesh(Ref<Mesh>()); - baker->base_inv=node->get_global_transform().affine_inverse(); - baker->bake(node); - - print_line("CELLS: "+itos(baker->cell_count)); - print_line("cell size: "+rtos(baker->cell_size)); - colors.resize(baker->cell_count*36); - vertices.resize(baker->cell_count*36); - - - { - DVector<Color>::Write cw=colors.write(); - DVector<Vector3>::Write vw=vertices.write(); - BakedLightBaker::Octant *oct = baker->leaf_list; - int vert_idx=0; - - while(oct) { - - Color color; - - for (int i=0;i<6;i++) { + ERR_FAIL_COND(node->get_baked_light().is_null()); + baker->bake(node->get_baked_light(),node); + update_timeout=0; + set_process(true); - Vector3 face_points[4]; - for (int j=0;j<4;j++) { - - float v[3]; - v[0]=1.0; - v[1]=1-2*((j>>1)&1); - v[2]=v[1]*(1-2*(j&1)); - - for (int k=0;k<3;k++) { - if (i<3) - face_points[j][(i+k)%3]=v[k]*(i>=3?-1:1); - else - face_points[3-j][(i+k)%3]=v[k]*(i>=3?-1:1); - } - } + } break; + case MENU_OPTION_CLEAR: { - for(int j=0;j<4;j++) { - face_points[j]*=baker->cell_size*0.5; - face_points[j]+=Vector3(oct->offset[0],oct->offset[1],oct->offset[2]); - } -#define ADD_VTX(m_idx) \ - vw[vert_idx]=face_points[m_idx]; \ - cw[vert_idx]=color; \ - vert_idx++; - //tri 1 - ADD_VTX(0); - ADD_VTX(1); - ADD_VTX(2); - //tri 2 - ADD_VTX(2); - ADD_VTX(3); - ADD_VTX(0); + } break; -#undef ADD_VTX + } +} - } +void BakedLightEditor::_bake_pressed() { - oct=oct->next_leaf; - } + ERR_FAIL_COND(!node); + if (node->get_baked_light().is_null()) { + err_dialog->set_text("BakedLightInstance does not contain a BakedLight resource."); + err_dialog->popup_centered(Size2(350,70)); + button_bake->set_pressed(false); + return; + } + if (baker->is_baking()) { - } + baker->set_pause(!button_bake->is_pressed()); + if (baker->is_paused()) { - Array a; - a.resize(Mesh::ARRAY_MAX); - a[Mesh::ARRAY_VERTEX]=vertices; - a[Mesh::ARRAY_COLOR]=colors; - while(mesh->get_surface_count()) - mesh->surface_remove(0); - mesh->add_surface(Mesh::PRIMITIVE_TRIANGLES,a); - mesh->surface_set_material(0,material); + set_process(false); + bake_info->set_text(""); + } else { - bake_thread_exit=false; update_timeout=0; set_process(true); - bake_thread=Thread::create(_bake_thread_func,this); - preview->set_mesh(mesh); - + } - } break; - case MENU_OPTION_CLEAR: { + } else { + baker->bake(node->get_baked_light(),node); + update_timeout=0; + set_process(true); + } +} +void BakedLightEditor::_clear_pressed(){ - } break; + baker->clear(); + button_bake->set_pressed(false); + bake_info->set_text(""); - } } +void BakedLightEditor::edit(BakedLightInstance *p_baked_light) { -void BakedLightEditor::edit(BakedLight *p_baked_light) { - - if (node==p_baked_light) + if (p_baked_light==NULL || node==p_baked_light) { return; - if (node) { - node->remove_child(preview); } + if (node && node!=p_baked_light) + _end_baking(); - node=p_baked_light; - _end_baking(); - if (node) - node->add_child(preview); + node=p_baked_light; + //_end_baking(); } @@ -1041,35 +219,33 @@ void BakedLightEditor::edit(BakedLight *p_baked_light) { void BakedLightEditor::_bind_methods() { ObjectTypeDB::bind_method("_menu_option",&BakedLightEditor::_menu_option); + ObjectTypeDB::bind_method("_bake_pressed",&BakedLightEditor::_bake_pressed); + ObjectTypeDB::bind_method("_clear_pressed",&BakedLightEditor::_clear_pressed); } BakedLightEditor::BakedLightEditor() { - options = memnew( MenuButton ); - - options->set_text("BakedLight"); - options->get_popup()->add_item("Bake..",MENU_OPTION_BAKE); - options->get_popup()->add_item("Clear",MENU_OPTION_CLEAR); - options->get_popup()->connect("item_pressed", this,"_menu_option"); - + bake_hbox = memnew( HBoxContainer ); + button_bake = memnew( ToolButton ); + button_bake->set_text("Bake!"); + button_bake->set_toggle_mode(true); + button_reset = memnew( Button ); + bake_info = memnew( Label ); + bake_hbox->add_child( button_bake ); + bake_hbox->add_child( button_reset ); + bake_hbox->add_child( bake_info ); err_dialog = memnew( AcceptDialog ); add_child(err_dialog); node=NULL; baker = memnew( BakedLightBaker ); - preview = memnew( MeshInstance ); - bake_thread=NULL; - update_timeout=0; - material = Ref<FixedMaterial> ( memnew( FixedMaterial ) ); - material->set_fixed_flag(FixedMaterial::FLAG_USE_COLOR_ARRAY,true); - material->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA,true); - material->set_flag(FixedMaterial::FLAG_UNSHADED,true); - material->set_flag(FixedMaterial::FLAG_DOUBLE_SIDED,true); - material->set_parameter(FixedMaterial::PARAM_DIFFUSE,Color(1,1,1)); + button_bake->connect("pressed",this,"_bake_pressed"); + button_reset->connect("pressed",this,"_clear_pressed"); + + update_timeout=0; - mesh = Ref<Mesh>( memnew( Mesh )); } @@ -1081,28 +257,24 @@ BakedLightEditor::~BakedLightEditor() { void BakedLightEditorPlugin::edit(Object *p_object) { - baked_light_editor->edit(p_object->cast_to<BakedLight>()); + baked_light_editor->edit(p_object->cast_to<BakedLightInstance>()); } bool BakedLightEditorPlugin::handles(Object *p_object) const { - return p_object->is_type("BakedLight"); + return p_object->is_type("BakedLightInstance"); } void BakedLightEditorPlugin::make_visible(bool p_visible) { if (p_visible) { baked_light_editor->show(); - baked_light_editor->options->show(); + baked_light_editor->bake_hbox->show(); } else { baked_light_editor->hide(); - baked_light_editor->options->show(); + baked_light_editor->bake_hbox->hide(); baked_light_editor->edit(NULL); - if (baked_light_editor->node) { - baked_light_editor->node->remove_child(baked_light_editor->preview); - baked_light_editor->node=NULL; - } } } @@ -1112,9 +284,9 @@ BakedLightEditorPlugin::BakedLightEditorPlugin(EditorNode *p_node) { editor=p_node; baked_light_editor = memnew( BakedLightEditor ); editor->get_viewport()->add_child(baked_light_editor); - add_custom_control(CONTAINER_SPATIAL_EDITOR_MENU,baked_light_editor->options); + add_custom_control(CONTAINER_SPATIAL_EDITOR_MENU,baked_light_editor->bake_hbox); baked_light_editor->hide(); - baked_light_editor->options->hide(); + baked_light_editor->bake_hbox->hide(); } diff --git a/tools/editor/plugins/baked_light_editor_plugin.h b/tools/editor/plugins/baked_light_editor_plugin.h index 9424503a16..4ecc0b458f 100644 --- a/tools/editor/plugins/baked_light_editor_plugin.h +++ b/tools/editor/plugins/baked_light_editor_plugin.h @@ -3,15 +3,17 @@ #include "tools/editor/editor_plugin.h" #include "tools/editor/editor_node.h" -#include "scene/3d/baked_light.h" +#include "tools/editor/plugins/baked_light_baker.h" #include "scene/gui/spin_box.h" + + /** @author Juan Linietsky <reduzio@gmail.com> */ -class BakedLightBaker; + class MeshInstance; class BakedLightEditor : public Control { @@ -20,20 +22,18 @@ class BakedLightEditor : public Control { float update_timeout; - DVector<Color> colors; - DVector<Vector3> vertices; - Ref<Mesh> mesh; - Ref<FixedMaterial> material; - - Thread *bake_thread; - bool bake_thread_exit; + DVector<uint8_t> octree_texture; - MeshInstance *preview; BakedLightBaker *baker; AcceptDialog *err_dialog; - MenuButton * options; - BakedLight *node; + HBoxContainer *bake_hbox; + Button *button_bake; + Button *button_reset; + Label *bake_info; + + + BakedLightInstance *node; enum Menu { @@ -41,7 +41,9 @@ class BakedLightEditor : public Control { MENU_OPTION_CLEAR }; - static void _bake_thread_func(void *arg); + void _bake_pressed(); + void _clear_pressed(); + void _end_baking(); void _menu_option(int); @@ -52,7 +54,7 @@ protected: void _notification(int p_what); public: - void edit(BakedLight *p_baked_light); + void edit(BakedLightInstance *p_baked_light); BakedLightEditor(); ~BakedLightEditor(); }; diff --git a/tools/editor/project_export.cpp b/tools/editor/project_export.cpp index aac3837da9..d757a4c07d 100644 --- a/tools/editor/project_export.cpp +++ b/tools/editor/project_export.cpp @@ -232,6 +232,26 @@ void ProjectExportDialog::_format_toggled() { } +void ProjectExportDialog::_script_edited(Variant v) { + + if (updating_script) + return; + updating_script=true; + EditorNode::get_undo_redo()->create_action("Edit Script Options"); + EditorNode::get_undo_redo()->add_do_method(EditorImportExport::get_singleton(),"script_set_action",script_mode->get_selected()); + EditorNode::get_undo_redo()->add_undo_method(EditorImportExport::get_singleton(),"script_set_action",EditorImportExport::get_singleton()->script_get_action()); + EditorNode::get_undo_redo()->add_do_method(EditorImportExport::get_singleton(),"script_set_encryption_key",script_key->get_text()); + EditorNode::get_undo_redo()->add_undo_method(EditorImportExport::get_singleton(),"script_set_encryption_key",EditorImportExport::get_singleton()->script_get_encryption_key()); + EditorNode::get_undo_redo()->add_do_method(this,"_update_script"); + EditorNode::get_undo_redo()->add_undo_method(this,"_update_script"); + EditorNode::get_undo_redo()->add_do_method(this,"_save_export_cfg"); + EditorNode::get_undo_redo()->add_undo_method(this,"_save_export_cfg"); + EditorNode::get_undo_redo()->commit_action(); + updating_script=false; + + +} + void ProjectExportDialog::_notification(int p_what) { switch(p_what) { @@ -277,10 +297,16 @@ void ProjectExportDialog::_notification(int p_what) { image_action->select(EditorImportExport::get_singleton()->get_export_image_action()); image_quality->set_val(EditorImportExport::get_singleton()->get_export_image_quality()); image_shrink->set_val(EditorImportExport::get_singleton()->get_export_image_shrink()); + _update_script(); + + image_quality->connect("value_changed",this,"_quality_edited"); image_shrink->connect("value_changed",this,"_shrink_edited"); image_action->connect("item_selected",this,"_image_export_edited"); + script_mode->connect("item_selected",this,"_script_edited"); + script_key->connect("text_changed",this,"_script_edited"); + for(int i=0;i<formats.size();i++) { if (EditorImportExport::get_singleton()->get_image_formats().has(formats[i]->get_text(0))) formats[i]->set_checked(0,true); @@ -651,10 +677,15 @@ bool ProjectExportDialog::_update_group_treef(TreeItem *p_parent,EditorFileSyste } void ProjectExportDialog::_update_group_tree() { + if (updating) + return; + group_images->clear(); if (_get_selected_group()=="") return; + + updating=true; print_line("****UGT"); List<String> img_extensions; ImageLoader::get_recognized_extensions(&img_extensions); @@ -677,7 +708,7 @@ void ProjectExportDialog::_update_group_tree() { groupenum+=","+String(E->get()); } - + updating=false; _update_group_treef(NULL,EditorFileSystem::get_singleton()->get_filesystem(),extensions,groupenum,group_index); @@ -690,7 +721,7 @@ void ProjectExportDialog::_group_changed(Variant v) { return; if (_get_selected_group()=="") return; - + updating=true; StringName name = _get_selected_group(); EditorNode::get_undo_redo()->create_action("Change Image Group"); EditorNode::get_undo_redo()->add_do_method(EditorImportExport::get_singleton(),"image_export_group_set_image_action",name,group_image_action->get_selected()); @@ -706,6 +737,7 @@ void ProjectExportDialog::_group_changed(Variant v) { EditorNode::get_undo_redo()->add_do_method(this,"_save_export_cfg"); EditorNode::get_undo_redo()->add_undo_method(this,"_save_export_cfg"); EditorNode::get_undo_redo()->commit_action(); + updating=false; } void ProjectExportDialog::_group_item_edited() { @@ -926,11 +958,11 @@ void ProjectExportDialog::_group_atlas_preview() { int flags=0; - if (Globals::get_singleton()->get("texture_import/filter")) + if (Globals::get_singleton()->get("image_loader/filter")) flags|=EditorTextureImportPlugin::IMAGE_FLAG_FILTER; - if (!Globals::get_singleton()->get("texture_import/gen_mipmaps")) + if (!Globals::get_singleton()->get("image_loader/gen_mipmaps")) flags|=EditorTextureImportPlugin::IMAGE_FLAG_NO_MIPMAPS; - if (!Globals::get_singleton()->get("texture_import/repeat")) + if (!Globals::get_singleton()->get("image_loader/repeat")) flags|=EditorTextureImportPlugin::IMAGE_FLAG_REPEAT; flags|=EditorTextureImportPlugin::IMAGE_FLAG_FIX_BORDER_ALPHA; @@ -956,6 +988,17 @@ void ProjectExportDialog::_group_atlas_preview() { } +void ProjectExportDialog::_update_script() { + + if (updating_script) + return; + updating_script=true; + script_mode->select(EditorImportExport::get_singleton()->script_get_action()); + script_key->set_text(EditorImportExport::get_singleton()->script_get_encryption_key()); + updating_script=false; + +} + void ProjectExportDialog::_image_filter_changed(String) { _update_group_tree(); @@ -991,6 +1034,8 @@ void ProjectExportDialog::_bind_methods() { ObjectTypeDB::bind_method(_MD("_group_atlas_preview"),&ProjectExportDialog::_group_atlas_preview); ObjectTypeDB::bind_method(_MD("_group_select_all"),&ProjectExportDialog::_group_select_all); ObjectTypeDB::bind_method(_MD("_group_select_none"),&ProjectExportDialog::_group_select_none); + ObjectTypeDB::bind_method(_MD("_script_edited"),&ProjectExportDialog::_script_edited); + ObjectTypeDB::bind_method(_MD("_update_script"),&ProjectExportDialog::_update_script); ObjectTypeDB::bind_method(_MD("export_platform"),&ProjectExportDialog::export_platform); @@ -1171,7 +1216,7 @@ ProjectExportDialog::ProjectExportDialog(EditorNode *p_editor) { group_lossy_quality->set_step(0.1); group_lossy_quality->set_val(0.7); group_options->add_margin_child("Lossy Quality:",group_lossy_quality); - group_lossy_quality->connect("value_changed",this,"_group_changed"); + group_lossy_quality->connect("value_changed",this,"_quality_edited"); group_atlas = memnew(CheckButton); group_atlas->set_pressed("Generate Atlas"); @@ -1261,6 +1306,18 @@ ProjectExportDialog::ProjectExportDialog(EditorNode *p_editor) { hbc->add_child(button_reload); */ + script_vbox = memnew( VBoxContainer ); + script_vbox->set_name("Script"); + sections->add_child(script_vbox); + script_mode = memnew( OptionButton ); + script_vbox->add_margin_child("Script Export Mode:",script_mode); + script_mode->add_item("Text"); + script_mode->add_item("Compiled"); + script_mode->add_item("Encrypted (Provide Key Below)"); + script_key = memnew( LineEdit ); + script_vbox->add_margin_child("Script Encryption Key (256-bits as hex):",script_key); + + updating=false; @@ -1302,6 +1359,7 @@ ProjectExportDialog::ProjectExportDialog(EditorNode *p_editor) { add_child(pck_export); button_export = add_button("Export..",!OS::get_singleton()->get_swap_ok_cancel(),"export_pck"); + updating_script=false; } diff --git a/tools/editor/project_export.h b/tools/editor/project_export.h index 6ceffadc62..dfe7a2d900 100644 --- a/tools/editor/project_export.h +++ b/tools/editor/project_export.h @@ -132,6 +132,12 @@ private: TextureFrame *atlas_preview_frame; + VBoxContainer *script_vbox; + OptionButton *script_mode; + LineEdit *script_key; + + + void _export_mode_changed(int p_idx); void _prop_edited(String what); @@ -166,6 +172,9 @@ private: void _group_select_none(); void _group_del(Object *item,int p_column, int p_button); + bool updating_script; + void _update_script(); + void _script_edited(Variant v); void _export_action(const String& p_file); void _export_action_pck(const String& p_file); void ok_pressed(); |