특정 기기(특정 모델)를 클릭하면 그걸 감지하도록 코드를 짰다.
내가 시도한 코드는 더보기와 같다.
맨 처음엔 three.interaction을 써서 간단히 구현할 수 있을 줄 알았다.
// three.interaction 방식
// new a interaction, then you can add interaction-event with your free style
const interaction = new Interaction(this.renderer, this.scene, this.camera)
this.scene.resource.cursor = 'pointer'
this.scene.resource.on('click', function (ev) {
console.log(ev, interaction)
})
안됐다!
TypeError: "x" is not a constructor - JavaScript | MDN
TypeError
developer.mozilla.org
이런 오류가 자꾸 떴는데 구글링하다가 저런 라이브러리는 나중에 호환 안 될 가능성이 높으니 비추한다하여 겸사겸사 많이 쓰는 raycaster로 갈아탔다.
다 안돼서 계속 넣고 수정하고 넣고 수정하고의 반복이었다.
/* raycaster 형식 클릭 이벤트 */
// 1번째 방식
this.renderer.domElement.addEventListener('click', onclick, true)
var selectedObject = this.scene.resource.obj
var raycaster = new THREE.Raycaster()
function onclick(event) {
alert('onclick')
var mouse = new THREE.Vector2()
raycaster.setFromCamera(mouse, this.render.camera)
var intersects = raycaster.intersectObjects(this.scene.resource.obj, true) //array
if (intersects.length > 0) {
selectedObject = intersects[0]
alert(selectedObject)
}
}
// 2번째 방식
let pointer,
raycaster = false
init()
function init() {
raycaster = new THREE.Raycaster()
pointer = new THREE.Vector2()
document.body.appendChild(this.renderer.domElement)
document.addEventListener('pointerdown', onPointerDown)
}
function onPointerDown(event) {
pointer.set((event.clientX / window.innerWidth) * 2 - 1, -(event.clientY / window.innerHeight) * 2 + 1)
raycaster.setFromCamera(pointer, this.camera)
const intersects = raycaster.intersectObjects(this.scene.resource.obj, false)
if (intersects.length > 0) {
const intersect = intersects[0]
}
}
// 3번째 방식 -> three.projector을 이제 안쓴다함
document.addEventListener('mousedown', onDocumentMouseDown, false)
var projector = new THREE.Projector()
function onDocumentMouseDown(event) {
event.preventDefault()
var vector = new THREE.Vector3(
(event.clientX / window.innerWidth) * 2 - 1,
-(event.clientY / window.innerHeight) * 2 + 1,
0.5
)
projector.unprojectVector(vector, this.camera)
var ray = new THREE.Ray(this.camera.position, vector.subSelf(this.camera.position).normalize())
var intersects = ray.intersectObjects(this.scene.resource.obj)
if (intersects.length > 0) {
intersects[0].object.materials[0].color.setHex(Math.random() * 0xffffff)
}
/*
// Parse all the faces
for ( var i in intersects ) {
intersects[ i ].face.material[ 0 ].color
.setHex( Math.random() * 0xffffff | 0x80000000 );
}
*/
// }
// 4번째 방식
const raycaster = new THREE.Raycaster() // create once
const mouse = new THREE.Vector2() // create once
mouse.x = (event.clientX / this.renderer.domElement.clientWidth) * 2 - 1
mouse.y = -(event.clientY / this.renderer.domElement.clientHeight) * 2 + 1
raycaster.setFromCamera(mouse, this.camera)
const intersects = raycaster.intersectObjects(this.scene.resource.obj)
// 5번째 방식
var projector = new THREE.Projector();
function onDocumentMouseDown(event) {
var vector = new THREE.Vector3(event.clientX / window.innerWidth) * 2 - 1, -(event.clientY / window.innerHeight) * 2 + 1, 0.5);
vector = vector.unproject(camera);
var raycaster = new THREE.Raycaster(camera.position, vector.sub(camera.position).normalize());
var intersects = raycaster.intersectObjects([sphere, cylinder, cube]);
if (intersects.length > 0) {
intersects[0].object.material.transparent = true;
intersects[0].object.material.opacity = 0.1;
}
그런데 아무리 수정해봐도 계속 TypeError: renderer is undefined 에러가 떴다.
멘토님께 sos를 치니 선언되기 전에 호출한게 문제라고 하셨다.
큰 깨달음을 얻고 순서를 선언 후 밑으로 내렸다.
그러니 저 오류는 뜨지 않아서 여러 수정을 또 거쳤다.

결국 1번 방식에 멘토님 조언대로 마우스 좌표 값 조정을 추가하고 진행했는데, 클릭 자체는 감지하고 클릭한 좌표도 들어왔으나 intersects에 값이 들어오질 않았다. 콘솔로 찍어본 intersects는 빈 배열이었다.
무엇이 문제인고 하여 콘솔로그 죄다 찍어보고 마우스 설정을 뺐다가 넣었다가 이것저것 시도해보았지만 해결이 안됐다. 그래서 처음에 이 코드를 따온 사이트를 찾기 위해 구글링을 하다가 다음 사이트를 발견했다.
Code viewer - Ancient Brain
ancientbrain.com
여기엔 마우스를 함수에 넣은 채로 if문에서 필터를 사용하길래 혹시나 하는 마음에 비슷하게 수정하고 추가해보았다. 그리고...드디어 작동했다!!!
/* raycaster 형식 클릭 이벤트 */
document.addEventListener('click', onclick, true)
let selectedObject = null
const raycaster = new THREE.Raycaster()
const mouse = new THREE.Vector2()
function onclick(event) {
// alert('onclick')
// console.log('click', event)
// console.log('mouse', mouse)
// console.log('scene.resource.obj', scene.resource.obj.children)
if (selectedObject) {
// console.log('selectedObj', selectedObject)
}
mouse.x = (event.clientX / window.innerWidth) * 2 - 1
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1
raycaster.setFromCamera(mouse, cameraElement)
const intersects = raycaster.intersectObjects(scene.resource.obj.children, true) //array
// console.log('intersects', intersects)
if (intersects.length > 0) {
const res = intersects.filter(function (res) {
return res && res.object
})[0]
if (res && res.object) {
selectedObject = res.object
alert(selectedObject.parent.name)
}
}
}
intersects에도 드디어 값이 담겼다!
팀원분이 클릭 시에 parent.name을 쓰면 mesh의 부모격 되는 모델명을 찾을 수 있다고 알려주셔서 그걸로 해당 모델을 클릭하면 alert가 뜨도록 코드를 추가했다.
따라서 최종 코드는 다음과 같다.
/* raycaster 형식 클릭 이벤트 */
document.addEventListener('click', onclick, true)
let selectedObject = null
const raycaster = new THREE.Raycaster()
const mouse = new THREE.Vector2()
function onclick(event) {
// alert('onclick')
// console.log('click', event)
// console.log('mouse', mouse)
// console.log('scene.resource.obj', scene.resource.obj.children)
if (selectedObject) {
// console.log('selectedObj', selectedObject)
}
mouse.x = (event.clientX / window.innerWidth) * 2 - 1
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1
raycaster.setFromCamera(mouse, cameraElement)
const intersects = raycaster.intersectObjects(scene.resource.obj.children, true) //array
console.log('intersects', intersects)
if (intersects.length > 0) {
const res = intersects.filter(function (res) {
return res && res.object
})[0]
if (res && res.object) {
selectedObject = res.object
alert(selectedObject.parent.name)
if (selectedObject.parent.name == 'StaticMesh4') {
alert('모델 찾았습니다')
}
}
}
}
정말 신기하게도 깨질듯 아프던 머리가 해결하자마자 싹 나았다.
만병통치약이 따로 없다^^
'공부 > Digital Twin Bootcamp Project' 카테고리의 다른 글
[Team 6] 비전 인식 카메라 작동 안함 오류 (0) | 2022.03.28 |
---|---|
[Team 6] Smart Connector - dotnet build (0) | 2022.03.28 |
[Team 6] three.js Texture 구현 오류 해결 (0) | 2022.03.23 |
[Team 6] Edukit(공장 기기 kit) 디지털 트윈 프로젝트 (0) | 2022.03.23 |
[Team 제주 넘는 차] 프로젝트 보고서 및 회고록 (0) | 2022.03.15 |