Skip to content

FBX

Example

Example Source Code
tsx
import React, { useCallback, useEffect, useRef, useState } from 'react'
import ReactDOM from 'react-dom'
import * as THREE from 'three'
import { FBXLoader } from 'FBXLoader'
import { MbMap, MbTiandituLayer } from '@mapbox-react/core'

const App = () => {
  const [mapCenter] = useState([116.3466, 39.8704])
  const [zoom, setZoom] = useState(16)
  const [pitch, setPitch] = useState(45)
  const mapInst = useRef<any>()

  let map: any
  const altitude = 0
  let mixers: THREE.AnimationMixer[] = []
  let clock = new THREE.Clock()

  const mapCreated = (mapbox: any) => {
    map = mapbox
    mixers = []
    clock = new THREE.Clock()
  }
  const add3DLayer = () => {
    loaderModels()
  }

  const loaderModels = () => {
    const loader = new FBXLoader()
    loader.load(
      `https://mapbox-web.github.io/mapbox-react/fbx/Samba Dancing.fbx`,
      (dancer) => {
        dancer.scale.multiplyScalar(4)
        dancer.rotation.x = Math.PI * 1.5
        const mixer = new THREE.AnimationMixer(dancer)
        const action = mixer.clipAction(dancer.animations[0])
        action.play()

        mixers.push(mixer)

        addThreeLayer(dancer)
      }
    )
  }
  const addThreeLayer = (dancer) => {
    const threeLayer = new map.mapboxgl.supermap.ThreeLayer('threeLayer')
    threeLayer.on('initialized', render)

    let light: THREE.PointLight
    function render() {
      const renderer = threeLayer.getThreeRenderer(),
        scene = threeLayer.getScene(),
        camera = threeLayer.getCamera()

      light = new THREE.PointLight(0xffffff, 0.8)
      light.position.copy(camera.position)
      scene.add(light)
      scene.add(new THREE.AmbientLight(0xffffff))

      threeLayer.setPosition(dancer, mapCenter)

      scene.add(dancer)
        ; (function animate() {
          const delta = clock.getDelta()
          for (const mixer of mixers) {
            mixer.update(delta)
          }
          renderer.render(scene, camera)

          requestAnimationFrame(animate)
        })()
    }

    // 均匀光照,与相机位置同步
    // Even lighting, synchronized with camera position
    threeLayer.on('render', () => {
      light && light.position.copy(threeLayer.renderer.camera.position)
    })
    map.addLayer(threeLayer)
  }

  return (
    <div className="map-wrapper">
      <MbMap
        ref={mapInst}
        center={mapCenter}
        zoom={zoom}
        pitch={pitch}
        onCreated={mapCreated}
      >
        <MbTiandituLayer types={['vec', 'cva']} onCreated={add3DLayer} />
      </MbMap>
    </div>
  )
}

ReactDOM.render(<App />, document.querySelector('#root'))