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/mesh.cpp')
-rw-r--r--intern/cycles/blender/mesh.cpp528
1 files changed, 296 insertions, 232 deletions
diff --git a/intern/cycles/blender/mesh.cpp b/intern/cycles/blender/mesh.cpp
index 63913b7cd7f..1d1eadebc39 100644
--- a/intern/cycles/blender/mesh.cpp
+++ b/intern/cycles/blender/mesh.cpp
@@ -1,6 +1,8 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2011-2022 Blender Foundation */
+#include <optional>
+
#include "blender/session.h"
#include "blender/sync.h"
#include "blender/util.h"
@@ -22,22 +24,23 @@
#include "util/log.h"
#include "util/math.h"
-#include "mikktspace.h"
+#include "mikktspace.hh"
+
+#include "DNA_meshdata_types.h"
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)
+template<bool is_subd> struct MikkMeshWrapper {
+ MikkMeshWrapper(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->get_num_subd_faces()) ? mesh->subd_attributes :
- mesh->attributes;
+ const AttributeSet &attributes = is_subd ? mesh->subd_attributes : mesh->attributes;
Attribute *attr_vN = attributes.find(ATTR_STD_VERTEX_NORMAL);
vertex_normal = attr_vN->data_float3();
@@ -47,7 +50,9 @@ struct MikkUserData {
if (attr_orco) {
orco = attr_orco->data_float3();
+ float3 orco_size;
mesh_texture_space(*(BL::Mesh *)&b_mesh, orco_loc, orco_size);
+ inv_orco_size = 1.0f / orco_size;
}
}
else {
@@ -58,160 +63,126 @@ struct MikkUserData {
}
}
- 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->get_num_subd_faces()) {
- return userdata->mesh->get_num_subd_faces();
- }
- else {
- return userdata->mesh->num_triangles();
+ int GetNumFaces()
+ {
+ if constexpr (is_subd) {
+ return mesh->get_num_subd_faces();
+ }
+ else {
+ return mesh->num_triangles();
+ }
}
-}
-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->get_num_subd_faces()) {
- const Mesh *mesh = userdata->mesh;
- return mesh->get_subd_num_corners()[face_num];
- }
- else {
- return 3;
+ int GetNumVerticesOfFace(const int face_num)
+ {
+ if constexpr (is_subd) {
+ return mesh->get_subd_num_corners()[face_num];
+ }
+ else {
+ return 3;
+ }
}
-}
-static int mikk_vertex_index(const Mesh *mesh, const int face_num, const int vert_num)
-{
- if (mesh->get_num_subd_faces()) {
- const Mesh::SubdFace &face = mesh->get_subd_face(face_num);
- return mesh->get_subd_face_corners()[face.start_corner + vert_num];
- }
- else {
- return mesh->get_triangles()[face_num * 3 + vert_num];
+ int CornerIndex(const int face_num, const int vert_num)
+ {
+ if constexpr (is_subd) {
+ const Mesh::SubdFace &face = mesh->get_subd_face(face_num);
+ return face.start_corner + vert_num;
+ }
+ else {
+ return face_num * 3 + vert_num;
+ }
}
-}
-static int mikk_corner_index(const Mesh *mesh, const int face_num, const int vert_num)
-{
- if (mesh->get_num_subd_faces()) {
- const Mesh::SubdFace &face = mesh->get_subd_face(face_num);
- return face.start_corner + vert_num;
- }
- else {
- return face_num * 3 + vert_num;
+ int VertexIndex(const int face_num, const int vert_num)
+ {
+ int corner = CornerIndex(face_num, vert_num);
+ if constexpr (is_subd) {
+ return mesh->get_subd_face_corners()[corner];
+ }
+ else {
+ return mesh->get_triangles()[corner];
+ }
}
-}
-
-static void mikk_get_position(const SMikkTSpaceContext *context,
- float P[3],
- 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->get_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 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;
+ mikk::float3 GetPosition(const int face_num, const int vert_num)
+ {
+ const float3 vP = mesh->get_verts()[VertexIndex(face_num, vert_num)];
+ return mikk::float3(vP.x, vP.y, vP.z);
}
-}
-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->get_num_subd_faces()) {
- const Mesh::SubdFace &face = mesh->get_subd_face(face_num);
- if (face.smooth) {
- const int vertex_index = mikk_vertex_index(mesh, face_num, vert_num);
- vN = userdata->vertex_normal[vertex_index];
+ mikk::float3 GetTexCoord(const int face_num, const int vert_num)
+ {
+ /* TODO: Check whether introducing a template boolean in order to
+ * turn this into a constexpr is worth it. */
+ if (texface != NULL) {
+ const int corner_index = CornerIndex(face_num, vert_num);
+ float2 tfuv = texface[corner_index];
+ return mikk::float3(tfuv.x, tfuv.y, 1.0f);
+ }
+ else if (orco != NULL) {
+ const int vertex_index = VertexIndex(face_num, vert_num);
+ const float2 uv = map_to_sphere((orco[vertex_index] + orco_loc) * inv_orco_size);
+ return mikk::float3(uv.x, uv.y, 1.0f);
}
else {
- vN = face.normal(mesh);
+ return mikk::float3(0.0f, 0.0f, 1.0f);
}
}
- else {
- if (mesh->get_smooth()[face_num]) {
- const int vertex_index = mikk_vertex_index(mesh, face_num, vert_num);
- vN = userdata->vertex_normal[vertex_index];
+
+ mikk::float3 GetNormal(const int face_num, const int vert_num)
+ {
+ float3 vN;
+ if (is_subd) {
+ const Mesh::SubdFace &face = mesh->get_subd_face(face_num);
+ if (face.smooth) {
+ const int vertex_index = VertexIndex(face_num, vert_num);
+ vN = vertex_normal[vertex_index];
+ }
+ else {
+ vN = face.normal(mesh);
+ }
}
else {
- const Mesh::Triangle tri = mesh->get_triangle(face_num);
- vN = tri.compute_normal(&mesh->get_verts()[0]);
+ if (mesh->get_smooth()[face_num]) {
+ const int vertex_index = VertexIndex(face_num, vert_num);
+ vN = vertex_normal[vertex_index];
+ }
+ else {
+ const Mesh::Triangle tri = mesh->get_triangle(face_num);
+ vN = tri.compute_normal(&mesh->get_verts()[0]);
+ }
}
+ return mikk::float3(vN.x, vN.y, vN.z);
}
- 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)
-{
- 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;
+ void SetTangentSpace(const int face_num, const int vert_num, mikk::float3 T, bool orientation)
+ {
+ const int corner_index = CornerIndex(face_num, vert_num);
+ tangent[corner_index] = make_float3(T.x, T.y, T.z);
+ if (tangent_sign != NULL) {
+ tangent_sign[corner_index] = orientation ? 1.0f : -1.0f;
+ }
}
-}
+
+ const Mesh *mesh;
+ int num_faces;
+
+ float3 *vertex_normal;
+ float2 *texface;
+ float3 *orco;
+ float3 orco_loc, inv_orco_size;
+
+ float3 *tangent;
+ float *tangent_sign;
+};
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->get_num_subd_faces()) ? mesh->subd_attributes :
- mesh->attributes;
+ const bool is_subd = mesh->get_num_subd_faces();
+ AttributeSet &attributes = is_subd ? mesh->subd_attributes : mesh->attributes;
Attribute *attr;
ustring name;
if (layer_name != NULL) {
@@ -247,24 +218,18 @@ static void mikk_compute_tangents(
}
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);
+ if (is_subd) {
+ MikkMeshWrapper<true> userdata(b_mesh, layer_name, mesh, tangent, tangent_sign);
+ /* Compute tangents. */
+ mikk::Mikktspace(userdata).genTangSpace();
+ }
+ else {
+ MikkMeshWrapper<false> userdata(b_mesh, layer_name, mesh, tangent, tangent_sign);
+ /* Compute tangents. */
+ mikk::Mikktspace(userdata).genTangSpace();
+ }
}
template<typename TypeInCycles, typename GetValueAtIndex>
@@ -277,10 +242,15 @@ static void fill_generic_attribute(BL::Mesh &b_mesh,
switch (b_domain) {
case BL::Attribute::domain_CORNER: {
if (subdivision) {
- for (BL::MeshPolygon &p : b_mesh.polygons) {
- int n = p.loop_total();
- for (int i = 0; i < n; i++) {
- *data = get_value_at_index(p.loop_start() + i);
+ const int polys_num = b_mesh.polygons.length();
+ if (polys_num == 0) {
+ return;
+ }
+ const MPoly *polys = static_cast<const MPoly *>(b_mesh.polygons[0].ptr.data);
+ for (int i = 0; i < polys_num; i++) {
+ const MPoly &b_poly = polys[i];
+ for (int j = 0; j < b_poly.totloop; j++) {
+ *data = get_value_at_index(b_poly.loopstart + j);
data++;
}
}
@@ -297,27 +267,32 @@ static void fill_generic_attribute(BL::Mesh &b_mesh,
break;
}
case BL::Attribute::domain_EDGE: {
+ const size_t edges_num = b_mesh.edges.length();
+ if (edges_num == 0) {
+ return;
+ }
if constexpr (std::is_same_v<TypeInCycles, uchar4>) {
/* uchar4 edge attributes do not exist, and averaging in place
* would not work. */
assert(0);
}
else {
- /* Average edge attributes at vertices. */
- const size_t num_verts = b_mesh.vertices.length();
- vector<int> count(num_verts, 0);
-
- for (BL::MeshEdge &e : b_mesh.edges) {
- BL::Array<int, 2> vertices = e.vertices();
- TypeInCycles value = get_value_at_index(e.index());
+ const MEdge *edges = static_cast<const MEdge *>(b_mesh.edges[0].ptr.data);
+ const size_t verts_num = b_mesh.vertices.length();
+ vector<int> count(verts_num, 0);
- data[vertices[0]] += value;
- data[vertices[1]] += value;
- count[vertices[0]]++;
- count[vertices[1]]++;
+ /* Average edge attributes at vertices. */
+ for (int i = 0; i < edges_num; i++) {
+ TypeInCycles value = get_value_at_index(i);
+
+ const MEdge &b_edge = edges[i];
+ data[b_edge.v1] += value;
+ data[b_edge.v2] += value;
+ count[b_edge.v1]++;
+ count[b_edge.v2]++;
}
- for (size_t i = 0; i < num_verts; i++) {
+ for (size_t i = 0; i < verts_num; i++) {
if (count[i] > 1) {
data[i] /= (float)count[i];
}
@@ -601,6 +576,12 @@ static void attr_create_uv_map(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh)
static void attr_create_subd_uv_map(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh, bool subdivide_uvs)
{
+ const int polys_num = b_mesh.polygons.length();
+ if (polys_num == 0) {
+ return;
+ }
+ const MPoly *polys = static_cast<const MPoly *>(b_mesh.polygons[0].ptr.data);
+
if (!b_mesh.uv_layers.empty()) {
BL::Mesh::uv_layers_iterator l;
int i = 0;
@@ -634,10 +615,10 @@ static void attr_create_subd_uv_map(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh,
float2 *fdata = uv_attr->data_float2();
- for (BL::MeshPolygon &p : b_mesh.polygons) {
- int n = p.loop_total();
- for (int j = 0; j < n; j++) {
- *(fdata++) = get_float2(l->data[p.loop_start() + j].uv());
+ for (int i = 0; i < polys_num; i++) {
+ const MPoly &b_poly = polys[i];
+ for (int j = 0; j < b_poly.totloop; j++) {
+ *(fdata++) = get_float2(l->data[b_poly.loopstart + j].uv());
}
}
}
@@ -700,6 +681,8 @@ static void attr_create_pointiness(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh, b
if (num_verts == 0) {
return;
}
+ const MVert *verts = static_cast<const MVert *>(b_mesh.vertices[0].ptr.data);
+
/* STEP 1: Find out duplicated vertices and point duplicates to a single
* original vertex.
*/
@@ -752,10 +735,12 @@ static void attr_create_pointiness(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh, b
*/
vector<float3> vert_normal(num_verts, zero_float3());
/* First we accumulate all vertex normals in the original index. */
+ const float(*b_vert_normals)[3] = static_cast<const float(*)[3]>(
+ b_mesh.vertex_normals[0].ptr.data);
for (int vert_index = 0; vert_index < num_verts; ++vert_index) {
- const float3 normal = get_float3(b_mesh.vertices[vert_index].normal());
+ const float *b_vert_normal = b_vert_normals[vert_index];
const int orig_index = vert_orig_index[vert_index];
- vert_normal[orig_index] += normal;
+ vert_normal[orig_index] += make_float3(b_vert_normal[0], b_vert_normal[1], b_vert_normal[2]);
}
/* Then we normalize the accumulated result and flush it to all duplicates
* as well.
@@ -768,18 +753,24 @@ static void attr_create_pointiness(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh, b
vector<int> counter(num_verts, 0);
vector<float> raw_data(num_verts, 0.0f);
vector<float3> edge_accum(num_verts, zero_float3());
- 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]];
+
+ const MEdge *edges = static_cast<MEdge *>(b_mesh.edges[0].ptr.data);
+ const int edges_num = b_mesh.edges.length();
+
+ for (int i = 0; i < edges_num; i++) {
+ const MEdge &b_edge = edges[i];
+ const int v0 = vert_orig_index[b_edge.v1];
+ const int v1 = vert_orig_index[b_edge.v2];
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());
+ const MVert &b_vert_0 = verts[v0];
+ const MVert &b_vert_1 = verts[v1];
+ float3 co0 = make_float3(b_vert_0.co[0], b_vert_0.co[1], b_vert_0.co[2]);
+ float3 co1 = make_float3(b_vert_1.co[0], b_vert_1.co[1], b_vert_1.co[2]);
float3 edge = normalize(co1 - co0);
edge_accum[v0] += edge;
edge_accum[v1] += -edge;
@@ -807,11 +798,11 @@ static void attr_create_pointiness(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh, b
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]];
+ for (int i = 0; i < edges_num; i++) {
+ const MEdge &b_edge = edges[i];
+ const int v0 = vert_orig_index[b_edge.v1];
+ const int v1 = vert_orig_index[b_edge.v2];
if (visited_edges.exists(v0, v1)) {
continue;
}
@@ -850,6 +841,7 @@ static void attr_create_random_per_island(Scene *scene,
return;
}
+ const int polys_num = b_mesh.polygons.length();
int number_of_vertices = b_mesh.vertices.length();
if (number_of_vertices == 0) {
return;
@@ -857,8 +849,11 @@ static void attr_create_random_per_island(Scene *scene,
DisjointSet vertices_sets(number_of_vertices);
- for (BL::MeshEdge &e : b_mesh.edges) {
- vertices_sets.join(e.vertices()[0], e.vertices()[1]);
+ const MEdge *edges = static_cast<MEdge *>(b_mesh.edges[0].ptr.data);
+ const int edges_num = b_mesh.edges.length();
+
+ for (int i = 0; i < edges_num; i++) {
+ vertices_sets.join(edges[i].v1, edges[i].v2);
}
AttributeSet &attributes = (subdivision) ? mesh->subd_attributes : mesh->attributes;
@@ -871,14 +866,37 @@ static void attr_create_random_per_island(Scene *scene,
}
}
else {
- for (BL::MeshPolygon &p : b_mesh.polygons) {
- data[p.index()] = hash_uint_to_float(vertices_sets.find(p.vertices()[0]));
+ if (polys_num != 0) {
+ const MPoly *polys = static_cast<const MPoly *>(b_mesh.polygons[0].ptr.data);
+ const MLoop *loops = static_cast<const MLoop *>(b_mesh.loops[0].ptr.data);
+ for (int i = 0; i < polys_num; i++) {
+ const MPoly &b_poly = polys[i];
+ const MLoop &b_loop = loops[b_poly.loopstart];
+ data[i] = hash_uint_to_float(vertices_sets.find(b_loop.v));
+ }
}
}
}
/* Create Mesh */
+static std::optional<BL::IntAttribute> find_material_index_attribute(BL::Mesh b_mesh)
+{
+ for (BL::Attribute &b_attribute : b_mesh.attributes) {
+ if (b_attribute.domain() != BL::Attribute::domain_FACE) {
+ continue;
+ }
+ if (b_attribute.data_type() != BL::Attribute::data_type_INT) {
+ continue;
+ }
+ if (b_attribute.name() != "material_index") {
+ continue;
+ }
+ return BL::IntAttribute{b_attribute};
+ }
+ return std::nullopt;
+}
+
static void create_mesh(Scene *scene,
Mesh *mesh,
BL::Mesh &b_mesh,
@@ -890,6 +908,7 @@ static void create_mesh(Scene *scene,
{
/* count vertices and faces */
int numverts = b_mesh.vertices.length();
+ const int polys_num = b_mesh.polygons.length();
int numfaces = (!subdivision) ? b_mesh.loop_triangles.length() : b_mesh.polygons.length();
int numtris = 0;
int numcorners = 0;
@@ -902,13 +921,17 @@ static void create_mesh(Scene *scene,
return;
}
+ const MVert *verts = static_cast<const MVert *>(b_mesh.vertices[0].ptr.data);
+
if (!subdivision) {
numtris = numfaces;
}
else {
- for (BL::MeshPolygon &p : b_mesh.polygons) {
- numngons += (p.loop_total() == 4) ? 0 : 1;
- numcorners += p.loop_total();
+ const MPoly *polys = static_cast<const MPoly *>(b_mesh.polygons[0].ptr.data);
+ for (int i = 0; i < polys_num; i++) {
+ const MPoly &b_poly = polys[i];
+ numngons += (b_poly.totloop == 4) ? 0 : 1;
+ numcorners += b_poly.totloop;
}
}
@@ -920,17 +943,23 @@ static void create_mesh(Scene *scene,
mesh->reserve_mesh(numverts, numtris);
/* 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()));
+ for (int i = 0; i < numverts; i++) {
+ const MVert &b_vert = verts[i];
+ mesh->add_vertex(make_float3(b_vert.co[0], b_vert.co[1], b_vert.co[2]));
+ }
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();
+ if (subdivision || !use_loop_normals) {
+ const float(*b_vert_normals)[3] = static_cast<const float(*)[3]>(
+ b_mesh.vertex_normals[0].ptr.data);
+ for (int i = 0; i < numverts; i++) {
+ const float *b_vert_normal = b_vert_normals[i];
+ N[i] = make_float3(b_vert_normal[0], b_vert_normal[1], b_vert_normal[2]);
+ }
+ }
/* create generated coordinates from undeformed coordinates */
const bool need_default_tangent = (subdivision == false) && (b_mesh.uv_layers.empty()) &&
@@ -945,19 +974,30 @@ static void create_mesh(Scene *scene,
float3 *generated = attr->data_float3();
size_t i = 0;
+ BL::Mesh::vertices_iterator v;
for (b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v) {
generated[i++] = get_float3(v->undeformed_co()) * size - loc;
}
}
+ std::optional<BL::IntAttribute> material_indices = find_material_index_attribute(b_mesh);
+ auto get_material_index = [&](const int poly_index) -> int {
+ if (material_indices) {
+ return clamp(material_indices->data[poly_index].value(), 0, used_shaders.size() - 1);
+ }
+ return 0;
+ };
+
/* create faces */
+ const MPoly *polys = static_cast<const MPoly *>(b_mesh.polygons[0].ptr.data);
if (!subdivision) {
for (BL::MeshLoopTriangle &t : b_mesh.loop_triangles) {
- BL::MeshPolygon p = b_mesh.polygons[t.polygon_index()];
+ const int poly_index = t.polygon_index();
+ const MPoly &b_poly = polys[poly_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;
+ int shader = get_material_index(poly_index);
+ bool smooth = (b_poly.flag & ME_SMOOTH) || use_loop_normals;
if (use_loop_normals) {
BL::Array<float, 9> loop_normals = t.split_normals();
@@ -977,15 +1017,19 @@ static void create_mesh(Scene *scene,
else {
vector<int> vi;
- for (BL::MeshPolygon &p : b_mesh.polygons) {
- int n = p.loop_total();
- int shader = clamp(p.material_index(), 0, used_shaders.size() - 1);
- bool smooth = p.use_smooth() || use_loop_normals;
+ const MLoop *loops = static_cast<const MLoop *>(b_mesh.loops[0].ptr.data);
+
+ for (int i = 0; i < numfaces; i++) {
+ const MPoly &b_poly = polys[i];
+ int n = b_poly.totloop;
+ int shader = get_material_index(i);
+ bool smooth = (b_poly.flag & ME_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();
+
+ vi[i] = loops[b_poly.loopstart + i].v;
}
/* create subd faces */
@@ -1038,27 +1082,33 @@ static void create_subd_mesh(Scene *scene,
create_mesh(scene, mesh, b_mesh, used_shaders, need_motion, motion_scale, true, subdivide_uvs);
- /* export creases */
- size_t num_creases = 0;
+ const int edges_num = b_mesh.edges.length();
+
+ if (edges_num != 0) {
+ size_t num_creases = 0;
+ const MEdge *edges = static_cast<MEdge *>(b_mesh.edges[0].ptr.data);
- for (BL::MeshEdge &e : b_mesh.edges) {
- if (e.crease() != 0.0f) {
- num_creases++;
+ for (int i = 0; i < edges_num; i++) {
+ const MEdge &b_edge = edges[i];
+ if (b_edge.crease != 0) {
+ num_creases++;
+ }
}
- }
- mesh->reserve_subd_creases(num_creases);
+ mesh->reserve_subd_creases(num_creases);
- for (BL::MeshEdge &e : b_mesh.edges) {
- if (e.crease() != 0.0f) {
- mesh->add_edge_crease(e.vertices()[0], e.vertices()[1], e.crease());
+ for (int i = 0; i < edges_num; i++) {
+ const MEdge &b_edge = edges[i];
+ if (b_edge.crease != 0) {
+ mesh->add_edge_crease(b_edge.v1, b_edge.v2, float(b_edge.crease) / 255.0f);
+ }
}
- }
- for (BL::MeshVertexCreaseLayer &c : b_mesh.vertex_creases) {
- for (int i = 0; i < c.data.length(); ++i) {
- if (c.data[i].value() != 0.0f) {
- mesh->add_vertex_crease(i, c.data[i].value());
+ for (BL::MeshVertexCreaseLayer &c : b_mesh.vertex_creases) {
+ for (int i = 0; i < c.data.length(); ++i) {
+ if (c.data[i].value() != 0.0f) {
+ mesh->add_vertex_crease(i, c.data[i].value());
+ }
}
}
}
@@ -1179,6 +1229,12 @@ void BlenderSync::sync_mesh_motion(BL::Depsgraph b_depsgraph,
/* TODO(sergey): Perform preliminary check for number of vertices. */
if (b_mesh) {
+ const int b_verts_num = b_mesh.vertices.length();
+ if (b_verts_num == 0) {
+ free_object_to_mesh(b_data, b_ob_info, b_mesh);
+ return;
+ }
+
/* Export deformed coordinates. */
/* Find attributes. */
Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
@@ -1196,22 +1252,30 @@ void BlenderSync::sync_mesh_motion(BL::Depsgraph b_depsgraph,
/* 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;
+
+ const MVert *verts = static_cast<const MVert *>(b_mesh.vertices[0].ptr.data);
+
/* 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());
+ for (int i = 0; i < std::min<size_t>(b_verts_num, numverts); i++) {
+ const MVert &b_vert = verts[i];
+ mP[i] = make_float3(b_vert.co[0], b_vert.co[1], b_vert.co[2]);
+ }
+ if (mN) {
+ const float(*b_vert_normals)[3] = static_cast<const float(*)[3]>(
+ b_mesh.vertex_normals[0].ptr.data);
+ for (int i = 0; i < std::min<size_t>(b_verts_num, numverts); i++) {
+ const float *b_vert_normal = b_vert_normals[i];
+ mN[i] = make_float3(b_vert_normal[0], b_vert_normal[1], b_vert_normal[2]);
+ }
}
if (new_attribute) {
/* In case of new attribute, we verify if there really was any motion. */
- if (b_mesh.vertices.length() != numverts ||
+ if (b_verts_num != numverts ||
memcmp(mP, &mesh->get_verts()[0], sizeof(float3) * numverts) == 0) {
/* no motion, remove attributes again */
- if (b_mesh.vertices.length() != numverts) {
+ if (b_verts_num != numverts) {
VLOG_WARNING << "Topology differs, disabling motion blur for object " << ob_name;
}
else {
@@ -1235,7 +1299,7 @@ void BlenderSync::sync_mesh_motion(BL::Depsgraph b_depsgraph,
}
}
else {
- if (b_mesh.vertices.length() != numverts) {
+ if (b_verts_num != numverts) {
VLOG_WARNING << "Topology differs, discarding motion blur for object " << ob_name
<< " at time " << motion_step;
memcpy(mP, &mesh->get_verts()[0], sizeof(float3) * numverts);