Fix (partial) T47198: Cycles have broken UVs in some degenerated quads cases

The issue was discontinuity in logic when importing vertices from blender
and then importing data layers regardless of how we split the face. Quite
interesting we didn't notice this issue before.

Thanks Bastien for the investigation, based on D1742 but redid it to make
patch a bit more clear to follow.
This commit is contained in:
Sergey Sharybin 2016-01-20 09:13:04 +01:00
parent 7e9feac3e0
commit a6eae73391
Notes: blender-bot 2024-04-11 14:26:06 +02:00
Referenced by commit 54d3506253, Fix error in rBa6eae7339190.
Referenced by commit bf5ddb9728, Fix T47198: Broken UV/VCol in BI and Cycles with some degenerated faces - BI part.
Referenced by issue #47213, World Sampling in Cycles broken when rendering with GPU
1 changed files with 121 additions and 31 deletions

View File

@ -35,6 +35,48 @@
CCL_NAMESPACE_BEGIN
/* Per-face bit flags. */
enum {
/* Face has no special flags. */
FACE_FLAG_NONE = (0 << 0),
/* Quad face was split using 1-3 diagonal. */
FACE_FLAG_DIVIDE_13 = (1 << 0),
/* Quad face was split using 2-4 diagonal. */
FACE_FLAG_DIVIDE_24 = (1 << 1),
};
/* Get vertex indices to create triangles from a given face.
*
* Two triangles has vertex indices in the original Blender-side face.
* If face is already a quad tri_b will not be initialized.
*/
inline void face_split_tri_indices(const int num_verts,
const int face_flag,
int tri_a[3],
int tri_b[3])
{
if(face_flag & FACE_FLAG_DIVIDE_24) {
tri_a[0] = 0;
tri_a[1] = 1;
tri_a[2] = 3;
if(num_verts == 4) {
tri_b[0] = 2;
tri_b[1] = 3;
tri_b[2] = 1;
}
}
else /*if(face_flag & FACE_FLAG_DIVIDE_13)*/ {
tri_a[0] = 0;
tri_a[1] = 1;
tri_a[2] = 2;
if(num_verts == 4) {
tri_b[0] = 0;
tri_b[1] = 2;
tri_b[2] = 3;
}
}
}
/* Tangent Space */
struct MikkUserData {
@ -140,7 +182,13 @@ static void mikk_set_tangent_space(const SMikkTSpaceContext *context, const floa
userdata->tangent[face*4 + vert] = make_float4(T[0], T[1], T[2], sign);
}
static void mikk_compute_tangents(BL::Mesh b_mesh, BL::MeshTextureFaceLayer *b_layer, Mesh *mesh, const vector<int>& nverts, bool need_sign, bool active_render)
static void mikk_compute_tangents(BL::Mesh b_mesh,
BL::MeshTextureFaceLayer *b_layer,
Mesh *mesh,
const vector<int>& nverts,
const vector<int>& face_flags,
bool need_sign,
bool active_render)
{
/* setup userdata */
MikkUserData userdata(b_mesh, b_layer, nverts.size());
@ -199,28 +247,31 @@ static void mikk_compute_tangents(BL::Mesh b_mesh, BL::MeshTextureFaceLayer *b_l
}
for(int i = 0; i < nverts.size(); i++) {
tangent[0] = float4_to_float3(userdata.tangent[i*4 + 0]);
tangent[1] = float4_to_float3(userdata.tangent[i*4 + 1]);
tangent[2] = float4_to_float3(userdata.tangent[i*4 + 2]);
int tri_a[3], tri_b[3];
face_split_tri_indices(nverts[i], face_flags[i], tri_a, tri_b);
tangent[0] = float4_to_float3(userdata.tangent[i*4 + tri_a[0]]);
tangent[1] = float4_to_float3(userdata.tangent[i*4 + tri_a[1]]);
tangent[2] = float4_to_float3(userdata.tangent[i*4 + tri_a[2]]);
tangent += 3;
if(tangent_sign) {
tangent_sign[0] = userdata.tangent[i*4 + 0].w;
tangent_sign[1] = userdata.tangent[i*4 + 1].w;
tangent_sign[2] = userdata.tangent[i*4 + 2].w;
tangent_sign[0] = userdata.tangent[i*4 + tri_a[0]].w;
tangent_sign[1] = userdata.tangent[i*4 + tri_a[1]].w;
tangent_sign[2] = userdata.tangent[i*4 + tri_a[2]].w;
tangent_sign += 3;
}
if(nverts[i] == 4) {
tangent[0] = float4_to_float3(userdata.tangent[i*4 + 0]);
tangent[1] = float4_to_float3(userdata.tangent[i*4 + 2]);
tangent[2] = float4_to_float3(userdata.tangent[i*4 + 3]);
tangent[0] = float4_to_float3(userdata.tangent[i*4 + tri_b[0]]);
tangent[1] = float4_to_float3(userdata.tangent[i*4 + tri_b[1]]);
tangent[2] = float4_to_float3(userdata.tangent[i*4 + tri_b[2]]);
tangent += 3;
if(tangent_sign) {
tangent_sign[0] = userdata.tangent[i*4 + 0].w;
tangent_sign[1] = userdata.tangent[i*4 + 2].w;
tangent_sign[2] = userdata.tangent[i*4 + 3].w;
tangent_sign[0] = userdata.tangent[i*4 + tri_b[0]].w;
tangent_sign[1] = userdata.tangent[i*4 + tri_b[1]].w;
tangent_sign[2] = userdata.tangent[i*4 + tri_b[2]].w;
tangent_sign += 3;
}
}
@ -273,7 +324,8 @@ static void create_mesh_volume_attributes(Scene *scene, BL::Object b_ob, Mesh *m
static void attr_create_vertex_color(Scene *scene,
Mesh *mesh,
BL::Mesh b_mesh,
const vector<int>& nverts)
const vector<int>& nverts,
const vector<int>& face_flags)
{
BL::Mesh::tessface_vertex_colors_iterator l;
for(b_mesh.tessface_vertex_colors.begin(l); l != b_mesh.tessface_vertex_colors.end(); ++l) {
@ -288,14 +340,25 @@ static void attr_create_vertex_color(Scene *scene,
size_t i = 0;
for(l->data.begin(c); c != l->data.end(); ++c, ++i) {
cdata[0] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color1())));
cdata[1] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color2())));
cdata[2] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color3())));
int tri_a[3], tri_b[3];
face_split_tri_indices(nverts[i], face_flags[i], tri_a, tri_b);
uchar4 colors[4];
colors[0] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color1())));
colors[1] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color2())));
colors[2] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color3())));
if(nverts[i] == 4) {
colors[3] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color4())));
}
cdata[0] = colors[tri_a[0]];
cdata[1] = colors[tri_a[1]];
cdata[2] = colors[tri_a[2]];
if(nverts[i] == 4) {
cdata[3] = cdata[0];
cdata[4] = cdata[2];
cdata[5] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color4())));
cdata[3] = colors[tri_b[0]];
cdata[4] = colors[tri_b[1]];
cdata[5] = colors[tri_b[2]];
cdata += 6;
}
else
@ -308,7 +371,8 @@ static void attr_create_vertex_color(Scene *scene,
static void attr_create_uv_map(Scene *scene,
Mesh *mesh,
BL::Mesh b_mesh,
const vector<int>& nverts)
const vector<int>& nverts,
const vector<int>& face_flags)
{
if(b_mesh.tessface_uv_textures.length() != 0) {
BL::Mesh::tessface_uv_textures_iterator l;
@ -332,15 +396,26 @@ static void attr_create_uv_map(Scene *scene,
size_t i = 0;
for(l->data.begin(t); t != l->data.end(); ++t, ++i) {
fdata[0] = get_float3(t->uv1());
fdata[1] = get_float3(t->uv2());
fdata[2] = get_float3(t->uv3());
int tri_a[3], tri_b[3];
face_split_tri_indices(nverts[i], face_flags[i], tri_a, tri_b);
float3 uvs[4];
uvs[0] = get_float3(t->uv1());
uvs[1] = get_float3(t->uv2());
uvs[2] = get_float3(t->uv3());
if(nverts[i] == 4) {
uvs[3] = get_float3(t->uv4());
}
fdata[0] = uvs[tri_a[0]];
fdata[1] = uvs[tri_a[1]];
fdata[2] = uvs[tri_a[2]];
fdata += 3;
if(nverts[i] == 4) {
fdata[0] = get_float3(t->uv1());
fdata[1] = get_float3(t->uv3());
fdata[2] = get_float3(t->uv4());
fdata[0] = uvs[tri_b[0]];
fdata[1] = uvs[tri_b[0]];
fdata[2] = uvs[tri_b[0]];
fdata += 3;
}
}
@ -355,13 +430,25 @@ static void attr_create_uv_map(Scene *scene,
name = ustring((string(l->name().c_str()) + ".tangent_sign").c_str());
bool need_sign = (mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std));
mikk_compute_tangents(b_mesh, &(*l), mesh, nverts, need_sign, active_render);
mikk_compute_tangents(b_mesh,
&(*l),
mesh,
nverts,
face_flags,
need_sign,
active_render);
}
}
}
else if(mesh->need_attribute(scene, ATTR_STD_UV_TANGENT)) {
bool need_sign = mesh->need_attribute(scene, ATTR_STD_UV_TANGENT_SIGN);
mikk_compute_tangents(b_mesh, NULL, mesh, nverts, need_sign, true);
mikk_compute_tangents(b_mesh,
NULL,
mesh,
nverts,
face_flags,
need_sign,
true);
}
}
@ -482,6 +569,7 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<
/* create faces */
vector<int> nverts(numfaces);
vector<int> face_flags(numfaces, FACE_FLAG_NONE);
int fi = 0, ti = 0;
for(b_mesh.tessfaces.begin(f); f != b_mesh.tessfaces.end(); ++f, ++fi) {
@ -519,10 +607,12 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<
{
mesh->set_triangle(ti++, vi[0], vi[1], vi[3], shader, smooth);
mesh->set_triangle(ti++, vi[2], vi[3], vi[1], shader, smooth);
face_flags[fi] |= FACE_FLAG_DIVIDE_24;
}
else {
mesh->set_triangle(ti++, vi[0], vi[1], vi[2], shader, smooth);
mesh->set_triangle(ti++, vi[0], vi[2], vi[3], shader, smooth);
face_flags[fi] |= FACE_FLAG_DIVIDE_13;
}
}
else
@ -534,8 +624,8 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<
/* Create all needed attributes.
* The calculate functions will check whether they're needed or not.
*/
attr_create_vertex_color(scene, mesh, b_mesh, nverts);
attr_create_uv_map(scene, mesh, b_mesh, nverts);
attr_create_vertex_color(scene, mesh, b_mesh, nverts, face_flags);
attr_create_uv_map(scene, mesh, b_mesh, nverts, face_flags);
/* for volume objects, create a matrix to transform from object space to
* mesh texture space. this does not work with deformations but that can