目录
约束:
- 只能在球形表面上面移动,不能移开,
- 棒棒糖的角度要与球面的法向线一样垂直
效果:
代码:
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
}
}
}
})