summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorJuan Linietsky <reduzio@gmail.com>2014-08-14 10:31:38 -0300
committerJuan Linietsky <reduzio@gmail.com>2014-08-14 10:31:38 -0300
commit2ee4ac183babedd679e901b0158f5268556deceb (patch)
treec0b5215b7ab17186835e1919912fa09de7301bfb /tools
parentc3e1d7b7c788530dc69e973352763a90da05d4e1 (diff)
Little Bits
-=-=-=-=-=- -Fixed small bugs all around -Added ability to show/hide entire sections of the spatial (3D) tree -WIP new vehicle (not ready yet) based on Bullet
Diffstat (limited to 'tools')
-rw-r--r--tools/editor/icons/icon_light_map.pngbin0 -> 441 bytes
-rw-r--r--tools/editor/io_plugins/editor_scene_import_plugin.cpp17
-rw-r--r--tools/editor/io_plugins/editor_scene_import_plugin.h1
-rw-r--r--tools/editor/io_plugins/editor_texture_import_plugin.cpp2
-rw-r--r--tools/editor/plugins/baked_light_baker.cpp528
-rw-r--r--tools/editor/plugins/baked_light_baker.h18
-rw-r--r--tools/editor/plugins/baked_light_editor_plugin.cpp36
-rw-r--r--tools/editor/plugins/baked_light_editor_plugin.h3
-rw-r--r--tools/editor/plugins/shader_editor_plugin.cpp4
-rw-r--r--tools/editor/scene_tree_editor.cpp38
-rw-r--r--tools/export/blender25/io_scene_dae/export_dae.py7
11 files changed, 626 insertions, 28 deletions
diff --git a/tools/editor/icons/icon_light_map.png b/tools/editor/icons/icon_light_map.png
new file mode 100644
index 0000000000..96d3f6e11c
--- /dev/null
+++ b/tools/editor/icons/icon_light_map.png
Binary files differ
diff --git a/tools/editor/io_plugins/editor_scene_import_plugin.cpp b/tools/editor/io_plugins/editor_scene_import_plugin.cpp
index 3cc8ffd151..170598291a 100644
--- a/tools/editor/io_plugins/editor_scene_import_plugin.cpp
+++ b/tools/editor/io_plugins/editor_scene_import_plugin.cpp
@@ -407,6 +407,7 @@ void EditorSceneImportDialog::_import(bool p_and_open) {
rim->add_source(EditorImportPlugin::validate_source_path(import_path->get_text()));
rim->set_option("flags",flags);
+ print_line("GET FLAGS: "+itos(texture_options->get_flags()));
rim->set_option("texture_flags",texture_options->get_flags());
rim->set_option("texture_format",texture_options->get_format());
rim->set_option("texture_quality",texture_options->get_quality());
@@ -640,6 +641,7 @@ const EditorSceneImportDialog::FlagInfo EditorSceneImportDialog::scene_flag_name
{EditorSceneImportPlugin::SCENE_FLAG_DETECT_ALPHA,"Materials","Set Alpha in Materials (-alpha)",true},
{EditorSceneImportPlugin::SCENE_FLAG_DETECT_VCOLOR,"Materials","Set Vert. Color in Materials (-vcol)",true},
{EditorSceneImportPlugin::SCENE_FLAG_LINEARIZE_DIFFUSE_TEXTURES,"Actions","SRGB->Linear Of Diffuse Textures",false},
+ {EditorSceneImportPlugin::SCENE_FLAG_SET_LIGHTMAP_TO_UV2_IF_EXISTS,"Actions","Set Material Lightmap to UV2 if Tex2Array Exists",true},
{EditorSceneImportPlugin::SCENE_FLAG_CREATE_COLLISIONS,"Create","Create Collisions (-col},-colonly)",true},
{EditorSceneImportPlugin::SCENE_FLAG_CREATE_PORTALS,"Create","Create Portals (-portal)",true},
{EditorSceneImportPlugin::SCENE_FLAG_CREATE_ROOMS,"Create","Create Rooms (-room)",true},
@@ -1036,7 +1038,7 @@ Node* EditorSceneImportPlugin::_fix_node(Node *p_node,Node *p_root,Map<Ref<Mesh>
}
- if (p_flags&(SCENE_FLAG_DETECT_ALPHA|SCENE_FLAG_DETECT_VCOLOR) && p_node->cast_to<MeshInstance>()) {
+ if (p_flags&(SCENE_FLAG_DETECT_ALPHA|SCENE_FLAG_DETECT_VCOLOR|SCENE_FLAG_SET_LIGHTMAP_TO_UV2_IF_EXISTS) && p_node->cast_to<MeshInstance>()) {
MeshInstance *mi = p_node->cast_to<MeshInstance>();
@@ -1061,6 +1063,10 @@ Node* EditorSceneImportPlugin::_fix_node(Node *p_node,Node *p_root,Map<Ref<Mesh>
mat->set_name(_fixstr(mat->get_name(),"vcol"));
}
+ if (p_flags&SCENE_FLAG_SET_LIGHTMAP_TO_UV2_IF_EXISTS && m->surface_get_format(i)&Mesh::ARRAY_FORMAT_TEX_UV2) {
+ mat->set_flag(Material::FLAG_LIGHTMAP_ON_UV2,true);
+ }
+
}
}
}
@@ -1224,13 +1230,13 @@ Node* EditorSceneImportPlugin::_fix_node(Node *p_node,Node *p_root,Map<Ref<Mesh>
col->set_name("col");
p_node->add_child(col);
-
- StaticBody *sb = col->cast_to<StaticBody>();
+ StaticBody *sb=col->cast_to<StaticBody>();
CollisionShape *colshape = memnew( CollisionShape);
colshape->set_shape(sb->get_shape(0));
colshape->set_name("shape");
- sb->add_child(colshape);
+ col->add_child(colshape);
colshape->set_owner(p_node->get_owner());
+ sb->set_owner(p_node->get_owner());
} else if (p_flags&SCENE_FLAG_CREATE_NAVMESH &&_teststr(name,"navmesh") && p_node->cast_to<MeshInstance>()) {
@@ -1892,8 +1898,7 @@ Error EditorSceneImportPlugin::import2(Node *scene, const String& p_dest_path, c
Ref<ResourceImportMetadata> imd = memnew( ResourceImportMetadata );
print_line("flags: "+itos(image_flags));
uint32_t flags = image_flags;
- if (E->get())
- flags|=EditorTextureImportPlugin::IMAGE_FLAG_CONVERT_TO_LINEAR;
+
imd->set_option("flags",flags);
imd->set_option("format",image_format);
imd->set_option("quality",image_quality);
diff --git a/tools/editor/io_plugins/editor_scene_import_plugin.h b/tools/editor/io_plugins/editor_scene_import_plugin.h
index 114233df80..3b39f0c962 100644
--- a/tools/editor/io_plugins/editor_scene_import_plugin.h
+++ b/tools/editor/io_plugins/editor_scene_import_plugin.h
@@ -131,6 +131,7 @@ public:
SCENE_FLAG_COMPRESS_GEOMETRY=1<<26,
SCENE_FLAG_GENERATE_TANGENT_ARRAYS=1<<27,
SCENE_FLAG_LINEARIZE_DIFFUSE_TEXTURES=1<<28,
+ SCENE_FLAG_SET_LIGHTMAP_TO_UV2_IF_EXISTS=1<<29,
};
diff --git a/tools/editor/io_plugins/editor_texture_import_plugin.cpp b/tools/editor/io_plugins/editor_texture_import_plugin.cpp
index c7593625ff..760651bbfd 100644
--- a/tools/editor/io_plugins/editor_texture_import_plugin.cpp
+++ b/tools/editor/io_plugins/editor_texture_import_plugin.cpp
@@ -725,6 +725,7 @@ Error EditorTextureImportPlugin::import2(const String& p_path, const Ref<Resourc
bool atlas = from->get_option("atlas");
int flags=from->get_option("flags");
+ print_line("GET FLAGS: "+itos(flags));
uint32_t tex_flags=0;
if (flags&EditorTextureImportPlugin::IMAGE_FLAG_REPEAT)
@@ -993,6 +994,7 @@ Error EditorTextureImportPlugin::import2(const String& p_path, const Ref<Resourc
if ((image.get_format()==Image::FORMAT_RGB || image.get_format()==Image::FORMAT_RGBA) && flags&IMAGE_FLAG_CONVERT_TO_LINEAR) {
+ print_line("CONVERT BECAUSE: "+itos(flags));
image.srgb_to_linear();
}
diff --git a/tools/editor/plugins/baked_light_baker.cpp b/tools/editor/plugins/baked_light_baker.cpp
index 2be6d3da24..1574ce81d7 100644
--- a/tools/editor/plugins/baked_light_baker.cpp
+++ b/tools/editor/plugins/baked_light_baker.cpp
@@ -45,7 +45,7 @@ BakedLightBaker::MeshTexture* BakedLightBaker::_get_mat_tex(const Ref<Texture>&
}
-void BakedLightBaker::_add_mesh(const Ref<Mesh>& p_mesh,const Ref<Material>& p_mat_override,const Transform& p_xform) {
+void BakedLightBaker::_add_mesh(const Ref<Mesh>& p_mesh,const Ref<Material>& p_mat_override,const Transform& p_xform,int p_baked_texture) {
for(int i=0;i<p_mesh->get_surface_count();i++) {
@@ -55,6 +55,7 @@ void BakedLightBaker::_add_mesh(const Ref<Mesh>& p_mesh,const Ref<Material>& p_m
Ref<Material> mat = p_mat_override.is_valid()?p_mat_override:p_mesh->surface_get_material(i);
MeshMaterial *matptr=NULL;
+ int baked_tex=p_baked_texture;
if (mat.is_valid()) {
@@ -112,6 +113,8 @@ void BakedLightBaker::_add_mesh(const Ref<Mesh>& p_mesh,const Ref<Material>& p_m
DVector<Vector3>::Read vr=vertices.read();
DVector<Vector2> uv;
DVector<Vector2>::Read uvr;
+ DVector<Vector2> uv2;
+ DVector<Vector2>::Read uv2r;
DVector<Vector3> normal;
DVector<Vector3>::Read normalr;
bool read_uv=false;
@@ -122,6 +125,18 @@ void BakedLightBaker::_add_mesh(const Ref<Mesh>& p_mesh,const Ref<Material>& p_m
uv=a[Mesh::ARRAY_TEX_UV];
uvr=uv.read();
read_uv=true;
+
+ if (mat.is_valid() && mat->get_flag(Material::FLAG_LIGHTMAP_ON_UV2) && p_mesh->surface_get_format(i)&Mesh::ARRAY_FORMAT_TEX_UV2) {
+
+ uv2=a[Mesh::ARRAY_TEX_UV2];
+ uv2r=uv2.read();
+
+ } else {
+ uv2r=uv.read();
+ if (baked_light->get_transfer_lightmaps_only_to_uv2()) {
+ baked_tex=-1;
+ }
+ }
}
if (p_mesh->surface_get_format(i)&Mesh::ARRAY_FORMAT_NORMAL) {
@@ -145,11 +160,16 @@ void BakedLightBaker::_add_mesh(const Ref<Mesh>& p_mesh,const Ref<Material>& p_m
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;
+ t.baked_texture=baked_tex;
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] ];
+
+ t.bake_uvs[0]=uv2r[ ir[i*3+0] ];
+ t.bake_uvs[1]=uv2r[ ir[i*3+1] ];
+ t.bake_uvs[2]=uv2r[ ir[i*3+2] ];
}
if (read_normal) {
@@ -167,11 +187,17 @@ void BakedLightBaker::_add_mesh(const Ref<Mesh>& p_mesh,const Ref<Material>& p_m
t.vertices[1]=p_xform.xform(vr[ i*3+1 ]);
t.vertices[2]=p_xform.xform(vr[ i*3+2 ]);
t.material=matptr;
+ t.baked_texture=baked_tex;
if (read_uv) {
t.uvs[0]=uvr[ i*3+0 ];
t.uvs[1]=uvr[ i*3+1 ];
t.uvs[2]=uvr[ i*3+2 ];
+
+ t.bake_uvs[0]=uv2r[ i*3+0 ];
+ t.bake_uvs[1]=uv2r[ i*3+1 ];
+ t.bake_uvs[2]=uv2r[ i*3+2 ];
+
}
if (read_normal) {
@@ -193,7 +219,7 @@ void BakedLightBaker::_parse_geometry(Node* p_node) {
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());
+ _add_mesh(mesh,meshi->get_material_override(),base_inv * meshi->get_global_transform(),meshi->get_baked_light_texture_id());
}
} else if (p_node->cast_to<Light>()) {
@@ -214,9 +240,11 @@ void BakedLightBaker::_parse_geometry(Node* p_node) {
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.darkening=dl->get_parameter(DirectionalLight::PARAM_SHADOW_DARKENING);
dirl.radius=dl->get_parameter(DirectionalLight::PARAM_RADIUS);
dirl.bake_direct=dl->get_bake_mode()==Light::BAKE_MODE_FULL;
dirl.rays_thrown=0;
+ dirl.bake_shadow=dl->get_bake_mode()==Light::BAKE_MODE_INDIRECT_AND_SHADOWS;
lights.push_back(dirl);
}
@@ -720,7 +748,7 @@ void BakedLightBaker::_plot_light(int p_light_index, const Vector3& p_plot_pos,
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);
+ //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;
@@ -1310,7 +1338,7 @@ double BakedLightBaker::get_normalization(int p_light_idx) const {
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;
}
@@ -1460,6 +1488,13 @@ void BakedLightBaker::bake(const Ref<BakedLight> &p_light, Node* p_node) {
normal_damp=baked_light->get_normal_damp();
octree_extra_margin=baked_light->get_cell_extra_margin();
+ baked_textures.clear();
+ for(int i=0;i<baked_light->get_lightmaps_count();i++) {
+ BakeTexture bt;
+ bt.width=baked_light->get_lightmap_gen_size(i).x;
+ bt.height=baked_light->get_lightmap_gen_size(i).y;
+ baked_textures.push_back(bt);
+ }
ep.step("Parsing Geometry",0);
@@ -1690,6 +1725,484 @@ void BakedLightBaker::_stop_thread() {
thread=NULL;
}
+void BakedLightBaker::_plot_pixel_to_lightmap(int x, int y, int width, int height, uint8_t *image, const Vector3& p_pos,const Vector3& p_normal,double *p_norm_ptr,float mult,float gamma) {
+
+
+ uint8_t *ptr = &image[(y*width+x)*4];
+ int lc = lights.size();
+
+
+ Color color;
+
+ Octant *octants=octant_pool.ptr();
+
+
+ int octant_idx=0;
+
+
+ while(true) {
+
+ Octant &octant=octants[octant_idx];
+
+ if (octant.leaf) {
+
+ Vector3 lpos = p_pos-octant.aabb.pos;
+ lpos/=octant.aabb.size;
+
+ Vector3 cols[8];
+
+ for(int i=0;i<8;i++) {
+
+ for(int j=0;j<lc;j++) {
+ cols[i].x+=octant.light[j].accum[i][0]*p_norm_ptr[j];
+ cols[i].y+=octant.light[j].accum[i][1]*p_norm_ptr[j];
+ cols[i].z+=octant.light[j].accum[i][2]*p_norm_ptr[j];
+ }
+ }
+
+
+ /*Vector3 final = (cols[0] + (cols[1] - cols[0]) * lpos.y);
+ final = final + ((cols[2] + (cols[3] - cols[2]) * lpos.y) - final)*lpos.x;
+
+ Vector3 final2 = (cols[4+0] + (cols[4+1] - cols[4+0]) * lpos.y);
+ final2 = final2 + ((cols[4+2] + (cols[4+3] - cols[4+2]) * lpos.y) - final2)*lpos.x;*/
+
+ Vector3 finala = cols[0].linear_interpolate(cols[1],lpos.x);
+ Vector3 finalb = cols[2].linear_interpolate(cols[3],lpos.x);
+ Vector3 final = finala.linear_interpolate(finalb,lpos.y);
+
+ Vector3 final2a = cols[4+0].linear_interpolate(cols[4+1],lpos.x);
+ Vector3 final2b = cols[4+2].linear_interpolate(cols[4+3],lpos.x);
+ Vector3 final2 = final2a.linear_interpolate(final2b,lpos.y);
+
+ final = final.linear_interpolate(final2,lpos.z);
+ if (baked_light->get_format()==BakedLight::FORMAT_HDR8)
+ final*=8.0;
+
+
+ color.r=pow(final.x*mult,gamma);
+ color.g=pow(final.y*mult,gamma);
+ color.b=pow(final.z*mult,gamma);
+ color.a=1.0;
+
+ int lc = lights.size();
+ LightData *lv = lights.ptr();
+ for(int i=0;i<lc;i++) {
+ //shadow baking
+ if (!lv[i].bake_shadow)
+ continue;
+ Vector3 from = p_pos+p_normal*0.01;
+ Vector3 to;
+ float att=0;
+ switch(lv[i].type) {
+ case VS::LIGHT_DIRECTIONAL: {
+ to=from-lv[i].dir*lv[i].length;
+ } break;
+ case VS::LIGHT_OMNI: {
+ to=lv[i].pos;
+ float d = MIN(lv[i].radius,to.distance_to(from))/lv[i].radius;
+ att=d;//1.0-d;
+ } break;
+ default: continue;
+ }
+
+ uint32_t* stack = ray_stack;
+ BVH **bstack = bvh_stack;
+
+ enum {
+ TEST_RAY_BIT=0,
+ VISIT_LEFT_BIT=1,
+ VISIT_RIGHT_BIT=2,
+ VISIT_DONE_BIT=3,
+
+
+ };
+
+ bool intersected=false;
+
+ int level=0;
+
+ Vector3 n = (to-from);
+ float len=n.length();
+ if (len==0)
+ continue;
+ n/=len;
+
+ const BVH *bvhptr = bvh;
+
+ bstack[0]=bvh;
+ stack[0]=TEST_RAY_BIT;
+
+
+ while(!intersected) {
+
+ uint32_t mode = stack[level];
+ const BVH &b = *bstack[level];
+ bool done=false;
+
+ switch(mode) {
+ case TEST_RAY_BIT: {
+
+ if (b.leaf) {
+
+
+ Face3 f3(b.leaf->vertices[0],b.leaf->vertices[1],b.leaf->vertices[2]);
+
+
+ Vector3 res;
+
+ if (f3.intersects_segment(from,to)) {
+ intersected=true;
+ done=true;
+ }
+
+ stack[level]=VISIT_DONE_BIT;
+ } else {
+
+
+ bool valid = b.aabb.smits_intersect_ray(from,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_RAY_BIT;
+ level++;
+
+ } continue;
+ case VISIT_RIGHT_BIT: {
+
+ stack[level]=VISIT_DONE_BIT;
+ bstack[level+1]=b.children[1];
+ stack[level+1]=TEST_RAY_BIT;
+ level++;
+ } continue;
+ case VISIT_DONE_BIT: {
+
+ if (level==0) {
+ done=true;
+ break;
+ } else
+ level--;
+
+ } continue;
+ }
+
+
+ if (done)
+ break;
+ }
+
+
+
+ if (intersected) {
+
+ color.a=Math::lerp(MAX(0.01,lv[i].darkening),1.0,att);
+ }
+
+ }
+
+ break;
+ } else {
+
+ Vector3 lpos = p_pos - octant.aabb.pos;
+ Vector3 half = octant.aabb.size * 0.5;
+
+ int ofs=0;
+
+ if (lpos.x >= half.x)
+ ofs|=1;
+ if (lpos.y >= half.y)
+ ofs|=2;
+ if (lpos.z >= half.z)
+ ofs|=4;
+
+ octant_idx = octant.children[ofs];
+
+ if (octant_idx==0)
+ return;
+
+ }
+ }
+
+ ptr[0]=CLAMP(color.r*255.0,0,255);
+ ptr[1]=CLAMP(color.g*255.0,0,255);
+ ptr[2]=CLAMP(color.b*255.0,0,255);
+ ptr[3]=CLAMP(color.a*255.0,0,255);
+
+}
+
+
+Error BakedLightBaker::transfer_to_lightmaps() {
+
+ if (!triangles.size() || baked_textures.size()==0)
+ return ERR_UNCONFIGURED;
+
+ EditorProgress ep("transfer_to_lightmaps","Transfer to Lightmaps:",baked_textures.size()*2+triangles.size());
+
+ for(int i=0;i<baked_textures.size();i++) {
+
+ ERR_FAIL_COND_V( baked_textures[i].width<=0 || baked_textures[i].height<=0,ERR_UNCONFIGURED );
+
+ baked_textures[i].data.resize( baked_textures[i].width*baked_textures[i].height*4 );
+ zeromem(baked_textures[i].data.ptr(),baked_textures[i].data.size());
+ ep.step("Allocating Texture #"+itos(i+1),i);
+ }
+
+ 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);
+ }
+ float gamma = baked_light->get_gamma_adjust();
+ float mult = baked_light->get_energy_multiplier();
+
+
+ const double *normptr=norm_arr.ptr();
+ for(int i=0;i<triangles.size();i++) {
+
+ if (i%200==0) {
+ ep.step("Baking Triangle #"+itos(i),i+baked_textures.size());
+ }
+ Triangle &t=triangles[i];
+ if (t.baked_texture<0 || t.baked_texture>=baked_textures.size())
+ continue;
+
+ BakeTexture &bt=baked_textures[t.baked_texture];
+ Vector3 normal = Plane(t.vertices[0],t.vertices[1],t.vertices[2]).normal;
+
+
+ int x[3];
+ int y[3];
+
+ Vector3 vertices[3]={
+ t.vertices[0],
+ t.vertices[1],
+ t.vertices[2]
+ };
+
+ for(int j=0;j<3;j++) {
+
+ x[j]=t.bake_uvs[j].x*bt.width;
+ y[j]=t.bake_uvs[j].y*bt.height;
+ x[j]=CLAMP(x[j],0,bt.width-1);
+ y[j]=CLAMP(y[j],0,bt.height-1);
+ }
+
+
+ {
+
+ // sort the points vertically
+ if (y[1] > y[2]) {
+ SWAP(x[1], x[2]);
+ SWAP(y[1], y[2]);
+ SWAP(vertices[1],vertices[2]);
+ }
+ if (y[0] > y[1]) {
+ SWAP(x[0], x[1]);
+ SWAP(y[0], y[1]);
+ SWAP(vertices[0],vertices[1]);
+ }
+ if (y[1] > y[2]) {
+ SWAP(x[1], x[2]);
+ SWAP(y[1], y[2]);
+ SWAP(vertices[1],vertices[2]);
+ }
+
+ double dx_far = double(x[2] - x[0]) / (y[2] - y[0] + 1);
+ double dx_upper = double(x[1] - x[0]) / (y[1] - y[0] + 1);
+ double dx_low = double(x[2] - x[1]) / (y[2] - y[1] + 1);
+ double xf = x[0];
+ double xt = x[0] + dx_upper; // if y[0] == y[1], special case
+ for (int yi = y[0]; yi <= (y[2] > bt.height-1 ? bt.height-1 : y[2]); yi++)
+ {
+ if (yi >= 0) {
+ for (int xi = (xf > 0 ? int(xf) : 0); xi <= (xt < bt.width ? xt : bt.width-1) ; xi++) {
+ //pixels[int(x + y * width)] = color;
+
+ Vector2 v0 = Vector2(x[1]-x[0],y[1]-y[0]);
+ Vector2 v1 = Vector2(x[2]-x[0],y[2]-y[0]);
+ //vertices[2] - vertices[0];
+ Vector2 v2 = Vector2(xi-x[0],yi-y[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);
+ Vector3 pos;
+ if (denom==0) {
+ pos=t.vertices[0];
+ } else {
+ float v = (d11 * d20 - d01 * d21) / denom;
+ float w = (d00 * d21 - d01 * d20) / denom;
+ float u = 1.0f - v - w;
+ pos = vertices[0]*u + vertices[1]*v + vertices[2]*w;
+ }
+ _plot_pixel_to_lightmap(xi,yi,bt.width,bt.height,bt.data.ptr(),pos,normal,norm_arr.ptr(),mult,gamma);
+
+ }
+
+ for (int xi = (xf < bt.width ? int(xf) : bt.width-1); xi >= (xt > 0 ? xt : 0); xi--) {
+ //pixels[int(x + y * width)] = color;
+ Vector2 v0 = Vector2(x[1]-x[0],y[1]-y[0]);
+ Vector2 v1 = Vector2(x[2]-x[0],y[2]-y[0]);
+ //vertices[2] - vertices[0];
+ Vector2 v2 = Vector2(xi-x[0],yi-y[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);
+ Vector3 pos;
+ if (denom==0) {
+ pos=t.vertices[0];
+ } else {
+ float v = (d11 * d20 - d01 * d21) / denom;
+ float w = (d00 * d21 - d01 * d20) / denom;
+ float u = 1.0f - v - w;
+ pos = vertices[0]*u + vertices[1]*v + vertices[2]*w;
+ }
+
+ _plot_pixel_to_lightmap(xi,yi,bt.width,bt.height,bt.data.ptr(),pos,normal,norm_arr.ptr(),mult,gamma);
+
+ }
+ }
+ xf += dx_far;
+ if (yi < y[1])
+ xt += dx_upper;
+ else
+ xt += dx_low;
+ }
+ }
+
+ }
+
+
+ for(int i=0;i<baked_textures.size();i++) {
+
+
+ {
+
+ ep.step("Post-Processing Texture #"+itos(i),i+baked_textures.size()+triangles.size());
+
+ BakeTexture &bt=baked_textures[i];
+
+ Vector<uint8_t> copy_data=bt.data;
+ uint8_t *data=bt.data.ptr();
+ uint8_t *src_data=copy_data.ptr();
+ const int max_radius=8;
+ const int shadow_radius=2;
+ const int max_dist=0x7FFFFFFF;
+
+ for(int x=0;x<bt.width;x++) {
+
+ for(int y=0;y<bt.height;y++) {
+
+
+ uint8_t a = copy_data[(y*bt.width+x)*4+3];
+
+ if (a>0) {
+ //blur shadow
+
+ int from_x = MAX(0,x-shadow_radius);
+ int to_x = MIN(bt.width-1,x+shadow_radius);
+ int from_y = MAX(0,y-shadow_radius);
+ int to_y = MIN(bt.height-1,y+shadow_radius);
+
+ int sum=0;
+ int sumc=0;
+
+ for(int k=from_y;k<=to_y;k++) {
+ for(int l=from_x;l<=to_x;l++) {
+
+ const uint8_t * rp = &copy_data[(k*bt.width+l)<<2];
+
+ sum+=rp[3];
+ sumc++;
+ }
+ }
+
+ sum/=sumc;
+ data[(y*bt.width+x)*4+3]=sum;
+
+ } else {
+
+ int closest_dist=max_dist;
+ uint8_t closest_color[4];
+
+ int from_x = MAX(0,x-max_radius);
+ int to_x = MIN(bt.width-1,x+max_radius);
+ int from_y = MAX(0,y-max_radius);
+ int to_y = MIN(bt.height-1,y+max_radius);
+
+ for(int k=from_y;k<=to_y;k++) {
+ for(int l=from_x;l<=to_x;l++) {
+
+ int dy = y-k;
+ int dx = x-l;
+ int dist = dy*dy+dx*dx;
+ if (dist>=closest_dist)
+ continue;
+
+ const uint8_t * rp = &copy_data[(k*bt.width+l)<<2];
+
+ if (rp[3]==0)
+ continue;
+
+ closest_dist=dist;
+ closest_color[0]=rp[0];
+ closest_color[1]=rp[1];
+ closest_color[2]=rp[2];
+ closest_color[3]=rp[3];
+ }
+ }
+
+
+ if (closest_dist!=max_dist) {
+
+ data[(y*bt.width+x)*4+0]=closest_color[0];
+ data[(y*bt.width+x)*4+1]=closest_color[1];
+ data[(y*bt.width+x)*4+2]=closest_color[2];
+ data[(y*bt.width+x)*4+3]=closest_color[3];
+ }
+ }
+ }
+ }
+ }
+
+ DVector<uint8_t> dv;
+ dv.resize(baked_textures[i].data.size());
+ {
+ DVector<uint8_t>::Write w = dv.write();
+ copymem(w.ptr(),baked_textures[i].data.ptr(),baked_textures[i].data.size());
+ }
+
+ Image img(baked_textures[i].width,baked_textures[i].height,0,Image::FORMAT_RGBA,dv);
+ Ref<ImageTexture> tex = memnew( ImageTexture );
+ tex->create_from_image(img);
+ baked_light->set_lightmap_texture(i,tex);
+ }
+
+
+ return OK;
+}
+
void BakedLightBaker::clear() {
@@ -1711,7 +2224,14 @@ void BakedLightBaker::clear() {
for(int i=0;i<octant_pool.size();i++) {
if (octant_pool[i].leaf) {
memdelete_arr( octant_pool[i].light );
+ } 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();
}
octant_pool.clear();
octant_pool_size=0;
diff --git a/tools/editor/plugins/baked_light_baker.h b/tools/editor/plugins/baked_light_baker.h
index 99c8211eed..722255a565 100644
--- a/tools/editor/plugins/baked_light_baker.h
+++ b/tools/editor/plugins/baked_light_baker.h
@@ -94,11 +94,13 @@ public:
struct Triangle {
- AABB aabb;
+ AABB aabb;
Vector3 vertices[3];
Vector2 uvs[3];
+ Vector2 bake_uvs[3];
Vector3 normals[3];
MeshMaterial *material;
+ int baked_texture;
_FORCE_INLINE_ Vector2 get_uv(const Vector3& p_pos) {
@@ -180,6 +182,12 @@ public:
}
};
+ struct BakeTexture {
+
+ Vector<uint8_t> data;
+ int width,height;
+ };
+
struct LightData {
@@ -194,10 +202,12 @@ public:
float energy;
float length;
int rays_thrown;
+ bool bake_shadow;
float radius;
float attenuation;
float spot_angle;
+ float darkening;
float spot_attenuation;
float area;
@@ -220,6 +230,7 @@ public:
int octant_pool_size;
BVH*bvh;
Vector<Triangle> triangles;
+ Vector<BakeTexture> baked_textures;
Transform base_inv;
int leaf_list;
int octree_depth;
@@ -255,13 +266,14 @@ public:
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 _add_mesh(const Ref<Mesh>& p_mesh,const Ref<Material>& p_mat_override,const Transform& p_xform,int p_baked_texture=-1);
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);
+ _FORCE_INLINE_ void _plot_pixel_to_lightmap(int x, int y, int width, int height, uint8_t *image, const Vector3& p_pos,const Vector3& p_normal,double *p_norm_ptr,float mult,float gamma);
void _free_bvh(BVH* p_bvh);
@@ -302,6 +314,8 @@ public:
bool is_paused();
int get_rays_sec() { return rays_sec; }
+ Error transfer_to_lightmaps();
+
void update_octree_image(DVector<uint8_t> &p_image);
Ref<BakedLight> get_baked_light() { return baked_light; }
diff --git a/tools/editor/plugins/baked_light_editor_plugin.cpp b/tools/editor/plugins/baked_light_editor_plugin.cpp
index a1383f22fe..3d48f2e732 100644
--- a/tools/editor/plugins/baked_light_editor_plugin.cpp
+++ b/tools/editor/plugins/baked_light_editor_plugin.cpp
@@ -38,6 +38,7 @@ void BakedLightEditor::_notification(int p_option) {
button_bake->set_icon(get_icon("Bake","EditorIcons"));
button_reset->set_icon(get_icon("Reload","EditorIcons"));
+ button_make_lightmaps->set_icon(get_icon("LightMap","EditorIcons"));
}
if (p_option==NOTIFICATION_PROCESS) {
@@ -148,7 +149,7 @@ void BakedLightEditor::_menu_option(int p_option) {
ERR_FAIL_COND(!node);
ERR_FAIL_COND(node->get_baked_light().is_null());
baker->bake(node->get_baked_light(),node);
-
+ node->get_baked_light()->set_mode(BakedLight::MODE_OCTREE);
update_timeout=0;
set_process(true);
@@ -180,14 +181,19 @@ void BakedLightEditor::_bake_pressed() {
set_process(false);
bake_info->set_text("");
+ button_reset->show();
+ button_make_lightmaps->show();
+
} else {
update_timeout=0;
set_process(true);
+ button_make_lightmaps->hide();
+ button_reset->hide();
}
-
} else {
baker->bake(node->get_baked_light(),node);
+ node->get_baked_light()->set_mode(BakedLight::MODE_OCTREE);
update_timeout=0;
set_process(true);
}
@@ -216,13 +222,27 @@ void BakedLightEditor::edit(BakedLightInstance *p_baked_light) {
}
+void BakedLightEditor::_bake_lightmaps() {
+
+ Error err = baker->transfer_to_lightmaps();
+ if (err) {
+
+ err_dialog->set_text("Error baking to lightmaps!\nMake sure that a bake has just\n happened and that lightmaps are\n configured. ");
+ err_dialog->popup_centered(Size2(350,70));
+ return;
+ }
+ node->get_baked_light()->set_mode(BakedLight::MODE_LIGHTMAPS);
+
+
+}
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);
+ ObjectTypeDB::bind_method("_bake_lightmaps",&BakedLightEditor::_bake_lightmaps);
}
BakedLightEditor::BakedLightEditor() {
@@ -233,6 +253,11 @@ BakedLightEditor::BakedLightEditor() {
button_bake->set_text("Bake!");
button_bake->set_toggle_mode(true);
button_reset = memnew( Button );
+ button_make_lightmaps = memnew( Button );
+ button_bake->set_tooltip("Start/Unpause the baking process.\nThis bakes lighting into the lightmap octree.");
+ button_make_lightmaps ->set_tooltip("Convert the lightmap octree to lightmap textures\n(must have set up UV/Lightmaps properly before!).");
+
+
bake_info = memnew( Label );
bake_hbox->add_child( button_bake );
bake_hbox->add_child( button_reset );
@@ -243,8 +268,15 @@ BakedLightEditor::BakedLightEditor() {
node=NULL;
baker = memnew( BakedLightBaker );
+ bake_hbox->add_child(button_make_lightmaps);
+ button_make_lightmaps->hide();
+
button_bake->connect("pressed",this,"_bake_pressed");
button_reset->connect("pressed",this,"_clear_pressed");
+ button_make_lightmaps->connect("pressed",this,"_bake_lightmaps");
+ button_reset->hide();
+ button_reset->set_tooltip("Reset the lightmap octree baking process (start over).");
+
update_timeout=0;
diff --git a/tools/editor/plugins/baked_light_editor_plugin.h b/tools/editor/plugins/baked_light_editor_plugin.h
index 4ecc0b458f..7912bd92e5 100644
--- a/tools/editor/plugins/baked_light_editor_plugin.h
+++ b/tools/editor/plugins/baked_light_editor_plugin.h
@@ -30,6 +30,7 @@ class BakedLightEditor : public Control {
HBoxContainer *bake_hbox;
Button *button_bake;
Button *button_reset;
+ Button *button_make_lightmaps;
Label *bake_info;
@@ -41,6 +42,8 @@ class BakedLightEditor : public Control {
MENU_OPTION_CLEAR
};
+ void _bake_lightmaps();
+
void _bake_pressed();
void _clear_pressed();
diff --git a/tools/editor/plugins/shader_editor_plugin.cpp b/tools/editor/plugins/shader_editor_plugin.cpp
index 73b6265819..17c4291378 100644
--- a/tools/editor/plugins/shader_editor_plugin.cpp
+++ b/tools/editor/plugins/shader_editor_plugin.cpp
@@ -436,8 +436,10 @@ void ShaderEditor::save_external_data() {
void ShaderEditor::apply_shaders() {
- if (shader.is_valid())
+ if (shader.is_valid()) {
shader->set_code(vertex_editor->get_text_edit()->get_text(),fragment_editor->get_text_edit()->get_text(),light_editor->get_text_edit()->get_text(),0,0);
+ shader->set_edited(true);
+ }
}
void ShaderEditor::_close_callback() {
diff --git a/tools/editor/scene_tree_editor.cpp b/tools/editor/scene_tree_editor.cpp
index 4d0ed3e1dd..e0202be84e 100644
--- a/tools/editor/scene_tree_editor.cpp
+++ b/tools/editor/scene_tree_editor.cpp
@@ -66,11 +66,19 @@ void SceneTreeEditor::_cell_button_pressed(Object *p_item,int p_column,int p_id)
} else if (p_id==BUTTON_VISIBILITY) {
- if (n->is_type("GeometryInstance")) {
- bool v = n->call("get_flag",VS::INSTANCE_FLAG_VISIBLE);
- undo_redo->create_action("Toggle Geometry Visible");
- undo_redo->add_do_method(n,"set_flag",VS::INSTANCE_FLAG_VISIBLE,!v);
- undo_redo->add_undo_method(n,"set_flag",VS::INSTANCE_FLAG_VISIBLE,v);
+ if (n->is_type("Spatial")) {
+
+ Spatial *ci = n->cast_to<Spatial>();
+ if (!ci->is_visible() && ci->get_parent_spatial() && !ci->get_parent_spatial()->is_visible()) {
+ error->set_text("This item cannot be made visible because the parent is hidden. Unhide the parent first.");
+ error->popup_centered_minsize(Size2(400,80));
+ return;
+ }
+
+ bool v = !bool(n->call("is_hidden"));
+ undo_redo->create_action("Toggle Spatial Visible");
+ undo_redo->add_do_method(n,"_set_visible_",!v);
+ undo_redo->add_undo_method(n,"_set_visible_",v);
undo_redo->commit_action();
} else if (n->is_type("CanvasItem")) {
@@ -189,9 +197,9 @@ void SceneTreeEditor::_add_nodes(Node *p_node,TreeItem *p_parent) {
if (!p_node->is_connected("visibility_changed",this,"_node_visibility_changed"))
p_node->connect("visibility_changed",this,"_node_visibility_changed",varray(p_node));
- } else if (p_node->is_type("GeometryInstance")) {
+ } else if (p_node->is_type("Spatial")) {
- bool h = !p_node->call("get_flag",VS::INSTANCE_FLAG_VISIBLE);
+ bool h = p_node->call("is_hidden");
if (h)
item->add_button(0,get_icon("Hidden","EditorIcons"),BUTTON_VISIBILITY);
else
@@ -226,7 +234,16 @@ void SceneTreeEditor::_add_nodes(Node *p_node,TreeItem *p_parent) {
void SceneTreeEditor::_node_visibility_changed(Node *p_node) {
+
+ if (p_node!=get_scene_node() && !p_node->get_owner()) {
+
+ return;
+ }
TreeItem* item=p_node?_find(tree->get_root(),p_node->get_path()):NULL;
+ if (!item) {
+
+ return;
+ }
int idx=item->get_button_by_id(0,BUTTON_VISIBILITY);
ERR_FAIL_COND(idx==-1);
@@ -234,11 +251,10 @@ void SceneTreeEditor::_node_visibility_changed(Node *p_node) {
if (p_node->is_type("CanvasItem")) {
visible = !p_node->call("is_hidden");
- } else if (p_node->is_type("GeometryInstance")) {
- visible = p_node->call("get_flag",VS::INSTANCE_FLAG_VISIBLE);
+ } else if (p_node->is_type("Spatial")) {
+ visible = !p_node->call("is_hidden");
}
-
if (!visible)
item->set_button(0,idx,get_icon("Hidden","EditorIcons"));
else
@@ -274,7 +290,7 @@ void SceneTreeEditor::_node_removed(Node *p_node) {
if (p_node->is_connected("script_changed",this,"_node_script_changed"))
p_node->disconnect("script_changed",this,"_node_script_changed");
- if (p_node->is_type("GeometryInstance") || p_node->is_type("CanvasItem")) {
+ if (p_node->is_type("Spatial") || p_node->is_type("CanvasItem")) {
if (p_node->is_connected("visibility_changed",this,"_node_visibility_changed"))
p_node->disconnect("visibility_changed",this,"_node_visibility_changed");
}
diff --git a/tools/export/blender25/io_scene_dae/export_dae.py b/tools/export/blender25/io_scene_dae/export_dae.py
index 15ec77cf8f..ec907a998d 100644
--- a/tools/export/blender25/io_scene_dae/export_dae.py
+++ b/tools/export/blender25/io_scene_dae/export_dae.py
@@ -293,6 +293,9 @@ class DaeExporter:
self.writel(S_FX,6,'</bump>')
self.writel(S_FX,5,'</technique>')
+ self.writel(S_FX,5,'<technique profile="GOOGLEEARTH">')
+ self.writel(S_FX,6,'<double_sided>'+["0","1"][double_sided_hint]+"</double_sided>")
+ self.writel(S_FX,5,'</technique>')
self.writel(S_FX,4,'</extra>')
self.writel(S_FX,3,'</technique>')
@@ -359,7 +362,7 @@ class DaeExporter:
mat= None
if (mat!=None):
- materials[f.material_index]=self.export_material( mat )
+ materials[f.material_index]=self.export_material( mat,mesh.show_double_sided )
else:
materials[f.material_index]=None #weird, has no material?
@@ -730,7 +733,7 @@ class DaeExporter:
self.writel(S_LAMPS,2,'<optics>')
self.writel(S_LAMPS,3,'<technique_common>')
- if (light.type=="POINT" or light.type=="HEMI"):
+ if (light.type=="POINT"):
self.writel(S_LAMPS,4,'<point>')
self.writel(S_LAMPS,5,'<color>'+strarr(light.color)+'</color>')
att_by_distance = 2.0 / light.distance # convert to linear attenuation