computeVertexNormals method
void
computeVertexNormals()
Computes vertex normals for the given vertex data. For indexed geometries, the method sets each vertex normal to be the average of the face normals of the faces that share that vertex.
For non-indexed geometries, vertices are not shared, and the method sets each vertex normal to be the same as the face normal.
Implementation
/// For non-indexed geometries, vertices are not shared, and the method sets each vertex normal to be the same as the face normal.
void computeVertexNormals() {
final index = this.index;
final positionAttribute = getAttributeFromString('position');
if (positionAttribute != null) {
Float32BufferAttribute? normalAttribute = getAttributeFromString('normal');
if (normalAttribute == null) {
final array = List<double>.filled(positionAttribute.count * 3, 0);
normalAttribute = Float32BufferAttribute.fromList(array, 3, false);
setAttributeFromString('normal', normalAttribute);
}
else {
// reset existing normals to zero
for (int i = 0, il = normalAttribute.count; i < il; i++) {
normalAttribute.setXYZ(i, 0, 0, 0);
}
}
final pA = Vector3.zero(), pB = Vector3.zero(), pC = Vector3.zero();
final nA = Vector3.zero(), nB = Vector3.zero(), nC = Vector3.zero();
final cb = Vector3.zero(), ab = Vector3.zero();
// indexed elements
if (index != null) {
for (int i = 0, il = index.count; i < il; i += 3) {
final vA = index.getX(i + 0)!.toInt();
final vB = index.getX(i + 1)!.toInt();
final vC = index.getX(i + 2)!.toInt();
pA.fromBuffer(positionAttribute, vA);
pB.fromBuffer(positionAttribute, vB);
pC.fromBuffer(positionAttribute, vC);
cb.sub2(pC, pB);
ab.sub2(pA, pB);
cb.cross(ab);
nA.fromBuffer(normalAttribute, vA);
nB.fromBuffer(normalAttribute, vB);
nC.fromBuffer(normalAttribute, vC);
nA.add(cb);
nB.add(cb);
nC.add(cb);
normalAttribute.setXYZ(vA, nA.x, nA.y, nA.z);
normalAttribute.setXYZ(vB, nB.x, nB.y, nB.z);
normalAttribute.setXYZ(vC, nC.x, nC.y, nC.z);
}
}
else {
for (int i = 0, il = positionAttribute.count; i < il; i += 3) {
pA.fromBuffer(positionAttribute, i + 0);
pB.fromBuffer(positionAttribute, i + 1);
pC.fromBuffer(positionAttribute, i + 2);
cb.sub2(pC, pB);
ab.sub2(pA, pB);
cb.cross(ab);
normalAttribute.setXYZ(i + 0, cb.x, cb.y, cb.z);
normalAttribute.setXYZ(i + 1, cb.x, cb.y, cb.z);
normalAttribute.setXYZ(i + 2, cb.x, cb.y, cb.z);
}
}
normalizeNormals();
normalAttribute.needsUpdate = true;
}
}