|
| 1 | +// @config HIDDEN |
| 2 | +import { deviceType, rootPath } from 'examples/utils'; |
| 3 | +import * as pc from 'playcanvas'; |
| 4 | + |
| 5 | +const canvas = /** @type {HTMLCanvasElement} */ (document.getElementById('application-canvas')); |
| 6 | +window.focus(); |
| 7 | + |
| 8 | +const gfxOptions = { |
| 9 | + deviceTypes: [deviceType], |
| 10 | + |
| 11 | + // disable antialiasing as gaussian splats do not benefit from it and it's expensive |
| 12 | + antialias: false |
| 13 | +}; |
| 14 | + |
| 15 | +const device = await pc.createGraphicsDevice(canvas, gfxOptions); |
| 16 | +device.maxPixelRatio = Math.min(window.devicePixelRatio, 2); |
| 17 | + |
| 18 | +const createOptions = new pc.AppOptions(); |
| 19 | +createOptions.graphicsDevice = device; |
| 20 | +createOptions.mouse = new pc.Mouse(document.body); |
| 21 | +createOptions.touch = new pc.TouchDevice(document.body); |
| 22 | +createOptions.keyboard = new pc.Keyboard(document.body); |
| 23 | + |
| 24 | +createOptions.componentSystems = [ |
| 25 | + pc.RenderComponentSystem, |
| 26 | + pc.CameraComponentSystem, |
| 27 | + pc.LightComponentSystem, |
| 28 | + pc.ScriptComponentSystem, |
| 29 | + pc.GSplatComponentSystem |
| 30 | +]; |
| 31 | +createOptions.resourceHandlers = [pc.TextureHandler, pc.ContainerHandler, pc.ScriptHandler, pc.GSplatHandler]; |
| 32 | + |
| 33 | +const app = new pc.AppBase(canvas); |
| 34 | +app.init(createOptions); |
| 35 | + |
| 36 | +// Set the canvas to fill the window and automatically change resolution to be the same as the canvas size |
| 37 | +app.setCanvasFillMode(pc.FILLMODE_FILL_WINDOW); |
| 38 | +app.setCanvasResolution(pc.RESOLUTION_AUTO); |
| 39 | + |
| 40 | +// Ensure canvas is resized when window changes size |
| 41 | +const resize = () => app.resizeCanvas(); |
| 42 | +window.addEventListener('resize', resize); |
| 43 | +app.on('destroy', () => { |
| 44 | + window.removeEventListener('resize', resize); |
| 45 | +}); |
| 46 | + |
| 47 | +pc.Tracing.set(pc.TRACEID_SHADER_ALLOC, true); |
| 48 | + |
| 49 | +const assets = { |
| 50 | + biker: new pc.Asset('gsplat', 'gsplat', { url: `${rootPath}/static/assets/splats/biker.compressed.ply` }), |
| 51 | + // church: new pc.Asset('gsplat', 'gsplat', { url: `${rootPath}/static/assets/splats/church.ply` }), |
| 52 | + // church: new pc.Asset('gsplat', 'gsplat', { url: `${rootPath}/static/assets/splats/onsen.ply` }), |
| 53 | + // church: new pc.Asset('gsplat', 'gsplat', { url: `${rootPath}/static/assets/splats/uzumasa.ply` }), |
| 54 | + church: new pc.Asset('gsplat', 'gsplat', { url: `${rootPath}/static/assets/splats/morocco.ply` }), |
| 55 | + |
| 56 | + // logo: new pc.Asset('gsplat', 'gsplat', { url: `${rootPath}/static/assets/splats/playcanvas-logo/meta.json` }), |
| 57 | + logo: new pc.Asset('gsplat', 'gsplat', { url: `${rootPath}/static/assets/splats/pclogo.ply` }), |
| 58 | + // logo: new pc.Asset('gsplat', 'gsplat', { url: `${rootPath}/static/assets/splats/anneli.ply` }), |
| 59 | + // logo: new pc.Asset('gsplat', 'gsplat', { url: `${rootPath}/static/assets/splats/museum.ply` }), |
| 60 | + // logo: new pc.Asset('gsplat', 'gsplat', { url: `${rootPath}/static/assets/splats/uzumasa.ply` }), |
| 61 | + guitar: new pc.Asset('gsplat', 'gsplat', { url: `${rootPath}/static/assets/splats/guitar.compressed.ply` }), |
| 62 | + |
| 63 | + shoe: new pc.Asset('gsplat', 'gsplat', { url: `${rootPath}/static/assets/splats/shoe-with-sh.ply` }), |
| 64 | + shoeNoSh: new pc.Asset('gsplat', 'gsplat', { url: `${rootPath}/static/assets/splats/shoe-without-sh.ply` }), |
| 65 | + |
| 66 | + // pokemon: new pc.Asset('gsplat', 'gsplat', { url: `${rootPath}/static/assets/splats/pokemon.ply` }), |
| 67 | + skull: new pc.Asset('gsplat', 'gsplat', { url: `${rootPath}/static/assets/splats/skull.ply` }), |
| 68 | + |
| 69 | + fly: new pc.Asset('fly', 'script', { url: `${rootPath}/static/scripts/camera/fly-camera.js` }), |
| 70 | + orbit: new pc.Asset('script', 'script', { url: `${rootPath}/static/scripts/camera/orbit-camera.js` }) |
| 71 | +}; |
| 72 | + |
| 73 | +const assetListLoader = new pc.AssetListLoader(Object.values(assets), app.assets); |
| 74 | +assetListLoader.load(() => { |
| 75 | + app.start(); |
| 76 | + |
| 77 | + // create a splat entity and place it in the world |
| 78 | + const biker = new pc.Entity(); |
| 79 | + biker.setLocalPosition(2.5, 1, 1); |
| 80 | + biker.setLocalEulerAngles(180, 90, 0); |
| 81 | + // biker.setLocalScale(0.7, 0.7, 0.7); |
| 82 | + // biker.setLocalScale(7, 7, 7); |
| 83 | + |
| 84 | + const biker2 = new pc.Entity(); |
| 85 | + biker2.setLocalPosition(2.5, 1, 0); |
| 86 | + biker2.setLocalEulerAngles(180, 90, 0); |
| 87 | + // biker2.setLocalScale(0.7, 0.7, 0.7); |
| 88 | + biker2.setLocalScale(7, 7, 7); |
| 89 | + |
| 90 | + |
| 91 | + const logo = new pc.Entity(); |
| 92 | + logo.setLocalPosition(0, 1.5, 1); |
| 93 | + logo.setLocalEulerAngles(180, 0, 0); |
| 94 | + logo.setLocalScale(0.5, 0.5, 0.5); |
| 95 | + |
| 96 | + const church = new pc.Entity(); |
| 97 | + church.setLocalEulerAngles(180, 90, 0); |
| 98 | + |
| 99 | + const guitar = new pc.Entity(); |
| 100 | + guitar.setLocalPosition(0, 0.6, 4); |
| 101 | + guitar.setLocalEulerAngles(180, 0, 0); |
| 102 | + guitar.setLocalScale(0.5, 0.5, 0.5); |
| 103 | + |
| 104 | + // Create an Entity with a camera component |
| 105 | + const camera = new pc.Entity(); |
| 106 | + camera.addComponent('camera', { |
| 107 | + clearColor: new pc.Color(0.2, 0.2, 0.2), |
| 108 | + fov: 75, |
| 109 | + toneMapping: pc.TONEMAP_ACES |
| 110 | + }); |
| 111 | + camera.setLocalPosition(-0.8, 2, 3); |
| 112 | + camera.addComponent('script'); |
| 113 | + camera.script.create('orbitCameraInputMouse'); |
| 114 | + camera.script.create('orbitCameraInputTouch'); |
| 115 | + camera.script.create('flyCamera', { |
| 116 | + attributes: { |
| 117 | + speed: 2 |
| 118 | + } |
| 119 | + }); |
| 120 | + |
| 121 | + app.root.addChild(camera); |
| 122 | + |
| 123 | + // temporary API |
| 124 | + const manager = new pc.GSplatManager(app.graphicsDevice, camera); |
| 125 | + |
| 126 | + const worldLayer = app.scene.layers.getLayerByName('World'); |
| 127 | + worldLayer.addMeshInstances([manager.renderer.meshInstance]); |
| 128 | + |
| 129 | + manager.add(assets.church.resource, church); |
| 130 | + manager.add(assets.guitar.resource, guitar); |
| 131 | + manager.add(assets.logo.resource, logo); |
| 132 | + |
| 133 | + |
| 134 | + let timeToChange = 1; |
| 135 | + let time = 0; |
| 136 | + let guitarTime = 0; |
| 137 | + let added = false; |
| 138 | + app.on('update', (/** @type {number} */ dt) => { |
| 139 | + time += dt; |
| 140 | + timeToChange -= dt; |
| 141 | + |
| 142 | + logo.rotateLocal(0, 100 * dt, 0); |
| 143 | + |
| 144 | + // each even second, update the guitar as well |
| 145 | + // if (Math.floor(time) % 2 === 0) { |
| 146 | + guitarTime += dt; |
| 147 | + |
| 148 | + // orbit guitar around |
| 149 | + guitar.setLocalPosition(0.5 * Math.sin(guitarTime), 2, 0.5 * Math.cos(guitarTime) + 1); |
| 150 | + // } |
| 151 | + |
| 152 | + // ping pong logo between two positions along x-axies |
| 153 | + logo.setLocalPosition(5.5 + 5 * Math.sin(time), 1.5, -2); |
| 154 | + |
| 155 | + |
| 156 | + if (timeToChange <= 0) { |
| 157 | + |
| 158 | + if (!added) { |
| 159 | + console.log('adding shoe'); |
| 160 | + added = true; |
| 161 | + timeToChange = 1; |
| 162 | + |
| 163 | + // worldLayer.removeMeshInstances([manager.meshInstance]); |
| 164 | + manager.add(assets.skull.resource, biker); |
| 165 | + // manager.add(assets.shoe.resource, biker2); |
| 166 | + // worldLayer.addMeshInstances([manager.meshInstance]); |
| 167 | + |
| 168 | + } else { |
| 169 | + console.log('removing shoe'); |
| 170 | + added = false; |
| 171 | + timeToChange = 1; |
| 172 | + |
| 173 | + // worldLayer.removeMeshInstances([manager.meshInstance]); |
| 174 | + |
| 175 | + |
| 176 | + manager.remove(biker); |
| 177 | + // manager.remove(biker2); |
| 178 | + // worldLayer.addMeshInstances([manager.meshInstance]); |
| 179 | + } |
| 180 | + } |
| 181 | + |
| 182 | + |
| 183 | + manager.update(); |
| 184 | + }); |
| 185 | +}); |
| 186 | + |
| 187 | +export { app }; |
0 commit comments