These ten questions turn on Babylon.js 89,603 behaviors that catch developers who know the engine: a position that aliases a vector, world positions that lag their parents, defaults that clip and race, clones that share, PBR settings that are not set, a particle system that stalls readiness, bodies that ignore their meshes, a pipeline that switches antialiasing off, getters that disagree with their options, and XR that fails quietly. Save both pages beside bookstore.js (First Render) and l2-physics.js (Havok) and run them with the check.mjs script of Test Yourself!, which is how the answers in Appendix H were produced in Chrome 154 1 . Write down what each line prints, and why, before you look.
Questions
<!-- 1. A Vector3 assigned to a book's position, then changed. Where is the book?
(Section 7.2.2) -->
<!-- 2. A book on a shelf of a bookcase at x -1.8. What x do absolutePosition and
getAbsolutePosition() report before the first frame, and after a forced
computeWorldMatrix(true)? (Sections 7.2.2 and 7.4.6) -->
<!-- 3. A UniversalCamera with default settings. What are its near plane and speed?
(Sections 7.3.2 and 7.3.5) -->
<!-- 4. A book cloned and the clone painted red. What is shared, and what color is the
original? (Sections 7.4.4 and 7.5.1) -->
<!-- 5. A new PBRMaterial. What metallic and roughness does it report? (Section 7.5.3) -->
<canvas id="view"></canvas>
<script src="https://cdn.jsdelivr.net/npm/babylonjs@9.28.0/babylon.js"></script>
<script src="bookstore.js"></script>
<script>
{
const engine = new BABYLON.Engine(view);
const scene = BookNestStore.createScene(engine);
const bookcase = BookNestStore.createBookcase(scene, 'bookcaseLeft', -1.8);
const [book, second] = BookNestStore.placeBooks(scene, bookcase);
const where = new BABYLON.Vector3(0, 1.27, -0.02);
book.position = where;
where.x = 0.5;
console.log('1:', book.position.x);
const x = () => second.getAbsolutePosition().x.toFixed(3);
console.log('2:', second.absolutePosition.x.toFixed(3), x(),
second.computeWorldMatrix(true) && x());
const camera = new BABYLON.UniversalCamera('walk', new BABYLON.Vector3(0, 1.6, 0), scene);
console.log('3:', camera.minZ, camera.speed);
const copy = book.clone('copy');
copy.material.diffuseColor = BABYLON.Color3.Red();
console.log('4:', copy.geometry === book.geometry, copy.material === book.material,
book.material.diffuseColor.toHexString());
const paper = new BABYLON.PBRMaterial('paper', scene);
console.log('5:', paper.metallic, paper.roughness);
window.__done = true;
}
</script><!-- 6. A particle system created, its texture still to come. Does whenReadyAsync()
resolve within two seconds? (Section 7.15.1) -->
<!-- 7. A book dropped with Havok, then lifted by hand after it lands. Where is it one frame
later? (Section 7.14.3) -->
<!-- 8. A DefaultRenderingPipeline on an antialiased engine, then grain switched on. How
many MSAA samples, and how much grain? (Section 7.16.2) -->
<!-- 9. A spatial sound created with a 90-degree inner cone. What cone does it report?
(Section 7.19.3) -->
<!-- 10. The default XR experience on a computer with no headset. What happens?
(Section 7.20.1) -->
<canvas id="view"></canvas>
<script src="https://cdn.jsdelivr.net/npm/babylonjs@9.28.0/babylon.js"></script>
<script src="bookstore.js"></script>
<script src="l2-physics.js"></script>
<script>
(async () => {
const engine = new BABYLON.Engine(view, true);
const scene = BookNestStore.createScene(engine);
const { floor } = BookNestStore.createRoom(scene);
const camera = BookNestStore.createWalkCamera(scene);
const dust = new BABYLON.ParticleSystem('dust', 100, scene);
const timeout = new Promise((resolve) => setTimeout(() => resolve('timed out'), 2000));
console.log('6:', await Promise.race([scene.whenReadyAsync().then(() => 'ready'), timeout]));
dust.dispose();
await BookNestPhysics.enableHavok(scene); // fixed 1/60 s steps
const book = BABYLON.MeshBuilder.CreateBox('book', { width: 0.1, height: 0.3 }, scene);
book.position.y = 1;
new BABYLON.PhysicsAggregate(floor, BABYLON.PhysicsShapeType.BOX, { mass: 0 }, scene);
new BABYLON.PhysicsAggregate(book, BABYLON.PhysicsShapeType.BOX, { mass: 0.6 }, scene);
for (let frame = 0; frame < 60; frame++) scene.render();
book.position.y = 2;
scene.render();
console.log('7:', book.position.y.toFixed(3));
const look = new BABYLON.DefaultRenderingPipeline('look', true, scene, [camera]);
look.grainEnabled = true;
console.log('8:', look.samples, look.grain.intensity);
await BABYLON.CreateAudioEngineAsync();
const tick = new AudioBuffer({ length: 4800, sampleRate: 48000 });
const sound = await BABYLON.CreateSoundAsync('tick', tick,
{ spatialEnabled: true, spatialConeInnerAngle: Math.PI / 2 });
console.log('9:', sound.spatial.coneInnerAngle.toFixed(3));
const xr = await scene.createDefaultXRExperienceAsync({ floorMeshes: [floor] });
const button = document.querySelector('.xr-button-overlay button');
console.log('10:', await navigator.xr.isSessionSupported('immersive-vr'),
Object.keys(xr).length, button ? 'enter button' : 'no button');
window.__done = true;
})().catch((error) => { console.log('error:', error.message); window.__done = true; });
</script>