diff options
Diffstat (limited to 'tools/editor/plugins')
-rw-r--r-- | tools/editor/plugins/baked_light_editor_plugin.cpp | 996 | ||||
-rw-r--r-- | tools/editor/plugins/baked_light_editor_plugin.h | 70 | ||||
-rw-r--r-- | tools/editor/plugins/sample_editor_plugin.cpp | 149 | ||||
-rw-r--r-- | tools/editor/plugins/sample_library_editor_plugin.cpp | 2 |
4 files changed, 1144 insertions, 73 deletions
diff --git a/tools/editor/plugins/baked_light_editor_plugin.cpp b/tools/editor/plugins/baked_light_editor_plugin.cpp new file mode 100644 index 0000000000..b1e42e3369 --- /dev/null +++ b/tools/editor/plugins/baked_light_editor_plugin.cpp @@ -0,0 +1,996 @@ +#include "baked_light_editor_plugin.h" +#include "scene/gui/box_container.h" +#include "scene/3d/mesh_instance.h" +#include "scene/3d/light.h" + + +class BakedLightBaker { +public: + + enum { + + ATTENUATION_CURVE_LEN=256 + }; + + struct Octant { + bool leaf; + union { + struct { + float light_accum[3]; + float surface_area; + Octant *next_leaf; + float offset[3]; + }; + Octant* children[8]; + }; + }; + + struct Triangle { + + Vector3 vertices[3]; + Vector2 uv[3]; + }; + + + struct BVH { + + AABB aabb; + Vector3 center; + Triangle *leaf; + BVH*children[2]; + }; + + + struct BVHCmpX { + + bool operator()(const BVH* p_left, const BVH* p_right) const { + + return p_left->center.x < p_right->center.x; + } + }; + + struct BVHCmpY { + + bool operator()(const BVH* p_left, const BVH* p_right) const { + + return p_left->center.y < p_right->center.y; + } + }; + struct BVHCmpZ { + + bool operator()(const BVH* p_left, const BVH* p_right) const { + + return p_left->center.z < p_right->center.z; + } + }; + + + struct DirLight { + + + Vector3 pos; + Vector3 up; + Vector3 left; + Vector3 dir; + Color diffuse; + Color specular; + float energy; + float length; + int rays_thrown; + + }; + + AABB octree_aabb; + Octant *octree; + BVH*bvh; + Vector<Triangle> triangles; + Transform base_inv; + Octant *leaf_list; + int octree_depth; + int cell_count; + uint32_t *ray_stack; + BVH **bvh_stack; + float cell_size; + float plot_size; //multiplied by cell size + Vector<DirLight> directional_lights; + int max_bounces; + + + + void _add_mesh(const Ref<Mesh>& p_mesh,const Ref<Material>& p_mat_override,const Transform& p_xform); + void _parse_geometry(Node* p_node); + BVH* _parse_bvh(BVH** p_children,int p_size,int p_depth,int& max_depth); + void _make_bvh(); + void _make_octree(); + void _octree_insert(const AABB& p_aabb,Octant *p_octant,Triangle* p_triangle, int p_depth); + + void _free_octree(Octant *p_octant) { + + if (!p_octant->leaf) { + + for(int i=0;i<8;i++) { + if (p_octant->children[i]) + _free_octree(p_octant->children[i]); + } + } + + memdelete(p_octant); + } + + void _free_bvh(BVH* p_bvh) { + + if (!p_bvh->leaf) { + if (p_bvh->children[0]) + _free_bvh(p_bvh->children[0]); + if (p_bvh->children[1]) + _free_bvh(p_bvh->children[1]); + } + + memdelete(p_bvh); + + } + + void _fix_lights(); + + + void _plot_light(const Vector3& p_plot_pos,const AABB& p_plot_aabb, Octant *p_octant, const AABB& p_aabb,const Color& p_light); + void _throw_ray(const Vector3& p_from, const Vector3& p_to,const Color& p_light,float *p_att_curve,float p_att_curve_len,int p_bounces); + + + void throw_rays(int p_amount); + float get_normalization() const; + + + void bake(Node *p_base); + + + void clear() { + + if (octree) + _free_octree(octree); + if (bvh) + _free_bvh(bvh); + + if (ray_stack) + memdelete_arr(ray_stack); + if (bvh_stack) + memdelete_arr(bvh_stack); + + octree=NULL; + bvh=NULL; + leaf_list=NULL; + cell_count=0; + ray_stack=NULL; + bvh_stack=NULL; + } + + BakedLightBaker() { + octree_depth=8; + octree=NULL; + bvh=NULL; + leaf_list=NULL; + cell_count=0; + ray_stack=NULL; + bvh_stack=NULL; + plot_size=2; + max_bounces=3; + } + + ~BakedLightBaker() { + + clear(); + } + +}; + + +void BakedLightBaker::_add_mesh(const Ref<Mesh>& p_mesh,const Ref<Material>& p_mat_override,const Transform& p_xform) { + + + for(int i=0;i<p_mesh->get_surface_count();i++) { + + if (p_mesh->surface_get_primitive_type(i)!=Mesh::PRIMITIVE_TRIANGLES) + continue; + Ref<Material> mat = p_mat_override.is_valid()?p_mat_override:p_mesh->surface_get_material(i); + + int facecount=0; + + + if (p_mesh->surface_get_format(i)&Mesh::ARRAY_FORMAT_INDEX) { + + facecount=p_mesh->surface_get_array_index_len(i); + } else { + + facecount=p_mesh->surface_get_array_len(i); + } + + ERR_CONTINUE((facecount==0 || (facecount%3)!=0)); + + facecount/=3; + + int tbase=triangles.size(); + triangles.resize(facecount+tbase); + + + Array a = p_mesh->surface_get_arrays(i); + + DVector<Vector3> vertices = a[Mesh::ARRAY_VERTEX]; + DVector<Vector3>::Read vr=vertices.read(); + + if (p_mesh->surface_get_format(i)&Mesh::ARRAY_FORMAT_INDEX) { + + DVector<int> indices = a[Mesh::ARRAY_INDEX]; + DVector<int>::Read ir = indices.read(); + + for(int i=0;i<facecount;i++) { + Triangle &t=triangles[tbase+i]; + t.vertices[0]=p_xform.xform(vr[ ir[i*3+0] ]); + t.vertices[1]=p_xform.xform(vr[ ir[i*3+1] ]); + t.vertices[2]=p_xform.xform(vr[ ir[i*3+2] ]); + } + + } else { + + for(int i=0;i<facecount;i++) { + Triangle &t=triangles[tbase+i]; + t.vertices[0]=p_xform.xform(vr[ i*3+0 ]); + t.vertices[1]=p_xform.xform(vr[ i*3+1 ]); + t.vertices[2]=p_xform.xform(vr[ i*3+2 ]); + } + } + } + +} + + +void BakedLightBaker::_parse_geometry(Node* p_node) { + + if (p_node->cast_to<MeshInstance>()) { + + MeshInstance *meshi=p_node->cast_to<MeshInstance>(); + Ref<Mesh> mesh=meshi->get_mesh(); + if (mesh.is_valid()) { + _add_mesh(mesh,meshi->get_material_override(),base_inv * meshi->get_global_transform()); + } + } + + if (p_node->cast_to<DirectionalLight>()) { + + DirectionalLight *dl=p_node->cast_to<DirectionalLight>(); + + DirLight dirl; + dirl.diffuse=dl->get_color(DirectionalLight::COLOR_DIFFUSE); + dirl.specular=dl->get_color(DirectionalLight::COLOR_SPECULAR); + dirl.energy=dl->get_parameter(DirectionalLight::PARAM_ENERGY); + dirl.pos=dl->get_global_transform().origin; + dirl.up=dl->get_global_transform().basis.get_axis(1).normalized(); + dirl.left=dl->get_global_transform().basis.get_axis(0).normalized(); + dirl.dir=-dl->get_global_transform().basis.get_axis(2).normalized(); + dirl.rays_thrown=0; + directional_lights.push_back(dirl); + + } + + for(int i=0;i<p_node->get_child_count();i++) { + + _parse_geometry(p_node->get_child(i)); + } +} + + +void BakedLightBaker::_fix_lights() { + + + for(int i=0;i<directional_lights.size();i++) { + + DirLight &dl=directional_lights[i]; + float up_max=-1e10; + float dir_max=-1e10; + float left_max=-1e10; + float up_min=1e10; + float dir_min=1e10; + float left_min=1e10; + + for(int j=0;j<triangles.size();j++) { + + for(int k=0;k<3;k++) { + + Vector3 v = triangles[j].vertices[j]; + + float up_d = dl.up.dot(v); + float dir_d = dl.dir.dot(v); + float left_d = dl.left.dot(v); + + if (up_d>up_max) + up_max=up_d; + if (up_d<up_min) + up_min=up_d; + + if (left_d>left_max) + left_max=left_d; + if (left_d<left_min) + left_min=left_d; + + if (dir_d>dir_max) + dir_max=dir_d; + if (dir_d<dir_min) + dir_min=dir_d; + + } + } + + //make a center point, then the upvector and leftvector + dl.pos = dl.left*( left_max+left_min )*0.5 + dl.up*( up_max+up_min )*0.5 + dl.dir*(dir_min-(dir_max-dir_min)); + dl.left*=(left_max-left_min)*0.5; + dl.up*=(up_max-up_min)*0.5; + dl.length = (dir_max - dir_min)*10; //arbitrary number to keep it in scale + + } +} + +BakedLightBaker::BVH* BakedLightBaker::_parse_bvh(BVH** p_children, int p_size, int p_depth, int &max_depth) { + + if (p_depth>max_depth) { + max_depth=p_depth; + } + + if (p_size==1) { + + return p_children[0]; + } else if (p_size==0) { + + return NULL; + } + + + AABB aabb; + aabb=p_children[0]->aabb; + for(int i=1;i<p_size;i++) { + + aabb.merge_with(p_children[i]->aabb); + } + + int li=aabb.get_longest_axis_index(); + + switch(li) { + + case Vector3::AXIS_X: { + SortArray<BVH*,BVHCmpX> sort_x; + sort_x.nth_element(0,p_size,p_size/2,p_children); + //sort_x.sort(&p_bb[p_from],p_size); + } break; + case Vector3::AXIS_Y: { + SortArray<BVH*,BVHCmpY> sort_y; + sort_y.nth_element(0,p_size,p_size/2,p_children); + //sort_y.sort(&p_bb[p_from],p_size); + } break; + case Vector3::AXIS_Z: { + SortArray<BVH*,BVHCmpZ> sort_z; + sort_z.nth_element(0,p_size,p_size/2,p_children); + //sort_z.sort(&p_bb[p_from],p_size); + + } break; + } + + + BVH* left = _parse_bvh(p_children,p_size/2,p_depth+1,max_depth); + BVH* right = _parse_bvh(&p_children[p_size/2],p_size-p_size/2,p_depth+1,max_depth); + + BVH *_new = memnew(BVH); + _new->aabb=aabb; + _new->center=aabb.pos+aabb.size*0.5; + _new->children[0]=left; + _new->children[1]=right; + _new->leaf=NULL; + + return _new; +} + +void BakedLightBaker::_make_bvh() { + + Vector<BVH*> bases; + bases.resize(triangles.size()); + int max_depth=0; + for(int i=0;i<triangles.size();i++) { + bases[i]=memnew( BVH ); + bases[i]->leaf=&triangles[i]; + bases[i]->aabb.pos=triangles[i].vertices[0]; + bases[i]->aabb.expand_to(triangles[i].vertices[1]); + bases[i]->aabb.expand_to(triangles[i].vertices[2]); + bases[i]->center=bases[i]->aabb.pos+bases[i]->aabb.size*0.5; + } + + bvh=_parse_bvh(bases.ptr(),bases.size(),1,max_depth); + ray_stack = memnew_arr(uint32_t,max_depth); + bvh_stack = memnew_arr(BVH*,max_depth); +} + +void BakedLightBaker::_octree_insert(const AABB& p_aabb,Octant *p_octant,Triangle* p_triangle, int p_depth) { + + if (p_octant->leaf) { + + if (p_aabb.has_point(p_triangle->vertices[0]) && p_aabb.has_point(p_triangle->vertices[1]) &&p_aabb.has_point(p_triangle->vertices[2])) { + //face is completely enclosed, add area + p_octant->surface_area+=Face3(p_triangle->vertices[0],p_triangle->vertices[1],p_triangle->vertices[2]).get_area(); + } else { + //not completely enclosed, will need to be clipped.. + Vector<Vector3> poly; + poly.push_back(p_triangle->vertices[0]); + poly.push_back(p_triangle->vertices[1]); + poly.push_back(p_triangle->vertices[2]); + + //clip + for(int i=0;i<3;i++) { + + //top plane + Plane p(0,0,0,0); + p.normal[i]=1.0; + p.d=p_aabb.pos[i]+p_aabb.size[i]; + poly=Geometry::clip_polygon(poly,p); + + //bottom plane + p.normal[i]=-1.0; + p.d=-p_aabb.pos[i]; + poly=Geometry::clip_polygon(poly,p); + } + //calculate area + for(int i=2;i<poly.size();i++) { + p_octant->surface_area+=Face3(poly[0],poly[i-1],poly[i]).get_area(); + } + } + + } else { + + + for(int i=0;i<8;i++) { + + AABB aabb=p_aabb; + aabb.size*=0.5; + if (i&1) + aabb.pos.x+=aabb.size.x; + if (i&2) + aabb.pos.y+=aabb.size.y; + if (i&4) + aabb.pos.z+=aabb.size.z; + + AABB fit_aabb=aabb; + //fit_aabb=fit_aabb.grow(bvh->aabb.size.x*0.0001); + + if (!Face3(p_triangle->vertices[0],p_triangle->vertices[1],p_triangle->vertices[2]).intersects_aabb(fit_aabb)) + continue; + + if (!p_octant->children[i]) { + p_octant->children[i]=memnew(Octant); + if (p_depth==0) { + p_octant->children[i]->leaf=true; + p_octant->children[i]->light_accum[0]=0; + p_octant->children[i]->light_accum[1]=0; + p_octant->children[i]->light_accum[2]=0; + p_octant->children[i]->offset[0]=aabb.pos.x+aabb.size.x*0.5; + p_octant->children[i]->offset[1]=aabb.pos.y+aabb.size.y*0.5; + p_octant->children[i]->offset[2]=aabb.pos.z+aabb.size.z*0.5; + p_octant->children[i]->surface_area=0; + p_octant->children[i]->next_leaf=leaf_list; + leaf_list=p_octant->children[i]; + cell_count++; + } else { + + p_octant->children[i]->leaf=false; + for(int j=0;j<8;j++) { + p_octant->children[i]->children[j]=0; + } + } + } + + _octree_insert(aabb,p_octant->children[i],p_triangle,p_depth-1); + } + } +} + + +void BakedLightBaker::_make_octree() { + + AABB base = bvh->aabb; + float lal=base.get_longest_axis_size(); + //must be square because we want square blocks + base.size.x=lal; + base.size.y=lal; + base.size.z=lal; + base.grow_by(lal*0.001); //for precision + octree_aabb=base; + + cell_size=base.size.x; + for(int i=0;i<=octree_depth;i++) + cell_size/=2.0; + + octree = memnew( Octant ); + octree->leaf=false; + for(int i=0;i<8;i++) + octree->children[i]=NULL; + + for(int i=0;i<triangles.size();i++) { + + _octree_insert(octree_aabb,octree,&triangles[i],octree_depth-1); + } + +} + + +void BakedLightBaker::_plot_light(const Vector3& p_plot_pos,const AABB& p_plot_aabb, Octant *p_octant, const AABB& p_aabb,const Color& p_light) { + + + if (p_octant->leaf) { + + float r=cell_size*plot_size; + Vector3 center=p_aabb.pos+p_aabb.size*0.5; + float d = p_plot_pos.distance_to(center); + if (d>r) + return; //oh crap! outside radius + float intensity = 1.0 - (d/r)*(d/r); //not gauss but.. + p_octant->light_accum[0]+=p_light.r*intensity; + p_octant->light_accum[1]+=p_light.g*intensity; + p_octant->light_accum[2]+=p_light.b*intensity; + + } else { + + for(int i=0;i<8;i++) { + + if (!p_octant->children[i]) + continue; + + AABB aabb=p_aabb; + aabb.size*=0.5; + if (i&1) + aabb.pos.x+=aabb.size.x; + if (i&2) + aabb.pos.y+=aabb.size.y; + if (i&4) + aabb.pos.z+=aabb.size.z; + + + if (!aabb.intersects(p_plot_aabb)) + continue; + + _plot_light(p_plot_pos,p_plot_aabb,p_octant->children[i],aabb,p_light); + + } + + } +} + + +void BakedLightBaker::_throw_ray(const Vector3& p_begin, const Vector3& p_end,const Color& p_light,float *p_att_curve,float p_att_curve_len,int p_bounces) { + + + uint32_t* stack = ray_stack; + BVH **bstack = bvh_stack; + + enum { + TEST_AABB_BIT=0, + VISIT_LEFT_BIT=1, + VISIT_RIGHT_BIT=2, + VISIT_DONE_BIT=3, + + + }; + + Vector3 n = (p_end-p_begin).normalized(); + real_t d=1e10; + bool inters=false; + Vector3 r_normal; + Vector3 r_point; + + //for(int i=0;i<max_depth;i++) + // stack[i]=0; + + int level=0; + //AABB ray_aabb; + //ray_aabb.pos=p_begin; + //ray_aabb.expand_to(p_end); + + + const BVH *bvhptr = bvh; + + bstack[0]=bvh; + stack[0]=TEST_AABB_BIT; + + + while(true) { + + uint32_t mode = stack[level]; + const BVH &b = *bstack[level]; + bool done=false; + + switch(mode) { + case TEST_AABB_BIT: { + + if (b.leaf) { + + + Face3 f3(b.leaf->vertices[0],b.leaf->vertices[1],b.leaf->vertices[2]); + + + Vector3 res; + + if (f3.intersects_segment(p_begin,p_end,&res)) { + + + float nd = n.dot(res); + if (nd<d) { + + d=nd; + r_point=res; + r_normal=f3.get_plane().get_normal(); + inters=true; + } + + } + + stack[level]=VISIT_DONE_BIT; + } else { + + + bool valid = b.aabb.intersects_segment(p_begin,p_end); + // bool valid = b.aabb.intersects(ray_aabb); + + if (!valid) { + + stack[level]=VISIT_DONE_BIT; + + } else { + + stack[level]=VISIT_LEFT_BIT; + } + } + + } continue; + case VISIT_LEFT_BIT: { + + stack[level]=VISIT_RIGHT_BIT; + bstack[level+1]=b.children[0]; + stack[level+1]=TEST_AABB_BIT; + level++; + + } continue; + case VISIT_RIGHT_BIT: { + + stack[level]=VISIT_DONE_BIT; + bstack[level+1]=b.children[1]; + stack[level+1]=TEST_AABB_BIT; + level++; + } continue; + case VISIT_DONE_BIT: { + + if (level==0) { + done=true; + break; + } else + level--; + + } continue; + } + + + if (done) + break; + } + + + if (inters) { + + //print_line("collision!"); + if (n.dot(r_normal)>0) + r_normal=-r_normal; + + //ok... + Color diffuse_at_point(0.8,0.8,0.8); + Color specular_at_point(0.8,0.8,0.8); + + AABB aabb; + aabb.pos=r_point; + aabb.pos-=Vector3(1,1,1)*cell_size*plot_size; + aabb.size=Vector3(2,2,2)*cell_size*plot_size; + + _plot_light(r_point,aabb,octree,octree_aabb,p_light); + + } + +} + + + + + + +float BakedLightBaker::get_normalization() const { + + float nrg=0; + for(int i=0;i<directional_lights.size();i++) { + + const DirLight &dl=directional_lights[i]; + float total_area = dl.left.length()*2*dl.up.length()*2; + float cell_area = cell_size*cell_size;; + nrg+= dl.energy * (dl.rays_thrown * cell_area / total_area); + nrg*=5; + } + + return nrg; +} + +void BakedLightBaker::throw_rays(int p_amount) { + + + + for(int i=0;i<directional_lights.size();i++) { + + DirLight &dl=directional_lights[i]; + + float sr = Math::sqrt(p_amount); + float aspect = dl.up.length()/dl.left.length(); + + + for(int j=0;j<p_amount;j++) { + Vector3 from = dl.pos; + from+=dl.up*(Math::randf()*2.0-1.0); + from+=dl.left*(Math::randf()*2.0-1.0); + Vector3 to = from+dl.dir*dl.length; + Color col=dl.diffuse; + col.r*=dl.energy; + col.g*=dl.energy; + col.b*=dl.energy; + dl.rays_thrown++; + _throw_ray(from,to,col,NULL,0,max_bounces); + } + + + } +} + + + + + + + + + + + + + +void BakedLightBaker::bake(Node* p_node) { + + cell_count=0; + + _parse_geometry(p_node); + _fix_lights(); + _make_bvh(); + _make_octree(); + +} + + + + +void BakedLightEditor::_node_removed(Node *p_node) { + + if(p_node==node) { + node=NULL; + p_node->remove_child(preview); + preview->set_mesh(Ref<Mesh>()); + hide(); + } + +} + + + +void BakedLightEditor::_menu_option(int p_option) { + + + switch(p_option) { + + + case MENU_OPTION_BAKE: { + + ERR_FAIL_COND(!node); + preview->set_mesh(Ref<Mesh>()); + baker->base_inv=node->get_global_transform().affine_inverse(); + baker->bake(node); + baker->throw_rays(100000); + float norm = baker->get_normalization(); + float max_lum=0; + + print_line("CELLS: "+itos(baker->cell_count)); + DVector<Color> colors; + DVector<Vector3> vertices; + colors.resize(baker->cell_count*36); + vertices.resize(baker->cell_count*36); + + + { + DVector<Color>::Write cw=colors.write(); + DVector<Vector3>::Write vw=vertices.write(); + BakedLightBaker::Octant *oct = baker->leaf_list; + int vert_idx=0; + + while(oct) { + + Color color; + color.r=oct->light_accum[0]/norm; + color.g=oct->light_accum[1]/norm; + color.b=oct->light_accum[2]/norm; + float lum = color.get_v(); + if (lum>max_lum) + max_lum=lum; + + for (int i=0;i<6;i++) { + + + Vector3 face_points[4]; + for (int j=0;j<4;j++) { + + float v[3]; + v[0]=1.0; + v[1]=1-2*((j>>1)&1); + v[2]=v[1]*(1-2*(j&1)); + + for (int k=0;k<3;k++) { + + if (i<3) + face_points[j][(i+k)%3]=v[k]*(i>=3?-1:1); + else + face_points[3-j][(i+k)%3]=v[k]*(i>=3?-1:1); + } + } + + for(int j=0;j<4;j++) { + face_points[j]*=baker->cell_size; + face_points[j]+=Vector3(oct->offset[0],oct->offset[1],oct->offset[2]); + } + +#define ADD_VTX(m_idx) \ + vw[vert_idx]=face_points[m_idx]; \ + cw[vert_idx]=color; \ + vert_idx++; + + //tri 1 + ADD_VTX(0); + ADD_VTX(1); + ADD_VTX(2); + //tri 2 + ADD_VTX(2); + ADD_VTX(3); + ADD_VTX(0); + +#undef ADD_VTX + + } + + oct=oct->next_leaf; + } + + + } + + print_line("max lum: "+rtos(max_lum)); + Array a; + a.resize(Mesh::ARRAY_MAX); + a[Mesh::ARRAY_VERTEX]=vertices; + a[Mesh::ARRAY_COLOR]=colors; + + Ref<FixedMaterial> matcol = memnew( FixedMaterial ); + matcol->set_fixed_flag(FixedMaterial::FLAG_USE_COLOR_ARRAY,true); + matcol->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA,true); + matcol->set_flag(FixedMaterial::FLAG_UNSHADED,true); + matcol->set_flag(FixedMaterial::FLAG_DOUBLE_SIDED,true); + matcol->set_parameter(FixedMaterial::PARAM_DIFFUSE,Color(1,1,1)); + Ref<Mesh> m = memnew( Mesh ); + m->add_surface(Mesh::PRIMITIVE_TRIANGLES,a); + m->surface_set_material(0,matcol); + preview->set_mesh(m); + + + + + + } break; + case MENU_OPTION_CLEAR: { + + + + } break; + + } +} + + +void BakedLightEditor::edit(BakedLight *p_baked_light) { + + if (node==p_baked_light) + return; + if (node) { + node->remove_child(preview); + } + + node=p_baked_light; + + if (node) + node->add_child(preview); + +} + + + +void BakedLightEditor::_bind_methods() { + + ObjectTypeDB::bind_method("_menu_option",&BakedLightEditor::_menu_option); +} + +BakedLightEditor::BakedLightEditor() { + + + options = memnew( MenuButton ); + + options->set_text("BakedLight"); + options->get_popup()->add_item("Bake..",MENU_OPTION_BAKE); + options->get_popup()->add_item("Clear",MENU_OPTION_CLEAR); + options->get_popup()->connect("item_pressed", this,"_menu_option"); + + + err_dialog = memnew( AcceptDialog ); + add_child(err_dialog); + node=NULL; + baker = memnew( BakedLightBaker ); + preview = memnew( MeshInstance ); +} + +BakedLightEditor::~BakedLightEditor() { + + memdelete(baker); +} + +void BakedLightEditorPlugin::edit(Object *p_object) { + + baked_light_editor->edit(p_object->cast_to<BakedLight>()); +} + +bool BakedLightEditorPlugin::handles(Object *p_object) const { + + return p_object->is_type("BakedLight"); +} + +void BakedLightEditorPlugin::make_visible(bool p_visible) { + + if (p_visible) { + baked_light_editor->show(); + baked_light_editor->options->show(); + } else { + + baked_light_editor->hide(); + baked_light_editor->options->show(); + baked_light_editor->edit(NULL); + if (baked_light_editor->node) { + baked_light_editor->node->remove_child(baked_light_editor->preview); + baked_light_editor->node=NULL; + } + } + +} + +BakedLightEditorPlugin::BakedLightEditorPlugin(EditorNode *p_node) { + + editor=p_node; + baked_light_editor = memnew( BakedLightEditor ); + editor->get_viewport()->add_child(baked_light_editor); + add_custom_control(CONTAINER_SPATIAL_EDITOR_MENU,baked_light_editor->options); + baked_light_editor->hide(); + baked_light_editor->options->hide(); +} + + +BakedLightEditorPlugin::~BakedLightEditorPlugin() +{ +} + + diff --git a/tools/editor/plugins/baked_light_editor_plugin.h b/tools/editor/plugins/baked_light_editor_plugin.h new file mode 100644 index 0000000000..698d3f825f --- /dev/null +++ b/tools/editor/plugins/baked_light_editor_plugin.h @@ -0,0 +1,70 @@ +#ifndef BAKED_LIGHT_EDITOR_PLUGIN_H +#define BAKED_LIGHT_EDITOR_PLUGIN_H + +#include "tools/editor/editor_plugin.h" +#include "tools/editor/editor_node.h" +#include "scene/3d/baked_light.h" +#include "scene/gui/spin_box.h" + +/** + @author Juan Linietsky <reduzio@gmail.com> +*/ + + +class BakedLightBaker; +class MeshInstance; + +class BakedLightEditor : public Control { + + OBJ_TYPE(BakedLightEditor, Control ); + + + MeshInstance *preview; + BakedLightBaker *baker; + AcceptDialog *err_dialog; + + MenuButton * options; + BakedLight *node; + + enum Menu { + + MENU_OPTION_BAKE, + MENU_OPTION_CLEAR + }; + + void _menu_option(int); + +friend class BakedLightEditorPlugin; +protected: + void _node_removed(Node *p_node); + static void _bind_methods(); +public: + + void edit(BakedLight *p_baked_light); + BakedLightEditor(); + ~BakedLightEditor(); +}; + +class BakedLightEditorPlugin : public EditorPlugin { + + OBJ_TYPE( BakedLightEditorPlugin, EditorPlugin ); + + BakedLightEditor *baked_light_editor; + EditorNode *editor; + +public: + + virtual String get_name() const { return "BakedLight"; } + bool has_main_screen() const { return false; } + virtual void edit(Object *p_node); + virtual bool handles(Object *p_node) const; + virtual void make_visible(bool p_visible); + + BakedLightEditorPlugin(EditorNode *p_node); + ~BakedLightEditorPlugin(); + +}; + +#endif // MULTIMESH_EDITOR_PLUGIN_H + + diff --git a/tools/editor/plugins/sample_editor_plugin.cpp b/tools/editor/plugins/sample_editor_plugin.cpp index f55d6640c2..e3fad58a89 100644 --- a/tools/editor/plugins/sample_editor_plugin.cpp +++ b/tools/editor/plugins/sample_editor_plugin.cpp @@ -95,93 +95,98 @@ void SampleEditor::generate_preview_texture(const Ref<Sample>& p_sample,Ref<Imag if (len<1) return; - for(int i=0;i<w;i++) { - // i trust gcc will optimize this loop - float max[2]={-1e10,-1e10}; - float min[2]={1e10,1e10}; - int c=stereo?2:1; - int from = i*len/w; - int to = (i+1)*len/w; - if (to>=len) - to=len-1; - - if (_16) { - const int16_t*src =(const int16_t*)sdata; - - for(int j=0;j<c;j++) { - - for(int k=from;k<=to;k++) { - - float v = src[k*c+j]/32768.0; - if (v>max[j]) - max[j]=v; - if (v<min[j]) - min[j]=v; + if (p_sample->get_format()==Sample::FORMAT_IMA_ADPCM) { + + + } else { + for(int i=0;i<w;i++) { + // i trust gcc will optimize this loop + float max[2]={-1e10,-1e10}; + float min[2]={1e10,1e10}; + int c=stereo?2:1; + int from = i*len/w; + int to = (i+1)*len/w; + if (to>=len) + to=len-1; + + if (_16) { + const int16_t*src =(const int16_t*)sdata; + + for(int j=0;j<c;j++) { + + for(int k=from;k<=to;k++) { + + float v = src[k*c+j]/32768.0; + if (v>max[j]) + max[j]=v; + if (v<min[j]) + min[j]=v; + } + } + } else { - } - } else { + const int8_t*src =(const int8_t*)sdata; - const int8_t*src =(const int8_t*)sdata; + for(int j=0;j<c;j++) { - for(int j=0;j<c;j++) { + for(int k=from;k<=to;k++) { - for(int k=from;k<=to;k++) { + float v = src[k*c+j]/128.0; + if (v>max[j]) + max[j]=v; + if (v<min[j]) + min[j]=v; + } - float v = src[k*c+j]/128.0; - if (v>max[j]) - max[j]=v; - if (v<min[j]) - min[j]=v; } - } - } - if (!stereo) { - for(int j=0;j<h;j++) { - float v = (j/(float)h) * 2.0 - 1.0; - uint8_t* imgofs = &imgw[(j*w+i)*3]; - if (v>min[0] && v<max[0]) { - imgofs[0]=255; - imgofs[1]=150; - imgofs[2]=80; - } else { - imgofs[0]=0; - imgofs[1]=0; - imgofs[2]=0; + if (!stereo) { + for(int j=0;j<h;j++) { + float v = (j/(float)h) * 2.0 - 1.0; + uint8_t* imgofs = &imgw[(j*w+i)*3]; + if (v>min[0] && v<max[0]) { + imgofs[0]=255; + imgofs[1]=150; + imgofs[2]=80; + } else { + imgofs[0]=0; + imgofs[1]=0; + imgofs[2]=0; + } } - } - } else { - - for(int j=0;j<h;j++) { - - int half,ofs; - float v; - if (j<(h/2)) { - half=0; - ofs=0; - v = (j/(float)(h/2)) * 2.0 - 1.0; - } else { - half=1; - ofs=h/2; - v = ((j-(h/2))/(float)(h/2)) * 2.0 - 1.0; + } else { + + for(int j=0;j<h;j++) { + + int half,ofs; + float v; + if (j<(h/2)) { + half=0; + ofs=0; + v = (j/(float)(h/2)) * 2.0 - 1.0; + } else { + half=1; + ofs=h/2; + v = ((j-(h/2))/(float)(h/2)) * 2.0 - 1.0; + } + + uint8_t* imgofs = &imgw[(j*w+i)*3]; + if (v>min[half] && v<max[half]) { + imgofs[0]=255; + imgofs[1]=150; + imgofs[2]=80; + } else { + imgofs[0]=0; + imgofs[1]=0; + imgofs[2]=0; + } } - uint8_t* imgofs = &imgw[(j*w+i)*3]; - if (v>min[half] && v<max[half]) { - imgofs[0]=255; - imgofs[1]=150; - imgofs[2]=80; - } else { - imgofs[0]=0; - imgofs[1]=0; - imgofs[2]=0; - } } } - } imgdata = DVector<uint8_t>::Write(); diff --git a/tools/editor/plugins/sample_library_editor_plugin.cpp b/tools/editor/plugins/sample_library_editor_plugin.cpp index 86ac1671ae..84143dcd4b 100644 --- a/tools/editor/plugins/sample_library_editor_plugin.cpp +++ b/tools/editor/plugins/sample_library_editor_plugin.cpp @@ -262,7 +262,7 @@ void SampleLibraryEditor::_update_library() { ti->set_editable(2,false); ti->set_selectable(2,false); Ref<Sample> s = sample_library->get_sample(E->get()); - ti->set_text(2,String()+/*itos(s->get_length())+" frames ("+String::num(s->get_length()/(float)s->get_mix_rate(),2)+" s), "+*/(s->get_format()==Sample::FORMAT_PCM16?"16 Bits, ":"8 bits, ")+(s->is_stereo()?"Stereo":"Mono")); + ti->set_text(2,String()+/*itos(s->get_length())+" frames ("+String::num(s->get_length()/(float)s->get_mix_rate(),2)+" s), "+*/(s->get_format()==Sample::FORMAT_PCM16?"16 Bits, ":(s->get_format()==Sample::FORMAT_PCM8?"8 bits, ":"IMA-ADPCM,"))+(s->is_stereo()?"Stereo":"Mono")); ti->set_cell_mode(3,TreeItem::CELL_MODE_RANGE); ti->set_range_config(3,-60,24,0.01); |