summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--SConstruct1
-rw-r--r--core/SCsub28
-rw-r--r--core/bind/core_bind.cpp4
-rw-r--r--core/image.cpp9
-rw-r--r--core/image.h6
-rw-r--r--core/io/resource_format_xml.cpp9
-rw-r--r--core/io/resource_format_xml.h2
-rw-r--r--core/math/aabb.cpp9
-rw-r--r--core/math/aabb.h61
-rw-r--r--core/math/face3.cpp2
-rw-r--r--core/math/face3.h169
-rw-r--r--core/packed_data_container.cpp20
-rw-r--r--core/packed_data_container.h2
-rw-r--r--core/script_language.cpp2
-rw-r--r--core/script_language.h1
-rw-r--r--core/ustring.cpp113
-rw-r--r--core/variant_op.cpp2
-rw-r--r--demos/3d/platformer/stage2.xml336
-rw-r--r--demos/3d/platformer/tiles.resbin81468 -> 81673 bytes
-rw-r--r--drivers/gles2/rasterizer_gles2.cpp49
-rw-r--r--drivers/gles2/shaders/material.glsl89
-rw-r--r--drivers/unix/ip_unix.cpp2
-rw-r--r--modules/gdscript/gd_script.cpp29
-rw-r--r--modules/gdscript/gd_tokenizer.cpp1
-rw-r--r--modules/gdscript/register_types.cpp78
-rw-r--r--modules/gridmap/grid_map.cpp140
-rw-r--r--modules/gridmap/grid_map.h13
-rw-r--r--platform/javascript/detect.py2
-rw-r--r--scene/3d/baked_light.cpp7
-rw-r--r--scene/3d/baked_light.h15
-rw-r--r--scene/3d/baked_light_instance.cpp65
-rw-r--r--scene/3d/baked_light_instance.h33
-rw-r--r--scene/3d/light.cpp32
-rw-r--r--scene/3d/light.h17
-rw-r--r--scene/3d/sprite_3d.cpp1
-rw-r--r--scene/3d/sprite_3d.h4
-rw-r--r--scene/3d/visual_instance.cpp78
-rw-r--r--scene/3d/visual_instance.h9
-rw-r--r--scene/register_scene_types.cpp5
-rw-r--r--scene/resources/baked_light.cpp308
-rw-r--r--scene/resources/baked_light.h106
-rw-r--r--scene/scene_string_names.cpp4
-rw-r--r--scene/scene_string_names.h3
-rw-r--r--servers/visual/rasterizer.h21
-rw-r--r--servers/visual/visual_server_raster.cpp309
-rw-r--r--servers/visual/visual_server_raster.h57
-rw-r--r--servers/visual/visual_server_wrap_mt.h20
-rw-r--r--servers/visual_server.cpp2
-rw-r--r--servers/visual_server.h29
-rw-r--r--tools/editor/editor_import_export.cpp63
-rw-r--r--tools/editor/editor_import_export.h14
-rw-r--r--tools/editor/icons/icon_bake.pngbin0 -> 419 bytes
-rw-r--r--tools/editor/icons/icon_reload.pngbin371 -> 567 bytes
-rw-r--r--tools/editor/io_plugins/editor_import_collada.cpp1
-rw-r--r--tools/editor/io_plugins/editor_texture_import_plugin.cpp16
-rw-r--r--tools/editor/plugins/baked_light_baker.cpp1765
-rw-r--r--tools/editor/plugins/baked_light_baker.h316
-rw-r--r--tools/editor/plugins/baked_light_editor_plugin.cpp1080
-rw-r--r--tools/editor/plugins/baked_light_editor_plugin.h30
-rw-r--r--tools/editor/project_export.cpp70
-rw-r--r--tools/editor/project_export.h9
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("&gt;","<");
p_str=p_str.replace("&lt;",">");
@@ -205,7 +207,7 @@ void ResourceInteractiveLoaderXML::unquote(String& p_str) {
p_str=p_str.replace("&#"+String::num(i)+";",chr);
}
p_str=p_str.replace("&amp;","&");
-
+*/
//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("&gt;","<");
- str=str.replace("&lt;",">");
- str=str.replace("&apos;","'");
- str=str.replace("&quot;","\"");
- /*
- 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("&amp;","&");
+ 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
index 0ab7c92ef6..e7e810f23f 100644
--- a/demos/3d/platformer/tiles.res
+++ b/demos/3d/platformer/tiles.res
Binary files differ
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
new file mode 100644
index 0000000000..b1b0f941da
--- /dev/null
+++ b/tools/editor/icons/icon_bake.png
Binary files differ
diff --git a/tools/editor/icons/icon_reload.png b/tools/editor/icons/icon_reload.png
index a79cd11546..07f53efb56 100644
--- a/tools/editor/icons/icon_reload.png
+++ b/tools/editor/icons/icon_reload.png
Binary files differ
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();