playcanvas制作3d地球
代码语言:html
所属分类:其他
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>ISS Tracker (PlayCanvas)</title> <style> body { overflow: hidden; background-color: #000; } canvas { position: fixed; top: 0; left: 0; width: 100%; height: 100%; } #logo { z-index: 2; position: fixed; padding: 24px; top: 0; right: 0; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } </style> </head> <body translate="no"> <script type="text/javascript" src="http://repo.bfw.wiki/bfwrepo/js/playcanvas-1.22.0.js"></script> <script > /********************************************** * UTILS **********************************************/ const fetchData = async endpoint => { const res = await fetch(endpoint); if (res.ok) { const data = await res.json(); return data; } throw new Error('unexpected status', response); }; const applyMaterialTextures = (textures, material, assetPrefix = 'root', cb) => { let count = 0; Object.entries(textures).forEach(([property, url], i, l) => { const asset = new pc.Asset(`${assetPrefix}-${property}`, 'texture', { url }); app.assets.add(asset); app.assets.load(asset); asset.ready(() => { count++; material[property] = asset.resource; if (count === l.length) { if (typeof cb === 'function') cb(material); } }); }); }; /********************************************** * SETUP * --------------------------------------------- * create canvas and add it to the DOM * create app and attach canvas and inputs * enable crossorigin asset loading * setup window resize listeners * setup canvasFillMode, canvasResolution * load slighly higher res sphere model **********************************************/ const canvas = document.createElement('canvas'); document.body.appendChild(canvas); const app = new pc.Application(canvas, { elementInput: new pc.ElementInput(canvas), keyboard: new pc.Keyboard(canvas), mouse: new pc.Mouse(canvas), touch: 'ontouchstart' in window ? new pc.TouchDevice(canvas) : null }); app.start(); app.loader.getHandler('texture').crossOrigin = 'anonymous'; app.setCanvasFillMode(pc.FILLMODE_FILL_WINDOW); app.setCanvasResolution(pc.RESOLUTION_AUTO); window.addEventListener('resize', function () { app.resizeCanvas(canvas.width, canvas.height); }); app.scene.ambientLight = new pc.Color(0.1529, 0.1529, 0.1529); app.scene.gammaCorrection = pc.GAMMA_SRGB; app.scene.toneMapping = pc.TONEMAP_ACES; app.scene.lightmapMaxResolution = 2048; app.scene.lightmapMode = pc.BAKE_COLORDIR; app.scene.lightmapSizeMultiplier = 16; const SPHERE_MODEL = 'https://s.halvves.com/sphere.json'; const sphereModel = new pc.Asset('sphere', 'model', { url: SPHERE_MODEL }); app.assets.add(sphereModel); app.assets.load(sphereModel); /********************************************** * SCRIPT: LOADING MANAGER * --------------------------------------------- * rotate entity based on a speed attribute **********************************************/ const LoadingManager = pc.createScript('loading-manager'); LoadingManager.prototype.initialize = function () { this.skyboxIntensity = 0; this.loadedMaterials = []; this.matOpacity = 0; this.targetOpacity = 0; this.main = null; this.mainScale = new pc.Vec3(0.001, 0.001, 0.001); this.mainTargetScale = new pc.Vec3().copy(this.mainScale); this.app.on('material:loaded', this.handleMaterialLoad, this); this.app.once('skymap:loaded', this.handleSkymapLoad, this); this.app.once('register:main', this.registerMain, this); }; LoadingManager.prototype.update = function (dt) { if (this.targetOpacity > 0 && this.matOpacity < 1) { this.matOpacity = pc.math.lerp(this.matOpacity, this.targetOpacity, dt); this.loadedMaterials.forEach(mat => mat.setParameter('material_opacity', this.matOpacity)); } if (this.skyboxIntensity > 0 && app.scene.skyboxIntensity < 1) { app.scene.skyboxIntensity = pc.math.lerp( app.scene.skyboxIntensity, this.skyboxIntensity, 0.1 * dt); } if (this.main && this.mainTargetScale.x === 1) { this.mainScale.lerp(this.main.getLocalScale(), this.mainTargetScale, 2 * dt); this.main.setLocalScale(this.mainScale); } }; LoadingManager.prototype.handleMaterialLoad = function (mat) { this.loadedMaterials.push(mat); if (this.loadedMaterials.length === 3) { setTimeout(() => this.mainTargetScale.set(1, 1, 1), 2000); setTimeout(() => this.targetOpacity = 1, 2500); } }; LoadingManager.prototype.handleSkymapLoad = function () { this.skyboxIntensity = 1; }; LoadingManager.prototype.registerMain = function (main) { this.main = main; }; app.root.addComponent('script'); app.root.script.create(LoadingManager.__name); /********************************************** * SCENE: SKYBOX **********************************************/ const SKYMAP_ASSETS = [ 'https://s.halvves.com/TychoSkymapII.t3_08192x04096_80_mx.jpg', 'https://s.halvves.com/TychoSkymapII.t3_08192x04096_80_px.jpg', 'https://s.halvves.com/TychoSkymapII.t3_08192x04096_80_my.jpg', 'https://s.halvves.com/TychoSkymapII.t3_08192x04096_80_py.jpg', 'https://s.halvves.com/TychoSkymapII.t3_08192x04096_80_pz.jpg', 'https://s.halvves.com/TychoSkymapII.t3_08192x04096_80_mz.jpg']; const skymapAsset = new pc.Asset('skymap', 'cubemap', null, { 'textures': SKYMAP_ASSETS.map((url, i) => { const asset = new pc.Asset(`skymap-${i}`, 'texture', { url }); app.assets.add(asset); app.assets.load(asset); return asset.id; }), 'magFilter': 1, 'minFilter': 5, 'anisotropy': 1, 'name': 'skymap' }); app.scene.skyboxIntensity = 0; app.assets.add(skymapAsset); app.assets.load(skymapAsset); skymapAsset.ready(() => { app.scene.skyboxMip = 1; app.scene.setSkybox(skymapAsset.resources); app.fire('skymap:loaded'); }); /********************************************** * SCRIPT: ORBIT CAMERA * --------------------------------------------- * **********************************************/ var Camera = pc.createScript('camera'); Camera.attributes.add('maxElevation', { type: 'number', title: 'Max Elevation', default: 70 }); // initialize code called once per entity Camera.prototype.initialize = function () { this.viewPos = new pc.Vec3(); this.targetViewPos = new pc.Vec3(); this.tempVec = new pc.Vec3(); this.distance = 5; this.targetDistance = 5; this.rotX = 180; this.rotY = -15; this.targetRotX = 25; this.targetRotY = 15; this.quatX = new pc.Quat(); this.quatY = new pc.Quat(); this.transformStarted = false; this.app.mouse.on(pc.EVENT_MOUSEMOVE, this.onMouseMove, this); this.app.mouse.on(pc.EVENT_MOUSEWHEEL, this.onMouseWheel, this); }; Camera.prototype.dolly = function (movez) { this.targetDistance = Math.max(this.targetDistance + movez, 1.8); }; Camera.prototype.orbit = function (movex, movey) { this.targetRotX += movex; this.targetRotY += movey; this.targetRotY = pc.math.clamp(this.targetRotY, -this.maxElevation, this.maxElevation); }; Camera.prototype.onMouseWheel = function (event) { event.event.preventDefault(); this.dolly(event.wheel * -0.25); }; Camera.prototype.onMouseMove = function (event) { if (event.buttons[pc.MOUSEBUTTON_LEFT]) this.orbit(event.dx * 0.2, event.dy * 0.2); }; // update code called every frame Camera.prototype.update = function (dt) { // Implement a delay in camera controls by lerping towards a target this.viewPos.lerp(this.viewPos, this.targetViewPos, dt / 0.1); this.distance = pc.math.lerp(this.distance, this.targetDistance, dt / 0.2); this.rotX = pc.math.lerp(this.rotX, this.targetRotX, dt / 0.2); this.rotY = pc.math.lerp(this.rotY, this.targetRotY, dt / 0.2); // Calculate the camera's rotation this.quatX.setFromAxisAngle(pc.Vec3.RIGHT, -this.rotY); this.quatY.setFromAxisAngle(pc.Vec3.UP, -this.rotX); this.quatY.mul(this.quatX); // Set the camera's current position and orientation this.entity.setPosition(this.viewPos); this.entity.setRotation(this.quatY); this.entity.translateLocal(0, 0, this.distance); }; /********************************************** * ENTITY: CAMERA **********************************************/ const camera = new pc.Entity(); camera.addComponent('camera', { clearColor: new pc.Color(0, 0, 0) }); camera.setPosition(0, 0, 3); camera.addComponent('script'); camera.script.create(Camera.__name); app.root.addChild(camera); /********************************************** * SCRIPT: ROTATE * --------------------------------------------- * rotate entity based on a speed attribute **********************************************/ const Rotate = pc.createScript('rotate'); Rotate.attributes.add('speed', { type: 'number', default: 1 }); Rotate.prototype.update = function (dt) { this.entity.rotateLocal(0, dt * this.speed, 0); }; /********************************************** * SCRIPT: EARTHTIME * --------------------------------------------- * rotate entity based on time on earth **********************************************/ const ROTATION_AT_MIDNIGHT = -60; // rough estimation for this model const DAY_IN_MS = 1000 * 60 * 60 * 24; const EarthTime = pc.createScript('earth-time'); EarthTime.prototype.update = function (dt) { const progress = Dat.........完整代码请登录后点击上方下载按钮下载查看
网友评论0