Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'intern/cycles/blender/blender_mesh.cpp')
-rw-r--r--intern/cycles/blender/blender_mesh.cpp313
1 files changed, 216 insertions, 97 deletions
diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp
index a5e4b7bd2ae..7135e938afb 100644
--- a/intern/cycles/blender/blender_mesh.cpp
+++ b/intern/cycles/blender/blender_mesh.cpp
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
@@ -20,6 +20,7 @@
#include "scene.h"
#include "blender_sync.h"
+#include "blender_session.h"
#include "blender_util.h"
#include "subd_mesh.h"
@@ -27,6 +28,8 @@
#include "subd_split.h"
#include "util_foreach.h"
+#include "util_logging.h"
+#include "util_math.h"
#include "mikktspace.h"
@@ -104,7 +107,9 @@ static void mikk_get_texture_coordinate(const SMikkTSpaceContext *context, float
int vert_idx = userdata->mesh.tessfaces[face_num].vertices()[vert_num];
float3 orco =
get_float3(userdata->mesh.vertices[vert_idx].undeformed_co());
- map_to_sphere(&uv[0], &uv[1], orco[0], orco[1], orco[2]);
+ float2 tmp = map_to_sphere(make_float3(orco[0], orco[1], orco[2]));
+ uv[0] = tmp.x;
+ uv[1] = tmp.y;
}
}
@@ -135,7 +140,7 @@ static void mikk_set_tangent_space(const SMikkTSpaceContext *context, const floa
userdata->tangent[face*4 + vert] = make_float4(T[0], T[1], T[2], sign);
}
-static void mikk_compute_tangents(BL::Mesh b_mesh, BL::MeshTextureFaceLayer *b_layer, Mesh *mesh, vector<int>& nverts, bool need_sign, bool active_render)
+static void mikk_compute_tangents(BL::Mesh b_mesh, BL::MeshTextureFaceLayer *b_layer, Mesh *mesh, const vector<int>& nverts, bool need_sign, bool active_render)
{
/* setup userdata */
MikkUserData userdata(b_mesh, b_layer, nverts.size());
@@ -237,8 +242,16 @@ static void create_mesh_volume_attribute(BL::Object b_ob, Mesh *mesh, ImageManag
bool animated = false;
volume_data->manager = image_manager;
- volume_data->slot = image_manager->add_image(Attribute::standard_name(std),
- b_ob.ptr.data, animated, frame, is_float, is_linear, INTERPOLATION_LINEAR, true);
+ volume_data->slot = image_manager->add_image(
+ Attribute::standard_name(std),
+ b_ob.ptr.data,
+ animated,
+ frame,
+ is_float,
+ is_linear,
+ INTERPOLATION_LINEAR,
+ EXTENSION_REPEAT,
+ true);
}
static void create_mesh_volume_attributes(Scene *scene, BL::Object b_ob, Mesh *mesh, float frame)
@@ -256,6 +269,167 @@ static void create_mesh_volume_attributes(Scene *scene, BL::Object b_ob, Mesh *m
create_mesh_volume_attribute(b_ob, mesh, scene->image_manager, ATTR_STD_VOLUME_VELOCITY, frame);
}
+/* Create vertex color attributes. */
+static void attr_create_vertex_color(Scene *scene,
+ Mesh *mesh,
+ BL::Mesh b_mesh,
+ const vector<int>& nverts)
+{
+ BL::Mesh::tessface_vertex_colors_iterator l;
+ for(b_mesh.tessface_vertex_colors.begin(l); l != b_mesh.tessface_vertex_colors.end(); ++l) {
+ if(!mesh->need_attribute(scene, ustring(l->name().c_str())))
+ continue;
+
+ Attribute *attr = mesh->attributes.add(
+ ustring(l->name().c_str()), TypeDesc::TypeColor, ATTR_ELEMENT_CORNER_BYTE);
+
+ BL::MeshColorLayer::data_iterator c;
+ uchar4 *cdata = attr->data_uchar4();
+ size_t i = 0;
+
+ for(l->data.begin(c); c != l->data.end(); ++c, ++i) {
+ cdata[0] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color1())));
+ cdata[1] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color2())));
+ cdata[2] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color3())));
+
+ if(nverts[i] == 4) {
+ cdata[3] = cdata[0];
+ cdata[4] = cdata[2];
+ cdata[5] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color4())));
+ cdata += 6;
+ }
+ else
+ cdata += 3;
+ }
+ }
+}
+
+/* Create uv map attributes. */
+static void attr_create_uv_map(Scene *scene,
+ Mesh *mesh,
+ BL::Mesh b_mesh,
+ const vector<int>& nverts)
+{
+ if(b_mesh.tessface_uv_textures.length() != 0) {
+ BL::Mesh::tessface_uv_textures_iterator l;
+
+ for(b_mesh.tessface_uv_textures.begin(l); l != b_mesh.tessface_uv_textures.end(); ++l) {
+ bool active_render = l->active_render();
+ AttributeStandard std = (active_render)? ATTR_STD_UV: ATTR_STD_NONE;
+ ustring name = ustring(l->name().c_str());
+
+ /* UV map */
+ if(mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std)) {
+ Attribute *attr;
+
+ if(active_render)
+ attr = mesh->attributes.add(std, name);
+ else
+ attr = mesh->attributes.add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CORNER);
+
+ BL::MeshTextureFaceLayer::data_iterator t;
+ float3 *fdata = attr->data_float3();
+ size_t i = 0;
+
+ for(l->data.begin(t); t != l->data.end(); ++t, ++i) {
+ fdata[0] = get_float3(t->uv1());
+ fdata[1] = get_float3(t->uv2());
+ fdata[2] = get_float3(t->uv3());
+ fdata += 3;
+
+ if(nverts[i] == 4) {
+ fdata[0] = get_float3(t->uv1());
+ fdata[1] = get_float3(t->uv3());
+ fdata[2] = get_float3(t->uv4());
+ fdata += 3;
+ }
+ }
+ }
+
+ /* UV tangent */
+ std = (active_render)? ATTR_STD_UV_TANGENT: ATTR_STD_NONE;
+ name = ustring((string(l->name().c_str()) + ".tangent").c_str());
+
+ if(mesh->need_attribute(scene, name) || (active_render && mesh->need_attribute(scene, std))) {
+ std = (active_render)? ATTR_STD_UV_TANGENT_SIGN: ATTR_STD_NONE;
+ name = ustring((string(l->name().c_str()) + ".tangent_sign").c_str());
+ bool need_sign = (mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std));
+
+ mikk_compute_tangents(b_mesh, &(*l), mesh, nverts, need_sign, active_render);
+ }
+ }
+ }
+ else if(mesh->need_attribute(scene, ATTR_STD_UV_TANGENT)) {
+ bool need_sign = mesh->need_attribute(scene, ATTR_STD_UV_TANGENT_SIGN);
+ mikk_compute_tangents(b_mesh, NULL, mesh, nverts, need_sign, true);
+ }
+}
+
+/* Create vertex pointiness attributes. */
+static void attr_create_pointiness(Scene *scene,
+ Mesh *mesh,
+ BL::Mesh b_mesh)
+{
+ if(mesh->need_attribute(scene, ATTR_STD_POINTINESS)) {
+ const int numverts = b_mesh.vertices.length();
+ Attribute *attr = mesh->attributes.add(ATTR_STD_POINTINESS);
+ float *data = attr->data_float();
+ int *counter = new int[numverts];
+ float *raw_data = new float[numverts];
+ float3 *edge_accum = new float3[numverts];
+
+ /* Calculate pointiness using single ring neighborhood. */
+ memset(counter, 0, sizeof(int) * numverts);
+ memset(raw_data, 0, sizeof(float) * numverts);
+ memset(edge_accum, 0, sizeof(float3) * numverts);
+ BL::Mesh::edges_iterator e;
+ int i = 0;
+ for(b_mesh.edges.begin(e); e != b_mesh.edges.end(); ++e, ++i) {
+ int v0 = b_mesh.edges[i].vertices()[0],
+ v1 = b_mesh.edges[i].vertices()[1];
+ float3 co0 = get_float3(b_mesh.vertices[v0].co()),
+ co1 = get_float3(b_mesh.vertices[v1].co());
+ float3 edge = normalize(co1 - co0);
+ edge_accum[v0] += edge;
+ edge_accum[v1] += -edge;
+ ++counter[v0];
+ ++counter[v1];
+ }
+ i = 0;
+ BL::Mesh::vertices_iterator v;
+ for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v, ++i) {
+ if(counter[i] > 0) {
+ float3 normal = get_float3(b_mesh.vertices[i].normal());
+ float angle = safe_acosf(dot(normal, edge_accum[i] / counter[i]));
+ raw_data[i] = angle * M_1_PI_F;
+ }
+ else {
+ raw_data[i] = 0.0f;
+ }
+ }
+
+ /* Blur vertices to approximate 2 ring neighborhood. */
+ memset(counter, 0, sizeof(int) * numverts);
+ memcpy(data, raw_data, sizeof(float) * numverts);
+ i = 0;
+ for(b_mesh.edges.begin(e); e != b_mesh.edges.end(); ++e, ++i) {
+ int v0 = b_mesh.edges[i].vertices()[0],
+ v1 = b_mesh.edges[i].vertices()[1];
+ data[v0] += raw_data[v1];
+ data[v1] += raw_data[v0];
+ ++counter[v0];
+ ++counter[v1];
+ }
+ for(i = 0; i < numverts; ++i) {
+ data[i] /= counter[i] + 1;
+ }
+
+ delete [] counter;
+ delete [] raw_data;
+ delete [] edge_accum;
+ }
+}
+
/* Create Mesh */
static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<uint>& used_shaders)
@@ -303,6 +477,9 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<
generated[i++] = get_float3(v->undeformed_co())*size - loc;
}
+ /* Create needed vertex attributes. */
+ attr_create_pointiness(scene, mesh, b_mesh);
+
/* create faces */
vector<int> nverts(numfaces);
int fi = 0, ti = 0;
@@ -312,7 +489,7 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<
int n = (vi[3] == 0)? 3: 4;
int mi = clamp(f->material_index(), 0, used_shaders.size()-1);
int shader = used_shaders[mi];
- bool smooth = f->use_smooth();
+ bool smooth = f->use_smooth() || use_loop_normals;
/* split vertices if normal is different
*
@@ -354,92 +531,11 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<
nverts[fi] = n;
}
- /* create vertex color attributes */
- {
- BL::Mesh::tessface_vertex_colors_iterator l;
-
- for(b_mesh.tessface_vertex_colors.begin(l); l != b_mesh.tessface_vertex_colors.end(); ++l) {
- if(!mesh->need_attribute(scene, ustring(l->name().c_str())))
- continue;
-
- Attribute *attr = mesh->attributes.add(
- ustring(l->name().c_str()), TypeDesc::TypeColor, ATTR_ELEMENT_CORNER_BYTE);
-
- BL::MeshColorLayer::data_iterator c;
- uchar4 *cdata = attr->data_uchar4();
- size_t i = 0;
-
- for(l->data.begin(c); c != l->data.end(); ++c, ++i) {
- cdata[0] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color1())));
- cdata[1] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color2())));
- cdata[2] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color3())));
-
- if(nverts[i] == 4) {
- cdata[3] = cdata[0];
- cdata[4] = cdata[2];
- cdata[5] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color4())));
- cdata += 6;
- }
- else
- cdata += 3;
- }
- }
- }
-
- /* create uv map attributes */
- if (b_mesh.tessface_uv_textures.length() != 0) {
- BL::Mesh::tessface_uv_textures_iterator l;
-
- for(b_mesh.tessface_uv_textures.begin(l); l != b_mesh.tessface_uv_textures.end(); ++l) {
- bool active_render = l->active_render();
- AttributeStandard std = (active_render)? ATTR_STD_UV: ATTR_STD_NONE;
- ustring name = ustring(l->name().c_str());
-
- /* UV map */
- if(mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std)) {
- Attribute *attr;
-
- if(active_render)
- attr = mesh->attributes.add(std, name);
- else
- attr = mesh->attributes.add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CORNER);
-
- BL::MeshTextureFaceLayer::data_iterator t;
- float3 *fdata = attr->data_float3();
- size_t i = 0;
-
- for(l->data.begin(t); t != l->data.end(); ++t, ++i) {
- fdata[0] = get_float3(t->uv1());
- fdata[1] = get_float3(t->uv2());
- fdata[2] = get_float3(t->uv3());
- fdata += 3;
-
- if(nverts[i] == 4) {
- fdata[0] = get_float3(t->uv1());
- fdata[1] = get_float3(t->uv3());
- fdata[2] = get_float3(t->uv4());
- fdata += 3;
- }
- }
- }
-
- /* UV tangent */
- std = (active_render)? ATTR_STD_UV_TANGENT: ATTR_STD_NONE;
- name = ustring((string(l->name().c_str()) + ".tangent").c_str());
-
- if(mesh->need_attribute(scene, name) || (active_render && mesh->need_attribute(scene, std))) {
- std = (active_render)? ATTR_STD_UV_TANGENT_SIGN: ATTR_STD_NONE;
- name = ustring((string(l->name().c_str()) + ".tangent_sign").c_str());
- bool need_sign = (mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std));
-
- mikk_compute_tangents(b_mesh, &(*l), mesh, nverts, need_sign, active_render);
- }
- }
- }
- else if(mesh->need_attribute(scene, ATTR_STD_UV_TANGENT)) {
- bool need_sign = mesh->need_attribute(scene, ATTR_STD_UV_TANGENT_SIGN);
- mikk_compute_tangents(b_mesh, NULL, mesh, nverts, need_sign, true);
- }
+ /* Create all needed attributes.
+ * The calculate functions will check whether they're needed or not.
+ */
+ attr_create_vertex_color(scene, mesh, b_mesh, nverts);
+ attr_create_uv_map(scene, mesh, b_mesh, nverts);
/* for volume objects, create a matrix to transform from object space to
* mesh texture space. this does not work with deformations but that can
@@ -501,6 +597,14 @@ static void create_subd_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, PointerR
Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tris)
{
+ /* When viewport display is not needed during render we can force some
+ * caches to be releases from blender side in order to reduce peak memory
+ * footprint during synchronization process.
+ */
+ const bool is_interface_locked = b_engine.render() &&
+ b_engine.render().use_lock_interface();
+ const bool can_free_caches = BlenderSession::headless || is_interface_locked;
+
/* test if we can instance or if the object is modified */
BL::ID b_ob_data = b_ob.data();
BL::ID key = (BKE_object_is_modified(b_ob))? b_ob: b_ob_data;
@@ -525,7 +629,13 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tri
}
/* test if we need to sync */
- bool use_mesh_geometry = render_layer.use_surfaces || render_layer.use_hair;
+ int requested_geometry_flags = Mesh::GEOMETRY_NONE;
+ if(render_layer.use_surfaces) {
+ requested_geometry_flags |= Mesh::GEOMETRY_TRIANGLES;
+ }
+ if(render_layer.use_hair) {
+ requested_geometry_flags |= Mesh::GEOMETRY_CURVES;
+ }
Mesh *mesh;
if(!mesh_map.sync(&mesh, key)) {
@@ -534,7 +644,7 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tri
/* test if shaders changed, these can be object level so mesh
* does not get tagged for recalc */
else if(mesh->used_shaders != used_shaders);
- else if(use_mesh_geometry != mesh->geometry_synced);
+ else if(requested_geometry_flags != mesh->geometry_flags);
else {
/* even if not tagged for recalc, we may need to sync anyway
* because the shader needs different mesh attributes */
@@ -568,7 +678,7 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tri
mesh->used_shaders = used_shaders;
mesh->name = ustring(b_ob_data.name().c_str());
- if(use_mesh_geometry) {
+ if(requested_geometry_flags != Mesh::GEOMETRY_NONE) {
/* mesh objects does have special handle in the dependency graph,
* they're ensured to have properly updated.
*
@@ -594,11 +704,15 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tri
if(render_layer.use_hair)
sync_curves(mesh, b_mesh, b_ob, false);
+ if(can_free_caches) {
+ b_ob.cache_release();
+ }
+
/* free derived mesh */
b_data.meshes.remove(b_mesh);
}
- mesh->geometry_synced = true;
}
+ mesh->geometry_flags = requested_geometry_flags;
/* displacement method */
if(cmesh.data) {
@@ -728,6 +842,7 @@ void BlenderSync::sync_mesh_motion(BL::Object b_ob, Object *object, float motion
return;
}
+ /* TODO(sergey): Perform preliminary check for number of verticies. */
if(numverts) {
/* find attributes */
Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
@@ -759,13 +874,17 @@ void BlenderSync::sync_mesh_motion(BL::Object b_ob, Object *object, float motion
/* in case of new attribute, we verify if there really was any motion */
if(new_attribute) {
- if(i != numverts || memcmp(mP, &mesh->verts[0], sizeof(float3)*numverts) == 0) {
+ if(b_mesh.vertices.length() != numverts ||
+ memcmp(mP, &mesh->verts[0], sizeof(float3)*numverts) == 0)
+ {
/* no motion, remove attributes again */
+ VLOG(1) << "No actual deformation motion for object " << b_ob.name();
mesh->attributes.remove(ATTR_STD_MOTION_VERTEX_POSITION);
if(attr_mN)
mesh->attributes.remove(ATTR_STD_MOTION_VERTEX_NORMAL);
}
else if(time_index > 0) {
+ VLOG(1) << "Filling deformation motion for object " << b_ob.name();
/* motion, fill up previous steps that we might have skipped because
* they had no motion, but we need them anyway now */
float3 *P = &mesh->verts[0];