| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421 |
- import { ObjectLoader } from '../../../src/loaders/ObjectLoader.js';
- import { Scene } from '../../../src/scenes/Scene.js';
- import { Mesh } from '../../../src/objects/Mesh.js';
- import { Group } from '../../../src/objects/Group.js';
- import { BoxGeometry } from '../../../src/geometries/BoxGeometry.js';
- import { SphereGeometry } from '../../../src/geometries/SphereGeometry.js';
- import { BufferGeometry } from '../../../src/core/BufferGeometry.js';
- import { Float32BufferAttribute } from '../../../src/core/BufferAttribute.js';
- import { MeshBasicMaterial } from '../../../src/materials/MeshBasicMaterial.js';
- import { MeshStandardMaterial } from '../../../src/materials/MeshStandardMaterial.js';
- import { AmbientLight } from '../../../src/lights/AmbientLight.js';
- import { DirectionalLight } from '../../../src/lights/DirectionalLight.js';
- import { PointLight } from '../../../src/lights/PointLight.js';
- import { PerspectiveCamera } from '../../../src/cameras/PerspectiveCamera.js';
- import { OrthographicCamera } from '../../../src/cameras/OrthographicCamera.js';
- import { Color } from '../../../src/math/Color.js';
- import { Fog } from '../../../src/scenes/Fog.js';
- export default QUnit.module( 'JSON4 Format', () => {
- QUnit.module( 'Round-trip', () => {
- QUnit.test( 'Simple Mesh round-trip', ( assert ) => {
- const geometry = new BoxGeometry( 2, 3, 4 );
- const material = new MeshBasicMaterial( { color: 0xff0000 } );
- const mesh = new Mesh( geometry, material );
- mesh.position.set( 1, 2, 3 );
- mesh.name = 'TestMesh';
- mesh.updateMatrix();
- const json = mesh.toJSON();
- const loader = new ObjectLoader();
- const restored = loader.parse( json );
- assert.ok( restored.isMesh, 'Restored is Mesh' );
- assert.strictEqual( restored.name, 'TestMesh', 'Name preserved' );
- assert.strictEqual( restored.position.x, 1, 'Position.x preserved' );
- assert.strictEqual( restored.position.y, 2, 'Position.y preserved' );
- assert.strictEqual( restored.position.z, 3, 'Position.z preserved' );
- assert.strictEqual( restored.geometry.parameters.width, 2, 'Geometry width preserved' );
- assert.strictEqual( restored.material.color.getHex(), 0xff0000, 'Material color preserved' );
- } );
- QUnit.test( 'Scene with multiple objects round-trip', ( assert ) => {
- const scene = new Scene();
- scene.name = 'TestScene';
- scene.background = new Color( 0x87ceeb );
- const geometry = new BoxGeometry( 1, 1, 1 );
- const material = new MeshBasicMaterial( { color: 0xff0000 } );
- const mesh1 = new Mesh( geometry, material );
- mesh1.name = 'Mesh1';
- mesh1.position.set( 0, 0, 0 );
- const mesh2 = new Mesh( geometry, material );
- mesh2.name = 'Mesh2';
- mesh2.position.set( 2, 0, 0 );
- scene.add( mesh1, mesh2 );
- const json = scene.toJSON();
- const loader = new ObjectLoader();
- const restored = loader.parse( json );
- assert.ok( restored.isScene, 'Restored is Scene' );
- assert.strictEqual( restored.name, 'TestScene', 'Scene name preserved' );
- assert.strictEqual( restored.background.getHex(), 0x87ceeb, 'Background preserved' );
- assert.strictEqual( restored.children.length, 2, 'Has 2 children' );
- assert.strictEqual( restored.children[ 0 ].name, 'Mesh1', 'First child name' );
- assert.strictEqual( restored.children[ 1 ].name, 'Mesh2', 'Second child name' );
- } );
- QUnit.test( 'Hierarchy round-trip', ( assert ) => {
- const scene = new Scene();
- const parent = new Group();
- parent.name = 'Parent';
- parent.position.set( 1, 0, 0 );
- const child = new Group();
- child.name = 'Child';
- child.position.set( 0, 1, 0 );
- const grandchild = new Mesh(
- new BoxGeometry( 1, 1, 1 ),
- new MeshBasicMaterial( { color: 0xff0000 } )
- );
- grandchild.name = 'Grandchild';
- grandchild.position.set( 0, 0, 1 );
- child.add( grandchild );
- parent.add( child );
- scene.add( parent );
- const json = scene.toJSON();
- const loader = new ObjectLoader();
- const restored = loader.parse( json );
- const restoredParent = restored.children[ 0 ];
- const restoredChild = restoredParent.children[ 0 ];
- const restoredGrandchild = restoredChild.children[ 0 ];
- assert.strictEqual( restoredParent.name, 'Parent', 'Parent name' );
- assert.strictEqual( restoredChild.name, 'Child', 'Child name' );
- assert.strictEqual( restoredGrandchild.name, 'Grandchild', 'Grandchild name' );
- assert.strictEqual( restoredGrandchild.parent, restoredChild, 'Parent-child relation' );
- } );
- QUnit.test( 'BufferGeometry with custom attributes round-trip', ( assert ) => {
- const geometry = new BufferGeometry();
- geometry.setAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 1, 0, 0, 0, 1, 0 ], 3 ) );
- geometry.setAttribute( 'normal', new Float32BufferAttribute( [ 0, 0, 1, 0, 0, 1, 0, 0, 1 ], 3 ) );
- geometry.setAttribute( 'uv', new Float32BufferAttribute( [ 0, 0, 1, 0, 0.5, 1 ], 2 ) );
- const material = new MeshBasicMaterial( { color: 0xff0000 } );
- const mesh = new Mesh( geometry, material );
- const json = mesh.toJSON();
- const loader = new ObjectLoader();
- const restored = loader.parse( json );
- assert.ok( restored.geometry.attributes.position, 'Has position' );
- assert.ok( restored.geometry.attributes.normal, 'Has normal' );
- assert.ok( restored.geometry.attributes.uv, 'Has uv' );
- assert.strictEqual( restored.geometry.attributes.position.count, 3, 'Position count' );
- assert.strictEqual( restored.geometry.attributes.uv.itemSize, 2, 'UV itemSize' );
- } );
- QUnit.test( 'MeshStandardMaterial round-trip', ( assert ) => {
- const material = new MeshStandardMaterial( {
- color: 0xff0000,
- roughness: 0.3,
- metalness: 0.8,
- emissive: 0x00ff00,
- emissiveIntensity: 0.5
- } );
- const mesh = new Mesh( new BoxGeometry( 1, 1, 1 ), material );
- const json = mesh.toJSON();
- const loader = new ObjectLoader();
- const restored = loader.parse( json );
- assert.ok( restored.material.isMeshStandardMaterial, 'Is MeshStandardMaterial' );
- assert.strictEqual( restored.material.color.getHex(), 0xff0000, 'Color preserved' );
- assert.strictEqual( restored.material.roughness, 0.3, 'Roughness preserved' );
- assert.strictEqual( restored.material.metalness, 0.8, 'Metalness preserved' );
- assert.strictEqual( restored.material.emissive.getHex(), 0x00ff00, 'Emissive preserved' );
- assert.strictEqual( restored.material.emissiveIntensity, 0.5, 'EmissiveIntensity preserved' );
- } );
- QUnit.test( 'Lights round-trip', ( assert ) => {
- const scene = new Scene();
- const ambient = new AmbientLight( 0xffffff, 0.5 );
- ambient.name = 'Ambient';
- const directional = new DirectionalLight( 0xffffff, 1 );
- directional.name = 'Directional';
- directional.position.set( 5, 10, 5 );
- const point = new PointLight( 0xff0000, 2, 50, 2 );
- point.name = 'Point';
- point.position.set( 0, 5, 0 );
- scene.add( ambient, directional, point );
- scene.updateMatrixWorld( true );
- const json = scene.toJSON();
- const loader = new ObjectLoader();
- const restored = loader.parse( json );
- const restoredAmbient = restored.getObjectByName( 'Ambient' );
- const restoredDirectional = restored.getObjectByName( 'Directional' );
- const restoredPoint = restored.getObjectByName( 'Point' );
- assert.ok( restoredAmbient.isAmbientLight, 'Ambient is AmbientLight' );
- assert.strictEqual( restoredAmbient.intensity, 0.5, 'Ambient intensity' );
- assert.ok( restoredDirectional.isDirectionalLight, 'Directional is DirectionalLight' );
- assert.strictEqual( restoredDirectional.position.x, 5, 'Directional position.x' );
- assert.ok( restoredPoint.isPointLight, 'Point is PointLight' );
- assert.strictEqual( restoredPoint.color.getHex(), 0xff0000, 'Point color' );
- assert.strictEqual( restoredPoint.distance, 50, 'Point distance' );
- assert.strictEqual( restoredPoint.decay, 2, 'Point decay' );
- } );
- QUnit.test( 'Cameras round-trip', ( assert ) => {
- const scene = new Scene();
- const perspective = new PerspectiveCamera( 75, 16 / 9, 0.1, 1000 );
- perspective.name = 'Perspective';
- perspective.position.set( 0, 0, 5 );
- perspective.zoom = 1.5;
- const ortho = new OrthographicCamera( - 10, 10, 10, - 10, 0.1, 100 );
- ortho.name = 'Ortho';
- ortho.position.set( 0, 10, 0 );
- scene.add( perspective, ortho );
- const json = scene.toJSON();
- const loader = new ObjectLoader();
- const restored = loader.parse( json );
- const restoredPerspective = restored.getObjectByName( 'Perspective' );
- const restoredOrtho = restored.getObjectByName( 'Ortho' );
- assert.ok( restoredPerspective.isPerspectiveCamera, 'Is PerspectiveCamera' );
- assert.strictEqual( restoredPerspective.fov, 75, 'FOV preserved' );
- assert.strictEqual( restoredPerspective.zoom, 1.5, 'Zoom preserved' );
- assert.ok( restoredOrtho.isOrthographicCamera, 'Is OrthographicCamera' );
- assert.strictEqual( restoredOrtho.left, - 10, 'Left preserved' );
- assert.strictEqual( restoredOrtho.right, 10, 'Right preserved' );
- } );
- QUnit.test( 'Scene with Fog round-trip', ( assert ) => {
- const scene = new Scene();
- scene.fog = new Fog( 0xffffff, 10, 100 );
- scene.fog.name = 'TestFog';
- const json = scene.toJSON();
- const loader = new ObjectLoader();
- const restored = loader.parse( json );
- assert.ok( restored.fog.isFog, 'Has Fog' );
- assert.strictEqual( restored.fog.color.getHex(), 0xffffff, 'Fog color' );
- assert.strictEqual( restored.fog.near, 10, 'Fog near' );
- assert.strictEqual( restored.fog.far, 100, 'Fog far' );
- assert.strictEqual( restored.fog.name, 'TestFog', 'Fog name' );
- } );
- QUnit.test( 'Object transforms round-trip', ( assert ) => {
- const mesh = new Mesh(
- new BoxGeometry( 1, 1, 1 ),
- new MeshBasicMaterial( { color: 0xff0000 } )
- );
- mesh.position.set( 1, 2, 3 );
- mesh.rotation.set( Math.PI / 4, Math.PI / 2, 0 );
- mesh.scale.set( 2, 2, 2 );
- mesh.updateMatrix();
- const json = mesh.toJSON();
- const loader = new ObjectLoader();
- const restored = loader.parse( json );
- assert.ok( Math.abs( restored.position.x - 1 ) < 0.0001, 'Position.x' );
- assert.ok( Math.abs( restored.position.y - 2 ) < 0.0001, 'Position.y' );
- assert.ok( Math.abs( restored.position.z - 3 ) < 0.0001, 'Position.z' );
- assert.ok( Math.abs( restored.scale.x - 2 ) < 0.0001, 'Scale.x' );
- assert.ok( Math.abs( restored.scale.y - 2 ) < 0.0001, 'Scale.y' );
- assert.ok( Math.abs( restored.scale.z - 2 ) < 0.0001, 'Scale.z' );
- } );
- QUnit.test( 'userData round-trip', ( assert ) => {
- const mesh = new Mesh(
- new BoxGeometry( 1, 1, 1 ),
- new MeshBasicMaterial( { color: 0xff0000 } )
- );
- mesh.userData = {
- customString: 'hello',
- customNumber: 42,
- customBool: true,
- customArray: [ 1, 2, 3 ],
- customObject: { nested: 'value' }
- };
- const json = mesh.toJSON();
- const loader = new ObjectLoader();
- const restored = loader.parse( json );
- assert.strictEqual( restored.userData.customString, 'hello', 'String preserved' );
- assert.strictEqual( restored.userData.customNumber, 42, 'Number preserved' );
- assert.strictEqual( restored.userData.customBool, true, 'Bool preserved' );
- assert.deepEqual( restored.userData.customArray, [ 1, 2, 3 ], 'Array preserved' );
- assert.deepEqual( restored.userData.customObject, { nested: 'value' }, 'Object preserved' );
- } );
- QUnit.test( 'Object properties round-trip', ( assert ) => {
- const mesh = new Mesh(
- new BoxGeometry( 1, 1, 1 ),
- new MeshBasicMaterial( { color: 0xff0000 } )
- );
- mesh.visible = false;
- mesh.castShadow = true;
- mesh.receiveShadow = true;
- mesh.frustumCulled = false;
- mesh.renderOrder = 5;
- const json = mesh.toJSON();
- const loader = new ObjectLoader();
- const restored = loader.parse( json );
- assert.strictEqual( restored.visible, false, 'Visible' );
- assert.strictEqual( restored.castShadow, true, 'CastShadow' );
- assert.strictEqual( restored.receiveShadow, true, 'ReceiveShadow' );
- assert.strictEqual( restored.frustumCulled, false, 'FrustumCulled' );
- assert.strictEqual( restored.renderOrder, 5, 'RenderOrder' );
- } );
- QUnit.test( 'Shared geometry/material round-trip', ( assert ) => {
- const scene = new Scene();
- const geometry = new BoxGeometry( 1, 1, 1 );
- const material = new MeshBasicMaterial( { color: 0xff0000 } );
- const mesh1 = new Mesh( geometry, material );
- mesh1.name = 'Mesh1';
- const mesh2 = new Mesh( geometry, material );
- mesh2.name = 'Mesh2';
- mesh2.position.x = 2;
- scene.add( mesh1, mesh2 );
- const json = scene.toJSON();
- const loader = new ObjectLoader();
- const restored = loader.parse( json );
- const restoredMesh1 = restored.getObjectByName( 'Mesh1' );
- const restoredMesh2 = restored.getObjectByName( 'Mesh2' );
- assert.strictEqual( restoredMesh1.geometry, restoredMesh2.geometry, 'Geometry shared' );
- assert.strictEqual( restoredMesh1.material, restoredMesh2.material, 'Material shared' );
- } );
- QUnit.test( 'Complex scene round-trip', ( assert ) => {
- const scene = new Scene();
- scene.name = 'ComplexScene';
- scene.background = new Color( 0x333333 );
- scene.fog = new Fog( 0x333333, 10, 100 );
- const group = new Group();
- group.name = 'ObjectsGroup';
- const geometry1 = new BoxGeometry( 1, 1, 1 );
- const geometry2 = new SphereGeometry( 0.5, 16, 8 );
- const material1 = new MeshBasicMaterial( { color: 0xff0000 } );
- const material2 = new MeshStandardMaterial( { color: 0x00ff00, roughness: 0.5 } );
- const box = new Mesh( geometry1, material1 );
- box.name = 'Box';
- box.position.set( - 2, 0, 0 );
- const sphere = new Mesh( geometry2, material2 );
- sphere.name = 'Sphere';
- sphere.position.set( 2, 0, 0 );
- group.add( box, sphere );
- scene.add( group );
- const ambient = new AmbientLight( 0xffffff, 0.3 );
- scene.add( ambient );
- const directional = new DirectionalLight( 0xffffff, 1 );
- directional.position.set( 5, 10, 5 );
- scene.add( directional );
- const camera = new PerspectiveCamera( 75, 1, 0.1, 1000 );
- camera.name = 'MainCamera';
- camera.position.set( 0, 0, 10 );
- scene.add( camera );
- const json = scene.toJSON();
- const loader = new ObjectLoader();
- const restored = loader.parse( json );
- assert.ok( restored.isScene, 'Is Scene' );
- assert.strictEqual( restored.name, 'ComplexScene', 'Scene name' );
- assert.strictEqual( restored.background.getHex(), 0x333333, 'Background' );
- assert.ok( restored.fog.isFog, 'Has Fog' );
- const restoredGroup = restored.getObjectByName( 'ObjectsGroup' );
- assert.ok( restoredGroup.isGroup, 'Group found' );
- assert.strictEqual( restoredGroup.children.length, 2, 'Group has 2 children' );
- const restoredBox = restored.getObjectByName( 'Box' );
- const restoredSphere = restored.getObjectByName( 'Sphere' );
- assert.ok( restoredBox.isMesh, 'Box found' );
- assert.ok( restoredSphere.isMesh, 'Sphere found' );
- const restoredCamera = restored.getObjectByName( 'MainCamera' );
- assert.ok( restoredCamera.isPerspectiveCamera, 'Camera found' );
- } );
- } );
- } );
|