You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-13 13:31:48 +00:00
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
This commit is contained in:
BIN
tools/editor/icons/icon_light_map.png
Normal file
BIN
tools/editor/icons/icon_light_map.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 441 B |
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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 = ©_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 = ©_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;
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user