Three.js 강좌 #3 Geometry part-1
3. Geometry
three.js의 기본 구성요소
mesh 생성시 필요한것
- mesh의 형상을 정의하는 geometry
- 색상/투명도 등을 지정할 수 있는 material
- 지난 #2 강의 예제 코드에서는 geometry에 육면체의 형상을 정의하는 BoxGeometry를 사용함
three.js에서 제공하는 기본 Geometry
- 기본적으로 BufferGeometry를 상속받고 있음
- 자주색으로 표시된 geometry 살펴볼 예정
- ParametricGeometry: 수학적 함수식에 2개의 값을 입력하여 얻을수 있는 좌표로 구성되는 지오메트리
- EdgesGeometry: 지오메트리를 구성하는 인접면의 각도에 따라 지오메트리를 재구성함
PolyhedrongGeometry: 다면체를 구성하는 지오메트리
이를 상속받는 지오메트리들
- IcosahedronGeometry(20면체)
- OctahedrongGeometry(8면체)
- DodecahedronGeometry(12면체)
- TetrahedronGeometry(4면체)
Geometry의 형상을 정의하기 위한 데이터
- 지오메트리는 3차원 오브젝트의 형상을 정의한다.
- 정점(Vertex): 형상을 정의함. xyz축에 대한 좌표
- 정점 인덱스: 3차원 오브젝트의 면을 구성하는 정점에 대한 인덱스
- 수직 벡터: 정점에 대한 수직 벡터
- 정점 색상: 벡터 정점의 색상
- 텍스쳐 맵핑을 위한 UV 좌표
- 사용자 정의 데이터
-> 이러한 데이터들은 3차원으로 시각화 될 때 GPU에 한번에 전달되어 빠르게 처리된다.
WireframeGeometry, BoxGeometry
02-geometry.html
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="02-geometry.css">
<script type="module" src="02-geometry.js" defer></script>
</head>
<body>
<div id="webgl-container"></div>
</body>
</html>
02-geometry.js
회색에 노란 선이 있는 정육면체 오브젝트로 변경
_setupModel() {
// 가로, 세로 깊이 크기가 모두 1인 geometry
/*
BoxGeometry: 가로, 세로, 깊이 크기와 함께 가로,세로,깊이 각각에 대한 분할(Segments)수로 정의됨(분할수는 지정하지 않으면 기본값 1)
*/
//const geometry = new THREE.BoxGeometry(1, 1, 1);
// 가로, 세로, 깊이 방향으로 2개씩 분할됨
const geometry = new THREE.BoxGeometry(1, 1, 1, 2, 2, 2);
// 회색 색상의 재질로 mesh 타입 오브젝트 생성
const fillMaterial = new THREE.MeshPhongMaterial({ color: 0x515151 });
const cube = new THREE.Mesh(geometry, fillMaterial);
// 노란색 선 재질 생성
const lineMaterial = new THREE.LineBasicMaterial({color: 0xffff00});
// 앞에서 만든 geometry를 이용해 line타입 오브젝트 생성
/*
WireframeGeometry 클래스: 와이어프레임 형태로 지오메트리 표현
만약 WireframeGeometry 적용하지 않고 생성하면 모델의 모든 외곽선이 표시되지 않음.
*/
const line = new THREE.LineSegments(
new THREE.WireframeGeometry(geometry), lineMaterial);
// mesh 오브젝트와 line 오브젝트를 하나의 오브젝트로 다루기 위해 그룹으로 묶음
const group = new THREE.Group()
/*
cube를 삭제하면 노란색 line만 보임,
line을 삭제하면 회색 cube만 보임
*/
group.add(cube);
group.add(line);
// 그룹 객체를 scene에 추가
this._scene.add(group);
this._cube = group;
}
BoxGeometry 생성 시 Segments 수
- 분할수는 지정하지 않으면 기본값 1이지만, 다음과 같이 분할수를 2로 지정해주면 실행결과가 다음과 같다.
const geometry = new THREE.BoxGeometry(1, 1, 1, 2, 2, 2);
- 가로, 세로, 깊이에 대해 2개로 분할됨을 확인할 수 있다..
자동회전이 아닌 마우스로 회전할 수 있도록 변경
- 오브젝트 자동회전 하게 했던 코드 주석처리
- 마우스 회전에 필요한 OrbitControls 클래스 import
- App 클래스에 컨트롤들 정의하는데 사용할 메서드인 _setupControls() 정의
- _setupControls() 함수 생성
import * as THREE from '../build/three.module.js';
import { OrbitControls } from '../examples/jsm/controls/OrbitControls.js'
class App {
constructor() {
const divContainer = document.querySelector("#webgl-container");
this._divContainer = divContainer;
const renderer = new THREE.WebGL1Renderer({ antialias: true });
renderer.setPixelRatio(window.devicePixelRatio);
divContainer.appendChild(renderer.domElement);
this._renderer = renderer;
const scene = new THREE.Scene();
this._scene = scene;
this._setupCamera();
this._setupLight();
this._setupModel();
// 컨트롤들 정의하는데 사용하는 메서드
this._setupControls();
window.onresize = this.resize.bind(this);
this.resize();
requestAnimationFrame(this.render.bind(this));
}
//
_setupControls() {
// OrbitControls 객체를 생성할 때는 카메라 객체와 마우스 이벤트를 받는 DOM 요소 필요
// 이벤트를 받는 DOM 요소는 id가 webgl-container인 div 요소
new OrbitControls(this._camera, this._divContainer);
}
update(time) {
time *= 0.001;
//오브젝트 자동 회전
//this._cube.rotation.x = time;
//this._cube.rotation.y = time;
}
}
02-geometry.js 전체 코드
import * as THREE from '../build/three.module.js';
import { OrbitControls } from '../examples/jsm/controls/OrbitControls.js'
class App {
constructor() {
const divContainer = document.querySelector("#webgl-container");
this._divContainer = divContainer;
const renderer = new THREE.WebGL1Renderer({ antialias: true });
renderer.setPixelRatio(window.devicePixelRatio);
divContainer.appendChild(renderer.domElement);
this._renderer = renderer;
const scene = new THREE.Scene();
this._scene = scene;
this._setupCamera();
this._setupLight();
this._setupModel();
this._setupControls();
window.onresize = this.resize.bind(this);
this.resize();
requestAnimationFrame(this.render.bind(this));
}
_setupControls() {
new OrbitControls(this._camera, this._divContainer);
}
_setupCamera() {
const width = this._divContainer.clientWidth;
const height = this._divContainer.clientHeight;
const camera = new THREE.PerspectiveCamera(
75,
width / height,
0.1,
100
);
camera.position.z=2;
this._camera = camera;
}
_setupLight() {
const color = 0xffffff;
const intensity = 1;
const light = new THREE.DirectionalLight(color, intensity);
light.position.set(-1, 2, 4);
this._scene.add(light);
}
_setupModel() {
const geometry = new THREE.BoxGeometry(1, 1, 1);
//const geometry = new THREE.BoxGeometry(1, 1, 1, 2, 2, 2);
const fillMaterial = new THREE.MeshPhongMaterial({ color: 0x515151 });
const cube = new THREE.Mesh(geometry, fillMaterial);
const lineMaterial = new THREE.LineBasicMaterial({color: 0xffff00});
const line = new THREE.LineSegments(
new THREE.WireframeGeometry(geometry), lineMaterial);
const group = new THREE.Group()
group.add(cube);
group.add(line);
this._scene.add(group);
this._cube = group;
}
resize() {
const width = this._divContainer.clientWidth;
const height = this._divContainer.clientHeight;
this._camera.aspect = width / height;
this._camera.updateProjectionMatrix();
this._renderer.setSize(width, height);
}
render(time) {
this._renderer.render(this._scene, this._camera);
this.update(time);
requestAnimationFrame(this.render.bind(this));
}
update(time) {
time *= 0.001;
//오브젝트 자동 회전
//this._cube.rotation.x = time;
//this._cube.rotation.y = time;
}
}
window.onload = function() {
new App();
}
실행 결과
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="02-geometry.css">
<script type="module" src="02-geometry.js" defer></script>
</head>
<body>
<div id="webgl-container"></div>
</body>
</html>
_setupModel() {
// 가로, 세로 깊이 크기가 모두 1인 geometry
/*
BoxGeometry: 가로, 세로, 깊이 크기와 함께 가로,세로,깊이 각각에 대한 분할(Segments)수로 정의됨(분할수는 지정하지 않으면 기본값 1)
*/
//const geometry = new THREE.BoxGeometry(1, 1, 1);
// 가로, 세로, 깊이 방향으로 2개씩 분할됨
const geometry = new THREE.BoxGeometry(1, 1, 1, 2, 2, 2);
// 회색 색상의 재질로 mesh 타입 오브젝트 생성
const fillMaterial = new THREE.MeshPhongMaterial({ color: 0x515151 });
const cube = new THREE.Mesh(geometry, fillMaterial);
// 노란색 선 재질 생성
const lineMaterial = new THREE.LineBasicMaterial({color: 0xffff00});
// 앞에서 만든 geometry를 이용해 line타입 오브젝트 생성
/*
WireframeGeometry 클래스: 와이어프레임 형태로 지오메트리 표현
만약 WireframeGeometry 적용하지 않고 생성하면 모델의 모든 외곽선이 표시되지 않음.
*/
const line = new THREE.LineSegments(
new THREE.WireframeGeometry(geometry), lineMaterial);
// mesh 오브젝트와 line 오브젝트를 하나의 오브젝트로 다루기 위해 그룹으로 묶음
const group = new THREE.Group()
/*
cube를 삭제하면 노란색 line만 보임,
line을 삭제하면 회색 cube만 보임
*/
group.add(cube);
group.add(line);
// 그룹 객체를 scene에 추가
this._scene.add(group);
this._cube = group;
}
const geometry = new THREE.BoxGeometry(1, 1, 1, 2, 2, 2);
import * as THREE from '../build/three.module.js';
import { OrbitControls } from '../examples/jsm/controls/OrbitControls.js'
class App {
constructor() {
const divContainer = document.querySelector("#webgl-container");
this._divContainer = divContainer;
const renderer = new THREE.WebGL1Renderer({ antialias: true });
renderer.setPixelRatio(window.devicePixelRatio);
divContainer.appendChild(renderer.domElement);
this._renderer = renderer;
const scene = new THREE.Scene();
this._scene = scene;
this._setupCamera();
this._setupLight();
this._setupModel();
// 컨트롤들 정의하는데 사용하는 메서드
this._setupControls();
window.onresize = this.resize.bind(this);
this.resize();
requestAnimationFrame(this.render.bind(this));
}
//
_setupControls() {
// OrbitControls 객체를 생성할 때는 카메라 객체와 마우스 이벤트를 받는 DOM 요소 필요
// 이벤트를 받는 DOM 요소는 id가 webgl-container인 div 요소
new OrbitControls(this._camera, this._divContainer);
}
update(time) {
time *= 0.001;
//오브젝트 자동 회전
//this._cube.rotation.x = time;
//this._cube.rotation.y = time;
}
}
import * as THREE from '../build/three.module.js';
import { OrbitControls } from '../examples/jsm/controls/OrbitControls.js'
class App {
constructor() {
const divContainer = document.querySelector("#webgl-container");
this._divContainer = divContainer;
const renderer = new THREE.WebGL1Renderer({ antialias: true });
renderer.setPixelRatio(window.devicePixelRatio);
divContainer.appendChild(renderer.domElement);
this._renderer = renderer;
const scene = new THREE.Scene();
this._scene = scene;
this._setupCamera();
this._setupLight();
this._setupModel();
this._setupControls();
window.onresize = this.resize.bind(this);
this.resize();
requestAnimationFrame(this.render.bind(this));
}
_setupControls() {
new OrbitControls(this._camera, this._divContainer);
}
_setupCamera() {
const width = this._divContainer.clientWidth;
const height = this._divContainer.clientHeight;
const camera = new THREE.PerspectiveCamera(
75,
width / height,
0.1,
100
);
camera.position.z=2;
this._camera = camera;
}
_setupLight() {
const color = 0xffffff;
const intensity = 1;
const light = new THREE.DirectionalLight(color, intensity);
light.position.set(-1, 2, 4);
this._scene.add(light);
}
_setupModel() {
const geometry = new THREE.BoxGeometry(1, 1, 1);
//const geometry = new THREE.BoxGeometry(1, 1, 1, 2, 2, 2);
const fillMaterial = new THREE.MeshPhongMaterial({ color: 0x515151 });
const cube = new THREE.Mesh(geometry, fillMaterial);
const lineMaterial = new THREE.LineBasicMaterial({color: 0xffff00});
const line = new THREE.LineSegments(
new THREE.WireframeGeometry(geometry), lineMaterial);
const group = new THREE.Group()
group.add(cube);
group.add(line);
this._scene.add(group);
this._cube = group;
}
resize() {
const width = this._divContainer.clientWidth;
const height = this._divContainer.clientHeight;
this._camera.aspect = width / height;
this._camera.updateProjectionMatrix();
this._renderer.setSize(width, height);
}
render(time) {
this._renderer.render(this._scene, this._camera);
this.update(time);
requestAnimationFrame(this.render.bind(this));
}
update(time) {
time *= 0.001;
//오브젝트 자동 회전
//this._cube.rotation.x = time;
//this._cube.rotation.y = time;
}
}
window.onload = function() {
new App();
}
Author And Source
이 문제에 관하여(Three.js 강좌 #3 Geometry part-1), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@jisubin12/Three.js-강좌-3-Geometry저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)