summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp11
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.cpp401
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.h72
-rw-r--r--drivers/gles3/shader_gles3.cpp23
-rw-r--r--drivers/gles3/shader_gles3.h10
-rw-r--r--drivers/gles3/shaders/SCsub1
-rw-r--r--drivers/gles3/shaders/blend_shape.glsl197
-rwxr-xr-xmethods.py39
-rw-r--r--scene/resources/mesh.cpp6
-rw-r--r--scene/resources/mesh.h18
-rw-r--r--scene/resources/surface_tool.cpp38
-rw-r--r--servers/visual/rasterizer.h3
-rw-r--r--servers/visual/visual_server_scene.cpp27
-rw-r--r--servers/visual_server.cpp12
-rw-r--r--tools/editor/io_plugins/editor_import_collada.cpp28
-rw-r--r--tools/editor/plugins/script_editor_plugin.cpp2
16 files changed, 726 insertions, 162 deletions
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
index 7a0e21b620..9de441c2bb 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<RasterizerStorageGLES3::Surface*>(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 a618953b86..559f733e4d 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<Instantiable*,int>::Element *E=material->instantiable_owners.front();E;E=E->next()) {
- E->key()->instance_material_change_notify();
+ for(Map<Geometry*,int>::Element *E=material->geometry_owners.front();E;E=E->next()) {
+ E->key()->material_changed_notify();
}
for(Map<RasterizerScene::InstanceBase*,int>::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<Instantiable*,int>::Element *I = material->instantiable_owners.find(p_instantiable);
+ Map<Geometry*,int>::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<Instantiable*,int>::Element *I = material->instantiable_owners.find(p_instantiable);
+ Map<Geometry*,int>::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;i<VS::ARRAY_MAX;i++) {
if (! (p_format&(1<<i) ) ) {
attribs[i].enabled=false;
- morph_attribs[i].enabled=false;
attribs[i].integer=false;
- morph_attribs[i].integer=false;
continue;
}
@@ -2466,14 +2463,6 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh,uint32_t p_format,VS::P
attribs[i].index=i;
attribs[i].integer=false;
- if (has_morph) {
- morph_attribs[i].enabled=true;
- morph_attribs[i].offset=morph_stride;
- morph_attribs[i].index=i+8;
- } else {
- morph_attribs[i].enabled=false;
- }
-
switch(i) {
case VS::ARRAY_VERTEX: {
@@ -2494,13 +2483,6 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh,uint32_t p_format,VS::P
attribs[i].normalized=GL_FALSE;
- if (has_morph) {
- //morph
- morph_attribs[i].normalized=GL_FALSE;
- morph_attribs[i].size=attribs[i].size;
- morph_attribs[i].type=GL_FLOAT;
- morph_stride+=attribs[i].size*4;
- }
} break;
case VS::ARRAY_NORMAL: {
@@ -2516,13 +2498,7 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh,uint32_t p_format,VS::P
attribs[i].normalized=GL_FALSE;
}
- if (has_morph) {
- //morph
- morph_attribs[i].normalized=GL_FALSE;
- morph_attribs[i].size=attribs[i].size;
- morph_attribs[i].type=GL_FLOAT;
- morph_stride+=12;
- }
+
} break;
case VS::ARRAY_TANGENT: {
@@ -2539,12 +2515,6 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh,uint32_t p_format,VS::P
attribs[i].normalized=GL_FALSE;
}
- if (has_morph) {
- morph_attribs[i].normalized=GL_FALSE;
- morph_attribs[i].size=attribs[i].size;
- morph_attribs[i].type=GL_FLOAT;
- morph_stride+=16;
- }
} break;
case VS::ARRAY_COLOR: {
@@ -2561,12 +2531,6 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh,uint32_t p_format,VS::P
attribs[i].normalized=GL_FALSE;
}
- if (has_morph) {
- morph_attribs[i].normalized=GL_FALSE;
- morph_attribs[i].size=attribs[i].size;
- morph_attribs[i].type=GL_FLOAT;
- morph_stride+=16;
- }
} break;
case VS::ARRAY_TEX_UV: {
@@ -2583,12 +2547,6 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh,uint32_t p_format,VS::P
attribs[i].normalized=GL_FALSE;
- if (has_morph) {
- morph_attribs[i].normalized=GL_FALSE;
- morph_attribs[i].size=attribs[i].size;
- morph_attribs[i].type=GL_FLOAT;
- morph_stride+=8;
- }
} break;
case VS::ARRAY_TEX_UV2: {
@@ -2604,12 +2562,7 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh,uint32_t p_format,VS::P
}
attribs[i].normalized=GL_FALSE;
- if (has_morph) {
- morph_attribs[i].normalized=GL_FALSE;
- morph_attribs[i].size=attribs[i].size;
- morph_attribs[i].type=GL_FLOAT;
- morph_stride+=8;
- }
+
} break;
case VS::ARRAY_BONES: {
@@ -2627,12 +2580,7 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh,uint32_t p_format,VS::P
attribs[i].normalized=GL_FALSE;
attribs[i].integer=true;
- if (has_morph) {
- morph_attribs[i].normalized=GL_FALSE;
- morph_attribs[i].size=attribs[i].size;
- morph_attribs[i].type=GL_UNSIGNED_SHORT;
- morph_stride+=8;
- }
+
} break;
case VS::ARRAY_WEIGHTS: {
@@ -2650,12 +2598,6 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh,uint32_t p_format,VS::P
attribs[i].normalized=GL_FALSE;
}
- if (has_morph) {
- morph_attribs[i].normalized=GL_FALSE;
- morph_attribs[i].size=attribs[i].size;
- morph_attribs[i].type=GL_FLOAT;
- morph_stride+=8;
- }
} break;
case VS::ARRAY_INDEX: {
@@ -2678,9 +2620,6 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh,uint32_t p_format,VS::P
for(int i=0;i<VS::ARRAY_MAX-1;i++) {
attribs[i].stride=stride;
- if (has_morph) {
- morph_attribs[i].stride=morph_stride;
- }
}
//validate sizes
@@ -2731,7 +2670,6 @@ void RasterizerStorageGLES3::mesh_add_surface(RID p_mesh,uint32_t p_format,VS::P
for(int i=0;i<VS::ARRAY_MAX;i++) {
surface->attribs[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;i<VS::ARRAY_MAX-1;i++) {
+ for(int j=0;j<VS::ARRAY_MAX-1;j++) {
- if (!attribs[i].enabled)
+ if (!attribs[j].enabled)
continue;
- if (attribs[i].integer) {
- glVertexAttribIPointer(attribs[i].index,attribs[i].size,attribs[i].type,attribs[i].stride,((uint8_t*)0)+attribs[i].offset);
+ if (attribs[j].integer) {
+ glVertexAttribIPointer(attribs[j].index,attribs[j].size,attribs[j].type,attribs[j].stride,((uint8_t*)0)+attribs[j].offset);
} else {
- glVertexAttribPointer(attribs[i].index,attribs[i].size,attribs[i].type,attribs[i].normalized,attribs[i].stride,((uint8_t*)0)+attribs[i].offset);
+ glVertexAttribPointer(attribs[j].index,attribs[j].size,attribs[j].type,attribs[j].normalized,attribs[j].stride,((uint8_t*)0)+attribs[j].offset);
}
- glEnableVertexAttribArray(attribs[i].index);
+ glEnableVertexAttribArray(attribs[j].index);
}
@@ -2889,13 +2826,13 @@ void RasterizerStorageGLES3::mesh_surface_set_material(RID p_mesh, int p_surface
return;
if (mesh->surfaces[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;i<VS::ARRAY_MAX-1;i++) {
+ shaders.blend_shapes.set_conditional(cond[i],s->format&(1<<i)); //enable conditional for format
+ if (s->format&(1<<i)) {
+ stride+=sizes[i];
+ }
+ }
+
+
+ //copy all first
+ float base_weight=1.0;
+
+ int mtc = s->morph_targets.size();
+
+ if (s->mesh->morph_target_mode==VS::MORPH_MODE_NORMALIZED) {
+
+ for(int i=0;i<mtc;i++) {
+ base_weight-=p_weights[i];
+ }
+ }
+
+
+
+ shaders.blend_shapes.set_conditional(BlendShapeShaderGLES3::ENABLE_BLEND,false); //first pass does not blend
+ shaders.blend_shapes.set_conditional(BlendShapeShaderGLES3::USE_2D_VERTEX,s->format&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;ti<mtc;ti++) {
+ float weight = p_weights[ti];
+
+ if (weight<0.001) //not bother with this one
+ continue;
+
+ glBindVertexArray(s->morph_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;i<VS::ARRAY_MAX-1;i++) {
+
+ if (s->format&(1<<i)) {
+ glEnableVertexAttribArray(i+8);
+ switch(i) {
+
+ case VS::ARRAY_VERTEX: {
+ if (s->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;i<VS::ARRAY_MAX-1;i++) {
+
+ if (s->format&(1<<i)) {
+ glEnableVertexAttribArray(i);
+ switch(i) {
+
+ case VS::ARRAY_VERTEX: {
+ if (s->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<RasterizerScene::InstanceBase*>::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<Geometry*,int>::Element *E=material->geometry_owners.front();E;E=E->next()) {
+
+ Geometry *g = E->key();
+ g->material=RID();
+ }
+ for (Map<RasterizerScene::InstanceBase*,int>::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;i<ins->materials.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<RasterizerScene::InstanceBase*>::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 623962bf61..361e738af5 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*,int> instantiable_owners;
+ Map<Geometry*,int> geometry_owners;
Map<RasterizerScene::InstanceBase*,int> instance_owners;
bool can_cast_shadow_cache;
@@ -404,8 +435,8 @@ public:
mutable SelfList<Material>::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> 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<float> bones; //4x3 or 4x2 depending on what is needed
GLuint ubo;
SelfList<Skeleton> update_list;
+ Set<RasterizerScene::InstanceBase*> 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 78f35c493a..d29927b137 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<const char*> feedback;
+ for(int i=0;i<feedback_count;i++) {
+
+ if (feedbacks[i].conditional==-1 || (1<<feedbacks[i].conditional)&conditional_version.version) {
+ //conditional for this feedback is enabled
+ print_line("tf varying: "+itos(feedback.size())+" "+String(feedbacks[i].name));
+ feedback.push_back(feedbacks[i].name);
+ }
+ }
+
+ if (feedback.size()) {
+ glTransformFeedbackVaryings(v.id,feedback.size(),feedback.ptr(),GL_INTERLEAVED_ATTRIBS );
+ }
+
+ }
+
glLinkProgram(v.id);
glGetProgramiv(v.id, GL_LINK_STATUS, &status);
@@ -604,7 +623,7 @@ GLint ShaderGLES3::get_uniform_location(const String& p_name) const {
}
-void ShaderGLES3::setup(const char** p_conditional_defines, int p_conditional_count,const char** p_uniform_names,int p_uniform_count, const AttributePair* p_attribute_pairs, int p_attribute_count, const TexUnitPair *p_texunit_pairs, int p_texunit_pair_count, const UBOPair *p_ubo_pairs, int p_ubo_pair_count,const char*p_vertex_code, const char *p_fragment_code,int p_vertex_code_start,int p_fragment_code_start) {
+void ShaderGLES3::setup(const char** p_conditional_defines, int p_conditional_count,const char** p_uniform_names,int p_uniform_count, const AttributePair* p_attribute_pairs, int p_attribute_count, const TexUnitPair *p_texunit_pairs, int p_texunit_pair_count, const UBOPair *p_ubo_pairs, int p_ubo_pair_count, const Feedback* p_feedback, int p_feedback_count,const char*p_vertex_code, const char *p_fragment_code,int p_vertex_code_start,int p_fragment_code_start) {
ERR_FAIL_COND(version);
conditional_version.key=0;
@@ -623,6 +642,8 @@ void ShaderGLES3::setup(const char** p_conditional_defines, int p_conditional_co
attribute_pair_count=p_attribute_count;
ubo_pairs=p_ubo_pairs;
ubo_count=p_ubo_pair_count;
+ feedbacks=p_feedback;
+ feedback_count=p_feedback_count;
//split vertex and shader code (thank you, retarded shader compiler programmers from you know what company).
{
diff --git a/drivers/gles3/shader_gles3.h b/drivers/gles3/shader_gles3.h
index b9749b0228..8b402716a6 100644
--- a/drivers/gles3/shader_gles3.h
+++ b/drivers/gles3/shader_gles3.h
@@ -87,6 +87,12 @@ protected:
int index;
};
+ struct Feedback {
+
+ const char *name;
+ int conditional;
+ };
+
bool uniforms_dirty;
private:
@@ -95,6 +101,7 @@ private:
int texunit_pair_count;
int conditional_count;
int ubo_count;
+ int feedback_count;
int vertex_code_start;
int fragment_code_start;
int attribute_pair_count;
@@ -162,6 +169,7 @@ private:
const AttributePair *attribute_pairs;
const TexUnitPair *texunit_pairs;
const UBOPair *ubo_pairs;
+ const Feedback *feedbacks;
const char* vertex_code;
const char* fragment_code;
CharString fragment_code0;
@@ -293,7 +301,7 @@ protected:
_FORCE_INLINE_ int _get_uniform(int p_which) const;
_FORCE_INLINE_ void _set_conditional(int p_which, bool p_value);
- void setup(const char** p_conditional_defines, int p_conditional_count,const char** p_uniform_names,int p_uniform_count, const AttributePair* p_attribute_pairs, int p_attribute_count, const TexUnitPair *p_texunit_pairs, int p_texunit_pair_count, const UBOPair *p_ubo_pairs, int p_ubo_pair_count,const char*p_vertex_code, const char *p_fragment_code,int p_vertex_code_start,int p_fragment_code_start);
+ void setup(const char** p_conditional_defines, int p_conditional_count,const char** p_uniform_names,int p_uniform_count, const AttributePair* p_attribute_pairs, int p_attribute_count, const TexUnitPair *p_texunit_pairs, int p_texunit_pair_count, const UBOPair *p_ubo_pairs,int p_ubo_pair_count, const Feedback* p_feedback, int p_feedback_count,const char*p_vertex_code, const char *p_fragment_code,int p_vertex_code_start,int p_fragment_code_start);
ShaderGLES3();
public:
diff --git a/drivers/gles3/shaders/SCsub b/drivers/gles3/shaders/SCsub
index 44d325b091..a9808dcbcf 100644
--- a/drivers/gles3/shaders/SCsub
+++ b/drivers/gles3/shaders/SCsub
@@ -7,4 +7,5 @@ if env['BUILDERS'].has_key('GLES3_GLSL'):
env.GLES3_GLSL('scene.glsl');
env.GLES3_GLSL('cubemap_filter.glsl');
env.GLES3_GLSL('cube_to_dp.glsl');
+ env.GLES3_GLSL('blend_shape.glsl');
diff --git a/drivers/gles3/shaders/blend_shape.glsl b/drivers/gles3/shaders/blend_shape.glsl
new file mode 100644
index 0000000000..4e0d066823
--- /dev/null
+++ b/drivers/gles3/shaders/blend_shape.glsl
@@ -0,0 +1,197 @@
+[vertex]
+
+
+/*
+from VisualServer:
+
+ARRAY_VERTEX=0,
+ARRAY_NORMAL=1,
+ARRAY_TANGENT=2,
+ARRAY_COLOR=3,
+ARRAY_TEX_UV=4,
+ARRAY_TEX_UV2=5,
+ARRAY_BONES=6,
+ARRAY_WEIGHTS=7,
+ARRAY_INDEX=8,
+*/
+
+#ifdef USE_2D_VERTEX
+#define VFORMAT vec2
+#else
+#define VFORMAT vec3
+#endif
+
+/* INPUT ATTRIBS */
+
+layout(location=0) in highp VFORMAT vertex_attrib;
+layout(location=1) in vec3 normal_attrib;
+
+#ifdef ENABLE_TANGENT
+layout(location=2) in vec4 tangent_attrib;
+#endif
+
+#ifdef ENABLE_COLOR
+layout(location=3) in vec4 color_attrib;
+#endif
+
+#ifdef ENABLE_UV
+layout(location=4) in vec2 uv_attrib;
+#endif
+
+#ifdef ENABLE_UV2
+layout(location=5) in vec2 uv2_attrib;
+#endif
+
+#ifdef ENABLE_SKELETON
+layout(location=6) in ivec4 bone_attrib;
+layout(location=7) in vec4 weight_attrib;
+#endif
+
+/* BLEND ATTRIBS */
+
+#ifdef ENABLE_BLEND
+
+layout(location=8) in highp VFORMAT vertex_attrib_blend;
+layout(location=9) in vec3 normal_attrib_blend;
+
+#ifdef ENABLE_TANGENT
+layout(location=10) in vec4 tangent_attrib_blend;
+#endif
+
+#ifdef ENABLE_COLOR
+layout(location=11) in vec4 color_attrib_blend;
+#endif
+
+#ifdef ENABLE_UV
+layout(location=12) in vec2 uv_attrib_blend;
+#endif
+
+#ifdef ENABLE_UV2
+layout(location=13) in vec2 uv2_attrib_blend;
+#endif
+
+#ifdef ENABLE_SKELETON
+layout(location=14) in ivec4 bone_attrib_blend;
+layout(location=15) in vec4 weight_attrib_blend;
+#endif
+
+#endif
+
+/* OUTPUTS */
+
+out VFORMAT vertex_out; //tfb:
+
+#ifdef ENABLE_NORMAL
+out vec3 normal_out; //tfb:ENABLE_NORMAL
+#endif
+
+#ifdef ENABLE_TANGENT
+out vec4 tangent_out; //tfb:ENABLE_TANGENT
+#endif
+
+#ifdef ENABLE_COLOR
+out vec4 color_out; //tfb:ENABLE_COLOR
+#endif
+
+#ifdef ENABLE_UV
+out vec2 uv_out; //tfb:ENABLE_UV
+#endif
+
+#ifdef ENABLE_UV2
+out vec2 uv2_out; //tfb:ENABLE_UV2
+#endif
+
+#ifdef ENABLE_SKELETON
+out ivec4 bone_out; //tfb:ENABLE_SKELETON
+out vec4 weight_out; //tfb:ENABLE_SKELETON
+#endif
+
+uniform float blend_amount;
+
+void main() {
+
+
+#ifdef ENABLE_BLEND
+
+ vertex_out = vertex_attrib_blend + vertex_attrib * blend_amount;
+
+#ifdef ENABLE_NORMAL
+ normal_out = normal_attrib_blend + normal_attrib * blend_amount;
+#endif
+
+#ifdef ENABLE_TANGENT
+
+ tangent_out.xyz = tangent_attrib_blend.xyz + tangent_attrib.xyz * blend_amount;
+ tangent_out.w = tangent_attrib_blend.w; //just copy, no point in blending his
+#endif
+
+#ifdef ENABLE_COLOR
+
+ color_out = color_attrib_blend + color_attrib * blend_amount;
+#endif
+
+#ifdef ENABLE_UV
+
+ uv_out = uv_attrib_blend + uv_attrib * blend_amount;
+#endif
+
+#ifdef ENABLE_UV2
+
+ uv2_out = uv2_attrib_blend + uv2_attrib * blend_amount;
+#endif
+
+
+#ifdef ENABLE_SKELETON
+
+ bone_out = bone_attrib_blend;
+ weight_out = weight_attrib_blend + weight_attrib * blend_amount;
+#endif
+
+#else //ENABLE_BLEND
+
+
+ vertex_out = vertex_attrib * blend_amount;
+
+#ifdef ENABLE_NORMAL
+ normal_out = normal_attrib * blend_amount;
+#endif
+
+#ifdef ENABLE_TANGENT
+
+ tangent_out.xyz = tangent_attrib.xyz * blend_amount;
+ tangent_out.w = tangent_attrib.w; //just copy, no point in blending his
+#endif
+
+#ifdef ENABLE_COLOR
+
+ color_out = color_attrib * blend_amount;
+#endif
+
+#ifdef ENABLE_UV
+
+ uv_out = uv_attrib * blend_amount;
+#endif
+
+#ifdef ENABLE_UV2
+
+ uv2_out = uv2_attrib * blend_amount;
+#endif
+
+
+#ifdef ENABLE_SKELETON
+
+ bone_out = bone_attrib;
+ weight_out = weight_attrib * blend_amount;
+#endif
+
+#endif
+ gl_Position = vec4(0.0);
+}
+
+[fragment]
+
+
+void main() {
+
+}
+
diff --git a/methods.py b/methods.py
index f6bae4a64e..e1c8ef7d11 100755
--- a/methods.py
+++ b/methods.py
@@ -671,6 +671,7 @@ class LegacyGLHeaderStruct:
self.fragment_lines=[]
self.uniforms=[]
self.attributes=[]
+ self.feedbacks=[]
self.fbos=[]
self.conditionals=[]
self.enums={}
@@ -823,6 +824,20 @@ def include_file_in_legacygl_header( filename, header_data, depth ):
bind=bind.replace("attrib:","").strip()
header_data.attributes+=[(name,bind)]
+ if ( line.strip().find("out ")==0 and line.find("tfb:")!=-1):
+ uline = line.replace("out ","");
+ uline = uline.replace("highp ","");
+ uline = uline.replace(";","");
+ uline = uline[ uline.find(" "): ].strip()
+
+
+ if (uline.find("//")!=-1):
+ name,bind = uline.split("//")
+ if (bind.find("tfb:")!=-1):
+ name=name.strip()
+ bind=bind.replace("tfb:","").strip()
+ header_data.feedbacks+=[(name,bind)]
+
line=line.replace("\r","")
line=line.replace("\n","")
@@ -1039,12 +1054,14 @@ def build_legacygl_header( filename, include, class_suffix, output_attribs ):
fd.write("\t\tstatic const Enum *_enums=NULL;\n")
fd.write("\t\tstatic const EnumValue *_enum_values=NULL;\n")
+ conditionals_found = []
if (len(header_data.conditionals)):
fd.write("\t\tstatic const char* _conditional_strings[]={\n")
if (len(header_data.conditionals)):
for x in header_data.conditionals:
fd.write("\t\t\t\"#define "+x+"\\n\",\n");
+ conditionals_found.append(x)
fd.write("\t\t};\n\n");
else:
fd.write("\t\tstatic const char **_conditional_strings=NULL;\n")
@@ -1070,6 +1087,24 @@ def build_legacygl_header( filename, include, class_suffix, output_attribs ):
else:
fd.write("\t\tstatic AttributePair *_attribute_pairs=NULL;\n")
+ feedback_count=0
+
+ if (len(header_data.feedbacks)):
+
+ fd.write("\t\tstatic const Feedback _feedbacks[]={\n")
+ for x in header_data.feedbacks:
+ name = x[0]
+ cond = x[1]
+ if (cond in conditionals_found):
+ fd.write("\t\t\t{\""+name+"\","+str(conditionals_found.index(cond))+"},\n");
+ else:
+ fd.write("\t\t\t{\""+name+"\",-1},\n");
+
+ feedback_count+=1
+
+ fd.write("\t\t};\n\n");
+ else:
+ fd.write("\t\tstatic const Feedback* _feedbacks=NULL;\n")
if (len(header_data.texunits)):
fd.write("\t\tstatic TexUnitPair _texunit_pairs[]={\n")
@@ -1109,9 +1144,9 @@ def build_legacygl_header( filename, include, class_suffix, output_attribs ):
fd.write("\t\tstatic const int _fragment_code_start="+str(header_data.fragment_offset)+";\n")
if output_attribs:
- fd.write("\t\tsetup(_conditional_strings,"+str(len(header_data.conditionals))+",_uniform_strings,"+str(len(header_data.uniforms))+",_attribute_pairs,"+str(len(header_data.attributes))+", _texunit_pairs,"+str(len(header_data.texunits))+",_ubo_pairs,"+str(len(header_data.ubos))+",_vertex_code,_fragment_code,_vertex_code_start,_fragment_code_start);\n")
+ fd.write("\t\tsetup(_conditional_strings,"+str(len(header_data.conditionals))+",_uniform_strings,"+str(len(header_data.uniforms))+",_attribute_pairs,"+str(len(header_data.attributes))+", _texunit_pairs,"+str(len(header_data.texunits))+",_ubo_pairs,"+str(len(header_data.ubos))+",_feedbacks,"+str(feedback_count)+",_vertex_code,_fragment_code,_vertex_code_start,_fragment_code_start);\n")
else:
- fd.write("\t\tsetup(_conditional_strings,"+str(len(header_data.conditionals))+",_uniform_strings,"+str(len(header_data.uniforms))+",_texunit_pairs,"+str(len(header_data.texunits))+",_enums,"+str(len(header_data.enums))+",_enum_values,"+str(enum_value_count)+",_ubo_pairs,"+str(len(header_data.ubos))+",_vertex_code,_fragment_code,_vertex_code_start,_fragment_code_start);\n")
+ fd.write("\t\tsetup(_conditional_strings,"+str(len(header_data.conditionals))+",_uniform_strings,"+str(len(header_data.uniforms))+",_texunit_pairs,"+str(len(header_data.texunits))+",_enums,"+str(len(header_data.enums))+",_enum_values,"+str(enum_value_count)+",_ubo_pairs,"+str(len(header_data.ubos))+",_feedbacks,"+str(feedback_count)+",_vertex_code,_fragment_code,_vertex_code_start,_fragment_code_start);\n")
fd.write("\t};\n\n")
diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp
index e737c5c37e..ec33bb53d9 100644
--- a/scene/resources/mesh.cpp
+++ b/scene/resources/mesh.cpp
@@ -316,14 +316,14 @@ void Mesh::add_surface(uint32_t p_format,PrimitiveType p_primitive,const DVector
}
-void Mesh::add_surface_from_arrays(PrimitiveType p_primitive,const Array& p_arrays,const Array& p_blend_shapes) {
+void Mesh::add_surface_from_arrays(PrimitiveType p_primitive,const Array& p_arrays,const Array& p_blend_shapes,uint32_t p_flags) {
ERR_FAIL_COND(p_arrays.size()!=ARRAY_MAX);
Surface s;
- VisualServer::get_singleton()->mesh_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 2b28f1187e..b671d8c3b3 100644
--- a/scene/resources/mesh.h
+++ b/scene/resources/mesh.h
@@ -77,6 +77,22 @@ public:
ARRAY_FORMAT_WEIGHTS=1<<ARRAY_WEIGHTS,
ARRAY_FORMAT_INDEX=1<<ARRAY_INDEX,
+ ARRAY_COMPRESS_BASE=(ARRAY_INDEX+1),
+ ARRAY_COMPRESS_VERTEX=1<<(ARRAY_VERTEX+ARRAY_COMPRESS_BASE), // mandatory
+ ARRAY_COMPRESS_NORMAL=1<<(ARRAY_NORMAL+ARRAY_COMPRESS_BASE),
+ ARRAY_COMPRESS_TANGENT=1<<(ARRAY_TANGENT+ARRAY_COMPRESS_BASE),
+ ARRAY_COMPRESS_COLOR=1<<(ARRAY_COLOR+ARRAY_COMPRESS_BASE),
+ ARRAY_COMPRESS_TEX_UV=1<<(ARRAY_TEX_UV+ARRAY_COMPRESS_BASE),
+ ARRAY_COMPRESS_TEX_UV2=1<<(ARRAY_TEX_UV2+ARRAY_COMPRESS_BASE),
+ ARRAY_COMPRESS_BONES=1<<(ARRAY_BONES+ARRAY_COMPRESS_BASE),
+ ARRAY_COMPRESS_WEIGHTS=1<<(ARRAY_WEIGHTS+ARRAY_COMPRESS_BASE),
+ ARRAY_COMPRESS_INDEX=1<<(ARRAY_INDEX+ARRAY_COMPRESS_BASE),
+
+ ARRAY_FLAG_USE_2D_VERTICES=ARRAY_COMPRESS_INDEX<<1,
+ ARRAY_FLAG_USE_16_BIT_BONES=ARRAY_COMPRESS_INDEX<<2,
+
+ ARRAY_COMPRESS_DEFAULT=ARRAY_COMPRESS_VERTEX|ARRAY_COMPRESS_NORMAL|ARRAY_COMPRESS_TANGENT|ARRAY_COMPRESS_COLOR|ARRAY_COMPRESS_TEX_UV|ARRAY_COMPRESS_TEX_UV2|ARRAY_COMPRESS_WEIGHTS
+
};
enum PrimitiveType {
@@ -122,7 +138,7 @@ protected:
public:
- void add_surface_from_arrays(PrimitiveType p_primitive,const Array& p_arrays,const Array& p_blend_shapes=Array());
+ void add_surface_from_arrays(PrimitiveType p_primitive, const Array& p_arrays, const Array& p_blend_shapes=Array(), uint32_t p_flags=ARRAY_COMPRESS_DEFAULT);
void add_surface(uint32_t p_format,PrimitiveType p_primitive,const DVector<uint8_t>& p_array,int p_vertex_count,const DVector<uint8_t>& p_index_array,int p_index_count,const AABB& p_aabb,const Vector<DVector<uint8_t> >& p_blend_shapes=Vector<DVector<uint8_t> >(),const Vector<AABB>& p_bone_aabbs=Vector<AABB>());
Array surface_get_arrays(int p_surface) const;
diff --git a/scene/resources/surface_tool.cpp b/scene/resources/surface_tool.cpp
index 6f08d69221..8e6175fa5b 100644
--- a/scene/resources/surface_tool.cpp
+++ b/scene/resources/surface_tool.cpp
@@ -355,7 +355,30 @@ Ref<Mesh> SurfaceTool::commit(const Ref<Mesh>& p_existing) {
w=DVector<Color>::Write();
a[i]=array;
} break;
- case Mesh::ARRAY_FORMAT_BONES:
+ case Mesh::ARRAY_FORMAT_BONES: {
+
+
+ DVector<int> array;
+ array.resize(varr_len*4);
+ DVector<int>::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<int>::Write();
+ a[i]=array;
+
+ } break;
case Mesh::ARRAY_FORMAT_WEIGHTS: {
@@ -367,18 +390,11 @@ Ref<Mesh> SurfaceTool::commit(const Ref<Mesh>& 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 5f536b8fd4..21cf391af5 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 2439eacd75..0f7dabcc12 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;i<new_morph_count;i++) {
+ p_instance->morph_values[i]=0;
+ }
+ }
}
if ((1<<p_instance->base_type)&VS::INSTANCE_GEOMETRY_MASK) {
diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp
index 27b08c4c50..ac894f1286 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<int> array = p_arrays[ai];
@@ -912,7 +912,7 @@ void VisualServer::mesh_add_surface_from_arrays(RID p_mesh,PrimitiveType p_primi
bsformat|=(1<<j);
}
- ERR_FAIL_COND( (bsformat)!=(format&(VS::ARRAY_FORMAT_BONES-1)));
+ ERR_FAIL_COND( (bsformat)!=(format&(VS::ARRAY_FORMAT_INDEX-1)));
}
}
@@ -1089,7 +1089,7 @@ void VisualServer::mesh_add_surface_from_arrays(RID p_mesh,PrimitiveType p_primi
DVector<uint8_t> 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<uint8_t> 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<uint8_t> p
DVector<int>::Write w = arr.write();
for(int j=0;j<p_vertex_len;j++) {
- const int *v = (const int*)&r[j*total_elem_size+offsets[i]];
+ const uint8_t *v = (const uint8_t*)&r[j*total_elem_size+offsets[i]];
for(int k=0;k<4;k++) {
w[j*4+k]=v[k];
}
diff --git a/tools/editor/io_plugins/editor_import_collada.cpp b/tools/editor/io_plugins/editor_import_collada.cpp
index fa9e372eb3..217a5fe78d 100644
--- a/tools/editor/io_plugins/editor_import_collada.cpp
+++ b/tools/editor/io_plugins/editor_import_collada.cpp
@@ -85,7 +85,7 @@ struct ColladaImport {
Error _create_scene(Collada::Node *p_node, Spatial *p_parent);
Error _create_resources(Collada::Node *p_node);
Error _create_material(const String& p_material);
- Error _create_mesh_surfaces(bool p_optimize,Ref<Mesh>& p_mesh,const Map<String,Collada::NodeGeometry::Material>& p_material_map,const Collada::MeshData &meshdata,const Transform& p_local_xform,const Vector<int> &bone_remap, const Collada::SkinControllerData *p_skin_data, const Collada::MorphControllerData *p_morph_data,Vector<Ref<Mesh> > p_morph_meshes=Vector<Ref<Mesh> >());
+ Error _create_mesh_surfaces(bool p_optimize, Ref<Mesh>& p_mesh, const Map<String,Collada::NodeGeometry::Material>& p_material_map, const Collada::MeshData &meshdata, const Transform& p_local_xform, const Vector<int> &bone_remap, const Collada::SkinControllerData *p_skin_data, const Collada::MorphControllerData *p_morph_data, Vector<Ref<Mesh> > p_morph_meshes=Vector<Ref<Mesh> >(), 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<int>& p_indices,const
}
}
-Error ColladaImport::_create_mesh_surfaces(bool p_optimize,Ref<Mesh>& p_mesh,const Map<String,Collada::NodeGeometry::Material>& p_material_map,const Collada::MeshData &meshdata,const Transform& p_local_xform,const Vector<int> &bone_remap, const Collada::SkinControllerData *skin_controller, const Collada::MorphControllerData *p_morph_data,Vector<Ref<Mesh> > p_morph_meshes) {
+Error ColladaImport::_create_mesh_surfaces(bool p_optimize,Ref<Mesh>& p_mesh,const Map<String,Collada::NodeGeometry::Material>& p_material_map,const Collada::MeshData &meshdata,const Transform& p_local_xform,const Vector<int> &bone_remap, const Collada::SkinControllerData *skin_controller, const Collada::MorphControllerData *p_morph_data,Vector<Ref<Mesh> > 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<Mesh>& p_mesh,con
DVector<Color> final_color_array;
DVector<Vector3> final_uv_array;
DVector<Vector3> final_uv2_array;
- DVector<float> final_bone_array;
+ DVector<int> final_bone_array;
DVector<float> final_weight_array;
uint32_t final_format=0;
@@ -1223,12 +1223,12 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize,Ref<Mesh>& p_mesh,con
if (has_weights) {
DVector<float> weightarray;
- DVector<float> bonearray;
+ DVector<int> bonearray;
weightarray.resize(vertex_array.size()*4);
DVector<float>::Write weightarrayw = weightarray.write();
bonearray.resize(vertex_array.size()*4);
- DVector<float>::Write bonearrayw = bonearray.write();
+ DVector<int>::Write bonearrayw = bonearray.write();
for(int k=0;k<vlen;k++) {
float sum=0;
@@ -1237,7 +1237,7 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize,Ref<Mesh>& p_mesh,con
if (l<vertex_array[k].weights.size()) {
weightarrayw[k*VS::ARRAY_WEIGHTS_SIZE+l]=vertex_array[k].weights[l].weight;
sum+=weightarrayw[k*VS::ARRAY_WEIGHTS_SIZE+l];
- bonearrayw[k*VS::ARRAY_WEIGHTS_SIZE+l]=vertex_array[k].weights[l].bone_idx;
+ bonearrayw[k*VS::ARRAY_WEIGHTS_SIZE+l]=int(vertex_array[k].weights[l].bone_idx);
//COLLADA_PRINT(itos(k)+": "+rtos(bonearrayw[k*VS::ARRAY_WEIGHTS_SIZE+l])+":"+rtos(weightarray[k*VS::ARRAY_WEIGHTS_SIZE+l]));
} else {
@@ -1254,7 +1254,7 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize,Ref<Mesh>& p_mesh,con
}
weightarrayw = DVector<float>::Write();
- bonearrayw = DVector<float>::Write();
+ bonearrayw = DVector<int>::Write();
final_weight_array = weightarray;
final_bone_array = bonearray;
@@ -1461,14 +1461,20 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize,Ref<Mesh>& 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> mesh=Ref<Mesh>(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<Ref<Mesh> >(),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 3cd6d8336a..d650725e2e 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<ConfigFile> p_layout) {
void ScriptEditor::_help_class_open(const String& p_class) {
+ if (p_class=="")
+ return;
for(int i=0;i<tab_container->get_child_count();i++) {