<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      常用three.js

      x 左右

      y 上下

      z 前后

      const model = new THREE.Group();
      // 創建邊界框可視化輔助對象,顏色為黃色
      
       const box = new THREE.Box3().setFromObject(模型);
       const helper = new THREE.Box3Helper(box, 0xffff00)
       
       
      const box3 = new THREE.Box3().setFromObject(模型);
      const box3Helper = new THREE.Box3Helper(box3, 0xff0000); 
      scene.add(box3Helper);
      背景色
      const renderer = new THREE.WebGLRenderer({
              antialias: true,  //設置抗鋸齒
              alpha:false,  //透明開啟與關閉
              logarithmicDepthBuffer:true, //能解決部分模型沖突閃爍的問題
          });
      renderer.setSize(Width, Height);
      renderer.setPixelRatio(window.devicePixelRatio)  //告訴three.js瀏覽器的像素比,防止模糊
      document.getElementById("dineas").appendChild(renderer.domElement);
       
      //設置背景色
      renderer.setClearColor(0x444444) //設置背景色
      renderer.setClearColor(0x444444,0) //也可以加透明
      
       //透明度
      renderer.setClearAlpha(0)

      軌道控制器

      import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'; 
      // 引入軌道控制器
      
      this.controls = new OrbitControls(this.camera, this.renderer.domElement );  
      //創建軌道控制器(相機,渲染器)
      
      //創建動畫
      animate() {
          requestAnimationFrame(this.animate);
          this.renderer.render(this.scene, this.camera);
      },
          
          // 設置相機控件軌道控制器OrbitControls
          const controls = new OrbitControls(camera, renderer.domElement);
          // 修改相機指向的位置
          controls.target.set(0, 0, 0)
          controls.update()
      
          controls.addEventListener('change',function(e){
              console.log('camera.position',camera.position);
          })
      軌道控制器的屬性
      controls.enablePan = false
      // 禁止右鍵平移(模型true)
      
      controls.enableZoom = false
      // 禁止縮放
      
      controls.enableRotate = false
      //禁止右鍵旋轉
      
      controls.minDistance = 200
      //縮放的最小
      controls.maxDistance = 500
      //縮放的最大
      
      controls.addEventListener("change",function(){
          // 相機位置與目標觀察點的距離
          const dis = controls.getDistance()
          console.log(dis)
      })
      
      controls.minPolarAngle = 0
      //上下旋轉的范圍 
      
      controls.maxPolarAngle = Math.PI/2
      //上下旋轉的范圍
      
      controls.minAzimuthAngle = 0
      //左右旋轉的范圍 
      
      controls.maxAzimuthAngle = Math.PI/2
      //左右旋轉的范圍 

       

      添加背景圖
      var urls = ['1.png', '1.png','1.png', '1.png','1.png', '1.png',];
      scene.background = new THREE.CubeTextureLoader().setPath('/').load(urls)
      添加霧
      scene.fog = new THREE.Fog( 0xcccccc, 10, 15 );
      網格坐標輔助對象.
      this.gridHelper = new THREE.GridHelper();
      this.scene.add( this.gridHelper );
      3維坐標軸
      const axesHelper = new THREE.AxesHelper( 5 );
      this.scene.add( axesHelper );
       
      獲取網格模型的世界坐標
      const posit = new THREE.Vector3()
      mesh.getWorldPosition(posit)
      console.log(posit,"模型的世界坐標")
       

       

      移動物體或相機
      this.物體.position.set(0,3,0)
      this.物體.position.x = 1
      this.物體.position.z = 1
      this.物體.position.y = 1
       縮放物體
      this.物體.scale.set(1,2,3)
      this.物體.scale.x = 1
      this.物體.scale.z = 1
      this.物體.scale.y = 1
      旋轉物體
      this.物體.rotation.set(Math.PI/4,0,0)
      //Math.PI圓周率
      
      this.物體.rotation.set(Math.PI/4,0,0,"xzy")
      //可添加旋轉順序
      
      this.物體.rotation.x = 1
      this.物體.rotation.z = 1
      this.物體.rotation.y = 1
      
      this.物體.rotateY(0.01)

       

      gsap 通過gsap插件設置動畫
      npm i gsap  //安裝
      import gsap from 'gsap'; //引入
      
      let animation = gsap.to(this.cube.position, {        
              z: 5,  //方向
              duration: 5, //時間
              ease: "power1.inOut", //動畫運動方式
              repeat: -1, //動畫次數 -1無限次
              yoyo:true, //往返運行
              delay:2,  //延時時間
              onComplete: () => {
                console.log("動畫結束")
              },
              onStart: () => {
                console.log("動畫開始")
              }
            })
            // gsap.to(this.cube.rotation, { y: 2 * Math.PI, duration: 5 })
      
            //監聽雙擊事件 
            this.renderer.domElement.addEventListener("dblclick",()=>{
              if (animation.isActive()) { //判斷動畫是在運動中還是停止中 true運動中 false停止中
                animation.pause()  // 設置暫定
              }else{
                animation.resume() //設置開啟動畫
              }
            })
      監聽頁面變化
      // 監聽頁面變化
            window.addEventListener("resize",()=>{
              console.log("畫面變化了")
              // 更新攝像頭
              this.camera.aspect = window.innerWidth / window.innerHeight
              // 更新攝像機的投影矩陣
              this.camera.updateProjectionMatrix()
              // 更新渲染器
              this.renderer.setSize(window.innerWidth,window.innerHeight)
              // 設置渲染器的像素比
              this.renderer.setPixelRatio(window.devicePixelRatio)
            })
      紋理
      //紋理
            this.textureLoader = new THREE.TextureLoader() //創建紋理
            const doorcolor = this.textureLoader.load('./customerY.png')  //加載紋理圖
            const doorcolor1 = this.textureLoader.load('./customerY.png')  //加載紋理圖
            console.log(doorcolor,"doorcolor")
            // doorcolor.offset.x = 0.5    //設置紋理偏移量
            doorcolor.center.set(0.5,0.5)  //旋轉中心點
            doorcolor.rotation = Math.PI / 4  //旋轉紋理
            
            // 創建物體
            this.geometry = new THREE.BoxGeometry(1, 1, 1);
            this.material = new THREE.MeshBasicMaterial({ 
              color: 0x00ff00,  //物體顏色
              map:doorcolor,    //物體添加紋理
              alphaMap:doorcolor1, //添加透明紋理
              transparent:true,  //是否透明
              side:THREE.DoubleSide  //渲染兩面
            });
            this.cube = new THREE.Mesh(this.geometry, this.material);
            this.scene.add(this.cube);

       

      性能檢測

      import  Stats  from 'three/examples/jsm/libs/stats.module.js'; //性能檢測
      
      // 性能檢測
      this.Stats = new Stats()
      this.$refs.container.appendChild(this.Stats.domElement)
      animate() {
            this.Stats.update()
            requestAnimationFrame(this.animate);
      },

       

      創建隨機數

      (Math.random()-0.1)*20
      //在20以內隨機

       

      渲染器

      //創建渲染器
      const renderer = new THREE.WebGLRenderer({
          antialias:true,  //設置抗鋸齒
      });
      
      renderer.setSize(window.innerWidth, window.innerHeight);
      //渲染的寬高
      
      renderer.setPixelRatio(window.devicePixelRatio)
      //告訴three.js瀏覽器的像素比,防止模糊
      
      renderer.setClearColor(0x444444)
      // 設置渲染器的背景色
      
      document.getElementById("app").appendChild(renderer.domElement);
      //把渲染器插入到那個標簽下

       

      動畫與畫布窗口變化

      // 渲染循環
      function animate() {
          controls.update()
          renderer.render(scene, camera);
          requestAnimationFrame(animate);
      }
      animate();
      
      
      // 畫布跟隨窗口變化
      window.onresize = function () {
          renderer.setSize(window.innerWidth, window.innerHeight);
          camera.aspect = window.innerWidth / window.innerHeight;
          camera.updateProjectionMatrix();
      };

       

      gui插件

      import { GUI } from "three/examples/jsm/libs/lil-gui.module.min.js";
      //導入插件
      
      const gui = new GUI();
      // 實例化一個gui對象
      
      //改變值 
      gui.add(mesh.position, 'x', 0, 180);
      //gui.add(要改變的對象, 要改變的對象名, 改變的最小值, 改變的最大值);
      
      gui.add(obj,'x',0,180).name("測試")
      //可以改變顯示的名字
      
      gui.add(obj,'x',0,180).step(0.1)
      //改變的步數
      
      //監聽改變的值
      gui.add(obj,'x',0,180).name("測試").onChange((value)=>{
          console.log(value)
          mesh.position.x = value
      })
      改變顏色
      //改變顏色 addColor
      gui.addColor(obj,'color').name("測試1").onChange((value)=>{
          mesh.material.color.set(value)
      })
      設置選擇值
      //可選擇-100,0,100
      gui.add(obj,'scale',[-100,0,100]).name("測試").onChange((value)=>{
          mesh.position.x = value
      })
      
      //可設置名稱
      gui.add(obj,'scale',{left:-100,centter:0,right:100}).name("測試").onChange((value)=>{
          mesh.position.x = value
      })
      
      //可中文設置
      gui.add(obj,'scale',{左:-100,中:0,右:100}).name("測試").onChange((value)=>{
          mesh.position.x = value
      })
      設置單選
      gui.add(obj,'danxua').name('是否').onChange((value)=>{
          console.log(value)
      })
      設置分組
      const mat = gui.addFolder("材質")
      // 設置分組
      mat.close()
      // 設置默認關閉
      mat.add(mesh.position,'y',0,1000)
      // 在mat分組上設置

       

      光源與受光源物體

      受光照影響材質

      光源

      點光源
      // 創建點光源
      const pointLight = new THREE.PointLight(0xffffff,1,100 )
      pointLight.position.set( 80,80, 80 );//偏移光源位置,觀察渲染效果變化
      pointLight.intensity = 38100;//光照強度
      pointLight.distance = 300;// 光的衰減
      pointLight.decay = 2;//光照強度
      scene.add( pointLight );
       環境光
      // 環境光
      const light = new THREE.AmbientLight( 0x404040 ,4); // 柔和的白光
      scene.add( light );
      平行光
      // 平行光
      const directionalLight = new THREE.DirectionalLight( 0xffffff, 1 );
      // 創建平行光
      directionalLight.position.set(100,100,100)
      // 創建平行光位置
      directionalLight.target = mesh
      // 設置平行光執行的物體
      scene.add( directionalLight );
      聚光源
        // // // 聚光源
          const spotLight = new THREE.SpotLight(0xffffff,40)  
          // //創建聚光源,參數一:顏色,參數二:光照強度
          spotLight.castShadow = true;
          spotLight.angle = Math.PI/15
          // //設置聚光源發散角度
          spotLight.distance = 300
          spotLight.decay = 0
          scene.add( spotLight );
          
          spotLight.position.set(0,180,0)
         //設置聚光源的位置
      
          spotLight.target.position.set(0,0,0)
          // 設置聚光源照的位置
          scene.add(spotLight.target)
          // 設置聚光源照添加到場景中

      幾何體

      // 生成一個緩沖幾何體(可以自定義形狀)
      const geometry = new THREE.BufferGeometry()
      
      // 創建類型化數組(三個頂點等于一個坐標)
      const vertices = new Float32Array([
          0,0,0,
          50,0,0,
          0,100,0,
          0,0,10,
          0,0,100,
          50,0,10
      ])
      const attribute = new THREE.BufferAttribute(vertices,3)
      // 屬性緩沖對象表示
      console.log(attribute)
      
      geometry.attributes.position = attribute
      // 設置幾何體的頂點位置屬性
      
      const material = new THREE.PointsMaterial({color:0xffff00,size:10})
      // 創建點材質點材質
      
      const points = new THREE.Points(geometry,material)
      // 創建點模型
      const line1 = new THREE.Line(geometry,material)
      // 創建線模型(會順著鏈接起來,但是最后點和開始點不會鏈接)
      
      const line2 = new THREE.LineLoop(geometry,material)
      // 創建線模型(會順著鏈接起來,會閉合線條)
      
      const line3 = new THREE.LineSegments(geometry,material)
      // 創建線模型(非連續的線條)
      
      scene.add(line3)
      點模型
      const points = new THREE.Points(geometry,material)
       
      線模型(會順著鏈接起來,但是最后點和開始點不會鏈接)
      const line1 = new THREE.Line(geometry,material)
       
      線模型(會順著鏈接起來,會閉合線條)
      const line2 = new THREE.LineLoop(geometry,material)
       
      線模型(非連續的線條)
      const line3 = new THREE.LineSegments(geometry,material)

       

      通過網格模型渲染
      // 生成一個緩沖幾何體(可以自定義形狀)
      const geometry = new THREE.BufferGeometry()
      
      // 創建類型化數組(三個頂點等于一個坐標)
      const vertices = new Float32Array([
          0,0,0,
          50,0,0,
          0,100,0,
          0,0,10,
          0,0,100,
          50,0,10
      ])
      const attribute = new THREE.BufferAttribute(vertices,3)
      // 屬性緩沖對象表示
      console.log(attribute)
      
      geometry.attributes.position = attribute
      // 設置幾何體的頂點位置屬性
      
      const material = new THREE.MeshBasicMaterial({
          color:0xffff00,
          // side:THREE.FrontSide //默認只有正面可見
          side:THREE.DoubleSide //兩面可見
          // side:THREE.FrontSide //背面可見
      })
      // 創建網格材質
      
      const mesh = new THREE.Mesh(geometry, material);
      // 通過網格模型渲染
      通過類型化創建
      const vertices = new Float32Array([
          0,0,0,
          50,0,0,
          0,100,0,
          50,100,0,
      ])
      const attribute = new THREE.BufferAttribute(vertices,3)
      const indexes = new Uint16Array([0,1,2,1,3,2])
      // 0表述第一組,1表述第二組,2表示第三組,3表述第四組
      //0 = 0,0,0 || 1=50,0,0 || 2=0,100,0 || 3=50,100,0
      geometry.index = new THREE.BufferAttribute(indexes,1)
      const mesh = new THREE.Mesh(geometry, material);

       

      旋轉、縮放、平移幾何體

      居中
      geometry.translate(50, 0, 0);//偏移
      // 居中:已經偏移的幾何體居中,執行.center(),你可以看到幾何體重新與坐標原點重合
      geometry.center();
      角度
      cube.rotation.y = Math.PI/4
      //旋轉角度
      設置顏色
      material.color.set(0x005001) //十六進制設置顏色
      material.color.set('#005001') //css設置顏色
      克隆
      const cube2 = cube.clone()  //克隆
      復制
      cube2.rotation.copy(cube.rotation)  //復制

       

      層級

      創建組對象
      const geometry = new THREE.BoxGeometry( 100, 100, 100 ); 
      const material = new THREE.MeshBasicMaterial( {color:0xff000f}); 
      const cube1 = new THREE.Mesh( geometry, material ); 
      const cube2 = new THREE.Mesh( geometry, material ); 
      cube2.translateX(150)
      
      // 創建組對象
      const group = new THREE.Group()
      group.add(cube1)  //把物體加入組里
      group.add(cube2)
      
      group.add(cube1,cube2)  //可以同時添加多個
      
      group.translateX(150)  //可以操作組對象,操作組對象,子對象也會同時操作
      
      scene.add(group) //把組放到場景中
      遞歸查找所有的子對象
      // 遞歸循環所有模型節點
      group3.traverse((obj)=>{
          // 判斷是否是網格模型
          if (obj.type == "Mesh") {
              // 是網格模型則修改顏色
              obj.material.color.set(0xffffff)
          }
          console.log(obj,"obj")
      })
       查找指定模型名稱
      const obj = group3.getObjectByName("4號樓")
      const obj = gltf.scene.getObjectByName("外殼01")
      示例
      const group = new THREE.Group()
      const group2 = new THREE.Group()
      const group3 = new THREE.Group()
      group.name = '高層'
      for (let i = 0; i < 5; i++) {
          const geometry = new THREE.BoxGeometry( 20, 60, 10 ); 
          const material = new THREE.MeshBasicMaterial( {color:0xff000f}); 
          const cube = new THREE.Mesh( geometry, material ); 
          cube.name = (i+1)+"號樓"
          cube.translateX(i*40)
          cube.translateY(70)
          group.add(cube)
      }
      group2.name = '洋房'
      for (let i = 0; i < 5; i++) {
          const geometry = new THREE.BoxGeometry( 20, 30, 10 ); 
          const material = new THREE.MeshBasicMaterial( {color:0xff000f}); 
          const cube = new THREE.Mesh( geometry, material ); 
          cube.name = (i+6)+"號樓"
          cube.translateX(i*40)
          cube.translateZ(40)
          group2.add(cube)
      }
      group3.name = '小區'
      group3.add(group,group2)
        //可以同時添加多個
      scene.add(group3) //把組放到場景中
      console.log('group', JSON.parse(JSON.stringify(group)))
      
      // 遞歸循環所有模型節點
      group3.traverse((obj)=>{
          // 判斷是否是網格模型
          if (obj.type == "Mesh") {
              // 是網格模型則修改顏色
              obj.material.color.set(0xffffff)
          }
          console.log(obj,"obj")
      })
      
      // 查找指定模型名稱
      const obj = group3.getObjectByName("4號樓")
      obj.material.color.set(0xfff00f)
      添加局部坐標
      const Helper = new THREE.AxesHelper(50);
      cube.add(Helper);
      改變物體原點
      const geometry = new THREE.BoxGeometry( 20, 20, 20 ); 
      const material = new THREE.MeshLambertMaterial( {color:0xff000f}); 
      const cube = new THREE.Mesh( geometry, material ); 
      geometry.translate(20/2,0,0)
      // 改變物體原點
      刪除子類
      const geometry = new THREE.BoxGeometry( 20, 20, 20 ); 
      const material = new THREE.MeshLambertMaterial( {color:0xff000f}); 
      const cube = new THREE.Mesh( geometry, material ); 
      const cube1 = new THREE.Mesh( geometry, material ); 
      cube1.position.x = 50
      const group = new THREE.Group()
      group.add(cube,cube1)
      
      group.remove(cube)
      // 刪除
      顯示隱藏
      cube1.visible = false
      // 隱藏,可以隱藏材質

       

      紋理

      創建紋理貼圖
      const geometry = new THREE.SphereGeometry(50);
      
      // 創建一個紋理加載器
      const loadtex = new THREE.TextureLoader()
      // 加載圖片
      const texture = loadtex.load('/earth.jpg')
      
      const material = new THREE.MeshLambertMaterial({
          // color: 0xff000f,
          // map:texture,//設置材質的顏色貼圖
      }); 
      material.map = texture; //可以直接訪問材質屬性設置
      
      const cube = new THREE.Mesh(geometry, material);
      自定義uv坐標
      // 創建一個紋理加載器
      const loadtex = new THREE.TextureLoader()
       // 加載圖片
      const texture = loadtex.load('/earth.jpg')
      
      // 生成一個緩沖幾何體(可以自定義形狀)
      const geometry = new THREE.BufferGeometry()
      
      // 創建類型化數組(三個頂點等于一個坐標)
      const vertices = new Float32Array([
          0,0,0,
          160,0,0,
          160,80,0,
          0,80,0,
      ])
      const attribute = new THREE.BufferAttribute(vertices,3)
      // 屬性緩沖對象表示
      console.log(attribute)
      
      geometry.attributes.position = attribute
      // 設置幾何體的頂點位置屬性
      
      // Uint16Array類型數組創建頂點索引數據
      const indexes = new Uint16Array([0,1,2,0,2,3])
      geometry.index = new THREE.BufferAttribute(indexes,1) 
      
      
      const material = new THREE.MeshBasicMaterial({
          map:texture,
      })
      // 創建網格材質
      const mesh = new THREE.Mesh(geometry, material);
      
      // 創建uv坐標
      const uvs = new Float32Array([
          0,0,
          1,0,
          1,1,
          0,1
      ])
      // 通過幾何體的頂點位置設置uv坐標
      geometry.attributes.uv = new THREE.BufferAttribute(uvs,2) 
      scene.add(mesh)

      頂點UV坐標可以在0~1.0之間任意取值,紋理貼圖左下角對應的UV坐標是(0,0)右上角對應的坐標(1,1)

      紋理對象陣列(地轉)
      const scene = new THREE.Scene();
      const gui = new GUI()
      const geometry = new THREE.PlaneGeometry(800,800);
      // const geometry = new THREE.CircleGeometry( 5, 32 );
      // const geometry = new THREE.SphereGeometry(50);
      
      geometry.rotateX(Math.PI/2)
      
      // 創建一個紋理加載器
      const loadtex = new THREE.TextureLoader()
      // // 加載圖片
      const texture = loadtex.load('/瓷磚.jpg')
      
      //陣列
      texture.wrapS = THREE.RepeatWrapping    //上下開啟陣列
      texture.wrapT = THREE.RepeatWrapping    //左右開啟陣列
      texture.repeat.set(30,30)  //上下左右的陣列次數
      
      const material = new THREE.MeshLambertMaterial({
          side:THREE.DoubleSide,
          map:texture,//設置材質的顏色貼圖
      }); 
      const cube = new THREE.Mesh(geometry, material);
      
      scene.add(cube)
       開啟透明
      // 創建一個紋理加載器
      const loadtex = new THREE.TextureLoader()
      // 加載圖片
      const texture = loadtex.load('/轉彎.png')
      const material = new THREE.MeshLambertMaterial({
          map:texture,//設置材質的顏色貼圖
          transparent:true, //開啟透明
      }); 
      const cube = new THREE.Mesh(geometry, material);
      scene.add(cube)
      uv偏移量
      const geometry = new THREE.PlaneGeometry(50,50);
      // 創建一個紋理加載器
      const loadtex = new THREE.TextureLoader()
      // 加載圖片
      const texture = loadtex.load('/轉彎.png')
      const material = new THREE.MeshLambertMaterial({
          map:texture,//設置材質的顏色貼圖
          transparent:true, //開啟透明
      }); 
      
      // uv偏移量
      texture.offset.x += 0.5
      texture.offset.y += 0.5
      
      texture.wrapS = THREE.RepeatWrapping //被裁掉的自動追加到后面
      
      
      const cube = new THREE.Mesh(geometry, material);
      scene.add(cube)

      加載模型

      import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'; //引入GLTF加載器
      const scene = new THREE.Scene();
      //創建一個GLTF加載器
      const loader = new GLTFLoader()
      //聲明一個組對象,用來添加加載成功的三維場景
      const model = new THREE.Group()
      
      //gltf加載成功后返回一個對象
      loader.load('/工廠.gltf',(gltf)=>{
          console.log(gltf,"gltf")
      
          //三維場景添加到model組對象中
          model.add(gltf.scene)
      })
      scene.add(model)
      
      // 設置相機控件軌道控制器OrbitControls
      const controls = new OrbitControls(camera, renderer.domElement);
      // 修改相機指向的位置
      controls.target.set(-14,-24,10)
      controls.update()

       單獨給貼紙

      //gltf加載成功后返回一個對象
      loader.load('/工廠.gltf',(gltf)=>{
          console.log(gltf.scene,"gltf")
          gltf.scene.traverse((moxin)=>{
              if (moxin.isMesh) {
                  if (moxin.material.map) {
                      console.log("判斷是否存在貼圖",moxin.material.map.encoding)
                  }
              }
          })
          //三維場景添加到model組對象中
          model.add(gltf.scene)
      })
      scene.add(model)
      
      
      // // 創建一個紋理加載器
      const loadtex = new THREE.TextureLoader()
      // // // 加載圖片
      const texture = loadtex.load('/瓷磚.jpg')
      texture.encoding = THREE.sRGBEncoding
      
      // 反轉貼圖
      texture.flipY = false
      renderer.outputColorSpace = THREE.SRGBColorSpace;
       

       

      PBR材質

      MeshStandardMaterial 材質
      material.metalness = 1     (0-1)     
      //金屬度 0表述金屬度低,1表述金屬度高,(值越高越像金屬)
      
      material.roughness = 0.5   (0-1)   
      //粗糙度 0表述表面光滑,1表示粗糙 (值越高越粗糙)
      
      
      // CubeTextureLoader環境貼圖,setPath加載的文件夾,load加載的文件,
      // 加載環境貼圖
      // 加載周圍環境6個方向貼圖
      // 上下左右前后6張貼圖構成一個立方體空間
      // 'px.jpg', 'nx.jpg':x軸正方向、負方向貼圖  p:正positive  n:負negative
      // 'py.jpg', 'ny.jpg':y軸貼圖
      // 'pz.jpg', 'nz.jpg':z軸貼圖
      const texturecube = new THREE.CubeTextureLoader().setPath('/環境貼圖/環境貼圖0/')
      .load(['px.jpg','nx.jpg','py.jpg','ny.jpg','pz.jpg','nz.jpg',])
      
      moxin.material.envMap = texturecube 
      //環境貼圖(給某個物體添加環境貼圖)
      moxin.material.envMapIntensity =  1  
      //環境貼圖的影響程度
       給全部物體添加貼圖
      // 環境貼圖紋理對象textureCube作為.environment屬性值,影響所有模型
      scene.environment = textureCube;
      環境貼圖色彩空間編碼.encoding
      //如果renderer.outputEncoding=THREE.sRGBEncoding;環境貼圖需要保持一致
      textureCube.encoding = THREE.sRGBEncoding;   

      MeshPhysicalMaterial清漆層

      const material = new THREE.MeshPhysicalMaterial( {
      	clearcoat: 1.0,//物體表面清漆層或者說透明涂層的厚度
      	clearcoatRoughness: 0.1,//透明涂層表面的粗糙度
          color: obj.material.color, //默認顏色
          metalness: 0.9,//金屬度
          roughness: 0.5,//粗糙度
          envMap: textureCube, //環境貼圖
          envMapIntensity: 2.5, //環境貼圖對Mesh表面影響程度
      } );
      
      
      //示例
      //創建一個GLTF加載器
      const loader = new GLTFLoader()
      //聲明一個組對象,用來添加加載成功的三維場景
      const model = new THREE.Group()
      //gltf加載成功后返回一個對象
      loader.load('/轎車.glb',(gltf)=>{
          console.log(gltf,"gltf")
          const obj = gltf.scene.getObjectByName("外殼01")
          obj.material = new THREE.MeshPhysicalMaterial({
              color: obj.material.color, //默認顏色
              metalness: 0.9,//車外殼金屬度
              roughness: 0.5,//車外殼粗糙度
              envMap: texturecube, //環境貼圖
              envMapIntensity: 2.5, //環境貼圖對Mesh表面影響程度
              clearcoat:1, //物體表面清漆層或者說透明涂層的厚度
              clearcoatRoughness:0, //透明涂層表面的粗糙度
          })  
          model.add(gltf.scene)
      },function ( xhr ) {
          //加載進度
      		console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );
      
      	},)
      scene.add(model)
       玻璃
      const obj1 = gltf.scene.getObjectByName("玻璃01")
          obj1.material = new THREE.MeshPhysicalMaterial({
              color: obj1.material.color, //默認顏色
              metalness: 0,//車外殼金屬度
              roughness: 0,//車外殼粗糙度
              envMapIntensity: 0, //環境貼圖對Mesh表面影響程度
              
              transmission: 1.0, //玻璃材質透光率
              ior:1.5, ////折射率  非金屬材料的折射率從1.0到2.333。默認值為1.5。
          })

       

      相機

      正投影相機
      let Width = window.innerWidth 
          let Height = window.innerHeight
          const k = Width/Height
          const s = 500
          const camera = new THREE.OrthographicCamera(-s*k,s*k,s,-s,1,8000)
          camera.position.set(0, 2000, 0);
          camera.lookAt(2000, 100, 2000); //相機觀察目標指向Three.js坐標系原點
      
       // 設置相機控件軌道控制器OrbitControls
          const controls = new OrbitControls(camera, renderer.domElement);
          // 修改相機指向的位置
          controls.target.set(200, 0, 200)
          controls.update()
      相機屬性
        // //相機
          const camera = new THREE.PerspectiveCamera(30, Width / Height, 0.1, 3000);
          camera.position.set(800, 800, 800); //相機的位置
          camera.lookAt(0, 0, 0); //相機看的方向
      
      // 設置相機控件軌道控制器OrbitControls
      const controls = new OrbitControls(camera, renderer.domElement);
      controls.target.set(0, 0, 0) //這里要和 camera.lookAt(0, 0, 0)保持同步
      controls.update()

       

      包圍盒 

       const geometry = new THREE.BoxGeometry(100, 100, 100);
          const material = new THREE.MeshLambertMaterial({
              color: 0x00ffff,
          });
          const mesh = new THREE.Mesh(geometry, material);
          scene.add(mesh);
          
          // 包圍盒
          const box3 = new THREE.Box3()
          box3.expandByObject(mesh)  //計算的模型
          const size = new THREE.Vector3()
          box3.getSize(size)  //獲取模型計算的尺寸
          console.log(size,"size")
      
          const center = new THREE.Vector3()
          box3.getCenter(center) //獲取模型計算的位置
          console.log(center,"center")

       

      后期處理

      import { EffectComposer } from "three/examples/jsm/postprocessing/EffectComposer.js";  //效果合成器
      import { RenderPass } from "three/examples/jsm/postprocessing/RenderPass";   //引入渲染通道
      
      const composer = new EffectComposer(renderer) 
      //創建效果合成器,renderer渲染器作為參數
      
      const renderpass =new RenderPass(scene,camera)  
      //創建渲染通道,參數為 scene場景 camera相機
      
      composer.addPass(renderpass)
      //效果合成器添加渲染通道
      
        // 渲染循環
          function animate() {
              renderer.render(scene, camera);
              composer.render();
              requestAnimationFrame(animate);
          }
      描邊效果
      import { OutlinePass } from "three/examples/jsm/postprocessing/OutlinePass"; //引入描邊效果
      
         // OutlinePass 創建描邊效果 參數一:2維向量 就是畫布的尺寸, scene場景 camera相機
          const v2 = new THREE.Vector2(Width,Height)
          const outlinePass = new OutlinePass(v2,scene,camera)
      
          // 那個模型需要需要描邊,可以有多個
          outlinePass.selectedObjects = [mesh1]
      
          outlinePass.visibleEdgeColor.set(0xffff00)
          // 設置描邊的顏色
          
          outlinePass.edgeThickness = 5
          // 設置描邊的厚度
      
          outlinePass.edgeStrength = 6
          // 設置描邊的亮度
      
          outlinePass.pulsePeriod = 2
          // 設置描邊閃爍,0就是不閃爍
      
          // 把描邊添加到效果合成器里
          composer.addPass(outlinePass)

       

      發光效果
      import { UnrealBloomPass } from "three/examples/jsm/postprocessing/UnrealBloomPass";
      // unrealBloomPass 創建發光效果
          const v2 = new THREE.Vector2(Width,Height)
          const unrealBloomPass = new UnrealBloomPass(v2)
      
          unrealBloomPass.strength = 1
          composer.addPass(unrealBloomPass)
      解決顏色偏差
      import { GammaCorrectionShader } from "three/examples/jsm/shaders/GammaCorrectionShader.js";
      import { ShaderPass } from "three/examples/jsm/postprocessing/ShaderPass";
      
      const gammaPass = new ShaderPass(GammaCorrectionShader)
      composer.addPass(gammaPass)

       

      選擇模型

      選擇單個模型
      renderer.domElement.addEventListener('click', function (event) {
              // .offsetY、.offsetX以canvas畫布左上角為坐標原點,單位px
              const px = event.offsetX;
              const py = event.offsetY;
              //屏幕坐標px、py轉WebGL標準設備坐標x、y
              //width、height表示canvas畫布寬高度
              const x = (px / window.innerWidth) * 2 - 1;
              const y = -(py / window.innerHeight) * 2 + 1;
              //創建一個射線投射器`Raycaster`
              const raycaster = new THREE.Raycaster();
              //.setFromCamera()計算射線投射器`Raycaster`的射線屬性.ray
              // 形象點說就是在點擊位置創建一條射線,射線穿過的模型代表選中
              raycaster.setFromCamera(new THREE.Vector2(x, y), camera);
              //.intersectObjects([mesh1, mesh2, mesh3])對參數中的網格模型對象進行射線交叉計算
              // 未選中對象返回空數組[],選中一個對象,數組1個元素,選中兩個對象,數組兩個元素
              const intersects = raycaster.intersectObjects([mesh1, mesh2, mesh]);
              console.log("射線器返回的對象", intersects);
              // intersects.length大于0說明,說明選中了模型
              if (intersects.length > 0) {
                  // 選中模型的第一個模型,設置為紅色
                  intersects[0].object.material.color.set(0xff0000);
              }
          })

      選擇組模型

      const model = new THREE.Group()
          const loader = new GLTFLoader()
          loader.load('/工廠.gltf', (gltf) => {
              console.log(gltf, "gltf")
      
              //三維場景添加到model組對象中
              model.add(gltf.scene)
          })
          scene.add(model)
      
      
      renderer.domElement.addEventListener('click', function (event) {
              const px = event.offsetX;
              const py = event.offsetY;
              const x = (px / window.innerWidth) * 2 - 1;
              const y = -(py / window.innerHeight) * 2 + 1;
              const raycaster = new THREE.Raycaster();
              raycaster.setFromCamera(new THREE.Vector2(x, y), camera);
              // 固定設置
      
      
              //首先找到要設置的組模型
              const cunshu = model.getObjectByName("存儲罐")
      
              // 循環設置自定屬性,全部指向父類
              for (let i = 0; i < cunshu.children.length; i++) {
                  const element = cunshu.children[i];
                  element.traverse(function(obj){
                      if (obj.isMesh) {
                          obj.ancestors = element
                      }
                  })
              }
      
              const intersects = raycaster.intersectObjects(cunshu.children);
              composer.addPass(outlinePass)
              if (intersects.length > 0) {
                  //設置發光效果
                  outlinePass.selectedObjects = [intersects[0].object.aaaaa]
              }
          })

       

      頁面物體標注html內容

      添加基礎標簽
      const group = new THREE.Group()
          // 創建一個組
          let div = document.getElementById('label')
          // 選擇在頁面中創建的div
          let label = new CSS2DObject(div)
          // 創建css,導入標簽
          label.position.set(200,200,200)
          // 設置標簽的位置
          group.add(label)
          // 添加到組中
          scene.add(group); 
          // 將組添加到場景中
      
          const css2Renderer = new CSS2DRenderer()
          // 標簽渲染
          css2Renderer.setSize(window.innerWidth, window.innerHeight);
          document.getElementById("sanwei").appendChild(css2Renderer.domElement);
          css2Renderer.domElement.style.position = 'absolute';
          css2Renderer.domElement.style.top = '0px';
      css2Renderer.domElement.style.pointerEvents = 'none'; 
          // 添加穿透
      
          // 渲染循環
          function animate() {
              css2Renderer.render(scene, camera);
              renderer.render(scene, camera);
              requestAnimationFrame(animate);
          }
       可以直接標注到模型
        let div = document.getElementById('label')
          // 選擇在頁面中創建的div
          let label = new CSS2DObject(div)
          // 設置標簽的位置
          mesh.add(label)
          // 可以直接標注到某個模型下
      標注到模型的某個點上
      let div = document.getElementById('label')
          // 選擇在頁面中創建的div
          let label = new CSS2DObject(div)
          // 設置標簽的位置
          mesh.add(label)
          // 可以直接標注到某個模型下
      
          const pos = mesh.geometry.attributes.position;
          // 獲取幾何體頂點1的xyz坐標,設置標簽局部坐標.position屬性
          label.position.set(pos.getX(0),pos.getY(0),pos.getZ(0));

       

      模型動畫

      基礎動畫
      import * as THREE from 'three';
      
      
      const geometry = new THREE.BoxGeometry(50, 50, 50);
      const material = new THREE.MeshLambertMaterial({ color: 0x00ffff });
      const model = new THREE.Mesh(geometry, material);
      
      model.name = 'box'
      // 定義模型名字
      
      const times = [0,3,6]  //定義時間線0秒,3秒,5秒
      const values = [0,0,0 ,100,0,0 ,0,0,100] //定義每秒的位置
      
      // 設置關鍵幀數據THREE.KeyframeTrack(參數一:要加入的關鍵幀,參數二:定義的時間線,參數三:定義的參數位置或改變的狀態)
      const posKF = new THREE.KeyframeTrack('box.position',times,values)
      const colorKF = new THREE.KeyframeTrack('box.material.color',[2, 5],[1, 0, 0, 0, 0, 1])
      
      // 1.3 AnimationClip表示一個關鍵幀動畫,可以基于關鍵幀數據產生動畫效果
      // 創建一個clip關鍵幀動畫對象,命名"test",動畫持續時間6s
      // AnimationClip包含的所有關鍵幀數據都放到參數3數組中即可
      const clip = new THREE.AnimationClip("test",6,[posKF,colorKF ]);
      
      // 包含關鍵的模型
      const mixer = new THREE.AnimationMixer(model)
      const clipAction = mixer.clipAction(clip); 
      
      clipAction.play()
      
      
      // 通過Clock對象輔助獲取每次loop()執行的時間間隔。
      const clock = new THREE.Clock();
      
      // 執行mixer.update()更新播放器AnimationMixer時間數據
      function loop() {
          requestAnimationFrame(loop);
          const frameT = clock.getDelta();
          // 更新播放器相關的時間
          mixer.update(frameT);
      }
      loop();
      
      
      
      export default model;
      循環方式
      clipAction.loop = THREE.LoopOnce //只執行一次
      clipAction.loop = THREE.LoopRepeat  //重復次數為repetitions的值, 且每次循環結束時候將回到起始動作開始下一次循環。
      clipAction.loop = THREE.LoopPingPong  //重復次數為repetitions的值, 且像乒乓球一樣在起始點與結束點之間來回循環。
      物體狀態停留在動畫結束的時候
      clipAction.clampWhenFinished = true;
       // 物體狀態停留在動畫結束的時候
      停止、播放、暫停
      clipAction.play();
      //播放動畫
      
      clipAction.stop();
      //動畫停止結束,回到開始狀態
      
      clipAction.paused = false  //播放
      clipAction.paused = true  //暫停
      //暫停狀態
      倍速
      clipAction.timeScale = 1;//默認
      clipAction.timeScale = 2;//2倍速
      播放模型動畫
       const loader = new GLTFLoader()
          //聲明一個組對象,用來添加加載成功的三維場景
          const model = new THREE.Group()
          //gltf加載成功后返回一個對象
          loader.load('/工廠1.glb', (gltf) => {
              console.log(gltf, "gltf")
              const clock = new THREE.Clock();
              // // 包含關鍵的模型
              const mixer = new THREE.AnimationMixer(gltf.scene)
              const clipAction = mixer.clipAction(gltf.animations[0]);
              clipAction.loop = THREE.LoopOnce //只執行一次
              clipAction.play()
      
              // 監聽動畫是否播放完成
              mixer.addEventListener('finished',function(){
                  clipAction.reset() //重制播放
              })
      
              function loop() {
                  requestAnimationFrame(loop);
                  const frameT = clock.getDelta();
                  // 更新播放器相關的時間
                  mixer.update(frameT);
              }
              loop();
              //三維場景添加到model組對象中
              model.add(gltf.scene)
          })
          scene.add(model)

      動畫庫tween.js

      npm安裝

      npm i @tweenjs/tween.js@^18
      import TWEEN from '@tweenjs/tween.js';

      tweenjs基本語法

      let pos = { x: 10, z: 10, y: 10 }  //基礎信息
          const tween = new TWEEN.Tween(pos)  //創建動畫
          tween.to({ x: 100, z: 100, y: 100 },2000) // 參數一:{這里面是要改變后的值},參數二:執行的時間
          tween.start(); //開始執行
      
         
          function loop() {
              TWEEN.update();//tween更新
              requestAnimationFrame(loop);
          }
          loop();
      
          //第二種寫法
          const tween = new TWEEN.Tween(pos).to({ x: 100, z: 100, y: 100 },2000).start(); 

       tweenjs改變threejs模型對象位置

      //創建一段mesh平移的動畫
      const tween = new TWEEN.Tween(mesh.position);
      //經過2000毫秒,pos對象的x和y屬性分別從零變化為100、50
      tween.to({x: 100,y: 50}, 2000);
      //緩動方式
      tween.easing(TWEEN.Easing.Sinusoidal.InOut) 
      //tween動畫開始執行
      tween.start();
      
      //tween動畫停止
      tween.stop()
      
      //tween動畫暫停
      tween.pause()
      
      //tween動畫繼續執行
      tween.pause()

      換個語法形式書寫也可以,更簡潔

      const tween = new TWEEN.Tween(mesh.position).to({x: 100,y: 50}, 2000).start();
      const tween = new TWEEN.Tween(mesh.position)
      .to({x: 100,y: 50}, 2000)
      .easing(TWEEN.Easing.Sinusoidal.InOut) 
      .start();

      Tweenjs回調函數

      twwenjs庫提供了onStartonUpdateonComplete等用于控制動畫執行的回調函數。

      • onStart:動畫開始執行觸發
      • onUpdate:動畫執行過程中,一直被調用執行
      • onComplete:動畫正常執行完觸發

      .onUpdate(function(obj){})結構中,obj對應的是new TWEEN.Tween(pos)的參數對象pos。

      const tween = new TWEEN.Tween(pos).to({x: 0}, 4000)
      // 開始執行:動畫片段tween開始執行的時候觸發onStart
      .onStart(function(obj){
      	...
      })
      
                  const theEntire = scene.getObjectByName("區域")
                  let enlarModel = graychoose(event, theEntire.children, camera, '-檔案柜')
                  console.log(enlarModel, "enlarModel")
                  console.log(JSON.stringify(enlarModel), "enlarModel")
      
                  const options = {
                      trs: false,
                      onlyVisible: true,
                      binary: true,
                      maxTextureSize: 4096
                  };
                  var gltfExporter = new GLTFExporter();
                  gltfExporter.parse(
                      enlarModel,
                      function (result) {
                          if (result instanceof ArrayBuffer) {
                              saveArrayBuffer(result, 'scene.glb');
                          } else {
                              const output = JSON.stringify(result, null, 2);
                              console.log(output);
                              saveString(output, 'scene.gltf');
                          }
                      },
                      function (error) {
                          console.log('An error happened during parsing', error);
                      },
                      options
                  );
      
                  const link = document.createElement('a');
                  link.style.display = 'none';
                  document.body.appendChild(link); // Firefox workaround, see #6594
                  function save(blob, filename) {
                      link.href = URL.createObjectURL(blob);
                      link.download = filename;
                      link.click();
                  }
                  function saveArrayBuffer(buffer, filename) {
                      save(new Blob([buffer], { type: 'application/octet-stream' }), filename);
                  }
                  function saveString(text, filename) {
                      save(new Blob([text], { type: 'text/plain' }), filename);
                  }

       

      posted @ 2023-11-28 16:14  雨落風  閱讀(112)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 亚洲人成网线在线播放VA| 国产精品三级中文字幕| 一本色道久久88亚洲综合| 旬阳县| 国产亚洲欧美日韩俺去了| 欧美黑人巨大videos精品| 国产AV午夜精品一区二区三区| 国产99久一区二区三区a片| 亚洲综合av一区二区三区| 长腿校花无力呻吟娇喘| 377p欧洲日本亚洲大胆| 国产精品久久久久久久专区| 成人av天堂网在线观看| 一区二区三区四区在线不卡高清 | 亚洲欧洲日产国无高清码图片| 欧美精品高清在线观看| 美日韩精品一区二区三区| 99riav国产精品视频| 亚洲av片在线免费观看| 内射干少妇亚洲69xxx| 狠狠综合久久av一区二| 久久人人97超碰爱香蕉| 漂亮人妻中文字幕丝袜| 免费无码va一区二区三区| 性饥渴少妇AV无码毛片| 精品人妻二区中文字幕| 国产成人精品亚洲午夜| 亚洲日韩性欧美中文字幕| 欧洲熟妇色xxxx欧美老妇多毛网站| 97碰碰碰免费公开在线视频| 鲁一鲁一鲁一鲁一澡| 国产精品久久久久久久专区| 国产精品亚洲国际在线看| 亚洲一区二区精品偷拍| 精品人妻av区乱码| 国产毛片基地| 在线观看国产区亚洲一区| 久久毛片少妇高潮| 成全高清在线播放电视剧| 精品人妻系列无码人妻漫画 | 韩国免费a级毛片久久|