inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

Three.js로 시작하는 3D 인터랙티브 웹

형태가 바뀌는 이미지 패널 만들기 4

파티클 레이캐스터터

351

Boom

작성한 질문수 20

0

레이캐스터를  파티클에 하면 제대로 선택이 안되는거  같은데  혹시  이유를  아시나요 ㅠ,ㅠ

인터랙티브-웹 blender Three.js

답변 1

1

1분코딩

아래 코드를 참고해보세요~
ex06.js에 레이캐스터를 추가한 코드입니다.

import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import { ImagePanel } from './ImagePanel';
import gsap from 'gsap';

// ----- 주제: 형태가 바뀌는 이미지 패널

export default function example() {
	// Renderer
	const canvas = document.querySelector('#three-canvas');
	const renderer = new THREE.WebGLRenderer({
		canvas,
		antialias: true
	});
	renderer.setSize(window.innerWidth, window.innerHeight);
	renderer.setPixelRatio(window.devicePixelRatio > 1 ? 2 : 1);

	// Scene
	const scene = new THREE.Scene();

	// Camera
	const camera = new THREE.PerspectiveCamera(
		75,
		window.innerWidth / window.innerHeight,
		0.1,
		1000
	);
	camera.position.y = 1.5;
	camera.position.z = 4;
	scene.add(camera);

	// Light
	const ambientLight = new THREE.AmbientLight('white', 0.5);
	scene.add(ambientLight);

	const directionalLight = new THREE.DirectionalLight('white', 1);
	directionalLight.position.x = 1;
	directionalLight.position.z = 2;
	scene.add(directionalLight);

	// Controls
	const controls = new OrbitControls(camera, renderer.domElement);
	controls.enableDamping = true;
	
	// Mesh
	const planeGeometry = new THREE.PlaneGeometry(0.3, 0.3);

	const textureLoader = new THREE.TextureLoader();

	// Points
	const sphereGeometry = new THREE.SphereGeometry(1, 8, 8);
	const spherePositionArray = sphereGeometry.attributes.position.array;
	const randomPositionArray = [];
	for (let i = 0; i < spherePositionArray.length; i++) {
		randomPositionArray.push((Math.random() - 0.5) * 10);
	}

	// 여러개의 Plane Mesh 생성
	const meshes = [];
	const imagePanels = [];
	let imagePanel;
	for (let i = 0; i < spherePositionArray.length; i += 3) {
		imagePanel = new ImagePanel({
			textureLoader,
			scene,
			geometry: planeGeometry,
			imageSrc: `/images/0${Math.ceil(Math.random() * 5)}.jpg`,
			x: spherePositionArray[i],
			y: spherePositionArray[i + 1],
			z: spherePositionArray[i + 2]
		});

		imagePanels.push(imagePanel);
		meshes.push(imagePanel.mesh);
	}

	// 그리기
	const clock = new THREE.Clock();

	function draw() {
		const delta = clock.getDelta();

		controls.update();

		renderer.render(scene, camera);
		renderer.setAnimationLoop(draw);
	}

	function checkIntersects() {
		raycaster.setFromCamera(mouse, camera);

		const intersects = raycaster.intersectObjects(meshes);
		for (const item of intersects) {
			console.log(item.object.name);
			item.object.material.color.set('red');
			break;
		}
		// if (intersects[0]) {
		// 	intersects[0].object.material.color.set('blue');
		// }
	}

	function setSize() {
		camera.aspect = window.innerWidth / window.innerHeight;
		camera.updateProjectionMatrix();
		renderer.setSize(window.innerWidth, window.innerHeight);
		renderer.render(scene, camera);
	}

	const raycaster = new THREE.Raycaster();
	const mouse = new THREE.Vector2();

	function setShape(e) {
		const type = e.target.dataset.type;
		let array;

		switch (type) {
			case 'random':
				array = randomPositionArray;
				break;
			case 'sphere':
				array = spherePositionArray;
				break;
		}

		for (let i = 0; i < imagePanels.length; i++) {
			// 위치 이동
			gsap.to(
				imagePanels[i].mesh.position,
				{
					duration: 2,
					x: array[i * 3],
					y: array[i * 3 + 1],
					z: array[i * 3 + 2]
				}
			);

			// 회전
			if (type === 'random') {
				gsap.to(
					imagePanels[i].mesh.rotation,
					{
						duration: 2,
						x: 0,
						y: 0,
						z: 0
					}
				);
			} else if (type === 'sphere') {
				gsap.to(
					imagePanels[i].mesh.rotation,
					{
						duration: 2,
						x: imagePanels[i].sphereRotationX,
						y: imagePanels[i].sphereRotationY,
						z: imagePanels[i].sphereRotationZ
					}
				);
			}
		}
	}

	// 버튼
	const btnWrapper = document.createElement('div');
	btnWrapper.classList.add('btns');

	const randomBtn = document.createElement('button');
	randomBtn.dataset.type = 'random';
	randomBtn.style.cssText = 'position: absolute; left: 20px; top: 20px';
	randomBtn.innerHTML = 'Random';
	btnWrapper.append(randomBtn);

	const sphereBtn = document.createElement('button');
	sphereBtn.dataset.type = 'sphere';
	sphereBtn.style.cssText = 'position: absolute; left: 20px; top: 50px';
	sphereBtn.innerHTML = 'Sphere';
	btnWrapper.append(sphereBtn);

	document.body.append(btnWrapper);

	// 이벤트
	btnWrapper.addEventListener('click', setShape);
	window.addEventListener('resize', setSize);

	canvas.addEventListener('click', e => {
		mouse.x = e.clientX / canvas.clientWidth * 2 - 1;
		mouse.y = -(e.clientY / canvas.clientHeight * 2 - 1);
		checkIntersects();
	});

	draw();
}

CDN으로 수업을 들을경우

0

16

1

리액트/next.js와 같이 사용하는 강의 계획은 없으신가요?

0

98

1

소스코드 파일이 강의랑 같나요?

0

138

2

materials 배열에 있는 top, bottom ... 들에 대해서

0

131

0

gltf 포맷 사용

0

262

1

점프 애니메이션 stop

0

143

2

사양에 따른 다른 결과

0

119

1

중복 질문 삭제

0

167

1

혹시 이 빛의 범위를 조절할 수 있는 방법이 있나요?

0

129

1

gltf.scene.children 이 없는데도 모델이 화면에 떠요

0

118

2

GLF파일 export한 후에 three.js에서 렌더링 된 모델에는 텍스처 적용이 안되어있습니다..!

0

180

1

일반 유리, 강화 유리 강의에서 Glass 객체의 position X를 -1, 1로 설정한 이유를 모르겠어요

0

85

0

그림자가 다르게 표현됩니다

0

155

1

setAnimationLoop 위치가...

0

111

1

얼굴 그릴 때 붓이 깔끔하게 칠해지지 않고 얼룩덜룩해요

0

150

1

블렌더 texture paint 시 미러모드

0

172

0

DragControls의 인자값을 바꾸지 않았는데 에러가 안떠요!

0

110

1

blender 에서 색칠하기 편 Texter paint slot추가없음

0

1025

2

fin 버전도 그냥 실행이 안돼요

0

304

2

자바스크립트 실행이 안되는 것 같아요

0

408

1

모니터 해상도에 따라 mesh의 크기가 변할 수 있나요?

0

247

1

live server와 localhost:8080

0

361

1

material에 canvas 를 texture 로 넣는방법이 궁금해요

0

279

1

모바일 조이스틱은 어떻게 만들 수 있을까요?

0

219

1