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