summaryrefslogtreecommitdiff
path: root/tools/editor/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'tools/editor/plugins')
-rw-r--r--tools/editor/plugins/baked_light_editor_plugin.cpp996
-rw-r--r--tools/editor/plugins/baked_light_editor_plugin.h70
-rw-r--r--tools/editor/plugins/sample_editor_plugin.cpp149
-rw-r--r--tools/editor/plugins/sample_library_editor_plugin.cpp2
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);