Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Roblox
GitHub Repository: Roblox/luau
Path: blob/master/bench/tests/mesh-normal-scalar.lua
2725 views
1
--!strict
2
local function prequire(name) local success, result = pcall(require, name); return success and result end
3
local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support")
4
5
function test()
6
7
type Vertex = {
8
pX: number, pY: number, pZ: number,
9
uvX: number, uvY: number, uvZ: number,
10
nX: number, nY: number, nZ: number,
11
tX: number, tY: number, tZ: number,
12
bX: number, bY: number, bZ: number,
13
h: number
14
}
15
16
local grid_size = 100
17
18
local mesh: {
19
vertices: {Vertex},
20
indices: {number},
21
triangle_cone_p: {{x: number, y: number, z: number}},
22
triangle_cone_n: {{x: number, y: number, z: number}}
23
} = {
24
vertices = table.create(grid_size * grid_size),
25
indices = table.create((grid_size - 1) * (grid_size - 1) * 6),
26
triangle_cone_p = table.create((grid_size - 1) * (grid_size - 1) * 2),
27
triangle_cone_n = table.create((grid_size - 1) * (grid_size - 1) * 2)
28
}
29
30
local function init_vertices()
31
local i = 1
32
for y = 1,grid_size do
33
for x = 1,grid_size do
34
local v: Vertex = {}
35
36
v.pX = x
37
v.pY = y
38
v.pZ = math.cos(x) + math.sin(y)
39
40
v.uvX = (x-1)/(grid_size-1)
41
v.uvY = (y-1)/(grid_size-1)
42
v.uvZ = 0
43
44
v.nX = 0
45
v.nY = 0
46
v.nZ = 0
47
48
v.bX = 0
49
v.bY = 0
50
v.bZ = 0
51
52
v.tX = 0
53
v.tY = 0
54
v.tZ = 0
55
56
v.h = 0
57
58
mesh.vertices[i] = v
59
i += 1
60
end
61
end
62
end
63
64
local function init_indices()
65
local i = 1
66
for y = 1,grid_size-1 do
67
for x = 1,grid_size-1 do
68
mesh.indices[i] = x + (y-1)*grid_size
69
i += 1
70
mesh.indices[i] = x + y*grid_size
71
i += 1
72
mesh.indices[i] = (x+1) + (y-1)*grid_size
73
i += 1
74
mesh.indices[i] = (x+1) + (y-1)*grid_size
75
i += 1
76
mesh.indices[i] = x + y*grid_size
77
i += 1
78
mesh.indices[i] = (x+1) + y*grid_size
79
i += 1
80
end
81
end
82
end
83
84
local function calculate_normals()
85
local norm_sum = 0
86
87
for i = 1,#mesh.indices,3 do
88
local a = mesh.vertices[mesh.indices[i]]
89
local b = mesh.vertices[mesh.indices[i + 1]]
90
local c = mesh.vertices[mesh.indices[i + 2]]
91
92
local abx = a.pX - b.pX
93
local aby = a.pY - b.pY
94
local abz = a.pZ - b.pZ
95
96
local acx = a.pX - c.pX
97
local acy = a.pY - c.pY
98
local acz = a.pZ - c.pZ
99
100
local nx = aby * acz - abz * acy;
101
local ny = abz * acx - abx * acz;
102
local nz = abx * acy - aby * acx;
103
104
a.nX += nx
105
a.nY += ny
106
a.nZ += nz
107
108
b.nX += nx
109
b.nY += ny
110
b.nZ += nz
111
112
c.nX += nx
113
c.nY += ny
114
c.nZ += nz
115
end
116
117
for _,v in mesh.vertices do
118
local magnitude = math.sqrt(v.nX * v.nX + v.nY * v.nY + v.nZ * v.nZ)
119
120
v.nX /= magnitude
121
v.nY /= magnitude
122
v.nZ /= magnitude
123
124
norm_sum += v.nX * v.nX + v.nY * v.nY + v.nZ * v.nZ
125
end
126
127
return norm_sum
128
end
129
130
local function compute_triangle_cones()
131
local mesh_area = 0
132
133
local pos = 1
134
135
for i = 1,#mesh.indices,3 do
136
local p0 = mesh.vertices[mesh.indices[i]]
137
local p1 = mesh.vertices[mesh.indices[i + 1]]
138
local p2 = mesh.vertices[mesh.indices[i + 2]]
139
140
local p10x = p1.pX - p0.pX
141
local p10y = p1.pY - p0.pY
142
local p10z = p1.pZ - p0.pZ
143
local p20x = p2.pX - p0.pX
144
local p20y = p2.pY - p0.pY
145
local p20z = p2.pZ - p0.pZ
146
147
local normalx = p10y * p20z - p10z * p20y;
148
local normaly = p10z * p20x - p10x * p20z;
149
local normalz = p10x * p20y - p10y * p20x;
150
151
local area = math.sqrt(normalx * normalx + normaly * normaly + normalz * normalz)
152
local invarea = if area == 0 then 0 else 1 / area;
153
154
local rx = (p0.pX + p1.pX + p2.pX) / 3
155
local ry = (p0.pY + p1.pY + p2.pY) / 3
156
local rz = (p0.pZ + p1.pZ + p2.pZ) / 3
157
158
mesh.triangle_cone_p[pos] = { x = rx, y = ry, z = rz }
159
mesh.triangle_cone_n[pos] = { x = normalx * invarea, y = normaly * invarea, z = normalz * invarea}
160
pos += 1
161
162
mesh_area += area
163
end
164
165
return mesh_area
166
end
167
168
local function compute_tangent_space()
169
local checksum = 0
170
171
for i = 1,#mesh.indices,3 do
172
local a = mesh.vertices[mesh.indices[i]]
173
local b = mesh.vertices[mesh.indices[i + 1]]
174
local c = mesh.vertices[mesh.indices[i + 2]]
175
176
local x1 = b.pX - a.pX
177
local x2 = c.pX - a.pX
178
local y1 = b.pY - a.pY
179
local y2 = c.pY - a.pY
180
local z1 = b.pZ - a.pZ
181
local z2 = c.pZ - a.pZ
182
183
local s1 = b.uvX - a.uvX
184
local s2 = c.uvX - a.uvX
185
local t1 = b.uvY - a.uvY
186
local t2 = c.uvY - a.uvY
187
188
local r = 1.0 / (s1 * t2 - s2 * t1);
189
local sdirX = (t2 * x1 - t1 * x2) * r
190
local sdirY = (t2 * y1 - t1 * y2) * r
191
local sdirZ = (t2 * z1 - t1 * z2) * r
192
local tdirX = (s1 * x2 - s2 * x1) * r
193
local tdirY = (s1 * y2 - s2 * y1) * r
194
local tdirZ = (s1 * z2 - s2 * z1) * r
195
196
a.tX += sdirX
197
a.tY += sdirY
198
a.tZ += sdirZ
199
b.tX += sdirX
200
b.tY += sdirY
201
b.tZ += sdirZ
202
c.tX += sdirX
203
c.tY += sdirY
204
c.tZ += sdirZ
205
206
a.bX += tdirX
207
a.bY += tdirY
208
a.bZ += tdirZ
209
b.bX += tdirX
210
b.bY += tdirY
211
b.bZ += tdirZ
212
c.bX += tdirX
213
c.bY += tdirY
214
c.bZ += tdirZ
215
end
216
217
for _,v in mesh.vertices do
218
local tX = v.tX
219
local tY = v.tY
220
local tZ = v.tZ
221
222
-- Gram-Schmidt orthogonalize
223
local ndt = v.nX * tX + v.nY * tY + v.nZ * tZ
224
local tmnsX = tX - v.nX * ndt
225
local tmnsY = tY - v.nY * ndt
226
local tmnsZ = tZ - v.nZ * ndt
227
local l = math.sqrt(tmnsX * tmnsX + tmnsY * tmnsY + tmnsZ * tmnsZ)
228
229
local invl = 1 / l
230
v.tX = tmnsX * invl
231
v.tY = tmnsY * invl
232
v.tZ = tmnsZ * invl
233
234
local normalx = v.nY * tZ - v.nZ * tY;
235
local normaly = v.nZ * tX - v.nX * tZ;
236
local normalz = v.nX * tY - v.nY * tX;
237
238
local ht = normalx * v.bX + normaly * v.bY + normalz * v.bZ
239
240
v.h = ht < 0 and -1 or 1
241
242
checksum += v.tX + v.h
243
end
244
245
return checksum
246
end
247
248
init_vertices()
249
init_indices()
250
calculate_normals()
251
compute_triangle_cones()
252
compute_tangent_space()
253
end
254
255
bench.runCode(test, "mesh-normal-scalar")
256
257