Load optimizer with compass

Make writing a habit together! This is the fifth day of my participation in the “Gold Digging Day New Plan · April More text Challenge”. Click here for more details.

This article mainly introduces threejs optimization loading efficiency and compass implementation, the above figure is the integration of the previous function of the article, specifically to clip ~

Here why will optimize and compass in an article, because both are relatively simple, so consider combined for an article introduction ~

By the way, anyone interested in particles can read my previous article! I wrote it in great detail, but! I was restricted to streaming, not recommended to the home page! Writing is not easy, pig sigh ~

The compass

The effect is as shown in the cover drawing. It is mainly realized by the rotation and synchronization of two pictures following the scene, which is relatively simple

Code analysis: through a base map and the overlay of the compass picture, through the frame animation to calculate the Angle of the camera synchronized to the compass rotation

Viewer.prototype.initCompass = function () {
  const znzbg = document.createElement('img')
  znzbg.src = '/static/images/znzd.png'
  znzbg.style.position = 'absolute'
  znzbg.style.right = '500px'
  znzbg.style.top = '80px'
  znzbg.style.width = '80px'
  znzbg.style.height = '80px'
  const znz = document.createElement('img')
  znz.src = '/static/images/znz.png'
  znz.style.position = 'absolute'
  znz.style.right = '510px'
  znz.style.top = '90px'
  znz.style.width = '60px'
  znz.style.height = '60px'
  this.znz = znz
  this.el.appendChild(znzbg)
  this.el.appendChild(znz)
  this.renderFunction.push(() = > {
    var dir = new THREE.Vector3(-this.camera.position.x, 0, -this.camera.position.z).normalize()
    var theta = Math.atan2(-dir.x, -dir.z)
    if (this.znz) this.znz.style.transform = `rotate(${THREE.Math.radToDeg(theta) + 45}deg)`})}Copy the code

Threejs load optimization

Experienced students have a problem, that is, the scene is large, each time to load it takes a lot of time. If multiple scenes are loaded into memory at the same time, a lag occurs. How to solve this problem?

Model tile loading

The first time we load the scene, we need to parse the model file. The time for parsing the file cannot be optimized, but we can fragment the model file – tile load. Loading as a tile is just a split load, so it doesn’t affect the loading time of the scene

What if we load the fragmented model asynchronously through a configuration JSON? Does this greatly speed up the loading rate? Ideally, the more fragmented the model, the faster the loading rate

const configFile = 'data/parkBuildings/fbs/config.json' / / configuration JSON
return new Promise((resolve, reject) = > {
  axios.get(configFile, {baseURL}).then(res= > {
  // Load the model
  loadModel
}).catch(reason= > {
  console.error(reason)
  reject(reason)
})
Copy the code
// Tile loading
Viewer.prototype.loadModel = (url, layeridx, callback) = > {
  const that = gapp
  const loader = new GLTFExtensionLoader(gapp.manager)
  loader.workingPath = loader.workingPathForURL(url)
  loader.load(url)
    .then(gltf= > {
      gltf.scene.traverse((e) = > {
        e.layers.set(layeridx)
        e.userData.orglayers = layeridx // Primitive level
      })
      const clips = gltf.animations || []// If there is an animated segment. Extract all animation segments
      gapp.addclips(clips, layeridx)
      gapp.glayers[layeridx].add(gltf.scene)
      callback ? callback(gltf.scene) : ' '})}Copy the code

Problems with tile loading

Through the above optimization, do you feel there are still defects ~ we usually achieve multiple scenes of the solution is a one-time load through the camera level switch? Or do you switch over and load the model?

In fact, the problem shows the above optimization still exists! When we need to switch the requirements of multiple scenes, if it is loaded at one time, it is stored in the memory. Although it is not necessary to load multiple times by adjusting the hierarchy through the camera, it still has the problem of too much memory consumption and lag. Therefore, through the first solution, we still can’t solve the problem of fast loading and slow loading to the maximum extent. Of course, if we switch scenes to do the loading, then the user experience is too poor, this scheme is of course passed. So what can we do to have it both ways?

Load optimization

I don’t know if you’re familiar with indexDb, but indexDb is a non-relational database for the browser. Here’s how an indexDb can be used to optimize the scene.

indexDb

  1. JSON parsed from model files can be anywhere from tens of megabytes to hundreds of megabytes, which is too large for the storage commonly used by the back browser
  2. IndexDb does exactly that and is a mongodb – like database. File names and parsed objects can be stored in indexDb in one-to-one correspondence
  3. This allowed us to convert all tile resolution objects to a specific JSON format via Threejs’ toJSON and store them as key-value pairs in indexDb after the first loading of all scene models.
  4. Secondary loading and switching only need to fetch the corresponding tile object in indexDb according to the configuration object through Threejs fromJSON method, parse the JSON into the object format and add to the scene
// Convert to threejs-specific JSON formatScene.tojson () (Threejs, in order to reduce the size of the tile object, split the material as much as possible, associate it with id and save it as JSON)// Parse json into objects
Viewer.prototype.fromJSON = function (json, layeridx, isRayobj) {
  return new Promise((resolve, reject) = > {
    // Parse the JSON object
    let loader = new THREE.ObjectLoader();
    let loadedMesh = loader.parse(json);
    let scene = this.mergeToMaterialsMap(loadedMesh, true)
    resolve(scene)
  })
}
Copy the code

Summary of scene optimization scheme

< tile asynchronous loading > < store and transform tile objects > < parse tile objects without repeated parsing > < multiple scene switch without re-parsing model > < load one scene at a time to reduce memory footprint >

conclusion

Not easy to write, pig sigh! Students who are interested in Threejs can follow my column and update threejs-related cases and solutions from time to time