diff options
author | Campbell Barton <ideasman42@gmail.com> | 2019-04-17 07:17:24 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2019-04-17 07:21:24 +0300 |
commit | e12c08e8d170b7ca40f204a5b0423c23a9fbc2c1 (patch) | |
tree | 8cf3453d12edb177a218ef8009357518ec6cab6a /intern/cycles/blender/blender_mesh.cpp | |
parent | b3dabc200a4b0399ec6b81f2ff2730d07b44fcaa (diff) |
ClangFormat: apply to source, most of intern
Apply clang format as proposed in T53211.
For details on usage and instructions for migrating branches
without conflicts, see:
https://wiki.blender.org/wiki/Tools/ClangFormat
Diffstat (limited to 'intern/cycles/blender/blender_mesh.cpp')
-rw-r--r-- | intern/cycles/blender/blender_mesh.cpp | 2173 |
1 files changed, 1053 insertions, 1120 deletions
diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp index 9b2c2c8e5d5..de594f4fb6c 100644 --- a/intern/cycles/blender/blender_mesh.cpp +++ b/intern/cycles/blender/blender_mesh.cpp @@ -38,1241 +38,1174 @@ CCL_NAMESPACE_BEGIN /* Tangent Space */ struct MikkUserData { - MikkUserData(const BL::Mesh& b_mesh, - const char *layer_name, - const Mesh *mesh, - float3 *tangent, - float *tangent_sign) - : mesh(mesh), - texface(NULL), - orco(NULL), - tangent(tangent), - tangent_sign(tangent_sign) - { - const AttributeSet& attributes = (mesh->subd_faces.size()) ? - mesh->subd_attributes : mesh->attributes; - - Attribute *attr_vN = attributes.find(ATTR_STD_VERTEX_NORMAL); - vertex_normal = attr_vN->data_float3(); - - if(layer_name == NULL) { - Attribute *attr_orco = attributes.find(ATTR_STD_GENERATED); - - if(attr_orco) { - orco = attr_orco->data_float3(); - mesh_texture_space(*(BL::Mesh*)&b_mesh, orco_loc, orco_size); - } - } - else { - Attribute *attr_uv = attributes.find(ustring(layer_name)); - if(attr_uv != NULL) { - texface = attr_uv->data_float2(); - } - } - } - - const Mesh *mesh; - int num_faces; - - float3 *vertex_normal; - float2 *texface; - float3 *orco; - float3 orco_loc, orco_size; - - float3 *tangent; - float *tangent_sign; + MikkUserData(const BL::Mesh &b_mesh, + const char *layer_name, + const Mesh *mesh, + float3 *tangent, + float *tangent_sign) + : mesh(mesh), texface(NULL), orco(NULL), tangent(tangent), tangent_sign(tangent_sign) + { + const AttributeSet &attributes = (mesh->subd_faces.size()) ? mesh->subd_attributes : + mesh->attributes; + + Attribute *attr_vN = attributes.find(ATTR_STD_VERTEX_NORMAL); + vertex_normal = attr_vN->data_float3(); + + if (layer_name == NULL) { + Attribute *attr_orco = attributes.find(ATTR_STD_GENERATED); + + if (attr_orco) { + orco = attr_orco->data_float3(); + mesh_texture_space(*(BL::Mesh *)&b_mesh, orco_loc, orco_size); + } + } + else { + Attribute *attr_uv = attributes.find(ustring(layer_name)); + if (attr_uv != NULL) { + texface = attr_uv->data_float2(); + } + } + } + + const Mesh *mesh; + int num_faces; + + float3 *vertex_normal; + float2 *texface; + float3 *orco; + float3 orco_loc, orco_size; + + float3 *tangent; + float *tangent_sign; }; static int mikk_get_num_faces(const SMikkTSpaceContext *context) { - const MikkUserData *userdata = (const MikkUserData *)context->m_pUserData; - if(userdata->mesh->subd_faces.size()) { - return userdata->mesh->subd_faces.size(); - } - else { - return userdata->mesh->num_triangles(); - } + const MikkUserData *userdata = (const MikkUserData *)context->m_pUserData; + if (userdata->mesh->subd_faces.size()) { + return userdata->mesh->subd_faces.size(); + } + else { + return userdata->mesh->num_triangles(); + } } -static int mikk_get_num_verts_of_face(const SMikkTSpaceContext *context, - const int face_num) +static int mikk_get_num_verts_of_face(const SMikkTSpaceContext *context, const int face_num) { - const MikkUserData *userdata = (const MikkUserData *)context->m_pUserData; - if(userdata->mesh->subd_faces.size()) { - const Mesh *mesh = userdata->mesh; - return mesh->subd_faces[face_num].num_corners; - } - else { - return 3; - } + const MikkUserData *userdata = (const MikkUserData *)context->m_pUserData; + if (userdata->mesh->subd_faces.size()) { + const Mesh *mesh = userdata->mesh; + return mesh->subd_faces[face_num].num_corners; + } + else { + return 3; + } } static int mikk_vertex_index(const Mesh *mesh, const int face_num, const int vert_num) { - if(mesh->subd_faces.size()) { - const Mesh::SubdFace& face = mesh->subd_faces[face_num]; - return mesh->subd_face_corners[face.start_corner + vert_num]; - } - else { - return mesh->triangles[face_num * 3 + vert_num]; - } + if (mesh->subd_faces.size()) { + const Mesh::SubdFace &face = mesh->subd_faces[face_num]; + return mesh->subd_face_corners[face.start_corner + vert_num]; + } + else { + return mesh->triangles[face_num * 3 + vert_num]; + } } static int mikk_corner_index(const Mesh *mesh, const int face_num, const int vert_num) { - if(mesh->subd_faces.size()) { - const Mesh::SubdFace& face = mesh->subd_faces[face_num]; - return face.start_corner + vert_num; - } - else { - return face_num * 3 + vert_num; - } + if (mesh->subd_faces.size()) { + const Mesh::SubdFace &face = mesh->subd_faces[face_num]; + return face.start_corner + vert_num; + } + else { + return face_num * 3 + vert_num; + } } static void mikk_get_position(const SMikkTSpaceContext *context, float P[3], - const int face_num, const int vert_num) + const int face_num, + const int vert_num) { - const MikkUserData *userdata = (const MikkUserData *)context->m_pUserData; - const Mesh *mesh = userdata->mesh; - const int vertex_index = mikk_vertex_index(mesh, face_num, vert_num); - const float3 vP = mesh->verts[vertex_index]; - P[0] = vP.x; - P[1] = vP.y; - P[2] = vP.z; + const MikkUserData *userdata = (const MikkUserData *)context->m_pUserData; + const Mesh *mesh = userdata->mesh; + const int vertex_index = mikk_vertex_index(mesh, face_num, vert_num); + const float3 vP = mesh->verts[vertex_index]; + P[0] = vP.x; + P[1] = vP.y; + P[2] = vP.z; } static void mikk_get_texture_coordinate(const SMikkTSpaceContext *context, float uv[2], - const int face_num, const int vert_num) + const int face_num, + const int vert_num) { - const MikkUserData *userdata = (const MikkUserData *)context->m_pUserData; - const Mesh *mesh = userdata->mesh; - if(userdata->texface != NULL) { - const int corner_index = mikk_corner_index(mesh, face_num, vert_num); - float2 tfuv = userdata->texface[corner_index]; - uv[0] = tfuv.x; - uv[1] = tfuv.y; - } - else if(userdata->orco != NULL) { - const int vertex_index = mikk_vertex_index(mesh, face_num, vert_num); - const float3 orco_loc = userdata->orco_loc; - const float3 orco_size = userdata->orco_size; - const float3 orco = (userdata->orco[vertex_index] + orco_loc) / orco_size; - - const float2 tmp = map_to_sphere(orco); - uv[0] = tmp.x; - uv[1] = tmp.y; - } - else { - uv[0] = 0.0f; - uv[1] = 0.0f; - } + const MikkUserData *userdata = (const MikkUserData *)context->m_pUserData; + const Mesh *mesh = userdata->mesh; + if (userdata->texface != NULL) { + const int corner_index = mikk_corner_index(mesh, face_num, vert_num); + float2 tfuv = userdata->texface[corner_index]; + uv[0] = tfuv.x; + uv[1] = tfuv.y; + } + else if (userdata->orco != NULL) { + const int vertex_index = mikk_vertex_index(mesh, face_num, vert_num); + const float3 orco_loc = userdata->orco_loc; + const float3 orco_size = userdata->orco_size; + const float3 orco = (userdata->orco[vertex_index] + orco_loc) / orco_size; + + const float2 tmp = map_to_sphere(orco); + uv[0] = tmp.x; + uv[1] = tmp.y; + } + else { + uv[0] = 0.0f; + uv[1] = 0.0f; + } } -static void mikk_get_normal(const SMikkTSpaceContext *context, float N[3], - const int face_num, const int vert_num) +static void mikk_get_normal(const SMikkTSpaceContext *context, + float N[3], + const int face_num, + const int vert_num) { - const MikkUserData *userdata = (const MikkUserData *)context->m_pUserData; - const Mesh *mesh = userdata->mesh; - float3 vN; - if(mesh->subd_faces.size()) { - const Mesh::SubdFace& face = mesh->subd_faces[face_num]; - if(face.smooth) { - const int vertex_index = mikk_vertex_index(mesh, face_num, vert_num); - vN = userdata->vertex_normal[vertex_index]; - } - else { - vN = face.normal(mesh); - } - } - else { - if(mesh->smooth[face_num]) { - const int vertex_index = mikk_vertex_index(mesh, face_num, vert_num); - vN = userdata->vertex_normal[vertex_index]; - } - else { - const Mesh::Triangle tri = mesh->get_triangle(face_num); - vN = tri.compute_normal(&mesh->verts[0]); - } - } - N[0] = vN.x; - N[1] = vN.y; - N[2] = vN.z; + const MikkUserData *userdata = (const MikkUserData *)context->m_pUserData; + const Mesh *mesh = userdata->mesh; + float3 vN; + if (mesh->subd_faces.size()) { + const Mesh::SubdFace &face = mesh->subd_faces[face_num]; + if (face.smooth) { + const int vertex_index = mikk_vertex_index(mesh, face_num, vert_num); + vN = userdata->vertex_normal[vertex_index]; + } + else { + vN = face.normal(mesh); + } + } + else { + if (mesh->smooth[face_num]) { + const int vertex_index = mikk_vertex_index(mesh, face_num, vert_num); + vN = userdata->vertex_normal[vertex_index]; + } + else { + const Mesh::Triangle tri = mesh->get_triangle(face_num); + vN = tri.compute_normal(&mesh->verts[0]); + } + } + N[0] = vN.x; + N[1] = vN.y; + N[2] = vN.z; } static void mikk_set_tangent_space(const SMikkTSpaceContext *context, const float T[], const float sign, - const int face_num, const int vert_num) + const int face_num, + const int vert_num) { - MikkUserData *userdata = (MikkUserData *)context->m_pUserData; - const Mesh *mesh = userdata->mesh; - const int corner_index = mikk_corner_index(mesh, face_num, vert_num); - userdata->tangent[corner_index] = make_float3(T[0], T[1], T[2]); - if(userdata->tangent_sign != NULL) { - userdata->tangent_sign[corner_index] = sign; - } + MikkUserData *userdata = (MikkUserData *)context->m_pUserData; + const Mesh *mesh = userdata->mesh; + const int corner_index = mikk_corner_index(mesh, face_num, vert_num); + userdata->tangent[corner_index] = make_float3(T[0], T[1], T[2]); + if (userdata->tangent_sign != NULL) { + userdata->tangent_sign[corner_index] = sign; + } } -static void mikk_compute_tangents(const BL::Mesh& b_mesh, - const char *layer_name, - Mesh *mesh, - bool need_sign, - bool active_render) +static void mikk_compute_tangents( + const BL::Mesh &b_mesh, const char *layer_name, Mesh *mesh, bool need_sign, bool active_render) { - /* Create tangent attributes. */ - AttributeSet& attributes = (mesh->subd_faces.size()) ? - mesh->subd_attributes : mesh->attributes; - Attribute *attr; - ustring name; - if(layer_name != NULL) { - name = ustring((string(layer_name) + ".tangent").c_str()); - } - else { - name = ustring("orco.tangent"); - } - if(active_render) { - attr = attributes.add(ATTR_STD_UV_TANGENT, name); - } - else { - attr = attributes.add(name, TypeDesc::TypeVector, ATTR_ELEMENT_CORNER); - } - float3 *tangent = attr->data_float3(); - /* Create bitangent sign attribute. */ - float *tangent_sign = NULL; - if(need_sign) { - Attribute *attr_sign; - ustring name_sign; - if(layer_name != NULL) { - name_sign = ustring((string(layer_name) + - ".tangent_sign").c_str()); - } - else { - name_sign = ustring("orco.tangent_sign"); - } - - if(active_render) { - attr_sign = attributes.add(ATTR_STD_UV_TANGENT_SIGN, name_sign); - } - else { - attr_sign = attributes.add(name_sign, - TypeDesc::TypeFloat, - ATTR_ELEMENT_CORNER); - } - tangent_sign = attr_sign->data_float(); - } - /* Setup userdata. */ - MikkUserData userdata(b_mesh, layer_name, mesh, tangent, tangent_sign); - /* Setup interface. */ - SMikkTSpaceInterface sm_interface; - memset(&sm_interface, 0, sizeof(sm_interface)); - sm_interface.m_getNumFaces = mikk_get_num_faces; - sm_interface.m_getNumVerticesOfFace = mikk_get_num_verts_of_face; - sm_interface.m_getPosition = mikk_get_position; - sm_interface.m_getTexCoord = mikk_get_texture_coordinate; - sm_interface.m_getNormal = mikk_get_normal; - sm_interface.m_setTSpaceBasic = mikk_set_tangent_space; - /* Setup context. */ - SMikkTSpaceContext context; - memset(&context, 0, sizeof(context)); - context.m_pUserData = &userdata; - context.m_pInterface = &sm_interface; - /* Compute tangents. */ - genTangSpaceDefault(&context); + /* Create tangent attributes. */ + AttributeSet &attributes = (mesh->subd_faces.size()) ? mesh->subd_attributes : mesh->attributes; + Attribute *attr; + ustring name; + if (layer_name != NULL) { + name = ustring((string(layer_name) + ".tangent").c_str()); + } + else { + name = ustring("orco.tangent"); + } + if (active_render) { + attr = attributes.add(ATTR_STD_UV_TANGENT, name); + } + else { + attr = attributes.add(name, TypeDesc::TypeVector, ATTR_ELEMENT_CORNER); + } + float3 *tangent = attr->data_float3(); + /* Create bitangent sign attribute. */ + float *tangent_sign = NULL; + if (need_sign) { + Attribute *attr_sign; + ustring name_sign; + if (layer_name != NULL) { + name_sign = ustring((string(layer_name) + ".tangent_sign").c_str()); + } + else { + name_sign = ustring("orco.tangent_sign"); + } + + if (active_render) { + attr_sign = attributes.add(ATTR_STD_UV_TANGENT_SIGN, name_sign); + } + else { + attr_sign = attributes.add(name_sign, TypeDesc::TypeFloat, ATTR_ELEMENT_CORNER); + } + tangent_sign = attr_sign->data_float(); + } + /* Setup userdata. */ + MikkUserData userdata(b_mesh, layer_name, mesh, tangent, tangent_sign); + /* Setup interface. */ + SMikkTSpaceInterface sm_interface; + memset(&sm_interface, 0, sizeof(sm_interface)); + sm_interface.m_getNumFaces = mikk_get_num_faces; + sm_interface.m_getNumVerticesOfFace = mikk_get_num_verts_of_face; + sm_interface.m_getPosition = mikk_get_position; + sm_interface.m_getTexCoord = mikk_get_texture_coordinate; + sm_interface.m_getNormal = mikk_get_normal; + sm_interface.m_setTSpaceBasic = mikk_set_tangent_space; + /* Setup context. */ + SMikkTSpaceContext context; + memset(&context, 0, sizeof(context)); + context.m_pUserData = &userdata; + context.m_pInterface = &sm_interface; + /* Compute tangents. */ + genTangSpaceDefault(&context); } /* Create Volume Attribute */ -static void create_mesh_volume_attribute(BL::Object& b_ob, - Mesh *mesh, - ImageManager *image_manager, - AttributeStandard std, - float frame) +static void create_mesh_volume_attribute( + BL::Object &b_ob, Mesh *mesh, ImageManager *image_manager, AttributeStandard std, float frame) { - BL::SmokeDomainSettings b_domain = object_smoke_domain_find(b_ob); - - if(!b_domain) - return; - - mesh->volume_isovalue = b_domain.clipping(); - - Attribute *attr = mesh->attributes.add(std); - VoxelAttribute *volume_data = attr->data_voxel(); - ImageMetaData metadata; - bool animated = false; - bool use_alpha = true; - - volume_data->manager = image_manager; - volume_data->slot = image_manager->add_image( - Attribute::standard_name(std), - b_ob.ptr.data, - animated, - frame, - INTERPOLATION_LINEAR, - EXTENSION_CLIP, - use_alpha, - metadata); + BL::SmokeDomainSettings b_domain = object_smoke_domain_find(b_ob); + + if (!b_domain) + return; + + mesh->volume_isovalue = b_domain.clipping(); + + Attribute *attr = mesh->attributes.add(std); + VoxelAttribute *volume_data = attr->data_voxel(); + ImageMetaData metadata; + bool animated = false; + bool use_alpha = true; + + volume_data->manager = image_manager; + volume_data->slot = image_manager->add_image(Attribute::standard_name(std), + b_ob.ptr.data, + animated, + frame, + INTERPOLATION_LINEAR, + EXTENSION_CLIP, + use_alpha, + metadata); } -static void create_mesh_volume_attributes(Scene *scene, - BL::Object& b_ob, - Mesh *mesh, - float frame) +static void create_mesh_volume_attributes(Scene *scene, BL::Object &b_ob, Mesh *mesh, float frame) { - /* for smoke volume rendering */ - if(mesh->need_attribute(scene, ATTR_STD_VOLUME_DENSITY)) - create_mesh_volume_attribute(b_ob, mesh, scene->image_manager, ATTR_STD_VOLUME_DENSITY, frame); - if(mesh->need_attribute(scene, ATTR_STD_VOLUME_COLOR)) - create_mesh_volume_attribute(b_ob, mesh, scene->image_manager, ATTR_STD_VOLUME_COLOR, frame); - if(mesh->need_attribute(scene, ATTR_STD_VOLUME_FLAME)) - create_mesh_volume_attribute(b_ob, mesh, scene->image_manager, ATTR_STD_VOLUME_FLAME, frame); - if(mesh->need_attribute(scene, ATTR_STD_VOLUME_HEAT)) - create_mesh_volume_attribute(b_ob, mesh, scene->image_manager, ATTR_STD_VOLUME_HEAT, frame); - if(mesh->need_attribute(scene, ATTR_STD_VOLUME_TEMPERATURE)) - create_mesh_volume_attribute(b_ob, mesh, scene->image_manager, ATTR_STD_VOLUME_TEMPERATURE, frame); - if(mesh->need_attribute(scene, ATTR_STD_VOLUME_VELOCITY)) - create_mesh_volume_attribute(b_ob, mesh, scene->image_manager, ATTR_STD_VOLUME_VELOCITY, frame); + /* for smoke volume rendering */ + if (mesh->need_attribute(scene, ATTR_STD_VOLUME_DENSITY)) + create_mesh_volume_attribute(b_ob, mesh, scene->image_manager, ATTR_STD_VOLUME_DENSITY, frame); + if (mesh->need_attribute(scene, ATTR_STD_VOLUME_COLOR)) + create_mesh_volume_attribute(b_ob, mesh, scene->image_manager, ATTR_STD_VOLUME_COLOR, frame); + if (mesh->need_attribute(scene, ATTR_STD_VOLUME_FLAME)) + create_mesh_volume_attribute(b_ob, mesh, scene->image_manager, ATTR_STD_VOLUME_FLAME, frame); + if (mesh->need_attribute(scene, ATTR_STD_VOLUME_HEAT)) + create_mesh_volume_attribute(b_ob, mesh, scene->image_manager, ATTR_STD_VOLUME_HEAT, frame); + if (mesh->need_attribute(scene, ATTR_STD_VOLUME_TEMPERATURE)) + create_mesh_volume_attribute( + b_ob, mesh, scene->image_manager, ATTR_STD_VOLUME_TEMPERATURE, frame); + if (mesh->need_attribute(scene, ATTR_STD_VOLUME_VELOCITY)) + 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, - bool subdivision) +static void attr_create_vertex_color(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh, bool subdivision) { - if(subdivision) { - BL::Mesh::vertex_colors_iterator l; - - for(b_mesh.vertex_colors.begin(l); l != b_mesh.vertex_colors.end(); ++l) { - if(!mesh->need_attribute(scene, ustring(l->name().c_str()))) - continue; - - Attribute *attr = mesh->subd_attributes.add(ustring(l->name().c_str()), - TypeDesc::TypeColor, - ATTR_ELEMENT_CORNER_BYTE); - - BL::Mesh::polygons_iterator p; - uchar4 *cdata = attr->data_uchar4(); - - for(b_mesh.polygons.begin(p); p != b_mesh.polygons.end(); ++p) { - int n = p->loop_total(); - for(int i = 0; i < n; i++) { - float3 color = get_float3(l->data[p->loop_start() + i].color()); - /* Compress/encode vertex color using the sRGB curve. */ - *(cdata++) = color_float_to_byte(color_srgb_to_linear_v3(color)); - } - } - } - } - else { - BL::Mesh::vertex_colors_iterator l; - for(b_mesh.vertex_colors.begin(l); l != b_mesh.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::Mesh::loop_triangles_iterator t; - uchar4 *cdata = attr->data_uchar4(); - - for(b_mesh.loop_triangles.begin(t); t != b_mesh.loop_triangles.end(); ++t) { - int3 li = get_int3(t->loops()); - float3 c1 = get_float3(l->data[li[0]].color()); - float3 c2 = get_float3(l->data[li[1]].color()); - float3 c3 = get_float3(l->data[li[2]].color()); - - /* Compress/encode vertex color using the sRGB curve. */ - cdata[0] = color_float_to_byte(color_srgb_to_linear_v3(c1)); - cdata[1] = color_float_to_byte(color_srgb_to_linear_v3(c2)); - cdata[2] = color_float_to_byte(color_srgb_to_linear_v3(c3)); - cdata += 3; - } - } - } + if (subdivision) { + BL::Mesh::vertex_colors_iterator l; + + for (b_mesh.vertex_colors.begin(l); l != b_mesh.vertex_colors.end(); ++l) { + if (!mesh->need_attribute(scene, ustring(l->name().c_str()))) + continue; + + Attribute *attr = mesh->subd_attributes.add( + ustring(l->name().c_str()), TypeDesc::TypeColor, ATTR_ELEMENT_CORNER_BYTE); + + BL::Mesh::polygons_iterator p; + uchar4 *cdata = attr->data_uchar4(); + + for (b_mesh.polygons.begin(p); p != b_mesh.polygons.end(); ++p) { + int n = p->loop_total(); + for (int i = 0; i < n; i++) { + float3 color = get_float3(l->data[p->loop_start() + i].color()); + /* Compress/encode vertex color using the sRGB curve. */ + *(cdata++) = color_float_to_byte(color_srgb_to_linear_v3(color)); + } + } + } + } + else { + BL::Mesh::vertex_colors_iterator l; + for (b_mesh.vertex_colors.begin(l); l != b_mesh.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::Mesh::loop_triangles_iterator t; + uchar4 *cdata = attr->data_uchar4(); + + for (b_mesh.loop_triangles.begin(t); t != b_mesh.loop_triangles.end(); ++t) { + int3 li = get_int3(t->loops()); + float3 c1 = get_float3(l->data[li[0]].color()); + float3 c2 = get_float3(l->data[li[1]].color()); + float3 c3 = get_float3(l->data[li[2]].color()); + + /* Compress/encode vertex color using the sRGB curve. */ + cdata[0] = color_float_to_byte(color_srgb_to_linear_v3(c1)); + cdata[1] = color_float_to_byte(color_srgb_to_linear_v3(c2)); + cdata[2] = color_float_to_byte(color_srgb_to_linear_v3(c3)); + cdata += 3; + } + } + } } /* Create uv map attributes. */ -static void attr_create_uv_map(Scene *scene, - Mesh *mesh, - BL::Mesh& b_mesh) +static void attr_create_uv_map(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh) { - if(b_mesh.uv_layers.length() != 0) { - BL::Mesh::uv_layers_iterator l; - - for(b_mesh.uv_layers.begin(l); l != b_mesh.uv_layers.end(); ++l) { - const bool active_render = l->active_render(); - AttributeStandard uv_std = (active_render)? ATTR_STD_UV: ATTR_STD_NONE; - ustring uv_name = ustring(l->name().c_str()); - AttributeStandard tangent_std = (active_render)? ATTR_STD_UV_TANGENT - : ATTR_STD_NONE; - ustring tangent_name = ustring( - (string(l->name().c_str()) + ".tangent").c_str()); - - /* Denotes whether UV map was requested directly. */ - const bool need_uv = mesh->need_attribute(scene, uv_name) || - mesh->need_attribute(scene, uv_std); - /* Denotes whether tangent was requested directly. */ - const bool need_tangent = - mesh->need_attribute(scene, tangent_name) || - (active_render && mesh->need_attribute(scene, tangent_std)); - - /* UV map */ - /* NOTE: We create temporary UV layer if its needed for tangent but - * wasn't requested by other nodes in shaders. - */ - Attribute *uv_attr = NULL; - if(need_uv || need_tangent) { - if(active_render) { - uv_attr = mesh->attributes.add(uv_std, uv_name); - } - else { - uv_attr = mesh->attributes.add(uv_name, - TypeFloat2, - ATTR_ELEMENT_CORNER); - } - - BL::Mesh::loop_triangles_iterator t; - float2 *fdata = uv_attr->data_float2(); - - for(b_mesh.loop_triangles.begin(t); t != b_mesh.loop_triangles.end(); ++t) { - int3 li = get_int3(t->loops()); - fdata[0] = get_float2(l->data[li[0]].uv()); - fdata[1] = get_float2(l->data[li[1]].uv()); - fdata[2] = get_float2(l->data[li[2]].uv()); - fdata += 3; - } - } - - /* UV tangent */ - if(need_tangent) { - AttributeStandard sign_std = - (active_render)? ATTR_STD_UV_TANGENT_SIGN - : ATTR_STD_NONE; - ustring sign_name = ustring( - (string(l->name().c_str()) + ".tangent_sign").c_str()); - bool need_sign = (mesh->need_attribute(scene, sign_name) || - mesh->need_attribute(scene, sign_std)); - mikk_compute_tangents(b_mesh, - l->name().c_str(), - mesh, - need_sign, - active_render); - } - /* Remove temporarily created UV attribute. */ - if(!need_uv && uv_attr != NULL) { - mesh->attributes.remove(uv_attr); - } - } - } - 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, need_sign, true); - if(!mesh->need_attribute(scene, ATTR_STD_GENERATED)) { - mesh->attributes.remove(ATTR_STD_GENERATED); - } - } + if (b_mesh.uv_layers.length() != 0) { + BL::Mesh::uv_layers_iterator l; + + for (b_mesh.uv_layers.begin(l); l != b_mesh.uv_layers.end(); ++l) { + const bool active_render = l->active_render(); + AttributeStandard uv_std = (active_render) ? ATTR_STD_UV : ATTR_STD_NONE; + ustring uv_name = ustring(l->name().c_str()); + AttributeStandard tangent_std = (active_render) ? ATTR_STD_UV_TANGENT : ATTR_STD_NONE; + ustring tangent_name = ustring((string(l->name().c_str()) + ".tangent").c_str()); + + /* Denotes whether UV map was requested directly. */ + const bool need_uv = mesh->need_attribute(scene, uv_name) || + mesh->need_attribute(scene, uv_std); + /* Denotes whether tangent was requested directly. */ + const bool need_tangent = mesh->need_attribute(scene, tangent_name) || + (active_render && mesh->need_attribute(scene, tangent_std)); + + /* UV map */ + /* NOTE: We create temporary UV layer if its needed for tangent but + * wasn't requested by other nodes in shaders. + */ + Attribute *uv_attr = NULL; + if (need_uv || need_tangent) { + if (active_render) { + uv_attr = mesh->attributes.add(uv_std, uv_name); + } + else { + uv_attr = mesh->attributes.add(uv_name, TypeFloat2, ATTR_ELEMENT_CORNER); + } + + BL::Mesh::loop_triangles_iterator t; + float2 *fdata = uv_attr->data_float2(); + + for (b_mesh.loop_triangles.begin(t); t != b_mesh.loop_triangles.end(); ++t) { + int3 li = get_int3(t->loops()); + fdata[0] = get_float2(l->data[li[0]].uv()); + fdata[1] = get_float2(l->data[li[1]].uv()); + fdata[2] = get_float2(l->data[li[2]].uv()); + fdata += 3; + } + } + + /* UV tangent */ + if (need_tangent) { + AttributeStandard sign_std = (active_render) ? ATTR_STD_UV_TANGENT_SIGN : ATTR_STD_NONE; + ustring sign_name = ustring((string(l->name().c_str()) + ".tangent_sign").c_str()); + bool need_sign = (mesh->need_attribute(scene, sign_name) || + mesh->need_attribute(scene, sign_std)); + mikk_compute_tangents(b_mesh, l->name().c_str(), mesh, need_sign, active_render); + } + /* Remove temporarily created UV attribute. */ + if (!need_uv && uv_attr != NULL) { + mesh->attributes.remove(uv_attr); + } + } + } + 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, need_sign, true); + if (!mesh->need_attribute(scene, ATTR_STD_GENERATED)) { + mesh->attributes.remove(ATTR_STD_GENERATED); + } + } } -static void attr_create_subd_uv_map(Scene *scene, - Mesh *mesh, - BL::Mesh& b_mesh, - bool subdivide_uvs) +static void attr_create_subd_uv_map(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh, bool subdivide_uvs) { - if(b_mesh.uv_layers.length() != 0) { - BL::Mesh::uv_layers_iterator l; - int i = 0; - - for(b_mesh.uv_layers.begin(l); l != b_mesh.uv_layers.end(); ++l, ++i) { - bool active_render = l->active_render(); - AttributeStandard uv_std = (active_render)? ATTR_STD_UV: ATTR_STD_NONE; - ustring uv_name = ustring(l->name().c_str()); - AttributeStandard tangent_std = (active_render)? ATTR_STD_UV_TANGENT - : ATTR_STD_NONE; - ustring tangent_name = ustring( - (string(l->name().c_str()) + ".tangent").c_str()); - - /* Denotes whether UV map was requested directly. */ - const bool need_uv = mesh->need_attribute(scene, uv_name) || - mesh->need_attribute(scene, uv_std); - /* Denotes whether tangent was requested directly. */ - const bool need_tangent = - mesh->need_attribute(scene, tangent_name) || - (active_render && mesh->need_attribute(scene, tangent_std)); - - Attribute *uv_attr = NULL; - - /* UV map */ - if(need_uv || need_tangent) { - if(active_render) - uv_attr = mesh->subd_attributes.add(uv_std, uv_name); - else - uv_attr = mesh->subd_attributes.add(uv_name, TypeFloat2, ATTR_ELEMENT_CORNER); - - if(subdivide_uvs) { - uv_attr->flags |= ATTR_SUBDIVIDED; - } - - BL::Mesh::polygons_iterator p; - float2 *fdata = uv_attr->data_float2(); - - for(b_mesh.polygons.begin(p); p != b_mesh.polygons.end(); ++p) { - int n = p->loop_total(); - for(int j = 0; j < n; j++) { - *(fdata++) = get_float2(l->data[p->loop_start() + j].uv()); - } - } - } - - /* UV tangent */ - if(need_tangent) { - AttributeStandard sign_std = - (active_render)? ATTR_STD_UV_TANGENT_SIGN - : ATTR_STD_NONE; - ustring sign_name = ustring( - (string(l->name().c_str()) + ".tangent_sign").c_str()); - bool need_sign = (mesh->need_attribute(scene, sign_name) || - mesh->need_attribute(scene, sign_std)); - mikk_compute_tangents(b_mesh, - l->name().c_str(), - mesh, - need_sign, - active_render); - } - /* Remove temporarily created UV attribute. */ - if(!need_uv && uv_attr != NULL) { - mesh->subd_attributes.remove(uv_attr); - } - } - } - 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, need_sign, true); - if(!mesh->need_attribute(scene, ATTR_STD_GENERATED)) { - mesh->subd_attributes.remove(ATTR_STD_GENERATED); - } - } + if (b_mesh.uv_layers.length() != 0) { + BL::Mesh::uv_layers_iterator l; + int i = 0; + + for (b_mesh.uv_layers.begin(l); l != b_mesh.uv_layers.end(); ++l, ++i) { + bool active_render = l->active_render(); + AttributeStandard uv_std = (active_render) ? ATTR_STD_UV : ATTR_STD_NONE; + ustring uv_name = ustring(l->name().c_str()); + AttributeStandard tangent_std = (active_render) ? ATTR_STD_UV_TANGENT : ATTR_STD_NONE; + ustring tangent_name = ustring((string(l->name().c_str()) + ".tangent").c_str()); + + /* Denotes whether UV map was requested directly. */ + const bool need_uv = mesh->need_attribute(scene, uv_name) || + mesh->need_attribute(scene, uv_std); + /* Denotes whether tangent was requested directly. */ + const bool need_tangent = mesh->need_attribute(scene, tangent_name) || + (active_render && mesh->need_attribute(scene, tangent_std)); + + Attribute *uv_attr = NULL; + + /* UV map */ + if (need_uv || need_tangent) { + if (active_render) + uv_attr = mesh->subd_attributes.add(uv_std, uv_name); + else + uv_attr = mesh->subd_attributes.add(uv_name, TypeFloat2, ATTR_ELEMENT_CORNER); + + if (subdivide_uvs) { + uv_attr->flags |= ATTR_SUBDIVIDED; + } + + BL::Mesh::polygons_iterator p; + float2 *fdata = uv_attr->data_float2(); + + for (b_mesh.polygons.begin(p); p != b_mesh.polygons.end(); ++p) { + int n = p->loop_total(); + for (int j = 0; j < n; j++) { + *(fdata++) = get_float2(l->data[p->loop_start() + j].uv()); + } + } + } + + /* UV tangent */ + if (need_tangent) { + AttributeStandard sign_std = (active_render) ? ATTR_STD_UV_TANGENT_SIGN : ATTR_STD_NONE; + ustring sign_name = ustring((string(l->name().c_str()) + ".tangent_sign").c_str()); + bool need_sign = (mesh->need_attribute(scene, sign_name) || + mesh->need_attribute(scene, sign_std)); + mikk_compute_tangents(b_mesh, l->name().c_str(), mesh, need_sign, active_render); + } + /* Remove temporarily created UV attribute. */ + if (!need_uv && uv_attr != NULL) { + mesh->subd_attributes.remove(uv_attr); + } + } + } + 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, need_sign, true); + if (!mesh->need_attribute(scene, ATTR_STD_GENERATED)) { + mesh->subd_attributes.remove(ATTR_STD_GENERATED); + } + } } /* Create vertex pointiness attributes. */ /* Compare vertices by sum of their coordinates. */ class VertexAverageComparator { -public: - VertexAverageComparator(const array<float3>& verts) - : verts_(verts) { - } - - bool operator()(const int& vert_idx_a, const int& vert_idx_b) - { - const float3 &vert_a = verts_[vert_idx_a]; - const float3 &vert_b = verts_[vert_idx_b]; - if(vert_a == vert_b) { - /* Special case for doubles, so we ensure ordering. */ - return vert_idx_a > vert_idx_b; - } - const float x1 = vert_a.x + vert_a.y + vert_a.z; - const float x2 = vert_b.x + vert_b.y + vert_b.z; - return x1 < x2; - } - -protected: - const array<float3>& verts_; + public: + VertexAverageComparator(const array<float3> &verts) : verts_(verts) + { + } + + bool operator()(const int &vert_idx_a, const int &vert_idx_b) + { + const float3 &vert_a = verts_[vert_idx_a]; + const float3 &vert_b = verts_[vert_idx_b]; + if (vert_a == vert_b) { + /* Special case for doubles, so we ensure ordering. */ + return vert_idx_a > vert_idx_b; + } + const float x1 = vert_a.x + vert_a.y + vert_a.z; + const float x2 = vert_b.x + vert_b.y + vert_b.z; + return x1 < x2; + } + + protected: + const array<float3> &verts_; }; -static void attr_create_pointiness(Scene *scene, - Mesh *mesh, - BL::Mesh& b_mesh, - bool subdivision) +static void attr_create_pointiness(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh, bool subdivision) { - if(!mesh->need_attribute(scene, ATTR_STD_POINTINESS)) { - return; - } - const int num_verts = b_mesh.vertices.length(); - if(num_verts == 0) { - return; - } - /* STEP 1: Find out duplicated vertices and point duplicates to a single - * original vertex. - */ - vector<int> sorted_vert_indeices(num_verts); - for(int vert_index = 0; vert_index < num_verts; ++vert_index) { - sorted_vert_indeices[vert_index] = vert_index; - } - VertexAverageComparator compare(mesh->verts); - sort(sorted_vert_indeices.begin(), sorted_vert_indeices.end(), compare); - /* This array stores index of the original vertex for the given vertex - * index. - */ - vector<int> vert_orig_index(num_verts); - for(int sorted_vert_index = 0; - sorted_vert_index < num_verts; - ++sorted_vert_index) - { - const int vert_index = sorted_vert_indeices[sorted_vert_index]; - const float3 &vert_co = mesh->verts[vert_index]; - bool found = false; - for(int other_sorted_vert_index = sorted_vert_index + 1; - other_sorted_vert_index < num_verts; - ++other_sorted_vert_index) - { - const int other_vert_index = - sorted_vert_indeices[other_sorted_vert_index]; - const float3 &other_vert_co = mesh->verts[other_vert_index]; - /* We are too far away now, we wouldn't have duplicate. */ - if((other_vert_co.x + other_vert_co.y + other_vert_co.z) - - (vert_co.x + vert_co.y + vert_co.z) > 3 * FLT_EPSILON) - { - break; - } - /* Found duplicate. */ - if(len_squared(other_vert_co - vert_co) < FLT_EPSILON) { - found = true; - vert_orig_index[vert_index] = other_vert_index; - break; - } - } - if(!found) { - vert_orig_index[vert_index] = vert_index; - } - } - /* Make sure we always points to the very first orig vertex. */ - for(int vert_index = 0; vert_index < num_verts; ++vert_index) { - int orig_index = vert_orig_index[vert_index]; - while(orig_index != vert_orig_index[orig_index]) { - orig_index = vert_orig_index[orig_index]; - } - vert_orig_index[vert_index] = orig_index; - } - sorted_vert_indeices.free_memory(); - /* STEP 2: Calculate vertex normals taking into account their possible - * duplicates which gets "welded" together. - */ - vector<float3> vert_normal(num_verts, make_float3(0.0f, 0.0f, 0.0f)); - /* First we accumulate all vertex normals in the original index. */ - for(int vert_index = 0; vert_index < num_verts; ++vert_index) { - const float3 normal = get_float3(b_mesh.vertices[vert_index].normal()); - const int orig_index = vert_orig_index[vert_index]; - vert_normal[orig_index] += normal; - } - /* Then we normalize the accumulated result and flush it to all duplicates - * as well. - */ - for(int vert_index = 0; vert_index < num_verts; ++vert_index) { - const int orig_index = vert_orig_index[vert_index]; - vert_normal[vert_index] = normalize(vert_normal[orig_index]); - } - /* STEP 3: Calculate pointiness using single ring neighborhood. */ - vector<int> counter(num_verts, 0); - vector<float> raw_data(num_verts, 0.0f); - vector<float3> edge_accum(num_verts, make_float3(0.0f, 0.0f, 0.0f)); - BL::Mesh::edges_iterator e; - EdgeMap visited_edges; - int edge_index = 0; - memset(&counter[0], 0, sizeof(int) * counter.size()); - for(b_mesh.edges.begin(e); e != b_mesh.edges.end(); ++e, ++edge_index) { - const int v0 = vert_orig_index[b_mesh.edges[edge_index].vertices()[0]], - v1 = vert_orig_index[b_mesh.edges[edge_index].vertices()[1]]; - if(visited_edges.exists(v0, v1)) { - continue; - } - visited_edges.insert(v0, v1); - 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]; - } - for(int vert_index = 0; vert_index < num_verts; ++vert_index) { - const int orig_index = vert_orig_index[vert_index]; - if(orig_index != vert_index) { - /* Skip duplicates, they'll be overwritten later on. */ - continue; - } - if(counter[vert_index] > 0) { - const float3 normal = vert_normal[vert_index]; - const float angle = - safe_acosf(dot(normal, - edge_accum[vert_index] / counter[vert_index])); - raw_data[vert_index] = angle * M_1_PI_F; - } - else { - raw_data[vert_index] = 0.0f; - } - } - /* STEP 3: Blur vertices to approximate 2 ring neighborhood. */ - AttributeSet& attributes = (subdivision)? mesh->subd_attributes: mesh->attributes; - Attribute *attr = attributes.add(ATTR_STD_POINTINESS); - float *data = attr->data_float(); - memcpy(data, &raw_data[0], sizeof(float) * raw_data.size()); - memset(&counter[0], 0, sizeof(int) * counter.size()); - edge_index = 0; - visited_edges.clear(); - for(b_mesh.edges.begin(e); e != b_mesh.edges.end(); ++e, ++edge_index) { - const int v0 = vert_orig_index[b_mesh.edges[edge_index].vertices()[0]], - v1 = vert_orig_index[b_mesh.edges[edge_index].vertices()[1]]; - if(visited_edges.exists(v0, v1)) { - continue; - } - visited_edges.insert(v0, v1); - data[v0] += raw_data[v1]; - data[v1] += raw_data[v0]; - ++counter[v0]; - ++counter[v1]; - } - for(int vert_index = 0; vert_index < num_verts; ++vert_index) { - data[vert_index] /= counter[vert_index] + 1; - } - /* STEP 4: Copy attribute to the duplicated vertices. */ - for(int vert_index = 0; vert_index < num_verts; ++vert_index) { - const int orig_index = vert_orig_index[vert_index]; - data[vert_index] = data[orig_index]; - } + if (!mesh->need_attribute(scene, ATTR_STD_POINTINESS)) { + return; + } + const int num_verts = b_mesh.vertices.length(); + if (num_verts == 0) { + return; + } + /* STEP 1: Find out duplicated vertices and point duplicates to a single + * original vertex. + */ + vector<int> sorted_vert_indeices(num_verts); + for (int vert_index = 0; vert_index < num_verts; ++vert_index) { + sorted_vert_indeices[vert_index] = vert_index; + } + VertexAverageComparator compare(mesh->verts); + sort(sorted_vert_indeices.begin(), sorted_vert_indeices.end(), compare); + /* This array stores index of the original vertex for the given vertex + * index. + */ + vector<int> vert_orig_index(num_verts); + for (int sorted_vert_index = 0; sorted_vert_index < num_verts; ++sorted_vert_index) { + const int vert_index = sorted_vert_indeices[sorted_vert_index]; + const float3 &vert_co = mesh->verts[vert_index]; + bool found = false; + for (int other_sorted_vert_index = sorted_vert_index + 1; other_sorted_vert_index < num_verts; + ++other_sorted_vert_index) { + const int other_vert_index = sorted_vert_indeices[other_sorted_vert_index]; + const float3 &other_vert_co = mesh->verts[other_vert_index]; + /* We are too far away now, we wouldn't have duplicate. */ + if ((other_vert_co.x + other_vert_co.y + other_vert_co.z) - + (vert_co.x + vert_co.y + vert_co.z) > + 3 * FLT_EPSILON) { + break; + } + /* Found duplicate. */ + if (len_squared(other_vert_co - vert_co) < FLT_EPSILON) { + found = true; + vert_orig_index[vert_index] = other_vert_index; + break; + } + } + if (!found) { + vert_orig_index[vert_index] = vert_index; + } + } + /* Make sure we always points to the very first orig vertex. */ + for (int vert_index = 0; vert_index < num_verts; ++vert_index) { + int orig_index = vert_orig_index[vert_index]; + while (orig_index != vert_orig_index[orig_index]) { + orig_index = vert_orig_index[orig_index]; + } + vert_orig_index[vert_index] = orig_index; + } + sorted_vert_indeices.free_memory(); + /* STEP 2: Calculate vertex normals taking into account their possible + * duplicates which gets "welded" together. + */ + vector<float3> vert_normal(num_verts, make_float3(0.0f, 0.0f, 0.0f)); + /* First we accumulate all vertex normals in the original index. */ + for (int vert_index = 0; vert_index < num_verts; ++vert_index) { + const float3 normal = get_float3(b_mesh.vertices[vert_index].normal()); + const int orig_index = vert_orig_index[vert_index]; + vert_normal[orig_index] += normal; + } + /* Then we normalize the accumulated result and flush it to all duplicates + * as well. + */ + for (int vert_index = 0; vert_index < num_verts; ++vert_index) { + const int orig_index = vert_orig_index[vert_index]; + vert_normal[vert_index] = normalize(vert_normal[orig_index]); + } + /* STEP 3: Calculate pointiness using single ring neighborhood. */ + vector<int> counter(num_verts, 0); + vector<float> raw_data(num_verts, 0.0f); + vector<float3> edge_accum(num_verts, make_float3(0.0f, 0.0f, 0.0f)); + BL::Mesh::edges_iterator e; + EdgeMap visited_edges; + int edge_index = 0; + memset(&counter[0], 0, sizeof(int) * counter.size()); + for (b_mesh.edges.begin(e); e != b_mesh.edges.end(); ++e, ++edge_index) { + const int v0 = vert_orig_index[b_mesh.edges[edge_index].vertices()[0]], + v1 = vert_orig_index[b_mesh.edges[edge_index].vertices()[1]]; + if (visited_edges.exists(v0, v1)) { + continue; + } + visited_edges.insert(v0, v1); + 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]; + } + for (int vert_index = 0; vert_index < num_verts; ++vert_index) { + const int orig_index = vert_orig_index[vert_index]; + if (orig_index != vert_index) { + /* Skip duplicates, they'll be overwritten later on. */ + continue; + } + if (counter[vert_index] > 0) { + const float3 normal = vert_normal[vert_index]; + const float angle = safe_acosf(dot(normal, edge_accum[vert_index] / counter[vert_index])); + raw_data[vert_index] = angle * M_1_PI_F; + } + else { + raw_data[vert_index] = 0.0f; + } + } + /* STEP 3: Blur vertices to approximate 2 ring neighborhood. */ + AttributeSet &attributes = (subdivision) ? mesh->subd_attributes : mesh->attributes; + Attribute *attr = attributes.add(ATTR_STD_POINTINESS); + float *data = attr->data_float(); + memcpy(data, &raw_data[0], sizeof(float) * raw_data.size()); + memset(&counter[0], 0, sizeof(int) * counter.size()); + edge_index = 0; + visited_edges.clear(); + for (b_mesh.edges.begin(e); e != b_mesh.edges.end(); ++e, ++edge_index) { + const int v0 = vert_orig_index[b_mesh.edges[edge_index].vertices()[0]], + v1 = vert_orig_index[b_mesh.edges[edge_index].vertices()[1]]; + if (visited_edges.exists(v0, v1)) { + continue; + } + visited_edges.insert(v0, v1); + data[v0] += raw_data[v1]; + data[v1] += raw_data[v0]; + ++counter[v0]; + ++counter[v1]; + } + for (int vert_index = 0; vert_index < num_verts; ++vert_index) { + data[vert_index] /= counter[vert_index] + 1; + } + /* STEP 4: Copy attribute to the duplicated vertices. */ + for (int vert_index = 0; vert_index < num_verts; ++vert_index) { + const int orig_index = vert_orig_index[vert_index]; + data[vert_index] = data[orig_index]; + } } /* Create Mesh */ static void create_mesh(Scene *scene, Mesh *mesh, - BL::Mesh& b_mesh, - const vector<Shader*>& used_shaders, + BL::Mesh &b_mesh, + const vector<Shader *> &used_shaders, bool subdivision = false, bool subdivide_uvs = true) { - /* count vertices and faces */ - int numverts = b_mesh.vertices.length(); - int numfaces = (!subdivision) ? b_mesh.loop_triangles.length() : b_mesh.polygons.length(); - int numtris = 0; - int numcorners = 0; - int numngons = 0; - bool use_loop_normals = b_mesh.use_auto_smooth() && (mesh->subdivision_type != Mesh::SUBDIVISION_CATMULL_CLARK); - - /* If no faces, create empty mesh. */ - if(numfaces == 0) { - return; - } - - if(!subdivision) { - numtris = numfaces; - } - else { - BL::Mesh::polygons_iterator p; - for(b_mesh.polygons.begin(p); p != b_mesh.polygons.end(); ++p) { - numngons += (p->loop_total() == 4)? 0: 1; - numcorners += p->loop_total(); - } - } - - /* allocate memory */ - mesh->reserve_mesh(numverts, numtris); - mesh->reserve_subd_faces(numfaces, numngons, numcorners); - - /* create vertex coordinates and normals */ - BL::Mesh::vertices_iterator v; - for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v) - mesh->add_vertex(get_float3(v->co())); - - AttributeSet& attributes = (subdivision)? mesh->subd_attributes: mesh->attributes; - Attribute *attr_N = attributes.add(ATTR_STD_VERTEX_NORMAL); - float3 *N = attr_N->data_float3(); - - for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v, ++N) - *N = get_float3(v->normal()); - N = attr_N->data_float3(); - - /* create generated coordinates from undeformed coordinates */ - const bool need_default_tangent = - (subdivision == false) && - (b_mesh.uv_layers.length() == 0) && - (mesh->need_attribute(scene, ATTR_STD_UV_TANGENT)); - if(mesh->need_attribute(scene, ATTR_STD_GENERATED) || - need_default_tangent) - { - Attribute *attr = attributes.add(ATTR_STD_GENERATED); - attr->flags |= ATTR_SUBDIVIDED; - - float3 loc, size; - mesh_texture_space(b_mesh, loc, size); - - float3 *generated = attr->data_float3(); - size_t i = 0; - - for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v) { - generated[i++] = get_float3(v->undeformed_co())*size - loc; - } - } - - /* create faces */ - if(!subdivision) { - BL::Mesh::loop_triangles_iterator t; - - for(b_mesh.loop_triangles.begin(t); t != b_mesh.loop_triangles.end(); ++t) { - BL::MeshPolygon p = b_mesh.polygons[t->polygon_index()]; - int3 vi = get_int3(t->vertices()); - - int shader = clamp(p.material_index(), 0, used_shaders.size()-1); - bool smooth = p.use_smooth() || use_loop_normals; - - if(use_loop_normals) { - BL::Array<float, 9> loop_normals = t->split_normals(); - for(int i = 0; i < 3; i++) { - N[vi[i]] = make_float3(loop_normals[i * 3], - loop_normals[i * 3 + 1], - loop_normals[i * 3 + 2]); - } - } - - /* Create triangles. - * - * NOTE: Autosmooth is already taken care about. - */ - mesh->add_triangle(vi[0], vi[1], vi[2], shader, smooth); - } - } - else { - BL::Mesh::polygons_iterator p; - vector<int> vi; - - for(b_mesh.polygons.begin(p); p != b_mesh.polygons.end(); ++p) { - int n = p->loop_total(); - int shader = clamp(p->material_index(), 0, used_shaders.size()-1); - bool smooth = p->use_smooth() || use_loop_normals; - - vi.resize(n); - for(int i = 0; i < n; i++) { - /* NOTE: Autosmooth is already taken care about. */ - vi[i] = b_mesh.loops[p->loop_start() + i].vertex_index(); - } - - /* create subd faces */ - mesh->add_subd_face(&vi[0], n, shader, smooth); - } - } - - /* Create all needed attributes. - * The calculate functions will check whether they're needed or not. - */ - attr_create_pointiness(scene, mesh, b_mesh, subdivision); - attr_create_vertex_color(scene, mesh, b_mesh, subdivision); - - if(subdivision) { - attr_create_subd_uv_map(scene, mesh, b_mesh, subdivide_uvs); - } - else { - attr_create_uv_map(scene, mesh, b_mesh); - } - - /* for volume objects, create a matrix to transform from object space to - * mesh texture space. this does not work with deformations but that can - * probably only be done well with a volume grid mapping of coordinates */ - if(mesh->need_attribute(scene, ATTR_STD_GENERATED_TRANSFORM)) { - Attribute *attr = mesh->attributes.add(ATTR_STD_GENERATED_TRANSFORM); - Transform *tfm = attr->data_transform(); - - float3 loc, size; - mesh_texture_space(b_mesh, loc, size); - - *tfm = transform_translate(-loc)*transform_scale(size); - } + /* count vertices and faces */ + int numverts = b_mesh.vertices.length(); + int numfaces = (!subdivision) ? b_mesh.loop_triangles.length() : b_mesh.polygons.length(); + int numtris = 0; + int numcorners = 0; + int numngons = 0; + bool use_loop_normals = b_mesh.use_auto_smooth() && + (mesh->subdivision_type != Mesh::SUBDIVISION_CATMULL_CLARK); + + /* If no faces, create empty mesh. */ + if (numfaces == 0) { + return; + } + + if (!subdivision) { + numtris = numfaces; + } + else { + BL::Mesh::polygons_iterator p; + for (b_mesh.polygons.begin(p); p != b_mesh.polygons.end(); ++p) { + numngons += (p->loop_total() == 4) ? 0 : 1; + numcorners += p->loop_total(); + } + } + + /* allocate memory */ + mesh->reserve_mesh(numverts, numtris); + mesh->reserve_subd_faces(numfaces, numngons, numcorners); + + /* create vertex coordinates and normals */ + BL::Mesh::vertices_iterator v; + for (b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v) + mesh->add_vertex(get_float3(v->co())); + + AttributeSet &attributes = (subdivision) ? mesh->subd_attributes : mesh->attributes; + Attribute *attr_N = attributes.add(ATTR_STD_VERTEX_NORMAL); + float3 *N = attr_N->data_float3(); + + for (b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v, ++N) + *N = get_float3(v->normal()); + N = attr_N->data_float3(); + + /* create generated coordinates from undeformed coordinates */ + const bool need_default_tangent = (subdivision == false) && (b_mesh.uv_layers.length() == 0) && + (mesh->need_attribute(scene, ATTR_STD_UV_TANGENT)); + if (mesh->need_attribute(scene, ATTR_STD_GENERATED) || need_default_tangent) { + Attribute *attr = attributes.add(ATTR_STD_GENERATED); + attr->flags |= ATTR_SUBDIVIDED; + + float3 loc, size; + mesh_texture_space(b_mesh, loc, size); + + float3 *generated = attr->data_float3(); + size_t i = 0; + + for (b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v) { + generated[i++] = get_float3(v->undeformed_co()) * size - loc; + } + } + + /* create faces */ + if (!subdivision) { + BL::Mesh::loop_triangles_iterator t; + + for (b_mesh.loop_triangles.begin(t); t != b_mesh.loop_triangles.end(); ++t) { + BL::MeshPolygon p = b_mesh.polygons[t->polygon_index()]; + int3 vi = get_int3(t->vertices()); + + int shader = clamp(p.material_index(), 0, used_shaders.size() - 1); + bool smooth = p.use_smooth() || use_loop_normals; + + if (use_loop_normals) { + BL::Array<float, 9> loop_normals = t->split_normals(); + for (int i = 0; i < 3; i++) { + N[vi[i]] = make_float3( + loop_normals[i * 3], loop_normals[i * 3 + 1], loop_normals[i * 3 + 2]); + } + } + + /* Create triangles. + * + * NOTE: Autosmooth is already taken care about. + */ + mesh->add_triangle(vi[0], vi[1], vi[2], shader, smooth); + } + } + else { + BL::Mesh::polygons_iterator p; + vector<int> vi; + + for (b_mesh.polygons.begin(p); p != b_mesh.polygons.end(); ++p) { + int n = p->loop_total(); + int shader = clamp(p->material_index(), 0, used_shaders.size() - 1); + bool smooth = p->use_smooth() || use_loop_normals; + + vi.resize(n); + for (int i = 0; i < n; i++) { + /* NOTE: Autosmooth is already taken care about. */ + vi[i] = b_mesh.loops[p->loop_start() + i].vertex_index(); + } + + /* create subd faces */ + mesh->add_subd_face(&vi[0], n, shader, smooth); + } + } + + /* Create all needed attributes. + * The calculate functions will check whether they're needed or not. + */ + attr_create_pointiness(scene, mesh, b_mesh, subdivision); + attr_create_vertex_color(scene, mesh, b_mesh, subdivision); + + if (subdivision) { + attr_create_subd_uv_map(scene, mesh, b_mesh, subdivide_uvs); + } + else { + attr_create_uv_map(scene, mesh, b_mesh); + } + + /* for volume objects, create a matrix to transform from object space to + * mesh texture space. this does not work with deformations but that can + * probably only be done well with a volume grid mapping of coordinates */ + if (mesh->need_attribute(scene, ATTR_STD_GENERATED_TRANSFORM)) { + Attribute *attr = mesh->attributes.add(ATTR_STD_GENERATED_TRANSFORM); + Transform *tfm = attr->data_transform(); + + float3 loc, size; + mesh_texture_space(b_mesh, loc, size); + + *tfm = transform_translate(-loc) * transform_scale(size); + } } static void create_subd_mesh(Scene *scene, Mesh *mesh, - BL::Object& b_ob, - BL::Mesh& b_mesh, - const vector<Shader*>& used_shaders, + BL::Object &b_ob, + BL::Mesh &b_mesh, + const vector<Shader *> &used_shaders, float dicing_rate, int max_subdivisions) { - BL::SubsurfModifier subsurf_mod(b_ob.modifiers[b_ob.modifiers.length()-1]); - bool subdivide_uvs = subsurf_mod.uv_smooth() != BL::SubsurfModifier::uv_smooth_NONE; + BL::SubsurfModifier subsurf_mod(b_ob.modifiers[b_ob.modifiers.length() - 1]); + bool subdivide_uvs = subsurf_mod.uv_smooth() != BL::SubsurfModifier::uv_smooth_NONE; - create_mesh(scene, mesh, b_mesh, used_shaders, true, subdivide_uvs); + create_mesh(scene, mesh, b_mesh, used_shaders, true, subdivide_uvs); - /* export creases */ - size_t num_creases = 0; - BL::Mesh::edges_iterator e; + /* export creases */ + size_t num_creases = 0; + BL::Mesh::edges_iterator e; - for(b_mesh.edges.begin(e); e != b_mesh.edges.end(); ++e) { - if(e->crease() != 0.0f) { - num_creases++; - } - } + for (b_mesh.edges.begin(e); e != b_mesh.edges.end(); ++e) { + if (e->crease() != 0.0f) { + num_creases++; + } + } - mesh->subd_creases.resize(num_creases); + mesh->subd_creases.resize(num_creases); - Mesh::SubdEdgeCrease* crease = mesh->subd_creases.data(); - for(b_mesh.edges.begin(e); e != b_mesh.edges.end(); ++e) { - if(e->crease() != 0.0f) { - crease->v[0] = e->vertices()[0]; - crease->v[1] = e->vertices()[1]; - crease->crease = e->crease(); + Mesh::SubdEdgeCrease *crease = mesh->subd_creases.data(); + for (b_mesh.edges.begin(e); e != b_mesh.edges.end(); ++e) { + if (e->crease() != 0.0f) { + crease->v[0] = e->vertices()[0]; + crease->v[1] = e->vertices()[1]; + crease->crease = e->crease(); - crease++; - } - } + crease++; + } + } - /* set subd params */ - if(!mesh->subd_params) { - mesh->subd_params = new SubdParams(mesh); - } - SubdParams& sdparams = *mesh->subd_params; + /* set subd params */ + if (!mesh->subd_params) { + mesh->subd_params = new SubdParams(mesh); + } + SubdParams &sdparams = *mesh->subd_params; - PointerRNA cobj = RNA_pointer_get(&b_ob.ptr, "cycles"); + PointerRNA cobj = RNA_pointer_get(&b_ob.ptr, "cycles"); - sdparams.dicing_rate = max(0.1f, RNA_float_get(&cobj, "dicing_rate") * dicing_rate); - sdparams.max_level = max_subdivisions; + sdparams.dicing_rate = max(0.1f, RNA_float_get(&cobj, "dicing_rate") * dicing_rate); + sdparams.max_level = max_subdivisions; - sdparams.objecttoworld = get_transform(b_ob.matrix_world()); + sdparams.objecttoworld = get_transform(b_ob.matrix_world()); } /* Sync */ -static void sync_mesh_fluid_motion(BL::Object& b_ob, Scene *scene, Mesh *mesh) +static void sync_mesh_fluid_motion(BL::Object &b_ob, Scene *scene, Mesh *mesh) { - if(scene->need_motion() == Scene::MOTION_NONE) - return; + if (scene->need_motion() == Scene::MOTION_NONE) + return; - BL::DomainFluidSettings b_fluid_domain = object_fluid_domain_find(b_ob); + BL::DomainFluidSettings b_fluid_domain = object_fluid_domain_find(b_ob); - if(!b_fluid_domain) - return; + if (!b_fluid_domain) + return; - /* If the mesh has modifiers following the fluid domain we can't export motion. */ - if(b_fluid_domain.fluid_mesh_vertices.length() != mesh->verts.size()) - return; + /* If the mesh has modifiers following the fluid domain we can't export motion. */ + if (b_fluid_domain.fluid_mesh_vertices.length() != mesh->verts.size()) + return; - /* Find or add attribute */ - float3 *P = &mesh->verts[0]; - Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); + /* Find or add attribute */ + float3 *P = &mesh->verts[0]; + Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); - if(!attr_mP) { - attr_mP = mesh->attributes.add(ATTR_STD_MOTION_VERTEX_POSITION); - } + if (!attr_mP) { + attr_mP = mesh->attributes.add(ATTR_STD_MOTION_VERTEX_POSITION); + } - /* Only export previous and next frame, we don't have any in between data. */ - float motion_times[2] = {-1.0f, 1.0f}; - for(int step = 0; step < 2; step++) { - float relative_time = motion_times[step] * scene->motion_shutter_time() * 0.5f; - float3 *mP = attr_mP->data_float3() + step*mesh->verts.size(); + /* Only export previous and next frame, we don't have any in between data. */ + float motion_times[2] = {-1.0f, 1.0f}; + for (int step = 0; step < 2; step++) { + float relative_time = motion_times[step] * scene->motion_shutter_time() * 0.5f; + float3 *mP = attr_mP->data_float3() + step * mesh->verts.size(); - BL::DomainFluidSettings::fluid_mesh_vertices_iterator fvi; - int i = 0; + BL::DomainFluidSettings::fluid_mesh_vertices_iterator fvi; + int i = 0; - for(b_fluid_domain.fluid_mesh_vertices.begin(fvi); fvi != b_fluid_domain.fluid_mesh_vertices.end(); ++fvi, ++i) { - mP[i] = P[i] + get_float3(fvi->velocity()) * relative_time; - } - } + for (b_fluid_domain.fluid_mesh_vertices.begin(fvi); + fvi != b_fluid_domain.fluid_mesh_vertices.end(); + ++fvi, ++i) { + mP[i] = P[i] + get_float3(fvi->velocity()) * relative_time; + } + } } -Mesh *BlenderSync::sync_mesh(BL::Depsgraph& b_depsgraph, - BL::Object& b_ob, - BL::Object& b_ob_instance, +Mesh *BlenderSync::sync_mesh(BL::Depsgraph &b_depsgraph, + BL::Object &b_ob, + BL::Object &b_ob_instance, bool object_updated, bool show_self, bool show_particles) { - /* 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_instance: b_ob_data; - BL::Material material_override = view_layer.material_override; - - /* find shader indices */ - vector<Shader*> used_shaders; - - BL::Object::material_slots_iterator slot; - for(b_ob.material_slots.begin(slot); slot != b_ob.material_slots.end(); ++slot) { - if(material_override) { - find_shader(material_override, used_shaders, scene->default_surface); - } - else { - BL::ID b_material(slot->material()); - find_shader(b_material, used_shaders, scene->default_surface); - } - } - - if(used_shaders.size() == 0) { - if(material_override) - find_shader(material_override, used_shaders, scene->default_surface); - else - used_shaders.push_back(scene->default_surface); - } - - /* test if we need to sync */ - int requested_geometry_flags = Mesh::GEOMETRY_NONE; - if(view_layer.use_surfaces) { - requested_geometry_flags |= Mesh::GEOMETRY_TRIANGLES; - } - if(view_layer.use_hair) { - requested_geometry_flags |= Mesh::GEOMETRY_CURVES; - } - Mesh *mesh; - - if(!mesh_map.sync(&mesh, key)) { - /* if transform was applied to mesh, need full update */ - if(object_updated && mesh->transform_applied); - /* 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(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 */ - bool attribute_recalc = false; - - foreach(Shader *shader, mesh->used_shaders) - if(shader->need_update_mesh) - attribute_recalc = true; - - if(!attribute_recalc) - return mesh; - } - } - - /* ensure we only sync instanced meshes once */ - if(mesh_synced.find(mesh) != mesh_synced.end()) - return mesh; - - progress.set_sync_status("Synchronizing object", b_ob.name()); - - mesh_synced.insert(mesh); - - /* create derived mesh */ - array<int> oldtriangles; - array<Mesh::SubdFace> oldsubd_faces; - array<int> oldsubd_face_corners; - oldtriangles.steal_data(mesh->triangles); - oldsubd_faces.steal_data(mesh->subd_faces); - oldsubd_face_corners.steal_data(mesh->subd_face_corners); - - /* compares curve_keys rather than strands in order to handle quick hair - * adjustments in dynamic BVH - other methods could probably do this better*/ - array<float3> oldcurve_keys; - array<float> oldcurve_radius; - oldcurve_keys.steal_data(mesh->curve_keys); - oldcurve_radius.steal_data(mesh->curve_radius); - - mesh->clear(); - mesh->used_shaders = used_shaders; - mesh->name = ustring(b_ob_data.name().c_str()); - - if(requested_geometry_flags != Mesh::GEOMETRY_NONE) { - /* Adaptive subdivision setup. Not for baking since that requires - * exact mapping to the Blender mesh. */ - if(scene->bake_manager->get_baking()) { - mesh->subdivision_type = Mesh::SUBDIVISION_NONE; - } - else { - mesh->subdivision_type = object_subdivision_type(b_ob, preview, experimental); - } - - /* For some reason, meshes do not need this... */ - bool need_undeformed = mesh->need_attribute(scene, ATTR_STD_GENERATED); - - BL::Mesh b_mesh = object_to_mesh(b_data, - b_ob, - b_depsgraph, - need_undeformed, - mesh->subdivision_type); - - if(b_mesh) { - /* Sync mesh itself. */ - if(view_layer.use_surfaces && show_self) { - if(mesh->subdivision_type != Mesh::SUBDIVISION_NONE) - create_subd_mesh(scene, mesh, b_ob, b_mesh, used_shaders, - dicing_rate, max_subdivisions); - else - create_mesh(scene, mesh, b_mesh, used_shaders, false); - - create_mesh_volume_attributes(scene, b_ob, mesh, b_scene.frame_current()); - } - - /* Sync hair curves. */ - if(view_layer.use_hair && show_particles && mesh->subdivision_type == Mesh::SUBDIVISION_NONE) { - sync_curves(mesh, b_mesh, b_ob, false); - } - - free_object_to_mesh(b_data, b_ob, b_mesh); - } - } - mesh->geometry_flags = requested_geometry_flags; - - /* fluid motion */ - sync_mesh_fluid_motion(b_ob, scene, mesh); - - /* tag update */ - bool rebuild = (oldtriangles != mesh->triangles) || - (oldsubd_faces != mesh->subd_faces) || - (oldsubd_face_corners != mesh->subd_face_corners) || - (oldcurve_keys != mesh->curve_keys) || - (oldcurve_radius != mesh->curve_radius); - - mesh->tag_update(scene, rebuild); - - return mesh; + /* 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_instance : b_ob_data; + BL::Material material_override = view_layer.material_override; + + /* find shader indices */ + vector<Shader *> used_shaders; + + BL::Object::material_slots_iterator slot; + for (b_ob.material_slots.begin(slot); slot != b_ob.material_slots.end(); ++slot) { + if (material_override) { + find_shader(material_override, used_shaders, scene->default_surface); + } + else { + BL::ID b_material(slot->material()); + find_shader(b_material, used_shaders, scene->default_surface); + } + } + + if (used_shaders.size() == 0) { + if (material_override) + find_shader(material_override, used_shaders, scene->default_surface); + else + used_shaders.push_back(scene->default_surface); + } + + /* test if we need to sync */ + int requested_geometry_flags = Mesh::GEOMETRY_NONE; + if (view_layer.use_surfaces) { + requested_geometry_flags |= Mesh::GEOMETRY_TRIANGLES; + } + if (view_layer.use_hair) { + requested_geometry_flags |= Mesh::GEOMETRY_CURVES; + } + Mesh *mesh; + + if (!mesh_map.sync(&mesh, key)) { + /* if transform was applied to mesh, need full update */ + if (object_updated && mesh->transform_applied) + ; + /* 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 (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 */ + bool attribute_recalc = false; + + foreach (Shader *shader, mesh->used_shaders) + if (shader->need_update_mesh) + attribute_recalc = true; + + if (!attribute_recalc) + return mesh; + } + } + + /* ensure we only sync instanced meshes once */ + if (mesh_synced.find(mesh) != mesh_synced.end()) + return mesh; + + progress.set_sync_status("Synchronizing object", b_ob.name()); + + mesh_synced.insert(mesh); + + /* create derived mesh */ + array<int> oldtriangles; + array<Mesh::SubdFace> oldsubd_faces; + array<int> oldsubd_face_corners; + oldtriangles.steal_data(mesh->triangles); + oldsubd_faces.steal_data(mesh->subd_faces); + oldsubd_face_corners.steal_data(mesh->subd_face_corners); + + /* compares curve_keys rather than strands in order to handle quick hair + * adjustments in dynamic BVH - other methods could probably do this better*/ + array<float3> oldcurve_keys; + array<float> oldcurve_radius; + oldcurve_keys.steal_data(mesh->curve_keys); + oldcurve_radius.steal_data(mesh->curve_radius); + + mesh->clear(); + mesh->used_shaders = used_shaders; + mesh->name = ustring(b_ob_data.name().c_str()); + + if (requested_geometry_flags != Mesh::GEOMETRY_NONE) { + /* Adaptive subdivision setup. Not for baking since that requires + * exact mapping to the Blender mesh. */ + if (scene->bake_manager->get_baking()) { + mesh->subdivision_type = Mesh::SUBDIVISION_NONE; + } + else { + mesh->subdivision_type = object_subdivision_type(b_ob, preview, experimental); + } + + /* For some reason, meshes do not need this... */ + bool need_undeformed = mesh->need_attribute(scene, ATTR_STD_GENERATED); + + BL::Mesh b_mesh = object_to_mesh( + b_data, b_ob, b_depsgraph, need_undeformed, mesh->subdivision_type); + + if (b_mesh) { + /* Sync mesh itself. */ + if (view_layer.use_surfaces && show_self) { + if (mesh->subdivision_type != Mesh::SUBDIVISION_NONE) + create_subd_mesh(scene, mesh, b_ob, b_mesh, used_shaders, dicing_rate, max_subdivisions); + else + create_mesh(scene, mesh, b_mesh, used_shaders, false); + + create_mesh_volume_attributes(scene, b_ob, mesh, b_scene.frame_current()); + } + + /* Sync hair curves. */ + if (view_layer.use_hair && show_particles && + mesh->subdivision_type == Mesh::SUBDIVISION_NONE) { + sync_curves(mesh, b_mesh, b_ob, false); + } + + free_object_to_mesh(b_data, b_ob, b_mesh); + } + } + mesh->geometry_flags = requested_geometry_flags; + + /* fluid motion */ + sync_mesh_fluid_motion(b_ob, scene, mesh); + + /* tag update */ + bool rebuild = (oldtriangles != mesh->triangles) || (oldsubd_faces != mesh->subd_faces) || + (oldsubd_face_corners != mesh->subd_face_corners) || + (oldcurve_keys != mesh->curve_keys) || (oldcurve_radius != mesh->curve_radius); + + mesh->tag_update(scene, rebuild); + + return mesh; } -void BlenderSync::sync_mesh_motion(BL::Depsgraph& b_depsgraph, - BL::Object& b_ob, +void BlenderSync::sync_mesh_motion(BL::Depsgraph &b_depsgraph, + BL::Object &b_ob, Object *object, float motion_time) { - /* ensure we only sync instanced meshes once */ - Mesh *mesh = object->mesh; - - if(mesh_motion_synced.find(mesh) != mesh_motion_synced.end()) - return; - - mesh_motion_synced.insert(mesh); - - /* ensure we only motion sync meshes that also had mesh synced, to avoid - * unnecessary work and to ensure that its attributes were clear */ - if(mesh_synced.find(mesh) == mesh_synced.end()) - return; - - /* Find time matching motion step required by mesh. */ - int motion_step = mesh->motion_step(motion_time); - if(motion_step < 0) { - return; - } - - /* skip empty meshes */ - const size_t numverts = mesh->verts.size(); - const size_t numkeys = mesh->curve_keys.size(); - - if(!numverts && !numkeys) - return; - - /* skip objects without deforming modifiers. this is not totally reliable, - * would need a more extensive check to see which objects are animated */ - BL::Mesh b_mesh(PointerRNA_NULL); - - /* fluid motion is exported immediate with mesh, skip here */ - BL::DomainFluidSettings b_fluid_domain = object_fluid_domain_find(b_ob); - if(b_fluid_domain) - return; - - if(ccl::BKE_object_is_deform_modified(b_ob, b_scene, preview)) { - /* get derived mesh */ - b_mesh = object_to_mesh(b_data, - b_ob, - b_depsgraph, - false, - Mesh::SUBDIVISION_NONE); - } - - if(!b_mesh) { - /* if we have no motion blur on this frame, but on other frames, copy */ - if(numverts) { - /* triangles */ - Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); - - if(attr_mP) { - Attribute *attr_mN = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_NORMAL); - Attribute *attr_N = mesh->attributes.find(ATTR_STD_VERTEX_NORMAL); - float3 *P = &mesh->verts[0]; - float3 *N = (attr_N)? attr_N->data_float3(): NULL; - - memcpy(attr_mP->data_float3() + motion_step*numverts, P, sizeof(float3)*numverts); - if(attr_mN) - memcpy(attr_mN->data_float3() + motion_step*numverts, N, sizeof(float3)*numverts); - } - } - - if(numkeys) { - /* curves */ - Attribute *attr_mP = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); - - if(attr_mP) { - float3 *keys = &mesh->curve_keys[0]; - memcpy(attr_mP->data_float3() + motion_step*numkeys, keys, sizeof(float3)*numkeys); - } - } - - 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); - Attribute *attr_mN = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_NORMAL); - Attribute *attr_N = mesh->attributes.find(ATTR_STD_VERTEX_NORMAL); - bool new_attribute = false; - /* Add new attributes if they don't exist already. */ - if(!attr_mP) { - attr_mP = mesh->attributes.add(ATTR_STD_MOTION_VERTEX_POSITION); - if(attr_N) - attr_mN = mesh->attributes.add(ATTR_STD_MOTION_VERTEX_NORMAL); - - new_attribute = true; - } - /* Load vertex data from mesh. */ - float3 *mP = attr_mP->data_float3() + motion_step*numverts; - float3 *mN = (attr_mN)? attr_mN->data_float3() + motion_step*numverts: NULL; - /* NOTE: We don't copy more that existing amount of vertices to prevent - * possible memory corruption. - */ - BL::Mesh::vertices_iterator v; - int i = 0; - for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end() && i < numverts; ++v, ++i) { - mP[i] = get_float3(v->co()); - if(mN) - mN[i] = get_float3(v->normal()); - } - if(new_attribute) { - /* In case of new attribute, we verify if there really was any motion. */ - if(b_mesh.vertices.length() != numverts || - memcmp(mP, &mesh->verts[0], sizeof(float3)*numverts) == 0) - { - /* no motion, remove attributes again */ - if(b_mesh.vertices.length() != numverts) { - VLOG(1) << "Topology differs, disabling motion blur for object " - << b_ob.name(); - } - else { - 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(motion_step > 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]; - float3 *N = (attr_N)? attr_N->data_float3(): NULL; - for(int step = 0; step < motion_step; step++) { - memcpy(attr_mP->data_float3() + step*numverts, P, sizeof(float3)*numverts); - if(attr_mN) - memcpy(attr_mN->data_float3() + step*numverts, N, sizeof(float3)*numverts); - } - } - } - else { - if(b_mesh.vertices.length() != numverts) { - VLOG(1) << "Topology differs, discarding motion blur for object " - << b_ob.name() << " at time " << motion_step; - memcpy(mP, &mesh->verts[0], sizeof(float3)*numverts); - if(mN != NULL) { - memcpy(mN, attr_N->data_float3(), sizeof(float3)*numverts); - } - } - } - } - - /* hair motion */ - if(numkeys) - sync_curves(mesh, b_mesh, b_ob, true, motion_step); - - /* free derived mesh */ - free_object_to_mesh(b_data, b_ob, b_mesh); + /* ensure we only sync instanced meshes once */ + Mesh *mesh = object->mesh; + + if (mesh_motion_synced.find(mesh) != mesh_motion_synced.end()) + return; + + mesh_motion_synced.insert(mesh); + + /* ensure we only motion sync meshes that also had mesh synced, to avoid + * unnecessary work and to ensure that its attributes were clear */ + if (mesh_synced.find(mesh) == mesh_synced.end()) + return; + + /* Find time matching motion step required by mesh. */ + int motion_step = mesh->motion_step(motion_time); + if (motion_step < 0) { + return; + } + + /* skip empty meshes */ + const size_t numverts = mesh->verts.size(); + const size_t numkeys = mesh->curve_keys.size(); + + if (!numverts && !numkeys) + return; + + /* skip objects without deforming modifiers. this is not totally reliable, + * would need a more extensive check to see which objects are animated */ + BL::Mesh b_mesh(PointerRNA_NULL); + + /* fluid motion is exported immediate with mesh, skip here */ + BL::DomainFluidSettings b_fluid_domain = object_fluid_domain_find(b_ob); + if (b_fluid_domain) + return; + + if (ccl::BKE_object_is_deform_modified(b_ob, b_scene, preview)) { + /* get derived mesh */ + b_mesh = object_to_mesh(b_data, b_ob, b_depsgraph, false, Mesh::SUBDIVISION_NONE); + } + + if (!b_mesh) { + /* if we have no motion blur on this frame, but on other frames, copy */ + if (numverts) { + /* triangles */ + Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); + + if (attr_mP) { + Attribute *attr_mN = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_NORMAL); + Attribute *attr_N = mesh->attributes.find(ATTR_STD_VERTEX_NORMAL); + float3 *P = &mesh->verts[0]; + float3 *N = (attr_N) ? attr_N->data_float3() : NULL; + + memcpy(attr_mP->data_float3() + motion_step * numverts, P, sizeof(float3) * numverts); + if (attr_mN) + memcpy(attr_mN->data_float3() + motion_step * numverts, N, sizeof(float3) * numverts); + } + } + + if (numkeys) { + /* curves */ + Attribute *attr_mP = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); + + if (attr_mP) { + float3 *keys = &mesh->curve_keys[0]; + memcpy(attr_mP->data_float3() + motion_step * numkeys, keys, sizeof(float3) * numkeys); + } + } + + 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); + Attribute *attr_mN = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_NORMAL); + Attribute *attr_N = mesh->attributes.find(ATTR_STD_VERTEX_NORMAL); + bool new_attribute = false; + /* Add new attributes if they don't exist already. */ + if (!attr_mP) { + attr_mP = mesh->attributes.add(ATTR_STD_MOTION_VERTEX_POSITION); + if (attr_N) + attr_mN = mesh->attributes.add(ATTR_STD_MOTION_VERTEX_NORMAL); + + new_attribute = true; + } + /* Load vertex data from mesh. */ + float3 *mP = attr_mP->data_float3() + motion_step * numverts; + float3 *mN = (attr_mN) ? attr_mN->data_float3() + motion_step * numverts : NULL; + /* NOTE: We don't copy more that existing amount of vertices to prevent + * possible memory corruption. + */ + BL::Mesh::vertices_iterator v; + int i = 0; + for (b_mesh.vertices.begin(v); v != b_mesh.vertices.end() && i < numverts; ++v, ++i) { + mP[i] = get_float3(v->co()); + if (mN) + mN[i] = get_float3(v->normal()); + } + if (new_attribute) { + /* In case of new attribute, we verify if there really was any motion. */ + if (b_mesh.vertices.length() != numverts || + memcmp(mP, &mesh->verts[0], sizeof(float3) * numverts) == 0) { + /* no motion, remove attributes again */ + if (b_mesh.vertices.length() != numverts) { + VLOG(1) << "Topology differs, disabling motion blur for object " << b_ob.name(); + } + else { + 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 (motion_step > 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]; + float3 *N = (attr_N) ? attr_N->data_float3() : NULL; + for (int step = 0; step < motion_step; step++) { + memcpy(attr_mP->data_float3() + step * numverts, P, sizeof(float3) * numverts); + if (attr_mN) + memcpy(attr_mN->data_float3() + step * numverts, N, sizeof(float3) * numverts); + } + } + } + else { + if (b_mesh.vertices.length() != numverts) { + VLOG(1) << "Topology differs, discarding motion blur for object " << b_ob.name() + << " at time " << motion_step; + memcpy(mP, &mesh->verts[0], sizeof(float3) * numverts); + if (mN != NULL) { + memcpy(mN, attr_N->data_float3(), sizeof(float3) * numverts); + } + } + } + } + + /* hair motion */ + if (numkeys) + sync_curves(mesh, b_mesh, b_ob, true, motion_step); + + /* free derived mesh */ + free_object_to_mesh(b_data, b_ob, b_mesh); } CCL_NAMESPACE_END |