hierarchy.tests.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  1. import { ObjectLoader } from '../../../src/loaders/ObjectLoader.js';
  2. export default QUnit.module( 'JSON4 Format', () => {
  3. QUnit.module( 'Hierarchy', () => {
  4. QUnit.test( 'Parent-child relationships', ( assert ) => {
  5. const json = {
  6. metadata: { version: 4.7, type: 'Object', generator: 'Object3D.toJSON' },
  7. geometries: [ {
  8. uuid: 'geom-1',
  9. type: 'BoxGeometry',
  10. width: 1,
  11. height: 1,
  12. depth: 1
  13. } ],
  14. materials: [ {
  15. uuid: 'mat-1',
  16. type: 'MeshBasicMaterial',
  17. color: 16711680
  18. } ],
  19. object: {
  20. uuid: 'scene-1',
  21. type: 'Scene',
  22. children: [
  23. {
  24. uuid: 'group-1',
  25. type: 'Group',
  26. name: 'Parent',
  27. matrix: [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ],
  28. layers: 1,
  29. children: [
  30. {
  31. uuid: 'mesh-1',
  32. type: 'Mesh',
  33. name: 'Child',
  34. geometry: 'geom-1',
  35. material: 'mat-1',
  36. matrix: [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ],
  37. layers: 1
  38. }
  39. ]
  40. }
  41. ]
  42. }
  43. };
  44. const loader = new ObjectLoader();
  45. const scene = loader.parse( json );
  46. const parent = scene.children[ 0 ];
  47. const child = parent.children[ 0 ];
  48. assert.strictEqual( child.parent, parent, 'Child parent is correct' );
  49. assert.strictEqual( parent.children.length, 1, 'Parent has 1 child' );
  50. assert.strictEqual( child.name, 'Child', 'Child name' );
  51. } );
  52. QUnit.test( 'Nested hierarchy (3+ levels)', ( assert ) => {
  53. const json = {
  54. metadata: { version: 4.7, type: 'Object', generator: 'Object3D.toJSON' },
  55. geometries: [ {
  56. uuid: 'geom-1',
  57. type: 'BoxGeometry',
  58. width: 1,
  59. height: 1,
  60. depth: 1
  61. } ],
  62. materials: [ {
  63. uuid: 'mat-1',
  64. type: 'MeshBasicMaterial',
  65. color: 16711680
  66. } ],
  67. object: {
  68. uuid: 'scene-1',
  69. type: 'Scene',
  70. children: [
  71. {
  72. uuid: 'level1',
  73. type: 'Group',
  74. name: 'Level1',
  75. matrix: [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ],
  76. layers: 1,
  77. children: [
  78. {
  79. uuid: 'level2',
  80. type: 'Group',
  81. name: 'Level2',
  82. matrix: [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1 ],
  83. layers: 1,
  84. children: [
  85. {
  86. uuid: 'level3',
  87. type: 'Group',
  88. name: 'Level3',
  89. matrix: [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1 ],
  90. layers: 1,
  91. children: [
  92. {
  93. uuid: 'mesh-1',
  94. type: 'Mesh',
  95. name: 'DeepMesh',
  96. geometry: 'geom-1',
  97. material: 'mat-1',
  98. matrix: [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1 ],
  99. layers: 1
  100. }
  101. ]
  102. }
  103. ]
  104. }
  105. ]
  106. }
  107. ]
  108. }
  109. };
  110. const loader = new ObjectLoader();
  111. const scene = loader.parse( json );
  112. const level1 = scene.children[ 0 ];
  113. const level2 = level1.children[ 0 ];
  114. const level3 = level2.children[ 0 ];
  115. const mesh = level3.children[ 0 ];
  116. assert.strictEqual( level1.name, 'Level1', 'Level 1 name' );
  117. assert.strictEqual( level2.name, 'Level2', 'Level 2 name' );
  118. assert.strictEqual( level3.name, 'Level3', 'Level 3 name' );
  119. assert.strictEqual( mesh.name, 'DeepMesh', 'Deep mesh name' );
  120. assert.strictEqual( mesh.parent.parent.parent.parent, scene, 'Deep parent chain' );
  121. } );
  122. QUnit.test( 'Multiple meshes sharing same geometry UUID', ( assert ) => {
  123. const json = {
  124. metadata: { version: 4.7, type: 'Object', generator: 'Object3D.toJSON' },
  125. geometries: [ {
  126. uuid: 'shared-geom',
  127. type: 'BoxGeometry',
  128. width: 1,
  129. height: 1,
  130. depth: 1
  131. } ],
  132. materials: [
  133. { uuid: 'mat-1', type: 'MeshBasicMaterial', color: 16711680 },
  134. { uuid: 'mat-2', type: 'MeshBasicMaterial', color: 65280 }
  135. ],
  136. object: {
  137. uuid: 'scene-1',
  138. type: 'Scene',
  139. children: [
  140. {
  141. uuid: 'mesh-1',
  142. type: 'Mesh',
  143. geometry: 'shared-geom',
  144. material: 'mat-1',
  145. matrix: [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ],
  146. layers: 1
  147. },
  148. {
  149. uuid: 'mesh-2',
  150. type: 'Mesh',
  151. geometry: 'shared-geom',
  152. material: 'mat-2',
  153. matrix: [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 2, 0, 0, 1 ],
  154. layers: 1
  155. },
  156. {
  157. uuid: 'mesh-3',
  158. type: 'Mesh',
  159. geometry: 'shared-geom',
  160. material: 'mat-1',
  161. matrix: [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 4, 0, 0, 1 ],
  162. layers: 1
  163. }
  164. ]
  165. }
  166. };
  167. const loader = new ObjectLoader();
  168. const scene = loader.parse( json );
  169. const mesh1 = scene.children[ 0 ];
  170. const mesh2 = scene.children[ 1 ];
  171. const mesh3 = scene.children[ 2 ];
  172. assert.strictEqual( mesh1.geometry, mesh2.geometry, 'Mesh1 and Mesh2 share geometry' );
  173. assert.strictEqual( mesh2.geometry, mesh3.geometry, 'Mesh2 and Mesh3 share geometry' );
  174. } );
  175. QUnit.test( 'Multiple meshes sharing same material UUID', ( assert ) => {
  176. const json = {
  177. metadata: { version: 4.7, type: 'Object', generator: 'Object3D.toJSON' },
  178. geometries: [
  179. { uuid: 'geom-1', type: 'BoxGeometry', width: 1, height: 1, depth: 1 },
  180. { uuid: 'geom-2', type: 'SphereGeometry', radius: 0.5, widthSegments: 16, heightSegments: 8 }
  181. ],
  182. materials: [ {
  183. uuid: 'shared-mat',
  184. type: 'MeshBasicMaterial',
  185. color: 16711680
  186. } ],
  187. object: {
  188. uuid: 'scene-1',
  189. type: 'Scene',
  190. children: [
  191. {
  192. uuid: 'mesh-1',
  193. type: 'Mesh',
  194. geometry: 'geom-1',
  195. material: 'shared-mat',
  196. matrix: [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ],
  197. layers: 1
  198. },
  199. {
  200. uuid: 'mesh-2',
  201. type: 'Mesh',
  202. geometry: 'geom-2',
  203. material: 'shared-mat',
  204. matrix: [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 2, 0, 0, 1 ],
  205. layers: 1
  206. }
  207. ]
  208. }
  209. };
  210. const loader = new ObjectLoader();
  211. const scene = loader.parse( json );
  212. const mesh1 = scene.children[ 0 ];
  213. const mesh2 = scene.children[ 1 ];
  214. assert.strictEqual( mesh1.material, mesh2.material, 'Meshes share same material' );
  215. assert.notStrictEqual( mesh1.geometry, mesh2.geometry, 'Meshes have different geometries' );
  216. } );
  217. QUnit.test( 'LOD with levels', ( assert ) => {
  218. const json = {
  219. metadata: { version: 4.7, type: 'Object', generator: 'Object3D.toJSON' },
  220. geometries: [
  221. { uuid: 'geom-high', type: 'SphereGeometry', radius: 1, widthSegments: 32, heightSegments: 16 },
  222. { uuid: 'geom-med', type: 'SphereGeometry', radius: 1, widthSegments: 16, heightSegments: 8 },
  223. { uuid: 'geom-low', type: 'SphereGeometry', radius: 1, widthSegments: 8, heightSegments: 4 }
  224. ],
  225. materials: [ {
  226. uuid: 'mat-1',
  227. type: 'MeshBasicMaterial',
  228. color: 16711680
  229. } ],
  230. object: {
  231. uuid: 'lod-1',
  232. type: 'LOD',
  233. autoUpdate: true,
  234. matrix: [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ],
  235. layers: 1,
  236. levels: [
  237. { object: 'mesh-high', distance: 0, hysteresis: 0 },
  238. { object: 'mesh-med', distance: 50, hysteresis: 0 },
  239. { object: 'mesh-low', distance: 100, hysteresis: 0 }
  240. ],
  241. children: [
  242. {
  243. uuid: 'mesh-high',
  244. type: 'Mesh',
  245. name: 'High',
  246. geometry: 'geom-high',
  247. material: 'mat-1',
  248. matrix: [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ],
  249. layers: 1
  250. },
  251. {
  252. uuid: 'mesh-med',
  253. type: 'Mesh',
  254. name: 'Medium',
  255. geometry: 'geom-med',
  256. material: 'mat-1',
  257. matrix: [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ],
  258. layers: 1
  259. },
  260. {
  261. uuid: 'mesh-low',
  262. type: 'Mesh',
  263. name: 'Low',
  264. geometry: 'geom-low',
  265. material: 'mat-1',
  266. matrix: [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ],
  267. layers: 1
  268. }
  269. ]
  270. }
  271. };
  272. const loader = new ObjectLoader();
  273. const lod = loader.parse( json );
  274. assert.ok( lod.isLOD, 'Is LOD' );
  275. assert.strictEqual( lod.levels.length, 3, 'Has 3 levels' );
  276. assert.strictEqual( lod.levels[ 0 ].distance, 0, 'First level distance' );
  277. assert.strictEqual( lod.levels[ 1 ].distance, 50, 'Second level distance' );
  278. assert.strictEqual( lod.levels[ 2 ].distance, 100, 'Third level distance' );
  279. assert.strictEqual( lod.autoUpdate, true, 'autoUpdate is true' );
  280. } );
  281. QUnit.test( 'LOD with hysteresis', ( assert ) => {
  282. const json = {
  283. metadata: { version: 4.7, type: 'Object', generator: 'Object3D.toJSON' },
  284. geometries: [
  285. { uuid: 'geom-high', type: 'BoxGeometry', width: 1, height: 1, depth: 1 },
  286. { uuid: 'geom-low', type: 'BoxGeometry', width: 1, height: 1, depth: 1 }
  287. ],
  288. materials: [ {
  289. uuid: 'mat-1',
  290. type: 'MeshBasicMaterial',
  291. color: 16711680
  292. } ],
  293. object: {
  294. uuid: 'lod-1',
  295. type: 'LOD',
  296. matrix: [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ],
  297. layers: 1,
  298. levels: [
  299. { object: 'mesh-high', distance: 0, hysteresis: 0.5 },
  300. { object: 'mesh-low', distance: 100, hysteresis: 0.5 }
  301. ],
  302. children: [
  303. {
  304. uuid: 'mesh-high',
  305. type: 'Mesh',
  306. geometry: 'geom-high',
  307. material: 'mat-1',
  308. matrix: [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ],
  309. layers: 1
  310. },
  311. {
  312. uuid: 'mesh-low',
  313. type: 'Mesh',
  314. geometry: 'geom-low',
  315. material: 'mat-1',
  316. matrix: [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ],
  317. layers: 1
  318. }
  319. ]
  320. }
  321. };
  322. const loader = new ObjectLoader();
  323. const lod = loader.parse( json );
  324. assert.strictEqual( lod.levels[ 0 ].hysteresis, 0.5, 'First level hysteresis' );
  325. assert.strictEqual( lod.levels[ 1 ].hysteresis, 0.5, 'Second level hysteresis' );
  326. } );
  327. QUnit.test( 'Multiple siblings', ( assert ) => {
  328. const json = {
  329. metadata: { version: 4.7, type: 'Object', generator: 'Object3D.toJSON' },
  330. geometries: [ {
  331. uuid: 'geom-1',
  332. type: 'BoxGeometry',
  333. width: 1,
  334. height: 1,
  335. depth: 1
  336. } ],
  337. materials: [ {
  338. uuid: 'mat-1',
  339. type: 'MeshBasicMaterial',
  340. color: 16711680
  341. } ],
  342. object: {
  343. uuid: 'scene-1',
  344. type: 'Scene',
  345. children: [
  346. {
  347. uuid: 'mesh-1',
  348. type: 'Mesh',
  349. name: 'First',
  350. geometry: 'geom-1',
  351. material: 'mat-1',
  352. matrix: [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ],
  353. layers: 1
  354. },
  355. {
  356. uuid: 'mesh-2',
  357. type: 'Mesh',
  358. name: 'Second',
  359. geometry: 'geom-1',
  360. material: 'mat-1',
  361. matrix: [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 2, 0, 0, 1 ],
  362. layers: 1
  363. },
  364. {
  365. uuid: 'mesh-3',
  366. type: 'Mesh',
  367. name: 'Third',
  368. geometry: 'geom-1',
  369. material: 'mat-1',
  370. matrix: [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 4, 0, 0, 1 ],
  371. layers: 1
  372. },
  373. {
  374. uuid: 'mesh-4',
  375. type: 'Mesh',
  376. name: 'Fourth',
  377. geometry: 'geom-1',
  378. material: 'mat-1',
  379. matrix: [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 6, 0, 0, 1 ],
  380. layers: 1
  381. }
  382. ]
  383. }
  384. };
  385. const loader = new ObjectLoader();
  386. const scene = loader.parse( json );
  387. assert.strictEqual( scene.children.length, 4, 'Has 4 children' );
  388. assert.strictEqual( scene.children[ 0 ].name, 'First', 'First child name' );
  389. assert.strictEqual( scene.children[ 1 ].name, 'Second', 'Second child name' );
  390. assert.strictEqual( scene.children[ 2 ].name, 'Third', 'Third child name' );
  391. assert.strictEqual( scene.children[ 3 ].name, 'Fourth', 'Fourth child name' );
  392. } );
  393. QUnit.test( 'Mixed object types in hierarchy', ( assert ) => {
  394. const json = {
  395. metadata: { version: 4.7, type: 'Object', generator: 'Object3D.toJSON' },
  396. geometries: [ {
  397. uuid: 'geom-1',
  398. type: 'BoxGeometry',
  399. width: 1,
  400. height: 1,
  401. depth: 1
  402. } ],
  403. materials: [
  404. { uuid: 'mat-1', type: 'MeshBasicMaterial', color: 16711680 },
  405. { uuid: 'mat-2', type: 'SpriteMaterial', color: 65280 }
  406. ],
  407. object: {
  408. uuid: 'scene-1',
  409. type: 'Scene',
  410. children: [
  411. {
  412. uuid: 'group-1',
  413. type: 'Group',
  414. name: 'Objects',
  415. matrix: [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ],
  416. layers: 1,
  417. children: [
  418. {
  419. uuid: 'mesh-1',
  420. type: 'Mesh',
  421. geometry: 'geom-1',
  422. material: 'mat-1',
  423. matrix: [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ],
  424. layers: 1
  425. },
  426. {
  427. uuid: 'sprite-1',
  428. type: 'Sprite',
  429. material: 'mat-2',
  430. matrix: [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 2, 0, 0, 1 ],
  431. layers: 1
  432. }
  433. ]
  434. },
  435. {
  436. uuid: 'light-1',
  437. type: 'AmbientLight',
  438. color: 16777215,
  439. intensity: 0.5,
  440. matrix: [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ],
  441. layers: 1
  442. },
  443. {
  444. uuid: 'cam-1',
  445. type: 'PerspectiveCamera',
  446. fov: 75,
  447. aspect: 1,
  448. near: 0.1,
  449. far: 1000,
  450. matrix: [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 5, 1 ],
  451. layers: 1
  452. }
  453. ]
  454. }
  455. };
  456. const loader = new ObjectLoader();
  457. const scene = loader.parse( json );
  458. assert.strictEqual( scene.children.length, 3, 'Scene has 3 children' );
  459. assert.ok( scene.children[ 0 ].isGroup, 'First child is Group' );
  460. assert.ok( scene.children[ 1 ].isAmbientLight, 'Second child is AmbientLight' );
  461. assert.ok( scene.children[ 2 ].isPerspectiveCamera, 'Third child is PerspectiveCamera' );
  462. const group = scene.children[ 0 ];
  463. assert.ok( group.children[ 0 ].isMesh, 'Group first child is Mesh' );
  464. assert.ok( group.children[ 1 ].isSprite, 'Group second child is Sprite' );
  465. } );
  466. } );
  467. } );
粤ICP备19079148号