1
0
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:
Juan Linietsky
2014-08-14 10:31:38 -03:00
parent c3e1d7b7c7
commit 2ee4ac183b
56 changed files with 3943 additions and 1757 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 441 B

View File

@@ -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);

View File

@@ -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,
};

View File

@@ -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();
}

View File

@@ -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;

View File

@@ -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; }

View File

@@ -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;

View File

@@ -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();

View File

@@ -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() {

View File

@@ -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");
}