void GIProbe::_find_meshes(Node *p_at_node,Baker *p_baker){ MeshInstance *mi = p_at_node->cast_to<MeshInstance>(); if (mi && mi->get_flag(GeometryInstance::FLAG_USE_BAKED_LIGHT)) { Ref<Mesh> mesh = mi->get_mesh(); if (mesh.is_valid()) { Rect3 aabb = mesh->get_aabb(); Transform xf = get_global_transform().affine_inverse() * mi->get_global_transform(); if (Rect3(-extents,extents*2).intersects(xf.xform(aabb))) { Baker::PlotMesh pm; pm.local_xform=xf; pm.mesh=mesh; for(int i=0;i<mesh->get_surface_count();i++) { pm.instance_materials.push_back(mi->get_surface_material(i)); } pm.override_material=mi->get_material_override(); p_baker->mesh_list.push_back(pm); } } } for(int i=0;i<p_at_node->get_child_count();i++) { Node *child = p_at_node->get_child(i); if (!child->get_owner()) continue; //maybe a helper _find_meshes(child,p_baker); } }
void CollisionShape::make_convex_from_brothers() { Node *p = get_parent(); if (!p) return; for (int i = 0; i < p->get_child_count(); i++) { Node *n = p->get_child(i); MeshInstance *mi = Object::cast_to<MeshInstance>(n); if (mi) { Ref<Mesh> m = mi->get_mesh(); if (m.is_valid()) { Ref<Shape> s = m->create_convex_shape(); set_shape(s); } } } }
Node* EditorSceneImportPlugin::_fix_node(Node *p_node,Node *p_root,Map<Ref<Mesh>,Ref<Shape> > &collision_map,uint32_t p_flags,Set<Ref<ImageTexture> >& image_map) { // children first.. for(int i=0;i<p_node->get_child_count();i++) { Node *r = _fix_node(p_node->get_child(i),p_root,collision_map,p_flags,image_map); if (!r) { print_line("was erased.."); i--; //was erased } } String name = p_node->get_name(); bool isroot = p_node==p_root; if (!isroot && p_flags&SCENE_FLAG_REMOVE_NOIMP && _teststr(name,"noimp")) { memdelete(p_node); return NULL; } { List<PropertyInfo> pl; p_node->get_property_list(&pl); for(List<PropertyInfo>::Element *E=pl.front();E;E=E->next()) { if (E->get().type==Variant::OBJECT || E->get().type==Variant::ARRAY || E->get().type==Variant::DICTIONARY) { _find_resources(p_node->get(E->get().name),image_map); } } } if (p_flags&SCENE_FLAG_CREATE_BILLBOARDS && p_node->cast_to<MeshInstance>()) { MeshInstance *mi = p_node->cast_to<MeshInstance>(); bool bb=false; if ((_teststr(name,"bb"))) { bb=true; } else if (mi->get_mesh().is_valid() && (_teststr(mi->get_mesh()->get_name(),"bb"))) { bb=true; } if (bb) { mi->set_flag(GeometryInstance::FLAG_BILLBOARD,true); if (mi->get_mesh().is_valid()) { Ref<Mesh> m = mi->get_mesh(); for(int i=0;i<m->get_surface_count();i++) { Ref<FixedMaterial> fm = m->surface_get_material(i); if (fm.is_valid()) { fm->set_flag(Material::FLAG_UNSHADED,true); fm->set_flag(Material::FLAG_DOUBLE_SIDED,true); fm->set_hint(Material::HINT_NO_DEPTH_DRAW,true); fm->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA,true); } } } } } if (p_flags&SCENE_FLAG_REMOVE_NOIMP && p_node->cast_to<AnimationPlayer>()) { //remove animations referencing non-importable nodes AnimationPlayer *ap = p_node->cast_to<AnimationPlayer>(); List<StringName> anims; ap->get_animation_list(&anims); for(List<StringName>::Element *E=anims.front();E;E=E->next()) { Ref<Animation> anim=ap->get_animation(E->get()); ERR_CONTINUE(anim.is_null()); for(int i=0;i<anim->get_track_count();i++) { NodePath path = anim->track_get_path(i); for(int j=0;j<path.get_name_count();j++) { String node = path.get_name(j); if (_teststr(node,"noimp")) { anim->remove_track(i); i--; break; } } } } } if (p_flags&SCENE_FLAG_CREATE_IMPOSTORS && p_node->cast_to<MeshInstance>()) { MeshInstance *mi = p_node->cast_to<MeshInstance>(); String str; if ((_teststr(name,"imp"))) { str=name; } else if (mi->get_mesh().is_valid() && (_teststr(mi->get_mesh()->get_name(),"imp"))) { str=mi->get_mesh()->get_name(); } if (p_node->get_parent() && p_node->get_parent()->cast_to<MeshInstance>()) { MeshInstance *mi = p_node->cast_to<MeshInstance>(); MeshInstance *mip = p_node->get_parent()->cast_to<MeshInstance>(); String d=str.substr(str.find("imp")+3,str.length()); if (d!="") { if ((d[0]<'0' || d[0]>'9')) d=d.substr(1,d.length()); if (d.length() && d[0]>='0' && d[0]<='9') { float dist = d.to_double(); mi->set_flag(GeometryInstance::FLAG_BILLBOARD,true); mi->set_flag(GeometryInstance::FLAG_BILLBOARD_FIX_Y,true); mi->set_draw_range_begin(dist); mi->set_draw_range_end(100000); mip->set_draw_range_begin(0); mip->set_draw_range_end(dist); if (mi->get_mesh().is_valid()) { Ref<Mesh> m = mi->get_mesh(); for(int i=0;i<m->get_surface_count();i++) { Ref<FixedMaterial> fm = m->surface_get_material(i); if (fm.is_valid()) { fm->set_flag(Material::FLAG_UNSHADED,true); fm->set_flag(Material::FLAG_DOUBLE_SIDED,true); fm->set_hint(Material::HINT_NO_DEPTH_DRAW,true); fm->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA,true); } } } } } } } if (p_flags&SCENE_FLAG_CREATE_LODS && p_node->cast_to<MeshInstance>()) { MeshInstance *mi = p_node->cast_to<MeshInstance>(); String str; if ((_teststr(name,"lod"))) { str=name; } else if (mi->get_mesh().is_valid() && (_teststr(mi->get_mesh()->get_name(),"lod"))) { str=mi->get_mesh()->get_name(); } if (p_node->get_parent() && p_node->get_parent()->cast_to<MeshInstance>()) { MeshInstance *mi = p_node->cast_to<MeshInstance>(); MeshInstance *mip = p_node->get_parent()->cast_to<MeshInstance>(); String d=str.substr(str.find("lod")+3,str.length()); if (d!="") { if ((d[0]<'0' || d[0]>'9')) d=d.substr(1,d.length()); if (d.length() && d[0]>='0' && d[0]<='9') { float dist = d.to_double(); mi->set_draw_range_begin(dist); mi->set_draw_range_end(100000); mip->set_draw_range_begin(0); mip->set_draw_range_end(dist); /*if (mi->get_mesh().is_valid()) { Ref<Mesh> m = mi->get_mesh(); for(int i=0;i<m->get_surface_count();i++) { Ref<FixedMaterial> fm = m->surface_get_material(i); if (fm.is_valid()) { fm->set_flag(Material::FLAG_UNSHADED,true); fm->set_flag(Material::FLAG_DOUBLE_SIDED,true); fm->set_hint(Material::HINT_NO_DEPTH_DRAW,true); fm->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA,true); } } }*/ } } } } if (p_flags&SCENE_FLAG_CREATE_COLLISIONS && _teststr(name,"colonly") && p_node->cast_to<MeshInstance>()) { if (isroot) return p_node; MeshInstance *mi = p_node->cast_to<MeshInstance>(); Node * col = mi->create_trimesh_collision_node(); ERR_FAIL_COND_V(!col,NULL); col->set_name(_fixstr(name,"colonly")); col->cast_to<Spatial>()->set_transform(mi->get_transform()); p_node->replace_by(col); memdelete(p_node); p_node=col; } else if (p_flags&SCENE_FLAG_CREATE_COLLISIONS &&_teststr(name,"col") && p_node->cast_to<MeshInstance>()) { MeshInstance *mi = p_node->cast_to<MeshInstance>(); mi->set_name(_fixstr(name,"col")); mi->create_trimesh_collision(); } else if (p_flags&SCENE_FLAG_CREATE_ROOMS && _teststr(name,"room") && p_node->cast_to<MeshInstance>()) { if (isroot) return p_node; MeshInstance *mi = p_node->cast_to<MeshInstance>(); DVector<Face3> faces = mi->get_faces(VisualInstance::FACES_SOLID); BSP_Tree bsptree(faces); Ref<RoomBounds> area = memnew( RoomBounds ); area->set_bounds(faces); area->set_geometry_hint(faces); Room * room = memnew( Room ); room->set_name(_fixstr(name,"room")); room->set_transform(mi->get_transform()); room->set_room(area); p_node->replace_by(room); memdelete(p_node); p_node=room; } else if (p_flags&SCENE_FLAG_CREATE_ROOMS &&_teststr(name,"room")) { if (isroot) return p_node; Spatial *dummy = p_node->cast_to<Spatial>(); ERR_FAIL_COND_V(!dummy,NULL); Room * room = memnew( Room ); room->set_name(_fixstr(name,"room")); room->set_transform(dummy->get_transform()); p_node->replace_by(room); memdelete(p_node); p_node=room; room->compute_room_from_subtree(); } else if (p_flags&SCENE_FLAG_CREATE_PORTALS &&_teststr(name,"portal") && p_node->cast_to<MeshInstance>()) { if (isroot) return p_node; MeshInstance *mi = p_node->cast_to<MeshInstance>(); DVector<Face3> faces = mi->get_faces(VisualInstance::FACES_SOLID); ERR_FAIL_COND_V(faces.size()==0,NULL); //step 1 compute the plane Set<Vector3> points; Plane plane; Vector3 center; for(int i=0;i<faces.size();i++) { Face3 f = faces.get(i); Plane p = f.get_plane(); plane.normal+=p.normal; plane.d+=p.d; for(int i=0;i<3;i++) { Vector3 v = f.vertex[i].snapped(0.01); if (!points.has(v)) { points.insert(v); center+=v; } } } plane.normal.normalize(); plane.d/=faces.size(); center/=points.size(); //step 2, create points Transform t; t.basis.from_z(plane.normal); t.basis.transpose(); t.origin=center; Vector<Point2> portal_points; for(Set<Vector3>::Element *E=points.front();E;E=E->next()) { Vector3 local = t.xform_inv(E->get()); portal_points.push_back(Point2(local.x,local.y)); } // step 3 bubbly sort points int swaps=0; do { swaps=0; for(int i=0;i<portal_points.size()-1;i++) { float a = portal_points[i].atan2(); float b = portal_points[i+1].atan2(); if (a>b) { SWAP( portal_points[i], portal_points[i+1] ); swaps++; } } } while(swaps); Portal *portal = memnew( Portal ); portal->set_shape(portal_points); portal->set_transform( mi->get_transform() * t); p_node->replace_by(portal); memdelete(p_node); p_node=portal; } else if (p_node->cast_to<MeshInstance>()) { //last attempt, maybe collision insde the mesh data MeshInstance *mi = p_node->cast_to<MeshInstance>(); Ref<Mesh> mesh = mi->get_mesh(); if (!mesh.is_null()) { if (p_flags&SCENE_FLAG_CREATE_COLLISIONS && _teststr(mesh->get_name(),"col")) { mesh->set_name( _fixstr(mesh->get_name(),"col") ); Ref<Shape> shape; if (collision_map.has(mesh)) { shape = collision_map[mesh]; } else { shape = mesh->create_trimesh_shape(); if (!shape.is_null()) collision_map[mesh]=shape; } if (!shape.is_null()) { #if 0 StaticBody* static_body = memnew( StaticBody ); ERR_FAIL_COND_V(!static_body,NULL); static_body->set_name( String(mesh->get_name()) + "_col" ); shape->set_name(static_body->get_name()); static_body->add_shape(shape); mi->add_child(static_body); if (mi->get_owner()) static_body->set_owner( mi->get_owner() ); #endif } } for(int i=0;i<mesh->get_surface_count();i++) { Ref<FixedMaterial> fm = mesh->surface_get_material(i); if (fm.is_valid()) { String name = fm->get_name(); if (_teststr(name,"alpha")) { fm->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA,true); name=_fixstr(name,"alpha"); } if (_teststr(name,"vcol")) { fm->set_fixed_flag(FixedMaterial::FLAG_USE_COLOR_ARRAY,true); name=_fixstr(name,"vcol"); } fm->set_name(name); } } } } return p_node; }
void MeshLibraryEditor::_import_scene(Node *p_scene, Ref<MeshLibrary> p_library, bool p_merge) { if (!p_merge) p_library->clear(); for(int i=0;i<p_scene->get_child_count();i++) { Node *child = p_scene->get_child(i); if (!child->cast_to<MeshInstance>()) { if (child->get_child_count()>0) { child=child->get_child(0); if (!child->cast_to<MeshInstance>()) { continue; } } else continue; } MeshInstance *mi = child->cast_to<MeshInstance>(); Ref<Mesh> mesh=mi->get_mesh(); if (mesh.is_null()) continue; int id = p_library->find_item_name(mi->get_name()); if (id<0) { id=p_library->get_last_unused_item_id(); p_library->create_item(id); p_library->set_item_name(id,mi->get_name()); } p_library->set_item_mesh(id,mesh); Ref<Shape> collision; for(int j=0;j<mi->get_child_count();j++) { #if 1 Node *child2 = mi->get_child(j); if (!child2->cast_to<StaticBody>()) continue; StaticBody *sb = child2->cast_to<StaticBody>(); if (sb->get_shape_count()==0) continue; collision=sb->get_shape(0); if (!collision.is_null()) break; #endif } if (!collision.is_null()) { p_library->set_item_shape(id,collision); } } //generate previews! if (1) { Vector<int> ids = p_library->get_item_list(); RID vp = VS::get_singleton()->viewport_create(); VS::ViewportRect vr; vr.x=0; vr.y=0; vr.width=EditorSettings::get_singleton()->get("grid_map/preview_size"); vr.height=EditorSettings::get_singleton()->get("grid_map/preview_size"); VS::get_singleton()->viewport_set_rect(vp,vr); VS::get_singleton()->viewport_set_as_render_target(vp,true); VS::get_singleton()->viewport_set_render_target_update_mode(vp,VS::RENDER_TARGET_UPDATE_ALWAYS); RID scen = VS::get_singleton()->scenario_create(); VS::get_singleton()->viewport_set_scenario(vp,scen); RID cam = VS::get_singleton()->camera_create(); VS::get_singleton()->camera_set_transform(cam, Transform() ); VS::get_singleton()->viewport_attach_camera(vp,cam); RID light = VS::get_singleton()->light_create(VS::LIGHT_DIRECTIONAL); RID lightinst = VS::get_singleton()->instance_create2(light,scen); VS::get_singleton()->camera_set_orthogonal(cam,1.0,0.01,1000.0); EditorProgress ep("mlib","Creating Mesh Library",ids.size()); for(int i=0;i<ids.size();i++) { int id=ids[i]; Ref<Mesh> mesh = p_library->get_item_mesh(id); if (!mesh.is_valid()) continue; AABB aabb= mesh->get_aabb(); print_line("aabb: "+aabb); Vector3 ofs = aabb.pos + aabb.size*0.5; aabb.pos-=ofs; Transform xform; xform.basis=Matrix3().rotated(Vector3(0,1,0),Math_PI*0.25); xform.basis = Matrix3().rotated(Vector3(1,0,0),-Math_PI*0.25)*xform.basis; AABB rot_aabb = xform.xform(aabb); print_line("rot_aabb: "+rot_aabb); float m = MAX(rot_aabb.size.x,rot_aabb.size.y)*0.5; if (m==0) continue; m=1.0/m; m*=0.5; print_line("scale: "+rtos(m)); xform.basis.scale(Vector3(m,m,m)); xform.origin=-xform.basis.xform(ofs); //-ofs*m; xform.origin.z-=rot_aabb.size.z*2; RID inst = VS::get_singleton()->instance_create2(mesh->get_rid(),scen); VS::get_singleton()->instance_set_transform(inst,xform); ep.step("Thumbnail..",i); VS::get_singleton()->viewport_queue_screen_capture(vp); Main::iteration(); Image img = VS::get_singleton()->viewport_get_screen_capture(vp); ERR_CONTINUE(img.empty()); Ref<ImageTexture> it( memnew( ImageTexture )); it->create_from_image(img); p_library->set_item_preview(id,it); // print_line("loaded image, size: "+rtos(m)+" dist: "+rtos(dist)+" empty?"+itos(img.empty())+" w: "+itos(it->get_width())+" h: "+itos(it->get_height())); VS::get_singleton()->free(inst); } VS::get_singleton()->free(lightinst); VS::get_singleton()->free(light); VS::get_singleton()->free(vp); VS::get_singleton()->free(cam); VS::get_singleton()->free(scen); } }
void MeshInstanceEditor::_menu_option(int p_option) { Ref<Mesh> mesh = node->get_mesh(); if (mesh.is_null()) { err_dialog->set_text(TTR("Mesh is empty!")); err_dialog->popup_centered_minsize(); return; } switch (p_option) { case MENU_OPTION_CREATE_STATIC_TRIMESH_BODY: case MENU_OPTION_CREATE_STATIC_CONVEX_BODY: { bool trimesh_shape = (p_option == MENU_OPTION_CREATE_STATIC_TRIMESH_BODY); EditorSelection *editor_selection = EditorNode::get_singleton()->get_editor_selection(); UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); List<Node *> selection = editor_selection->get_selected_node_list(); if (selection.empty()) { Ref<Shape> shape = trimesh_shape ? mesh->create_trimesh_shape() : mesh->create_convex_shape(); if (shape.is_null()) return; CollisionShape *cshape = memnew(CollisionShape); cshape->set_shape(shape); StaticBody *body = memnew(StaticBody); body->add_child(cshape); Node *owner = node == get_tree()->get_edited_scene_root() ? node : node->get_owner(); if (trimesh_shape) ur->create_action(TTR("Create Static Trimesh Body")); else ur->create_action(TTR("Create Static Convex Body")); ur->add_do_method(node, "add_child", body); ur->add_do_method(body, "set_owner", owner); ur->add_do_method(cshape, "set_owner", owner); ur->add_do_reference(body); ur->add_undo_method(node, "remove_child", body); ur->commit_action(); return; } if (trimesh_shape) ur->create_action(TTR("Create Static Trimesh Body")); else ur->create_action(TTR("Create Static Convex Body")); for (List<Node *>::Element *E = selection.front(); E; E = E->next()) { MeshInstance *instance = E->get()->cast_to<MeshInstance>(); if (!instance) continue; Ref<Mesh> m = instance->get_mesh(); if (m.is_null()) continue; Ref<Shape> shape = trimesh_shape ? m->create_trimesh_shape() : m->create_convex_shape(); if (shape.is_null()) continue; CollisionShape *cshape = memnew(CollisionShape); cshape->set_shape(shape); StaticBody *body = memnew(StaticBody); body->add_child(cshape); Node *owner = instance == get_tree()->get_edited_scene_root() ? instance : instance->get_owner(); ur->add_do_method(instance, "add_child", body); ur->add_do_method(body, "set_owner", owner); ur->add_do_method(cshape, "set_owner", owner); ur->add_do_reference(body); ur->add_undo_method(instance, "remove_child", body); } ur->commit_action(); } break; case MENU_OPTION_CREATE_TRIMESH_COLLISION_SHAPE: case MENU_OPTION_CREATE_CONVEX_COLLISION_SHAPE: { if (node == get_tree()->get_edited_scene_root()) { err_dialog->set_text(TTR("This doesn't work on scene root!")); err_dialog->popup_centered_minsize(); return; } bool trimesh_shape = (p_option == MENU_OPTION_CREATE_TRIMESH_COLLISION_SHAPE); Ref<Shape> shape = trimesh_shape ? mesh->create_trimesh_shape() : mesh->create_convex_shape(); if (shape.is_null()) return; CollisionShape *cshape = memnew(CollisionShape); cshape->set_shape(shape); Node *owner = node->get_owner(); UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); if (trimesh_shape) ur->create_action(TTR("Create Trimesh Shape")); else ur->create_action(TTR("Create Convex Shape")); ur->add_do_method(node->get_parent(), "add_child", cshape); ur->add_do_method(node->get_parent(), "move_child", cshape, node->get_index() + 1); ur->add_do_method(cshape, "set_owner", owner); ur->add_do_reference(cshape); ur->add_undo_method(node->get_parent(), "remove_child", cshape); ur->commit_action(); } break; case MENU_OPTION_CREATE_NAVMESH: { Ref<NavigationMesh> nmesh = memnew(NavigationMesh); if (nmesh.is_null()) return; nmesh->create_from_mesh(mesh); NavigationMeshInstance *nmi = memnew(NavigationMeshInstance); nmi->set_navigation_mesh(nmesh); Node *owner = node == get_tree()->get_edited_scene_root() ? node : node->get_owner(); UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); ur->create_action(TTR("Create Navigation Mesh")); ur->add_do_method(node, "add_child", nmi); ur->add_do_method(nmi, "set_owner", owner); ur->add_do_reference(nmi); ur->add_undo_method(node, "remove_child", nmi); ur->commit_action(); } break; case MENU_OPTION_CREATE_OUTLINE_MESH: { outline_dialog->popup_centered(Vector2(200, 90)); } break; } }
void BakedLightmap::_find_meshes_and_lights(Node *p_at_node, List<PlotMesh> &plot_meshes, List<PlotLight> &plot_lights) { MeshInstance *mi = Object::cast_to<MeshInstance>(p_at_node); if (mi && mi->get_flag(GeometryInstance::FLAG_USE_BAKED_LIGHT) && mi->is_visible_in_tree()) { Ref<Mesh> mesh = mi->get_mesh(); if (mesh.is_valid()) { bool all_have_uv2 = true; for (int i = 0; i < mesh->get_surface_count(); i++) { if (!(mesh->surface_get_format(i) & Mesh::ARRAY_FORMAT_TEX_UV2)) { all_have_uv2 = false; break; } } if (all_have_uv2 && mesh->get_lightmap_size_hint() != Size2()) { //READY TO BAKE! size hint could be computed if not found, actually.. AABB aabb = mesh->get_aabb(); Transform xf = get_global_transform().affine_inverse() * mi->get_global_transform(); if (AABB(-extents, extents * 2).intersects(xf.xform(aabb))) { PlotMesh pm; pm.local_xform = xf; pm.mesh = mesh; pm.path = get_path_to(mi); pm.instance_idx = -1; for (int i = 0; i < mesh->get_surface_count(); i++) { pm.instance_materials.push_back(mi->get_surface_material(i)); } pm.override_material = mi->get_material_override(); plot_meshes.push_back(pm); } } } } Spatial *s = Object::cast_to<Spatial>(p_at_node); if (!mi && s) { Array meshes = p_at_node->call("get_bake_meshes"); if (meshes.size() && (meshes.size() & 1) == 0) { Transform xf = get_global_transform().affine_inverse() * s->get_global_transform(); for (int i = 0; i < meshes.size(); i += 2) { PlotMesh pm; Transform mesh_xf = meshes[i + 1]; pm.local_xform = xf * mesh_xf; pm.mesh = meshes[i]; pm.instance_idx = i / 2; if (!pm.mesh.is_valid()) continue; pm.path = get_path_to(s); plot_meshes.push_back(pm); } } } Light *light = Object::cast_to<Light>(p_at_node); if (light && light->get_bake_mode() != Light::BAKE_DISABLED) { PlotLight pl; Transform xf = get_global_transform().affine_inverse() * light->get_global_transform(); pl.local_xform = xf; pl.light = light; plot_lights.push_back(pl); } for (int i = 0; i < p_at_node->get_child_count(); i++) { Node *child = p_at_node->get_child(i); if (!child->get_owner()) continue; //maybe a helper _find_meshes_and_lights(child, plot_meshes, plot_lights); } }