diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 7a0e21b620b..9de441c2bb1 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -1111,7 +1111,16 @@ void RasterizerSceneGLES3::_setup_geometry(RenderList::Element *e) { case VS::INSTANCE_MESH: { RasterizerStorageGLES3::Surface *s = static_cast(e->geometry); - glBindVertexArray(s->array_id); // everything is so easy nowadays + + if (s->morph_targets.size() && e->instance->morph_values.size()) { + //blend shapes, use transform feedback + storage->mesh_render_blend_shapes(s,e->instance->morph_values.ptr()); + //rebind shader + state.scene_shader.bind(); + } else { + + glBindVertexArray(s->array_id); // everything is so easy nowadays + } } break; diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index a618953b860..559f733e4dd 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -2274,8 +2274,8 @@ void RasterizerStorageGLES3::_update_material(Material* material) { material->can_cast_shadow_cache=can_cast_shadow; material->is_animated_cache=is_animated; - for(Map::Element *E=material->instantiable_owners.front();E;E=E->next()) { - E->key()->instance_material_change_notify(); + for(Map::Element *E=material->geometry_owners.front();E;E=E->next()) { + E->key()->material_changed_notify(); } for(Map::Element *E=material->instance_owners.front();E;E=E->next()) { @@ -2379,32 +2379,32 @@ void RasterizerStorageGLES3::_update_material(Material* material) { } -void RasterizerStorageGLES3::_material_add_instantiable(RID p_material,Instantiable *p_instantiable) { +void RasterizerStorageGLES3::_material_add_geometry(RID p_material,Geometry *p_geometry) { Material * material = material_owner.getornull(p_material); ERR_FAIL_COND(!material); - Map::Element *I = material->instantiable_owners.find(p_instantiable); + Map::Element *I = material->geometry_owners.find(p_geometry); if (I) { I->get()++; } else { - material->instantiable_owners[p_instantiable]=1; + material->geometry_owners[p_geometry]=1; } } -void RasterizerStorageGLES3::_material_remove_instantiable(RID p_material,Instantiable *p_instantiable) { +void RasterizerStorageGLES3::_material_remove_geometry(RID p_material,Geometry *p_geometry) { Material * material = material_owner.getornull(p_material); ERR_FAIL_COND(!material); - Map::Element *I = material->instantiable_owners.find(p_instantiable); + Map::Element *I = material->geometry_owners.find(p_geometry); ERR_FAIL_COND(!I); I->get()--; if (I->get()==0) { - material->instantiable_owners.erase(I); + material->geometry_owners.erase(I); } } @@ -2446,18 +2446,15 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh,uint32_t p_format,VS::P bool has_morph = p_blend_shapes.size(); - Surface::Attrib attribs[VS::ARRAY_MAX],morph_attribs[VS::ARRAY_MAX]; + Surface::Attrib attribs[VS::ARRAY_MAX]; int stride=0; - int morph_stride=0; for(int i=0;iattribs[i]=attribs[i]; - surface->morph_attribs[i]=morph_attribs[i]; } { @@ -2763,12 +2701,11 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh,uint32_t p_format,VS::P glGenVertexArrays(1,&surface->array_id); glBindVertexArray(surface->array_id); glBindBuffer(GL_ARRAY_BUFFER,surface->vertex_id); - } else { + } else if (i==1) { //for instancing draw (can be changed and no one cares) glGenVertexArrays(1,&surface->instancing_array_id); glBindVertexArray(surface->instancing_array_id); glBindBuffer(GL_ARRAY_BUFFER,surface->vertex_id); - } @@ -2816,17 +2753,17 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh,uint32_t p_format,VS::P glBindVertexArray(mt.array_id); glBindBuffer(GL_ARRAY_BUFFER,mt.vertex_id); - for(int i=0;isurfaces[p_surface]->material.is_valid()) { - _material_remove_instantiable(mesh->surfaces[p_surface]->material,mesh); + _material_remove_geometry(mesh->surfaces[p_surface]->material,mesh->surfaces[p_surface]); } mesh->surfaces[p_surface]->material=p_material; if (mesh->surfaces[p_surface]->material.is_valid()) { - _material_add_instantiable(mesh->surfaces[p_surface]->material,mesh); + _material_add_geometry(mesh->surfaces[p_surface]->material,mesh->surfaces[p_surface]); } mesh->instance_material_change_notify(); @@ -3067,7 +3004,7 @@ void RasterizerStorageGLES3::mesh_remove_surface(RID p_mesh, int p_surface){ Surface *surface = mesh->surfaces[p_surface]; if (surface->material.is_valid()) { - _material_remove_instantiable(surface->material,mesh); + _material_remove_geometry(surface->material,mesh->surfaces[p_surface]); } glDeleteBuffers(1,&surface->vertex_id); @@ -3241,6 +3178,227 @@ void RasterizerStorageGLES3::mesh_clear(RID p_mesh){ } } +void RasterizerStorageGLES3::mesh_render_blend_shapes(Surface *s, float *p_weights) { + + glBindVertexArray(s->array_id); + + BlendShapeShaderGLES3::Conditionals cond[VS::ARRAY_MAX-1]={ + BlendShapeShaderGLES3::ENABLE_NORMAL, //will be ignored + BlendShapeShaderGLES3::ENABLE_NORMAL, + BlendShapeShaderGLES3::ENABLE_TANGENT, + BlendShapeShaderGLES3::ENABLE_COLOR, + BlendShapeShaderGLES3::ENABLE_UV, + BlendShapeShaderGLES3::ENABLE_UV2, + BlendShapeShaderGLES3::ENABLE_SKELETON, + BlendShapeShaderGLES3::ENABLE_SKELETON, + }; + + int stride=0; + + if (s->format&VS::ARRAY_FLAG_USE_2D_VERTICES) { + stride=2*4; + } else { + stride=3*4; + } + + static const int sizes[VS::ARRAY_MAX-1]={ + 3*4, + 3*4, + 4*4, + 4*4, + 2*4, + 2*4, + 4*4, + 4*4 + }; + + for(int i=1;iformat&(1<format&(1<morph_targets.size(); + + if (s->mesh->morph_target_mode==VS::MORPH_MODE_NORMALIZED) { + + for(int i=0;iformat&VS::ARRAY_FLAG_USE_2D_VERTICES); //use 2D vertices if needed + + shaders.blend_shapes.bind(); + + shaders.blend_shapes.set_uniform(BlendShapeShaderGLES3::BLEND_AMOUNT,base_weight); + glEnable(GL_RASTERIZER_DISCARD); + + glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, resources.transform_feedback_buffers[0]); + glBeginTransformFeedback(GL_POINTS); + glDrawArrays(GL_POINTS,0,s->array_len); + glEndTransformFeedback(); + + + shaders.blend_shapes.set_conditional(BlendShapeShaderGLES3::ENABLE_BLEND,true); //first pass does not blend + shaders.blend_shapes.bind(); + + for(int ti=0;timorph_targets[ti].array_id); + glBindBuffer(GL_ARRAY_BUFFER, resources.transform_feedback_buffers[0]); + glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, resources.transform_feedback_buffers[1]); + + shaders.blend_shapes.set_uniform(BlendShapeShaderGLES3::BLEND_AMOUNT,weight); + + int ofs=0; + for(int i=0;iformat&(1<format&VS::ARRAY_FLAG_USE_2D_VERTICES) { + glVertexAttribPointer(i+8,2,GL_FLOAT,GL_FALSE,stride,((uint8_t*)0)+ofs); + ofs+=2*4; + } else { + glVertexAttribPointer(i+8,3,GL_FLOAT,GL_FALSE,stride,((uint8_t*)0)+ofs); + ofs+=3*4; + } + } break; + case VS::ARRAY_NORMAL: { + glVertexAttribPointer(i+8,3,GL_FLOAT,GL_FALSE,stride,((uint8_t*)0)+ofs); + ofs+=3*4; + } break; + case VS::ARRAY_TANGENT: { + glVertexAttribPointer(i+8,4,GL_FLOAT,GL_FALSE,stride,((uint8_t*)0)+ofs); + ofs+=4*4; + + } break; + case VS::ARRAY_COLOR: { + glVertexAttribPointer(i+8,4,GL_FLOAT,GL_FALSE,stride,((uint8_t*)0)+ofs); + ofs+=4*4; + + } break; + case VS::ARRAY_TEX_UV: { + glVertexAttribPointer(i+8,2,GL_FLOAT,GL_FALSE,stride,((uint8_t*)0)+ofs); + ofs+=2*4; + + } break; + case VS::ARRAY_TEX_UV2: { + glVertexAttribPointer(i+8,2,GL_FLOAT,GL_FALSE,stride,((uint8_t*)0)+ofs); + ofs+=2*4; + + } break; + case VS::ARRAY_BONES: { + glVertexAttribIPointer(i+8,4,GL_UNSIGNED_INT,stride,((uint8_t*)0)+ofs); + ofs+=4*4; + + } break; + case VS::ARRAY_WEIGHTS: { + glVertexAttribPointer(i+8,4,GL_FLOAT,GL_FALSE,stride,((uint8_t*)0)+ofs); + ofs+=4*4; + + } break; + } + + } else { + glDisableVertexAttribArray(i+8); + } + } + + glBeginTransformFeedback(GL_POINTS); + glDrawArrays(GL_POINTS,0,s->array_len); + glEndTransformFeedback(); + + + SWAP(resources.transform_feedback_buffers[0],resources.transform_feedback_buffers[1]); + + } + + glDisable(GL_RASTERIZER_DISCARD); + glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0); + + + glBindVertexArray(resources.transform_feedback_array); + glBindBuffer(GL_ARRAY_BUFFER, resources.transform_feedback_buffers[0]); + + int ofs=0; + for(int i=0;iformat&(1<format&VS::ARRAY_FLAG_USE_2D_VERTICES) { + glVertexAttribPointer(i,2,GL_FLOAT,GL_FALSE,stride,((uint8_t*)0)+ofs); + ofs+=2*4; + } else { + glVertexAttribPointer(i,3,GL_FLOAT,GL_FALSE,stride,((uint8_t*)0)+ofs); + ofs+=3*4; + } + } break; + case VS::ARRAY_NORMAL: { + glVertexAttribPointer(i,3,GL_FLOAT,GL_FALSE,stride,((uint8_t*)0)+ofs); + ofs+=3*4; + } break; + case VS::ARRAY_TANGENT: { + glVertexAttribPointer(i,4,GL_FLOAT,GL_FALSE,stride,((uint8_t*)0)+ofs); + ofs+=4*4; + + } break; + case VS::ARRAY_COLOR: { + glVertexAttribPointer(i,4,GL_FLOAT,GL_FALSE,stride,((uint8_t*)0)+ofs); + ofs+=4*4; + + } break; + case VS::ARRAY_TEX_UV: { + glVertexAttribPointer(i,2,GL_FLOAT,GL_FALSE,stride,((uint8_t*)0)+ofs); + ofs+=2*4; + + } break; + case VS::ARRAY_TEX_UV2: { + glVertexAttribPointer(i,2,GL_FLOAT,GL_FALSE,stride,((uint8_t*)0)+ofs); + ofs+=2*4; + + } break; + case VS::ARRAY_BONES: { + glVertexAttribIPointer(i,4,GL_UNSIGNED_INT,stride,((uint8_t*)0)+ofs); + ofs+=4*4; + + } break; + case VS::ARRAY_WEIGHTS: { + glVertexAttribPointer(i,4,GL_FLOAT,GL_FALSE,stride,((uint8_t*)0)+ofs); + ofs+=4*4; + + } break; + } + + } else { + glDisableVertexAttribArray(i); + } + } + + if (s->index_array_len) { + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,s->index_id); + } + +} + /* MULTIMESH API */ @@ -3896,7 +4054,6 @@ void RasterizerStorageGLES3::skeleton_allocate(RID p_skeleton,int p_bones,bool p skeleton_update_list.add(&skeleton->update_list); } - skeleton->instance_change_notify(); } @@ -4017,7 +4174,10 @@ void RasterizerStorageGLES3::update_dirty_skeletons() { glBufferSubData(GL_UNIFORM_BUFFER,0,skeleton->bones.size()*sizeof(float),skeleton->bones.ptr()); glBindBuffer(GL_UNIFORM_BUFFER, 0); } - skeleton->instance_change_notify(); + + for (Set::Element *E=skeleton->instances.front();E;E=E->next()) { + E->get()->base_changed(); + } skeleton_update_list.remove(skeleton_update_list.first()); } @@ -4505,6 +4665,23 @@ void RasterizerStorageGLES3::portal_set_disabled_color(RID p_portal, const Color } +void RasterizerStorageGLES3::instance_add_skeleton(RID p_skeleton,RasterizerScene::InstanceBase *p_instance) { + + Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); + ERR_FAIL_COND(!skeleton); + + skeleton->instances.insert(p_instance); +} + +void RasterizerStorageGLES3::instance_remove_skeleton(RID p_skeleton,RasterizerScene::InstanceBase *p_instance) { + + Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); + ERR_FAIL_COND(!skeleton); + + skeleton->instances.erase(p_instance); +} + + void RasterizerStorageGLES3::instance_add_dependency(RID p_base,RasterizerScene::InstanceBase *p_instance) { Instantiable *inst=NULL; @@ -4530,9 +4707,6 @@ void RasterizerStorageGLES3::instance_add_dependency(RID p_base,RasterizerScene: ERR_FAIL_COND(!inst); } break; default: { - if (skeleton_owner.owns(p_base)) { - inst=skeleton_owner.getornull(p_base); - } if (!inst) { ERR_FAIL(); } @@ -4550,7 +4724,6 @@ void RasterizerStorageGLES3::instance_remove_dependency(RID p_base,RasterizerSce case VS::INSTANCE_MESH: { inst = mesh_owner.getornull(p_base); ERR_FAIL_COND(!inst); - } break; case VS::INSTANCE_MULTIMESH: { inst = multimesh_owner.getornull(p_base); @@ -4569,9 +4742,7 @@ void RasterizerStorageGLES3::instance_remove_dependency(RID p_base,RasterizerSce ERR_FAIL_COND(!inst); } break; default: { - if (skeleton_owner.owns(p_base)) { - inst=skeleton_owner.getornull(p_base); - } + if (!inst) { ERR_FAIL(); } @@ -5134,6 +5305,26 @@ bool RasterizerStorageGLES3::free(RID p_rid){ glDeleteBuffers(1,&material->ubo_id); } + //remove from owners + for (Map::Element *E=material->geometry_owners.front();E;E=E->next()) { + + Geometry *g = E->key(); + g->material=RID(); + } + for (Map::Element *E=material->instance_owners.front();E;E=E->next()) { + RasterizerScene::InstanceBase*ins=E->key(); + if (ins->material_override==p_rid) { + ins->material_override=RID(); + } + + for(int i=0;imaterials.size();i++) { + if (ins->materials[i]==p_rid) { + ins->materials[i]=RID(); + } + } + + } + material_owner.free(p_rid); memdelete(material); @@ -5144,6 +5335,11 @@ bool RasterizerStorageGLES3::free(RID p_rid){ if (skeleton->update_list.in_list()) { skeleton_update_list.remove(&skeleton->update_list); } + + for (Set::Element *E=skeleton->instances.front();E;E=E->next()) { + E->get()->skeleton=RID(); + } + skeleton_allocate(p_rid,0,false); skeleton_owner.free(p_rid); memdelete(skeleton); @@ -5370,6 +5566,23 @@ void RasterizerStorageGLES3::initialize() { glBindBuffer(GL_ARRAY_BUFFER,0); //unbind } + + { + //transform feedback buffers + uint32_t xf_feedback_size = GLOBAL_DEF("rendering/gles3/blend_shape_max_buffer_size_kb",4096); + for(int i=0;i<2;i++) { + + glGenBuffers(1,&resources.transform_feedback_buffers[i]); + glBindBuffer(GL_ARRAY_BUFFER,resources.transform_feedback_buffers[i]); + glBufferData(GL_ARRAY_BUFFER,xf_feedback_size*1024,NULL,GL_STREAM_DRAW); + } + + shaders.blend_shapes.init();; + + glGenVertexArrays(1,&resources.transform_feedback_array); + + } + shaders.cubemap_filter.init(); glEnable(_EXT_TEXTURE_CUBE_MAP_SEAMLESS); diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index 623962bf611..361e738af52 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -6,6 +6,7 @@ #include "shader_gles3.h" #include "shaders/copy.glsl.h" #include "shaders/canvas.glsl.h" +#include "shaders/blend_shape.glsl.h" #include "shaders/cubemap_filter.glsl.h" #include "self_list.h" #include "shader_compiler_gles3.h" @@ -65,6 +66,8 @@ public: CubemapFilterShaderGLES3 cubemap_filter; + BlendShapeShaderGLES3 blend_shapes; + ShaderCompilerGLES3::IdentifierActions actions_canvas; ShaderCompilerGLES3::IdentifierActions actions_scene; } shaders; @@ -79,6 +82,9 @@ public: GLuint quadie; GLuint quadie_array; + GLuint transform_feedback_buffers[2]; + GLuint transform_feedback_array; + } resources; struct Info { @@ -133,8 +139,33 @@ public: } }; + struct GeometryOwner : public Instantiable { + + virtual ~GeometryOwner() {} + }; + struct Geometry : Instantiable { + + enum Type { + GEOMETRY_INVALID, + GEOMETRY_SURFACE, + GEOMETRY_IMMEDIATE, + GEOMETRY_MULTISURFACE, + }; + Type type; + RID material; + uint64_t last_pass; + uint32_t index; + + virtual void material_changed_notify() {} + + Geometry() { + last_pass=0; + index=0; + } + + }; @@ -384,7 +415,7 @@ public: uint32_t index; uint64_t last_pass; - Map instantiable_owners; + Map geometry_owners; Map instance_owners; bool can_cast_shadow_cache; @@ -404,8 +435,8 @@ public: mutable SelfList::List _material_dirty_list; void _material_make_dirty(Material *p_material) const; - void _material_add_instantiable(RID p_material,Instantiable *p_instantiable); - void _material_remove_instantiable(RID p_material, Instantiable *p_instantiable); + void _material_add_geometry(RID p_material,Geometry *p_instantiable); + void _material_remove_geometry(RID p_material, Geometry *p_instantiable); mutable RID_Owner material_owner; @@ -433,31 +464,9 @@ public: /* MESH API */ - struct Geometry : Instantiable { - enum Type { - GEOMETRY_INVALID, - GEOMETRY_SURFACE, - GEOMETRY_IMMEDIATE, - GEOMETRY_MULTISURFACE, - }; - Type type; - RID material; - uint64_t last_pass; - uint32_t index; - Geometry() { - last_pass=0; - index=0; - } - - }; - - struct GeometryOwner : public Instantiable { - - virtual ~GeometryOwner() {} - }; struct Mesh; struct Surface : public Geometry { @@ -475,7 +484,7 @@ public: }; Attrib attribs[VS::ARRAY_MAX]; - Attrib morph_attribs[VS::ARRAY_MAX]; + Mesh *mesh; @@ -512,6 +521,10 @@ public: bool active; + virtual void material_changed_notify() { + mesh->instance_material_change_notify(); + } + Surface() { array_byte_size=0; @@ -590,6 +603,8 @@ public: virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton) const; virtual void mesh_clear(RID p_mesh); + void mesh_render_blend_shapes(Surface *s, float *p_weights); + /* MULTIMESH API */ struct MultiMesh : public GeometryOwner { @@ -699,12 +714,13 @@ public: /* SKELETON API */ - struct Skeleton : Instantiable { + struct Skeleton : RID_Data { int size; bool use_2d; Vector bones; //4x3 or 4x2 depending on what is needed GLuint ubo; SelfList update_list; + Set instances; //instances using skeleton Skeleton() : update_list(this) { size=0; @@ -843,6 +859,8 @@ public: virtual void portal_set_disable_distance(RID p_portal, float p_distance); virtual void portal_set_disabled_color(RID p_portal, const Color& p_color); + virtual void instance_add_skeleton(RID p_skeleton,RasterizerScene::InstanceBase *p_instance); + virtual void instance_remove_skeleton(RID p_skeleton,RasterizerScene::InstanceBase *p_instance); virtual void instance_add_dependency(RID p_base,RasterizerScene::InstanceBase *p_instance); virtual void instance_remove_dependency(RID p_base,RasterizerScene::InstanceBase *p_instance); diff --git a/drivers/gles3/shader_gles3.cpp b/drivers/gles3/shader_gles3.cpp index 78f35c493ab..d29927b1372 100644 --- a/drivers/gles3/shader_gles3.cpp +++ b/drivers/gles3/shader_gles3.cpp @@ -502,6 +502,25 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() { glBindAttribLocation(v.id, attribute_pairs[i].index, attribute_pairs[i].name ); } + //if feedback exists, set it up + + if (feedback_count) { + Vector feedback; + for(int i=0;imesh_add_surface_from_arrays(mesh,(VisualServer::PrimitiveType)p_primitive, p_arrays,p_blend_shapes); + VisualServer::get_singleton()->mesh_add_surface_from_arrays(mesh,(VisualServer::PrimitiveType)p_primitive, p_arrays,p_blend_shapes,p_flags); surfaces.push_back(s); @@ -1024,7 +1024,7 @@ void Mesh::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_morph_target_mode","mode"),&Mesh::set_morph_target_mode); ObjectTypeDB::bind_method(_MD("get_morph_target_mode"),&Mesh::get_morph_target_mode); - ObjectTypeDB::bind_method(_MD("add_surface_from_arrays","primitive","arrays","blend_shapes"),&Mesh::add_surface_from_arrays,DEFVAL(Array())); + ObjectTypeDB::bind_method(_MD("add_surface_from_arrays","primitive","arrays","blend_shapes","compress_flags"),&Mesh::add_surface_from_arrays,DEFVAL(Array()),DEFVAL(ARRAY_COMPRESS_DEFAULT)); ObjectTypeDB::bind_method(_MD("get_surface_count"),&Mesh::get_surface_count); ObjectTypeDB::bind_method(_MD("surface_remove","surf_idx"),&Mesh::surface_remove); ObjectTypeDB::bind_method(_MD("surface_get_array_len","surf_idx"),&Mesh::surface_get_array_len); diff --git a/scene/resources/mesh.h b/scene/resources/mesh.h index 2b28f1187ea..b671d8c3b38 100644 --- a/scene/resources/mesh.h +++ b/scene/resources/mesh.h @@ -77,6 +77,22 @@ public: ARRAY_FORMAT_WEIGHTS=1<& p_array,int p_vertex_count,const DVector& p_index_array,int p_index_count,const AABB& p_aabb,const Vector >& p_blend_shapes=Vector >(),const Vector& p_bone_aabbs=Vector()); Array surface_get_arrays(int p_surface) const; diff --git a/scene/resources/surface_tool.cpp b/scene/resources/surface_tool.cpp index 6f08d69221c..8e6175fa5b8 100644 --- a/scene/resources/surface_tool.cpp +++ b/scene/resources/surface_tool.cpp @@ -355,7 +355,30 @@ Ref SurfaceTool::commit(const Ref& p_existing) { w=DVector::Write(); a[i]=array; } break; - case Mesh::ARRAY_FORMAT_BONES: + case Mesh::ARRAY_FORMAT_BONES: { + + + DVector array; + array.resize(varr_len*4); + DVector::Write w = array.write(); + + int idx=0; + for(List< Vertex >::Element *E=vertex_array.front();E;E=E->next(),idx+=4) { + + const Vertex &v=E->get(); + + ERR_CONTINUE( v.bones.size()!=4 ); + + for(int j=0;j<4;j++) { + w[idx+j]=v.bones[j]; + } + + } + + w=DVector::Write(); + a[i]=array; + + } break; case Mesh::ARRAY_FORMAT_WEIGHTS: { @@ -367,18 +390,11 @@ Ref SurfaceTool::commit(const Ref& p_existing) { for(List< Vertex >::Element *E=vertex_array.front();E;E=E->next(),idx+=4) { const Vertex &v=E->get(); + ERR_CONTINUE( v.weights.size()!=4 ); for(int j=0;j<4;j++) { - switch(i) { - case Mesh::ARRAY_WEIGHTS: { - ERR_CONTINUE( v.weights.size()!=4 ); - w[idx+j]=v.weights[j]; - } break; - case Mesh::ARRAY_BONES: { - ERR_CONTINUE( v.bones.size()!=4 ); - w[idx+j]=v.bones[j]; - } break; - } + + w[idx+j]=v.weights[j]; } } diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h index 5f536b8fd40..21cf391af5b 100644 --- a/servers/visual/rasterizer.h +++ b/servers/visual/rasterizer.h @@ -380,7 +380,8 @@ public: virtual void portal_set_disable_distance(RID p_portal, float p_distance)=0; virtual void portal_set_disabled_color(RID p_portal, const Color& p_color)=0; - + virtual void instance_add_skeleton(RID p_skeleton,RasterizerScene::InstanceBase *p_instance)=0; + virtual void instance_remove_skeleton(RID p_skeleton,RasterizerScene::InstanceBase *p_instance)=0; virtual void instance_add_dependency(RID p_base,RasterizerScene::InstanceBase *p_instance)=0; virtual void instance_remove_dependency(RID p_base,RasterizerScene::InstanceBase *p_instance)=0; diff --git a/servers/visual/visual_server_scene.cpp b/servers/visual/visual_server_scene.cpp index 2439eacd756..0f7dabcc12b 100644 --- a/servers/visual/visual_server_scene.cpp +++ b/servers/visual/visual_server_scene.cpp @@ -738,13 +738,25 @@ void VisualServerScene::instance_attach_object_instance_ID(RID p_instance,Object } void VisualServerScene::instance_set_morph_target_weight(RID p_instance,int p_shape, float p_weight){ + Instance *instance = instance_owner.get( p_instance ); + ERR_FAIL_COND( !instance ); + + if (instance->update_item.in_list()) { + _update_dirty_instance(instance); + } + + ERR_FAIL_INDEX(p_shape,instance->morph_values.size()); + instance->morph_values[p_shape]=p_weight; } + void VisualServerScene::instance_set_surface_material(RID p_instance,int p_surface, RID p_material){ Instance *instance = instance_owner.get( p_instance ); ERR_FAIL_COND( !instance ); - _update_dirty_instance(instance); + if (instance->update_item.in_list()) { + _update_dirty_instance(instance); + } ERR_FAIL_INDEX(p_surface,instance->materials.size()); @@ -770,13 +782,13 @@ void VisualServerScene::instance_attach_skeleton(RID p_instance,RID p_skeleton){ return; if (instance->skeleton.is_valid()) { - VSG::storage->instance_remove_dependency(p_skeleton,instance); + VSG::storage->instance_remove_skeleton(p_skeleton,instance); } instance->skeleton=p_skeleton; if (instance->skeleton.is_valid()) { - VSG::storage->instance_add_dependency(p_skeleton,instance); + VSG::storage->instance_add_skeleton(p_skeleton,instance); } _instance_queue_update(instance,true); @@ -2227,6 +2239,7 @@ void VisualServerScene::_update_dirty_instance(Instance *p_instance) { if (p_instance->update_aabb) _update_instance_aabb(p_instance); + if (p_instance->update_materials) { if (p_instance->base_type==VS::INSTANCE_MESH) { @@ -2239,6 +2252,14 @@ void VisualServerScene::_update_dirty_instance(Instance *p_instance) { } } p_instance->materials.resize(new_mat_count); + + int new_morph_count = VSG::storage->mesh_get_morph_target_count(p_instance->base); + if (new_morph_count!=p_instance->morph_values.size()) { + p_instance->morph_values.resize(new_morph_count); + for(int i=0;imorph_values[i]=0; + } + } } if ((1<base_type)&VS::INSTANCE_GEOMETRY_MASK) { diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp index 27b08c4c500..ac894f1286b 100644 --- a/servers/visual_server.cpp +++ b/servers/visual_server.cpp @@ -709,7 +709,7 @@ Error VisualServer::_surface_set_data(Array p_arrays,uint32_t p_format,uint32_t } break; case VS::ARRAY_BONES: { - ERR_FAIL_COND_V( p_arrays[ai].get_type() != Variant::REAL_ARRAY, ERR_INVALID_PARAMETER ); + ERR_FAIL_COND_V( p_arrays[ai].get_type() != Variant::INT_ARRAY, ERR_INVALID_PARAMETER ); DVector array = p_arrays[ai]; @@ -912,7 +912,7 @@ void VisualServer::mesh_add_surface_from_arrays(RID p_mesh,PrimitiveType p_primi bsformat|=(1< noindex; AABB laabb; - Error err = _surface_set_data(p_blend_shapes[i],format&~ARRAY_FORMAT_INDEX,offsets,total_elem_size,vertex_array,array_len,noindex,0,laabb,bone_aabb); + Error err = _surface_set_data(p_blend_shapes[i],format&~ARRAY_FORMAT_INDEX,offsets,total_elem_size,vertex_array_shape,array_len,noindex,0,laabb,bone_aabb); aabb.merge_with(laabb); if (err) { ERR_EXPLAIN("Invalid blend shape array format for surface"); @@ -1194,9 +1194,9 @@ Array VisualServer::_get_array_from_surface(uint32_t p_format,DVector p case VS::ARRAY_BONES: { if (p_format&ARRAY_FLAG_USE_16_BIT_BONES) { - elem_size=sizeof(uint32_t); - } else { elem_size=sizeof(uint16_t)*4; + } else { + elem_size=sizeof(uint32_t); } } break; @@ -1487,7 +1487,7 @@ Array VisualServer::_get_array_from_surface(uint32_t p_format,DVector p DVector::Write w = arr.write(); for(int j=0;j& p_mesh,const Map& p_material_map,const Collada::MeshData &meshdata,const Transform& p_local_xform,const Vector &bone_remap, const Collada::SkinControllerData *p_skin_data, const Collada::MorphControllerData *p_morph_data,Vector > p_morph_meshes=Vector >()); + Error _create_mesh_surfaces(bool p_optimize, Ref& p_mesh, const Map& p_material_map, const Collada::MeshData &meshdata, const Transform& p_local_xform, const Vector &bone_remap, const Collada::SkinControllerData *p_skin_data, const Collada::MorphControllerData *p_morph_data, Vector > p_morph_meshes=Vector >(), bool p_for_morph=false); Error load(const String& p_path, int p_flags, bool p_force_make_tangents=false); void _fix_param_animation_tracks(); void create_animation(int p_clip,bool p_make_tracks_in_all_bones); @@ -597,7 +597,7 @@ static void _generate_tangents_and_binormals(const DVector& p_indices,const } } -Error ColladaImport::_create_mesh_surfaces(bool p_optimize,Ref& p_mesh,const Map& p_material_map,const Collada::MeshData &meshdata,const Transform& p_local_xform,const Vector &bone_remap, const Collada::SkinControllerData *skin_controller, const Collada::MorphControllerData *p_morph_data,Vector > p_morph_meshes) { +Error ColladaImport::_create_mesh_surfaces(bool p_optimize,Ref& p_mesh,const Map& p_material_map,const Collada::MeshData &meshdata,const Transform& p_local_xform,const Vector &bone_remap, const Collada::SkinControllerData *skin_controller, const Collada::MorphControllerData *p_morph_data,Vector > p_morph_meshes,bool p_for_morph) { bool local_xform_mirror=p_local_xform.basis.determinant() < 0; @@ -1072,7 +1072,7 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize,Ref& p_mesh,con DVector final_color_array; DVector final_uv_array; DVector final_uv2_array; - DVector final_bone_array; + DVector final_bone_array; DVector final_weight_array; uint32_t final_format=0; @@ -1223,12 +1223,12 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize,Ref& p_mesh,con if (has_weights) { DVector weightarray; - DVector bonearray; + DVector bonearray; weightarray.resize(vertex_array.size()*4); DVector::Write weightarrayw = weightarray.write(); bonearray.resize(vertex_array.size()*4); - DVector::Write bonearrayw = bonearray.write(); + DVector::Write bonearrayw = bonearray.write(); for(int k=0;k& p_mesh,con if (l& p_mesh,con } weightarrayw = DVector::Write(); - bonearrayw = DVector::Write(); + bonearrayw = DVector::Write(); final_weight_array = weightarray; final_bone_array = bonearray; @@ -1461,14 +1461,20 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize,Ref& p_mesh,con // print_line("want surface "+itos(mi)+" has "+itos(p_morph_meshes[mi]->get_surface_count())); Array a = p_morph_meshes[mi]->surface_get_arrays(surface); - a[Mesh::ARRAY_BONES]=Variant(); - a[Mesh::ARRAY_WEIGHTS]=Variant(); + //add valid weight and bone arrays if they exist, TODO check if they are unique to shape (generally not) + + if (final_weight_array.size()) + a[Mesh::ARRAY_WEIGHTS]=final_weight_array; + if (final_bone_array.size()) + a[Mesh::ARRAY_BONES]=final_bone_array; + a[Mesh::ARRAY_INDEX]=Variant(); //a.resize(Mesh::ARRAY_MAX); //no need for index mr.push_back(a); } - p_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES,d,mr); + + p_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES,d,mr,p_for_morph?0:Mesh::ARRAY_COMPRESS_DEFAULT); if (material.is_valid()) { p_mesh->surface_set_material(surface, material); @@ -1692,7 +1698,7 @@ Error ColladaImport::_create_resources(Collada::Node *p_node) { if (collada.state.mesh_data_map.has(meshid)) { Ref mesh=Ref(memnew( Mesh )); const Collada::MeshData &meshdata = collada.state.mesh_data_map[meshid]; - Error err = _create_mesh_surfaces(false,mesh,ng->material_map,meshdata,apply_xform,bone_remap,skin,NULL); + Error err = _create_mesh_surfaces(false,mesh,ng->material_map,meshdata,apply_xform,bone_remap,skin,NULL,Vector >(),true); ERR_FAIL_COND_V(err,err); morphs.push_back(mesh); diff --git a/tools/editor/plugins/script_editor_plugin.cpp b/tools/editor/plugins/script_editor_plugin.cpp index 3cd6d8336aa..d650725e2e4 100644 --- a/tools/editor/plugins/script_editor_plugin.cpp +++ b/tools/editor/plugins/script_editor_plugin.cpp @@ -1840,6 +1840,8 @@ void ScriptEditor::get_window_layout(Ref p_layout) { void ScriptEditor::_help_class_open(const String& p_class) { + if (p_class=="") + return; for(int i=0;iget_child_count();i++) {