Linux dpw.dpwebtech.com 3.10.0-1160.88.1.el7.x86_64 #1 SMP Tue Mar 7 15:41:52 UTC 2023 x86_64
Apache
: 192.232.243.69 | : 18.221.161.43
54 Domain
7.3.33
dpclient
www.github.com/MadExploits
Terminal
AUTO ROOT
Adminer
Backdoor Destroyer
Linux Exploit
Lock Shell
Lock File
Create User
CREATE RDP
PHP Mailer
BACKCONNECT
UNLOCK SHELL
HASH IDENTIFIER
CPANEL RESET
CREATE WP USER
README
+ Create Folder
+ Create File
/
home /
dpclient /
public_html /
HRD-Test /
manual /
ko /
[ HOME SHELL ]
Name
Size
Permission
Action
resources
[ DIR ]
drwxr-xr-x
align-html-elements-to-3d.html
34.71
KB
-rw-r--r--
backgrounds.html
14.09
KB
-rw-r--r--
billboards.html
16.08
KB
-rw-r--r--
cameras.html
30.68
KB
-rw-r--r--
canvas-textures.html
18.89
KB
-rw-r--r--
cleanup.html
18.02
KB
-rw-r--r--
custom-buffergeometry.html
23.81
KB
-rw-r--r--
debugging-glsl.html
7.45
KB
-rw-r--r--
debugging-javascript.html
31.93
KB
-rw-r--r--
fog.html
14.89
KB
-rw-r--r--
fundamentals.html
31.61
KB
-rw-r--r--
game.html
91.06
KB
-rw-r--r--
indexed-textures.html
31.35
KB
-rw-r--r--
lang.css
589
B
-rw-r--r--
lights.html
30.72
KB
-rw-r--r--
load-gltf.html
35.02
KB
-rw-r--r--
load-obj.html
37.24
KB
-rw-r--r--
material-table.html
1.86
KB
-rw-r--r--
materials.html
21.47
KB
-rw-r--r--
multiple-scenes.html
29.43
KB
-rw-r--r--
offscreencanvas.html
49.49
KB
-rw-r--r--
optimize-lots-of-objects-anima...
23.92
KB
-rw-r--r--
optimize-lots-of-objects.html
27.17
KB
-rw-r--r--
picking.html
22.34
KB
-rw-r--r--
post-processing-3dlut.html
27.84
KB
-rw-r--r--
post-processing.html
17.92
KB
-rw-r--r--
prerequisites.html
23.54
KB
-rw-r--r--
primitives.html
25.21
KB
-rw-r--r--
rendering-on-demand.html
12.77
KB
-rw-r--r--
rendertargets.html
8.71
KB
-rw-r--r--
responsive.html
16.99
KB
-rw-r--r--
scenegraph.html
31.44
KB
-rw-r--r--
setup.html
5.14
KB
-rw-r--r--
shadertoy.html
25.15
KB
-rw-r--r--
shadows.html
29.24
KB
-rw-r--r--
textures.html
35.63
KB
-rw-r--r--
tips.html
17.83
KB
-rw-r--r--
transparency.html
19.85
KB
-rw-r--r--
voxel-geometry.html
45.92
KB
-rw-r--r--
webxr-basics.html
21.66
KB
-rw-r--r--
webxr-look-to-select.html
22.26
KB
-rw-r--r--
webxr-point-to-select.html
17.58
KB
-rw-r--r--
Delete
Unzip
Zip
${this.title}
Close
Code Editor : custom-buffergeometry.html
<!DOCTYPE html><html lang="ko"><head> <meta charset="utf-8"> <title>사용자 지정 BufferGeometry</title> <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"> <meta name="twitter:card" content="summary_large_image"> <meta name="twitter:site" content="@threejs"> <meta name="twitter:title" content="Three.js – 사용자 지정 BufferGeometry"> <meta property="og:image" content="https://threejs.org/files/share.png"> <link rel="shortcut icon" href="../../files/favicon_white.ico" media="(prefers-color-scheme: dark)"> <link rel="shortcut icon" href="../../files/favicon.ico" media="(prefers-color-scheme: light)"> <link rel="stylesheet" href="../resources/lesson.css"> <link rel="stylesheet" href="../resources/lang.css"> <!-- Import maps polyfill --> <!-- Remove this when import maps will be widely supported --> <script async src="https://unpkg.com/es-module-shims@1.8.0/dist/es-module-shims.js"></script> <script type="importmap"> { "imports": { "three": "../../build/three.module.js" } } </script> <link rel="stylesheet" href="/manual/ko/lang.css"> </head> <body> <div class="container"> <div class="lesson-title"> <h1>사용자 지정 BufferGeometry</h1> </div> <div class="lesson"> <div class="lesson-main"> <p><a href="/docs/#api/ko/core/BufferGeometry"><code class="notranslate" translate="no">BufferGeometry</code></a>는 Three.js 내의 모든 <code class="notranslate" translate="no">geometry</code>를 나타냅니다(r125에서부터 <code class="notranslate" translate="no">Geometry</code>가 제거되었습니다). 좀 더 자세히 말하면 특정 <a href="/docs/#api/ko/core/BufferAttribute"><code class="notranslate" translate="no">BufferAttribute</code></a>라고 부르는 <strong>속성</strong>의 집합이죠.</p> <p>각 <a href="/docs/#api/ko/core/BufferAttribute"><code class="notranslate" translate="no">BufferAttribute</code></a>는 위치(positions), 법선(normals), 색(colors), uv 데이터의 배열이고, 이들을 모으면 각 꼭지점에 대한 <em>평행 배열</em> 형식의 데이터가 됩니다.</p> <div class="threejs_center"><img src="../resources/threejs-attributes.svg" style="width: 700px"></div> <p>그림을 보면 총 4개의 속성(attribute), <code class="notranslate" translate="no">position</code>, <code class="notranslate" translate="no">normal</code>, <code class="notranslate" translate="no">color</code>, <code class="notranslate" translate="no">uv</code>가 있습니다. 이들은 평행 배열로 각 속성의 N 번째 데이터 묶음이 한 꼭지점의 데이터를 나타냅니다. 표시한 index = 4 위치의 꼭지점 데이터를 보세요. 이 묶음이 하나의 꼭지점을 정의합니다.</p> <p>이해를 돕기 위해 정육면체의 한 모서리를 강조해보겠습니다.</p> <div class="threejs_center"><img src="../resources/cube-faces-vertex.svg" style="width: 500px"></div> <p>이 경우 맞닿은 면의 색이 다르기에, 이 모서리는 각 면에 다른 법선을 제공해야 합니다. 마찬가지로 UV도 달라야 하죠. 하나의 <em>꼭지점</em>은 위 4개 속성의 묶음이고, 때문에 속성이 달라진다면 그건 다른 꼭지점이 되는 것이죠.</p> <p>이전과 마찬가지로 <a href="/docs/#api/ko/core/BufferGeometry"><code class="notranslate" translate="no">BufferGeometry</code></a>로 정육면체를 만들어보겠습니다. 굳이 정육면체를 쓰는 이유는 모서리의 꼭지점을 공유하는 듯해도 사실 그렇지 않기 때문이죠. 필요한 꼭지점을 전부 생성한 후, 꼭지점 데이터를 평행 배열로 변환해 <a href="/docs/#api/ko/core/BufferAttribute"><code class="notranslate" translate="no">BufferAttribute</code></a>를 만들고, 이를 <a href="/docs/#api/ko/core/BufferGeometry"><code class="notranslate" translate="no">BufferGeometry</code></a>에 추가해야 합니다.</p> <p>먼저 정육면체를 만드는 데 필요한 데이터를 정렬합니다. 아까 말했듯 꼭지점의 속성 중 하나라도 다르다면 별도의 꼭지점으로 분리해야 합니다. 정육면체의 경우는 총 꼭지점 36개가 필요하죠. 면 6개, 면 하나당 삼각형 2개, 삼각형 하나 당 꼭지점 3개, 총 36개입니다.</p> <pre class="prettyprint showlinemods notranslate lang-js" translate="no">const vertices = [ // 앞쪽 { pos: [-1, -1, 1], norm: [ 0, 0, 1], uv: [0, 0], }, { pos: [ 1, -1, 1], norm: [ 0, 0, 1], uv: [1, 0], }, { pos: [-1, 1, 1], norm: [ 0, 0, 1], uv: [0, 1], }, { pos: [-1, 1, 1], norm: [ 0, 0, 1], uv: [0, 1], }, { pos: [ 1, -1, 1], norm: [ 0, 0, 1], uv: [1, 0], }, { pos: [ 1, 1, 1], norm: [ 0, 0, 1], uv: [1, 1], }, // 오른쪽 { pos: [ 1, -1, 1], norm: [ 1, 0, 0], uv: [0, 0], }, { pos: [ 1, -1, -1], norm: [ 1, 0, 0], uv: [1, 0], }, { pos: [ 1, 1, 1], norm: [ 1, 0, 0], uv: [0, 1], }, { pos: [ 1, 1, 1], norm: [ 1, 0, 0], uv: [0, 1], }, { pos: [ 1, -1, -1], norm: [ 1, 0, 0], uv: [1, 0], }, { pos: [ 1, 1, -1], norm: [ 1, 0, 0], uv: [1, 1], }, // 뒤쪽 { pos: [ 1, -1, -1], norm: [ 0, 0, -1], uv: [0, 0], }, { pos: [-1, -1, -1], norm: [ 0, 0, -1], uv: [1, 0], }, { pos: [ 1, 1, -1], norm: [ 0, 0, -1], uv: [0, 1], }, { pos: [ 1, 1, -1], norm: [ 0, 0, -1], uv: [0, 1], }, { pos: [-1, -1, -1], norm: [ 0, 0, -1], uv: [1, 0], }, { pos: [-1, 1, -1], norm: [ 0, 0, -1], uv: [1, 1], }, // 왼쪽 { pos: [-1, -1, -1], norm: [-1, 0, 0], uv: [0, 0], }, { pos: [-1, -1, 1], norm: [-1, 0, 0], uv: [1, 0], }, { pos: [-1, 1, -1], norm: [-1, 0, 0], uv: [0, 1], }, { pos: [-1, 1, -1], norm: [-1, 0, 0], uv: [0, 1], }, { pos: [-1, -1, 1], norm: [-1, 0, 0], uv: [1, 0], }, { pos: [-1, 1, 1], norm: [-1, 0, 0], uv: [1, 1], }, // 상단 { pos: [ 1, 1, -1], norm: [ 0, 1, 0], uv: [0, 0], }, { pos: [-1, 1, -1], norm: [ 0, 1, 0], uv: [1, 0], }, { pos: [ 1, 1, 1], norm: [ 0, 1, 0], uv: [0, 1], }, { pos: [ 1, 1, 1], norm: [ 0, 1, 0], uv: [0, 1], }, { pos: [-1, 1, -1], norm: [ 0, 1, 0], uv: [1, 0], }, { pos: [-1, 1, 1], norm: [ 0, 1, 0], uv: [1, 1], }, // 하단 { pos: [ 1, -1, 1], norm: [ 0, -1, 0], uv: [0, 0], }, { pos: [-1, -1, 1], norm: [ 0, -1, 0], uv: [1, 0], }, { pos: [ 1, -1, -1], norm: [ 0, -1, 0], uv: [0, 1], }, { pos: [ 1, -1, -1], norm: [ 0, -1, 0], uv: [0, 1], }, { pos: [-1, -1, 1], norm: [ 0, -1, 0], uv: [1, 0], }, { pos: [-1, -1, -1], norm: [ 0, -1, 0], uv: [1, 1], }, ]; </pre> <p>다음으로 이 배열을 3개의 평행 배열로 변환합니다.</p> <pre class="prettyprint showlinemods notranslate lang-js" translate="no">const positions = []; const normals = []; const uvs = []; for (const vertex of vertices) { positions.push(...vertex.pos); normals.push(...vertex.norm); uvs.push(...vertex.uv); } </pre> <p>이제 <a href="/docs/#api/ko/core/BufferGeometry"><code class="notranslate" translate="no">BufferGeometry</code></a>를 만듭니다. 그리고 각 배열로 <a href="/docs/#api/ko/core/BufferAttribute"><code class="notranslate" translate="no">BufferAttribute</code></a> 인스턴스를 생성한 뒤 <a href="/docs/#api/ko/core/BufferGeometry"><code class="notranslate" translate="no">BufferGeometry</code></a>에 추가합니다.</p> <pre class="prettyprint showlinemods notranslate lang-js" translate="no"> const geometry = new THREE.BufferGeometry(); const positionNumComponents = 3; const normalNumComponents = 3; const uvNumComponents = 2; geometry.setAttribute( 'position', new THREE.BufferAttribute(new Float32Array(positions), positionNumComponents)); geometry.setAttribute( 'normal', new THREE.BufferAttribute(new Float32Array(normals), normalNumComponents)); geometry.setAttribute( 'uv', new THREE.BufferAttribute(new Float32Array(uvs), uvNumComponents)); </pre> <p>이때 정확히 Three.js가 원하는 속성 이름을 써야 합니다(사용자 지정 쉐이더를 만들 때와는 달리). 이 경우에는 <code class="notranslate" translate="no">position</code>, <code class="notranslate" translate="no">normal</code>, <code class="notranslate" translate="no">uv</code>이죠. 꼭지점 색을 지정하려면 <code class="notranslate" translate="no">color</code> 속성을 지정해야 합니다.</p> <p>아까 <code class="notranslate" translate="no">positions</code>, <code class="notranslate" translate="no">normals</code>, <code class="notranslate" translate="no">uvs</code>, 3개의 자바스크립트 순수 배열을 생성했습니다. 그리고 위에서 해당 배열을 <a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/TypedArray">형식화 배열</a>, <code class="notranslate" translate="no">Float32Array</code>로 변환했죠. <a href="/docs/#api/ko/core/BufferAttribute"><code class="notranslate" translate="no">BufferAttribute</code></a>는 순수 배열이 아니라 형식화 배열을 인자로 받습니다. 또한 하나의 꼭지점에 몇 개의 요소를 사용할 지 지정해줘야 하죠. 위치(position)과 법선(normal)의 경우 x, y, z 총 3개이고, UV는 u, v 총 2개입니다.</p> <p></p><div translate="no" class="threejs_example_container notranslate"> <div><iframe class="threejs_example notranslate" translate="no" style=" " src="/manual/examples/resources/editor.html?url=/manual/examples/custom-buffergeometry-cube.html"></iframe></div> <a class="threejs_center" href="/manual/examples/custom-buffergeometry-cube.html" target="_blank">새 탭에서 보기</a> </div> <p></p> <p>데이터가 너무 많네요. 크게 구조를 바꾸긴 어렵지만, 꼭지점을 인덱스로 참조하게끔 바꾸면 조금 나을 듯합니다. 정육면체 데이터를 다시 봅시다. 각 면은 2개의 삼각형, 삼각형 하나에는 꼭지점이 3개 있으므로 면 하나에는 총 6개의 꼭지점이 있습니다. 하지만 이 중 꼭지점 2개는 완전히 같죠(같은 위치, 같은 법선, 같은 uv). 중복된 꼭지점을 제거하고 인덱스로 데이터를 불러오도록 바꿀 수 있겠네요. 먼저 중복된 꼭지점을 제거하겠습니다.</p> <pre class="prettyprint showlinemods notranslate lang-js" translate="no">const vertices = [ // 앞쪽 { pos: [-1, -1, 1], norm: [ 0, 0, 1], uv: [0, 0], }, // 0 { pos: [ 1, -1, 1], norm: [ 0, 0, 1], uv: [1, 0], }, // 1 { pos: [-1, 1, 1], norm: [ 0, 0, 1], uv: [0, 1], }, // 2 - - { pos: [-1, 1, 1], norm: [ 0, 0, 1], uv: [0, 1], }, - { pos: [ 1, -1, 1], norm: [ 0, 0, 1], uv: [1, 0], }, { pos: [ 1, 1, 1], norm: [ 0, 0, 1], uv: [1, 1], }, // 3 // 오른쪽 { pos: [ 1, -1, 1], norm: [ 1, 0, 0], uv: [0, 0], }, // 4 { pos: [ 1, -1, -1], norm: [ 1, 0, 0], uv: [1, 0], }, // 5 - - { pos: [ 1, 1, 1], norm: [ 1, 0, 0], uv: [0, 1], }, - { pos: [ 1, -1, -1], norm: [ 1, 0, 0], uv: [1, 0], }, { pos: [ 1, 1, 1], norm: [ 1, 0, 0], uv: [0, 1], }, // 6 { pos: [ 1, 1, -1], norm: [ 1, 0, 0], uv: [1, 1], }, // 7 // 뒤쪽 { pos: [ 1, -1, -1], norm: [ 0, 0, -1], uv: [0, 0], }, // 8 { pos: [-1, -1, -1], norm: [ 0, 0, -1], uv: [1, 0], }, // 9 - - { pos: [ 1, 1, -1], norm: [ 0, 0, -1], uv: [0, 1], }, - { pos: [-1, -1, -1], norm: [ 0, 0, -1], uv: [1, 0], }, { pos: [ 1, 1, -1], norm: [ 0, 0, -1], uv: [0, 1], }, // 10 { pos: [-1, 1, -1], norm: [ 0, 0, -1], uv: [1, 1], }, // 11 // 왼쪽 { pos: [-1, -1, -1], norm: [-1, 0, 0], uv: [0, 0], }, // 12 { pos: [-1, -1, 1], norm: [-1, 0, 0], uv: [1, 0], }, // 13 - - { pos: [-1, 1, -1], norm: [-1, 0, 0], uv: [0, 1], }, - { pos: [-1, -1, 1], norm: [-1, 0, 0], uv: [1, 0], }, { pos: [-1, 1, -1], norm: [-1, 0, 0], uv: [0, 1], }, // 14 { pos: [-1, 1, 1], norm: [-1, 0, 0], uv: [1, 1], }, // 15 // 상단 { pos: [ 1, 1, -1], norm: [ 0, 1, 0], uv: [0, 0], }, // 16 { pos: [-1, 1, -1], norm: [ 0, 1, 0], uv: [1, 0], }, // 17 - - { pos: [ 1, 1, 1], norm: [ 0, 1, 0], uv: [0, 1], }, - { pos: [-1, 1, -1], norm: [ 0, 1, 0], uv: [1, 0], }, { pos: [ 1, 1, 1], norm: [ 0, 1, 0], uv: [0, 1], }, // 18 { pos: [-1, 1, 1], norm: [ 0, 1, 0], uv: [1, 1], }, // 19 // 하단 { pos: [ 1, -1, 1], norm: [ 0, -1, 0], uv: [0, 0], }, // 20 { pos: [-1, -1, 1], norm: [ 0, -1, 0], uv: [1, 0], }, // 21 - - { pos: [ 1, -1, -1], norm: [ 0, -1, 0], uv: [0, 1], }, - { pos: [-1, -1, 1], norm: [ 0, -1, 0], uv: [1, 0], }, { pos: [ 1, -1, -1], norm: [ 0, -1, 0], uv: [0, 1], }, // 22 { pos: [-1, -1, -1], norm: [ 0, -1, 0], uv: [1, 1], }, // 23 ]; </pre> <p>이제 꼭지점 24개만 남았습니다. 중복되는 꼭지점은 없죠. 이제 <a href="/docs/#api/ko/core/BufferGeometry.setIndex"><code class="notranslate" translate="no">BufferGeometry.setIndex</code></a> 메서드에 각 꼭지점 데이터의 인덱스값 36개-삼각형이 12개이므로-를 넘겨줍니다.</p> <pre class="prettyprint showlinemods notranslate lang-js" translate="no">geometry.setAttribute( 'position', new THREE.BufferAttribute(positions, positionNumComponents)); geometry.setAttribute( 'normal', new THREE.BufferAttribute(normals, normalNumComponents)); geometry.setAttribute( 'uv', new THREE.BufferAttribute(uvs, uvNumComponents)); +geometry.setIndex([ + 0, 1, 2, 2, 1, 3, // 앞쪽 + 4, 5, 6, 6, 5, 7, // 오른쪽 + 8, 9, 10, 10, 9, 11, // 뒤쪽 + 12, 13, 14, 14, 13, 15, // 왼쪽 + 16, 17, 18, 18, 17, 19, // 상단 + 20, 21, 22, 22, 21, 23, // 하단 +]); </pre> <p></p><div translate="no" class="threejs_example_container notranslate"> <div><iframe class="threejs_example notranslate" translate="no" style=" " src="/manual/examples/resources/editor.html?url=/manual/examples/custom-buffergeometry-cube-indexed.html"></iframe></div> <a class="threejs_center" href="/manual/examples/custom-buffergeometry-cube-indexed.html" target="_blank">새 탭에서 보기</a> </div> <p></p> <p><a href="/docs/#api/ko/core/BufferGeometry"><code class="notranslate" translate="no">BufferGeometry</code></a>에 법선을 지정하지 않았다면 <a href="/docs/#api/ko/core/BufferGeometry#computeVertexNormals"><code class="notranslate" translate="no">computeVertexNormals</code></a> 메서드를 호출해 자동으로 법선을 지정할 수 있습니다. 다만 데이터가 조금이라도 다르다면 꼭지점을 공유할 수 없기에 구체나 원통 같은 물체를 만들려 하는 경우에는 이음새가 보일 수 있어요.</p> <div class="spread"> <div> <div data-diagram="bufferGeometryCylinder"></div> <div class="code">BufferGeometry</div> </div> <div> <div data-diagram="geometryCylinder"></div> <div class="code">Geometry</div> </div> </div> <p>위 두 원통은 <code class="notranslate" translate="no">computeVertexNormals</code> 메서드를 호출해 법선을 생성했습니다. 자세히 보면 왼쪽 원통에 이음매가 있는 게 보일 텐데, 이는 원통의 끝과 시작점의 UV가 달라 꼭지점을 공유할 수 없기 때문입니다. 그다지 큰 문제는 아니지만, 알아두어 나쁠 건 없죠. 이를 해결하려면 법선을 직접 지정해야 합니다.</p> <p>아까는 처음에 순수 배열을 썼지만, 처음부터 <a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/TypedArray">형식화 배열</a>을 사용할 수도 있습니다. 다만 형식화 배열은 초기화할 때 미리 크기를 지정해줘야 합니다. 그렇게 어려운 일은 아니지만, 순수 배열은 <code class="notranslate" translate="no">push</code> 메서드로 요소를 추가하고 바뀐 길이를 <code class="notranslate" translate="no">length</code> 속성으로 확인할 수 있습니다. 하지만 형식화 배열을 사용하면 어디서 요소를 추가했는지 직접 일일이 기록해야 하죠.</p> <p>예제의 경우는 사전에 정해진 데이터를 사용하기에 배열 길이를 미리 구하는 게 어렵지 않습니다.</p> <pre class="prettyprint showlinemods notranslate lang-js" translate="no">-const positions = []; -const normals = []; -const uvs = []; +const numVertices = vertices.length; +const positionNumComponents = 3; +const normalNumComponents = 3; +const uvNumComponents = 2; +const positions = new Float32Array(numVertices * positionNumComponents); +const normals = new Float32Array(numVertices * normalNumComponents); +const uvs = new Float32Array(numVertices * uvNumComponents); +let posNdx = 0; +let nrmNdx = 0; +let uvNdx = 0; for (const vertex of vertices) { - positions.push(...vertex.pos); - normals.push(...vertex.norm); - uvs.push(...vertex.uv); + positions.set(vertex.pos, posNdx); + normals.set(vertex.norm, nrmNdx); + uvs.set(vertex.uv, uvNdx); + posNdx += positionNumComponents; + nrmNdx += normalNumComponents; + uvNdx += uvNumComponents; } geometry.setAttribute( 'position', - new THREE.BufferAttribute(new Float32Array(positions), positionNumComponents)); + new THREE.BufferAttribute(positions, positionNumComponents)); geometry.setAttribute( 'normal', - new THREE.BufferAttribute(new Float32Array(normals), normalNumComponents)); + new THREE.BufferAttribute(normals, normalNumComponents)); geometry.setAttribute( 'uv', - new THREE.BufferAttribute(new Float32Array(uvs), uvNumComponents)); + new THREE.BufferAttribute(uvs, uvNumComponents)); geometry.setIndex([ 0, 1, 2, 2, 1, 3, // 앞쪽 4, 5, 6, 6, 5, 7, // 오른쪽 8, 9, 10, 10, 9, 11, // 뒤쪽 12, 13, 14, 14, 13, 15, // 왼쪽 16, 17, 18, 18, 17, 19, // 상단 20, 21, 22, 22, 21, 23, // 하단 ]); </pre> <p></p><div translate="no" class="threejs_example_container notranslate"> <div><iframe class="threejs_example notranslate" translate="no" style=" " src="/manual/examples/resources/editor.html?url=/manual/examples/custom-buffergeometry-cube-typedarrays.html"></iframe></div> <a class="threejs_center" href="/manual/examples/custom-buffergeometry-cube-typedarrays.html" target="_blank">새 탭에서 보기</a> </div> <p></p> <p>꼭지점의 일부를 수정하고 싶다면 형식화 배열을 사용하는 게 좋습니다.</p> <p>뭔가 꼭지점을 동적으로 수정하는 예제를 찾아보려고 노력했는데, 찾기가 어렵네요. 그냥 구체를 만들고 구체의 각 사분면(quad)을 중심으로부터 안팎으로 움직여보겠습니다.</p> <p>아래는 구체의 위치값과 인덱스를 생성하는 코드입니다. 사분면 내의 꼭지점은 서로 공유할 수 있지만, 사분면은 각각 움직여야 하므로 사분면끼리는 공유하지 않도록 합니다.</p> <p>구체의 정점을 구하기 위해 좀 더 복잡한 방법을 쓸 수도 있지만, 귀찮으니 그냥 <a href="/docs/#api/ko/core/Object3D"><code class="notranslate" translate="no">Object3D</code></a> 3개를 계층 구조로 배열해 쓰겠습니다. 이 방식에 대해서는 <a href="optimize-lots-of-objects.html">많은 물체를 최적화하는 방법</a>에서 더 자세히 다루겠습니다.</p> <pre class="prettyprint showlinemods notranslate lang-js" translate="no">function makeSpherePositions(segmentsAround, segmentsDown) { const numVertices = segmentsAround * segmentsDown * 6; const numComponents = 3; const positions = new Float32Array(numVertices * numComponents); const indices = []; const longHelper = new THREE.Object3D(); const latHelper = new THREE.Object3D(); const pointHelper = new THREE.Object3D(); longHelper.add(latHelper); latHelper.add(pointHelper); pointHelper.position.z = 1; const temp = new THREE.Vector3(); function getPoint(lat, long) { latHelper.rotation.x = lat; longHelper.rotation.y = long; longHelper.updateMatrixWorld(true); return pointHelper.getWorldPosition(temp).toArray(); } let posNdx = 0; let ndx = 0; for (let down = 0; down < segmentsDown; ++down) { const v0 = down / segmentsDown; const v1 = (down + 1) / segmentsDown; const lat0 = (v0 - 0.5) * Math.PI; const lat1 = (v1 - 0.5) * Math.PI; for (let across = 0; across < segmentsAround; ++across) { const u0 = across / segmentsAround; const u1 = (across + 1) / segmentsAround; const long0 = u0 * Math.PI * 2; const long1 = u1 * Math.PI * 2; positions.set(getPoint(lat0, long0), posNdx); posNdx += numComponents; positions.set(getPoint(lat1, long0), posNdx); posNdx += numComponents; positions.set(getPoint(lat0, long1), posNdx); posNdx += numComponents; positions.set(getPoint(lat1, long1), posNdx); posNdx += numComponents; indices.push( ndx, ndx + 1, ndx + 2, ndx + 2, ndx + 1, ndx + 3, ); ndx += 4; } } return { positions, indices }; } </pre> <p>만든 함수를 다음처럼 호출합니다.</p> <pre class="prettyprint showlinemods notranslate lang-js" translate="no">const segmentsAround = 24; const segmentsDown = 16; const { positions, indices } = makeSpherePositions(segmentsAround, segmentsDown); </pre> <p>여기서 반환된 위치값(positions)은 구체의 위치값을 기반으로 합니다. 이는 법선의 값(normals)과 같으니 법선을 따로 구할 필요 없이 위치값을 복사해서 쓰면 됩니다.</p> <pre class="prettyprint showlinemods notranslate lang-js" translate="no">const normals = positions.slice(); </pre> <p>다음으로 각 속성을 지정합니다.</p> <pre class="prettyprint showlinemods notranslate lang-js" translate="no">const geometry = new THREE.BufferGeometry(); const positionNumComponents = 3; const normalNumComponents = 3; +const positionAttribute = new THREE.BufferAttribute(positions, positionNumComponents); +positionAttribute.setUsage(THREE.DynamicDrawUsage); geometry.setAttribute( 'position', + positionAttribute); geometry.setAttribute( 'normal', new THREE.BufferAttribute(normals, normalNumComponents)); geometry.setIndex(indices); </pre> <p>예제에서 차이점이 있는 부분을 표시해 두었습니다. 위치 속성에 참조값을 넘겨주었고, 이 속성이 동적이라고 명시했습니다. 이는 Three.js에게 해당 속성을 자주 변경될 수 있음을 알려주는 역할이죠.</p> <p>이제 <code class="notranslate" translate="no">render</code> 함수에서 매 프레임마다 법선을 기준으로 위치값을 변경해줍니다.</p> <pre class="prettyprint showlinemods notranslate lang-js" translate="no">const temp = new THREE.Vector3(); ... for (let i = 0; i < positions.length; i += 3) { const quad = (i / 12 | 0); const ringId = quad / segmentsAround | 0; const ringQuadId = quad % segmentsAround; const ringU = ringQuadId / segmentsAround; const angle = ringU * Math.PI * 2; temp.fromArray(normals, i); temp.multiplyScalar(THREE.MathUtils.lerp(1, 1.4, Math.sin(time + ringId + angle) * .5 + .5)); temp.toArray(positions, i); } positionAttribute.needsUpdate = true; </pre> <p>마지막으로 <code class="notranslate" translate="no">positionAttribute.needsUpdate</code> 속성을 활성화해 변화를 감지하도록 합니다.</p> <p></p><div translate="no" class="threejs_example_container notranslate"> <div><iframe class="threejs_example notranslate" translate="no" style=" " src="/manual/examples/resources/editor.html?url=/manual/examples/custom-buffergeometry-dynamic.html"></iframe></div> <a class="threejs_center" href="/manual/examples/custom-buffergeometry-dynamic.html" target="_blank">새 탭에서 보기</a> </div> <p></p> <p>이 글이 <a href="/docs/#api/ko/core/BufferGeometry"><code class="notranslate" translate="no">BufferGeometry</code></a>로 사용자 지정 geometry를 만들고, <a href="/docs/#api/ko/core/BufferAttribute"><code class="notranslate" translate="no">BufferAttribute</code></a>를 다루는 데 도움이 되었으면 좋겠습니다.</p> <p><canvas id="c"></canvas></p> <script type="module" src="../resources/threejs-custom-buffergeometry.js"></script> </div> </div> </div> <script src="../resources/prettify.js"></script> <script src="../resources/lesson.js"></script> </body></html>
Close