Hi @ankitm,
Here is my code to smooth the normals. Please note that I have renamed ccl::Mesh->triangles field to “indices”. Please let me know if my approach is wrong.
BTW, when I smooth normals with this approach (The same way blender/cycles does), I am facing an issue which is explained at Odd triangle in my mesh
Please let me know if any improvements can be done.
static void smooth_normals(ccl::Mesh &mesh)
{
Attribute *attr_vN = mesh.attributes.find(ATTR_STD_VERTEX_NORMAL);
if (!attr_vN) {
return;
}
float3 *vN = attr_vN->data_float3();
int indices_count = mesh.indices.size();
int vertices_count = mesh.verts.size();
memset(vN, 0, vertices_count * sizeof(float3));
bool flip = mesh.transform_negative_scaled;
std::unordered_map<float3, size_t, Float3Hash, Float3Equals> unique_positions_map;
std::vector<float3> normals;
normals.resize(0);
Transform ntfm;
if (mesh.transform_applied) {
ntfm = transform_inverse(mesh.transform_normal);
}
for (int i = 0, t = 0; i < indices_count; i += 3, t++) {
int i0 = mesh.indices[i];
int i1 = mesh.indices[i + 1];
int i2 = mesh.indices[i + 2];
float3 &v0 = mesh.verts[i0];
float3 &v1 = mesh.verts[i1];
float3 &v2 = mesh.verts[i2];
float3 &face_normal = GeometryUtils::compute_normal(v0, v1, v2);
if (mesh.transform_applied) {
face_normal = normalize(transform_direction(&ntfm, face_normal));
}
size_t ni0 = 0;
size_t ni1 = 0;
size_t ni2 = 0;
if (unique_positions_map.find(v0) == unique_positions_map.end()) {
ni0 = unique_positions_map.size();
unique_positions_map.insert(std::pair<float3, size_t>(v0, ni0));
normals.push_back(make_float3(0, 0, 0));
}
else {
ni0 = unique_positions_map.at(v0);
}
if (unique_positions_map.find(v1) == unique_positions_map.end()) {
ni1 = unique_positions_map.size();
unique_positions_map.insert(std::pair<float3, size_t>(v1, ni1));
normals.push_back(make_float3(0, 0, 0));
}
else {
ni1 = unique_positions_map.at(v1);
}
if (unique_positions_map.find(v2) == unique_positions_map.end()) {
ni2 = unique_positions_map.size();
unique_positions_map.insert(std::pair<float3, size_t>(v2, ni2));
normals.push_back(make_float3(0, 0, 0));
}
else {
ni2 = unique_positions_map.at(v2);
}
normals[ni0] += face_normal;
normals[ni1] += face_normal;
normals[ni2] += face_normal;
}
int normals_count = normals.size();
for (size_t i = 0; i < normals_count; i++) {
normals[i] = normalize(normals[i]);
if (flip) {
normals[i] = -normals[i];
}
}
for (size_t i = 0; i < vertices_count; i++) {
float3 &position = mesh.verts[i];
size_t normal_index = unique_positions_map.at(position);
vN[i] = normals[normal_index];
}
}