Skip to content

Instantly share code, notes, and snippets.

@kyechan99
Last active December 1, 2021 09:05
Show Gist options
  • Save kyechan99/b4edc1c574ac0efe002048eac564db39 to your computer and use it in GitHub Desktop.
Save kyechan99/b4edc1c574ac0efe002048eac564db39 to your computer and use it in GitHub Desktop.
three.js draw line smooth
// 모듈 설치 방식이 아니여도 무관합니다.
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