threejsパノラマとアンカー編集

パノラマとアンカーの編集

一緒に書く習慣を身につけましょう!「ナゲッツデイリーニュープラン・4月アップデートチャレンジ」に参加して6日目です。クリックしてイベントの詳細をご覧ください

今日は、threejsパノラマとアンカー編集ソリューションについて簡単に説明しましょう。パノラマはいわゆるスカイボックスで、シーンモデルの空の背景、夜の星空の背景、VR視聴などのシーンに適用されます〜

この記事では、いわゆるシーン編集スキームであるアンカー編集に焦点を当てます。ローコードと言えば、このアイデアはローコードに限りなく近いものです。お正月は忙しくて更新する時間がなかったので、4つの記事を延期しました!多くの人が私が終わるのを待っているのを見てとても残念です、私は必ず片付けて後で更新するでしょう!

パノラマ

実際、パノラマはそれとは何の関係もありません。それは、6つの側面の写真で接続された非常に大きな立方体の箱として想像することができます。そして、私たちのカメラは立方体の中に存在し、それは私たちがシーンにいるという視覚的なエラーを生み出します。

パノラマ解体

パノラマキューブの解体図は次のとおりです。6つの側面がつながっています。それを補うことができます。キューブを組み立てると、シームレスなシーンが表示されます。もちろん、よく見ると、まだ立方体の境界を見ることができます。

カメラの位置にサイコロの頭脳を追加できるのでわかりやすいです

スカイボックスがあるので、複数のシーンのスカイボックスには違いがあるはずです。シーンを切り替えるときに、対応するスカイボックスをどのように切り替えるのですか?非常に単純です。次のようにスイッチング関数をカプセル化する必要があります。

// 添加地面和天空盒
Viewer.prototype.changeSkyBox = function (skydir) {
  const that = this
  // 创建几何模型 BoxGeometry('x轴', '轴', 'z轴')
  const geometry = new THREE.BoxGeometry(999, 999, 999)
  // 创建纹理贴图  前后  上下  左右
  const texture0 = new THREE.TextureLoader().load((gAppPath + `/images/ysThree/sky/${skydir}/px.jpg`))
  const texture1 = new THREE.TextureLoader().load((gAppPath + `/images/ysThree/sky/${skydir}/nx.jpg`))
  const texture2 = new THREE.TextureLoader().load((gAppPath + `/images/ysThree/sky/${skydir}/py.jpg`))
  const texture3 = new THREE.TextureLoader().load((gAppPath + `/images/ysThree/sky/${skydir}/ny.jpg`))
  const texture4 = new THREE.TextureLoader().load((gAppPath + `/images/ysThree/sky/${skydir}/pz.jpg`))
  const texture5 = new THREE.TextureLoader().load((gAppPath + `/images/ysThree/sky/${skydir}/nz.jpg`))
  // 添加材质
  const material = [
    new THREE.MeshBasicMaterial({color: 0xffddff, map: texture0, side: THREE.DoubleSide}),
    new THREE.MeshBasicMaterial({color: 0xffddff, map: texture1, side: THREE.DoubleSide}),
    new THREE.MeshBasicMaterial({color: 0xffddff, map: texture2, side: THREE.DoubleSide}),
    new THREE.MeshBasicMaterial({color: 0xffddff, map: texture3, side: THREE.DoubleSide}),
    new THREE.MeshBasicMaterial({color: 0xffddff, map: texture4, side: THREE.DoubleSide}),
    new THREE.MeshBasicMaterial({color: 0xffddff, map: texture5, side: THREE.DoubleSide})
  ]
  // 创建网格对象
  const cube = new _3d.Mesh(geometry, material)
  cube.layers.enableAll()
  cube.name = 'skybox'
  that.skybox && this.scene.remove(that.skybox)
  that.skybox = cube
  that.AmbientGroup.add(cube)
}
复制代码

シーン編集スキーム

シーンごとに照明の位置やアイコンの位置が異なる場合があります。基本的な編集プラットフォームとして、シーンを構成可能にし、ニーズに応じてさまざまな変更を加える方法を検討する必要があります。前回の記事では、モデルをJSONの形式で構成することを紹介しましたが、シーン内のポイントとライトの位置をどのように構成するのでしょうか。

transformControls

トランスフォームコントローラ。ここでの主な機能は、アンカーポイントの移動、スケーリング、回転です。

コントローラを初期化します

//移动控制器
this.transformControls = new TransformControls(this.camera, this.renderer.domElement)
this.transformControls.setSize(0.5)
this.scene.add(this.transformControls) //添加入场景
复制代码

可動オブジェクトを追加する

たとえば、編集が有効になった後に呼び出されるlightクラスにtransform_attachメソッドを追加できます。アタッチ後にのみ、平行移動、回転、およびスケーリング操作のためにピックアップできます。

transformControls.attach(...)
//对象类中
transform_attach(value){
  if (value) {
    this.transformControls.attach(this.dlight)
  }
  else {
    this.transformControls.detach(this.dlight)
  }
}
复制代码

パン、ズーム、回転

gapp.history.executeは主にここでのビジネスロジックであり、編集されたオブジェクトを保存し、主にエコーに使用されます

ここでのSetPositionCommandの主な機能は、古い位置情報と新しい位置情報を記録することです。

上記の2つの方法とは別に、実際には、変換コントローラーを追加する限り、オブジェクトを操作できます。次に、情報を保存する必要がある理由を紹介します。

Viewer.prototype.bindTransformEvent = function () {

  this.transformControls.addEventListener('mouseDown', () => { //鼠标拾取到
    var object = gapp.transformControls.object //获取拾取对象
    this.objectPositionOnDown = object.position.clone()//保存位置
    this.objectRotationOnDown = object.rotation.clone()//保存角度
    this.objectScaleOnDown = object.scale.clone()//保存缩放大小
    gapp.controls.enabled = false
  })
  this.transformControls.addEventListener('mouseUp', () => {//鼠标提起
    var object = gapp.transformControls.object//获取拾取对象
    if (object !== undefined) {
      switch (gapp.transformControls.getMode()) { //这里判断是要进行平移、缩放、旋转操作
        case 'translate':
          if (!this.objectPositionOnDown.equals(object.position)) {
            gapp.history.execute(new SetPositionCommand(this, object, object.position, this.objectPositionOnDown))
          }
          break
        case 'rotate':
          if (!this.objectRotationOnDown.equals(object.rotation)) {
            gapp.history.execute(new SetRotationCommand(this, object, object.rotation, this.objectRotationOnDown))
          }
          break
        case 'scale':
          if (!this.objectScaleOnDown.equals(object.scale)) {
            gapp.history.execute(new SetScaleCommand(this, object, object.scale, this.objectScaleOnDown))
          }
          break
      }
    }
    gapp.controls.enabled = true
  })
}
复制代码

オブジェクトを保存

実際、これは私のローコードのアイデアと非常によく似ています。つまり、最終的には、構成されたすべてのオブジェクト情報をJSONの形式で保存します。他のプロジェクトで簡単にエコーするため。それをエコーする方法は?ライトの位置情報を編集し、 GUIを使用して色や明るさなどを調整すると、ライトオブジェクトオブジェクトをtoJSONを介してJSONに変換し、最終オブジェクトに保存してから、インターフェイスを介してJSONを取得できます。 。もう一度シーンに追加するだけです

//转化为threejs特有的json格式
 scene.toJSON() 
 (了解过json的同学可以发现,threejs为了缩小大小,将瓦片对象最大限度的拆分材质等,通过id关联并保存为json)
//解析json转为对象
Viewer.prototype.fromJSON = function (json, layeridx, isRayobj) {
  return new Promise((resolve, reject) => {
    // 解析 json 对象
    let loader = new THREE.ObjectLoader();
    let loadedMesh = loader.parse(json);
    let scene = this.mergeToMaterialsMap(loadedMesh, true)
    resolve(scene)
  })
}
复制代码

エピローグ

この記事は主にアイデアを紹介します。比較的基本的な記事ですが、もちろん、必要に応じて拡張することもできます。のようなものを作成するのは簡単ではありませんthreejsに興味のある学生は、私のコラムをフォローして、threejs関連のケースとソリューションを随時更新できます〜threejsコラム

おすすめ

転載: juejin.im/post/7085930124725452830