Three.js: Document removal of MultiMaterial

Created on 4 Mar 2017  路  14Comments  路  Source: mrdoob/three.js

Description of the problem

I see in 6f5223951d1e08f9da08d81c6c5d56d0b2a4b8ea and a few related commits that MultiMaterial is being removed (not exactly "deprecated"). There remains some code referencing MultiMaterial throughout the repo, such as ColladaLoader, which is now broken.

I don't see any documentation on this, either in the doc files or in an issue. Can someone please explain how MultiMaterial's functionality is to be replaced? Is there a particular reason for the removal?

Three.js version
  • [x] Dev
  • [ ] r84
  • [ ] ...
Browser
  • [x] All of them
  • [ ] Chrome
  • [ ] Firefox
  • [ ] Internet Explorer
OS
  • [x] All of them
  • [ ] Windows
  • [ ] Linux
  • [ ] Android
  • [ ] IOS
Question

Most helpful comment

The editor now also has minimal support (import, export but not edit).

screen shot 2017-03-30 at 19 32 50

All 14 comments

The change was proposed in https://github.com/mrdoob/three.js/issues/8924.

With the adopted API, both of these patterns are now acceptable:

var mesh = new THREE.Mesh( geometry, material ); // a single material

var mesh = new THREE.Mesh( geometry, materials ); // an array of materials

Thanks @WestLangley.

I'm sure others could still benefit from an update to the docs.

It looks like right now the Mesh just blindly takes whatever you give it, which is going to break a lot of old code and make it a little trickier to inspect Meshes' materials. I quite like the pattern you proposed here.

which is going to break a lot of old code and make it a little trickier to inspect Meshes' materials.

How so?

It looks like right now the Mesh just blindly takes whatever you give it, which is going to break a lot of old code

Not at all (and it won't break anything).
Finally, the current approach is the right one.
Now you can perform the following task:

if ( object.material.length > 1 ) {
    for (var m = 0; m < object.material.length; m++) {
        object.material[m].color.set( 0xffffff );
    }
} else {
    object.material.color.set( 0xffffff );
}

I would use Array.isArray()...

if ( Array.isArray( object.material ) ) {
    for ( var m = 0; m < object.material.length; m ++ ) {
        object.material[ m ].color.set( 0xffffff );
    }
} else {
    object.material.color.set( 0xffffff );
}

Okay, serialisation/deserialisation is done 鉁岋笍

So, from now on... this code:

var geometry = new THREE.BoxBufferGeometry( 1, 1, 1 );
var materials = [
    new THREE.MeshDepthMaterial(),
    new THREE.MeshNormalMaterial(),
    new THREE.MeshBasicMaterial( { wireframe: true } ),
    new THREE.MeshLambertMaterial( { color: 0xff0000 } ),
    new THREE.MeshPhongMaterial( { color: 0x0000ff } ),
    new THREE.MeshStandardMaterial( { color: 0x00ff00 } ),
];
var mesh = new THREE.Mesh( geometry, materials );
mesh.toJSON();

produces this:

{
    "metadata": {
        "version": 4.5,
        "type": "Object",
        "generator": "Object3D.toJSON"
    },
    "geometries": [
        {
            "uuid": "BC2110E2-3EA4-4C37-9041-DE1A49F5C06B",
            "type": "BoxBufferGeometry",
            "width": 1,
            "height": 1,
            "depth": 1
        }
    ],
    "materials": [
        {
            "uuid": "81EDCE16-A1EC-40B6-A4F3-D34374C6DF5A",
            "type": "MeshDepthMaterial",
            "depthFunc": 3,
            "depthTest": true,
            "depthWrite": true,
            "skinning": false,
            "morphTargets": false,
            "dithering": false
        },
        {
            "uuid": "8BBB3EE7-B8BD-4441-8CBF-B01A73DE1D9E",
            "type": "MeshNormalMaterial",
            "depthFunc": 3,
            "depthTest": true,
            "depthWrite": true,
            "skinning": false,
            "morphTargets": false,
            "dithering": false
        },
        {
            "uuid": "D3CD2958-6E36-42CE-B4C4-688B670CF8CD",
            "type": "MeshBasicMaterial",
            "color": 16777215,
            "depthFunc": 3,
            "depthTest": true,
            "depthWrite": true,
            "wireframe": true,
            "skinning": false,
            "morphTargets": false,
            "dithering": false
        },
        {
            "uuid": "22156F77-0963-4C68-99A7-BDE887313F2A",
            "type": "MeshLambertMaterial",
            "color": 16711680,
            "emissive": 0,
            "depthFunc": 3,
            "depthTest": true,
            "depthWrite": true,
            "skinning": false,
            "morphTargets": false,
            "dithering": false
        },
        {
            "uuid": "49C93E84-FD7F-49F4-AA55-9769194E25E8",
            "type": "MeshPhongMaterial",
            "color": 255,
            "emissive": 0,
            "specular": 1118481,
            "shininess": 30,
            "depthFunc": 3,
            "depthTest": true,
            "depthWrite": true,
            "skinning": false,
            "morphTargets": false,
            "dithering": false
        },
        {
            "uuid": "F8B0E57E-B25C-4A16-B917-4EE615B2B6D4",
            "type": "MeshStandardMaterial",
            "color": 65280,
            "roughness": 0.5,
            "metalness": 0.5,
            "emissive": 0,
            "depthFunc": 3,
            "depthTest": true,
            "depthWrite": true,
            "skinning": false,
            "morphTargets": false,
            "dithering": false
        }
    ],
    "object": {
        "uuid": "6E9A5918-B4C7-4D25-928D-4C283C8CE387",
        "type": "Mesh",
        "matrix": [1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],
        "geometry": "BC2110E2-3EA4-4C37-9041-DE1A49F5C06B",
        "material": [
            "81EDCE16-A1EC-40B6-A4F3-D34374C6DF5A",
            "8BBB3EE7-B8BD-4441-8CBF-B01A73DE1D9E",
            "D3CD2958-6E36-42CE-B4C4-688B670CF8CD",
            "22156F77-0963-4C68-99A7-BDE887313F2A",
            "49C93E84-FD7F-49F4-AA55-9769194E25E8",
            "F8B0E57E-B25C-4A16-B917-4EE615B2B6D4"
        ]
    }
}

And THREE.ObjectLoader loads that correctly.

The editor now also has minimal support (import, export but not edit).

screen shot 2017-03-30 at 19 32 50

@mrdoob @WestLangley does that mean THREE.Mesh.material can have both an array or an object? Also, will groups still work in Geometry and faces?

The new approach seems to be really nice, just i'm super scared of updating, 90% of our 3d related codebase is MultiMaterial. 馃槺

Yeah. Everything should still work. In fact, Multimaterial should still work, it would just display a warning in the console.

Closing since the removal of MultiMaterial is now well documented and sufficiently discussed.

mrdoob: And THREE.ObjectLoader loads that correctly...

No, it is not: Using ObjectLoader I just see cube without any materials! And the warning appears:

THREE.ObjectLoader: Undefined material (6) ["81EDCE16-A1EC-40B6-A4F3-D34374C6DF5A", "8BBB3EE7-B8BD-4441-8CBF-B01A73DE1D9E", "D3CD2958-6E36-42CE-B4C4-688B670CF8CD", "22156F77-0963-4C68-99A7-BDE887313F2A", "49C93E84-FD7F-49F4-AA55-9769194E25E8", "F8B0E57E-B25C-4A16-B917-4EE615B2B6D4"]

In the same time, I am able to load it correctly into three.js/Editor

@alexforever82 please, if you found a bug, create a new issue and include a jsfiddle.

As of #11835, the editor now can edit multi-materials.

screen shot 2017-08-01 at 5 01 15 pm

Was this page helpful?
0 / 5 - 0 ratings

Related issues

mrdoob picture mrdoob  路  66Comments

kdilayer picture kdilayer  路  62Comments

arctwelve picture arctwelve  路  92Comments

sunag picture sunag  路  161Comments

QuaziKb picture QuaziKb  路  73Comments