Hi, community!
There were several similar questions on SO about how to compute the volume of a geometry.
I wrote a function, that computes the volume of an buffer geometry (both indexed and non-indexed):
function getVolume(geometry) {
if (!geometry.isBufferGeometry) {
console.log("'geometry' must be an indexed or non-indexed buffer geometry");
return 0;
}
var isIndexed = geometry.index !== null;
let position = geometry.attributes.position;
let sum = 0;
let p1 = new THREE.Vector3(),
p2 = new THREE.Vector3(),
p3 = new THREE.Vector3();
if (!isIndexed) {
let faces = position.count / 3;
for (let i = 0; i < faces; i++) {
p1.fromBufferAttribute(position, i * 3 + 0);
p2.fromBufferAttribute(position, i * 3 + 1);
p3.fromBufferAttribute(position, i * 3 + 2);
sum += signedVolumeOfTriangle(p1, p2, p3);
}
}
else {
let index = geometry.index;
let faces = index.count / 3;
for (let i = 0; i < faces; i++){
p1.fromBufferAttribute(position, index.array[i * 3 + 0]);
p2.fromBufferAttribute(position, index.array[i * 3 + 1]);
p3.fromBufferAttribute(position, index.array[i * 3 + 2]);
sum += signedVolumeOfTriangle(p1, p2, p3);
}
}
return sum;
}
function signedVolumeOfTriangle(p1, p2, p3) {
return p1.dot(p2.cross(p3)) / 6.0;
}
Here is a codepen (have a look at the browser console):
Related SO topics:
PS I hope I didn’t re-invent a bicycle. If I did, just let me know
I like it. The method is well-known, but I believe having clear and usable code for it available will be helpful. Have you considered doing a PR to three.js, making it a BufferGeometry method?
If I remember right, the method requires the surface to be closed. Would you be able to detect whether or not the surface is closed, perhaps spitting out a warning if it is not?
Does scale of mesh affect volume calculating of BufferGeometry?
I have calculated volume, then changed scale of mesh, finally recalculate the volume and numbers were the same.
Should I do something special to recalculate it after scale change?
Thanks
Working fine with TextGeometry and scaling.
But what about BufferGeometry?
Im using method provided in first post in this thread to calculate volume.
Im using three.js for the first time, so sorry if my questions are obvious.
And what about it?
Feel free to modify the code, provided in the main post. You can multiply p1, p2, p3 with scaling vector (if you scale the mesh non-uniformly), or simply multiply the result with the scaling factor (in the case of uniform scaling), like @Fyrestar said before.
In fact, to scale a volume, just multiply the unscaled volume by the product of the three scale dimensions, regardless of whether the scaling is uniform or not (so scale**3 for uniform scale). There is no need to recalculate per face.
Apparently, it works on pure geometry, i.e. ignoring all transformations that occur in the vertex shader. If you can afford to apply all the transformations/animation to the geometry itself, the method may work as it is. Otherwise, you may have to try a different approach. Hm, it may perhaps be possible to “trick” a fragment shader into generating similar measurements…