diff options
Diffstat (limited to 'tools/editor')
-rw-r--r-- | tools/editor/editor_node.cpp | 5 | ||||
-rw-r--r-- | tools/editor/io_plugins/editor_mesh_import_plugin.cpp | 555 | ||||
-rw-r--r-- | tools/editor/io_plugins/editor_mesh_import_plugin.h | 29 | ||||
-rw-r--r-- | tools/editor/io_plugins/editor_sample_import_plugin.cpp | 178 | ||||
-rw-r--r-- | tools/editor/io_plugins/editor_sample_import_plugin.h | 1 | ||||
-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 | ||||
-rw-r--r-- | tools/editor/property_editor.cpp | 12 | ||||
-rw-r--r-- | tools/editor/property_editor.h | 2 |
11 files changed, 1901 insertions, 98 deletions
diff --git a/tools/editor/editor_node.cpp b/tools/editor/editor_node.cpp index fc644e76c5..9821dad872 100644 --- a/tools/editor/editor_node.cpp +++ b/tools/editor/editor_node.cpp @@ -85,12 +85,15 @@ #include "plugins/animation_tree_editor_plugin.h" #include "plugins/tile_set_editor_plugin.h" #include "plugins/animation_player_editor_plugin.h" +#include "plugins/baked_light_editor_plugin.h" // end #include "tools/editor/io_plugins/editor_texture_import_plugin.h" #include "tools/editor/io_plugins/editor_scene_import_plugin.h" #include "tools/editor/io_plugins/editor_font_import_plugin.h" #include "tools/editor/io_plugins/editor_sample_import_plugin.h" #include "tools/editor/io_plugins/editor_translation_import_plugin.h" +#include "tools/editor/io_plugins/editor_mesh_import_plugin.h" + EditorNode *EditorNode::singleton=NULL; @@ -4013,6 +4016,7 @@ EditorNode::EditorNode() { _scene_import->add_importer(_collada_import); editor_import_export->add_import_plugin( _scene_import); editor_import_export->add_import_plugin( Ref<EditorSceneAnimationImportPlugin>( memnew(EditorSceneAnimationImportPlugin(this)))); + editor_import_export->add_import_plugin( Ref<EditorMeshImportPlugin>( memnew(EditorMeshImportPlugin(this)))); editor_import_export->add_import_plugin( Ref<EditorFontImportPlugin>( memnew(EditorFontImportPlugin(this)))); editor_import_export->add_import_plugin( Ref<EditorSampleImportPlugin>( memnew(EditorSampleImportPlugin(this)))); editor_import_export->add_import_plugin( Ref<EditorTranslationImportPlugin>( memnew(EditorTranslationImportPlugin(this)))); @@ -4051,6 +4055,7 @@ EditorNode::EditorNode() { add_editor_plugin( memnew( Particles2DEditorPlugin(this) ) ); add_editor_plugin( memnew( Path2DEditorPlugin(this) ) ); add_editor_plugin( memnew( PathEditorPlugin(this) ) ); + add_editor_plugin( memnew( BakedLightEditorPlugin(this) ) ); for(int i=0;i<EditorPlugins::get_plugin_count();i++) add_editor_plugin( EditorPlugins::create(i,this) ); diff --git a/tools/editor/io_plugins/editor_mesh_import_plugin.cpp b/tools/editor/io_plugins/editor_mesh_import_plugin.cpp new file mode 100644 index 0000000000..d76a778433 --- /dev/null +++ b/tools/editor/io_plugins/editor_mesh_import_plugin.cpp @@ -0,0 +1,555 @@ +#include "editor_mesh_import_plugin.h" + +#include "scene/gui/file_dialog.h" +#include "tools/editor/editor_dir_dialog.h" +#include "tools/editor/editor_node.h" +#include "tools/editor/property_editor.h" +#include "scene/resources/sample.h" +#include "io/resource_saver.h" +#include "os/file_access.h" +#include "io/marshalls.h" +#include "scene/resources/surface_tool.h" + +class _EditorMeshImportOptions : public Object { + + OBJ_TYPE(_EditorMeshImportOptions,Object); +public: + + + bool generate_tangents; + bool generate_normals; + bool flip_faces; + bool smooth_shading; + bool weld_vertices; + bool import_material; + bool import_textures; + float weld_tolerance; + + + bool _set(const StringName& p_name, const Variant& p_value) { + + String n = p_name; + if (n=="generate/tangents") + generate_tangents=p_value; + else if (n=="generate/normals") + generate_normals=p_value; + else if (n=="import/materials") + import_material=p_value; + else if (n=="import/textures") + import_textures=p_value; + else if (n=="force/flip_faces") + flip_faces=p_value; + else if (n=="force/smooth_shading") + smooth_shading=p_value; + else if (n=="force/weld_vertices") + weld_vertices=p_value; + else if (n=="force/weld_tolerance") + weld_tolerance=p_value; + else + return false; + + return true; + + } + + bool _get(const StringName& p_name,Variant &r_ret) const{ + + String n = p_name; + if (n=="generate/tangents") + r_ret=generate_tangents; + else if (n=="generate/normals") + r_ret=generate_normals; + else if (n=="import/materials") + r_ret=import_material; + else if (n=="import/textures") + r_ret=import_textures; + else if (n=="force/flip_faces") + r_ret=flip_faces; + else if (n=="force/smooth_shading") + r_ret=smooth_shading; + else if (n=="force/weld_vertices") + r_ret=weld_vertices; + else if (n=="force/weld_tolerance") + r_ret=weld_tolerance; + else + return false; + + return true; + + } + void _get_property_list( List<PropertyInfo> *p_list) const{ + + p_list->push_back(PropertyInfo(Variant::BOOL,"generate/tangents")); + p_list->push_back(PropertyInfo(Variant::BOOL,"generate/normals")); + //not for nowp + //p_list->push_back(PropertyInfo(Variant::BOOL,"import/materials")); + //p_list->push_back(PropertyInfo(Variant::BOOL,"import/textures")); + p_list->push_back(PropertyInfo(Variant::BOOL,"force/flip_faces")); + p_list->push_back(PropertyInfo(Variant::BOOL,"force/smooth_shading")); + p_list->push_back(PropertyInfo(Variant::BOOL,"force/weld_vertices")); + p_list->push_back(PropertyInfo(Variant::REAL,"force/weld_tolerance",PROPERTY_HINT_RANGE,"0.00001,16,0.00001")); + //p_list->push_back(PropertyInfo(Variant::BOOL,"compress/enable")); + //p_list->push_back(PropertyInfo(Variant::INT,"compress/bitrate",PROPERTY_HINT_ENUM,"64,96,128,192")); + + + } + + + static void _bind_methods() { + + + ADD_SIGNAL( MethodInfo("changed")); + } + + + _EditorMeshImportOptions() { + + generate_tangents=true; + generate_normals=true; + flip_faces=false; + smooth_shading=false; + weld_vertices=true; + weld_tolerance=0.0001; + import_material=false; + import_textures=false; + + } + + +}; + +class EditorMeshImportDialog : public ConfirmationDialog { + + OBJ_TYPE(EditorMeshImportDialog,ConfirmationDialog); + + EditorMeshImportPlugin *plugin; + + LineEdit *import_path; + LineEdit *save_path; + FileDialog *file_select; + EditorDirDialog *save_select; + ConfirmationDialog *error_dialog; + PropertyEditor *option_editor; + + _EditorMeshImportOptions *options; + + +public: + + void _choose_files(const Vector<String>& p_path) { + + String files; + for(int i=0;i<p_path.size();i++) { + + if (i>0) + files+=","; + files+=p_path[i]; + } + /* + if (p_path.size()) { + String srctex=p_path[0]; + String ipath = EditorImportDB::get_singleton()->find_source_path(srctex); + + if (ipath!="") + save_path->set_text(ipath.get_base_dir()); + }*/ + import_path->set_text(files); + + } + void _choose_save_dir(const String& p_path) { + + save_path->set_text(p_path); + } + + void _browse() { + + file_select->popup_centered_ratio(); + } + + void _browse_target() { + + save_select->popup_centered_ratio(); + + } + + + void popup_import(const String& p_path) { + + popup_centered(Size2(400,400)); + if (p_path!="") { + + Ref<ResourceImportMetadata> rimd = ResourceLoader::load_import_metadata(p_path); + ERR_FAIL_COND(!rimd.is_valid()); + + save_path->set_text(p_path.get_base_dir()); + List<String> opts; + rimd->get_options(&opts); + for(List<String>::Element *E=opts.front();E;E=E->next()) { + + options->_set(E->get(),rimd->get_option(E->get())); + } + + String src = ""; + for(int i=0;i<rimd->get_source_count();i++) { + if (i>0) + src+=","; + src+=EditorImportPlugin::expand_source_path(rimd->get_source_path(i)); + } + import_path->set_text(src); + } + } + + + void _import() { + + Vector<String> meshes = import_path->get_text().split(","); + + if (meshes.size()==0) { + error_dialog->set_text("No meshes to import!"); + error_dialog->popup_centered(Size2(200,100)); + } + + for(int i=0;i<meshes.size();i++) { + + Ref<ResourceImportMetadata> imd = memnew( ResourceImportMetadata ); + + List<PropertyInfo> pl; + options->_get_property_list(&pl); + for(List<PropertyInfo>::Element *E=pl.front();E;E=E->next()) { + + Variant v; + String opt=E->get().name; + options->_get(opt,v); + imd->set_option(opt,v); + + } + + imd->add_source(EditorImportPlugin::validate_source_path(meshes[i])); + + String dst = save_path->get_text(); + if (dst=="") { + error_dialog->set_text("Save path is empty!"); + error_dialog->popup_centered(Size2(200,100)); + } + + dst = dst.plus_file(meshes[i].get_file().basename()+".msh"); + + Error err = plugin->import(dst,imd); + } + + hide(); + + } + + + void _notification(int p_what) { + + + if (p_what==NOTIFICATION_ENTER_SCENE) { + + option_editor->edit(options); + } + } + + static void _bind_methods() { + + + ObjectTypeDB::bind_method("_choose_files",&EditorMeshImportDialog::_choose_files); + ObjectTypeDB::bind_method("_choose_save_dir",&EditorMeshImportDialog::_choose_save_dir); + ObjectTypeDB::bind_method("_import",&EditorMeshImportDialog::_import); + ObjectTypeDB::bind_method("_browse",&EditorMeshImportDialog::_browse); + ObjectTypeDB::bind_method("_browse_target",&EditorMeshImportDialog::_browse_target); + // ADD_SIGNAL( MethodInfo("imported",PropertyInfo(Variant::OBJECT,"scene")) ); + } + + EditorMeshImportDialog(EditorMeshImportPlugin *p_plugin) { + + plugin=p_plugin; + + + set_title("Single Mesh Import"); + + VBoxContainer *vbc = memnew( VBoxContainer ); + add_child(vbc); + set_child_rect(vbc); + + + HBoxContainer *hbc = memnew( HBoxContainer ); + vbc->add_margin_child("Source Mesh(es):",hbc); + + import_path = memnew( LineEdit ); + import_path->set_h_size_flags(SIZE_EXPAND_FILL); + hbc->add_child(import_path); + + Button * import_choose = memnew( Button ); + import_choose->set_text(" .. "); + hbc->add_child(import_choose); + + import_choose->connect("pressed", this,"_browse"); + + hbc = memnew( HBoxContainer ); + vbc->add_margin_child("Target Path:",hbc); + + save_path = memnew( LineEdit ); + save_path->set_h_size_flags(SIZE_EXPAND_FILL); + hbc->add_child(save_path); + + Button * save_choose = memnew( Button ); + save_choose->set_text(" .. "); + hbc->add_child(save_choose); + + save_choose->connect("pressed", this,"_browse_target"); + + file_select = memnew(FileDialog); + file_select->set_access(FileDialog::ACCESS_FILESYSTEM); + add_child(file_select); + file_select->set_mode(FileDialog::MODE_OPEN_FILES); + file_select->connect("files_selected", this,"_choose_files"); + file_select->add_filter("*.obj ; Wavefront OBJ"); + save_select = memnew( EditorDirDialog ); + add_child(save_select); + + // save_select->set_mode(FileDialog::MODE_OPEN_DIR); + save_select->connect("dir_selected", this,"_choose_save_dir"); + + get_ok()->connect("pressed", this,"_import"); + get_ok()->set_text("Import"); + + + error_dialog = memnew ( ConfirmationDialog ); + add_child(error_dialog); + error_dialog->get_ok()->set_text("Accept"); + // error_dialog->get_cancel()->hide(); + + set_hide_on_ok(false); + options = memnew( _EditorMeshImportOptions ); + + option_editor = memnew( PropertyEditor ); + option_editor->hide_top_label(); + vbc->add_margin_child("Options:",option_editor,true); + } + + ~EditorMeshImportDialog() { + memdelete(options); + } + +}; + + +String EditorMeshImportPlugin::get_name() const { + + return "mesh"; +} +String EditorMeshImportPlugin::get_visible_name() const{ + + return "3D Mesh"; +} +void EditorMeshImportPlugin::import_dialog(const String& p_from){ + + dialog->popup_import(p_from); +} +Error EditorMeshImportPlugin::import(const String& p_path, const Ref<ResourceImportMetadata>& p_from){ + + + ERR_FAIL_COND_V(p_from->get_source_count()!=1,ERR_INVALID_PARAMETER); + + Ref<ResourceImportMetadata> from=p_from; + + String src_path=EditorImportPlugin::expand_source_path(from->get_source_path(0)); + FileAccessRef f = FileAccess::open(src_path,FileAccess::READ); + ERR_FAIL_COND_V(!f,ERR_CANT_OPEN); + + Ref<Mesh> mesh; + Map<String,Ref<Material> > name_map; + + if (FileAccess::exists(p_path)) { + mesh=ResourceLoader::load(p_path,"Mesh"); + if (mesh.is_valid()) { + for(int i=0;i<mesh->get_surface_count();i++) { + + if (!mesh->surface_get_material(i).is_valid()) + continue; + String name; + if (mesh->surface_get_name(i)!="") + name=mesh->surface_get_name(i); + else + name="Surface "+itos(i+1); + + name_map[name]=mesh->surface_get_material(i); + } + + while(mesh->get_surface_count()) { + mesh->surface_remove(0); + } + } + } + + if (!mesh.is_valid()) + mesh = Ref<Mesh>( memnew( Mesh ) ); + + + bool generate_normals=from->get_option("generate/normals"); + bool generate_tangents=from->get_option("generate/tangents"); + bool flip_faces=from->get_option("force/flip_faces"); + bool force_smooth=from->get_option("force/smooth_shading"); + bool weld_vertices=from->get_option("force/weld_vertices"); + float weld_tolerance=from->get_option("force/weld_tolerance"); + Vector<Vector3> vertices; + Vector<Vector3> normals; + Vector<Vector2> uvs; + String name; + + Ref<SurfaceTool> surf_tool = memnew( SurfaceTool) ; + surf_tool->begin(Mesh::PRIMITIVE_TRIANGLES); + if (force_smooth) + surf_tool->add_smooth_group(true); + int has_index_data=false; + + while(true) { + + + String l = f->get_line().strip_edges(); + + if (l.begins_with("v ")) { + //vertex + Vector<String> v = l.split(" ",false); + ERR_FAIL_COND_V(v.size()<4,ERR_INVALID_DATA); + Vector3 vtx; + vtx.x=v[1].to_float(); + vtx.y=v[2].to_float(); + vtx.z=v[3].to_float(); + vertices.push_back(vtx); + } else if (l.begins_with("vt ")) { + //uv + Vector<String> v = l.split(" ",false); + ERR_FAIL_COND_V(v.size()<3,ERR_INVALID_DATA); + Vector2 uv; + uv.x=v[1].to_float(); + uv.y=v[2].to_float(); + uvs.push_back(uv); + + } else if (l.begins_with("vn ")) { + //normal + Vector<String> v = l.split(" ",false); + ERR_FAIL_COND_V(v.size()<4,ERR_INVALID_DATA); + Vector3 nrm; + nrm.x=v[1].to_float(); + nrm.y=v[2].to_float(); + nrm.z=v[3].to_float(); + normals.push_back(nrm); + } if (l.begins_with("f ")) { + //vertex + + has_index_data=true; + Vector<String> v = l.split(" ",false); + ERR_FAIL_COND_V(v.size()<4,ERR_INVALID_DATA); + + //not very fast, could be sped up + + + Vector<String> face[3]; + face[0] = v[1].split("/"); + face[1] = v[2].split("/"); + ERR_FAIL_COND_V(face[0].size()==0,ERR_PARSE_ERROR); + ERR_FAIL_COND_V(face[0].size()!=face[1].size(),ERR_PARSE_ERROR); + for(int i=2;i<v.size()-1;i++) { + + face[2] = v[i+1].split("/"); + ERR_FAIL_COND_V(face[0].size()!=face[2].size(),ERR_PARSE_ERROR); + for(int j=0;j<3;j++) { + + int idx=j; + + if (!flip_faces && idx<2) { + idx=1^idx; + } + + + if (face[idx].size()==3) { + int norm = face[idx][2].to_int()-1; + ERR_FAIL_INDEX_V(norm,normals.size(),ERR_PARSE_ERROR); + surf_tool->add_normal(normals[norm]); + } + + if (face[idx].size()>=2 && face[idx][1]!=String()) { + + int uv = face[idx][1].to_int()-1; + ERR_FAIL_INDEX_V(uv,uvs.size(),ERR_PARSE_ERROR); + surf_tool->add_uv(uvs[uv]); + } + + int vtx = face[idx][0].to_int()-1; + print_line("vtx: "+itos(vtx)+"/"+itos(vertices.size())); + ERR_FAIL_INDEX_V(vtx,vertices.size(),ERR_PARSE_ERROR); + + Vector3 vertex = vertices[vtx]; + if (weld_vertices) + vertex=vertex.snapped(weld_tolerance); + surf_tool->add_vertex(vertex); + } + + face[1]=face[2]; + } + } else if (l.begins_with("s ") && !force_smooth) { //smoothing + String what = l.substr(2,l.length()).strip_edges(); + if (what=="off") + surf_tool->add_smooth_group(false); + else + surf_tool->add_smooth_group(true); + + } else if (l.begins_with("o ") || f->eof_reached()) { //new surface or done + + if (has_index_data) { + //new object/surface + if (generate_normals || force_smooth) + surf_tool->generate_normals(); + if (uvs.size() && (normals.size() || generate_normals)) + surf_tool->generate_tangents(); + + surf_tool->index(); + mesh = surf_tool->commit(mesh); + if (name=="") + name="Surface "+itos(mesh->get_surface_count()-1); + mesh->surface_set_name(mesh->get_surface_count()-1,name); + name=""; + surf_tool->clear(); + surf_tool->begin(Mesh::PRIMITIVE_TRIANGLES); + if (force_smooth) + surf_tool->add_smooth_group(true); + + has_index_data=false; + + if (f->eof_reached()) + break; + } + + if (l.begins_with("o ")) //name + name=l.substr(2,l.length()).strip_edges(); + } + } + + + from->set_source_md5(0,FileAccess::get_md5(src_path)); + from->set_editor(get_name()); + mesh->set_import_metadata(from); + + //re-apply materials if exist + for(int i=0;i<mesh->get_surface_count();i++) { + + String n = mesh->surface_get_name(i); + if (name_map.has(n)) + mesh->surface_set_material(i,name_map[n]); + } + + Error err = ResourceSaver::save(p_path,mesh); + + return err; +} + + +EditorMeshImportPlugin::EditorMeshImportPlugin(EditorNode* p_editor) { + + dialog = memnew( EditorMeshImportDialog(this)); + p_editor->get_gui_base()->add_child(dialog); +} + diff --git a/tools/editor/io_plugins/editor_mesh_import_plugin.h b/tools/editor/io_plugins/editor_mesh_import_plugin.h new file mode 100644 index 0000000000..014954685d --- /dev/null +++ b/tools/editor/io_plugins/editor_mesh_import_plugin.h @@ -0,0 +1,29 @@ +#ifndef EDITOR_MESH_IMPORT_PLUGIN_H +#define EDITOR_MESH_IMPORT_PLUGIN_H + + +#include "tools/editor/editor_import_export.h" +#include "scene/resources/font.h" + +class EditorNode; +class EditorMeshImportDialog; + +class EditorMeshImportPlugin : public EditorImportPlugin { + + OBJ_TYPE(EditorMeshImportPlugin,EditorImportPlugin); + + EditorMeshImportDialog *dialog; + + +public: + + virtual String get_name() const; + virtual String get_visible_name() const; + virtual void import_dialog(const String& p_from=""); + virtual Error import(const String& p_path, const Ref<ResourceImportMetadata>& p_from); + + + EditorMeshImportPlugin(EditorNode* p_editor); +}; + +#endif // EDITOR_MESH_IMPORT_PLUGIN_H diff --git a/tools/editor/io_plugins/editor_sample_import_plugin.cpp b/tools/editor/io_plugins/editor_sample_import_plugin.cpp index 55cba432e3..cd02156eef 100644 --- a/tools/editor/io_plugins/editor_sample_import_plugin.cpp +++ b/tools/editor/io_plugins/editor_sample_import_plugin.cpp @@ -41,6 +41,12 @@ class _EditorSampleImportOptions : public Object { OBJ_TYPE(_EditorSampleImportOptions,Object); public: + enum CompressMode { + COMPRESS_MODE_DISABLED, + COMPRESS_MODE_RAM, + COMPRESS_MODE_DISK + }; + enum CompressBitrate { COMPRESS_64, COMPRESS_96, @@ -57,7 +63,7 @@ public: bool edit_normalize; bool edit_loop; - bool compress_enable; + CompressMode compress_mode; CompressBitrate compress_bitrate; @@ -78,8 +84,8 @@ public: edit_normalize=p_value; else if (n=="edit/loop") edit_loop=p_value; - else if (n=="compress/enable") - compress_enable=p_value; + else if (n=="compress/mode") + compress_mode=CompressMode(int(p_value)); else if (n=="compress/bitrate") compress_bitrate=CompressBitrate(int(p_value)); else @@ -106,8 +112,8 @@ public: r_ret=edit_normalize; else if (n=="edit/loop") r_ret=edit_loop; - else if (n=="compress/enable") - r_ret=compress_enable; + else if (n=="compress/mode") + r_ret=compress_mode; else if (n=="compress/bitrate") r_ret=compress_bitrate; else @@ -125,7 +131,7 @@ public: p_list->push_back(PropertyInfo(Variant::BOOL,"edit/trim")); p_list->push_back(PropertyInfo(Variant::BOOL,"edit/normalize")); p_list->push_back(PropertyInfo(Variant::BOOL,"edit/loop")); - //p_list->push_back(PropertyInfo(Variant::BOOL,"compress/enable")); + p_list->push_back(PropertyInfo(Variant::INT,"compress/mode",PROPERTY_HINT_ENUM,"Disabled,RAM (Ima-ADPCM)")); //p_list->push_back(PropertyInfo(Variant::INT,"compress/bitrate",PROPERTY_HINT_ENUM,"64,96,128,192")); @@ -150,7 +156,7 @@ public: edit_normalize=true; edit_loop=false; - compress_enable=false; + compress_mode=COMPRESS_MODE_DISABLED; compress_bitrate=COMPRESS_128; } @@ -554,7 +560,11 @@ Error EditorSampleImportPlugin::import(const String& p_path, const Ref<ResourceI loop_end=len; } + int compression = from->get_option("compress/mode"); bool force_mono = from->get_option("force/mono"); + if (compression==_EditorSampleImportOptions::COMPRESS_MODE_RAM) + force_mono=true; + if (force_mono && chans==2) { Vector<float> new_data; @@ -575,19 +585,31 @@ Error EditorSampleImportPlugin::import(const String& p_path, const Ref<ResourceI DVector<uint8_t> dst_data; - dst_data.resize( data.size() * (is16?2:1)); - { - DVector<uint8_t>::Write w = dst_data.write(); + Sample::Format dst_format; - int ds=data.size(); - for(int i=0;i<ds;i++) { + if ( compression == _EditorSampleImportOptions::COMPRESS_MODE_RAM) { - if (is16) { - int16_t v = CLAMP(data[i]*32767,-32768,32767); - encode_uint16(v,&w[i*2]); - } else { - int8_t v = CLAMP(data[i]*127,-128,127); - w[i]=v; + dst_format=Sample::FORMAT_IMA_ADPCM; + + _compress_ima_adpcm(data,dst_data); + + } else { + + dst_format=is16?Sample::FORMAT_PCM16:Sample::FORMAT_PCM8; + dst_data.resize( data.size() * (is16?2:1)); + { + DVector<uint8_t>::Write w = dst_data.write(); + + int ds=data.size(); + for(int i=0;i<ds;i++) { + + if (is16) { + int16_t v = CLAMP(data[i]*32767,-32768,32767); + encode_uint16(v,&w[i*2]); + } else { + int8_t v = CLAMP(data[i]*127,-128,127); + w[i]=v; + } } } } @@ -603,7 +625,7 @@ Error EditorSampleImportPlugin::import(const String& p_path, const Ref<ResourceI target = smp; } - target->create(is16?Sample::FORMAT_PCM16:Sample::FORMAT_PCM8,chans==2?true:false,len); + target->create(dst_format,chans==2?true:false,len); target->set_data(dst_data); target->set_mix_rate(rate); target->set_loop_format(loop); @@ -621,6 +643,124 @@ Error EditorSampleImportPlugin::import(const String& p_path, const Ref<ResourceI } +void EditorSampleImportPlugin::_compress_ima_adpcm(const Vector<float>& p_data,DVector<uint8_t>& dst_data) { + + + /*p_sample_data->data = (void*)malloc(len); + xm_s8 *dataptr=(xm_s8*)p_sample_data->data;*/ + + static const int16_t _ima_adpcm_step_table[89] = { + 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, + 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, + 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, + 130, 143, 157, 173, 190, 209, 230, 253, 279, 307, + 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, + 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, + 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358, + 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, + 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767 + }; + + static const int8_t _ima_adpcm_index_table[16] = { + -1, -1, -1, -1, 2, 4, 6, 8, + -1, -1, -1, -1, 2, 4, 6, 8 + }; + + + int datalen = p_data.size(); + int datamax=datalen; + if (datalen&1) + datalen++; + + dst_data.resize(datalen/2+4); + DVector<uint8_t>::Write w = dst_data.write(); + + + int i,step_idx=0,prev=0; + uint8_t *out = w.ptr(); + //int16_t xm_prev=0; + const float *in=p_data.ptr(); + + + /* initial value is zero */ + *(out++) =0; + *(out++) =0; + /* Table index initial value */ + *(out++) =0; + /* unused */ + *(out++) =0; + + for (i=0;i<datalen;i++) { + int step,diff,vpdiff,signed_nibble,p,mask; + uint8_t nibble; + int16_t xm_sample; + + if (i>=datamax) + xm_sample=0; + else { + + + xm_sample=CLAMP(in[i]*32767.0,-32768,32767); + if (xm_sample==32767 || xm_sample==-32768) + printf("clippy!\n",xm_sample); + } + + // xm_sample=xm_sample+xm_prev; + // xm_prev=xm_sample; + + diff = (int)xm_sample - prev ; + + nibble=0 ; + step = _ima_adpcm_step_table[ step_idx ]; + vpdiff = step >> 3 ; + if (diff < 0) { + nibble=8; + diff=-diff ; + } + mask = 4 ; + while (mask) { + + if (diff >= step) { + + nibble |= mask; + diff -= step; + vpdiff += step; + } + + step >>= 1 ; + mask >>= 1 ; + }; + + if (nibble&8) + prev-=vpdiff ; + else + prev+=vpdiff ; + + if (prev > 32767) { + printf("%i,xms %i, prev %i,diff %i, vpdiff %i, clip up %i\n",i,xm_sample,prev,diff,vpdiff,prev); + prev=32767; + } else if (prev < -32768) { + printf("%i,xms %i, prev %i,diff %i, vpdiff %i, clip down %i\n",i,xm_sample,prev,diff,vpdiff,prev); + prev = -32768 ; + } + + step_idx += _ima_adpcm_index_table[nibble]; + if (step_idx< 0) + step_idx= 0 ; + else if (step_idx> 88) + step_idx= 88 ; + + + if (i&1) { + *out|=nibble<<4; + out++; + } else { + *out=nibble; + } + /*dataptr[i]=prev>>8;*/ + } + +} EditorSampleImportPlugin::EditorSampleImportPlugin(EditorNode* p_editor) { diff --git a/tools/editor/io_plugins/editor_sample_import_plugin.h b/tools/editor/io_plugins/editor_sample_import_plugin.h index a5420671e6..176dece0d5 100644 --- a/tools/editor/io_plugins/editor_sample_import_plugin.h +++ b/tools/editor/io_plugins/editor_sample_import_plugin.h @@ -40,6 +40,7 @@ class EditorSampleImportPlugin : public EditorImportPlugin { OBJ_TYPE(EditorSampleImportPlugin,EditorImportPlugin); EditorSampleImportDialog *dialog; + void _compress_ima_adpcm(const Vector<float>& p_data,DVector<uint8_t>& dst_data); public: virtual String get_name() const; 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); diff --git a/tools/editor/property_editor.cpp b/tools/editor/property_editor.cpp index 8c16207887..2087345888 100644 --- a/tools/editor/property_editor.cpp +++ b/tools/editor/property_editor.cpp @@ -261,12 +261,12 @@ bool CustomPropertyEditor::edit(Object* p_owner,const String& p_name,Variant::Ty for(int i=0;i<2;i++) { Point2 ofs(4,4); - ofs.y+=16*i; + ofs.y+=22*i; for(int j=0;j<10;j++) { - CheckButton *c=checks20[i*10+j]; + Button *c=checks20[i*10+j]; Point2 o=ofs; - o.x+=j*16; + o.x+=j*22; if (j>=5) o.x+=4; c->set_pos(o); @@ -277,7 +277,7 @@ bool CustomPropertyEditor::edit(Object* p_owner,const String& p_name,Variant::Ty } - set_size(checks20[19]->get_pos()+Size2(12,17)); + set_size(checks20[19]->get_pos()+Size2(20,25)); } else if (hint==PROPERTY_HINT_EXP_EASING) { @@ -1560,7 +1560,9 @@ CustomPropertyEditor::CustomPropertyEditor() { } for(int i=0;i<20;i++) { - checks20[i]=memnew( CheckButton ); + checks20[i]=memnew( Button ); + checks20[i]->set_toggle_mode(true); + checks20[i]->set_focus_mode(FOCUS_NONE); add_child(checks20[i]); checks20[i]->hide(); checks20[i]->connect("pressed",this,"_action_pressed",make_binds(i)); diff --git a/tools/editor/property_editor.h b/tools/editor/property_editor.h index 7ee14679c1..f13deab1ae 100644 --- a/tools/editor/property_editor.h +++ b/tools/editor/property_editor.h @@ -92,7 +92,7 @@ class CustomPropertyEditor : public Popup { ColorPicker *color_picker; TextEdit *text_edit; bool read_only; - CheckButton *checks20[20]; + Button *checks20[20]; Control *easing_draw; |