-
Notifications
You must be signed in to change notification settings - Fork 113
/
MapSphereNodeGeometry.ts
88 lines (74 loc) · 2.32 KB
/
MapSphereNodeGeometry.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
import {BufferGeometry, Float32BufferAttribute, Vector3} from 'three';
/**
* Map node geometry is a geometry used to represent the spherical map nodes.
*/
export class MapSphereNodeGeometry extends BufferGeometry
{
/**
* Map sphere geometry constructor.
*
* @param width - Width of the node.
* @param height - Height of the node.
* @param widthSegments - Number of subdivisions along the width.
* @param heightSegments - Number of subdivisions along the height.
*/
public constructor(radius: number, widthSegments: number, heightSegments: number, phiStart: number, phiLength: number, thetaStart: number, thetaLength: number)
{
super();
const thetaEnd = thetaStart + thetaLength;
let index = 0;
const grid = [];
const vertex = new Vector3();
const normal = new Vector3();
// Buffers
const indices = [];
const vertices = [];
const normals = [];
const uvs = [];
// Generate vertices, normals and uvs
for (let iy = 0; iy <= heightSegments; iy++)
{
const verticesRow = [];
const v = iy / heightSegments;
for (let ix = 0; ix <= widthSegments; ix++)
{
const u = ix / widthSegments;
// Vertex
vertex.x = -radius * Math.cos(phiStart + u * phiLength) * Math.sin(thetaStart + v * thetaLength);
vertex.y = radius * Math.cos(thetaStart + v * thetaLength);
vertex.z = radius * Math.sin(phiStart + u * phiLength) * Math.sin(thetaStart + v * thetaLength);
vertices.push(vertex.x, vertex.y, vertex.z);
// Normal
normal.set(vertex.x, vertex.y, vertex.z).normalize();
normals.push(normal.x, normal.y, normal.z);
// UV
uvs.push(u, 1 - v);
verticesRow.push(index++);
}
grid.push(verticesRow);
}
// Indices
for (let iy = 0; iy < heightSegments; iy++)
{
for (let ix = 0; ix < widthSegments; ix++)
{
const a = grid[iy][ix + 1];
const b = grid[iy][ix];
const c = grid[iy + 1][ix];
const d = grid[iy + 1][ix + 1];
if (iy !== 0 || thetaStart > 0)
{
indices.push(a, b, d);
}
if (iy !== heightSegments - 1 || thetaEnd < Math.PI)
{
indices.push(b, c, d);
}
}
}
this.setIndex(indices);
this.setAttribute('position', new Float32BufferAttribute(vertices, 3));
this.setAttribute('normal', new Float32BufferAttribute(normals, 3));
this.setAttribute('uv', new Float32BufferAttribute(uvs, 2));
}
}