threejs限制物体在一个球形上面移动

11 篇文章 0 订阅
3 篇文章 0 订阅

目录

效果:

​​ 

 代码:


约束:

  1. 只能在球形表面上面移动,不能移开,
  2. 棒棒糖的角度要与球面的法向线一样垂直

效果:

 

 代码:

addExample("限制在球形上面移动", function () {
   let { toRaw, ref, unref, provide, inject, getCurrentInstance, reactive, shallowReactive, computed, watchEffect, watch, onBeforeMount, onMounted, onBeforeUpdated, onUpdated, onBeforeUnmount, onUnmounted, toRef, toRefs } = Vue;
   return {
      template: `<div><div ref="main"></div></div>`,
      setup(props, ctx) {
         let [ref, app] = useApplication({
            webglRendererOptions: {

            },
            autoUpdate: true,
            clearColor: 0xffffff,
            helper: {
               axes: true
            },
            orbit: {},
            camera: {
               // 离中心,为3米
               position: new THREE.Vector3(0, 0, 300)
            }
            // cannon:{}
         })
         {
            // light
            let light = new THREE.DirectionalLight(0xffffff, 1)
            light.position.set(1000, 2000, 1000)

            app.scene.add(light)
         }
         let rootGroup = new THREE.Group()
         rootGroup.position.y=5
         //rootGroup.updateWorldMatrix(true, false)
         app.scene.add(rootGroup)

         let bbgQiuGroup = new THREE.Group()
         bbgQiuGroup.position.y=55
         rootGroup.add(bbgQiuGroup)
         {
            // 地面
            let geometry = new THREE.BoxGeometry(100, 10, 100)
            let material = new THREE.MeshPhongMaterial({
               color: 0xf00fdf
            })
            let mesh = new THREE.Mesh(geometry, material)
            mesh.name = 'ground'
            rootGroup.add(mesh)
         }
         {
            // 球形
            let geometry = new THREE.SphereGeometry(50, 16)
           // geometry.computeBoundingSphere()
           // geometry.translate(0, 50, 0)
            //  geometry.applyMatrix4(new THREE.Matrix4().makeTranslation(0,50,0))
            let material = new THREE.MeshStandardMaterial({
               color: 0x43fd43,
               // side:THREE.BackSide
            })
            let mesh = new THREE.Mesh(geometry, material)
            mesh.name = 'sphere'

            bbgQiuGroup.add(mesh)

         }
         {
            // 
            // 棒棒糖
            let bangbangtang = new THREE.Group()
            bangbangtang.position.y = 65
            bangbangtang.name = 'bangbangtang'
            let bangbangtang2 = new THREE.Group()
            bangbangtang2.name='bangbangtang2'
            bangbangtang2.rotation.x=-Math.PI/2
            // 糖
            let tangGeometry = new THREE.SphereGeometry(8, 30, 30)
           // tangGeometry.applyMatrix4(new THREE.Matrix4().makeTranslation(0, 30, 0))
            let tangMaterial = new THREE.MeshPhongMaterial({
               color: 0xff00ff,
               shininess: 100
            })
            let tang = new THREE.Mesh(tangGeometry, tangMaterial)
            tang.position.y=15
            // 塑料签
            let slqGeometry = new THREE.CylinderGeometry(2, 2, 30)
          //  slqGeometry.applyMatrix4(new THREE.Matrix4().makeTranslation(0, 15, 0))
            let slqMaterial = new THREE.MeshPhongMaterial({
               color: 0xffffff,
               specular: 0xffffff,
               shininess: 50
            })
            let slq = new THREE.Mesh(slqGeometry, slqMaterial)
            bangbangtang2.add(tang)
            bangbangtang2.add(slq)
            bangbangtang.add(bangbangtang2)
            bbgQiuGroup.add(bangbangtang)
         }

         let raycaster = new THREE.Raycaster()
         let bangbangtang = rootGroup.getObjectByName('bangbangtang')
         let bangbangtang2 = rootGroup.getObjectByName('bangbangtang2')
         let sphere = rootGroup.getObjectByName("sphere")
         let intersection = [], selectedObj = null
         let movePlane = new THREE.Plane()
         let movePosition = new THREE.Vector3()


         let eventObj = null

         let transformControl = new TransformControls(app.camera, app.renderer.domElement)
         app.scene.add(transformControl)

         let intersectionObjects=[bangbangtang]
         app.on('pointerdown', (e) => {
            intersection.length = 0
   
            raycaster.setFromCamera(e.mouse, app.camera)
            raycaster.intersectObjects(intersectionObjects, true, intersection)
            if (intersection.length) {

               let selectedObject=null
               intersection[0].object.traverseAncestors((obj)=>{
                  if(!selectedObject&&intersectionObjects.indexOf(obj)!==-1){
                     selectedObject=obj
                  }
               })
               let targetPosition = new THREE.Vector3()
               targetPosition.setFromMatrixPosition(selectedObject.matrixWorld)
               app.camera.getWorldDirection(movePlane.normal)
               // 首页设置plane平面方向与相机一致,从相机原点发出射线,判断射线是否与plane相交
               movePlane.setFromNormalAndCoplanarPoint(movePlane.normal, targetPosition)

               let offsetPosition=new THREE.Vector3()
               
               if (raycaster.ray.intersectPlane(movePlane, movePosition)) {
                  app.orbit.control.enabled = false

                  offsetPosition.copy(movePosition).sub(targetPosition)
                  // 减少
                  eventObj = {
                     intersection: intersection[0],
                     selectedObject: selectedObject,
                     button: e.originalEvent.button,
                     movePosition: movePosition.clone(),
                     offsetPosition:offsetPosition,
                     matrixWorld:selectedObject.parent.matrixWorld.clone().invert()
                  }
               }
            }
         })
         app.on('pointermove', (e) => {
            if (!eventObj) {
               return
            }
            raycaster.setFromCamera(e.mouse, app.camera)
            // // 相对位移
            // if(raycaster.ray.intersectPlane(movePlane,movePosition)){
            //       let offsetPosition=new THREE.Vector3()
            //       offsetPosition.subVectors(movePosition,eventObj.movePosition)
            //       let selectedObject=eventObj.selectedObject
            //       selectedObject.position.add(offsetPosition)
            //       eventObj.movePosition.copy(movePosition)
            // }
            // 绝对位移
            if (raycaster.ray.intersectPlane(movePlane, movePosition)) {
               /**@type {THREE.Vector3}*/
               let offsetPosition =movePosition.clone()
               offsetPosition.sub(eventObj.offsetPosition).applyMatrix4(eventObj.matrixWorld)
               let selectedObject = eventObj.selectedObject

               let p1=new THREE.Vector3()
               p1.copy(offsetPosition).normalize().multiplyScalar(64)
               selectedObject.position.copy(p1)
               
               updateAngle()
              
            }


         })
         let cameraWorldDirection=new THREE.Vector3()
         function updateAngle(){
            app.camera.getWorldDirection(cameraWorldDirection)
            let p1=new THREE.Vector3()
            p1.setFromMatrixPosition(bangbangtang.matrixWorld)
            let p2=new THREE.Vector3()
            p2.setFromMatrixPosition(sphere.matrixWorld)

            bangbangtang.lookAt(p2)
         }
      
        
         updateAngle()
         // app.on('onBeforeUpdate',()=>{
         //    updateAngle()
         // })
   
         app.on('pointerup', () => {
            eventObj = null
            app.orbit.control.enabled = true
         })
         return {
            main: ref
         }
      }
   }
})

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值