blackbook3d 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +341 -0
- data/README.md +92 -0
- data/SETUP.md +70 -0
- data/data/assets/Texture/A011a.tga +0 -0
- data/data/assets/untitled.awp3d +0 -0
- data/data/cube.mtl +12 -0
- data/data/cube.obj +246 -0
- data/data/cube.raw +12 -0
- data/data/engine_conf.json +9 -0
- data/data/fighter.raw +19198 -0
- data/data/font/100.raw +78 -0
- data/data/font/101.raw +99 -0
- data/data/font/102.raw +58 -0
- data/data/font/103.raw +258 -0
- data/data/font/104.raw +55 -0
- data/data/font/105.raw +48 -0
- data/data/font/106.raw +72 -0
- data/data/font/107.raw +6 -0
- data/data/font/108.raw +2 -0
- data/data/font/109.raw +105 -0
- data/data/font/110.raw +55 -0
- data/data/font/111.raw +96 -0
- data/data/font/112.raw +78 -0
- data/data/font/113.raw +78 -0
- data/data/font/114.raw +53 -0
- data/data/font/115.raw +132 -0
- data/data/font/116.raw +56 -0
- data/data/font/117.raw +54 -0
- data/data/font/118.raw +5 -0
- data/data/font/119.raw +11 -0
- data/data/font/120.raw +10 -0
- data/data/font/121.raw +6 -0
- data/data/font/122.raw +6 -0
- data/data/font/33.raw +118 -0
- data/data/font/37.raw +194 -0
- data/data/font/38.raw +200 -0
- data/data/font/39.raw +4 -0
- data/data/font/40.raw +48 -0
- data/data/font/41.raw +48 -0
- data/data/font/42.raw +226 -0
- data/data/font/43.raw +10 -0
- data/data/font/45.raw +2 -0
- data/data/font/46.raw +46 -0
- data/data/font/47.raw +2 -0
- data/data/font/48.raw +96 -0
- data/data/font/49.raw +2 -0
- data/data/font/50.raw +87 -0
- data/data/font/51.raw +145 -0
- data/data/font/52.raw +15 -0
- data/data/font/53.raw +76 -0
- data/data/font/54.raw +121 -0
- data/data/font/55.raw +4 -0
- data/data/font/56.raw +194 -0
- data/data/font/57.raw +133 -0
- data/data/font/61.raw +4 -0
- data/data/font/63.raw +117 -0
- data/data/font/65.raw +11 -0
- data/data/font/66.raw +108 -0
- data/data/font/67.raw +96 -0
- data/data/font/68.raw +54 -0
- data/data/font/69.raw +10 -0
- data/data/font/70.raw +8 -0
- data/data/font/71.raw +100 -0
- data/data/font/72.raw +10 -0
- data/data/font/73.raw +2 -0
- data/data/font/74.raw +39 -0
- data/data/font/75.raw +9 -0
- data/data/font/76.raw +4 -0
- data/data/font/77.raw +13 -0
- data/data/font/78.raw +8 -0
- data/data/font/79.raw +96 -0
- data/data/font/80.raw +56 -0
- data/data/font/81.raw +124 -0
- data/data/font/82.raw +94 -0
- data/data/font/83.raw +120 -0
- data/data/font/84.raw +6 -0
- data/data/font/85.raw +76 -0
- data/data/font/86.raw +5 -0
- data/data/font/87.raw +11 -0
- data/data/font/88.raw +10 -0
- data/data/font/89.raw +7 -0
- data/data/font/90.raw +6 -0
- data/data/font/91.raw +6 -0
- data/data/font/93.raw +6 -0
- data/data/font/94.raw +5 -0
- data/data/font/95.raw +2 -0
- data/data/font/97.raw +174 -0
- data/data/font/98.raw +100 -0
- data/data/font/99.raw +96 -0
- data/data/ground.raw +12 -0
- data/data/man.mtl +12 -0
- data/data/man.obj +7547 -0
- data/data/robo.mtl +11 -0
- data/data/robo.obj +42065 -0
- data/data/space.json +49 -0
- data/data/sphere.raw +1216 -0
- data/data/texture/Charcoal-2.jpg +0 -0
- data/data/texture/man.png +0 -0
- data/data/texture/man.tif +0 -0
- data/data/texture/t.jpg +0 -0
- data/data/texture/wood.jpg +0 -0
- data/data/texture/wood.png +0 -0
- data/data/texture/x.jpg +0 -0
- data/data/untitled.raw +124 -0
- data/data/w.raw +12474 -0
- data/data/wings.raw +45670 -0
- data/lib/BlackBook/anim.rb +184 -0
- data/lib/BlackBook/b3dobject.rb +475 -0
- data/lib/BlackBook/base.rb +79 -0
- data/lib/BlackBook/camera.rb +202 -0
- data/lib/BlackBook/color.rb +29 -0
- data/lib/BlackBook/constants.rb +327 -0
- data/lib/BlackBook/engine.rb +172 -0
- data/lib/BlackBook/functions.rb +650 -0
- data/lib/BlackBook/light.rb +91 -0
- data/lib/BlackBook/logger.rb +86 -0
- data/lib/BlackBook/material.rb +98 -0
- data/lib/BlackBook/registry.rb +71 -0
- data/lib/BlackBook/space.rb +396 -0
- data/lib/BlackBook/stime.rb +64 -0
- data/lib/Plugins/string_color.rb +74 -0
- data/lib/blackbook/version.rb +5 -0
- data/lib/blackbook.rb +52 -0
- data/lib/plugins.rb +32 -0
- data/lib/ui/button.rb +115 -0
- data/lib/ui/edit.rb +105 -0
- data/lib/ui/text.rb +284 -0
- data/lib/ui/ui.rb +88 -0
- data/lib/ui/ui_element.rb +45 -0
- data/lib/ui/window.rb +138 -0
- data/lib/ui.rb +30 -0
- data/lib/zipfile.rb +27 -0
- metadata +254 -0
|
@@ -0,0 +1,650 @@
|
|
|
1
|
+
##############################################################################
|
|
2
|
+
# BlackBook 3D Engine
|
|
3
|
+
# Copyright (C) 2015 Sinan ISLEKDEMIR
|
|
4
|
+
#
|
|
5
|
+
# This program is free software; you can redistribute it and/or modify
|
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
|
7
|
+
# the Free Software Foundation; either version 2 of the License, or
|
|
8
|
+
# (at your option) any later version.
|
|
9
|
+
#
|
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
# GNU General Public License for more details.
|
|
14
|
+
#
|
|
15
|
+
# You should have received a copy of the GNU General Public License along
|
|
16
|
+
# with this program; if not, write to the Free Software Foundation, Inc.,
|
|
17
|
+
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
18
|
+
##############################################################################
|
|
19
|
+
|
|
20
|
+
################################################################
|
|
21
|
+
# Project BlackBook
|
|
22
|
+
# Lead Engineer: Sinan ISLEKDEMIR
|
|
23
|
+
# Simulation Engine Ruby Sources
|
|
24
|
+
################################################################
|
|
25
|
+
|
|
26
|
+
require 'opengl'
|
|
27
|
+
require 'pp'
|
|
28
|
+
|
|
29
|
+
# Local Libs
|
|
30
|
+
require 'BlackBook/constants'
|
|
31
|
+
|
|
32
|
+
# Mathematics related general functions
|
|
33
|
+
module BlackBook
|
|
34
|
+
#
|
|
35
|
+
# glhProjectf (works only from perspective projection.
|
|
36
|
+
# With the orthogonal projection it gives different results than
|
|
37
|
+
# standard gluProject.
|
|
38
|
+
# https://www.opengl.org/wiki/GluProject_and_gluUnProject_code
|
|
39
|
+
#
|
|
40
|
+
# @param obj [CVector] Object Coordinates
|
|
41
|
+
# @param mv [Array] Model View Matrix
|
|
42
|
+
# @param p [Array] Projection Matrix
|
|
43
|
+
# @param v [Array] Viewport Matrix
|
|
44
|
+
#
|
|
45
|
+
# @return [Array] Window Coordinates
|
|
46
|
+
def glh_project_f(obj, mv, p, v)
|
|
47
|
+
mv = mv.flatten
|
|
48
|
+
p = p.flatten
|
|
49
|
+
v = v.flatten
|
|
50
|
+
# Transformation vector
|
|
51
|
+
f = []
|
|
52
|
+
# Modelview Transform
|
|
53
|
+
f[0] = mv[0] * obj.x + mv[4] * obj.y + mv[8] * obj.z + mv[12]
|
|
54
|
+
f[1] = mv[1] * obj.x + mv[5] * obj.y + mv[9] * obj.z + mv[13]
|
|
55
|
+
f[2] = mv[2] * obj.x + mv[6] * obj.y + mv[10] * obj.z + mv[14]
|
|
56
|
+
f[3] = mv[3] * obj.x + mv[7] * obj.y + mv[11] * obj.z + mv[15]
|
|
57
|
+
# Projection transform the final row of projection
|
|
58
|
+
# matrix is always [0 0 -1 0]
|
|
59
|
+
# so we optimize for that.
|
|
60
|
+
f[4] = p[0] * f[0] + p[4] * f[1] + p[8] * f[2] + p[12] * f[3]
|
|
61
|
+
f[5] = p[1] * f[0] + p[5] * f[1] + p[9] * f[2] + p[13] * f[3]
|
|
62
|
+
f[6] = p[2] * f[0] + p[6] * f[1] + p[10] * f[2] + p[14] * f[3]
|
|
63
|
+
f[7] = -f[2]
|
|
64
|
+
# The result normalizes between -1 and 1
|
|
65
|
+
return [nil, nil] if f[7] == 0.0
|
|
66
|
+
f[7] = 1.0 / f[7]
|
|
67
|
+
# Perspective division
|
|
68
|
+
f[4] *= f[7]
|
|
69
|
+
f[5] *= f[7]
|
|
70
|
+
f[6] *= f[7]
|
|
71
|
+
# Window coordinates
|
|
72
|
+
# Map x, y to range 0-1
|
|
73
|
+
window_coordinate = []
|
|
74
|
+
window_coordinate[0] = (f[4] * 0.5 + 0.5) * v[2] + v[0]
|
|
75
|
+
window_coordinate[1] = (f[5] * 0.5 + 0.5) * v[3] + v[1]
|
|
76
|
+
# This is only correct when glDepthRange(0.0, 1.0)
|
|
77
|
+
window_coordinate[2] = (1.0 * f[6]) * 0.5
|
|
78
|
+
window_coordinate
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
#
|
|
82
|
+
# Multiply 4 x 4 matrices
|
|
83
|
+
# @param m1 [Array] Array of 4x4 matrice
|
|
84
|
+
# @param m2 [Array] Array of 4x4 matrice
|
|
85
|
+
#
|
|
86
|
+
# @return [Array] Result array
|
|
87
|
+
def multiply_matrices_4by4(m1, m2)
|
|
88
|
+
raise 'Matrices must be array' unless m1.is_a?(Array) && m2.is_a?(Array)
|
|
89
|
+
r = []
|
|
90
|
+
r[0] = m1[0] * m2[0] + m1[4] * m2[1] + m1[8] * m2[2] + m1[12] * m2[3]
|
|
91
|
+
r[4] = m1[0] * m2[4] + m1[4] * m2[5] + m1[8] * m2[6] + m1[12] * m2[7]
|
|
92
|
+
r[8] = m1[0] * m2[8] + m1[4] * m2[9] + m1[8] * m2[10] + m1[12] * m2[11]
|
|
93
|
+
r[12] = m1[0] * m2[12] + m1[4] * m2[13] + m1[8] * m2[14] + m1[12] * m2[15]
|
|
94
|
+
r[1] = m1[1] * m2[0] + m1[5] * m2[1] + m1[9] * m2[2] + m1[13] * m2[3]
|
|
95
|
+
r[5] = m1[1] * m2[4] + m1[5] * m2[5] + m1[9] * m2[6] + m1[13] * m2[7]
|
|
96
|
+
r[9] = m1[1] * m2[8] + m1[5] * m2[9] + m1[9] * m2[10] + m1[13] * m2[11]
|
|
97
|
+
r[13] = m1[1] * m2[12] + m1[5] * m2[13] + m1[9] * m2[14] + m1[13] * m2[15]
|
|
98
|
+
r[2] = m1[2] * m2[0] + m1[6] * m2[1] + m1[10] * m2[2] + m1[14] * m2[3]
|
|
99
|
+
r[6] = m1[2] * m2[4] + m1[6] * m2[5] + m1[10] * m2[6] + m1[14] * m2[7]
|
|
100
|
+
r[10] = m1[2] * m2[8] + m1[6] * m2[9] + m1[10] * m2[10] + m1[14] * m2[11]
|
|
101
|
+
r[14] = m1[2] * m2[12] + m1[6] * m2[13] + m1[10] * m2[14] + m1[14] * m2[15]
|
|
102
|
+
r[3] = m1[3] * m2[0] + m1[7] * m2[1] + m1[11] * m2[2] + m1[15] * m2[3]
|
|
103
|
+
r[7] = m1[3] * m2[4] + m1[7] * m2[5] + m1[11] * m2[6] + m1[15] * m2[7]
|
|
104
|
+
r[11] = m1[3] * m2[8] + m1[7] * m2[9] + m1[11] * m2[10] + m1[15] * m2[11]
|
|
105
|
+
r[15] = m1[3] * m2[12] + m1[7] * m2[13] + m1[11] * m2[14] + m1[15] * m2[15]
|
|
106
|
+
r
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
#
|
|
110
|
+
# Multiply matrix array with a vector array
|
|
111
|
+
# Vector held as array for quick usage
|
|
112
|
+
#
|
|
113
|
+
# @param m [Array] Matrix
|
|
114
|
+
# @param v [Array] Vector
|
|
115
|
+
#
|
|
116
|
+
# @return [Array] Result
|
|
117
|
+
def multiply_matrix_by_vector( matrix, vector )
|
|
118
|
+
[matrix, vector].map { |x| raise "#{x} must be array" unless x.is_a? Array}
|
|
119
|
+
m, v, r = matrix, vector, []
|
|
120
|
+
r[0] = m[0] * v[0] + m[4] * v[1] + m[8] * v[2] + m[12] * v[3]
|
|
121
|
+
r[1] = m[1] * v[0] + m[5] * v[1] + m[9] * v[2] + m[13] * v[3]
|
|
122
|
+
r[2] = m[2] * v[0] + m[6] * v[1] + m[10] * v[2] + m[14] * v[3]
|
|
123
|
+
r[3] = m[3] * v[0] + m[7] * v[1] + m[11] * v[2] + m[15] * v[3]
|
|
124
|
+
r
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
#
|
|
128
|
+
# Return array position from x-y coordinates
|
|
129
|
+
# @param x [Integer] X Coordinate
|
|
130
|
+
# @param y [Integer] Y Coordinate
|
|
131
|
+
#
|
|
132
|
+
# @return [Integer] Array index
|
|
133
|
+
def _mat(x, y)
|
|
134
|
+
raise 'Coords must be Integer' unless x.is_a?(Integer) && y.is_a?(Integer)
|
|
135
|
+
y * 4 + x
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
#
|
|
139
|
+
# Return item of matrix array from x-y coordinates
|
|
140
|
+
# @param m [Array] Matrix
|
|
141
|
+
# @param x [Integer] X Coordinate
|
|
142
|
+
# @param y [Integer] Y Coordinate
|
|
143
|
+
#
|
|
144
|
+
# @return [type] [description]
|
|
145
|
+
def mat(m, x, y)
|
|
146
|
+
raise 'Matrix must be array' unless m.is_a? Array
|
|
147
|
+
m[_mat(x, y)]
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
#
|
|
151
|
+
# Invert matrix array
|
|
152
|
+
# @param m [Array] Matrix
|
|
153
|
+
#
|
|
154
|
+
# @return [Array] Inverted matrix
|
|
155
|
+
def glh_invert_matrix_f2(m)
|
|
156
|
+
raise "Matrix must be array" unless m.is_a? Array
|
|
157
|
+
out = []
|
|
158
|
+
r0 = []
|
|
159
|
+
r1 = []
|
|
160
|
+
r2 = []
|
|
161
|
+
r3 = []
|
|
162
|
+
r0[0] = mat(m, 0, 0)
|
|
163
|
+
r0[1] = mat(m, 0, 1)
|
|
164
|
+
r0[2] = mat(m, 0, 2)
|
|
165
|
+
r0[3] = mat(m, 0, 3)
|
|
166
|
+
r0[4] = 1.0
|
|
167
|
+
r0[5] = r0[6] = r0[7] = 0.0
|
|
168
|
+
r1[0] = mat(m, 1, 0)
|
|
169
|
+
r1[1] = mat(m, 1, 1)
|
|
170
|
+
r1[2] = mat(m, 1, 2)
|
|
171
|
+
r1[3] = mat(m, 1, 3)
|
|
172
|
+
r1[5] = 1.0
|
|
173
|
+
r1[4] = r1[6] = r1[7] = 0.0
|
|
174
|
+
r2[0] = mat(m, 2, 0)
|
|
175
|
+
r2[1] = mat(m, 2, 1)
|
|
176
|
+
r2[2] = mat(m, 2, 2)
|
|
177
|
+
r2[3] = mat(m, 2, 3)
|
|
178
|
+
r2[6] = 1.0
|
|
179
|
+
r2[4] = r2[5] = r2[7] = 0.0
|
|
180
|
+
r3[0] = mat(m, 3, 0)
|
|
181
|
+
r3[1] = mat(m, 3, 1)
|
|
182
|
+
r3[2] = mat(m, 3, 2)
|
|
183
|
+
r3[3] = mat(m, 3, 3)
|
|
184
|
+
r3[7] = 1.0
|
|
185
|
+
r3[4] = r3[5] = r3[6] = 0.0
|
|
186
|
+
|
|
187
|
+
case
|
|
188
|
+
when r3[0].abs > r2[0] then r3, r2 = r2, r3
|
|
189
|
+
when r2[0].abs > r1[0] then r2, r1 = r1, r2
|
|
190
|
+
when r1[0].abs > r0[0] then r1, r0 = r0, r1
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
return 0 if r0[0] == 0.0
|
|
194
|
+
|
|
195
|
+
m1 = r1[0] / r0[0]
|
|
196
|
+
m2 = r2[0] / r0[0]
|
|
197
|
+
m3 = r3[0] / r0[0]
|
|
198
|
+
|
|
199
|
+
[1, 2, 3].map do |x|
|
|
200
|
+
r1[x] -= m1 * r0[x]
|
|
201
|
+
r2[x] -= m2 * r0[x]
|
|
202
|
+
r3[x] -= m3 * r0[x]
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
[4, 5, 6, 7].map do |x|
|
|
206
|
+
unless x == 0.0
|
|
207
|
+
r1[x] -= m1 * r0[x]
|
|
208
|
+
r2[x] -= m2 * r0[x]
|
|
209
|
+
r3[x] -= m3 * r0[x]
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
r3, r2 = r2, r3 if r3[1].abs > r2[1].abs
|
|
214
|
+
r2, r1 = r1, r2 if r2[1].abs > r1[1].abs
|
|
215
|
+
|
|
216
|
+
return 0 if r1[1] == 0.0
|
|
217
|
+
|
|
218
|
+
m2 = r2[1] / r1[1]
|
|
219
|
+
m3 = r3[1] / r1[1]
|
|
220
|
+
|
|
221
|
+
r2[2] -= m2 * r1[2]
|
|
222
|
+
r3[2] -= m3 * r1[2]
|
|
223
|
+
r2[3] -= m2 * r1[3]
|
|
224
|
+
r3[3] -= m3 * r1[3]
|
|
225
|
+
|
|
226
|
+
[4, 5, 6, 7].map do |x|
|
|
227
|
+
unless r1[x] == 0.0
|
|
228
|
+
r2[x] -= m2 * r1[x]
|
|
229
|
+
r3[x] -= m3 * r1[x]
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
r3, r2 = r2, r3 if r3[2].abs > r2[2].abs
|
|
234
|
+
|
|
235
|
+
return 0 if r2[2] == 0.0
|
|
236
|
+
|
|
237
|
+
[3, 4, 5, 6, 7].map do |x|
|
|
238
|
+
r3[x] -= r3[2] / r2[2] * r2[x]
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
return 0 if 0.0 == r3[3]
|
|
242
|
+
|
|
243
|
+
[4, 5, 6, 7].map do |x|
|
|
244
|
+
r3[x] *= 1.0 / r3[3]
|
|
245
|
+
r2[x] = 1.0 / r2[2] * (r2[x] - r3[x] * r2[3])
|
|
246
|
+
r1[x] -= r3[x] * r1[3]
|
|
247
|
+
r0[x] -= r3[x] * r0[3]
|
|
248
|
+
r1[x] = 1.0 / r1[1] * (r1[x] - r2[x] * r1[2])
|
|
249
|
+
r0[x] -= r2[x] * r0[2]
|
|
250
|
+
r0[x] = 1.0 / r0[0] * (r0[x] - r1[x] * r0[1])
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
out[_mat(0, 0)] = r0[4]
|
|
254
|
+
out[_mat(0, 1)] = r0[5]
|
|
255
|
+
out[_mat(0, 2)] = r0[6]
|
|
256
|
+
out[_mat(0, 3)] = r0[7]
|
|
257
|
+
out[_mat(1, 0)] = r1[4]
|
|
258
|
+
out[_mat(1, 1)] = r1[5]
|
|
259
|
+
out[_mat(1, 2)] = r1[6]
|
|
260
|
+
out[_mat(1, 3)] = r1[7]
|
|
261
|
+
out[_mat(2, 0)] = r2[4]
|
|
262
|
+
out[_mat(2, 1)] = r2[5]
|
|
263
|
+
out[_mat(2, 2)] = r2[6]
|
|
264
|
+
out[_mat(2, 3)] = r2[7]
|
|
265
|
+
out[_mat(3, 0)] = r3[4]
|
|
266
|
+
out[_mat(3, 1)] = r3[5]
|
|
267
|
+
out[_mat(3, 2)] = r3[6]
|
|
268
|
+
out[_mat(3, 3)] = r3[7]
|
|
269
|
+
out
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
#
|
|
273
|
+
# GLU Unproject
|
|
274
|
+
# https://www.opengl.org/wiki/GluProject_and_gluUnProject_code
|
|
275
|
+
#
|
|
276
|
+
# @param wx [Float] Window X Coordinate
|
|
277
|
+
# @param wy [Float] Window Y Coordinate
|
|
278
|
+
# @param wz [Float] Window Z Coordinate
|
|
279
|
+
# @param m [Array] Model View Matrix
|
|
280
|
+
# @param p [Array] Projection Matrix
|
|
281
|
+
# @param v [Array] Viewport Matrix
|
|
282
|
+
#
|
|
283
|
+
# @return [CVector] Object coordinates
|
|
284
|
+
def glh_unprojectf(wx, wy, wz, m, p, v)
|
|
285
|
+
# Transformation matrices
|
|
286
|
+
m_in = []
|
|
287
|
+
# Calculation for inverting a matrix, compute projection x modelview
|
|
288
|
+
# and store in A[16]
|
|
289
|
+
m = m.flatten
|
|
290
|
+
p = p.flatten
|
|
291
|
+
v = v.flatten
|
|
292
|
+
a = multiply_matrices_4by4(p, m)
|
|
293
|
+
invert_m = glh_invert_matrix_f2(a)
|
|
294
|
+
return 0 if invert_m == 0
|
|
295
|
+
m_in[0] = (wx - v[0].to_f) / v[2].to_f * 2.0 - 1.0
|
|
296
|
+
m_in[1] = (wy - v[1].to_f) / v[3].to_f * 2.0 - 1.0
|
|
297
|
+
m_in[2] = 2.0 * wz - 1.0
|
|
298
|
+
m_in[3] = 1.0
|
|
299
|
+
out = multiply_matrix_by_vector(invert_m, m_in)
|
|
300
|
+
return 0 if out[3] == 0
|
|
301
|
+
out[3] = 1.0 / out[3]
|
|
302
|
+
CVector.new(out[0] * out[3], out[1] * out[3], out[2] * out[3])
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
#
|
|
306
|
+
# Cross Product of two vectors
|
|
307
|
+
# @param x1 [Float] [X1 Element of vector]
|
|
308
|
+
# @param y1 [Float] [Y1 Element of vector]
|
|
309
|
+
# @param z1 [Float] [Z1 Element of vector]
|
|
310
|
+
# @param x2 [Float] [X2 Element of vector]
|
|
311
|
+
# @param y2 [Float] [Y2 Element of vector]
|
|
312
|
+
# @param z2 [Float] [Z2 Element of vector]
|
|
313
|
+
#
|
|
314
|
+
# @return [Array] Array of vector elements [x, y, z]
|
|
315
|
+
def cross_prod(x1, y1, z1, x2, y2, z2)
|
|
316
|
+
[(y1 * z2 - y2 * z1), (x2 * z1 - x1 * z2), (x1 * y2 - x2 * y1)]
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
#
|
|
320
|
+
# GLULookAt Alternative Function
|
|
321
|
+
# @param eye [CVector] [Eye position]
|
|
322
|
+
# @param look_at [CVector] [Target position]
|
|
323
|
+
# @param up [CVector] [Up vector of camera]
|
|
324
|
+
#
|
|
325
|
+
# @return [Boolean] Success
|
|
326
|
+
def look_at(eye, look_at, up)
|
|
327
|
+
z = CVector.new(eye.x - look_at.x, eye.y - look_at.y, eye.z - look_at.z, 1)
|
|
328
|
+
z.normalize
|
|
329
|
+
y = CVector.new(up.x, up.y, up.z, 1)
|
|
330
|
+
x = y.cross(z)
|
|
331
|
+
y = z.cross(x)
|
|
332
|
+
x.normalize
|
|
333
|
+
y.normalize
|
|
334
|
+
mat = [x.x, y.x, z.x, 0, x.y, y.y, z.y, 0, x.z, y.z, z.z, 0, 0, 0, 0, 1]
|
|
335
|
+
GL.MultMatrixf(mat)
|
|
336
|
+
GL.Translatef(-eye.x, -eye.y, -eye.z)
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
#
|
|
340
|
+
# GLUPerspective Alternative
|
|
341
|
+
# @param fovY [Float] Field of view
|
|
342
|
+
# @param aspect [Float] Aspect ratio of view
|
|
343
|
+
# @param znear [Float] Near Plane
|
|
344
|
+
# @param zfar [Float] Far Plane
|
|
345
|
+
#
|
|
346
|
+
# @return [Boolean] Success
|
|
347
|
+
def perspective(fov_y, aspect, znear, zfar)
|
|
348
|
+
pi = 3.1415926535897932384626433832795
|
|
349
|
+
fh = Math.tan((fov_y / 2) / 180 * pi) * znear
|
|
350
|
+
fw = fh * aspect
|
|
351
|
+
GL.Frustum(-fw, fw, -fh, fh, znear, zfar)
|
|
352
|
+
end
|
|
353
|
+
|
|
354
|
+
#
|
|
355
|
+
# Draw grid
|
|
356
|
+
#
|
|
357
|
+
# @return [Boolean] Success
|
|
358
|
+
def draw_grid
|
|
359
|
+
count = BlackBook::Registry.instance.read('grid_count') || 200
|
|
360
|
+
size = BlackBook::Registry.instance.read('grid_size')
|
|
361
|
+
GL.PushMatrix
|
|
362
|
+
GL.Translatef(0.0, 0.0, 0.0)
|
|
363
|
+
|
|
364
|
+
GL.Disable(GL::LIGHTING)
|
|
365
|
+
GL.Color3f(0.8, 0.8, 0.8)
|
|
366
|
+
x = (count / 2) * size * -1.0
|
|
367
|
+
y = (count / 2) * size * -1.0
|
|
368
|
+
1.upto(count - 1) do |i|
|
|
369
|
+
GL.Begin(GL::LINES)
|
|
370
|
+
GL.Vertex(x + (size * i), y, 0)
|
|
371
|
+
GL.Vertex(x + (size * i), -y, 0)
|
|
372
|
+
GL.End()
|
|
373
|
+
GL.Begin(GL::LINES)
|
|
374
|
+
GL.Vertex(x, y + (size * i), 0)
|
|
375
|
+
GL.Vertex(-x, y + (size * i), 0)
|
|
376
|
+
GL.End()
|
|
377
|
+
end
|
|
378
|
+
GL.LineWidth 3
|
|
379
|
+
GL.Color3f(1.0, 0.0, 0.0)
|
|
380
|
+
GL.Begin(GL::LINES)
|
|
381
|
+
GL.Vertex3f(0, 0, 0)
|
|
382
|
+
GL.Vertex3f(100.0, 0, 0)
|
|
383
|
+
GL.End
|
|
384
|
+
GL.Color3f(0.0, 1.0, 0.0)
|
|
385
|
+
GL.Begin(GL::LINES)
|
|
386
|
+
GL.Vertex3f(0, 0, 0)
|
|
387
|
+
GL.Vertex3f(0.0, 100.0, 0)
|
|
388
|
+
GL.End
|
|
389
|
+
GL.Color3f(0.0, 0.0, 1.0)
|
|
390
|
+
GL.Begin(GL::LINES)
|
|
391
|
+
GL.Vertex3f(0, 0, 0)
|
|
392
|
+
GL.Vertex3f(0.0, 0.0, 100.0)
|
|
393
|
+
GL.End
|
|
394
|
+
GL.LineWidth 1
|
|
395
|
+
|
|
396
|
+
GL.Enable(GL::LIGHTING)
|
|
397
|
+
GL.PopMatrix
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
#
|
|
401
|
+
# CVector to color.
|
|
402
|
+
# RGBA (0-255, 0-255, 0-255, 0-1)
|
|
403
|
+
# @param color_vector [CVector] Color vector
|
|
404
|
+
#
|
|
405
|
+
# @return [Boolean] Success
|
|
406
|
+
def apply_color(color_vector)
|
|
407
|
+
r = color_vector.x == 0 ? 0 : color_vector.x / 255.0
|
|
408
|
+
g = color_vector.y == 0 ? 0 : color_vector.y / 255.0
|
|
409
|
+
b = color_vector.z == 0 ? 0 : color_vector.z / 255.0
|
|
410
|
+
GL.Color4f(
|
|
411
|
+
r,
|
|
412
|
+
g,
|
|
413
|
+
b,
|
|
414
|
+
color_vector.w
|
|
415
|
+
)
|
|
416
|
+
end
|
|
417
|
+
|
|
418
|
+
#
|
|
419
|
+
# Draw 2D Box
|
|
420
|
+
# @param options [Hash]
|
|
421
|
+
# options[:x, :y, :z, :w, :color, :border, :border_color]
|
|
422
|
+
#
|
|
423
|
+
# @return [Boolean] Success
|
|
424
|
+
def draw_box_2d( opts = {} )
|
|
425
|
+
GL.PushMatrix
|
|
426
|
+
GL.Disable(GL::LIGHTING)
|
|
427
|
+
GL.Enable(GL::COLOR_MATERIAL)
|
|
428
|
+
GL.Enable(GL::BLEND)
|
|
429
|
+
GL.BlendFunc(GL::SRC_ALPHA, GL::ONE_MINUS_SRC_ALPHA)
|
|
430
|
+
GL.Translatef(opts[:x], opts[:y], opts[:z])
|
|
431
|
+
# Border
|
|
432
|
+
if opts[:border]
|
|
433
|
+
apply_color(opts[:border_color]) if opts[:border_color]
|
|
434
|
+
line_width = opts[:border_size] || 1
|
|
435
|
+
# hackaround for compare float-nil error
|
|
436
|
+
opts[:height] ||= 0
|
|
437
|
+
GL.LineWidth(line_width)
|
|
438
|
+
GL.Begin(GL::LINE_STRIP)
|
|
439
|
+
GL.Vertex2d(-line_width, -line_width)
|
|
440
|
+
GL.Vertex2d(-line_width, opts[:height] + line_width)
|
|
441
|
+
GL.Vertex2d(opts[:width] + line_width, opts[:height] + line_width)
|
|
442
|
+
GL.Vertex2d(opts[:width] + line_width, -line_width)
|
|
443
|
+
GL.Vertex2d(-line_width, -line_width)
|
|
444
|
+
GL.End
|
|
445
|
+
end
|
|
446
|
+
# Window
|
|
447
|
+
apply_color(opts[:color])
|
|
448
|
+
GL.Begin(GL::QUADS)
|
|
449
|
+
GL.Vertex2d(0, 0)
|
|
450
|
+
GL.Vertex2d(0, opts[:height])
|
|
451
|
+
GL.Vertex2d(opts[:width], opts[:height])
|
|
452
|
+
GL.Vertex2d(opts[:width], 0)
|
|
453
|
+
GL.End
|
|
454
|
+
GL.PopMatrix
|
|
455
|
+
end
|
|
456
|
+
|
|
457
|
+
#
|
|
458
|
+
# Degrees to Radians Conversion
|
|
459
|
+
# @param degrees [Float] Degrees
|
|
460
|
+
#
|
|
461
|
+
# @return [Float] Radians
|
|
462
|
+
def deg_to_rad(degrees)
|
|
463
|
+
degrees * (Math::PI / 180.0)
|
|
464
|
+
end
|
|
465
|
+
|
|
466
|
+
#
|
|
467
|
+
# Radians to Degrees
|
|
468
|
+
# @param radians [Float] Radians
|
|
469
|
+
#
|
|
470
|
+
# @return [Float] Degrees
|
|
471
|
+
def rad_to_deg(radians)
|
|
472
|
+
result = radians * (180.0 / Math::PI)
|
|
473
|
+
result += 360 if result.negative?
|
|
474
|
+
result = 360 - result if result > 360
|
|
475
|
+
return result
|
|
476
|
+
end
|
|
477
|
+
|
|
478
|
+
#
|
|
479
|
+
# Calculate Normal of a given Triangle
|
|
480
|
+
# @param p1 [CVector] Triangle Vector A
|
|
481
|
+
# @param p2 [CVector] Triangle Vector B
|
|
482
|
+
# @param p3 [CVector] Triangle Vector C
|
|
483
|
+
#
|
|
484
|
+
# @return [CVector] Normal Vector
|
|
485
|
+
def calc_plane_normal(p1, p2, p3)
|
|
486
|
+
v1 = p2.sub(p1)
|
|
487
|
+
v2 = p3.sub(p1)
|
|
488
|
+
result = v1.cross(v2)
|
|
489
|
+
return result.normalize
|
|
490
|
+
end
|
|
491
|
+
|
|
492
|
+
#
|
|
493
|
+
# Convert Array to Vector
|
|
494
|
+
# @param data [Array] Array of floats
|
|
495
|
+
#
|
|
496
|
+
# @return [CVector] Result Vector
|
|
497
|
+
def array_to_vector( data = [] )
|
|
498
|
+
raise 'Data must be array' unless data.is_a? Array
|
|
499
|
+
CVector.new(data[0], data[1], data[2], 1)
|
|
500
|
+
end
|
|
501
|
+
|
|
502
|
+
#
|
|
503
|
+
# Draw Circle
|
|
504
|
+
# @param r [Float] Radius
|
|
505
|
+
# @param num_segments [Integer] Number of segments
|
|
506
|
+
#
|
|
507
|
+
# @return [type] [description]
|
|
508
|
+
def draw_circle(r, num_segments)
|
|
509
|
+
pi = 3.1415926535897932384626433832795
|
|
510
|
+
GL.Begin(GL::LINE_LOOP)
|
|
511
|
+
(0..num_segments).each do |ii|
|
|
512
|
+
theta = 2.0 * pi * ii.to_f / num_segments.to_f
|
|
513
|
+
x = r * Math.cos(theta)
|
|
514
|
+
y = r * Math.sin(theta)
|
|
515
|
+
GL.Vertex2f(x, y)
|
|
516
|
+
end
|
|
517
|
+
GL.End
|
|
518
|
+
end
|
|
519
|
+
|
|
520
|
+
#
|
|
521
|
+
# Vector combine
|
|
522
|
+
# @param [CVector] first vector
|
|
523
|
+
# @param [CVector] second vector
|
|
524
|
+
# @param [CVector] Factor
|
|
525
|
+
# @return [CVector] Result
|
|
526
|
+
def vector_combine(v1, v2, t)
|
|
527
|
+
CVector.new(
|
|
528
|
+
v1.x + (t * v2.x),
|
|
529
|
+
v1.y + (t * v2.y),
|
|
530
|
+
v1.z + (t * v2.z),
|
|
531
|
+
v1.w + (t * v2.w)
|
|
532
|
+
)
|
|
533
|
+
end
|
|
534
|
+
|
|
535
|
+
#
|
|
536
|
+
# RayCastTriangleIntersect
|
|
537
|
+
#
|
|
538
|
+
# @param [CVector] ray_start
|
|
539
|
+
# @param [CVector] ray_vector
|
|
540
|
+
# @param [CVector] p1
|
|
541
|
+
# @param [CVector] p2
|
|
542
|
+
# @param [CVector] p3
|
|
543
|
+
#
|
|
544
|
+
# @return [Hash] :hit boolean, :point CVector, :normal CVector
|
|
545
|
+
def raycast_triangle_intersect(ray_start, ray_vector, p1, p2, p3)
|
|
546
|
+
e2 = 1e-30
|
|
547
|
+
result = {}
|
|
548
|
+
result[:point] = CVector.new(0, 0, 0)
|
|
549
|
+
result[:normal] = CVector.new(0, 0, 0)
|
|
550
|
+
result[:hit] = false
|
|
551
|
+
pvec = CVector.new(0, 0, 0)
|
|
552
|
+
v1 = CVector.new(0, 0, 0)
|
|
553
|
+
v2 = CVector.new(0, 0, 0)
|
|
554
|
+
qvec = CVector.new(0, 0, 0)
|
|
555
|
+
tvec = CVector.new(0, 0, 0)
|
|
556
|
+
t = 0.0
|
|
557
|
+
u = 0.0
|
|
558
|
+
v = 0.0
|
|
559
|
+
det = 0.0
|
|
560
|
+
inv_det = 0.0
|
|
561
|
+
v1 = p2.sub(p1)
|
|
562
|
+
v2 = p3.sub(p1)
|
|
563
|
+
pvec = ray_vector.cross(v2)
|
|
564
|
+
det = v1.dot(pvec)
|
|
565
|
+
return result if det < e2 && det > -e2
|
|
566
|
+
inv_det = 1.0 / det
|
|
567
|
+
tvec = ray_start.sub(p1)
|
|
568
|
+
u = tvec.dot(pvec) * inv_det
|
|
569
|
+
return result if u < 0 || u > 1
|
|
570
|
+
qvec = tvec.cross(v1)
|
|
571
|
+
v = tvec.dot(pvec) * inv_det
|
|
572
|
+
result[:hit] = (v >= 0) && (u + v <= 1)
|
|
573
|
+
if result[:hit]
|
|
574
|
+
t = v2.dot(qvec) * inv_det
|
|
575
|
+
if t > 0
|
|
576
|
+
result[:point] = BlackBook.vector_combine(
|
|
577
|
+
ray_start,
|
|
578
|
+
ray_vector,
|
|
579
|
+
t
|
|
580
|
+
)
|
|
581
|
+
result[:normal] = v1.cross(v2)
|
|
582
|
+
result[:normal].normalize
|
|
583
|
+
else
|
|
584
|
+
result[:hit] = false
|
|
585
|
+
end
|
|
586
|
+
end
|
|
587
|
+
result
|
|
588
|
+
end
|
|
589
|
+
|
|
590
|
+
#
|
|
591
|
+
# Raycast Plane Intersect
|
|
592
|
+
# @param [CVector] ray_start
|
|
593
|
+
# @param [CVector] ray_vector
|
|
594
|
+
# @param [CVector] plane_point
|
|
595
|
+
# @param [CVector] plane_normal
|
|
596
|
+
# @return [Hash] result
|
|
597
|
+
#
|
|
598
|
+
def raycast_plane_intersect(ray_start, ray_vector, plane_point, plane_normal)
|
|
599
|
+
result = {}
|
|
600
|
+
result[:point] = CVector.new(0, 0, 0)
|
|
601
|
+
e2 = 1e-30
|
|
602
|
+
sp = CVector.new(0, 0, 0)
|
|
603
|
+
t = 0.0
|
|
604
|
+
d = 0.0
|
|
605
|
+
d = ray_vector.dot(plane_normal)
|
|
606
|
+
result[:hit] = ((d > e2) || (d < -e2))
|
|
607
|
+
if result[:hit]
|
|
608
|
+
sp = plane_point.sub(ray_start)
|
|
609
|
+
d = 1 / d
|
|
610
|
+
t = sp.dot(plane_normal) * d
|
|
611
|
+
if t > 0
|
|
612
|
+
result[:point] = BlackBook.vector_combine(ray_start, ray_vector, t)
|
|
613
|
+
else
|
|
614
|
+
result[:hit] = false
|
|
615
|
+
end
|
|
616
|
+
end
|
|
617
|
+
result
|
|
618
|
+
end
|
|
619
|
+
|
|
620
|
+
#
|
|
621
|
+
# Check if given point lays on the defined line
|
|
622
|
+
# @param [CVector] point
|
|
623
|
+
# @param [CVector] line_start
|
|
624
|
+
# @param [CVector] line_end
|
|
625
|
+
# @return [Boolean] result
|
|
626
|
+
#
|
|
627
|
+
def point_on_line(point, line_start, line_end)
|
|
628
|
+
e2 = 1e-30
|
|
629
|
+
line_length = line_start.distance line_end
|
|
630
|
+
point_to_start = line_start.distance point
|
|
631
|
+
point_to_end = line_end.distance point
|
|
632
|
+
c = point_to_start + point_to_end - line_length
|
|
633
|
+
puts 'Line length: ' + line_length.to_s
|
|
634
|
+
puts 'P2S: ' + point_to_start.to_s
|
|
635
|
+
puts 'P2E: ' + point_to_end.to_s
|
|
636
|
+
c.abs < e2
|
|
637
|
+
end
|
|
638
|
+
|
|
639
|
+
# Transform vector by matrix
|
|
640
|
+
# @param [CVector] Vector
|
|
641
|
+
# @param [Array] Matrix
|
|
642
|
+
def vector_transform(v, m)
|
|
643
|
+
result = CVector.new(0.0, 0.0, 0.0)
|
|
644
|
+
result.x = v.x * m[0][0] + v.y * m[1][0] + v.z * m[2][0] + v.w * m[3][0]
|
|
645
|
+
result.y = v.x * m[0][1] + v.y * m[1][1] + v.z * m[2][1] + v.w * m[3][1]
|
|
646
|
+
result.z = v.x * m[0][2] + v.y * m[1][2] + v.z * m[2][2] + v.w * m[3][2]
|
|
647
|
+
result.w = v.x * m[0][3] + v.y * m[1][3] + v.z * m[2][3] + v.w * m[3][3]
|
|
648
|
+
result
|
|
649
|
+
end
|
|
650
|
+
end
|