I was wondering why in three.js, MeshLambertMaterial isn’t a subclass of MeshBasicMaterial, if lambert is just the basic material plus simple lighting.
Same thing for phong – MeshPhongMaterial is just a lambert material with phong reflections.
So technically, MeshBasicMaterial should be the base class for MeshLambertMaterial, and MeshLambertMaterial should be the base class for MeshPhongMaterial, am I right? Right now, it is not so in the three.js code – all three of those material classes are “independent” from one another.
Right now those three material classes look like this in three.js:
class MeshBasicMaterial extends Material { }
class MeshLambertMaterial extends Material { }
class MeshPhongMaterial extends Material { }
But, shouldn’t it look like this?
class MeshBasicMaterial extends Material { }
class MeshLambertMaterial extends MeshBasicMaterial { }
class MeshPhongMaterial extends MeshLambertMaterial { }
This is a problem when you are trying do “proper” type checking when working with materials. For example, if you are writing a function that needs to set the color property of a material, you have to know ahead of time of all of the materials that could possibly support a color property, like this:
function setColor(material) {
if((material instanceof MeshBasicMaterial) || (material instanceof MeshLambertMaterial) || (material instanceof MeshPhongMaterial)) {
material.color = new Color(1, 0, 0);
return;
}
throw new Error(`material type ${material} not supported`);
}
On the other hand, if those three material types were in a prototype chain, where MeshBasicMaterial were the highest-level material type that supports a color property, you could simplify your code to this:
function setColor(material) {
if(material instanceof MeshBasicMaterial) {
// we still make it here if the material is MeshLambertMaterial or MeshPhongMaterial
material.color = new Color(1, 0, 0);
return;
}
throw new Error(`material type ${material} not supported`);
}