From 82b7c730c55d82ef295ada80971be66d4549241b Mon Sep 17 00:00:00 2001 From: howetuft Date: Thu, 25 Jan 2024 19:35:32 +0100 Subject: [PATCH] Expose vertex normals and tangent space attributes in Cycles XML API The vertex normals and tangent space attributes are not currently exposed by the XML API, in the Mesh node. This notably prevents the XML API user from applying normal maps to meshes in tangent space. To overcome this situation, this commit adds three XML attributes to the Mesh node: 'N' (vertex normals), 'tangent' and 'tangent_sign'. Nota: at the moment, these attributes are only available for non-subdivided meshes. --- src/app/cycles_xml.cpp | 84 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 76 insertions(+), 8 deletions(-) diff --git a/src/app/cycles_xml.cpp b/src/app/cycles_xml.cpp index 5f134e88d..088514280 100644 --- a/src/app/cycles_xml.cpp +++ b/src/app/cycles_xml.cpp @@ -443,7 +443,10 @@ static void xml_read_mesh(const XMLReadState &state, xml_node node) /* read vertices and polygons */ vector P; + vector VN; /* Vertex normals */ vector UV; + vector T; /* UV tangents */ + vector TS; /* UV tangent signs */ vector verts, nverts; xml_read_float3_array(P, node, "P"); @@ -490,12 +493,25 @@ static void xml_read_mesh(const XMLReadState &state, xml_node node) index_offset += nverts[i]; } - if (xml_read_float_array(UV, node, "UV")) { - ustring name = ustring("UVMap"); - Attribute *attr = mesh->attributes.add(ATTR_STD_UV, name); + /* Vertex normals */ + if (xml_read_float3_array(VN, node, Attribute::standard_name(ATTR_STD_VERTEX_NORMAL))) { + Attribute *attr = mesh->attributes.add(ATTR_STD_VERTEX_NORMAL); + float3 *fdata = attr->data_float3(); + + /* Loop over the normals */ + for (auto n : VN) { + fdata[0] = n; + fdata++; + } + } + + /* UV map */ + if (xml_read_float_array(UV, node, "UV") || + xml_read_float_array(UV, node, Attribute::standard_name(ATTR_STD_UV))) { + Attribute *attr = mesh->attributes.add(ATTR_STD_UV); float2 *fdata = attr->data_float2(); - /* loop over the triangles */ + /* Loop over the triangles */ index_offset = 0; for (size_t i = 0; i < nverts.size(); i++) { for (int j = 0; j < nverts[i] - 2; j++) { @@ -516,6 +532,58 @@ static void xml_read_mesh(const XMLReadState &state, xml_node node) index_offset += nverts[i]; } } + + /* Tangents */ + if (xml_read_float_array(T, node, Attribute::standard_name(ATTR_STD_UV_TANGENT))) { + Attribute *attr = mesh->attributes.add(ATTR_STD_UV_TANGENT); + float3 *fdata = attr->data_float3(); + + /* Loop over the triangles */ + index_offset = 0; + for (size_t i = 0; i < nverts.size(); i++) { + for (int j = 0; j < nverts[i] - 2; j++) { + int v0 = index_offset; + int v1 = index_offset + j + 1; + int v2 = index_offset + j + 2; + + assert(v0 * 3 + 2 < (int)T.size()); + assert(v1 * 3 + 2 < (int)T.size()); + assert(v2 * 3 + 2 < (int)T.size()); + + fdata[0] = make_float3(T[v0 * 3], T[v0 * 3 + 1], T[v0 * 3 + 2]); + fdata[1] = make_float3(T[v1 * 3], T[v1 * 3 + 1], T[v1 * 3 + 2]); + fdata[2] = make_float3(T[v2 * 3], T[v2 * 3 + 1], T[v2 * 3 + 2]); + fdata += 3; + } + index_offset += nverts[i]; + } + } + + /* Tangent signs */ + if (xml_read_float_array(TS, node, Attribute::standard_name(ATTR_STD_UV_TANGENT_SIGN))) { + Attribute *attr = mesh->attributes.add(ATTR_STD_UV_TANGENT_SIGN); + float *fdata = attr->data_float(); + + /* Loop over the triangles */ + index_offset = 0; + for (size_t i = 0; i < nverts.size(); i++) { + for (int j = 0; j < nverts[i] - 2; j++) { + int v0 = index_offset; + int v1 = index_offset + j + 1; + int v2 = index_offset + j + 2; + + assert(v0 < (int)TS.size()); + assert(v1 < (int)TS.size()); + assert(v2 < (int)TS.size()); + + fdata[0] = TS[v0]; + fdata[1] = TS[v1]; + fdata[2] = TS[v2]; + fdata += 3; + } + index_offset += nverts[i]; + } + } } else { /* create vertices */ @@ -537,10 +605,10 @@ static void xml_read_mesh(const XMLReadState &state, xml_node node) index_offset += nverts[i]; } - /* uv map */ - if (xml_read_float_array(UV, node, "UV")) { - ustring name = ustring("UVMap"); - Attribute *attr = mesh->subd_attributes.add(ATTR_STD_UV, name); + /* UV map */ + if (xml_read_float_array(UV, node, "UV") || + xml_read_float_array(UV, node, Attribute::standard_name(ATTR_STD_UV))) { + Attribute *attr = mesh->subd_attributes.add(ATTR_STD_UV); float3 *fdata = attr->data_float3(); #if 0 -- 2.30.2