<!DOCTYPE html> <html> <head> <title>Comp 86 example: Scene</title> <!-- This is like my Java3d Example2 --> <script type="importmap"> { "imports": { "three": "https://unpkg.com/three@0.156.0/build/three.module.js", "three/addons/": "https://unpkg.com/three@0.156.0/examples/jsm/" } } </script> <script type="module"> /* * Our stuff goes here * Do the scene as an object, subclass of THREE.Object3D * but kind of a silly object, cause no state or behavior, just constructor */ class SceneGraph extends THREE.Scene { constructor () { // Call the superclass' constructor super() // First item = a box, rotated and translated let box = new THREE.Mesh ( //*2 Tall box new THREE.BoxGeometry (1, 3, 1), //*2 new THREE.MeshPhongMaterial()) //*2 // Move it back from origin and to the right box.position.set (5, 0, -4) //*2 // Rotate it in X and Y box.rotation.set (45 * Math.PI/180, 30 * Math.PI/180, 0) //*2 // Plug it in to our scene this.add (box) //*2 // A sphere, in a different location let sphere = new THREE.Mesh ( //*3 Sphere new THREE.SphereGeometry(1, 32, 32), //*3 new THREE.MeshPhongMaterial()) //*3 sphere.position.set (-5, 0, -3) //*3 this.add (sphere) //*3 // A pyramid, using our class below let pyramid = new Pyramid () //*4 Pyramid pyramid.position.set (0, 0, -6) //*4 pyramid.rotation.set (0, 45 * Math.PI/180, 0) //*4 this.add (pyramid) //*4 } } /* * Make a pyramid out of other objects (3 Box's stacked up) * as a new mini scene graph that contains it */ class Pyramid extends THREE.Object3D { //*4 constructor () { super() // Bottom Box, located slightly down // (relative to origin of the pyramid) let bot = new THREE.Mesh ( //*5 Pyramid bottom box new THREE.BoxGeometry (3, 3, 3), //*5 new THREE.MeshPhongMaterial()) //*5 bot.position.set (0, -3/2, 0) //*5 this.add (bot) //*5 // Middle Box, slightly up let mid = new THREE.Mesh ( //*6 Pyramid middle box new THREE.BoxGeometry (2, 2, 2), //*6 new THREE.MeshPhongMaterial()) //*6 mid.position.set (0, 2/2, 0) //*6 this.add (mid) //*6 // Top box, further up let top = new THREE.Mesh ( //*7 Pyramid top box new THREE.BoxGeometry (1, 1, 1), //*7 new THREE.MeshPhongMaterial()) //*7 top.position.set (0, 2 + 1/2, 0) //*7 this.add (top) //*7 } } /* * The rest of this is boilerplate */ import * as THREE from "three"; import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; class Main { constructor () { // Set up window for 3D this.renderer = new THREE.WebGLRenderer( { antialias: true } ); this.renderer.setClearColor( new THREE.Color ("lightgrey")) this.renderer.setSize( window.innerWidth, window.innerHeight ); document.body.appendChild( this.renderer.domElement ); // Create our scene this.scene = new SceneGraph(); // Create the camera this.camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 1000 ); this.camera.position.z = 5; // Create a camera contol new OrbitControls( this.camera, this.renderer.domElement ); // Start animation loop this.animate() // In case window is resized // use () form of function definition cause need "this" // but don't need "event" arg window.onresize = () => this.onResize() } /* * Render the scene */ render() { this.renderer.render( this.scene, this.camera ); } /* * Animation loop */ animate () { requestAnimationFrame (() => {this.animate()}); this.render() } // In case window is resized onResize () { this.renderer.setSize( window.innerWidth, window.innerHeight ); this.camera.aspect = window.innerWidth / window.innerHeight; this.camera.updateProjectionMatrix(); this.render() } } window.onload = () => new Main () </script> </head> </html>