Last active
December 1, 2021 09:05
-
-
Save kyechan99/b4edc1c574ac0efe002048eac564db39 to your computer and use it in GitHub Desktop.
three.js draw line smooth
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 모듈 설치 방식이 아니여도 무관합니다. | |
import * as THREE from 'three'; | |
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls"; | |
var scene = new THREE.Scene(); | |
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000); | |
camera.position.set(0, 0, 10); | |
var renderer = new THREE.WebGLRenderer({ antialias:true }); | |
renderer.setSize(window.innerWidth, window.innerHeight); | |
document.body.appendChild(renderer.domElement); | |
var controls = new OrbitControls(camera, renderer.domElement); | |
var raycaster = new THREE.Raycaster(); | |
// 마우스 위치 저장용 | |
var mouse = new THREE.Vector2(); | |
var point = new THREE.Vector3(); | |
var plane = new THREE.Plane(); | |
var planeNormal = new THREE.Vector3(); | |
// 그리기 | |
let isDrawing = false; | |
let myLines = []; | |
let drawCount = 0; | |
const MAX_POS_LENGTH = 100000; | |
document.addEventListener("mousemove", event => { | |
getMousePosition(event); | |
if (isDrawing) | |
addPosition(); | |
}); | |
let keysPressed = {}; // 키 다중 입력 처리용 | |
document.addEventListener("keydown", event => { | |
let key = event.key || event.keyCode; | |
keysPressed[key] = true; | |
if ((key === ' ' || key === 32) && !isDrawing) { | |
isDrawing = true; | |
drawCount = 0; | |
var geometry = new THREE.BufferGeometry(); | |
var positions = new Float32Array( MAX_POS_LENGTH * 3 ); // (x,y,z 총 3개가 담기기 떄문에 * 3) | |
geometry.setAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) ); | |
geometry.setDrawRange( 0, drawCount ); | |
var material = new THREE.LineBasicMaterial( { color: 'white', linewidth: 4 } ); | |
myLines.push( new THREE.Line( geometry, material ) ); | |
scene.add(myLines[myLines.length - 1]); | |
} | |
if (keysPressed['Control'] && event.key == 'z' && !event.repeat) { | |
if (myLines.length) | |
scene.remove(myLines.pop()); | |
} | |
}); | |
document.addEventListener("keyup", event => { | |
let key = event.key || event.keyCode; | |
delete keysPressed[key]; | |
if ((key === ' ' || key === 32)) { | |
isDrawing = false; | |
} | |
}); | |
function getMousePosition(event) { | |
// 화면에서 마우스 위치 받아오기 | |
mouse.x = (event.clientX / window.innerWidth) * 2 - 1; | |
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1; | |
// plane 이용해서 마우스 위치를 3d 에서 얻어오기 | |
planeNormal.copy(camera.position).normalize(); | |
plane.setFromNormalAndCoplanarPoint(planeNormal, scene.position); | |
// raycaster | |
raycaster.setFromCamera(mouse, camera); | |
raycaster.ray.intersectPlane(plane, point); | |
} | |
function addPosition() { | |
// 현재 그리고 있는 line의 position 속성값 | |
const positions = myLines[myLines.length - 1].geometry.getAttribute('position'); | |
// 마우스 좌표 추가 | |
positions.array[ drawCount ++ ] = point.x; | |
positions.array[ drawCount ++ ] = point.y; | |
positions.array[ drawCount ++ ] = point.z; | |
// 최대 배열 크기 안넘어가게 방지 | |
drawCount %= MAX_POS_LENGTH; | |
// 0 ~ N(마우스가 이동한 좌표들 개수)개 까지 화면에 그림 | |
myLines[myLines.length - 1].geometry.setDrawRange( 0, drawCount / 3 ); | |
myLines[myLines.length - 1].geometry.getAttribute('position').needsUpdate = true; | |
} | |
function render() { | |
requestAnimationFrame(render); | |
renderer.render(scene, camera); | |
} | |
render(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment