rmath3d 1.0.2 → 1.1.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.
@@ -3,62 +3,59 @@ module RMath3D
3
3
  TOLERANCE = 1.0e-15
4
4
 
5
5
  #
6
- # Document-class: RMath3D::RMtx3
7
- # provies 3x3 matrix arithmetic.
6
+ # Document-class: RMath3D::RMtx2
7
+ # provies 2x2 matrix arithmetic.
8
8
  #
9
9
  # <b>Notice</b>
10
10
  # * elements are stored in column-major order.
11
11
  #
12
- class RMtx3
12
+ class RMtx2
13
13
 
14
14
  #
15
15
  # call-seq:
16
- # RMtx3.new -> ((1,0,0),(0,1,0),(0,0,1))
17
- # RMtx3.new(e) -> ((e,e,e), (e,e,e), (e,e,e))
18
- # RMtx3.new( other ) : Copy Constructor
19
- # RMtx3.new( e0, e1, ..., e8 ) -> ((e0,e1,e2), (e3,e4,e5), (e6,e7,e8))
16
+ # RMtx2.new -> ((1,0),(0,1))
17
+ # RMtx2.new(e) -> ((e,e), (e,e))
18
+ # RMtx2.new( other ) : Copy Constructor
19
+ # RMtx2.new( e0, e1, e2, e3 ) -> ((e0,e1), (e2,e3))
20
20
  #
21
- # Creates a new 3x3 matrix.
21
+ # Creates a new 2x2 matrix.
22
22
  #
23
23
  def initialize( *a )
24
24
  # [NOTE] elemetns are stored in column-major order.
25
25
  @e = []
26
26
  case a.length
27
27
  when 0
28
- @e = [ 0.0, 0.0, 0.0,
29
- 0.0, 0.0, 0.0,
30
- 0.0, 0.0, 0.0 ]
28
+ @e = [ 0.0, 0.0,
29
+ 0.0, 0.0 ]
31
30
  when 1
32
31
  case a[0]
33
32
  when Fixnum, Float
34
- @e = [ a[0], a[0], a[0],
35
- a[0], a[0], a[0],
36
- a[0], a[0], a[0] ]
37
- when RMtx3
33
+ @e = [ a[0], a[0],
34
+ a[0], a[0] ]
35
+ when RMtx2
38
36
  # Copy Constructor
39
- @e = [ a[0].e00, a[0].e10, a[0].e20,
40
- a[0].e01, a[0].e11, a[0].e21,
41
- a[0].e02, a[0].e12, a[0].e22 ]
37
+ @e = [ a[0].e00, a[0].e10,
38
+ a[0].e01, a[0].e11 ]
42
39
  else
43
- raise TypeError, "RMtx3#initialize : Unknown type #{a[0].class}."
40
+ raise TypeError, "RMtx2#initialize : Unknown type #{a[0].class}."
44
41
  return nil
45
42
  end
46
- when 9
43
+ when 4
47
44
  # Element-wise setter
48
- for row in 0...3 do
49
- for col in 0...3 do
50
- index = 3*row + col
45
+ for row in 0...2 do
46
+ for col in 0...2 do
47
+ index = 2*row + col
51
48
  case a[index]
52
49
  when Fixnum, Float
53
50
  setElement( row, col, a[index] )
54
51
  else
55
- raise TypeError, "RMtx3#initialize : Unknown type #{a[0].class}."
52
+ raise TypeError, "RMtx2#initialize : Unknown type #{a[0].class}."
56
53
  return nil
57
54
  end
58
55
  end
59
56
  end
60
57
  else
61
- raise RuntimeError, "RMtx3#initialize : wrong # of arguments (#{a.length})"
58
+ raise RuntimeError, "RMtx2#initialize : wrong # of arguments (#{a.length})"
62
59
  return nil
63
60
  end
64
61
 
@@ -71,9 +68,8 @@ module RMath3D
71
68
  # Returns human-readable string.
72
69
  #
73
70
  def to_s
74
- "( #{@e[0]}, #{@e[3]}, #{@e[6]} )\n" +
75
- "( #{@e[1]}, #{@e[4]}, #{@e[7]} )\n" +
76
- "( #{@e[2]}, #{@e[5]}, #{@e[8]} )\n"
71
+ "( #{@e[0]}, #{@e[2]} )\n" +
72
+ "( #{@e[1]}, #{@e[3]} )\n"
77
73
  end
78
74
 
79
75
  #
@@ -95,25 +91,25 @@ module RMath3D
95
91
  when Fixnum, Float, Bignum
96
92
  return [ self, arg ]
97
93
  else
98
- raise TypeError, "RMtx3#coerce : #{arg.self} can't be coerced into #{self.class}."
94
+ raise TypeError, "RMtx2#coerce : #{arg.self} can't be coerced into #{self.class}."
99
95
  return nil
100
96
  end
101
97
  end
102
98
 
103
99
  #
104
- # call-seq: setElements( e0, e1, ..., e8 )
100
+ # call-seq: setElements( e0, e1, e2, e3 )
105
101
  #
106
- # Stores given 9 new values.
102
+ # Stores given 4 new values.
107
103
  #
108
104
  def setElements( *a )
109
- if a.length != 9
110
- raise RuntimeError, "RMtx3#setElements : wrong # of arguments (#{a.length})"
105
+ if a.length != 4
106
+ raise RuntimeError, "RMtx2#setElements : wrong # of arguments (#{a.length})"
111
107
  return nil
112
108
  end
113
109
 
114
- for row in 0...3 do
115
- for col in 0...3 do
116
- index = 3*row + col
110
+ for row in 0...2 do
111
+ for col in 0...2 do
112
+ index = 2*row + col
117
113
  setElement( row, col, a[index] )
118
114
  end
119
115
  end
@@ -126,7 +122,7 @@ module RMath3D
126
122
  #
127
123
  def []=(row,col,value)
128
124
  # [NOTE] elemetns are stored in column-major order.
129
- @e[col*3+row] = value
125
+ @e[col*2+row] = value
130
126
  end
131
127
  alias_method :setElement, :'[]='
132
128
 
@@ -137,7 +133,7 @@ module RMath3D
137
133
  #
138
134
  def [](row,col)
139
135
  # [NOTE] elemetns are stored in column-major order.
140
- return @e[col*3+row]
136
+ return @e[col*2+row]
141
137
  end
142
138
  alias_method :getElement, :'[]'
143
139
 
@@ -145,79 +141,57 @@ module RMath3D
145
141
  def e00() getElement(0,0) end
146
142
  # Returns the element at row 0 and column 1.
147
143
  def e01() getElement(0,1) end
148
- # Returns the element at row 0 and column 2.
149
- def e02() getElement(0,2) end
150
144
  # Returns the element at row 1 and column 0.
151
145
  def e10() getElement(1,0) end
152
146
  # Returns the element at row 1 and column 1.
153
147
  def e11() getElement(1,1) end
154
- # Returns the element at row 1 and column 2.
155
- def e12() getElement(1,2) end
156
- # Returns the element at row 2 and column 0.
157
- def e20() getElement(2,0) end
158
- # Returns the element at row 2 and column 1.
159
- def e21() getElement(2,1) end
160
- # Returns the element at row 2 and column 2.
161
- def e22() getElement(2,2) end
162
148
 
163
149
  # Replaces the element at row 0 and column 0 by +value+.
164
150
  def e00=(value) setElement(0,0,value) end
165
151
  # Replaces the element at row 0 and column 1 by +value+.
166
152
  def e01=(value) setElement(0,1,value) end
167
- # Replaces the element at row 0 and column 2 by +value+.
168
- def e02=(value) setElement(0,2,value) end
169
153
  # Replaces the element at row 1 and column 0 by +value+.
170
154
  def e10=(value) setElement(1,0,value) end
171
155
  # Replaces the element at row 1 and column 1 by +value+.
172
156
  def e11=(value) setElement(1,1,value) end
173
- # Replaces the element at row 1 and column 2 by +value+.
174
- def e12=(value) setElement(1,2,value) end
175
- # Replaces the element at row 2 and column 0 by +value+.
176
- def e20=(value) setElement(2,0,value) end
177
- # Replaces the element at row 2 and column 1 by +value+.
178
- def e21=(value) setElement(2,1,value) end
179
- # Replaces the element at row 2 and column 2 by +value+.
180
- def e22=(value) setElement(2,2,value) end
181
157
 
182
158
 
183
159
  #
184
- # call-seq: mtx3.getRow(r) -> RVec3
160
+ # call-seq: mtx2.getRow(r) -> RVec2
185
161
  #
186
162
  # Returns +r+-th row vector.
187
163
  #
188
164
  def getRow( row )
189
- return RVec3.new( self[row,0], self[row,1], self[row,2] )
165
+ return RVec2.new( self[row,0], self[row,1] )
190
166
  end
191
167
 
192
168
  #
193
- # call-seq: mtx3.getColumn(c) -> RVec3
169
+ # call-seq: mtx2.getColumn(c) -> RVec2
194
170
  #
195
171
  # Returns +c+-th column vector.
196
172
  #
197
173
  def getColumn( column )
198
- return RVec3.new( self[0,column], self[1,column], self[2,column] )
174
+ return RVec2.new( self[0,column], self[1,column] )
199
175
  end
200
176
 
201
177
  #
202
- # call-seq: mtx3.setRow(v,r)
178
+ # call-seq: mtx2.setRow(v,r)
203
179
  #
204
180
  # Returns sets +r+-th row by vector +v+.
205
181
  #
206
182
  def setRow( v, row )
207
183
  self[row,0] = v.x
208
184
  self[row,1] = v.y
209
- self[row,2] = v.z
210
185
  end
211
186
 
212
187
  #
213
- # call-seq: mtx3.setColumn(v,c)
188
+ # call-seq: mtx2.setColumn(v,c)
214
189
  #
215
190
  # Returns sets +c+-th column by vector +v+.
216
191
  #
217
192
  def setColumn( v, column )
218
193
  self[0,column] = v.x
219
194
  self[1,column] = v.y
220
- self[2,column] = v.z
221
195
  end
222
196
 
223
197
  #
@@ -226,7 +200,7 @@ module RMath3D
226
200
  # Clears all elements by 0.0
227
201
  #
228
202
  def setZero
229
- 9.times do |i|
203
+ 4.times do |i|
230
204
  @e[i] = 0.0
231
205
  end
232
206
  return self
@@ -238,9 +212,9 @@ module RMath3D
238
212
  # Sets as identity matrix.
239
213
  #
240
214
  def setIdentity
241
- for row in 0...3 do
242
- for col in 0...3 do
243
- index = 3*row + col
215
+ for row in 0...2 do
216
+ for col in 0...2 do
217
+ index = 2*row + col
244
218
  if ( row == col )
245
219
  setElement( row, col, 1.0 )
246
220
  else
@@ -257,9 +231,7 @@ module RMath3D
257
231
  # Calculates determinant.
258
232
  #
259
233
  def getDeterminant
260
- e00 * (e11*e22 - e12*e21) -
261
- e01 * (e10*e22 - e12*e20) +
262
- e02 * (e10*e21 - e11*e20)
234
+ e00 * e11 - e01 * e10
263
235
  end
264
236
 
265
237
  #
@@ -268,9 +240,8 @@ module RMath3D
268
240
  # Returns transposed matrix.
269
241
  #
270
242
  def getTransposed
271
- return RMtx3.new( @e[0], @e[1], @e[2],
272
- @e[3], @e[4], @e[5],
273
- @e[6], @e[7], @e[8] )
243
+ return RMtx2.new( @e[0], @e[1],
244
+ @e[2], @e[3] )
274
245
  end
275
246
 
276
247
  #
@@ -279,9 +250,7 @@ module RMath3D
279
250
  # Transposeas its elements.
280
251
  #
281
252
  def transpose!
282
- @e[1], @e[3] = @e[3], @e[1]
283
- @e[2], @e[6] = @e[6], @e[2]
284
- @e[5], @e[7] = @e[7], @e[5]
253
+ @e[1], @e[2] = @e[2], @e[1]
285
254
  end
286
255
 
287
256
  #
@@ -290,27 +259,21 @@ module RMath3D
290
259
  # Returns the inverse.
291
260
  #
292
261
  def getInverse
293
- result = RMtx3.new
294
-
295
- result.e00 = (self.e11*self.e22 - self.e12*self.e21)
296
- result.e01 = -(self.e01*self.e22 - self.e02*self.e21)
297
- result.e02 = (self.e01*self.e12 - self.e02*self.e11)
298
-
299
- result.e10 = -(self.e10*self.e22 - self.e12*self.e20)
300
- result.e11 = (self.e00*self.e22 - self.e02*self.e20)
301
- result.e12 = -(self.e00*self.e12 - self.e02*self.e10)
302
-
303
- result.e20 = (self.e10*self.e21 - self.e11*self.e20)
304
- result.e21 = -(self.e00*self.e21 - self.e01*self.e20)
305
- result.e22 = (self.e00*self.e11 - self.e01*self.e10)
306
-
307
- det = e00 * result.e00 + e01 * result.e10 + e02 * result.e20
262
+ det = getDeterminant()
308
263
 
309
264
  if ( det.abs < TOLERANCE )
310
- raise RuntimeError, "RMtx3#getInverse : det.abs < TOLERANCE"
265
+ raise RuntimeError, "RMtx2#getInverse : det.abs < TOLERANCE"
311
266
  return nil
312
267
  end
313
268
 
269
+ result = RMtx2.new
270
+
271
+ result.e00 = self.e11
272
+ result.e01 = -self.e01
273
+
274
+ result.e10 = -self.e10
275
+ result.e11 = self.e00
276
+
314
277
  d = 1.0 / det
315
278
 
316
279
  result.mul!( d )
@@ -324,84 +287,38 @@ module RMath3D
324
287
  # Makes itself as the inverse of the original matrix.
325
288
  #
326
289
  def invert!
327
- elements = Array.new( 9 )
328
-
329
- elements[3*0+0] = (self.e11*self.e22 - self.e12*self.e21)
330
- elements[3*0+1] = -(self.e01*self.e22 - self.e02*self.e21)
331
- elements[3*0+2] = (self.e01*self.e12 - self.e02*self.e11)
332
-
333
- elements[3*1+0] = -(self.e10*self.e22 - self.e12*self.e20)
334
- elements[3*1+1] = (self.e00*self.e22 - self.e02*self.e20)
335
- elements[3*1+2] = -(self.e00*self.e12 - self.e02*self.e10)
336
-
337
- elements[3*2+0] = (self.e10*self.e21 - self.e11*self.e20)
338
- elements[3*2+1] = -(self.e00*self.e21 - self.e01*self.e20)
339
- elements[3*2+2] = (self.e00*self.e11 - self.e01*self.e10)
340
-
341
- det = e00 * elements[3*0+0] + e01 * elements[3*1+0] + e02 * elements[3*2+0]
290
+ det = getDeterminant()
342
291
 
343
292
  if ( det.abs < TOLERANCE )
344
- raise RuntimeError, "RMtx3#invert! : det.abs < TOLERANCE"
293
+ raise RuntimeError, "RMtx2#invert! : det.abs < TOLERANCE"
345
294
  return nil
346
295
  end
347
296
 
348
- d = 1.0 / det
349
-
350
- setElement( 0, 0, d * elements[3*0+0] )
351
- setElement( 0, 1, d * elements[3*0+1] )
352
- setElement( 0, 2, d * elements[3*0+2] )
353
- setElement( 1, 0, d * elements[3*1+0] )
354
- setElement( 1, 1, d * elements[3*1+1] )
355
- setElement( 1, 2, d * elements[3*1+2] )
356
- setElement( 2, 0, d * elements[3*2+0] )
357
- setElement( 2, 1, d * elements[3*2+1] )
358
- setElement( 2, 2, d * elements[3*2+2] )
359
-
360
- return self
361
- end
297
+ elements = Array.new( 4 )
362
298
 
363
- #
364
- # call-seq: rotationX(radian) -> self
365
- #
366
- # Makes a matrix that rotates around the x-axis.
367
- #
368
- def rotationX( radian )
369
- s = Math.sin( radian )
370
- c = Math.cos( radian )
299
+ elements[2*0+0] = self.e11
300
+ elements[2*0+1] = -self.e01
371
301
 
372
- setIdentity()
373
- self.e11 = c
374
- self.e12 = -s
375
- self.e21 = s
376
- self.e22 = c
302
+ elements[2*1+0] = -self.e10
303
+ elements[2*1+1] = self.e00
377
304
 
378
- return self
379
- end
305
+ d = 1.0 / det
380
306
 
381
- #
382
- # call-seq: rotationY(radian) -> self
383
- #
384
- # Makes a matrix that rotates around the y-axis.
385
- #
386
- def rotationY( radian )
387
- s = Math.sin( radian )
388
- c = Math.cos( radian )
307
+ setElement( 0, 0, d * elements[2*0+0] )
308
+ setElement( 0, 1, d * elements[2*0+1] )
389
309
 
390
- setIdentity()
391
- self.e00 = c
392
- self.e02 = s
393
- self.e20 = -s
394
- self.e22 = c
310
+ setElement( 1, 0, d * elements[2*1+0] )
311
+ setElement( 1, 1, d * elements[2*1+1] )
395
312
 
396
313
  return self
397
314
  end
398
315
 
399
316
  #
400
- # call-seq: rotationZ(radian) -> self
317
+ # call-seq: rotation(radian) -> self
401
318
  #
402
319
  # Makes a matrix that rotates around the z-axis.
403
320
  #
404
- def rotationZ( radian )
321
+ def rotation( radian )
405
322
  s = Math.sin( radian )
406
323
  c = Math.cos( radian )
407
324
 
@@ -415,88 +332,14 @@ module RMath3D
415
332
  end
416
333
 
417
334
  #
418
- # call-seq: rotationAxis(axis,radian) -> self
419
- #
420
- # Makes a matrix that rotates around the +axis+.
421
- #
422
- def rotationAxis( axis, radian )
423
- if ( axis.class != RVec3 )
424
- raise TypeError, "RMtx3#rotationAxis : Unknown type #{axis.class} given as axis."
425
- return nil
426
- end
427
- s = Math.sin( radian )
428
- c = Math.cos( radian )
429
- omc = 1.0 - c
430
- x = axis.x.to_f
431
- y = axis.y.to_f
432
- z = axis.z.to_f
433
-
434
- self.e00 = x*x*omc + c
435
- self.e01 = x*y*omc - z*s
436
- self.e02 = z*x*omc + y*s
437
- self.e10 = x*y*omc + z*s
438
- self.e11 = y*y*omc + c
439
- self.e12 = y*z*omc - x*s
440
- self.e20 = z*x*omc - y*s
441
- self.e21 = y*z*omc + x*s
442
- self.e22 = z*z*omc + c
443
-
444
- return self
445
- end
446
-
447
- #
448
- # call-seq: rotationQuaternion(q) -> self
449
- #
450
- # Makes a rotation matrix from a normalized quaternion +q+.
451
- #
452
- def rotationQuaternion( q )
453
- if ( q.class != RQuat )
454
- raise TypeError, "RMtx3#rotationQuaternion : Unknown type #{q.class} given as RQuat."
455
- return nil
456
- end
457
- x = q.x
458
- y = q.y
459
- z = q.z
460
- w = q.w
461
-
462
- x2 = 2.0 * x
463
- y2 = 2.0 * y
464
- z2 = 2.0 * z
465
-
466
- xx2 = x * x2
467
- yy2 = y * y2
468
- zz2 = z * z2
469
-
470
- yz2 = y * z2
471
- wx2 = w * x2
472
- xy2 = x * y2
473
- wz2 = w * z2
474
- xz2 = x * z2
475
- wy2 = w * y2
476
-
477
- self.e00 = 1.0 - yy2 - zz2
478
- self.e10 = xy2 + wz2
479
- self.e20 = xz2 - wy2
480
- self.e01 = xy2 - wz2
481
- self.e11 = 1.0 - xx2 - zz2
482
- self.e21 = yz2 + wx2
483
- self.e02 = xz2 + wy2
484
- self.e12 = yz2 - wx2
485
- self.e22 = 1.0 - xx2 - yy2
486
-
487
- return self
488
- end
489
-
490
- #
491
- # call-seq: scaling(sx,sy,sz) -> self
335
+ # call-seq: scaling(sx,sy) -> self
492
336
  #
493
337
  # Makes itself as a scaling matrix.
494
338
  #
495
- def scaling( sx, sy, sz )
339
+ def scaling( sx, sy )
496
340
  setIdentity()
497
341
  setElement( 0, 0, sx )
498
342
  setElement( 1, 1, sy )
499
- setElement( 2, 2, sz )
500
343
 
501
344
  return self
502
345
  end
@@ -516,7 +359,7 @@ module RMath3D
516
359
  # -mtx : Unary minus operator.
517
360
  #
518
361
  def -@
519
- return RMtx3.new( self * -1.0 )
362
+ return RMtx2.new( self * -1.0 )
520
363
  end
521
364
 
522
365
  #
@@ -525,14 +368,14 @@ module RMath3D
525
368
  # mtx1 + mtx2 : Binary plus operator.
526
369
  #
527
370
  def +( arg )
528
- if ( arg.class != RMtx3 )
529
- raise TypeError, "RMtx3#+(arg) : Unknown type #{arg.class} given as RMtx3."
371
+ if ( arg.class != RMtx2 )
372
+ raise TypeError, "RMtx2#+(arg) : Unknown type #{arg.class} given as RMtx2."
530
373
  return nil
531
374
  end
532
375
 
533
- result = RMtx3.new
534
- for row in 0...3 do
535
- for col in 0...3 do
376
+ result = RMtx2.new
377
+ for row in 0...2 do
378
+ for col in 0...2 do
536
379
  result.setElement( row, col, getElement(row,col) + arg.getElement(row,col) )
537
380
  end
538
381
  end
@@ -546,14 +389,14 @@ module RMath3D
546
389
  # mtx1 - mtx2 : Binary minus operator.
547
390
  #
548
391
  def -( arg )
549
- if ( arg.class != RMtx3 )
550
- raise TypeError, "RMtx3#-(arg) : Unknown type #{arg.class} given as RMtx3."
392
+ if ( arg.class != RMtx2 )
393
+ raise TypeError, "RMtx2#-(arg) : Unknown type #{arg.class} given as RMtx2."
551
394
  return nil
552
395
  end
553
396
 
554
- result = RMtx3.new
555
- for row in 0...3 do
556
- for col in 0...3 do
397
+ result = RMtx2.new
398
+ for row in 0...2 do
399
+ for col in 0...2 do
557
400
  result.setElement( row, col, getElement(row,col) - arg.getElement(row,col) )
558
401
  end
559
402
  end
@@ -569,16 +412,15 @@ module RMath3D
569
412
  def *( arg )
570
413
  case arg
571
414
  when Fixnum, Float, Bignum
572
- return RMtx3.new( arg*self.e00, arg*self.e01, arg*self.e02,
573
- arg*self.e10, arg*self.e11, arg*self.e12,
574
- arg*self.e20, arg*self.e21, arg*self.e22 )
415
+ return RMtx2.new( arg*self.e00, arg*self.e01,
416
+ arg*self.e10, arg*self.e11 )
575
417
 
576
- when RMtx3
577
- result = RMtx3.new
578
- for row in 0...3 do
579
- for col in 0...3 do
418
+ when RMtx2
419
+ result = RMtx2.new
420
+ for row in 0...2 do
421
+ for col in 0...2 do
580
422
  sum = 0.0
581
- for i in 0...3 do
423
+ for i in 0...2 do
582
424
  sum += getElement( row, i ) * arg.getElement( i, col )
583
425
  end
584
426
  result.setElement( row, col, sum )
@@ -587,7 +429,7 @@ module RMath3D
587
429
  return result
588
430
 
589
431
  else
590
- raise TypeError, "RMtx3#*(arg) : Unknown type #{arg.class} given."
432
+ raise TypeError, "RMtx2#*(arg) : Unknown type #{arg.class} given."
591
433
  return nil
592
434
  end
593
435
  end
@@ -598,13 +440,13 @@ module RMath3D
598
440
  # mtx1 == mtx2 : evaluates equality.
599
441
  #
600
442
  def ==( other )
601
- if ( other.class != RMtx3 )
602
- raise TypeError, "RMtx3#==(other) : Unknown type #{other.class} given as RMtx3."
443
+ if ( other.class != RMtx2 )
444
+ raise TypeError, "RMtx2#==(other) : Unknown type #{other.class} given as RMtx2."
603
445
  return nil
604
446
  end
605
447
 
606
- for row in 0...3 do
607
- for col in 0...3 do
448
+ for row in 0...2 do
449
+ for col in 0...2 do
608
450
  if ( (getElement(row,col) - other.getElement(row,col)).abs > TOLERANCE )
609
451
  return false
610
452
  end
@@ -619,14 +461,14 @@ module RMath3D
619
461
  # mtx1 += mtx2 : appends the elements of +mtx2+ into corresponding +mtx1+ elements.
620
462
  #
621
463
  def add!( other )
622
- if ( other.class != RMtx3 )
623
- raise TypeError, "RMtx3#add! : Unknown type #{other.class} given as RMtx3."
464
+ if ( other.class != RMtx2 )
465
+ raise TypeError, "RMtx2#add! : Unknown type #{other.class} given as RMtx2."
624
466
  return nil
625
467
  end
626
468
 
627
- result = RMtx3.new
628
- for row in 0...3 do
629
- for col in 0...3 do
469
+ result = RMtx2.new
470
+ for row in 0...2 do
471
+ for col in 0...2 do
630
472
  self.setElement( row, col, getElement(row,col) + other.getElement(row,col) )
631
473
  end
632
474
  end
@@ -640,14 +482,14 @@ module RMath3D
640
482
  # mtx1 -= mtx2 : subtracts the elements of +mtx2+ from corresponding +mtx1+ elements.
641
483
  #
642
484
  def sub!( other )
643
- if ( other.class != RMtx3 )
644
- raise TypeError, "RMtx3#sub! : Unknown type #{other.class} given as RMtx3."
485
+ if ( other.class != RMtx2 )
486
+ raise TypeError, "RMtx2#sub! : Unknown type #{other.class} given as RMtx2."
645
487
  return nil
646
488
  end
647
489
 
648
- result = RMtx3.new
649
- for row in 0...3 do
650
- for col in 0...3 do
490
+ result = RMtx2.new
491
+ for row in 0...2 do
492
+ for col in 0...2 do
651
493
  self.setElement( row, col, getElement(row,col) - other.getElement(row,col) )
652
494
  end
653
495
  end
@@ -665,21 +507,16 @@ module RMath3D
665
507
  when Fixnum, Float, Bignum
666
508
  self.e00 = other*self.e00
667
509
  self.e01 = other*self.e01
668
- self.e02 = other*self.e02
669
510
  self.e10 = other*self.e10
670
511
  self.e11 = other*self.e11
671
- self.e12 = other*self.e12
672
- self.e20 = other*self.e20
673
- self.e21 = other*self.e21
674
- self.e22 = other*self.e22
675
512
 
676
513
  return self
677
- when RMtx3
678
- result = RMtx3.new
679
- for row in 0...3 do
680
- for col in 0...3 do
514
+ when RMtx2
515
+ result = RMtx2.new
516
+ for row in 0...2 do
517
+ for col in 0...2 do
681
518
  sum = 0.0
682
- for i in 0...3 do
519
+ for i in 0...2 do
683
520
  sum += getElement( row, i ) * other.getElement( i, col )
684
521
  end
685
522
  result.setElement( row, col, sum )
@@ -688,13 +525,8 @@ module RMath3D
688
525
 
689
526
  self.e00 = result.e00
690
527
  self.e01 = result.e01
691
- self.e02 = result.e02
692
528
  self.e10 = result.e10
693
529
  self.e11 = result.e11
694
- self.e12 = result.e12
695
- self.e20 = result.e20
696
- self.e21 = result.e21
697
- self.e22 = result.e22
698
530
 
699
531
  return self
700
532
  end
@@ -702,65 +534,62 @@ module RMath3D
702
534
  end
703
535
 
704
536
  #
705
- # Document-class: RMath3D::RMtx4
706
- # provies 4x4 matrix arithmetic.
537
+ # Document-class: RMath3D::RMtx3
538
+ # provies 3x3 matrix arithmetic.
707
539
  #
708
540
  # <b>Notice</b>
709
541
  # * elements are stored in column-major order.
710
542
  #
711
- class RMtx4
543
+ class RMtx3
712
544
 
713
545
  #
714
546
  # call-seq:
715
- # RMtx4.new -> ((1,0,0,0),(0,1,0,0),(0,0,1,0),(0,0,0,1))
716
- # RMtx4.new(e) -> ((e,e,e,e),(e,e,e,e),(e,e,e,e),(e,e,e,e))
717
- # RMtx4.new( other ) : Copy Constructor
718
- # RMtx4.new( e0, e1, ..., e15 ) -> ((e0,e1,e2,e3),(e4,e5,e6,e7),(e8,e9,e10,e11),(e12,e13,e14,e15))
547
+ # RMtx3.new -> ((1,0,0),(0,1,0),(0,0,1))
548
+ # RMtx3.new(e) -> ((e,e,e), (e,e,e), (e,e,e))
549
+ # RMtx3.new( other ) : Copy Constructor
550
+ # RMtx3.new( e0, e1, ..., e8 ) -> ((e0,e1,e2), (e3,e4,e5), (e6,e7,e8))
719
551
  #
720
- # Creates a new 4x4 matrix.
552
+ # Creates a new 3x3 matrix.
721
553
  #
722
554
  def initialize( *a )
723
555
  # [NOTE] elemetns are stored in column-major order.
724
556
  @e = []
725
557
  case a.length
726
558
  when 0
727
- @e = [ 0.0, 0.0, 0.0, 0.0,
728
- 0.0, 0.0, 0.0, 0.0,
729
- 0.0, 0.0, 0.0, 0.0,
730
- 0.0, 0.0, 0.0, 0.0 ]
559
+ @e = [ 0.0, 0.0, 0.0,
560
+ 0.0, 0.0, 0.0,
561
+ 0.0, 0.0, 0.0 ]
731
562
  when 1
732
563
  case a[0]
733
564
  when Fixnum, Float
734
- @e = [ a[0], a[0], a[0], a[0],
735
- a[0], a[0], a[0], a[0],
736
- a[0], a[0], a[0], a[0],
737
- a[0], a[0], a[0], a[0] ]
738
- when RMtx4
565
+ @e = [ a[0], a[0], a[0],
566
+ a[0], a[0], a[0],
567
+ a[0], a[0], a[0] ]
568
+ when RMtx3
739
569
  # Copy Constructor
740
- @e = [ a[0].e00, a[0].e10, a[0].e20, a[0].e30,
741
- a[0].e01, a[0].e11, a[0].e21, a[0].e31,
742
- a[0].e02, a[0].e12, a[0].e22, a[0].e32,
743
- a[0].e03, a[0].e13, a[0].e23, a[0].e33 ]
570
+ @e = [ a[0].e00, a[0].e10, a[0].e20,
571
+ a[0].e01, a[0].e11, a[0].e21,
572
+ a[0].e02, a[0].e12, a[0].e22 ]
744
573
  else
745
- raise TypeError, "RMtx4#initialize : Unknown type #{a[0].class}."
574
+ raise TypeError, "RMtx3#initialize : Unknown type #{a[0].class}."
746
575
  return nil
747
576
  end
748
- when 16
577
+ when 9
749
578
  # Element-wise setter
750
- for row in 0...4 do
751
- for col in 0...4 do
752
- index = 4*row + col
579
+ for row in 0...3 do
580
+ for col in 0...3 do
581
+ index = 3*row + col
753
582
  case a[index]
754
583
  when Fixnum, Float
755
584
  setElement( row, col, a[index] )
756
585
  else
757
- raise TypeError, "RMtx4#initialize : Unknown type #{a[0].class}."
586
+ raise TypeError, "RMtx3#initialize : Unknown type #{a[0].class}."
758
587
  return nil
759
588
  end
760
589
  end
761
590
  end
762
591
  else
763
- raise RuntimeError, "RMtx4#initialize : wrong # of arguments (#{a.length})"
592
+ raise RuntimeError, "RMtx3#initialize : wrong # of arguments (#{a.length})"
764
593
  return nil
765
594
  end
766
595
 
@@ -773,10 +602,9 @@ module RMath3D
773
602
  # Returns human-readable string.
774
603
  #
775
604
  def to_s
776
- "( #{@e[0]}, #{@e[4]}, #{@e[8]}, #{@e[12]} )\n" +
777
- "( #{@e[1]}, #{@e[5]}, #{@e[9]}, #{@e[13]} )\n" +
778
- "( #{@e[2]}, #{@e[6]}, #{@e[10]}, #{@e[14]} )\n" +
779
- "( #{@e[3]}, #{@e[7]}, #{@e[11]}, #{@e[15]} )\n"
605
+ "( #{@e[0]}, #{@e[3]}, #{@e[6]} )\n" +
606
+ "( #{@e[1]}, #{@e[4]}, #{@e[7]} )\n" +
607
+ "( #{@e[2]}, #{@e[5]}, #{@e[8]} )\n"
780
608
  end
781
609
 
782
610
  #
@@ -798,25 +626,25 @@ module RMath3D
798
626
  when Fixnum, Float, Bignum
799
627
  return [ self, arg ]
800
628
  else
801
- raise TypeError, "RMtx4#coerce : #{arg.self} can't be coerced into #{self.class}."
629
+ raise TypeError, "RMtx3#coerce : #{arg.self} can't be coerced into #{self.class}."
802
630
  return nil
803
631
  end
804
632
  end
805
633
 
806
634
  #
807
- # call-seq: setElements( e0, e1, ..., e15 )
635
+ # call-seq: setElements( e0, e1, ..., e8 )
808
636
  #
809
- # Stores given 16 new values.
637
+ # Stores given 9 new values.
810
638
  #
811
639
  def setElements( *a )
812
- if a.length != 16
813
- raise RuntimeError, "RMtx4#setElements : wrong # of arguments (#{a.length})"
640
+ if a.length != 9
641
+ raise RuntimeError, "RMtx3#setElements : wrong # of arguments (#{a.length})"
814
642
  return nil
815
643
  end
816
644
 
817
- for row in 0...4 do
818
- for col in 0...4 do
819
- index = 4*row + col
645
+ for row in 0...3 do
646
+ for col in 0...3 do
647
+ index = 3*row + col
820
648
  setElement( row, col, a[index] )
821
649
  end
822
650
  end
@@ -829,7 +657,7 @@ module RMath3D
829
657
  #
830
658
  def []=(row,col,value)
831
659
  # [NOTE] elemetns are stored in column-major order.
832
- @e[col*4+row] = value
660
+ @e[col*3+row] = value
833
661
  end
834
662
  alias_method :setElement, :'[]='
835
663
 
@@ -840,7 +668,7 @@ module RMath3D
840
668
  #
841
669
  def [](row,col)
842
670
  # [NOTE] elemetns are stored in column-major order.
843
- return @e[col*4+row]
671
+ return @e[col*3+row]
844
672
  end
845
673
  alias_method :getElement, :'[]'
846
674
 
@@ -850,32 +678,18 @@ module RMath3D
850
678
  def e01() getElement(0,1) end
851
679
  # Returns the element at row 0 and column 2.
852
680
  def e02() getElement(0,2) end
853
- # Returns the element at row 0 and column 3.
854
- def e03() getElement(0,3) end
855
681
  # Returns the element at row 1 and column 0.
856
682
  def e10() getElement(1,0) end
857
683
  # Returns the element at row 1 and column 1.
858
684
  def e11() getElement(1,1) end
859
685
  # Returns the element at row 1 and column 2.
860
686
  def e12() getElement(1,2) end
861
- # Returns the element at row 1 and column 3.
862
- def e13() getElement(1,3) end
863
687
  # Returns the element at row 2 and column 0.
864
688
  def e20() getElement(2,0) end
865
689
  # Returns the element at row 2 and column 1.
866
690
  def e21() getElement(2,1) end
867
691
  # Returns the element at row 2 and column 2.
868
692
  def e22() getElement(2,2) end
869
- # Returns the element at row 2 and column 3.
870
- def e23() getElement(2,3) end
871
- # Returns the element at row 3 and column 0.
872
- def e30() getElement(3,0) end
873
- # Returns the element at row 3 and column 1.
874
- def e31() getElement(3,1) end
875
- # Returns the element at row 3 and column 2.
876
- def e32() getElement(3,2) end
877
- # Returns the element at row 3 and column 3.
878
- def e33() getElement(3,3) end
879
693
 
880
694
  # Replaces the element at row 0 and column 0 by +value+.
881
695
  def e00=(value) setElement(0,0,value) end
@@ -883,53 +697,40 @@ module RMath3D
883
697
  def e01=(value) setElement(0,1,value) end
884
698
  # Replaces the element at row 0 and column 2 by +value+.
885
699
  def e02=(value) setElement(0,2,value) end
886
- # Replaces the element at row 0 and column 3 by +value+.
887
- def e03=(value) setElement(0,3,value) end
888
700
  # Replaces the element at row 1 and column 0 by +value+.
889
701
  def e10=(value) setElement(1,0,value) end
890
702
  # Replaces the element at row 1 and column 1 by +value+.
891
703
  def e11=(value) setElement(1,1,value) end
892
704
  # Replaces the element at row 1 and column 2 by +value+.
893
705
  def e12=(value) setElement(1,2,value) end
894
- # Replaces the element at row 1 and column 3 by +value+.
895
- def e13=(value) setElement(1,3,value) end
896
706
  # Replaces the element at row 2 and column 0 by +value+.
897
707
  def e20=(value) setElement(2,0,value) end
898
708
  # Replaces the element at row 2 and column 1 by +value+.
899
709
  def e21=(value) setElement(2,1,value) end
900
710
  # Replaces the element at row 2 and column 2 by +value+.
901
711
  def e22=(value) setElement(2,2,value) end
902
- # Replaces the element at row 2 and column 3 by +value+.
903
- def e23=(value) setElement(2,3,value) end
904
- # Replaces the element at row 3 and column 0 by +value+.
905
- def e30=(value) setElement(3,0,value) end
906
- # Replaces the element at row 3 and column 1 by +value+.
907
- def e31=(value) setElement(3,1,value) end
908
- # Replaces the element at row 3 and column 2 by +value+.
909
- def e32=(value) setElement(3,2,value) end
910
- # Replaces the element at row 3 and column 3 by +value+.
911
- def e33=(value) setElement(3,3,value) end
712
+
912
713
 
913
714
  #
914
- # call-seq: mtx4.getRow(r) -> RVec4
715
+ # call-seq: mtx3.getRow(r) -> RVec3
915
716
  #
916
717
  # Returns +r+-th row vector.
917
718
  #
918
719
  def getRow( row )
919
- return RVec4.new( self[row,0], self[row,1], self[row,2], self[row,3] )
720
+ return RVec3.new( self[row,0], self[row,1], self[row,2] )
920
721
  end
921
722
 
922
723
  #
923
- # call-seq: mtx4.getColumn(c) -> RVec4
724
+ # call-seq: mtx3.getColumn(c) -> RVec3
924
725
  #
925
726
  # Returns +c+-th column vector.
926
727
  #
927
728
  def getColumn( column )
928
- return RVec4.new( self[0,column], self[1,column], self[2,column], self[3,column] )
729
+ return RVec3.new( self[0,column], self[1,column], self[2,column] )
929
730
  end
930
731
 
931
732
  #
932
- # call-seq: mtx4.setRow(v,r)
733
+ # call-seq: mtx3.setRow(v,r)
933
734
  #
934
735
  # Returns sets +r+-th row by vector +v+.
935
736
  #
@@ -937,11 +738,10 @@ module RMath3D
937
738
  self[row,0] = v.x
938
739
  self[row,1] = v.y
939
740
  self[row,2] = v.z
940
- self[row,3] = v.w
941
741
  end
942
742
 
943
743
  #
944
- # call-seq: mtx4.setColumn(v,c)
744
+ # call-seq: mtx3.setColumn(v,c)
945
745
  #
946
746
  # Returns sets +c+-th column by vector +v+.
947
747
  #
@@ -949,35 +749,15 @@ module RMath3D
949
749
  self[0,column] = v.x
950
750
  self[1,column] = v.y
951
751
  self[2,column] = v.z
952
- self[3,column] = v.w
953
- end
954
-
955
- def getUpper3x3
956
- return RMtx3.new( self.e00, self.e01, self.e02,
957
- self.e10, self.e11, self.e12,
958
- self.e20, self.e21, self.e22 )
959
- end
960
-
961
- def setUpper3x3( mtx3x3 )
962
- self.e00 = mtx3x3.e00
963
- self.e01 = mtx3x3.e01
964
- self.e02 = mtx3x3.e02
965
- self.e10 = mtx3x3.e10
966
- self.e11 = mtx3x3.e11
967
- self.e12 = mtx3x3.e12
968
- self.e20 = mtx3x3.e20
969
- self.e21 = mtx3x3.e21
970
- self.e22 = mtx3x3.e22
971
-
972
- return self
973
752
  end
974
753
 
754
+ #
975
755
  # call-seq: setZero
976
756
  #
977
757
  # Clears all elements by 0.0
978
758
  #
979
759
  def setZero
980
- 16.times do |i|
760
+ 9.times do |i|
981
761
  @e[i] = 0.0
982
762
  end
983
763
  return self
@@ -989,9 +769,9 @@ module RMath3D
989
769
  # Sets as identity matrix.
990
770
  #
991
771
  def setIdentity
992
- for row in 0...4 do
993
- for col in 0...4 do
994
- index = 4*row + col
772
+ for row in 0...3 do
773
+ for col in 0...3 do
774
+ index = 3*row + col
995
775
  if ( row == col )
996
776
  setElement( row, col, 1.0 )
997
777
  else
@@ -1002,23 +782,15 @@ module RMath3D
1002
782
  return self
1003
783
  end
1004
784
 
1005
- def det3( _e00,_e01,_e02, _e10,_e11,_e12, _e20,_e21,_e22 )
1006
- _e00 * (_e11*_e22 - _e12*_e21) -
1007
- _e01 * (_e10*_e22 - _e12*_e20) +
1008
- _e02 * (_e10*_e21 - _e11*_e20)
1009
- end
1010
- private :det3
1011
-
1012
785
  #
1013
786
  # call-seq: getDeterminant -> determinant
1014
787
  #
1015
788
  # Calculates determinant.
1016
789
  #
1017
790
  def getDeterminant
1018
- e00 * det3( e11,e12,e13, e21,e22,e23, e31,e32,e33 ) -
1019
- e01 * det3( e10,e12,e13, e20,e22,e23, e30,e32,e33 ) +
1020
- e02 * det3( e10,e11,e13, e20,e21,e23, e30,e31,e33 ) -
1021
- e03 * det3( e10,e11,e12, e20,e21,e22, e30,e31,e32 )
791
+ e00 * (e11*e22 - e12*e21) -
792
+ e01 * (e10*e22 - e12*e20) +
793
+ e02 * (e10*e21 - e11*e20)
1022
794
  end
1023
795
 
1024
796
  #
@@ -1027,10 +799,9 @@ module RMath3D
1027
799
  # Returns transposed matrix.
1028
800
  #
1029
801
  def getTransposed
1030
- return RMtx4.new( @e[ 0], @e[ 1], @e[ 2], @e[ 3],
1031
- @e[ 4], @e[ 5], @e[ 6], @e[ 7],
1032
- @e[ 8], @e[ 9], @e[10], @e[11],
1033
- @e[12], @e[13], @e[14], @e[15] )
802
+ return RMtx3.new( @e[0], @e[1], @e[2],
803
+ @e[3], @e[4], @e[5],
804
+ @e[6], @e[7], @e[8] )
1034
805
  end
1035
806
 
1036
807
  #
@@ -1039,12 +810,9 @@ module RMath3D
1039
810
  # Transposeas its elements.
1040
811
  #
1041
812
  def transpose!
1042
- @e[ 1], @e[ 4] = @e[ 4], @e[ 1]
1043
- @e[ 2], @e[ 8] = @e[ 8], @e[ 2]
1044
- @e[ 3], @e[12] = @e[12], @e[ 3]
1045
- @e[ 6], @e[ 9] = @e[ 9], @e[ 6]
1046
- @e[ 7], @e[13] = @e[13], @e[ 7]
1047
- @e[11], @e[14] = @e[14], @e[11]
813
+ @e[1], @e[3] = @e[3], @e[1]
814
+ @e[2], @e[6] = @e[6], @e[2]
815
+ @e[5], @e[7] = @e[7], @e[5]
1048
816
  end
1049
817
 
1050
818
  #
@@ -1053,32 +821,24 @@ module RMath3D
1053
821
  # Returns the inverse.
1054
822
  #
1055
823
  def getInverse
1056
- result = RMtx4.new
1057
-
1058
- result.e00 = det3( e11,e12,e13, e21,e22,e23, e31,e32,e33 )
1059
- result.e01 = -det3( e01,e02,e03, e21,e22,e23, e31,e32,e33 )
1060
- result.e02 = det3( e01,e02,e03, e11,e12,e13, e31,e32,e33 )
1061
- result.e03 = -det3( e01,e02,e03, e11,e12,e13, e21,e22,e23 )
824
+ result = RMtx3.new
1062
825
 
1063
- result.e10 = -det3( e10,e12,e13, e20,e22,e23, e30,e32,e33 )
1064
- result.e11 = det3( e00,e02,e03, e20,e22,e23, e30,e32,e33 )
1065
- result.e12 = -det3( e00,e02,e03, e10,e12,e13, e30,e32,e33 )
1066
- result.e13 = det3( e00,e02,e03, e10,e12,e13, e20,e22,e23 )
826
+ result.e00 = (self.e11*self.e22 - self.e12*self.e21)
827
+ result.e01 = -(self.e01*self.e22 - self.e02*self.e21)
828
+ result.e02 = (self.e01*self.e12 - self.e02*self.e11)
1067
829
 
1068
- result.e20 = det3( e10,e11,e13, e20,e21,e23, e30,e31,e33 )
1069
- result.e21 = -det3( e00,e01,e03, e20,e21,e23, e30,e31,e33 )
1070
- result.e22 = det3( e00,e01,e03, e10,e11,e13, e30,e31,e33 )
1071
- result.e23 = -det3( e00,e01,e03, e10,e11,e13, e20,e21,e23 )
830
+ result.e10 = -(self.e10*self.e22 - self.e12*self.e20)
831
+ result.e11 = (self.e00*self.e22 - self.e02*self.e20)
832
+ result.e12 = -(self.e00*self.e12 - self.e02*self.e10)
1072
833
 
1073
- result.e30 = -det3( e10,e11,e12, e20,e21,e22, e30,e31,e32 )
1074
- result.e31 = det3( e00,e01,e02, e20,e21,e22, e30,e31,e32 )
1075
- result.e32 = -det3( e00,e01,e02, e10,e11,e12, e30,e31,e32 )
1076
- result.e33 = det3( e00,e01,e02, e10,e11,e12, e20,e21,e22 )
834
+ result.e20 = (self.e10*self.e21 - self.e11*self.e20)
835
+ result.e21 = -(self.e00*self.e21 - self.e01*self.e20)
836
+ result.e22 = (self.e00*self.e11 - self.e01*self.e10)
1077
837
 
1078
- det = e00 * result.e00 + e01 * result.e10 + e02 * result.e20 + e03 * result.e30
838
+ det = e00 * result.e00 + e01 * result.e10 + e02 * result.e20
1079
839
 
1080
840
  if ( det.abs < TOLERANCE )
1081
- raise RuntimeError, "RMtx4#getInverse : det.abs < TOLERANCE"
841
+ raise RuntimeError, "RMtx3#getInverse : det.abs < TOLERANCE"
1082
842
  return nil
1083
843
  end
1084
844
 
@@ -1095,70 +855,38 @@ module RMath3D
1095
855
  # Makes itself as the inverse of the original matrix.
1096
856
  #
1097
857
  def invert!
1098
- elements = Array.new( 16 )
858
+ elements = Array.new( 9 )
1099
859
 
1100
- elements[4*0+0] = det3( self.e11,self.e12,self.e13, self.e21,self.e22,self.e23, self.e31,self.e32,self.e33 )
1101
- elements[4*0+1] = -det3( self.e01,self.e02,self.e03, self.e21,self.e22,self.e23, self.e31,self.e32,self.e33 )
1102
- elements[4*0+2] = det3( self.e01,self.e02,self.e03, self.e11,self.e12,self.e13, self.e31,self.e32,self.e33 )
1103
- elements[4*0+3] = -det3( self.e01,self.e02,self.e03, self.e11,self.e12,self.e13, self.e21,self.e22,self.e23 )
860
+ elements[3*0+0] = (self.e11*self.e22 - self.e12*self.e21)
861
+ elements[3*0+1] = -(self.e01*self.e22 - self.e02*self.e21)
862
+ elements[3*0+2] = (self.e01*self.e12 - self.e02*self.e11)
1104
863
 
1105
- elements[4*1+0] = -det3( self.e10,self.e12,self.e13, self.e20,self.e22,self.e23, self.e30,self.e32,self.e33 )
1106
- elements[4*1+1] = det3( self.e00,self.e02,self.e03, self.e20,self.e22,self.e23, self.e30,self.e32,self.e33 )
1107
- elements[4*1+2] = -det3( self.e00,self.e02,self.e03, self.e10,self.e12,self.e13, self.e30,self.e32,self.e33 )
1108
- elements[4*1+3] = det3( self.e00,self.e02,self.e03, self.e10,self.e12,self.e13, self.e20,self.e22,self.e23 )
1109
-
1110
- elements[4*2+0] = det3( self.e10,self.e11,self.e13, self.e20,self.e21,self.e23, self.e30,self.e31,self.e33 )
1111
- elements[4*2+1] = -det3( self.e00,self.e01,self.e03, self.e20,self.e21,self.e23, self.e30,self.e31,self.e33 )
1112
- elements[4*2+2] = det3( self.e00,self.e01,self.e03, self.e10,self.e11,self.e13, self.e30,self.e31,self.e33 )
1113
- elements[4*2+3] = -det3( self.e00,self.e01,self.e03, self.e10,self.e11,self.e13, self.e20,self.e21,self.e23 )
864
+ elements[3*1+0] = -(self.e10*self.e22 - self.e12*self.e20)
865
+ elements[3*1+1] = (self.e00*self.e22 - self.e02*self.e20)
866
+ elements[3*1+2] = -(self.e00*self.e12 - self.e02*self.e10)
1114
867
 
1115
- elements[4*3+0] = -det3( self.e10,self.e11,self.e12, self.e20,self.e21,self.e22, self.e30,self.e31,self.e32 )
1116
- elements[4*3+1] = det3( self.e00,self.e01,self.e02, self.e20,self.e21,self.e22, self.e30,self.e31,self.e32 )
1117
- elements[4*3+2] = -det3( self.e00,self.e01,self.e02, self.e10,self.e11,self.e12, self.e30,self.e31,self.e32 )
1118
- elements[4*3+3] = det3( self.e00,self.e01,self.e02, self.e10,self.e11,self.e12, self.e20,self.e21,self.e22 )
868
+ elements[3*2+0] = (self.e10*self.e21 - self.e11*self.e20)
869
+ elements[3*2+1] = -(self.e00*self.e21 - self.e01*self.e20)
870
+ elements[3*2+2] = (self.e00*self.e11 - self.e01*self.e10)
1119
871
 
1120
- det = e00 * elements[4*0+0] + e01 * elements[4*1+0] + e02 * elements[4*2+0] + e03 * elements[4*3+0]
872
+ det = e00 * elements[3*0+0] + e01 * elements[3*1+0] + e02 * elements[3*2+0]
1121
873
 
1122
- if ( det.abs< TOLERANCE )
1123
- raise RuntimeError, "RMtx4invert! : det.abs < TOLERANCE"
874
+ if ( det.abs < TOLERANCE )
875
+ raise RuntimeError, "RMtx3#invert! : det.abs < TOLERANCE"
1124
876
  return nil
1125
877
  end
1126
878
 
1127
879
  d = 1.0 / det
1128
880
 
1129
- setElement( 0, 0, d * elements[4*0+0] )
1130
- setElement( 0, 1, d * elements[4*0+1] )
1131
- setElement( 0, 2, d * elements[4*0+2] )
1132
- setElement( 0, 3, d * elements[4*0+3] )
1133
-
1134
- setElement( 1, 0, d * elements[4*1+0] )
1135
- setElement( 1, 1, d * elements[4*1+1] )
1136
- setElement( 1, 2, d * elements[4*1+2] )
1137
- setElement( 1, 3, d * elements[4*1+3] )
1138
-
1139
- setElement( 2, 0, d * elements[4*2+0] )
1140
- setElement( 2, 1, d * elements[4*2+1] )
1141
- setElement( 2, 2, d * elements[4*2+2] )
1142
- setElement( 2, 3, d * elements[4*2+3] )
1143
-
1144
- setElement( 3, 0, d * elements[4*3+0] )
1145
- setElement( 3, 1, d * elements[4*3+1] )
1146
- setElement( 3, 2, d * elements[4*3+2] )
1147
- setElement( 3, 3, d * elements[4*3+3] )
1148
-
1149
- return self
1150
- end
1151
-
1152
- #
1153
- # call-seq: translation(tx,ty,tz) -> self
1154
- #
1155
- # Makes itself as a translation matrix.
1156
- #
1157
- def translation( tx, ty, tz )
1158
- setIdentity()
1159
- self.e03 = tx
1160
- self.e13 = ty
1161
- self.e23 = tz
881
+ setElement( 0, 0, d * elements[3*0+0] )
882
+ setElement( 0, 1, d * elements[3*0+1] )
883
+ setElement( 0, 2, d * elements[3*0+2] )
884
+ setElement( 1, 0, d * elements[3*1+0] )
885
+ setElement( 1, 1, d * elements[3*1+1] )
886
+ setElement( 1, 2, d * elements[3*1+2] )
887
+ setElement( 2, 0, d * elements[3*2+0] )
888
+ setElement( 2, 1, d * elements[3*2+1] )
889
+ setElement( 2, 2, d * elements[3*2+2] )
1162
890
 
1163
891
  return self
1164
892
  end
@@ -1224,7 +952,7 @@ module RMath3D
1224
952
  #
1225
953
  def rotationAxis( axis, radian )
1226
954
  if ( axis.class != RVec3 )
1227
- raise TypeError, "RMtx4#rotationAxis : Unknown type #{axis.class} given as axis."
955
+ raise TypeError, "RMtx3#rotationAxis : Unknown type #{axis.class} given as axis."
1228
956
  return nil
1229
957
  end
1230
958
  s = Math.sin( radian )
@@ -1234,8 +962,6 @@ module RMath3D
1234
962
  y = axis.y.to_f
1235
963
  z = axis.z.to_f
1236
964
 
1237
- setIdentity()
1238
-
1239
965
  self.e00 = x*x*omc + c
1240
966
  self.e01 = x*y*omc - z*s
1241
967
  self.e02 = z*x*omc + y*s
@@ -1256,7 +982,7 @@ module RMath3D
1256
982
  #
1257
983
  def rotationQuaternion( q )
1258
984
  if ( q.class != RQuat )
1259
- raise TypeError, "RMtx4#rotationQuaternion : Unknown type #{q.class} given as RQuat."
985
+ raise TypeError, "RMtx3#rotationQuaternion : Unknown type #{q.class} given as RQuat."
1260
986
  return nil
1261
987
  end
1262
988
  x = q.x
@@ -1279,8 +1005,6 @@ module RMath3D
1279
1005
  xz2 = x * z2
1280
1006
  wy2 = w * y2
1281
1007
 
1282
- setIdentity()
1283
-
1284
1008
  self.e00 = 1.0 - yy2 - zz2
1285
1009
  self.e10 = xy2 + wz2
1286
1010
  self.e20 = xz2 - wy2
@@ -1308,150 +1032,6 @@ module RMath3D
1308
1032
  return self
1309
1033
  end
1310
1034
 
1311
- #
1312
- # call-seq: lookAtRH(eye,at,up) -> self
1313
- #
1314
- # Builds a viewing matrix for a right-handed coordinate system from:
1315
- # * eye position (+eye+: RVec3)
1316
- # * a point looking at (+at+: RVec3)
1317
- # * up vector (+up+: RVec3)
1318
- #
1319
- def lookAtRH( eye, at, up )
1320
- setIdentity()
1321
-
1322
- axis_z = (eye - at).normalize!
1323
- axis_x = RVec3.cross( up, axis_z ).normalize!
1324
- axis_y = RVec3.cross( axis_z, axis_x )
1325
-
1326
- self.e00 = axis_x[0]
1327
- self.e01 = axis_x[1]
1328
- self.e02 = axis_x[2]
1329
- self.e03 = -RVec3.dot( axis_x, eye )
1330
-
1331
- self.e10 = axis_y[0]
1332
- self.e11 = axis_y[1]
1333
- self.e12 = axis_y[2]
1334
- self.e13 = -RVec3.dot( axis_y, eye )
1335
-
1336
- self.e20 = axis_z[0]
1337
- self.e21 = axis_z[1]
1338
- self.e22 = axis_z[2]
1339
- self.e23 = -RVec3.dot( axis_z, eye )
1340
-
1341
- return self
1342
- end
1343
-
1344
- #
1345
- # call-seq: perspectiveRH(width,height,znear,zfar) -> self
1346
- #
1347
- # Builds a perspective projection matrix for a right-handed coordinate system from:
1348
- # * View volume width (+width+)
1349
- # * View volume height (+height+)
1350
- # * Near clip plane distance (+znear+)
1351
- # * Far clip plane distance (+zfar+)
1352
- #
1353
- def perspectiveRH( width, height, znear, zfar )
1354
- perspectiveOffCenterRH(-width/2.0, width/2.0, -height/2.0, height/2.0, znear, zfar )
1355
- return self
1356
- end
1357
-
1358
- #
1359
- # call-seq: perspectiveFovRH(fovy,aspect,znear,zfar) -> self
1360
- #
1361
- # Builds a perspective projection matrix for a right-handed coordinate system from:
1362
- # * Field of view in y direction (+fovy+ radian)
1363
- # * Aspect ratio (+aspect+)
1364
- # * Near clip plane distance (+znear+)
1365
- # * Far clip plane distance (+zfar+)
1366
- #
1367
- def perspectiveFovRH( fovy_radian, aspect, znear, zfar )
1368
- f = Math::tan( fovy_radian / 2.0 )
1369
- f = 1.0 / f
1370
-
1371
- setIdentity()
1372
- setElement( 0, 0, f / aspect )
1373
- setElement( 1, 1, f )
1374
- setElement( 2, 2, (zfar+znear)/(znear-zfar) )
1375
- setElement( 2, 3, 2*zfar*znear/(znear-zfar) )
1376
- setElement( 3, 2, -1.0 )
1377
- setElement( 3, 3, 0.0 )
1378
-
1379
- return self
1380
- end
1381
-
1382
- #
1383
- # call-seq: perspectiveOffCenterRH(left,right,bottom,top,znear,zfar) -> self
1384
- #
1385
- # Builds a perspective projection matrix for a right-handed coordinate system from:
1386
- # * Minimum value of the view volume width (+left+)
1387
- # * Maximum value of the view volume width (+right+)
1388
- # * Minimum value of the view volume height (+bottom+)
1389
- # * Maximum value of the view volume height (+top+)
1390
- # * Near clip plane distance (+znear+)
1391
- # * Far clip plane distance (+zfar+)
1392
- #
1393
- def perspectiveOffCenterRH( left, right, bottom, top, znear, zfar )
1394
- a = (right+left) / (right-left)
1395
- b = (top+bottom) / (top-bottom)
1396
- c = -(zfar+znear) / (zfar-znear)
1397
- d = -(2*znear*zfar) / (zfar-znear)
1398
-
1399
- setIdentity()
1400
-
1401
- setElement( 0, 0, 2*znear/(right-left) )
1402
- setElement( 0, 2, a )
1403
- setElement( 1, 1, 2*znear/(top-bottom) )
1404
- setElement( 1, 2, b )
1405
- setElement( 2, 2, c )
1406
- setElement( 2, 3, d )
1407
- setElement( 3, 2, -1.0 )
1408
- setElement( 3, 3, 0.0 )
1409
-
1410
- return self
1411
- end
1412
-
1413
- #
1414
- # call-seq: orthoRH(width,height,znear,zfar) -> self
1415
- #
1416
- # Builds a orthogonal projection matrix for a right-handed coordinate system from:
1417
- # * View volume width (+width+)
1418
- # * View volume height (+height+)
1419
- # * Near clip plane distance (+znear+)
1420
- # * Far clip plane distance (+zfar+)
1421
- #
1422
- def orthoRH( width, height, znear, zfar )
1423
- orthoOffCenterRH( -width/2.0, width/2.0, -height/2.0, height/2.0, znear, zfar )
1424
- return self
1425
- end
1426
-
1427
- #
1428
- # call-seq: orthoOffCenterRH(left,right,bottom,top,znear,zfar) -> self
1429
- #
1430
- # Builds a orthogonal projection matrix for a right-handed coordinate system from:
1431
- # * Minimum value of the view volume width (+left+)
1432
- # * Maximum value of the view volume width (+right+)
1433
- # * Minimum value of the view volume height (+bottom+)
1434
- # * Maximum value of the view volume height (+top+)
1435
- # * Near clip plane distance (+znear+)
1436
- # * Far clip plane distance (+zfar+)
1437
- #
1438
- def orthoOffCenterRH( left, right, bottom, top, znear, zfar )
1439
- tx = (right+left) / (right-left)
1440
- ty = (top+bottom) / (top-bottom)
1441
- tz = (zfar+znear) / (zfar-znear)
1442
-
1443
- setIdentity()
1444
-
1445
- setElement( 0, 0, 2.0/(right-left) )
1446
- setElement( 0, 3, tx )
1447
- setElement( 1, 1, 2.0/(top-bottom) )
1448
- setElement( 1, 3, ty )
1449
- setElement( 2, 2, -2.0/(zfar-znear) )
1450
- setElement( 2, 3, tz )
1451
-
1452
- return self
1453
- end
1454
-
1455
1035
  #
1456
1036
  # call-seq: +
1457
1037
  #
@@ -1467,7 +1047,7 @@ module RMath3D
1467
1047
  # -mtx : Unary minus operator.
1468
1048
  #
1469
1049
  def -@
1470
- return RMtx4.new( self * -1.0 )
1050
+ return RMtx3.new( self * -1.0 )
1471
1051
  end
1472
1052
 
1473
1053
  #
@@ -1476,14 +1056,14 @@ module RMath3D
1476
1056
  # mtx1 + mtx2 : Binary plus operator.
1477
1057
  #
1478
1058
  def +( arg )
1479
- if ( arg.class != RMtx4 )
1480
- raise TypeError, "RMtx4#+(arg) : Unknown type #{arg.class} given as RMtx4."
1059
+ if ( arg.class != RMtx3 )
1060
+ raise TypeError, "RMtx3#+(arg) : Unknown type #{arg.class} given as RMtx3."
1481
1061
  return nil
1482
1062
  end
1483
1063
 
1484
- result = RMtx4.new
1485
- for row in 0...4 do
1486
- for col in 0...4 do
1064
+ result = RMtx3.new
1065
+ for row in 0...3 do
1066
+ for col in 0...3 do
1487
1067
  result.setElement( row, col, getElement(row,col) + arg.getElement(row,col) )
1488
1068
  end
1489
1069
  end
@@ -1497,14 +1077,14 @@ module RMath3D
1497
1077
  # mtx1 - mtx2 : Binary minus operator.
1498
1078
  #
1499
1079
  def -( arg )
1500
- if ( arg.class != RMtx4 )
1501
- raise TypeError, "RMtx4#-(arg) : Unknown type #{arg.class} given as RMtx4."
1080
+ if ( arg.class != RMtx3 )
1081
+ raise TypeError, "RMtx3#-(arg) : Unknown type #{arg.class} given as RMtx3."
1502
1082
  return nil
1503
1083
  end
1504
1084
 
1505
- result = RMtx4.new
1506
- for row in 0...4 do
1507
- for col in 0...4 do
1085
+ result = RMtx3.new
1086
+ for row in 0...3 do
1087
+ for col in 0...3 do
1508
1088
  result.setElement( row, col, getElement(row,col) - arg.getElement(row,col) )
1509
1089
  end
1510
1090
  end
@@ -1520,17 +1100,16 @@ module RMath3D
1520
1100
  def *( arg )
1521
1101
  case arg
1522
1102
  when Fixnum, Float, Bignum
1523
- return RMtx4.new( arg*self.e00, arg*self.e01, arg*self.e02, arg*self.e03,
1524
- arg*self.e10, arg*self.e11, arg*self.e12, arg*self.e13,
1525
- arg*self.e20, arg*self.e21, arg*self.e22, arg*self.e23,
1526
- arg*self.e30, arg*self.e31, arg*self.e32, arg*self.e33 )
1103
+ return RMtx3.new( arg*self.e00, arg*self.e01, arg*self.e02,
1104
+ arg*self.e10, arg*self.e11, arg*self.e12,
1105
+ arg*self.e20, arg*self.e21, arg*self.e22 )
1527
1106
 
1528
- when RMtx4
1529
- result = RMtx4.new
1530
- for row in 0...4 do
1531
- for col in 0...4 do
1107
+ when RMtx3
1108
+ result = RMtx3.new
1109
+ for row in 0...3 do
1110
+ for col in 0...3 do
1532
1111
  sum = 0.0
1533
- for i in 0...4 do
1112
+ for i in 0...3 do
1534
1113
  sum += getElement( row, i ) * arg.getElement( i, col )
1535
1114
  end
1536
1115
  result.setElement( row, col, sum )
@@ -1539,7 +1118,7 @@ module RMath3D
1539
1118
  return result
1540
1119
 
1541
1120
  else
1542
- raise TypeError, "RMtx4#*(arg) : Unknown type #{arg.class} given."
1121
+ raise TypeError, "RMtx3#*(arg) : Unknown type #{arg.class} given."
1543
1122
  return nil
1544
1123
  end
1545
1124
  end
@@ -1550,13 +1129,13 @@ module RMath3D
1550
1129
  # mtx1 == mtx2 : evaluates equality.
1551
1130
  #
1552
1131
  def ==( other )
1553
- if ( other.class != RMtx4 )
1554
- raise TypeError, "RMtx4#==(other) : Unknown type #{other.class} given as RMtx4."
1132
+ if ( other.class != RMtx3 )
1133
+ raise TypeError, "RMtx3#==(other) : Unknown type #{other.class} given as RMtx3."
1555
1134
  return nil
1556
1135
  end
1557
1136
 
1558
- for row in 0...4 do
1559
- for col in 0...4 do
1137
+ for row in 0...3 do
1138
+ for col in 0...3 do
1560
1139
  if ( (getElement(row,col) - other.getElement(row,col)).abs > TOLERANCE )
1561
1140
  return false
1562
1141
  end
@@ -1571,14 +1150,14 @@ module RMath3D
1571
1150
  # mtx1 += mtx2 : appends the elements of +mtx2+ into corresponding +mtx1+ elements.
1572
1151
  #
1573
1152
  def add!( other )
1574
- if ( other.class != RMtx4 )
1575
- raise TypeError, "RMtx4#add! : Unknown type #{other.class} given as RMtx4."
1153
+ if ( other.class != RMtx3 )
1154
+ raise TypeError, "RMtx3#add! : Unknown type #{other.class} given as RMtx3."
1576
1155
  return nil
1577
1156
  end
1578
1157
 
1579
- result = RMtx4.new
1580
- for row in 0...4 do
1581
- for col in 0...4 do
1158
+ result = RMtx3.new
1159
+ for row in 0...3 do
1160
+ for col in 0...3 do
1582
1161
  self.setElement( row, col, getElement(row,col) + other.getElement(row,col) )
1583
1162
  end
1584
1163
  end
@@ -1592,14 +1171,14 @@ module RMath3D
1592
1171
  # mtx1 -= mtx2 : subtracts the elements of +mtx2+ from corresponding +mtx1+ elements.
1593
1172
  #
1594
1173
  def sub!( other )
1595
- if ( other.class != RMtx4 )
1596
- raise TypeError, "RMtx4#sub! : Unknown type #{other.class} given as RMtx4."
1174
+ if ( other.class != RMtx3 )
1175
+ raise TypeError, "RMtx3#sub! : Unknown type #{other.class} given as RMtx3."
1597
1176
  return nil
1598
1177
  end
1599
1178
 
1600
- result = RMtx4.new
1601
- for row in 0...4 do
1602
- for col in 0...4 do
1179
+ result = RMtx3.new
1180
+ for row in 0...3 do
1181
+ for col in 0...3 do
1603
1182
  self.setElement( row, col, getElement(row,col) - other.getElement(row,col) )
1604
1183
  end
1605
1184
  end
@@ -1618,31 +1197,20 @@ module RMath3D
1618
1197
  self.e00 = other*self.e00
1619
1198
  self.e01 = other*self.e01
1620
1199
  self.e02 = other*self.e02
1621
- self.e03 = other*self.e03
1622
-
1623
1200
  self.e10 = other*self.e10
1624
1201
  self.e11 = other*self.e11
1625
1202
  self.e12 = other*self.e12
1626
- self.e13 = other*self.e13
1627
-
1628
1203
  self.e20 = other*self.e20
1629
1204
  self.e21 = other*self.e21
1630
1205
  self.e22 = other*self.e22
1631
- self.e23 = other*self.e23
1632
-
1633
- self.e30 = other*self.e30
1634
- self.e31 = other*self.e31
1635
- self.e32 = other*self.e32
1636
- self.e33 = other*self.e33
1637
1206
 
1638
1207
  return self
1639
-
1640
- when RMtx4
1641
- result = RMtx4.new
1642
- for row in 0...4 do
1643
- for col in 0...4 do
1208
+ when RMtx3
1209
+ result = RMtx3.new
1210
+ for row in 0...3 do
1211
+ for col in 0...3 do
1644
1212
  sum = 0.0
1645
- for i in 0...4 do
1213
+ for i in 0...3 do
1646
1214
  sum += getElement( row, i ) * other.getElement( i, col )
1647
1215
  end
1648
1216
  result.setElement( row, col, sum )
@@ -1652,22 +1220,12 @@ module RMath3D
1652
1220
  self.e00 = result.e00
1653
1221
  self.e01 = result.e01
1654
1222
  self.e02 = result.e02
1655
- self.e03 = result.e03
1656
-
1657
1223
  self.e10 = result.e10
1658
1224
  self.e11 = result.e11
1659
1225
  self.e12 = result.e12
1660
- self.e13 = result.e13
1661
-
1662
1226
  self.e20 = result.e20
1663
1227
  self.e21 = result.e21
1664
1228
  self.e22 = result.e22
1665
- self.e23 = result.e23
1666
-
1667
- self.e30 = result.e30
1668
- self.e31 = result.e31
1669
- self.e32 = result.e32
1670
- self.e33 = result.e33
1671
1229
 
1672
1230
  return self
1673
1231
  end
@@ -1675,49 +1233,68 @@ module RMath3D
1675
1233
  end
1676
1234
 
1677
1235
  #
1678
- # Document-class: RMath3D::RQuat
1679
- # provies quaternion arithmetic.
1236
+ # Document-class: RMath3D::RMtx4
1237
+ # provies 4x4 matrix arithmetic.
1680
1238
  #
1681
- class RQuat
1239
+ # <b>Notice</b>
1240
+ # * elements are stored in column-major order.
1241
+ #
1242
+ class RMtx4
1682
1243
 
1683
1244
  #
1684
1245
  # call-seq:
1685
- # RQuat.new -> (0,0,0,0)
1686
- # RQuat.new(e) -> (e,e,e,e)
1687
- # RQuat.new( other ) : Copy Constructor
1688
- # RQuat.new( e0, e1, e2, e3 ) -> (e0,e1,e2,e3)
1246
+ # RMtx4.new -> ((1,0,0,0),(0,1,0,0),(0,0,1,0),(0,0,0,1))
1247
+ # RMtx4.new(e) -> ((e,e,e,e),(e,e,e,e),(e,e,e,e),(e,e,e,e))
1248
+ # RMtx4.new( other ) : Copy Constructor
1249
+ # RMtx4.new( e0, e1, ..., e15 ) -> ((e0,e1,e2,e3),(e4,e5,e6,e7),(e8,e9,e10,e11),(e12,e13,e14,e15))
1689
1250
  #
1690
- # Creates a new quaternion.
1251
+ # Creates a new 4x4 matrix.
1691
1252
  #
1692
1253
  def initialize( *a )
1254
+ # [NOTE] elemetns are stored in column-major order.
1693
1255
  @e = []
1694
1256
  case a.length
1695
1257
  when 0
1696
- @e = [0.0, 0.0, 0.0, 0.0]
1258
+ @e = [ 0.0, 0.0, 0.0, 0.0,
1259
+ 0.0, 0.0, 0.0, 0.0,
1260
+ 0.0, 0.0, 0.0, 0.0,
1261
+ 0.0, 0.0, 0.0, 0.0 ]
1697
1262
  when 1
1698
1263
  case a[0]
1699
1264
  when Fixnum, Float
1700
- @e = [ a[0], a[0], a[0], a[0] ]
1701
- when RQuat
1702
- @e = [ a[0].x, a[0].y, a[0].z, a[0].w ]
1265
+ @e = [ a[0], a[0], a[0], a[0],
1266
+ a[0], a[0], a[0], a[0],
1267
+ a[0], a[0], a[0], a[0],
1268
+ a[0], a[0], a[0], a[0] ]
1269
+ when RMtx4
1270
+ # Copy Constructor
1271
+ @e = [ a[0].e00, a[0].e10, a[0].e20, a[0].e30,
1272
+ a[0].e01, a[0].e11, a[0].e21, a[0].e31,
1273
+ a[0].e02, a[0].e12, a[0].e22, a[0].e32,
1274
+ a[0].e03, a[0].e13, a[0].e23, a[0].e33 ]
1703
1275
  else
1704
- raise TypeError, "RQuat#initialize : Unknown type #{a[0].class}."
1276
+ raise TypeError, "RMtx4#initialize : Unknown type #{a[0].class}."
1705
1277
  return nil
1706
1278
  end
1707
- when 4
1708
- a.each_with_index do |elem, index|
1709
- case elem
1710
- when Fixnum, Float
1711
- @e[index] = elem
1712
- else
1713
- raise TypeError, "RQuat#initialize : Unknown type #{elem.class}."
1714
- return nil
1279
+ when 16
1280
+ # Element-wise setter
1281
+ for row in 0...4 do
1282
+ for col in 0...4 do
1283
+ index = 4*row + col
1284
+ case a[index]
1285
+ when Fixnum, Float
1286
+ setElement( row, col, a[index] )
1287
+ else
1288
+ raise TypeError, "RMtx4#initialize : Unknown type #{a[0].class}."
1289
+ return nil
1290
+ end
1715
1291
  end
1716
1292
  end
1717
1293
  else
1718
- raise RuntimeError, "RQuat#initialize : wrong # of arguments (#{a.length})"
1294
+ raise RuntimeError, "RMtx4#initialize : wrong # of arguments (#{a.length})"
1719
1295
  return nil
1720
1296
  end
1297
+
1721
1298
  return self
1722
1299
  end
1723
1300
 
@@ -1727,7 +1304,10 @@ module RMath3D
1727
1304
  # Returns human-readable string.
1728
1305
  #
1729
1306
  def to_s
1730
- return "( #{@e[0]}, #{@e[1]}, #{@e[2]}, #{@e[3]} )\n"
1307
+ "( #{@e[0]}, #{@e[4]}, #{@e[8]}, #{@e[12]} )\n" +
1308
+ "( #{@e[1]}, #{@e[5]}, #{@e[9]}, #{@e[13]} )\n" +
1309
+ "( #{@e[2]}, #{@e[6]}, #{@e[10]}, #{@e[14]} )\n" +
1310
+ "( #{@e[3]}, #{@e[7]}, #{@e[11]}, #{@e[15]} )\n"
1731
1311
  end
1732
1312
 
1733
1313
  #
@@ -1744,266 +1324,1683 @@ module RMath3D
1744
1324
  #
1745
1325
  # Resolves type mismatch.
1746
1326
  #
1747
- def coerce( arg )
1327
+ def coerce
1748
1328
  case arg
1749
1329
  when Fixnum, Float, Bignum
1750
1330
  return [ self, arg ]
1751
1331
  else
1752
- raise TypeError, "RQuat#coerce : #{arg.self} can't be coerced into #{self.class}."
1332
+ raise TypeError, "RMtx4#coerce : #{arg.self} can't be coerced into #{self.class}."
1753
1333
  return nil
1754
1334
  end
1755
1335
  end
1756
1336
 
1757
1337
  #
1758
- # call-seq: setElements( e0, e1, e2, e3 )
1338
+ # call-seq: setElements( e0, e1, ..., e15 )
1759
1339
  #
1760
- # Stores given 4 new values.
1340
+ # Stores given 16 new values.
1761
1341
  #
1762
- def setElements( x, y, z, w )
1763
- self.x = x
1764
- self.y = y
1765
- self.z = z
1766
- self.w = w
1342
+ def setElements( *a )
1343
+ if a.length != 16
1344
+ raise RuntimeError, "RMtx4#setElements : wrong # of arguments (#{a.length})"
1345
+ return nil
1346
+ end
1347
+
1348
+ for row in 0...4 do
1349
+ for col in 0...4 do
1350
+ index = 4*row + col
1351
+ setElement( row, col, a[index] )
1352
+ end
1353
+ end
1767
1354
  end
1768
1355
 
1769
1356
  #
1770
- # call-seq: quat[i]= value
1357
+ # call-seq: [row,col]= value
1771
1358
  #
1772
- # Stores +value+ at +i+.
1359
+ # Stores +value+ at (+row+,+col+).
1773
1360
  #
1774
- def []=(i,value)
1775
- @e[i] = value
1361
+ def []=(row,col,value)
1362
+ # [NOTE] elemetns are stored in column-major order.
1363
+ @e[col*4+row] = value
1776
1364
  end
1365
+ alias_method :setElement, :'[]='
1777
1366
 
1778
1367
  #
1779
- # call-seq: x= value
1368
+ # call-seq: [row,col] -> value
1780
1369
  #
1781
- # Stores +value+ as +x+.
1370
+ # Returns the element at (+row+,+col+).
1782
1371
  #
1783
- def x=(value) @e[0] = value end
1372
+ def [](row,col)
1373
+ # [NOTE] elemetns are stored in column-major order.
1374
+ return @e[col*4+row]
1375
+ end
1376
+ alias_method :getElement, :'[]'
1377
+
1378
+ # Returns the element at row 0 and column 0.
1379
+ def e00() getElement(0,0) end
1380
+ # Returns the element at row 0 and column 1.
1381
+ def e01() getElement(0,1) end
1382
+ # Returns the element at row 0 and column 2.
1383
+ def e02() getElement(0,2) end
1384
+ # Returns the element at row 0 and column 3.
1385
+ def e03() getElement(0,3) end
1386
+ # Returns the element at row 1 and column 0.
1387
+ def e10() getElement(1,0) end
1388
+ # Returns the element at row 1 and column 1.
1389
+ def e11() getElement(1,1) end
1390
+ # Returns the element at row 1 and column 2.
1391
+ def e12() getElement(1,2) end
1392
+ # Returns the element at row 1 and column 3.
1393
+ def e13() getElement(1,3) end
1394
+ # Returns the element at row 2 and column 0.
1395
+ def e20() getElement(2,0) end
1396
+ # Returns the element at row 2 and column 1.
1397
+ def e21() getElement(2,1) end
1398
+ # Returns the element at row 2 and column 2.
1399
+ def e22() getElement(2,2) end
1400
+ # Returns the element at row 2 and column 3.
1401
+ def e23() getElement(2,3) end
1402
+ # Returns the element at row 3 and column 0.
1403
+ def e30() getElement(3,0) end
1404
+ # Returns the element at row 3 and column 1.
1405
+ def e31() getElement(3,1) end
1406
+ # Returns the element at row 3 and column 2.
1407
+ def e32() getElement(3,2) end
1408
+ # Returns the element at row 3 and column 3.
1409
+ def e33() getElement(3,3) end
1410
+
1411
+ # Replaces the element at row 0 and column 0 by +value+.
1412
+ def e00=(value) setElement(0,0,value) end
1413
+ # Replaces the element at row 0 and column 1 by +value+.
1414
+ def e01=(value) setElement(0,1,value) end
1415
+ # Replaces the element at row 0 and column 2 by +value+.
1416
+ def e02=(value) setElement(0,2,value) end
1417
+ # Replaces the element at row 0 and column 3 by +value+.
1418
+ def e03=(value) setElement(0,3,value) end
1419
+ # Replaces the element at row 1 and column 0 by +value+.
1420
+ def e10=(value) setElement(1,0,value) end
1421
+ # Replaces the element at row 1 and column 1 by +value+.
1422
+ def e11=(value) setElement(1,1,value) end
1423
+ # Replaces the element at row 1 and column 2 by +value+.
1424
+ def e12=(value) setElement(1,2,value) end
1425
+ # Replaces the element at row 1 and column 3 by +value+.
1426
+ def e13=(value) setElement(1,3,value) end
1427
+ # Replaces the element at row 2 and column 0 by +value+.
1428
+ def e20=(value) setElement(2,0,value) end
1429
+ # Replaces the element at row 2 and column 1 by +value+.
1430
+ def e21=(value) setElement(2,1,value) end
1431
+ # Replaces the element at row 2 and column 2 by +value+.
1432
+ def e22=(value) setElement(2,2,value) end
1433
+ # Replaces the element at row 2 and column 3 by +value+.
1434
+ def e23=(value) setElement(2,3,value) end
1435
+ # Replaces the element at row 3 and column 0 by +value+.
1436
+ def e30=(value) setElement(3,0,value) end
1437
+ # Replaces the element at row 3 and column 1 by +value+.
1438
+ def e31=(value) setElement(3,1,value) end
1439
+ # Replaces the element at row 3 and column 2 by +value+.
1440
+ def e32=(value) setElement(3,2,value) end
1441
+ # Replaces the element at row 3 and column 3 by +value+.
1442
+ def e33=(value) setElement(3,3,value) end
1784
1443
 
1785
1444
  #
1786
- # call-seq: y= value
1445
+ # call-seq: mtx4.getRow(r) -> RVec4
1787
1446
  #
1788
- # Stores +value+ as +y+.
1447
+ # Returns +r+-th row vector.
1789
1448
  #
1790
- def y=(value) @e[1] = value end
1449
+ def getRow( row )
1450
+ return RVec4.new( self[row,0], self[row,1], self[row,2], self[row,3] )
1451
+ end
1791
1452
 
1792
1453
  #
1793
- # call-seq: z= value
1454
+ # call-seq: mtx4.getColumn(c) -> RVec4
1794
1455
  #
1795
- # Stores +value+ as +z+.
1456
+ # Returns +c+-th column vector.
1796
1457
  #
1797
- def z=(value) @e[2] = value end
1458
+ def getColumn( column )
1459
+ return RVec4.new( self[0,column], self[1,column], self[2,column], self[3,column] )
1460
+ end
1461
+
1462
+ #
1463
+ # call-seq: mtx4.setRow(v,r)
1464
+ #
1465
+ # Returns sets +r+-th row by vector +v+.
1466
+ #
1467
+ def setRow( v, row )
1468
+ self[row,0] = v.x
1469
+ self[row,1] = v.y
1470
+ self[row,2] = v.z
1471
+ self[row,3] = v.w
1472
+ end
1473
+
1474
+ #
1475
+ # call-seq: mtx4.setColumn(v,c)
1476
+ #
1477
+ # Returns sets +c+-th column by vector +v+.
1478
+ #
1479
+ def setColumn( v, column )
1480
+ self[0,column] = v.x
1481
+ self[1,column] = v.y
1482
+ self[2,column] = v.z
1483
+ self[3,column] = v.w
1484
+ end
1485
+
1486
+ def getUpper3x3
1487
+ return RMtx3.new( self.e00, self.e01, self.e02,
1488
+ self.e10, self.e11, self.e12,
1489
+ self.e20, self.e21, self.e22 )
1490
+ end
1491
+
1492
+ def setUpper3x3( mtx3x3 )
1493
+ self.e00 = mtx3x3.e00
1494
+ self.e01 = mtx3x3.e01
1495
+ self.e02 = mtx3x3.e02
1496
+ self.e10 = mtx3x3.e10
1497
+ self.e11 = mtx3x3.e11
1498
+ self.e12 = mtx3x3.e12
1499
+ self.e20 = mtx3x3.e20
1500
+ self.e21 = mtx3x3.e21
1501
+ self.e22 = mtx3x3.e22
1502
+
1503
+ return self
1504
+ end
1505
+
1506
+ # call-seq: setZero
1507
+ #
1508
+ # Clears all elements by 0.0
1509
+ #
1510
+ def setZero
1511
+ 16.times do |i|
1512
+ @e[i] = 0.0
1513
+ end
1514
+ return self
1515
+ end
1516
+
1517
+ #
1518
+ # call-seq: setIdentity
1519
+ #
1520
+ # Sets as identity matrix.
1521
+ #
1522
+ def setIdentity
1523
+ for row in 0...4 do
1524
+ for col in 0...4 do
1525
+ index = 4*row + col
1526
+ if ( row == col )
1527
+ setElement( row, col, 1.0 )
1528
+ else
1529
+ setElement( row, col, 0.0 )
1530
+ end
1531
+ end
1532
+ end
1533
+ return self
1534
+ end
1535
+
1536
+ def det3( _e00,_e01,_e02, _e10,_e11,_e12, _e20,_e21,_e22 )
1537
+ _e00 * (_e11*_e22 - _e12*_e21) -
1538
+ _e01 * (_e10*_e22 - _e12*_e20) +
1539
+ _e02 * (_e10*_e21 - _e11*_e20)
1540
+ end
1541
+ private :det3
1542
+
1543
+ #
1544
+ # call-seq: getDeterminant -> determinant
1545
+ #
1546
+ # Calculates determinant.
1547
+ #
1548
+ def getDeterminant
1549
+ e00 * det3( e11,e12,e13, e21,e22,e23, e31,e32,e33 ) -
1550
+ e01 * det3( e10,e12,e13, e20,e22,e23, e30,e32,e33 ) +
1551
+ e02 * det3( e10,e11,e13, e20,e21,e23, e30,e31,e33 ) -
1552
+ e03 * det3( e10,e11,e12, e20,e21,e22, e30,e31,e32 )
1553
+ end
1554
+
1555
+ #
1556
+ # call-seq: getTransposed
1557
+ #
1558
+ # Returns transposed matrix.
1559
+ #
1560
+ def getTransposed
1561
+ return RMtx4.new( @e[ 0], @e[ 1], @e[ 2], @e[ 3],
1562
+ @e[ 4], @e[ 5], @e[ 6], @e[ 7],
1563
+ @e[ 8], @e[ 9], @e[10], @e[11],
1564
+ @e[12], @e[13], @e[14], @e[15] )
1565
+ end
1566
+
1567
+ #
1568
+ # call-seq: transpose!
1569
+ #
1570
+ # Transposeas its elements.
1571
+ #
1572
+ def transpose!
1573
+ @e[ 1], @e[ 4] = @e[ 4], @e[ 1]
1574
+ @e[ 2], @e[ 8] = @e[ 8], @e[ 2]
1575
+ @e[ 3], @e[12] = @e[12], @e[ 3]
1576
+ @e[ 6], @e[ 9] = @e[ 9], @e[ 6]
1577
+ @e[ 7], @e[13] = @e[13], @e[ 7]
1578
+ @e[11], @e[14] = @e[14], @e[11]
1579
+ end
1580
+
1581
+ #
1582
+ # call-seq: getInverse -> inverse
1583
+ #
1584
+ # Returns the inverse.
1585
+ #
1586
+ def getInverse
1587
+ result = RMtx4.new
1588
+
1589
+ result.e00 = det3( e11,e12,e13, e21,e22,e23, e31,e32,e33 )
1590
+ result.e01 = -det3( e01,e02,e03, e21,e22,e23, e31,e32,e33 )
1591
+ result.e02 = det3( e01,e02,e03, e11,e12,e13, e31,e32,e33 )
1592
+ result.e03 = -det3( e01,e02,e03, e11,e12,e13, e21,e22,e23 )
1593
+
1594
+ result.e10 = -det3( e10,e12,e13, e20,e22,e23, e30,e32,e33 )
1595
+ result.e11 = det3( e00,e02,e03, e20,e22,e23, e30,e32,e33 )
1596
+ result.e12 = -det3( e00,e02,e03, e10,e12,e13, e30,e32,e33 )
1597
+ result.e13 = det3( e00,e02,e03, e10,e12,e13, e20,e22,e23 )
1598
+
1599
+ result.e20 = det3( e10,e11,e13, e20,e21,e23, e30,e31,e33 )
1600
+ result.e21 = -det3( e00,e01,e03, e20,e21,e23, e30,e31,e33 )
1601
+ result.e22 = det3( e00,e01,e03, e10,e11,e13, e30,e31,e33 )
1602
+ result.e23 = -det3( e00,e01,e03, e10,e11,e13, e20,e21,e23 )
1603
+
1604
+ result.e30 = -det3( e10,e11,e12, e20,e21,e22, e30,e31,e32 )
1605
+ result.e31 = det3( e00,e01,e02, e20,e21,e22, e30,e31,e32 )
1606
+ result.e32 = -det3( e00,e01,e02, e10,e11,e12, e30,e31,e32 )
1607
+ result.e33 = det3( e00,e01,e02, e10,e11,e12, e20,e21,e22 )
1608
+
1609
+ det = e00 * result.e00 + e01 * result.e10 + e02 * result.e20 + e03 * result.e30
1610
+
1611
+ if ( det.abs < TOLERANCE )
1612
+ raise RuntimeError, "RMtx4#getInverse : det.abs < TOLERANCE"
1613
+ return nil
1614
+ end
1615
+
1616
+ d = 1.0 / det
1617
+
1618
+ result.mul!( d )
1619
+
1620
+ return result
1621
+ end
1622
+
1623
+ #
1624
+ # call-seq: invert! -> self
1625
+ #
1626
+ # Makes itself as the inverse of the original matrix.
1627
+ #
1628
+ def invert!
1629
+ elements = Array.new( 16 )
1630
+
1631
+ elements[4*0+0] = det3( self.e11,self.e12,self.e13, self.e21,self.e22,self.e23, self.e31,self.e32,self.e33 )
1632
+ elements[4*0+1] = -det3( self.e01,self.e02,self.e03, self.e21,self.e22,self.e23, self.e31,self.e32,self.e33 )
1633
+ elements[4*0+2] = det3( self.e01,self.e02,self.e03, self.e11,self.e12,self.e13, self.e31,self.e32,self.e33 )
1634
+ elements[4*0+3] = -det3( self.e01,self.e02,self.e03, self.e11,self.e12,self.e13, self.e21,self.e22,self.e23 )
1635
+
1636
+ elements[4*1+0] = -det3( self.e10,self.e12,self.e13, self.e20,self.e22,self.e23, self.e30,self.e32,self.e33 )
1637
+ elements[4*1+1] = det3( self.e00,self.e02,self.e03, self.e20,self.e22,self.e23, self.e30,self.e32,self.e33 )
1638
+ elements[4*1+2] = -det3( self.e00,self.e02,self.e03, self.e10,self.e12,self.e13, self.e30,self.e32,self.e33 )
1639
+ elements[4*1+3] = det3( self.e00,self.e02,self.e03, self.e10,self.e12,self.e13, self.e20,self.e22,self.e23 )
1640
+
1641
+ elements[4*2+0] = det3( self.e10,self.e11,self.e13, self.e20,self.e21,self.e23, self.e30,self.e31,self.e33 )
1642
+ elements[4*2+1] = -det3( self.e00,self.e01,self.e03, self.e20,self.e21,self.e23, self.e30,self.e31,self.e33 )
1643
+ elements[4*2+2] = det3( self.e00,self.e01,self.e03, self.e10,self.e11,self.e13, self.e30,self.e31,self.e33 )
1644
+ elements[4*2+3] = -det3( self.e00,self.e01,self.e03, self.e10,self.e11,self.e13, self.e20,self.e21,self.e23 )
1645
+
1646
+ elements[4*3+0] = -det3( self.e10,self.e11,self.e12, self.e20,self.e21,self.e22, self.e30,self.e31,self.e32 )
1647
+ elements[4*3+1] = det3( self.e00,self.e01,self.e02, self.e20,self.e21,self.e22, self.e30,self.e31,self.e32 )
1648
+ elements[4*3+2] = -det3( self.e00,self.e01,self.e02, self.e10,self.e11,self.e12, self.e30,self.e31,self.e32 )
1649
+ elements[4*3+3] = det3( self.e00,self.e01,self.e02, self.e10,self.e11,self.e12, self.e20,self.e21,self.e22 )
1650
+
1651
+ det = e00 * elements[4*0+0] + e01 * elements[4*1+0] + e02 * elements[4*2+0] + e03 * elements[4*3+0]
1652
+
1653
+ if ( det.abs< TOLERANCE )
1654
+ raise RuntimeError, "RMtx4invert! : det.abs < TOLERANCE"
1655
+ return nil
1656
+ end
1657
+
1658
+ d = 1.0 / det
1659
+
1660
+ setElement( 0, 0, d * elements[4*0+0] )
1661
+ setElement( 0, 1, d * elements[4*0+1] )
1662
+ setElement( 0, 2, d * elements[4*0+2] )
1663
+ setElement( 0, 3, d * elements[4*0+3] )
1664
+
1665
+ setElement( 1, 0, d * elements[4*1+0] )
1666
+ setElement( 1, 1, d * elements[4*1+1] )
1667
+ setElement( 1, 2, d * elements[4*1+2] )
1668
+ setElement( 1, 3, d * elements[4*1+3] )
1669
+
1670
+ setElement( 2, 0, d * elements[4*2+0] )
1671
+ setElement( 2, 1, d * elements[4*2+1] )
1672
+ setElement( 2, 2, d * elements[4*2+2] )
1673
+ setElement( 2, 3, d * elements[4*2+3] )
1674
+
1675
+ setElement( 3, 0, d * elements[4*3+0] )
1676
+ setElement( 3, 1, d * elements[4*3+1] )
1677
+ setElement( 3, 2, d * elements[4*3+2] )
1678
+ setElement( 3, 3, d * elements[4*3+3] )
1679
+
1680
+ return self
1681
+ end
1682
+
1683
+ #
1684
+ # call-seq: translation(tx,ty,tz) -> self
1685
+ #
1686
+ # Makes itself as a translation matrix.
1687
+ #
1688
+ def translation( tx, ty, tz )
1689
+ setIdentity()
1690
+ self.e03 = tx
1691
+ self.e13 = ty
1692
+ self.e23 = tz
1693
+
1694
+ return self
1695
+ end
1696
+
1697
+ #
1698
+ # call-seq: rotationX(radian) -> self
1699
+ #
1700
+ # Makes a matrix that rotates around the x-axis.
1701
+ #
1702
+ def rotationX( radian )
1703
+ s = Math.sin( radian )
1704
+ c = Math.cos( radian )
1705
+
1706
+ setIdentity()
1707
+ self.e11 = c
1708
+ self.e12 = -s
1709
+ self.e21 = s
1710
+ self.e22 = c
1711
+
1712
+ return self
1713
+ end
1714
+
1715
+ #
1716
+ # call-seq: rotationY(radian) -> self
1717
+ #
1718
+ # Makes a matrix that rotates around the y-axis.
1719
+ #
1720
+ def rotationY( radian )
1721
+ s = Math.sin( radian )
1722
+ c = Math.cos( radian )
1723
+
1724
+ setIdentity()
1725
+ self.e00 = c
1726
+ self.e02 = s
1727
+ self.e20 = -s
1728
+ self.e22 = c
1729
+
1730
+ return self
1731
+ end
1732
+
1733
+ #
1734
+ # call-seq: rotationZ(radian) -> self
1735
+ #
1736
+ # Makes a matrix that rotates around the z-axis.
1737
+ #
1738
+ def rotationZ( radian )
1739
+ s = Math.sin( radian )
1740
+ c = Math.cos( radian )
1741
+
1742
+ setIdentity()
1743
+ self.e00 = c
1744
+ self.e01 = -s
1745
+ self.e10 = s
1746
+ self.e11 = c
1747
+
1748
+ return self
1749
+ end
1750
+
1751
+ #
1752
+ # call-seq: rotationAxis(axis,radian) -> self
1753
+ #
1754
+ # Makes a matrix that rotates around the +axis+.
1755
+ #
1756
+ def rotationAxis( axis, radian )
1757
+ if ( axis.class != RVec3 )
1758
+ raise TypeError, "RMtx4#rotationAxis : Unknown type #{axis.class} given as axis."
1759
+ return nil
1760
+ end
1761
+ s = Math.sin( radian )
1762
+ c = Math.cos( radian )
1763
+ omc = 1.0 - c
1764
+ x = axis.x.to_f
1765
+ y = axis.y.to_f
1766
+ z = axis.z.to_f
1767
+
1768
+ setIdentity()
1769
+
1770
+ self.e00 = x*x*omc + c
1771
+ self.e01 = x*y*omc - z*s
1772
+ self.e02 = z*x*omc + y*s
1773
+ self.e10 = x*y*omc + z*s
1774
+ self.e11 = y*y*omc + c
1775
+ self.e12 = y*z*omc - x*s
1776
+ self.e20 = z*x*omc - y*s
1777
+ self.e21 = y*z*omc + x*s
1778
+ self.e22 = z*z*omc + c
1779
+
1780
+ return self
1781
+ end
1782
+
1783
+ #
1784
+ # call-seq: rotationQuaternion(q) -> self
1785
+ #
1786
+ # Makes a rotation matrix from a normalized quaternion +q+.
1787
+ #
1788
+ def rotationQuaternion( q )
1789
+ if ( q.class != RQuat )
1790
+ raise TypeError, "RMtx4#rotationQuaternion : Unknown type #{q.class} given as RQuat."
1791
+ return nil
1792
+ end
1793
+ x = q.x
1794
+ y = q.y
1795
+ z = q.z
1796
+ w = q.w
1797
+
1798
+ x2 = 2.0 * x
1799
+ y2 = 2.0 * y
1800
+ z2 = 2.0 * z
1801
+
1802
+ xx2 = x * x2
1803
+ yy2 = y * y2
1804
+ zz2 = z * z2
1805
+
1806
+ yz2 = y * z2
1807
+ wx2 = w * x2
1808
+ xy2 = x * y2
1809
+ wz2 = w * z2
1810
+ xz2 = x * z2
1811
+ wy2 = w * y2
1812
+
1813
+ setIdentity()
1814
+
1815
+ self.e00 = 1.0 - yy2 - zz2
1816
+ self.e10 = xy2 + wz2
1817
+ self.e20 = xz2 - wy2
1818
+ self.e01 = xy2 - wz2
1819
+ self.e11 = 1.0 - xx2 - zz2
1820
+ self.e21 = yz2 + wx2
1821
+ self.e02 = xz2 + wy2
1822
+ self.e12 = yz2 - wx2
1823
+ self.e22 = 1.0 - xx2 - yy2
1824
+
1825
+ return self
1826
+ end
1827
+
1828
+ #
1829
+ # call-seq: scaling(sx,sy,sz) -> self
1830
+ #
1831
+ # Makes itself as a scaling matrix.
1832
+ #
1833
+ def scaling( sx, sy, sz )
1834
+ setIdentity()
1835
+ setElement( 0, 0, sx )
1836
+ setElement( 1, 1, sy )
1837
+ setElement( 2, 2, sz )
1838
+
1839
+ return self
1840
+ end
1841
+
1842
+ #
1843
+ # call-seq: lookAtRH(eye,at,up) -> self
1844
+ #
1845
+ # Builds a viewing matrix for a right-handed coordinate system from:
1846
+ # * eye position (+eye+: RVec3)
1847
+ # * a point looking at (+at+: RVec3)
1848
+ # * up vector (+up+: RVec3)
1849
+ #
1850
+ def lookAtRH( eye, at, up )
1851
+ setIdentity()
1852
+
1853
+ axis_z = (eye - at).normalize!
1854
+ axis_x = RVec3.cross( up, axis_z ).normalize!
1855
+ axis_y = RVec3.cross( axis_z, axis_x )
1856
+
1857
+ self.e00 = axis_x[0]
1858
+ self.e01 = axis_x[1]
1859
+ self.e02 = axis_x[2]
1860
+ self.e03 = -RVec3.dot( axis_x, eye )
1861
+
1862
+ self.e10 = axis_y[0]
1863
+ self.e11 = axis_y[1]
1864
+ self.e12 = axis_y[2]
1865
+ self.e13 = -RVec3.dot( axis_y, eye )
1866
+
1867
+ self.e20 = axis_z[0]
1868
+ self.e21 = axis_z[1]
1869
+ self.e22 = axis_z[2]
1870
+ self.e23 = -RVec3.dot( axis_z, eye )
1871
+
1872
+ return self
1873
+ end
1874
+
1875
+ #
1876
+ # call-seq: perspectiveRH(width,height,znear,zfar) -> self
1877
+ #
1878
+ # Builds a perspective projection matrix for a right-handed coordinate system from:
1879
+ # * View volume width (+width+)
1880
+ # * View volume height (+height+)
1881
+ # * Near clip plane distance (+znear+)
1882
+ # * Far clip plane distance (+zfar+)
1883
+ #
1884
+ def perspectiveRH( width, height, znear, zfar )
1885
+ perspectiveOffCenterRH(-width/2.0, width/2.0, -height/2.0, height/2.0, znear, zfar )
1886
+ return self
1887
+ end
1888
+
1889
+ #
1890
+ # call-seq: perspectiveFovRH(fovy,aspect,znear,zfar) -> self
1891
+ #
1892
+ # Builds a perspective projection matrix for a right-handed coordinate system from:
1893
+ # * Field of view in y direction (+fovy+ radian)
1894
+ # * Aspect ratio (+aspect+)
1895
+ # * Near clip plane distance (+znear+)
1896
+ # * Far clip plane distance (+zfar+)
1897
+ #
1898
+ def perspectiveFovRH( fovy_radian, aspect, znear, zfar )
1899
+ f = Math::tan( fovy_radian / 2.0 )
1900
+ f = 1.0 / f
1901
+
1902
+ setIdentity()
1903
+ setElement( 0, 0, f / aspect )
1904
+ setElement( 1, 1, f )
1905
+ setElement( 2, 2, (zfar+znear)/(znear-zfar) )
1906
+ setElement( 2, 3, 2*zfar*znear/(znear-zfar) )
1907
+ setElement( 3, 2, -1.0 )
1908
+ setElement( 3, 3, 0.0 )
1909
+
1910
+ return self
1911
+ end
1912
+
1913
+ #
1914
+ # call-seq: perspectiveOffCenterRH(left,right,bottom,top,znear,zfar) -> self
1915
+ #
1916
+ # Builds a perspective projection matrix for a right-handed coordinate system from:
1917
+ # * Minimum value of the view volume width (+left+)
1918
+ # * Maximum value of the view volume width (+right+)
1919
+ # * Minimum value of the view volume height (+bottom+)
1920
+ # * Maximum value of the view volume height (+top+)
1921
+ # * Near clip plane distance (+znear+)
1922
+ # * Far clip plane distance (+zfar+)
1923
+ #
1924
+ def perspectiveOffCenterRH( left, right, bottom, top, znear, zfar )
1925
+ a = (right+left) / (right-left)
1926
+ b = (top+bottom) / (top-bottom)
1927
+ c = -(zfar+znear) / (zfar-znear)
1928
+ d = -(2*znear*zfar) / (zfar-znear)
1929
+
1930
+ setIdentity()
1931
+
1932
+ setElement( 0, 0, 2*znear/(right-left) )
1933
+ setElement( 0, 2, a )
1934
+ setElement( 1, 1, 2*znear/(top-bottom) )
1935
+ setElement( 1, 2, b )
1936
+ setElement( 2, 2, c )
1937
+ setElement( 2, 3, d )
1938
+ setElement( 3, 2, -1.0 )
1939
+ setElement( 3, 3, 0.0 )
1940
+
1941
+ return self
1942
+ end
1943
+
1944
+ #
1945
+ # call-seq: orthoRH(width,height,znear,zfar) -> self
1946
+ #
1947
+ # Builds a orthogonal projection matrix for a right-handed coordinate system from:
1948
+ # * View volume width (+width+)
1949
+ # * View volume height (+height+)
1950
+ # * Near clip plane distance (+znear+)
1951
+ # * Far clip plane distance (+zfar+)
1952
+ #
1953
+ def orthoRH( width, height, znear, zfar )
1954
+ orthoOffCenterRH( -width/2.0, width/2.0, -height/2.0, height/2.0, znear, zfar )
1955
+ return self
1956
+ end
1957
+
1958
+ #
1959
+ # call-seq: orthoOffCenterRH(left,right,bottom,top,znear,zfar) -> self
1960
+ #
1961
+ # Builds a orthogonal projection matrix for a right-handed coordinate system from:
1962
+ # * Minimum value of the view volume width (+left+)
1963
+ # * Maximum value of the view volume width (+right+)
1964
+ # * Minimum value of the view volume height (+bottom+)
1965
+ # * Maximum value of the view volume height (+top+)
1966
+ # * Near clip plane distance (+znear+)
1967
+ # * Far clip plane distance (+zfar+)
1968
+ #
1969
+ def orthoOffCenterRH( left, right, bottom, top, znear, zfar )
1970
+ tx = (right+left) / (right-left)
1971
+ ty = (top+bottom) / (top-bottom)
1972
+ tz = (zfar+znear) / (zfar-znear)
1973
+
1974
+ setIdentity()
1975
+
1976
+ setElement( 0, 0, 2.0/(right-left) )
1977
+ setElement( 0, 3, tx )
1978
+ setElement( 1, 1, 2.0/(top-bottom) )
1979
+ setElement( 1, 3, ty )
1980
+ setElement( 2, 2, -2.0/(zfar-znear) )
1981
+ setElement( 2, 3, tz )
1982
+
1983
+ return self
1984
+ end
1985
+
1986
+ #
1987
+ # call-seq: +
1988
+ #
1989
+ # +mtx : Unary plus operator.
1990
+ #
1991
+ def +@
1992
+ return self
1993
+ end
1994
+
1995
+ #
1996
+ # call-seq: -
1997
+ #
1998
+ # -mtx : Unary minus operator.
1999
+ #
2000
+ def -@
2001
+ return RMtx4.new( self * -1.0 )
2002
+ end
2003
+
2004
+ #
2005
+ # call-seq: +
2006
+ #
2007
+ # mtx1 + mtx2 : Binary plus operator.
2008
+ #
2009
+ def +( arg )
2010
+ if ( arg.class != RMtx4 )
2011
+ raise TypeError, "RMtx4#+(arg) : Unknown type #{arg.class} given as RMtx4."
2012
+ return nil
2013
+ end
2014
+
2015
+ result = RMtx4.new
2016
+ for row in 0...4 do
2017
+ for col in 0...4 do
2018
+ result.setElement( row, col, getElement(row,col) + arg.getElement(row,col) )
2019
+ end
2020
+ end
2021
+
2022
+ return result
2023
+ end
2024
+
2025
+ #
2026
+ # call-seq: -
2027
+ #
2028
+ # mtx1 - mtx2 : Binary minus operator.
2029
+ #
2030
+ def -( arg )
2031
+ if ( arg.class != RMtx4 )
2032
+ raise TypeError, "RMtx4#-(arg) : Unknown type #{arg.class} given as RMtx4."
2033
+ return nil
2034
+ end
2035
+
2036
+ result = RMtx4.new
2037
+ for row in 0...4 do
2038
+ for col in 0...4 do
2039
+ result.setElement( row, col, getElement(row,col) - arg.getElement(row,col) )
2040
+ end
2041
+ end
2042
+
2043
+ return result
2044
+ end
2045
+
2046
+ #
2047
+ # call-seq: *
2048
+ #
2049
+ # mtx1 * mtx2 : Binary multiply operator.
2050
+ #
2051
+ def *( arg )
2052
+ case arg
2053
+ when Fixnum, Float, Bignum
2054
+ return RMtx4.new( arg*self.e00, arg*self.e01, arg*self.e02, arg*self.e03,
2055
+ arg*self.e10, arg*self.e11, arg*self.e12, arg*self.e13,
2056
+ arg*self.e20, arg*self.e21, arg*self.e22, arg*self.e23,
2057
+ arg*self.e30, arg*self.e31, arg*self.e32, arg*self.e33 )
2058
+
2059
+ when RMtx4
2060
+ result = RMtx4.new
2061
+ for row in 0...4 do
2062
+ for col in 0...4 do
2063
+ sum = 0.0
2064
+ for i in 0...4 do
2065
+ sum += getElement( row, i ) * arg.getElement( i, col )
2066
+ end
2067
+ result.setElement( row, col, sum )
2068
+ end
2069
+ end
2070
+ return result
2071
+
2072
+ else
2073
+ raise TypeError, "RMtx4#*(arg) : Unknown type #{arg.class} given."
2074
+ return nil
2075
+ end
2076
+ end
2077
+
2078
+ #
2079
+ # call-seq: ==
2080
+ #
2081
+ # mtx1 == mtx2 : evaluates equality.
2082
+ #
2083
+ def ==( other )
2084
+ if ( other.class != RMtx4 )
2085
+ raise TypeError, "RMtx4#==(other) : Unknown type #{other.class} given as RMtx4."
2086
+ return nil
2087
+ end
2088
+
2089
+ for row in 0...4 do
2090
+ for col in 0...4 do
2091
+ if ( (getElement(row,col) - other.getElement(row,col)).abs > TOLERANCE )
2092
+ return false
2093
+ end
2094
+ end
2095
+ end
2096
+ return true
2097
+ end
2098
+
2099
+ #
2100
+ # call-seq: mtx1.add!( mtx2 )
2101
+ #
2102
+ # mtx1 += mtx2 : appends the elements of +mtx2+ into corresponding +mtx1+ elements.
2103
+ #
2104
+ def add!( other )
2105
+ if ( other.class != RMtx4 )
2106
+ raise TypeError, "RMtx4#add! : Unknown type #{other.class} given as RMtx4."
2107
+ return nil
2108
+ end
2109
+
2110
+ result = RMtx4.new
2111
+ for row in 0...4 do
2112
+ for col in 0...4 do
2113
+ self.setElement( row, col, getElement(row,col) + other.getElement(row,col) )
2114
+ end
2115
+ end
2116
+
2117
+ return self
2118
+ end
2119
+
2120
+ #
2121
+ # call-seq: mtx1.sub!( mtx2 )
2122
+ #
2123
+ # mtx1 -= mtx2 : subtracts the elements of +mtx2+ from corresponding +mtx1+ elements.
2124
+ #
2125
+ def sub!( other )
2126
+ if ( other.class != RMtx4 )
2127
+ raise TypeError, "RMtx4#sub! : Unknown type #{other.class} given as RMtx4."
2128
+ return nil
2129
+ end
2130
+
2131
+ result = RMtx4.new
2132
+ for row in 0...4 do
2133
+ for col in 0...4 do
2134
+ self.setElement( row, col, getElement(row,col) - other.getElement(row,col) )
2135
+ end
2136
+ end
2137
+
2138
+ return self
2139
+ end
2140
+
2141
+ #
2142
+ # call-seq: mtx1.mul!( mtx2 )
2143
+ #
2144
+ # mtx1 *= mtx2
2145
+ #
2146
+ def mul!( other )
2147
+ case other
2148
+ when Fixnum, Float, Bignum
2149
+ self.e00 = other*self.e00
2150
+ self.e01 = other*self.e01
2151
+ self.e02 = other*self.e02
2152
+ self.e03 = other*self.e03
2153
+
2154
+ self.e10 = other*self.e10
2155
+ self.e11 = other*self.e11
2156
+ self.e12 = other*self.e12
2157
+ self.e13 = other*self.e13
2158
+
2159
+ self.e20 = other*self.e20
2160
+ self.e21 = other*self.e21
2161
+ self.e22 = other*self.e22
2162
+ self.e23 = other*self.e23
2163
+
2164
+ self.e30 = other*self.e30
2165
+ self.e31 = other*self.e31
2166
+ self.e32 = other*self.e32
2167
+ self.e33 = other*self.e33
2168
+
2169
+ return self
2170
+
2171
+ when RMtx4
2172
+ result = RMtx4.new
2173
+ for row in 0...4 do
2174
+ for col in 0...4 do
2175
+ sum = 0.0
2176
+ for i in 0...4 do
2177
+ sum += getElement( row, i ) * other.getElement( i, col )
2178
+ end
2179
+ result.setElement( row, col, sum )
2180
+ end
2181
+ end
2182
+
2183
+ self.e00 = result.e00
2184
+ self.e01 = result.e01
2185
+ self.e02 = result.e02
2186
+ self.e03 = result.e03
2187
+
2188
+ self.e10 = result.e10
2189
+ self.e11 = result.e11
2190
+ self.e12 = result.e12
2191
+ self.e13 = result.e13
2192
+
2193
+ self.e20 = result.e20
2194
+ self.e21 = result.e21
2195
+ self.e22 = result.e22
2196
+ self.e23 = result.e23
2197
+
2198
+ self.e30 = result.e30
2199
+ self.e31 = result.e31
2200
+ self.e32 = result.e32
2201
+ self.e33 = result.e33
2202
+
2203
+ return self
2204
+ end
2205
+ end
2206
+ end
2207
+
2208
+ #
2209
+ # Document-class: RMath3D::RQuat
2210
+ # provies quaternion arithmetic.
2211
+ #
2212
+ class RQuat
2213
+
2214
+ #
2215
+ # call-seq:
2216
+ # RQuat.new -> (0,0,0,0)
2217
+ # RQuat.new(e) -> (e,e,e,e)
2218
+ # RQuat.new( other ) : Copy Constructor
2219
+ # RQuat.new( e0, e1, e2, e3 ) -> (e0,e1,e2,e3)
2220
+ #
2221
+ # Creates a new quaternion.
2222
+ #
2223
+ def initialize( *a )
2224
+ @e = []
2225
+ case a.length
2226
+ when 0
2227
+ @e = [0.0, 0.0, 0.0, 0.0]
2228
+ when 1
2229
+ case a[0]
2230
+ when Fixnum, Float
2231
+ @e = [ a[0], a[0], a[0], a[0] ]
2232
+ when RQuat
2233
+ @e = [ a[0].x, a[0].y, a[0].z, a[0].w ]
2234
+ else
2235
+ raise TypeError, "RQuat#initialize : Unknown type #{a[0].class}."
2236
+ return nil
2237
+ end
2238
+ when 4
2239
+ a.each_with_index do |elem, index|
2240
+ case elem
2241
+ when Fixnum, Float
2242
+ @e[index] = elem
2243
+ else
2244
+ raise TypeError, "RQuat#initialize : Unknown type #{elem.class}."
2245
+ return nil
2246
+ end
2247
+ end
2248
+ else
2249
+ raise RuntimeError, "RQuat#initialize : wrong # of arguments (#{a.length})"
2250
+ return nil
2251
+ end
2252
+ return self
2253
+ end
2254
+
2255
+ #
2256
+ # call-seq: to_s
2257
+ #
2258
+ # Returns human-readable string.
2259
+ #
2260
+ def to_s
2261
+ return "( #{@e[0]}, #{@e[1]}, #{@e[2]}, #{@e[3]} )\n"
2262
+ end
2263
+
2264
+ #
2265
+ # call-seq: to_a
2266
+ #
2267
+ # Returns its elements as a new Array.
2268
+ #
2269
+ def to_a
2270
+ return @e
2271
+ end
2272
+
2273
+ #
2274
+ # call-seq: coerse(other)
2275
+ #
2276
+ # Resolves type mismatch.
2277
+ #
2278
+ def coerce( arg )
2279
+ case arg
2280
+ when Fixnum, Float, Bignum
2281
+ return [ self, arg ]
2282
+ else
2283
+ raise TypeError, "RQuat#coerce : #{arg.self} can't be coerced into #{self.class}."
2284
+ return nil
2285
+ end
2286
+ end
2287
+
2288
+ #
2289
+ # call-seq: setElements( e0, e1, e2, e3 )
2290
+ #
2291
+ # Stores given 4 new values.
2292
+ #
2293
+ def setElements( x, y, z, w )
2294
+ self.x = x
2295
+ self.y = y
2296
+ self.z = z
2297
+ self.w = w
2298
+ end
2299
+
2300
+ #
2301
+ # call-seq: quat[i]= value
2302
+ #
2303
+ # Stores +value+ at +i+.
2304
+ #
2305
+ def []=(i,value)
2306
+ @e[i] = value
2307
+ end
2308
+
2309
+ #
2310
+ # call-seq: x= value
2311
+ #
2312
+ # Stores +value+ as +x+.
2313
+ #
2314
+ def x=(value) @e[0] = value end
2315
+
2316
+ #
2317
+ # call-seq: y= value
2318
+ #
2319
+ # Stores +value+ as +y+.
2320
+ #
2321
+ def y=(value) @e[1] = value end
2322
+
2323
+ #
2324
+ # call-seq: z= value
2325
+ #
2326
+ # Stores +value+ as +z+.
2327
+ #
2328
+ def z=(value) @e[2] = value end
1798
2329
 
1799
2330
  #
1800
2331
  # call-seq: w= value
1801
2332
  #
1802
- # Stores +value+ as +w+.
2333
+ # Stores +value+ as +w+.
2334
+ #
2335
+ def w=(value) @e[3] = value end
2336
+
2337
+ #
2338
+ # call-seq: xyz= vXYZ
2339
+ #
2340
+ # Copies the values of +vXYZ+(RVec3) into +x+, +y+ and +z+.
2341
+ #
2342
+ def xyz=( arg )
2343
+ if arg.class != RVec3
2344
+ raise TypeError, "RQuat#xyz= : Unknown type #{arg.class}."
2345
+ return nil
2346
+ end
2347
+ @e[0] = arg.x
2348
+ @e[1] = arg.y
2349
+ @e[2] = arg.z
2350
+ end
2351
+
2352
+ #
2353
+ # call-seq: quat[i] -> value
2354
+ #
2355
+ # Returns the element at +i+.
2356
+ #
2357
+ def [](i)
2358
+ @e[i]
2359
+ end
2360
+
2361
+
2362
+ #
2363
+ # call-seq: x -> value
2364
+ #
2365
+ # Returns the value of +x+.
2366
+ #
2367
+ def x() return @e[0] end
2368
+
2369
+ #
2370
+ # call-seq: y -> value
2371
+ #
2372
+ # Returns the value of +y+.
2373
+ #
2374
+ def y() return @e[1] end
2375
+
2376
+ #
2377
+ # call-seq: z -> value
2378
+ #
2379
+ # Returns the value of +z+.
2380
+ #
2381
+ def z() return @e[2] end
2382
+
2383
+ #
2384
+ # call-seq: w -> value
2385
+ #
2386
+ # Returns the value of +w+.
2387
+ #
2388
+ def w() return @e[3] end
2389
+
2390
+ #
2391
+ # call-seq: xyz -> RVec3
2392
+ #
2393
+ # Returns the values of +x+, +y+ and +z+ with new RVec3(+x+,+y+,+z+).
2394
+ #
2395
+ def xyz()
2396
+ return RVec3.new( @e[0], @e[1], @e[2] )
2397
+ end
2398
+
2399
+ #
2400
+ # call-seq: getLength
2401
+ #
2402
+ # Returns the Euclidean length.
2403
+ #
2404
+ def getLength
2405
+ return Math.sqrt( @e[0]*@e[0] + @e[1]*@e[1] + @e[2]*@e[2] + @e[3]*@e[3] )
2406
+ end
2407
+
2408
+ #
2409
+ # call-seq: getLengthSq
2410
+ #
2411
+ # Returns the squared Euclidean length.
2412
+ #
2413
+ def getLengthSq
2414
+ return (@e[0]*@e[0] + @e[1]*@e[1] + @e[2]*@e[2] + @e[3]*@e[3]).to_f
2415
+ end
2416
+
2417
+ #
2418
+ # call-seq: RQuat.dot(q_a,q_b) -> value
2419
+ #
2420
+ # Calculates the dot product of +q_a+ and +q_b+.
2421
+ #
2422
+ def RQuat.dot( q1, q2 )
2423
+ if q1.class != RQuat || q2.class != RQuat
2424
+ raise TypeError, "RQuat#dot : Unknown type q1:#{q2.class}, q2:#{q2.class}."
2425
+ return nil
2426
+ end
2427
+ return q1.x*q2.x + q1.y*q2.y + q1.z*q2.z + q1.w*q2.w
2428
+ end
2429
+
2430
+ #
2431
+ # call-seq: RQuat.slerp( q_a, q_b, t ) -> interpolated quaternion
2432
+ #
2433
+ # Calculates the spherical linear interpolation between +q_a+ and
2434
+ # +q_b+ at time +t+ (0.0~1.0).
2435
+ #
2436
+ def RQuat.slerp( q1, q2, t )
2437
+ if q1.class != RQuat || q2.class != RQuat
2438
+ raise TypeError, "RQuat#slerp : Unknown type q1:#{q2.class}, q2:#{q2.class}."
2439
+ return nil
2440
+ end
2441
+ s1 = 0.0
2442
+ s2 = 0.0
2443
+ it = 1.0 - t
2444
+ cosine = RQuat.dot( q1, q2 )
2445
+
2446
+ qn1 = q1
2447
+ qn2 = q2
2448
+
2449
+ if ( cosine < 0.0 )
2450
+ cosine *= -1.0
2451
+ qn1 *= -1.0
2452
+ end
2453
+
2454
+ if ( (1.0 - cosine) > TOLERANCE )
2455
+ theta = Math.acos( cosine )
2456
+ sin_theta = Math.sin( theta )
2457
+
2458
+ s1 = Math.sin( it * theta ) / sin_theta
2459
+ s2 = Math.sin( t * theta ) / sin_theta
2460
+ else
2461
+ s1 = it
2462
+ s2 = t
2463
+ end
2464
+
2465
+ qn1 *= s1
2466
+ qn2 *= s2
2467
+ qResult = qn1 + qn2
2468
+
2469
+ return qResult
2470
+ end
2471
+
2472
+ #
2473
+ # call-seq: setIdentity
2474
+ #
2475
+ # Sets as identity quaternion.
2476
+ #
2477
+ def setIdentity
2478
+ self.x = 0.0
2479
+ self.y = 0.0
2480
+ self.z = 0.0
2481
+ self.w = 1.0
2482
+ return self
2483
+ end
2484
+
2485
+ #
2486
+ # call-seq: getConjugated
2487
+ #
2488
+ # Returns its conjugate quaternion.
2489
+ #
2490
+ def getConjugated
2491
+ return RQuat.new( -@e[0], -@e[1], -@e[2], @e[3] )
2492
+ end
2493
+
2494
+ #
2495
+ # call-seq: conjugate!
2496
+ #
2497
+ # Conjugates itself.
2498
+ #
2499
+ def conjugate!
2500
+ @e[0] *= -1.0
2501
+ @e[1] *= -1.0
2502
+ @e[2] *= -1.0
2503
+ return self
2504
+ end
2505
+
2506
+ #
2507
+ # call-seq: getInverse -> inverse quaternion
2508
+ #
2509
+ # Returns the inverse.
2510
+ #
2511
+ def getInverse
2512
+ length_sq = getLengthSq()
2513
+ return RQuat.new( -@e[0]/length_sq, -@e[1]/length_sq, -@e[2]/length_sq, @e[3]/length_sq )
2514
+ end
2515
+
2516
+ #
2517
+ # call-seq: invert! -> self
2518
+ #
2519
+ # Inverts itself.
2520
+ #
2521
+ def invert!
2522
+ length_sq = getLengthSq()
2523
+ @e[0] /= -length_sq
2524
+ @e[1] /= -length_sq
2525
+ @e[2] /= -length_sq
2526
+ @e[3] /= length_sq
2527
+ return self
2528
+ end
2529
+
2530
+ #
2531
+ # call-seq: getNormalized -> RQuat
2532
+ #
2533
+ # Returns normalized quaternion.
2534
+ #
2535
+ def getNormalized
2536
+ length = getLength()
2537
+ return RQuat.new( @e[0]/length, @e[1]/length, @e[2]/length, @e[3]/length )
2538
+ end
2539
+
2540
+ #
2541
+ # call-seq: normalize! -> self
2542
+ #
2543
+ # Normalizes itself.
2544
+ #
2545
+ def normalize!
2546
+ length = getLength()
2547
+ @e[0] /= length
2548
+ @e[1] /= length
2549
+ @e[2] /= length
2550
+ @e[3] /= length
2551
+ return self
2552
+ end
2553
+
2554
+ #
2555
+ # call-seq: +
2556
+ #
2557
+ # +quat : Unary plus operator.
2558
+ #
2559
+ def +@
2560
+ return self
2561
+ end
2562
+
2563
+ #
2564
+ # call-seq: -
2565
+ #
2566
+ # -quat : Unary minus operator.
2567
+ #
2568
+ def -@
2569
+ return RQuat.new( -@e[0], -@e[1], -@e[2], -@e[3] )
2570
+ end
2571
+
2572
+ #
2573
+ # call-seq: +
2574
+ #
2575
+ # quat1 + quat2 : Binary plus operator.
2576
+ #
2577
+ def +( arg )
2578
+ if arg.class != RQuat
2579
+ raise TypeError, "RQuat#+ : Unknown type #{arg.class}."
2580
+ return nil
2581
+ end
2582
+ RQuat.new( x+arg.x, y+arg.y, z+arg.z, w+arg.w )
2583
+ end
2584
+
2585
+ #
2586
+ # call-seq: -
2587
+ #
2588
+ # quat1 - quat2 : Binary minus operator.
2589
+ #
2590
+ def -( arg )
2591
+ if arg.class != RQuat
2592
+ raise TypeError, "RQuat#- : Unknown type #{arg.class}."
2593
+ return nil
2594
+ end
2595
+ RQuat.new( x-arg.x, y-arg.y, z-arg.z, w-arg.w )
2596
+ end
2597
+
2598
+ #
2599
+ # call-seq: *
2600
+ #
2601
+ # quat1 * quat2 : Binary multiply operator.
2602
+ #
2603
+ def *( arg )
2604
+ case arg
2605
+ when RQuat
2606
+ q1x = self.x
2607
+ q1y = self.y
2608
+ q1z = self.z
2609
+ q1w = self.w
2610
+ q2x = arg.x
2611
+ q2y = arg.y
2612
+ q2z = arg.z
2613
+ q2w = arg.w
2614
+ x = q1w*q2x + q1x*q2w + q1y*q2z - q1z*q2y
2615
+ y = q1w*q2y - q1x*q2z + q1y*q2w + q1z*q2x
2616
+ z = q1w*q2z + q1x*q2y - q1y*q2x + q1z*q2w
2617
+ w = q1w*q2w - q1x*q2x - q1y*q2y - q1z*q2z
2618
+ return RQuat.new( x, y, z, w )
2619
+ when Fixnum, Float
2620
+ return RQuat.new( @e[0]*arg, @e[1]*arg, @e[2]*arg, @e[3]*arg )
2621
+ else
2622
+ raise TypeError, "RQuat#* : Unknown type #{arg}."
2623
+ return nil
2624
+ end
2625
+ end
2626
+
2627
+ #
2628
+ # call-seq: ==
2629
+ #
2630
+ # quat1 == quat2 : evaluates equality.
2631
+ #
2632
+ def ==( other )
2633
+ if other.class != RQuat
2634
+ raise TypeError, "RQuat#== : Unknown type #{other.class}."
2635
+ return nil
2636
+ end
2637
+
2638
+ if (x-other.x).abs<=Float::EPSILON &&
2639
+ (y-other.y).abs<=Float::EPSILON &&
2640
+ (z-other.z).abs<=Float::EPSILON &&
2641
+ (w-other.w).abs<=Float::EPSILON
2642
+ return true
2643
+ else
2644
+ return false
2645
+ end
2646
+ end
2647
+
2648
+ #
2649
+ # call-seq: quat1.add!( quat2 )
2650
+ #
2651
+ # quat1 += quat2 : appends the elements of +quat2+ into corresponding +quat1+ elements.
2652
+ #
2653
+ def add!( other )
2654
+ if other.class != RQuat
2655
+ raise TypeError, "RQ#add! : Unknown type #{other.class}."
2656
+ return nil
2657
+ end
2658
+
2659
+ self.x += other.x
2660
+ self.y += other.y
2661
+ self.z += other.z
2662
+ self.w += other.w
2663
+
2664
+ return self
2665
+ end
2666
+
2667
+ #
2668
+ # call-seq: quat1.sub!( quat2 )
2669
+ #
2670
+ # quat1 -= quat2 : subtracts the elements of +quat2+ from corresponding +quat1+ elements.
1803
2671
  #
1804
- def w=(value) @e[3] = value end
2672
+ def sub!( other )
2673
+ if other.class != RQuat
2674
+ raise TypeError, "RQuat#sub! : Unknown type #{other.class}."
2675
+ return nil
2676
+ end
2677
+
2678
+ self.x -= other.x
2679
+ self.y -= other.y
2680
+ self.z -= other.z
2681
+ self.w -= other.w
2682
+
2683
+ return self
2684
+ end
1805
2685
 
1806
2686
  #
1807
- # call-seq: xyz= vXYZ
2687
+ # call-seq: quat1.mul!( quat2 )
1808
2688
  #
1809
- # Copies the values of +vXYZ+(RVec3) into +x+, +y+ and +z+.
2689
+ # quat1 *= quat2
1810
2690
  #
1811
- def xyz=( arg )
1812
- if arg.class != RVec3
1813
- raise TypeError, "RQuat#xyz= : Unknown type #{arg.class}."
2691
+ def mul!( other )
2692
+ case other
2693
+ when RQuat
2694
+ q1x = self.x
2695
+ q1y = self.y
2696
+ q1z = self.z
2697
+ q1w = self.w
2698
+ q2x = other.x
2699
+ q2y = other.y
2700
+ q2z = other.z
2701
+ q2w = other.w
2702
+
2703
+ x = q1w*q2x + q1x*q2w + q1y*q2z - q1z*q2y
2704
+ y = q1w*q2y - q1x*q2z + q1y*q2w + q1z*q2x
2705
+ z = q1w*q2z + q1x*q2y - q1y*q2x + q1z*q2w
2706
+ w = q1w*q2w - q1x*q2x - q1y*q2y - q1z*q2z
2707
+
2708
+ self.x = x
2709
+ self.y = y
2710
+ self.z = z
2711
+ self.w = w
2712
+
2713
+ return self
2714
+
2715
+ when Fixnum, Float
2716
+ self.x *= other
2717
+ self.y *= other
2718
+ self.z *= other
2719
+ self.w *= other
2720
+ return self
2721
+
2722
+ else
2723
+ raise TypeError, "RQuat#mul! : Unknown type #{other.class}."
1814
2724
  return nil
1815
2725
  end
1816
- @e[0] = arg.x
1817
- @e[1] = arg.y
1818
- @e[2] = arg.z
1819
2726
  end
1820
2727
 
1821
2728
  #
1822
- # call-seq: quat[i] -> value
2729
+ # call-seq: rotationMarix(mtx4) -> self
1823
2730
  #
1824
- # Returns the element at +i+.
2731
+ # Makes a rotation quaternion from a rotation matrix +mtx4+ (RMtx4).
1825
2732
  #
1826
- def [](i)
1827
- @e[i]
1828
- end
2733
+ def rotationMatrix( mtx )
2734
+ if mtx.class != RMtx3 && mtx.class != RMtx4
2735
+ raise TypeError, "RQuat#rotationMatrix : Unknown type #{mtx.class}."
2736
+ return nil
2737
+ end
2738
+
2739
+ diag00 = mtx.getElement(0,0)
2740
+ diag11 = mtx.getElement(1,1)
2741
+ diag22 = mtx.getElement(2,2)
2742
+
2743
+ if ( diag00 + diag11 + diag22 > 0.0 )
2744
+ t = diag00 + diag11 + diag22 + 1.0
2745
+ s = 1.0 / ( Math.sqrt( t ) * 2.0 )
2746
+ self.w = s * t
2747
+ self.z = (mtx.getElement(1,0) - mtx.getElement(0,1)) * s
2748
+ self.y = (mtx.getElement(0,2) - mtx.getElement(2,0)) * s
2749
+ self.x = (mtx.getElement(2,1) - mtx.getElement(1,2)) * s
2750
+ elsif ( diag00 > diag11 && diag00 > diag22 )
2751
+ t = diag00 - diag11 - diag22 + 1.0
2752
+ s = 1.0 / ( Math.sqrt( t ) * 2.0 )
2753
+ self.x = s * t
2754
+ self.y = (mtx.getElement(1,0) + mtx.getElement(0,1)) * s
2755
+ self.z = (mtx.getElement(0,2) + mtx.getElement(2,0)) * s
2756
+ self.w = (mtx.getElement(2,1) - mtx.getElement(1,2)) * s
2757
+ elsif ( diag11 > diag22 )
2758
+ t = -diag00 + diag11 - diag22 + 1.0
2759
+ s = 1.0 / ( Math.sqrt( t ) * 2.0 )
2760
+ self.y = s * t
2761
+ self.x = (mtx.getElement(1,0) + mtx.getElement(0,1)) * s
2762
+ self.w = (mtx.getElement(0,2) - mtx.getElement(2,0)) * s
2763
+ self.z = (mtx.getElement(2,1) + mtx.getElement(1,2)) * s
2764
+ else
2765
+ t = -diag00 - diag11 + diag22 + 1.0
2766
+ s = 1.0 / ( Math.sqrt( t ) * 2.0 )
2767
+ self.z = s * t
2768
+ self.w = (mtx.getElement(1,0) - mtx.getElement(0,1)) * s
2769
+ self.x = (mtx.getElement(0,2) + mtx.getElement(2,0)) * s
2770
+ self.y = (mtx.getElement(2,1) + mtx.getElement(1,2)) * s
2771
+ end
1829
2772
 
2773
+ return self
2774
+ end
1830
2775
 
1831
2776
  #
1832
- # call-seq: x -> value
2777
+ # call-seq: rotationAxis(axis,radian) -> self
1833
2778
  #
1834
- # Returns the value of +x+.
2779
+ # Makes a quaternion that rotates around the +axis+.
1835
2780
  #
1836
- def x() return @e[0] end
2781
+ def rotationAxis( axis, radian )
2782
+ if axis.class != RVec3
2783
+ raise TypeError, "RQuat#rotationAxis : Unknown type #{axis.class}."
2784
+ return nil
2785
+ end
2786
+
2787
+ s = Math.sin( radian / 2.0 )
2788
+ self.x = s * axis.x
2789
+ self.y = s * axis.y
2790
+ self.z = s * axis.z
2791
+ self.w = Math.cos( radian / 2.0 )
2792
+
2793
+ return self
2794
+ end
1837
2795
 
1838
2796
  #
1839
- # call-seq: y -> value
2797
+ # call-seq: toAxisAngle -> [axis,radian]
1840
2798
  #
1841
- # Returns the value of +y+.
2799
+ # Returns its rotation axis (RVec3) and rotation angle (in radian).
1842
2800
  #
1843
- def y() return @e[1] end
2801
+ def toAxisAngle
2802
+ axis = RVec3.new( self.x, self.y, self.z ).normalize!
2803
+ radian = 2.0 * Math.acos( self.w )
2804
+
2805
+ return [ axis, radian ]
2806
+ end
2807
+ end
2808
+
2809
+ #
2810
+ # Document-class: RMath3D::RVec2
2811
+ # provies 2 element vector arithmetic.
2812
+ #
2813
+ class RVec2
1844
2814
 
1845
2815
  #
1846
- # call-seq: z -> value
2816
+ # call-seq:
2817
+ # RVec2.new -> (0,0)
2818
+ # RVec2.new(e) -> (e,e)
2819
+ # RVec2.new( other ) : Copy Constructor
2820
+ # RVec2.new( e0, e1 ) -> (e0,e1)
1847
2821
  #
1848
- # Returns the value of +z+.
2822
+ # Creates a new 3 element vector.
1849
2823
  #
1850
- def z() return @e[2] end
2824
+ def initialize( *a )
2825
+ @e = []
2826
+ case a.length
2827
+ when 0
2828
+ @e = [0.0, 0.0]
2829
+ when 1
2830
+ case a[0]
2831
+ when Fixnum, Float
2832
+ @e = [ a[0], a[0] ]
2833
+ when RVec2
2834
+ @e = [ a[0].x, a[0].y ]
2835
+ else
2836
+ raise TypeError, "RVec2#initialize : Unknown type #{a[0].class}."
2837
+ return nil
2838
+ end
2839
+ when 2
2840
+ a.each_with_index do |elem, index|
2841
+ case elem
2842
+ when Fixnum, Float
2843
+ @e[index] = elem
2844
+ else
2845
+ raise TypeError, "RVec2#initialize : Unknown type #{elem.class}."
2846
+ return nil
2847
+ end
2848
+ end
2849
+ else
2850
+ raise RuntimeError, "RVec2#initialize : wrong # of arguments (#{a.length})"
2851
+ return nil
2852
+ end
2853
+ return self
2854
+ end
1851
2855
 
1852
2856
  #
1853
- # call-seq: w -> value
2857
+ # call-seq: to_s
1854
2858
  #
1855
- # Returns the value of +w+.
2859
+ # Returns human-readable string.
1856
2860
  #
1857
- def w() return @e[3] end
2861
+ def to_s
2862
+ return "( #{@e[0]}, #{@e[1]} )\n"
2863
+ end
1858
2864
 
1859
2865
  #
1860
- # call-seq: xyz -> RVec3
2866
+ # call-seq: to_a
1861
2867
  #
1862
- # Returns the values of +x+, +y+ and +z+ with new RVec3(+x+,+y+,+z+).
2868
+ # Returns its elements as a new Array.
1863
2869
  #
1864
- def xyz()
1865
- return RVec3.new( @e[0], @e[1], @e[2] )
2870
+ def to_a
2871
+ return @e
1866
2872
  end
1867
2873
 
1868
2874
  #
1869
- # call-seq: getLength
2875
+ # call-seq: coerse(other)
1870
2876
  #
1871
- # Returns the Euclidean length.
2877
+ # Resolves type mismatch.
1872
2878
  #
1873
- def getLength
1874
- return Math.sqrt( @e[0]*@e[0] + @e[1]*@e[1] + @e[2]*@e[2] + @e[3]*@e[3] )
2879
+ def coerce( arg )
2880
+ case arg
2881
+ when Fixnum, Float, Bignum
2882
+ return [ self, arg ]
2883
+ else
2884
+ raise TypeError, "RVec2#coerce : #{arg.self} can't be coerced into #{self.class}."
2885
+ return nil
2886
+ end
1875
2887
  end
1876
2888
 
1877
2889
  #
1878
- # call-seq: getLengthSq
2890
+ # call-seq: setElements( e0, e1 )
1879
2891
  #
1880
- # Returns the squared Euclidean length.
2892
+ # Stores given 2 new values.
1881
2893
  #
1882
- def getLengthSq
1883
- return (@e[0]*@e[0] + @e[1]*@e[1] + @e[2]*@e[2] + @e[3]*@e[3]).to_f
2894
+ def setElements( x, y )
2895
+ self.x = x
2896
+ self.y = y
1884
2897
  end
1885
2898
 
1886
2899
  #
1887
- # call-seq: RQuat.dot(q_a,q_b) -> value
2900
+ # call-seq: vec2[i]= value
1888
2901
  #
1889
- # Calculates the dot product of +q_a+ and +q_b+.
2902
+ # Stores +value+ at +i+.
1890
2903
  #
1891
- def RQuat.dot( q1, q2 )
1892
- if q1.class != RQuat || q2.class != RQuat
1893
- raise TypeError, "RQuat#dot : Unknown type q1:#{q2.class}, q2:#{q2.class}."
1894
- return nil
1895
- end
1896
- return q1.x*q2.x + q1.y*q2.y + q1.z*q2.z + q1.w*q2.w
2904
+ def []=(i,value)
2905
+ @e[i] = value
1897
2906
  end
1898
2907
 
1899
2908
  #
1900
- # call-seq: RQuat.slerp( q_a, q_b, t ) -> interpolated quaternion
2909
+ # call-seq: x= value
1901
2910
  #
1902
- # Calculates the spherical linear interpolation between +q_a+ and
1903
- # +q_b+ at time +t+ (0.0~1.0).
2911
+ # Stores +value+ as +x+.
1904
2912
  #
1905
- def RQuat.slerp( q1, q2, t )
1906
- if q1.class != RQuat || q2.class != RQuat
1907
- raise TypeError, "RQuat#slerp : Unknown type q1:#{q2.class}, q2:#{q2.class}."
1908
- return nil
1909
- end
1910
- s1 = 0.0
1911
- s2 = 0.0
1912
- it = 1.0 - t
1913
- cosine = RQuat.dot( q1, q2 )
1914
-
1915
- qn1 = q1
1916
- qn2 = q2
1917
-
1918
- if ( cosine < 0.0 )
1919
- cosine *= -1.0
1920
- qn1 *= -1.0
1921
- end
1922
-
1923
- if ( (1.0 - cosine) > TOLERANCE )
1924
- theta = Math.acos( cosine )
1925
- sin_theta = Math.sin( theta )
1926
-
1927
- s1 = Math.sin( it * theta ) / sin_theta
1928
- s2 = Math.sin( t * theta ) / sin_theta
1929
- else
1930
- s1 = it
1931
- s2 = t
1932
- end
2913
+ def x=(value) @e[0] = value end
1933
2914
 
1934
- qn1 *= s1
1935
- qn2 *= s2
1936
- qResult = qn1 + qn2
2915
+ #
2916
+ # call-seq: y= value
2917
+ #
2918
+ # Stores +value+ as +y+.
2919
+ #
2920
+ def y=(value) @e[1] = value end
1937
2921
 
1938
- return qResult
2922
+ #
2923
+ # call-seq: vec3[i] -> value
2924
+ #
2925
+ # Returns the element at +i+.
2926
+ #
2927
+ def [](i)
2928
+ @e[i]
1939
2929
  end
1940
2930
 
1941
2931
  #
1942
- # call-seq: setIdentity
2932
+ # call-seq: x -> value
1943
2933
  #
1944
- # Sets as identity quaternion.
2934
+ # Returns the value of +x+.
1945
2935
  #
1946
- def setIdentity
1947
- self.x = 0.0
1948
- self.y = 0.0
1949
- self.z = 0.0
1950
- self.w = 1.0
1951
- return self
2936
+ def x() return @e[0] end
2937
+
2938
+ #
2939
+ # call-seq: y -> value
2940
+ #
2941
+ # Returns the value of +y+.
2942
+ #
2943
+ def y() return @e[1] end
2944
+
2945
+ #
2946
+ # call-seq: getLength
2947
+ #
2948
+ # Returns the Euclidean length.
2949
+ #
2950
+ def getLength
2951
+ return Math.sqrt( @e[0]*@e[0] + @e[1]*@e[1] )
1952
2952
  end
1953
2953
 
1954
2954
  #
1955
- # call-seq: getConjugated
2955
+ # call-seq: getLengthSq
1956
2956
  #
1957
- # Returns its conjugate quaternion.
2957
+ # Returns the squared Euclidean length.
1958
2958
  #
1959
- def getConjugated
1960
- return RQuat.new( -@e[0], -@e[1], -@e[2], @e[3] )
2959
+ def getLengthSq
2960
+ return (@e[0]*@e[0] + @e[1]*@e[1]).to_f
1961
2961
  end
1962
2962
 
1963
2963
  #
1964
- # call-seq: conjugate!
2964
+ # call-seq: RVec2.dot(v_a,v_b) -> value
1965
2965
  #
1966
- # Conjugates itself.
2966
+ # Calculates the dot product of +v_a+ and +v_b+.
1967
2967
  #
1968
- def conjugate!
1969
- @e[0] *= -1.0
1970
- @e[1] *= -1.0
1971
- @e[2] *= -1.0
1972
- return self
2968
+ def RVec2.dot( v1, v2 )
2969
+ return v1.x*v2.x + v1.y*v2.y
1973
2970
  end
1974
2971
 
1975
2972
  #
1976
- # call-seq: getInverse -> inverse quaternion
2973
+ # call-seq: RVec2.cross(v_a,v_b) -> value
1977
2974
  #
1978
- # Returns the inverse.
2975
+ # Calculates the cross product of +v_a+ and +v_b+.
1979
2976
  #
1980
- def getInverse
1981
- length_sq = getLengthSq()
1982
- return RQuat.new( -@e[0]/length_sq, -@e[1]/length_sq, -@e[2]/length_sq, @e[3]/length_sq )
2977
+ def RVec2.cross( v1, v2 )
2978
+ return v1.x*v2.y - v1.y*v2.x
1983
2979
  end
1984
2980
 
1985
2981
  #
1986
- # call-seq: invert! -> self
2982
+ # call-seq: transform(mtx2) -> transformed RVec2
1987
2983
  #
1988
- # Inverts itself.
2984
+ # Returns new RVec2 containing the result of the transformation of
2985
+ # RVec2(self.x,self.y) by +mtx2+ (RMtx2).
1989
2986
  #
1990
- def invert!
1991
- length_sq = getLengthSq()
1992
- @e[0] /= -length_sq
1993
- @e[1] /= -length_sq
1994
- @e[2] /= -length_sq
1995
- @e[3] /= length_sq
1996
- return self
2987
+ def transform( mtx2 )
2988
+ result = RVec2.new
2989
+ result.x = mtx2.e00 * self[0] + mtx2.e01 * self[1]
2990
+ result.y = mtx2.e10 * self[0] + mtx2.e11 * self[1]
2991
+
2992
+ return result
1997
2993
  end
1998
2994
 
1999
2995
  #
2000
- # call-seq: getNormalized -> RQuat
2996
+ # call-seq: getNormalized -> RVec2
2001
2997
  #
2002
- # Returns normalized quaternion.
2998
+ # Returns normalized vector.
2003
2999
  #
2004
3000
  def getNormalized
2005
- length = getLength()
2006
- return RQuat.new( @e[0]/length, @e[1]/length, @e[2]/length, @e[3]/length )
3001
+ l = getLength()
3002
+ l = 1.0/l
3003
+ return RVec2.new( @e[0]*l, @e[1]*l )
2007
3004
  end
2008
3005
 
2009
3006
  #
@@ -2012,18 +3009,17 @@ module RMath3D
2012
3009
  # Normalizes itself.
2013
3010
  #
2014
3011
  def normalize!
2015
- length = getLength()
2016
- @e[0] /= length
2017
- @e[1] /= length
2018
- @e[2] /= length
2019
- @e[3] /= length
3012
+ l = getLength()
3013
+ l = 1.0/l
3014
+ @e[0] *= l
3015
+ @e[1] *= l
2020
3016
  return self
2021
3017
  end
2022
3018
 
2023
3019
  #
2024
3020
  # call-seq: +
2025
3021
  #
2026
- # +quat : Unary plus operator.
3022
+ # +vec : Unary plus operator.
2027
3023
  #
2028
3024
  def +@
2029
3025
  return self
@@ -2032,63 +3028,49 @@ module RMath3D
2032
3028
  #
2033
3029
  # call-seq: -
2034
3030
  #
2035
- # -quat : Unary minus operator.
3031
+ # -vec : Unary minus operator.
2036
3032
  #
2037
3033
  def -@
2038
- return RQuat.new( -@e[0], -@e[1], -@e[2], -@e[3] )
3034
+ return RVec2.new( -@e[0], -@e[1] )
2039
3035
  end
2040
3036
 
2041
3037
  #
2042
3038
  # call-seq: +
2043
3039
  #
2044
- # quat1 + quat2 : Binary plus operator.
3040
+ # vec1 + vec2 : Binary plus operator.
2045
3041
  #
2046
3042
  def +( arg )
2047
- if arg.class != RQuat
2048
- raise TypeError, "RQuat#+ : Unknown type #{arg.class}."
3043
+ if arg.class != RVec2
3044
+ raise TypeError, "RVec2#+ : Unknown type #{arg.class}."
2049
3045
  return nil
2050
3046
  end
2051
- RQuat.new( x+arg.x, y+arg.y, z+arg.z, w+arg.w )
3047
+ RVec2.new( x+arg.x, y+arg.y )
2052
3048
  end
2053
3049
 
2054
3050
  #
2055
3051
  # call-seq: -
2056
3052
  #
2057
- # quat1 - quat2 : Binary minus operator.
3053
+ # vec1 - vec2 : Binary minus operator.
2058
3054
  #
2059
3055
  def -( arg )
2060
- if arg.class != RQuat
2061
- raise TypeError, "RQuat#- : Unknown type #{arg.class}."
3056
+ if arg.class != RVec2
3057
+ raise TypeError, "RVec2#- : Unknown type #{arg.class}."
2062
3058
  return nil
2063
3059
  end
2064
- RQuat.new( x-arg.x, y-arg.y, z-arg.z, w-arg.w )
3060
+ RVec2.new( x-arg.x, y-arg.y )
2065
3061
  end
2066
3062
 
2067
3063
  #
2068
3064
  # call-seq: *
2069
3065
  #
2070
- # quat1 * quat2 : Binary multiply operator.
3066
+ # vec1 * vec2 : Binary multiply operator.
2071
3067
  #
2072
3068
  def *( arg )
2073
3069
  case arg
2074
- when RQuat
2075
- q1x = self.x
2076
- q1y = self.y
2077
- q1z = self.z
2078
- q1w = self.w
2079
- q2x = arg.x
2080
- q2y = arg.y
2081
- q2z = arg.z
2082
- q2w = arg.w
2083
- x = q1w*q2x + q1x*q2w + q1y*q2z - q1z*q2y
2084
- y = q1w*q2y - q1x*q2z + q1y*q2w + q1z*q2x
2085
- z = q1w*q2z + q1x*q2y - q1y*q2x + q1z*q2w
2086
- w = q1w*q2w - q1x*q2x - q1y*q2y - q1z*q2z
2087
- return RQuat.new( x, y, z, w )
2088
3070
  when Fixnum, Float
2089
- return RQuat.new( @e[0]*arg, @e[1]*arg, @e[2]*arg, @e[3]*arg )
3071
+ return RVec2.new( @e[0]*arg, @e[1]*arg )
2090
3072
  else
2091
- raise TypeError, "RQuat#* : Unknown type #{arg}."
3073
+ raise TypeError, "RVec2#* : Unknown type #{arg}."
2092
3074
  return nil
2093
3075
  end
2094
3076
  end
@@ -2096,18 +3078,16 @@ module RMath3D
2096
3078
  #
2097
3079
  # call-seq: ==
2098
3080
  #
2099
- # quat1 == quat2 : evaluates equality.
3081
+ # vec1 == vec2 : evaluates equality.
2100
3082
  #
2101
3083
  def ==( other )
2102
- if other.class != RQuat
2103
- raise TypeError, "RQuat#== : Unknown type #{other.class}."
3084
+ if other.class != RVec2
3085
+ raise TypeError, "RVec2#== : Unknown type #{other.class}."
2104
3086
  return nil
2105
3087
  end
2106
3088
 
2107
3089
  if (x-other.x).abs<=Float::EPSILON &&
2108
- (y-other.y).abs<=Float::EPSILON &&
2109
- (z-other.z).abs<=Float::EPSILON &&
2110
- (w-other.w).abs<=Float::EPSILON
3090
+ (y-other.y).abs<=Float::EPSILON
2111
3091
  return true
2112
3092
  else
2113
3093
  return false
@@ -2115,164 +3095,55 @@ module RMath3D
2115
3095
  end
2116
3096
 
2117
3097
  #
2118
- # call-seq: quat1.add!( quat2 )
3098
+ # call-seq: vec1.add!( vec2 )
2119
3099
  #
2120
- # quat1 += quat2 : appends the elements of +quat2+ into corresponding +quat1+ elements.
3100
+ # vec1 += vec2 : appends the elements of +vec2+ into corresponding +vec1+ elements.
2121
3101
  #
2122
3102
  def add!( other )
2123
- if other.class != RQuat
2124
- raise TypeError, "RQ#add! : Unknown type #{other.class}."
3103
+ if other.class != RVec2
3104
+ raise TypeError, "RVec2#add! : Unknown type #{other.class}."
2125
3105
  return nil
2126
3106
  end
2127
3107
 
2128
3108
  self.x += other.x
2129
3109
  self.y += other.y
2130
- self.z += other.z
2131
- self.w += other.w
2132
3110
 
2133
3111
  return self
2134
3112
  end
2135
3113
 
2136
3114
  #
2137
- # call-seq: quat1.sub!( quat2 )
3115
+ # call-seq: vec1.sub!( vec2 )
2138
3116
  #
2139
- # quat1 -= quat2 : subtracts the elements of +quat2+ from corresponding +quat1+ elements.
3117
+ # vec1 -= vec2 : subtracts the elements of +vec2+ from corresponding +vec1+ elements.
2140
3118
  #
2141
3119
  def sub!( other )
2142
- if other.class != RQuat
2143
- raise TypeError, "RQuat#sub! : Unknown type #{other.class}."
3120
+ if other.class != RVec2
3121
+ raise TypeError, "RVec2#sub! : Unknown type #{other.class}."
2144
3122
  return nil
2145
3123
  end
2146
3124
 
2147
3125
  self.x -= other.x
2148
3126
  self.y -= other.y
2149
- self.z -= other.z
2150
- self.w -= other.w
2151
-
2152
- return self
2153
- end
2154
-
2155
- #
2156
- # call-seq: quat1.mul!( quat2 )
2157
- #
2158
- # quat1 *= quat2
2159
- #
2160
- def mul!( other )
2161
- case other
2162
- when RQuat
2163
- q1x = self.x
2164
- q1y = self.y
2165
- q1z = self.z
2166
- q1w = self.w
2167
- q2x = other.x
2168
- q2y = other.y
2169
- q2z = other.z
2170
- q2w = other.w
2171
-
2172
- x = q1w*q2x + q1x*q2w + q1y*q2z - q1z*q2y
2173
- y = q1w*q2y - q1x*q2z + q1y*q2w + q1z*q2x
2174
- z = q1w*q2z + q1x*q2y - q1y*q2x + q1z*q2w
2175
- w = q1w*q2w - q1x*q2x - q1y*q2y - q1z*q2z
2176
-
2177
- self.x = x
2178
- self.y = y
2179
- self.z = z
2180
- self.w = w
2181
-
2182
- return self
2183
-
2184
- when Fixnum, Float
2185
- self.x *= other
2186
- self.y *= other
2187
- self.z *= other
2188
- self.w *= other
2189
- return self
2190
-
2191
- else
2192
- raise TypeError, "RQuat#mul! : Unknown type #{other.class}."
2193
- return nil
2194
- end
2195
- end
2196
-
2197
- #
2198
- # call-seq: rotationMarix(mtx4) -> self
2199
- #
2200
- # Makes a rotation quaternion from a rotation matrix +mtx4+ (RMtx4).
2201
- #
2202
- def rotationMatrix( mtx )
2203
- if mtx.class != RMtx3 && mtx.class != RMtx4
2204
- raise TypeError, "RQuat#rotationMatrix : Unknown type #{mtx.class}."
2205
- return nil
2206
- end
2207
-
2208
- diag00 = mtx.getElement(0,0)
2209
- diag11 = mtx.getElement(1,1)
2210
- diag22 = mtx.getElement(2,2)
2211
-
2212
- if ( diag00 + diag11 + diag22 > 0.0 )
2213
- t = diag00 + diag11 + diag22 + 1.0
2214
- s = 1.0 / ( Math.sqrt( t ) * 2.0 )
2215
- self.w = s * t
2216
- self.z = (mtx.getElement(1,0) - mtx.getElement(0,1)) * s
2217
- self.y = (mtx.getElement(0,2) - mtx.getElement(2,0)) * s
2218
- self.x = (mtx.getElement(2,1) - mtx.getElement(1,2)) * s
2219
- elsif ( diag00 > diag11 && diag00 > diag22 )
2220
- t = diag00 - diag11 - diag22 + 1.0
2221
- s = 1.0 / ( Math.sqrt( t ) * 2.0 )
2222
- self.x = s * t
2223
- self.y = (mtx.getElement(1,0) + mtx.getElement(0,1)) * s
2224
- self.z = (mtx.getElement(0,2) + mtx.getElement(2,0)) * s
2225
- self.w = (mtx.getElement(2,1) - mtx.getElement(1,2)) * s
2226
- elsif ( diag11 > diag22 )
2227
- t = -diag00 + diag11 - diag22 + 1.0
2228
- s = 1.0 / ( Math.sqrt( t ) * 2.0 )
2229
- self.y = s * t
2230
- self.x = (mtx.getElement(1,0) + mtx.getElement(0,1)) * s
2231
- self.w = (mtx.getElement(0,2) - mtx.getElement(2,0)) * s
2232
- self.z = (mtx.getElement(2,1) + mtx.getElement(1,2)) * s
2233
- else
2234
- t = -diag00 - diag11 + diag22 + 1.0
2235
- s = 1.0 / ( Math.sqrt( t ) * 2.0 )
2236
- self.z = s * t
2237
- self.w = (mtx.getElement(1,0) - mtx.getElement(0,1)) * s
2238
- self.x = (mtx.getElement(0,2) + mtx.getElement(2,0)) * s
2239
- self.y = (mtx.getElement(2,1) + mtx.getElement(1,2)) * s
2240
- end
2241
3127
 
2242
3128
  return self
2243
3129
  end
2244
3130
 
2245
3131
  #
2246
- # call-seq: rotationAxis(axis,radian) -> self
3132
+ # call-seq: vec1.mul!( vec2 )
2247
3133
  #
2248
- # Makes a quaternion that rotates around the +axis+.
3134
+ # vec1 *= vec2
2249
3135
  #
2250
- def rotationAxis( axis, radian )
2251
- if axis.class != RVec3
2252
- raise TypeError, "RQuat#rotationAxis : Unknown type #{axis.class}."
3136
+ def mul!( arg )
3137
+ if arg.class != Fixnum && arg.class != Float
3138
+ raise TypeError, "RVec2#mul! : Unknown type #{arg.class}."
2253
3139
  return nil
2254
3140
  end
2255
3141
 
2256
- s = Math.sin( radian / 2.0 )
2257
- self.x = s * axis.x
2258
- self.y = s * axis.y
2259
- self.z = s * axis.z
2260
- self.w = Math.cos( radian / 2.0 )
3142
+ self.x *= arg
3143
+ self.y *= arg
2261
3144
 
2262
3145
  return self
2263
3146
  end
2264
-
2265
- #
2266
- # call-seq: toAxisAngle -> [axis,radian]
2267
- #
2268
- # Returns its rotation axis (RVec3) and rotation angle (in radian).
2269
- #
2270
- def toAxisAngle
2271
- axis = RVec3.new( self.x, self.y, self.z ).normalize!
2272
- radian = 2.0 * Math.acos( self.w )
2273
-
2274
- return [ axis, radian ]
2275
- end
2276
3147
  end
2277
3148
 
2278
3149
  #