@google/model-viewer
Version:
Easily display interactive 3D models on the web and in AR!
197 lines • 9.57 kB
JavaScript
/* @license
* Copyright 2020 Google LLC. All Rights Reserved.
* Licensed under the Apache License, Version 2.0 (the 'License');
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an 'AS IS' BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { expect } from 'chai';
import { $primitivesList, $variantData, Model } from '../../../../features/scene-graph/model.js';
import { ModelViewerElement } from '../../../../model-viewer.js';
import { CorrelatedSceneGraph } from '../../../../three-components/gltf-instance/correlated-scene-graph.js';
import { waitForEvent } from '../../../../utilities.js';
import { assetPath, loadThreeGLTF } from '../../../helpers.js';
const BRAIN_STEM_GLB_PATH = assetPath('models/glTF-Sample-Assets/Models/BrainStem/glTF-Binary/BrainStem.glb');
const CUBES_GLTF_PATH = assetPath('models/cubes.gltf');
const CUBE_GLTF_PATH = assetPath('models/cube.gltf');
const MESH_PRIMITIVES_GLB_PATH = assetPath('models/MeshPrimitivesVariants.glb');
const KHRONOS_TRIANGLE_GLB_PATH = assetPath('models/glTF-Sample-Assets/Models/Triangle/glTF/Triangle.gltf');
const findPrimitivesWithVariant = (model, variantName) => {
const result = new Array();
for (const primitive of model[$primitivesList]) {
if (primitive.variantInfo != null && model.hasVariant(variantName) &&
primitive.variantInfo.has(model[$variantData].get(variantName).index)) {
result.push(primitive);
}
}
return result.length > 0 ? result : null;
};
suite('scene-graph/model/mesh-primitives', () => {
suite('Primitive with default material', () => {
let element;
setup(async () => {
element = new ModelViewerElement();
element.src = KHRONOS_TRIANGLE_GLB_PATH;
document.body.insertBefore(element, document.body.firstChild);
await waitForEvent(element, 'load');
});
teardown(() => {
document.body.removeChild(element);
});
test('has a default material', async () => {
const model = element.model;
expect(model[$primitivesList].length).to.equal(1);
expect(model.materials.length).to.equal(1);
expect(model[$primitivesList][0].initialMaterialIdx).to.equal(0);
expect(model.materials[0].name).to.equal('Default');
});
});
suite('Static Primitive Without Variant', () => {
let model;
setup(async () => {
const threeGLTF = await loadThreeGLTF(CUBE_GLTF_PATH);
model = new Model(CorrelatedSceneGraph.from(threeGLTF));
});
test('Should not have any primitives with variant info', async () => {
let hasVariantInfoCount = 0;
for (const primitive of model[$primitivesList]) {
if (primitive.variantInfo.size > 0) {
hasVariantInfoCount++;
}
}
expect(hasVariantInfoCount).equals(0);
});
});
suite('Static Primitive With Variant', () => {
let model;
setup(async () => {
const threeGLTF = await loadThreeGLTF(CUBES_GLTF_PATH);
model = new Model(CorrelatedSceneGraph.from(threeGLTF));
});
test('Primitive count matches glTF file', async () => {
expect(model[$primitivesList].length).to.equal(2);
});
test('Primitives should have expected variant names', async () => {
expect(findPrimitivesWithVariant(model, 'Purple Yellow')).to.not.be.null;
expect(findPrimitivesWithVariant(model, 'Yellow Yellow')).to.not.be.null;
expect(findPrimitivesWithVariant(model, 'Yellow Red')).to.not.be.null;
});
test('Should not have any primitives without variant info', async () => {
let hasNoVariantInfoCount = 0;
for (const primitive of model[$primitivesList]) {
if (primitive.variantInfo == null) {
hasNoVariantInfoCount++;
}
}
expect(hasNoVariantInfoCount).equals(0);
});
test('Switching to incorrect variant name', async () => {
const primitive = findPrimitivesWithVariant(model, 'Purple Yellow')[0];
const material = await primitive.enableVariant('Does not exist');
expect(material).to.be.null;
});
test('Switching to current variant', async () => {
const primitives = findPrimitivesWithVariant(model, 'Purple Yellow');
const materials = new Array();
for (const primitive of primitives) {
materials.push(await primitive.enableVariant('Yellow Yellow'));
}
expect(materials).to.not.be.empty;
expect(materials.find((material) => {
return material.name === 'yellow';
})).to.not.be.null;
});
test('Switching to variant and then switch back', async () => {
const primitives = findPrimitivesWithVariant(model, 'Purple Yellow');
let materials = new Array();
for (const primitive of primitives) {
materials.push(await primitive.enableVariant('Yellow Yellow'));
}
expect(materials.find((material) => {
return material.name === 'yellow';
})).to.not.be.null;
materials = new Array();
for (const primitive of primitives) {
materials.push(await primitive.enableVariant('Purple Yellow'));
}
expect(materials.find((material) => {
return material.name === 'purple';
})).to.not.be.null;
});
test('Primitive switches to initial material', async () => {
const primitive = findPrimitivesWithVariant(model, 'Purple Yellow')[0];
// Gets current material.
const initialMaterial = await primitive.enableVariant('Purple Yellow');
// Switches to variant.
const variantMaterial = await primitive.enableVariant('Yellow Red');
expect(initialMaterial).to.not.equal(variantMaterial);
// Switches to initial material.
const resetMaterial = await primitive.enableVariant(null);
expect(resetMaterial).to.equal(initialMaterial);
});
});
suite('Mesh with multiple primitives each with variants', () => {
let model;
setup(async () => {
const threeGLTF = await loadThreeGLTF(MESH_PRIMITIVES_GLB_PATH);
model = new Model(CorrelatedSceneGraph.from(threeGLTF));
});
test('Primitive count matches glTF file', async () => {
expect(model[$primitivesList].length).to.equal(3);
});
test('Primitives should have expected variant names', async () => {
expect(findPrimitivesWithVariant(model, 'Normal')).to.not.be.null;
expect(findPrimitivesWithVariant(model, 'Inverse')).to.not.be.null;
});
test('Switching to incorrect variant name', async () => {
const primitive = findPrimitivesWithVariant(model, 'Normal')[0];
const material = await primitive.enableVariant('Does not exist');
expect(material).to.be.null;
});
test('Switching to variant and then switch back', async () => {
const MATERIAL_NAME = 'STEEL BLACK';
const primitives = findPrimitivesWithVariant(model, 'Normal');
let materials = new Array();
for (const primitive of primitives) {
materials.push(await primitive.enableVariant('Inverse'));
}
expect(materials).to.not.be.empty;
expect(materials.find((material) => {
return material.name === MATERIAL_NAME;
})).to.be.undefined;
materials = new Array();
for (const primitive of primitives) {
materials.push(await primitive.enableVariant('Normal'));
}
expect(materials.find((material) => {
return material.name === MATERIAL_NAME;
})).to.be.ok;
});
test('Primitive switches to initial material', async () => {
const primitive = findPrimitivesWithVariant(model, 'Normal')[0];
// Gets current material.
const initialMaterial = await primitive.enableVariant('Normal');
// Switches to variant.
const variantMaterial = await primitive.enableVariant('Inverse');
expect(initialMaterial).to.not.equal(variantMaterial);
// Switches to initial material.
const resetMaterial = await primitive.enableVariant(null);
expect(resetMaterial).to.equal(initialMaterial);
});
});
suite('Skinned Primitive Without Variant', () => {
test('Primitive count matches glTF file', async () => {
const threeGLTF = await loadThreeGLTF(BRAIN_STEM_GLB_PATH);
const model = new Model(CorrelatedSceneGraph.from(threeGLTF));
expect(model[$primitivesList].length).to.equal(59);
});
});
});
//# sourceMappingURL=primitive-node-spec.js.map