Project

General

Profile

« Previous | Next » 

Revision 5f8e909a

Added by Leszek Koltunski 4 days ago

Rename .java to .kt

View differences:

src/main/java/org/distorted/library/helpers/MatrixHelper.java
1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2023 Leszek Koltunski  leszek@koltunski.pl                                          //
3
//                                                                                               //
4
// This file is part of Distorted.                                                               //
5
//                                                                                               //
6
// This library is free software; you can redistribute it and/or                                 //
7
// modify it under the terms of the GNU Lesser General Public                                    //
8
// License as published by the Free Software Foundation; either                                  //
9
// version 2.1 of the License, or (at your option) any later version.                            //
10
//                                                                                               //
11
// This library is distributed in the hope that it will be useful,                               //
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU                             //
14
// Lesser General Public License for more details.                                               //
15
//                                                                                               //
16
// You should have received a copy of the GNU Lesser General Public                              //
17
// License along with this library; if not, write to the Free Software                           //
18
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA                //
19
///////////////////////////////////////////////////////////////////////////////////////////////////
20

  
21
package org.distorted.library.helpers;
22

  
23
///////////////////////////////////////////////////////////////////////////////////////////////////
24

  
25
public class MatrixHelper
26
  {
27
  public static void setIdentity(float[] output)
28
    {
29
    output[ 0] = 1;
30
    output[ 1] = 0;
31
    output[ 2] = 0;
32
    output[ 3] = 0;
33
    output[ 4] = 0;
34
    output[ 5] = 1;
35
    output[ 6] = 0;
36
    output[ 7] = 0;
37
    output[ 8] = 0;
38
    output[ 9] = 0;
39
    output[10] = 1;
40
    output[11] = 0;
41
    output[12] = 0;
42
    output[13] = 0;
43
    output[14] = 0;
44
    output[15] = 1;
45
    }
46

  
47
///////////////////////////////////////////////////////////////////////////////////////////////////
48

  
49
  public static void multiply(float[] output, float[] m1, float[] m2)
50
    {
51
    output[ 0] = m1[ 0]*m2[ 0] + m1[ 4]*m2[ 1] + m1[ 8]*m2[ 2] + m1[12]*m2[ 3];
52
    output[ 1] = m1[ 1]*m2[ 0] + m1[ 5]*m2[ 1] + m1[ 9]*m2[ 2] + m1[13]*m2[ 3];
53
    output[ 2] = m1[ 2]*m2[ 0] + m1[ 6]*m2[ 1] + m1[10]*m2[ 2] + m1[14]*m2[ 3];
54
    output[ 3] = m1[ 3]*m2[ 0] + m1[ 7]*m2[ 1] + m1[11]*m2[ 2] + m1[15]*m2[ 3];
55

  
56
    output[ 4] = m1[ 0]*m2[ 4] + m1[ 4]*m2[ 5] + m1[ 8]*m2[ 6] + m1[12]*m2[ 7];
57
    output[ 5] = m1[ 1]*m2[ 4] + m1[ 5]*m2[ 5] + m1[ 9]*m2[ 6] + m1[13]*m2[ 7];
58
    output[ 6] = m1[ 2]*m2[ 4] + m1[ 6]*m2[ 5] + m1[10]*m2[ 6] + m1[14]*m2[ 7];
59
    output[ 7] = m1[ 3]*m2[ 4] + m1[ 7]*m2[ 5] + m1[11]*m2[ 6] + m1[15]*m2[ 7];
60

  
61
    output[ 8] = m1[ 0]*m2[ 8] + m1[ 4]*m2[ 9] + m1[ 8]*m2[10] + m1[12]*m2[11];
62
    output[ 9] = m1[ 1]*m2[ 8] + m1[ 5]*m2[ 9] + m1[ 9]*m2[10] + m1[13]*m2[11];
63
    output[10] = m1[ 2]*m2[ 8] + m1[ 6]*m2[ 9] + m1[10]*m2[10] + m1[14]*m2[11];
64
    output[11] = m1[ 3]*m2[ 8] + m1[ 7]*m2[ 9] + m1[11]*m2[10] + m1[15]*m2[11];
65

  
66
    output[12] = m1[ 0]*m2[12] + m1[ 4]*m2[13] + m1[ 8]*m2[14] + m1[12]*m2[15];
67
    output[13] = m1[ 1]*m2[12] + m1[ 5]*m2[13] + m1[ 9]*m2[14] + m1[13]*m2[15];
68
    output[14] = m1[ 2]*m2[12] + m1[ 6]*m2[13] + m1[10]*m2[14] + m1[14]*m2[15];
69
    output[15] = m1[ 3]*m2[12] + m1[ 7]*m2[13] + m1[11]*m2[14] + m1[15]*m2[15];
70
    }
71

  
72
///////////////////////////////////////////////////////////////////////////////////////////////////
73

  
74
  public static void frustum(float[] output, float l, float r, float b, float t, float n, float f)
75
    {
76
    output[0]  =  2 * n / (r - l);
77
    output[1]  =  0;
78
    output[2]  =  0;
79
    output[3]  =  0;
80
    output[4]  =  0;
81
    output[5]  =  2 * n / (t - b);
82
    output[6]  =  0;
83
    output[7]  =  0;
84
    output[8]  =  (r + l) / (r - l);
85
    output[9]  =  (t + b) / (t - b);
86
    output[10] = -(f + n) / (f - n);
87
    output[11] = -1;
88
    output[12] =  0;
89
    output[13] =  0;
90
    output[14] = -(2 * f * n) / (f - n);
91
    output[15] =  0;
92
    }
93

  
94
///////////////////////////////////////////////////////////////////////////////////////////////////
95

  
96
  public static void ortho(float[] output, float l, float r, float b, float t, float n, float f)
97
    {
98
    output[0]  =  2 / (r - l);
99
    output[1]  =  0;
100
    output[2]  =  0;
101
    output[3]  =  0;
102
    output[4]  =  0;
103
    output[5]  =  2 / (t - b);
104
    output[6]  =  0;
105
    output[7]  =  0;
106
    output[8]  =  0;
107
    output[9]  =  0;
108
    output[10] = -2 / (f - n);
109
    output[11] =  0;
110
    output[12] = -(r + l) / (r - l);
111
    output[13] = -(t + b) / (t - b);
112
    output[14] = -(f + n) / (f - n);
113
    output[15] =  1;
114
    }
115

  
116
///////////////////////////////////////////////////////////////////////////////////////////////////
117

  
118
  public static void setLookAt(float[] output, float eyeX , float eyeY , float eyeZ ,
119
                                               float lookX, float lookY, float lookZ,
120
                                               float upX  , float upY  , float upZ  )
121
    {
122
    // TODO
123
    }
124

  
125
///////////////////////////////////////////////////////////////////////////////////////////////////
126
// this is android.opengl.Matrix.rotateM(), but with pre-computed sin and cos of the angle
127
// and also we have to pre-allocate and pass here two temp arrays.
128

  
129
  public static void rotateSinCos(float[] output, float[] tmp1, float[] tmp2, float sin, float cos, float x, float y, float z)
130
    {
131
    tmp1[0]  = (1-cos)*x*x + cos;
132
    tmp1[1]  = (1-cos)*x*y + sin*z;
133
    tmp1[2]  = (1-cos)*x*z - sin*y;
134
    tmp1[3]  = 0;
135
    tmp1[4]  = (1-cos)*x*y - sin*z;
136
    tmp1[5]  = (1-cos)*y*y + cos;
137
    tmp1[6]  = (1-cos)*y*z + sin*x;
138
    tmp1[7]  = 0;
139
    tmp1[8]  = (1-cos)*x*z + sin*y;
140
    tmp1[9]  = (1-cos)*y*z - sin*x;
141
    tmp1[10] = (1-cos)*z*z + cos;
142
    tmp1[11] = 0;
143
    tmp1[12] = 0;
144
    tmp1[13] = 0;
145
    tmp1[14] = 0;
146
    tmp1[15] = 1;
147

  
148
    tmp2[0]  =  output[ 0];
149
    tmp2[1]  =  output[ 1];
150
    tmp2[2]  =  output[ 2];
151
    tmp2[3]  =  output[ 3];
152
    tmp2[4]  =  output[ 4];
153
    tmp2[5]  =  output[ 5];
154
    tmp2[6]  =  output[ 6];
155
    tmp2[7]  =  output[ 7];
156
    tmp2[8]  =  output[ 8];
157
    tmp2[9]  =  output[ 9];
158
    tmp2[10] =  output[10];
159
    tmp2[11] =  output[11];
160
    tmp2[12] =  output[12];
161
    tmp2[13] =  output[13];
162
    tmp2[14] =  output[14];
163
    tmp2[15] =  output[15];
164

  
165
    multiply(output,tmp2,tmp1);
166
    }
167

  
168
///////////////////////////////////////////////////////////////////////////////////////////////////
169

  
170
  public static void translate(float[] output, float dx, float dy, float dz)
171
    {
172
    output[12] += ( output[ 0]*dx + output[ 4]*dy + output[ 8]*dz);
173
    output[13] += ( output[ 1]*dx + output[ 5]*dy + output[ 9]*dz);
174
    output[14] += ( output[ 2]*dx + output[ 6]*dy + output[10]*dz);
175
    output[15] += ( output[ 3]*dx + output[ 7]*dy + output[11]*dz);
176
    }
177

  
178
///////////////////////////////////////////////////////////////////////////////////////////////////
179

  
180
  public static void scale(float[] output, float sx, float sy, float sz)
181
    {
182
    output[ 0] *= sx;
183
    output[ 1] *= sx;
184
    output[ 2] *= sx;
185
    output[ 3] *= sx;
186

  
187
    output[ 4] *= sy;
188
    output[ 5] *= sy;
189
    output[ 6] *= sy;
190
    output[ 7] *= sy;
191

  
192
    output[ 8] *= sz;
193
    output[ 9] *= sz;
194
    output[10] *= sz;
195
    output[11] *= sz;
196
    }
197
  }
src/main/java/org/distorted/library/helpers/MatrixHelper.kt
1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2023 Leszek Koltunski  leszek@koltunski.pl                                          //
3
//                                                                                               //
4
// This file is part of Distorted.                                                               //
5
//                                                                                               //
6
// This library is free software; you can redistribute it and/or                                 //
7
// modify it under the terms of the GNU Lesser General Public                                    //
8
// License as published by the Free Software Foundation; either                                  //
9
// version 2.1 of the License, or (at your option) any later version.                            //
10
//                                                                                               //
11
// This library is distributed in the hope that it will be useful,                               //
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU                             //
14
// Lesser General Public License for more details.                                               //
15
//                                                                                               //
16
// You should have received a copy of the GNU Lesser General Public                              //
17
// License along with this library; if not, write to the Free Software                           //
18
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA                //
19
///////////////////////////////////////////////////////////////////////////////////////////////////
20

  
21
package org.distorted.library.helpers;
22

  
23
///////////////////////////////////////////////////////////////////////////////////////////////////
24

  
25
public class MatrixHelper
26
  {
27
  public static void setIdentity(float[] output)
28
    {
29
    output[ 0] = 1;
30
    output[ 1] = 0;
31
    output[ 2] = 0;
32
    output[ 3] = 0;
33
    output[ 4] = 0;
34
    output[ 5] = 1;
35
    output[ 6] = 0;
36
    output[ 7] = 0;
37
    output[ 8] = 0;
38
    output[ 9] = 0;
39
    output[10] = 1;
40
    output[11] = 0;
41
    output[12] = 0;
42
    output[13] = 0;
43
    output[14] = 0;
44
    output[15] = 1;
45
    }
46

  
47
///////////////////////////////////////////////////////////////////////////////////////////////////
48

  
49
  public static void multiply(float[] output, float[] m1, float[] m2)
50
    {
51
    output[ 0] = m1[ 0]*m2[ 0] + m1[ 4]*m2[ 1] + m1[ 8]*m2[ 2] + m1[12]*m2[ 3];
52
    output[ 1] = m1[ 1]*m2[ 0] + m1[ 5]*m2[ 1] + m1[ 9]*m2[ 2] + m1[13]*m2[ 3];
53
    output[ 2] = m1[ 2]*m2[ 0] + m1[ 6]*m2[ 1] + m1[10]*m2[ 2] + m1[14]*m2[ 3];
54
    output[ 3] = m1[ 3]*m2[ 0] + m1[ 7]*m2[ 1] + m1[11]*m2[ 2] + m1[15]*m2[ 3];
55

  
56
    output[ 4] = m1[ 0]*m2[ 4] + m1[ 4]*m2[ 5] + m1[ 8]*m2[ 6] + m1[12]*m2[ 7];
57
    output[ 5] = m1[ 1]*m2[ 4] + m1[ 5]*m2[ 5] + m1[ 9]*m2[ 6] + m1[13]*m2[ 7];
58
    output[ 6] = m1[ 2]*m2[ 4] + m1[ 6]*m2[ 5] + m1[10]*m2[ 6] + m1[14]*m2[ 7];
59
    output[ 7] = m1[ 3]*m2[ 4] + m1[ 7]*m2[ 5] + m1[11]*m2[ 6] + m1[15]*m2[ 7];
60

  
61
    output[ 8] = m1[ 0]*m2[ 8] + m1[ 4]*m2[ 9] + m1[ 8]*m2[10] + m1[12]*m2[11];
62
    output[ 9] = m1[ 1]*m2[ 8] + m1[ 5]*m2[ 9] + m1[ 9]*m2[10] + m1[13]*m2[11];
63
    output[10] = m1[ 2]*m2[ 8] + m1[ 6]*m2[ 9] + m1[10]*m2[10] + m1[14]*m2[11];
64
    output[11] = m1[ 3]*m2[ 8] + m1[ 7]*m2[ 9] + m1[11]*m2[10] + m1[15]*m2[11];
65

  
66
    output[12] = m1[ 0]*m2[12] + m1[ 4]*m2[13] + m1[ 8]*m2[14] + m1[12]*m2[15];
67
    output[13] = m1[ 1]*m2[12] + m1[ 5]*m2[13] + m1[ 9]*m2[14] + m1[13]*m2[15];
68
    output[14] = m1[ 2]*m2[12] + m1[ 6]*m2[13] + m1[10]*m2[14] + m1[14]*m2[15];
69
    output[15] = m1[ 3]*m2[12] + m1[ 7]*m2[13] + m1[11]*m2[14] + m1[15]*m2[15];
70
    }
71

  
72
///////////////////////////////////////////////////////////////////////////////////////////////////
73

  
74
  public static void frustum(float[] output, float l, float r, float b, float t, float n, float f)
75
    {
76
    output[0]  =  2 * n / (r - l);
77
    output[1]  =  0;
78
    output[2]  =  0;
79
    output[3]  =  0;
80
    output[4]  =  0;
81
    output[5]  =  2 * n / (t - b);
82
    output[6]  =  0;
83
    output[7]  =  0;
84
    output[8]  =  (r + l) / (r - l);
85
    output[9]  =  (t + b) / (t - b);
86
    output[10] = -(f + n) / (f - n);
87
    output[11] = -1;
88
    output[12] =  0;
89
    output[13] =  0;
90
    output[14] = -(2 * f * n) / (f - n);
91
    output[15] =  0;
92
    }
93

  
94
///////////////////////////////////////////////////////////////////////////////////////////////////
95

  
96
  public static void ortho(float[] output, float l, float r, float b, float t, float n, float f)
97
    {
98
    output[0]  =  2 / (r - l);
99
    output[1]  =  0;
100
    output[2]  =  0;
101
    output[3]  =  0;
102
    output[4]  =  0;
103
    output[5]  =  2 / (t - b);
104
    output[6]  =  0;
105
    output[7]  =  0;
106
    output[8]  =  0;
107
    output[9]  =  0;
108
    output[10] = -2 / (f - n);
109
    output[11] =  0;
110
    output[12] = -(r + l) / (r - l);
111
    output[13] = -(t + b) / (t - b);
112
    output[14] = -(f + n) / (f - n);
113
    output[15] =  1;
114
    }
115

  
116
///////////////////////////////////////////////////////////////////////////////////////////////////
117

  
118
  public static void setLookAt(float[] output, float eyeX , float eyeY , float eyeZ ,
119
                                               float lookX, float lookY, float lookZ,
120
                                               float upX  , float upY  , float upZ  )
121
    {
122
    // TODO
123
    }
124

  
125
///////////////////////////////////////////////////////////////////////////////////////////////////
126
// this is android.opengl.Matrix.rotateM(), but with pre-computed sin and cos of the angle
127
// and also we have to pre-allocate and pass here two temp arrays.
128

  
129
  public static void rotateSinCos(float[] output, float[] tmp1, float[] tmp2, float sin, float cos, float x, float y, float z)
130
    {
131
    tmp1[0]  = (1-cos)*x*x + cos;
132
    tmp1[1]  = (1-cos)*x*y + sin*z;
133
    tmp1[2]  = (1-cos)*x*z - sin*y;
134
    tmp1[3]  = 0;
135
    tmp1[4]  = (1-cos)*x*y - sin*z;
136
    tmp1[5]  = (1-cos)*y*y + cos;
137
    tmp1[6]  = (1-cos)*y*z + sin*x;
138
    tmp1[7]  = 0;
139
    tmp1[8]  = (1-cos)*x*z + sin*y;
140
    tmp1[9]  = (1-cos)*y*z - sin*x;
141
    tmp1[10] = (1-cos)*z*z + cos;
142
    tmp1[11] = 0;
143
    tmp1[12] = 0;
144
    tmp1[13] = 0;
145
    tmp1[14] = 0;
146
    tmp1[15] = 1;
147

  
148
    tmp2[0]  =  output[ 0];
149
    tmp2[1]  =  output[ 1];
150
    tmp2[2]  =  output[ 2];
151
    tmp2[3]  =  output[ 3];
152
    tmp2[4]  =  output[ 4];
153
    tmp2[5]  =  output[ 5];
154
    tmp2[6]  =  output[ 6];
155
    tmp2[7]  =  output[ 7];
156
    tmp2[8]  =  output[ 8];
157
    tmp2[9]  =  output[ 9];
158
    tmp2[10] =  output[10];
159
    tmp2[11] =  output[11];
160
    tmp2[12] =  output[12];
161
    tmp2[13] =  output[13];
162
    tmp2[14] =  output[14];
163
    tmp2[15] =  output[15];
164

  
165
    multiply(output,tmp2,tmp1);
166
    }
167

  
168
///////////////////////////////////////////////////////////////////////////////////////////////////
169

  
170
  public static void translate(float[] output, float dx, float dy, float dz)
171
    {
172
    output[12] += ( output[ 0]*dx + output[ 4]*dy + output[ 8]*dz);
173
    output[13] += ( output[ 1]*dx + output[ 5]*dy + output[ 9]*dz);
174
    output[14] += ( output[ 2]*dx + output[ 6]*dy + output[10]*dz);
175
    output[15] += ( output[ 3]*dx + output[ 7]*dy + output[11]*dz);
176
    }
177

  
178
///////////////////////////////////////////////////////////////////////////////////////////////////
179

  
180
  public static void scale(float[] output, float sx, float sy, float sz)
181
    {
182
    output[ 0] *= sx;
183
    output[ 1] *= sx;
184
    output[ 2] *= sx;
185
    output[ 3] *= sx;
186

  
187
    output[ 4] *= sy;
188
    output[ 5] *= sy;
189
    output[ 6] *= sy;
190
    output[ 7] *= sy;
191

  
192
    output[ 8] *= sz;
193
    output[ 9] *= sz;
194
    output[10] *= sz;
195
    output[11] *= sz;
196
    }
197
  }
src/main/java/org/distorted/library/helpers/QuatHelper.java
1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2021 Leszek Koltunski  leszek@koltunski.pl                                          //
3
//                                                                                               //
4
// This file is part of Distorted.                                                               //
5
//                                                                                               //
6
// This library is free software; you can redistribute it and/or                                 //
7
// modify it under the terms of the GNU Lesser General Public                                    //
8
// License as published by the Free Software Foundation; either                                  //
9
// version 2.1 of the License, or (at your option) any later version.                            //
10
//                                                                                               //
11
// This library is distributed in the hope that it will be useful,                               //
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU                             //
14
// Lesser General Public License for more details.                                               //
15
//                                                                                               //
16
// You should have received a copy of the GNU Lesser General Public                              //
17
// License along with this library; if not, write to the Free Software                           //
18
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA                //
19
///////////////////////////////////////////////////////////////////////////////////////////////////
20

  
21
package org.distorted.library.helpers;
22

  
23
import org.distorted.library.type.Static4D;
24

  
25
///////////////////////////////////////////////////////////////////////////////////////////////////
26

  
27
public class QuatHelper
28
  {
29
///////////////////////////////////////////////////////////////////////////////////////////////////
30
// return quat1*quat2
31

  
32
  public static Static4D quatMultiply( Static4D quat1, Static4D quat2 )
33
    {
34
    float qx = quat1.get0();
35
    float qy = quat1.get1();
36
    float qz = quat1.get2();
37
    float qw = quat1.get3();
38

  
39
    float rx = quat2.get0();
40
    float ry = quat2.get1();
41
    float rz = quat2.get2();
42
    float rw = quat2.get3();
43

  
44
    float tx = rw*qx - rz*qy + ry*qz + rx*qw;
45
    float ty = rw*qy + rz*qx + ry*qw - rx*qz;
46
    float tz = rw*qz + rz*qw - ry*qx + rx*qy;
47
    float tw = rw*qw - rz*qz - ry*qy - rx*qx;
48

  
49
    return new Static4D(tx,ty,tz,tw);
50
    }
51

  
52
///////////////////////////////////////////////////////////////////////////////////////////////////
53
// return quat1*quat2
54

  
55
  public static void quatMultiply( float[] ret, Static4D quat1, Static4D quat2 )
56
    {
57
    float qx = quat1.get0();
58
    float qy = quat1.get1();
59
    float qz = quat1.get2();
60
    float qw = quat1.get3();
61

  
62
    float rx = quat2.get0();
63
    float ry = quat2.get1();
64
    float rz = quat2.get2();
65
    float rw = quat2.get3();
66

  
67
    ret[0] = rw*qx - rz*qy + ry*qz + rx*qw;
68
    ret[1] = rw*qy + rz*qx + ry*qw - rx*qz;
69
    ret[2] = rw*qz + rz*qw - ry*qx + rx*qy;
70
    ret[3] = rw*qw - rz*qz - ry*qy - rx*qx;
71
    }
72

  
73
///////////////////////////////////////////////////////////////////////////////////////////////////
74
// return quat1*quat(rx,ry,rz,rw)
75

  
76
    public static void quatMultiply( float[] ret, Static4D quat1, float rx, float ry, float rz, float rw )
77
      {
78
      float qx = quat1.get0();
79
      float qy = quat1.get1();
80
      float qz = quat1.get2();
81
      float qw = quat1.get3();
82

  
83
      ret[0] = rw*qx - rz*qy + ry*qz + rx*qw;
84
      ret[1] = rw*qy + rz*qx + ry*qw - rx*qz;
85
      ret[2] = rw*qz + rz*qw - ry*qx + rx*qy;
86
      ret[3] = rw*qw - rz*qz - ry*qy - rx*qx;
87
      }
88

  
89
///////////////////////////////////////////////////////////////////////////////////////////////////
90
// return quat1*quat2
91

  
92
  public static float[] quatMultiply( float[] quat1, float[] quat2 )
93
    {
94
    float qx = quat1[0];
95
    float qy = quat1[1];
96
    float qz = quat1[2];
97
    float qw = quat1[3];
98

  
99
    float rx = quat2[0];
100
    float ry = quat2[1];
101
    float rz = quat2[2];
102
    float rw = quat2[3];
103

  
104
    float tx = rw*qx - rz*qy + ry*qz + rx*qw;
105
    float ty = rw*qy + rz*qx + ry*qw - rx*qz;
106
    float tz = rw*qz + rz*qw - ry*qx + rx*qy;
107
    float tw = rw*qw - rz*qz - ry*qy - rx*qx;
108

  
109
    return new float[] {tx,ty,tz,tw};
110
    }
111

  
112
///////////////////////////////////////////////////////////////////////////////////////////////////
113
// return quat1*(rx,ry,rz,rw)
114

  
115
  public static Static4D quatMultiply( Static4D quat, float rx, float ry, float rz, float rw )
116
    {
117
    float qx = quat.get0();
118
    float qy = quat.get1();
119
    float qz = quat.get2();
120
    float qw = quat.get3();
121

  
122
    float tx = rw*qx - rz*qy + ry*qz + rx*qw;
123
    float ty = rw*qy + rz*qx + ry*qw - rx*qz;
124
    float tz = rw*qz + rz*qw - ry*qx + rx*qy;
125
    float tw = rw*qw - rz*qz - ry*qy - rx*qx;
126

  
127
    return new Static4D(tx,ty,tz,tw);
128
    }
129

  
130
///////////////////////////////////////////////////////////////////////////////////////////////////
131
// return (qx,qy,qz,qw)*quat
132

  
133
  public static Static4D quatMultiply( float qx, float qy, float qz, float qw, Static4D quat )
134
    {
135
    float rx = quat.get0();
136
    float ry = quat.get1();
137
    float rz = quat.get2();
138
    float rw = quat.get3();
139

  
140
    float tx = rw*qx - rz*qy + ry*qz + rx*qw;
141
    float ty = rw*qy + rz*qx + ry*qw - rx*qz;
142
    float tz = rw*qz + rz*qw - ry*qx + rx*qy;
143
    float tw = rw*qw - rz*qz - ry*qy - rx*qx;
144

  
145
    return new Static4D(tx,ty,tz,tw);
146
    }
147

  
148
///////////////////////////////////////////////////////////////////////////////////////////////////
149
// return (qx,qy,qz,qw)*(rx,ry,rz,rw)
150

  
151
  public static Static4D quatMultiply( float qx, float qy, float qz, float qw, float rx, float ry, float rz, float rw )
152
    {
153
    float tx = rw*qx - rz*qy + ry*qz + rx*qw;
154
    float ty = rw*qy + rz*qx + ry*qw - rx*qz;
155
    float tz = rw*qz + rz*qw - ry*qx + rx*qy;
156
    float tw = rw*qw - rz*qz - ry*qy - rx*qx;
157

  
158
    return new Static4D(tx,ty,tz,tw);
159
    }
160

  
161
///////////////////////////////////////////////////////////////////////////////////////////////////
162
// ret = (qx,qy,qz,qw)*(rx,ry,rz,rw)
163

  
164
  public static void quatMultiply( float[] ret, float[] q, float[] r )
165
    {
166
    ret[0] = r[3]*q[0] - r[2]*q[1] + r[1]*q[2] + r[0]*q[3];
167
    ret[1] = r[3]*q[1] + r[2]*q[0] + r[1]*q[3] - r[0]*q[2];
168
    ret[2] = r[3]*q[2] + r[2]*q[3] - r[1]*q[0] + r[0]*q[1];
169
    ret[3] = r[3]*q[3] - r[2]*q[2] - r[1]*q[1] - r[0]*q[0];
170
    }
171

  
172
///////////////////////////////////////////////////////////////////////////////////////////////////
173
// ret = (qx,qy,qz,qw)*(rx,ry,rz,rw)
174

  
175
  public static void quatMultiply( float[] ret, Static4D q, float[] r )
176
    {
177
    float q0 = q.get0();
178
    float q1 = q.get1();
179
    float q2 = q.get2();
180
    float q3 = q.get3();
181

  
182
    ret[0] = r[3]*q0 - r[2]*q1 + r[1]*q2 + r[0]*q3;
183
    ret[1] = r[3]*q1 + r[2]*q0 + r[1]*q3 - r[0]*q2;
184
    ret[2] = r[3]*q2 + r[2]*q3 - r[1]*q0 + r[0]*q1;
185
    ret[3] = r[3]*q3 - r[2]*q2 - r[1]*q1 - r[0]*q0;
186
    }
187

  
188
///////////////////////////////////////////////////////////////////////////////////////////////////
189
// ret = (qx,qy,qz,qw)*(rx,ry,rz,rw)
190

  
191
  public static void quatMultiply( float[] ret, float[] q, Static4D r )
192
    {
193
    float r0 = r.get0();
194
    float r1 = r.get1();
195
    float r2 = r.get2();
196
    float r3 = r.get3();
197

  
198
    ret[0] = r3*q[0] - r2*q[1] + r1*q[2] + r0*q[3];
199
    ret[1] = r3*q[1] + r2*q[0] + r1*q[3] - r0*q[2];
200
    ret[2] = r3*q[2] + r2*q[3] - r1*q[0] + r0*q[1];
201
    ret[3] = r3*q[3] - r2*q[2] - r1*q[1] - r0*q[0];
202
    }
203

  
204
///////////////////////////////////////////////////////////////////////////////////////////////////
205
// ret = (qx,qy,qz,qw)*(rx,ry,rz,rw)
206

  
207
  public static void quatMultiply( float[] ret, float qx, float qy, float qz, float qw, float rx, float ry, float rz, float rw )
208
    {
209
    ret[0] = rw*qx - rz*qy + ry*qz + rx*qw;
210
    ret[1] = rw*qy + rz*qx + ry*qw - rx*qz;
211
    ret[2] = rw*qz + rz*qw - ry*qx + rx*qy;
212
    ret[3] = rw*qw - rz*qz - ry*qy - rx*qx;
213
    }
214

  
215
///////////////////////////////////////////////////////////////////////////////////////////////////
216
// ret = (qx,qy,qz,qw)*(rx,ry,rz,rw)
217

  
218
  private static void quatMultiply( float[] ret, int index, float qx, float qy, float qz, float qw, float rx, float ry, float rz, float rw )
219
    {
220
    ret[index  ] = rw*qx - rz*qy + ry*qz + rx*qw;
221
    ret[index+1] = rw*qy + rz*qx + ry*qw - rx*qz;
222
    ret[index+2] = rw*qz + rz*qw - ry*qx + rx*qy;
223
    ret[index+3] = rw*qw - rz*qz - ry*qy - rx*qx;
224
    }
225

  
226
///////////////////////////////////////////////////////////////////////////////////////////////////
227
// rotate (x1,x2,x3,x4) by quat  ( i.e. return quat*vector*(quat^-1) )
228

  
229
  public static Static4D rotateVectorByQuat(float x, float y, float z, float w, Static4D quat)
230
    {
231
    float qx = quat.get0();
232
    float qy = quat.get1();
233
    float qz = quat.get2();
234
    float qw = quat.get3();
235

  
236
    Static4D tmp = quatMultiply(qx,qy,qz,qw,x,y,z,w);
237

  
238
    return quatMultiply(tmp,-qx,-qy,-qz,qw);
239
    }
240

  
241
///////////////////////////////////////////////////////////////////////////////////////////////////
242
// rotate (x1,x2,x3,x4) by quat  ( i.e. return quat*vector*(quat^-1) )
243

  
244
  public static void rotateVectorByQuat(float[] output, float x, float y, float z, float w, Static4D quat)
245
    {
246
    float[] tmp = new float[4];
247

  
248
    float qx = quat.get0();
249
    float qy = quat.get1();
250
    float qz = quat.get2();
251
    float qw = quat.get3();
252

  
253
    quatMultiply(tmp,qx,qy,qz,qw,x,y,z,w);
254
    quatMultiply(output,tmp[0],tmp[1],tmp[2],tmp[3],-qx,-qy,-qz,qw);
255
    }
256

  
257
///////////////////////////////////////////////////////////////////////////////////////////////////
258
// rotate (x1,x2,x3,x4) by quat  ( i.e. return quat*vector*(quat^-1) )
259

  
260
  public static void rotateVectorByQuat(float[] output, int index, float x, float y, float z, float w, Static4D quat)
261
    {
262
    float[] tmp = new float[4];
263

  
264
    float qx = quat.get0();
265
    float qy = quat.get1();
266
    float qz = quat.get2();
267
    float qw = quat.get3();
268

  
269
    quatMultiply(tmp,qx,qy,qz,qw,x,y,z,w);
270
    quatMultiply(output,index,tmp[0],tmp[1],tmp[2],tmp[3],-qx,-qy,-qz,qw);
271
    }
272

  
273
///////////////////////////////////////////////////////////////////////////////////////////////////
274
// rotate (x1,x2,x3,x4) by quat  ( i.e. return quat*vector*(quat^-1) )
275

  
276
  public static void rotateVectorByQuat(float[] output, float x, float y, float z, float w, float[] quat)
277
    {
278
    float[] tmp = new float[4];
279

  
280
    float qx = quat[0];
281
    float qy = quat[1];
282
    float qz = quat[2];
283
    float qw = quat[3];
284

  
285
    quatMultiply(tmp,qx,qy,qz,qw,x,y,z,w);
286
    quatMultiply(output,tmp[0],tmp[1],tmp[2],tmp[3],-qx,-qy,-qz,qw);
287
    }
288

  
289
///////////////////////////////////////////////////////////////////////////////////////////////////
290
// rotate (x1,x2,x3,x4) by quat  ( i.e. return quat*vector*(quat^-1) )
291

  
292
  public static void rotateVectorByQuat(float[] output, int index, float x, float y, float z, float w, float[] quat)
293
    {
294
    float[] tmp = new float[4];
295

  
296
    float qx = quat[0];
297
    float qy = quat[1];
298
    float qz = quat[2];
299
    float qw = quat[3];
300

  
301
    quatMultiply(tmp,qx,qy,qz,qw,x,y,z,w);
302
    quatMultiply(output,index,tmp[0],tmp[1],tmp[2],tmp[3],-qx,-qy,-qz,qw);
303
    }
304

  
305
///////////////////////////////////////////////////////////////////////////////////////////////////
306
// rotate vec by quat ( i.e. return quat*vector*(quat^-1) )
307

  
308
  public static void rotateVectorByQuat(float[] output, float[] vec, float[] quat)
309
    {
310
    float[] tmp = new float[4];
311

  
312
    quatMultiply(tmp,quat,vec);
313

  
314
    quat[0] = -quat[0];
315
    quat[1] = -quat[1];
316
    quat[2] = -quat[2];
317

  
318
    quatMultiply(output,tmp,quat);
319

  
320
    quat[0] = -quat[0];
321
    quat[1] = -quat[1];
322
    quat[2] = -quat[2];
323
    }
324

  
325
///////////////////////////////////////////////////////////////////////////////////////////////////
326
// rotate vec by quat ( i.e. return quat*vector*(quat^-1) )
327

  
328
  public static void rotateVectorByQuat(float[] output, float[] vec, Static4D quat)
329
    {
330
    float[] tmp = new float[4];
331

  
332
    quatMultiply(tmp,quat,vec);
333

  
334
    float x1 = quat.get0();
335
    float y1 = quat.get1();
336
    float z1 = quat.get2();
337
    float w1 = quat.get3();
338
    quat.set(-x1,-y1,-z1,w1);
339

  
340
    quatMultiply(output,tmp,quat);
341

  
342
    float x2 = quat.get0();
343
    float y2 = quat.get1();
344
    float z2 = quat.get2();
345
    float w2 = quat.get3();
346
    quat.set(-x2,-y2,-z2,w2);
347
    }
348

  
349
///////////////////////////////////////////////////////////////////////////////////////////////////
350
// rotate 'vector' by quat  ( i.e. return quat*vector*(quat^-1) )
351

  
352
  public static Static4D rotateVectorByQuat(Static4D vector, Static4D quat)
353
    {
354
    float qx = quat.get0();
355
    float qy = quat.get1();
356
    float qz = quat.get2();
357
    float qw = quat.get3();
358

  
359
    Static4D tmp = quatMultiply(qx,qy,qz,qw,vector);
360

  
361
    return quatMultiply(tmp,-qx,-qy,-qz,qw);
362
    }
363

  
364
///////////////////////////////////////////////////////////////////////////////////////////////////
365
// rotate 'vector' by quat^(-1)  ( i.e. return (quat^-1)*vector*quat )
366

  
367
  public static Static4D rotateVectorByInvertedQuat(Static4D vector, Static4D quat)
368
    {
369
    float qx = quat.get0();
370
    float qy = quat.get1();
371
    float qz = quat.get2();
372
    float qw = quat.get3();
373

  
374
    Static4D tmp = quatMultiply(-qx,-qy,-qz,qw,vector);
375

  
376
    return quatMultiply(tmp,qx,qy,qz,qw);
377
    }
378

  
379
///////////////////////////////////////////////////////////////////////////////////////////////////
380
// rotate 'vector' by quat^(-1)  ( i.e. return (quat^-1)*vector*quat )
381

  
382
    public static void rotateVectorByInvertedQuat(float[] output, float x, float y, float z, float w, float[] quat)
383
      {
384
      float[] tmp = new float[4];
385

  
386
      float qx = quat[0];
387
      float qy = quat[1];
388
      float qz = quat[2];
389
      float qw = quat[3];
390

  
391
      quatMultiply(tmp,-qx,-qy,-qz,qw,x,y,z,w);
392
      quatMultiply(output,tmp[0],tmp[1],tmp[2],tmp[3],qx,qy,qz,qw);
393
      }
394

  
395
///////////////////////////////////////////////////////////////////////////////////////////////////
396
// rotate 'vector' by quat^(-1)  ( i.e. return (quat^-1)*vector*quat )
397

  
398
  public static void rotateVectorByInvertedQuat(float[] output, float x, float y, float z, float w, Static4D quat)
399
    {
400
    float[] tmp = new float[4];
401

  
402
    float qx = quat.get0();
403
    float qy = quat.get1();
404
    float qz = quat.get2();
405
    float qw = quat.get3();
406

  
407
    quatMultiply(tmp,-qx,-qy,-qz,qw,x,y,z,w);
408
    quatMultiply(output,tmp[0],tmp[1],tmp[2],tmp[3],qx,qy,qz,qw);
409
    }
410

  
411
///////////////////////////////////////////////////////////////////////////////////////////////////
412

  
413
  public static Static4D quatFromDrag(float dragX, float dragY)
414
    {
415
    float axisX = dragY;  // inverted X and Y - rotation axis is perpendicular to (dragX,dragY)
416
    float axisY = dragX;  // Why not (-dragY, dragX) ? because Y axis is also inverted!
417
    float axisZ = 0;
418
    float axisL = (float)Math.sqrt(axisX*axisX + axisY*axisY + axisZ*axisZ);
419

  
420
    if( axisL>0 )
421
      {
422
      axisX /= axisL;
423
      axisY /= axisL;
424
      axisZ /= axisL;
425

  
426
      float ratio = axisL;
427
      ratio = ratio - (int)ratio;     // the cos() is only valid in (0,Pi)
428

  
429
      float cosA = (float)Math.cos(Math.PI*ratio);
430
      float sinA = (float)Math.sqrt(1-cosA*cosA);
431

  
432
      return new Static4D(axisX*sinA, axisY*sinA, axisZ*sinA, cosA);
433
      }
434

  
435
    return new Static4D(0f, 0f, 0f, 1f);
436
    }
437

  
438
///////////////////////////////////////////////////////////////////////////////////////////////////
439

  
440
  public static double computeCos(double oldX, double oldY, double newX, double newY, double len1, double len2)
441
    {
442
    double ret= (oldX*newX+oldY*newY) / (len1*len2);
443
    if( ret<-1.0 ) return -1.0;
444
    if( ret> 1.0 ) return  1.0;
445

  
446
    return ret;
447
    }
448

  
449
///////////////////////////////////////////////////////////////////////////////////////////////////
450
// sin of (signed!) angle between vectors 'old' and 'new', counterclockwise!
451

  
452
  public static double computeSin(double oldX, double oldY, double newX, double newY, double len1, double len2)
453
    {
454
    double ret= (newX*oldY-oldX*newY) / (len1*len2);
455
    if( ret<-1.0 ) return -1.0;
456
    if( ret> 1.0 ) return  1.0;
457

  
458
    return ret;
459
    }
460

  
461
///////////////////////////////////////////////////////////////////////////////////////////////////
462
// return quat Q that turns 3D vector A=(ax,ay,az) to another 3D vector B=(bx,by,bz)
463
// take care of double-cover by ensuring that always Q.get3() >=0
464

  
465
  public static Static4D retRotationQuat(float ax, float ay, float az, float bx, float by, float bz)
466
    {
467
    float nx = ay*bz - az*by;
468
    float ny = az*bx - ax*bz;
469
    float nz = ax*by - ay*bx;
470

  
471
    float sin = (float)Math.sqrt(nx*nx + ny*ny + nz*nz);
472
    float cos = ax*bx + ay*by + az*bz;
473

  
474
    if( sin!=0 )
475
      {
476
      nx /= sin;
477
      ny /= sin;
478
      nz /= sin;
479
      }
480

  
481
    // Why sin<=0 and cos>=0 ?
482
    // 0<angle<180 -> 0<halfAngle<90 -> both sin and cos are positive.
483
    // But1: quats work counterclockwise -> negate cos.
484
    // But2: double-cover, we prefer to have the cos positive (so that unit=(0,0,0,1))
485
    // so negate again both cos and sin.
486
    float sinHalf =-(float)Math.sqrt((1-cos)/2);
487
    float cosHalf = (float)Math.sqrt((1+cos)/2);
488

  
489
    return new Static4D(nx*sinHalf,ny*sinHalf,nz*sinHalf,cosHalf);
490
    }
491
  }
src/main/java/org/distorted/library/helpers/QuatHelper.kt
1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2021 Leszek Koltunski  leszek@koltunski.pl                                          //
3
//                                                                                               //
4
// This file is part of Distorted.                                                               //
5
//                                                                                               //
6
// This library is free software; you can redistribute it and/or                                 //
7
// modify it under the terms of the GNU Lesser General Public                                    //
8
// License as published by the Free Software Foundation; either                                  //
9
// version 2.1 of the License, or (at your option) any later version.                            //
10
//                                                                                               //
11
// This library is distributed in the hope that it will be useful,                               //
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU                             //
14
// Lesser General Public License for more details.                                               //
15
//                                                                                               //
16
// You should have received a copy of the GNU Lesser General Public                              //
17
// License along with this library; if not, write to the Free Software                           //
18
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA                //
19
///////////////////////////////////////////////////////////////////////////////////////////////////
20

  
21
package org.distorted.library.helpers;
22

  
23
import org.distorted.library.type.Static4D;
24

  
25
///////////////////////////////////////////////////////////////////////////////////////////////////
26

  
27
public class QuatHelper
28
  {
29
///////////////////////////////////////////////////////////////////////////////////////////////////
30
// return quat1*quat2
31

  
32
  public static Static4D quatMultiply( Static4D quat1, Static4D quat2 )
33
    {
34
    float qx = quat1.get0();
35
    float qy = quat1.get1();
36
    float qz = quat1.get2();
37
    float qw = quat1.get3();
38

  
39
    float rx = quat2.get0();
40
    float ry = quat2.get1();
41
    float rz = quat2.get2();
42
    float rw = quat2.get3();
43

  
44
    float tx = rw*qx - rz*qy + ry*qz + rx*qw;
45
    float ty = rw*qy + rz*qx + ry*qw - rx*qz;
46
    float tz = rw*qz + rz*qw - ry*qx + rx*qy;
47
    float tw = rw*qw - rz*qz - ry*qy - rx*qx;
48

  
49
    return new Static4D(tx,ty,tz,tw);
50
    }
51

  
52
///////////////////////////////////////////////////////////////////////////////////////////////////
53
// return quat1*quat2
54

  
55
  public static void quatMultiply( float[] ret, Static4D quat1, Static4D quat2 )
56
    {
57
    float qx = quat1.get0();
58
    float qy = quat1.get1();
59
    float qz = quat1.get2();
60
    float qw = quat1.get3();
61

  
62
    float rx = quat2.get0();
63
    float ry = quat2.get1();
64
    float rz = quat2.get2();
65
    float rw = quat2.get3();
66

  
67
    ret[0] = rw*qx - rz*qy + ry*qz + rx*qw;
68
    ret[1] = rw*qy + rz*qx + ry*qw - rx*qz;
69
    ret[2] = rw*qz + rz*qw - ry*qx + rx*qy;
70
    ret[3] = rw*qw - rz*qz - ry*qy - rx*qx;
71
    }
72

  
73
///////////////////////////////////////////////////////////////////////////////////////////////////
74
// return quat1*quat(rx,ry,rz,rw)
75

  
76
    public static void quatMultiply( float[] ret, Static4D quat1, float rx, float ry, float rz, float rw )
77
      {
78
      float qx = quat1.get0();
79
      float qy = quat1.get1();
80
      float qz = quat1.get2();
81
      float qw = quat1.get3();
82

  
83
      ret[0] = rw*qx - rz*qy + ry*qz + rx*qw;
84
      ret[1] = rw*qy + rz*qx + ry*qw - rx*qz;
85
      ret[2] = rw*qz + rz*qw - ry*qx + rx*qy;
86
      ret[3] = rw*qw - rz*qz - ry*qy - rx*qx;
87
      }
88

  
89
///////////////////////////////////////////////////////////////////////////////////////////////////
90
// return quat1*quat2
91

  
92
  public static float[] quatMultiply( float[] quat1, float[] quat2 )
93
    {
94
    float qx = quat1[0];
95
    float qy = quat1[1];
96
    float qz = quat1[2];
97
    float qw = quat1[3];
98

  
99
    float rx = quat2[0];
100
    float ry = quat2[1];
101
    float rz = quat2[2];
102
    float rw = quat2[3];
103

  
104
    float tx = rw*qx - rz*qy + ry*qz + rx*qw;
105
    float ty = rw*qy + rz*qx + ry*qw - rx*qz;
106
    float tz = rw*qz + rz*qw - ry*qx + rx*qy;
107
    float tw = rw*qw - rz*qz - ry*qy - rx*qx;
108

  
109
    return new float[] {tx,ty,tz,tw};
110
    }
111

  
112
///////////////////////////////////////////////////////////////////////////////////////////////////
113
// return quat1*(rx,ry,rz,rw)
114

  
115
  public static Static4D quatMultiply( Static4D quat, float rx, float ry, float rz, float rw )
116
    {
117
    float qx = quat.get0();
118
    float qy = quat.get1();
119
    float qz = quat.get2();
120
    float qw = quat.get3();
121

  
122
    float tx = rw*qx - rz*qy + ry*qz + rx*qw;
123
    float ty = rw*qy + rz*qx + ry*qw - rx*qz;
124
    float tz = rw*qz + rz*qw - ry*qx + rx*qy;
125
    float tw = rw*qw - rz*qz - ry*qy - rx*qx;
126

  
127
    return new Static4D(tx,ty,tz,tw);
128
    }
129

  
130
///////////////////////////////////////////////////////////////////////////////////////////////////
131
// return (qx,qy,qz,qw)*quat
132

  
133
  public static Static4D quatMultiply( float qx, float qy, float qz, float qw, Static4D quat )
134
    {
135
    float rx = quat.get0();
136
    float ry = quat.get1();
137
    float rz = quat.get2();
138
    float rw = quat.get3();
139

  
140
    float tx = rw*qx - rz*qy + ry*qz + rx*qw;
141
    float ty = rw*qy + rz*qx + ry*qw - rx*qz;
142
    float tz = rw*qz + rz*qw - ry*qx + rx*qy;
143
    float tw = rw*qw - rz*qz - ry*qy - rx*qx;
144

  
145
    return new Static4D(tx,ty,tz,tw);
146
    }
147

  
148
///////////////////////////////////////////////////////////////////////////////////////////////////
149
// return (qx,qy,qz,qw)*(rx,ry,rz,rw)
150

  
151
  public static Static4D quatMultiply( float qx, float qy, float qz, float qw, float rx, float ry, float rz, float rw )
152
    {
153
    float tx = rw*qx - rz*qy + ry*qz + rx*qw;
154
    float ty = rw*qy + rz*qx + ry*qw - rx*qz;
155
    float tz = rw*qz + rz*qw - ry*qx + rx*qy;
156
    float tw = rw*qw - rz*qz - ry*qy - rx*qx;
157

  
158
    return new Static4D(tx,ty,tz,tw);
159
    }
160

  
161
///////////////////////////////////////////////////////////////////////////////////////////////////
162
// ret = (qx,qy,qz,qw)*(rx,ry,rz,rw)
163

  
164
  public static void quatMultiply( float[] ret, float[] q, float[] r )
165
    {
166
    ret[0] = r[3]*q[0] - r[2]*q[1] + r[1]*q[2] + r[0]*q[3];
167
    ret[1] = r[3]*q[1] + r[2]*q[0] + r[1]*q[3] - r[0]*q[2];
168
    ret[2] = r[3]*q[2] + r[2]*q[3] - r[1]*q[0] + r[0]*q[1];
169
    ret[3] = r[3]*q[3] - r[2]*q[2] - r[1]*q[1] - r[0]*q[0];
170
    }
171

  
172
///////////////////////////////////////////////////////////////////////////////////////////////////
173
// ret = (qx,qy,qz,qw)*(rx,ry,rz,rw)
174

  
175
  public static void quatMultiply( float[] ret, Static4D q, float[] r )
176
    {
177
    float q0 = q.get0();
178
    float q1 = q.get1();
179
    float q2 = q.get2();
180
    float q3 = q.get3();
181

  
182
    ret[0] = r[3]*q0 - r[2]*q1 + r[1]*q2 + r[0]*q3;
183
    ret[1] = r[3]*q1 + r[2]*q0 + r[1]*q3 - r[0]*q2;
184
    ret[2] = r[3]*q2 + r[2]*q3 - r[1]*q0 + r[0]*q1;
185
    ret[3] = r[3]*q3 - r[2]*q2 - r[1]*q1 - r[0]*q0;
186
    }
187

  
188
///////////////////////////////////////////////////////////////////////////////////////////////////
189
// ret = (qx,qy,qz,qw)*(rx,ry,rz,rw)
190

  
191
  public static void quatMultiply( float[] ret, float[] q, Static4D r )
192
    {
193
    float r0 = r.get0();
194
    float r1 = r.get1();
195
    float r2 = r.get2();
196
    float r3 = r.get3();
197

  
198
    ret[0] = r3*q[0] - r2*q[1] + r1*q[2] + r0*q[3];
199
    ret[1] = r3*q[1] + r2*q[0] + r1*q[3] - r0*q[2];
200
    ret[2] = r3*q[2] + r2*q[3] - r1*q[0] + r0*q[1];
201
    ret[3] = r3*q[3] - r2*q[2] - r1*q[1] - r0*q[0];
202
    }
203

  
204
///////////////////////////////////////////////////////////////////////////////////////////////////
205
// ret = (qx,qy,qz,qw)*(rx,ry,rz,rw)
206

  
207
  public static void quatMultiply( float[] ret, float qx, float qy, float qz, float qw, float rx, float ry, float rz, float rw )
208
    {
209
    ret[0] = rw*qx - rz*qy + ry*qz + rx*qw;
210
    ret[1] = rw*qy + rz*qx + ry*qw - rx*qz;
211
    ret[2] = rw*qz + rz*qw - ry*qx + rx*qy;
212
    ret[3] = rw*qw - rz*qz - ry*qy - rx*qx;
213
    }
214

  
215
///////////////////////////////////////////////////////////////////////////////////////////////////
216
// ret = (qx,qy,qz,qw)*(rx,ry,rz,rw)
217

  
218
  private static void quatMultiply( float[] ret, int index, float qx, float qy, float qz, float qw, float rx, float ry, float rz, float rw )
219
    {
220
    ret[index  ] = rw*qx - rz*qy + ry*qz + rx*qw;
221
    ret[index+1] = rw*qy + rz*qx + ry*qw - rx*qz;
222
    ret[index+2] = rw*qz + rz*qw - ry*qx + rx*qy;
223
    ret[index+3] = rw*qw - rz*qz - ry*qy - rx*qx;
224
    }
225

  
226
///////////////////////////////////////////////////////////////////////////////////////////////////
227
// rotate (x1,x2,x3,x4) by quat  ( i.e. return quat*vector*(quat^-1) )
228

  
229
  public static Static4D rotateVectorByQuat(float x, float y, float z, float w, Static4D quat)
230
    {
231
    float qx = quat.get0();
232
    float qy = quat.get1();
233
    float qz = quat.get2();
234
    float qw = quat.get3();
235

  
236
    Static4D tmp = quatMultiply(qx,qy,qz,qw,x,y,z,w);
237

  
238
    return quatMultiply(tmp,-qx,-qy,-qz,qw);
239
    }
240

  
241
///////////////////////////////////////////////////////////////////////////////////////////////////
242
// rotate (x1,x2,x3,x4) by quat  ( i.e. return quat*vector*(quat^-1) )
243

  
244
  public static void rotateVectorByQuat(float[] output, float x, float y, float z, float w, Static4D quat)
245
    {
246
    float[] tmp = new float[4];
247

  
248
    float qx = quat.get0();
249
    float qy = quat.get1();
250
    float qz = quat.get2();
251
    float qw = quat.get3();
252

  
253
    quatMultiply(tmp,qx,qy,qz,qw,x,y,z,w);
254
    quatMultiply(output,tmp[0],tmp[1],tmp[2],tmp[3],-qx,-qy,-qz,qw);
255
    }
256

  
257
///////////////////////////////////////////////////////////////////////////////////////////////////
258
// rotate (x1,x2,x3,x4) by quat  ( i.e. return quat*vector*(quat^-1) )
259

  
260
  public static void rotateVectorByQuat(float[] output, int index, float x, float y, float z, float w, Static4D quat)
261
    {
262
    float[] tmp = new float[4];
263

  
264
    float qx = quat.get0();
265
    float qy = quat.get1();
266
    float qz = quat.get2();
267
    float qw = quat.get3();
268

  
269
    quatMultiply(tmp,qx,qy,qz,qw,x,y,z,w);
270
    quatMultiply(output,index,tmp[0],tmp[1],tmp[2],tmp[3],-qx,-qy,-qz,qw);
271
    }
272

  
273
///////////////////////////////////////////////////////////////////////////////////////////////////
274
// rotate (x1,x2,x3,x4) by quat  ( i.e. return quat*vector*(quat^-1) )
275

  
276
  public static void rotateVectorByQuat(float[] output, float x, float y, float z, float w, float[] quat)
277
    {
278
    float[] tmp = new float[4];
279

  
280
    float qx = quat[0];
281
    float qy = quat[1];
282
    float qz = quat[2];
283
    float qw = quat[3];
284

  
285
    quatMultiply(tmp,qx,qy,qz,qw,x,y,z,w);
286
    quatMultiply(output,tmp[0],tmp[1],tmp[2],tmp[3],-qx,-qy,-qz,qw);
287
    }
288

  
289
///////////////////////////////////////////////////////////////////////////////////////////////////
290
// rotate (x1,x2,x3,x4) by quat  ( i.e. return quat*vector*(quat^-1) )
291

  
292
  public static void rotateVectorByQuat(float[] output, int index, float x, float y, float z, float w, float[] quat)
293
    {
294
    float[] tmp = new float[4];
295

  
296
    float qx = quat[0];
297
    float qy = quat[1];
298
    float qz = quat[2];
299
    float qw = quat[3];
300

  
301
    quatMultiply(tmp,qx,qy,qz,qw,x,y,z,w);
302
    quatMultiply(output,index,tmp[0],tmp[1],tmp[2],tmp[3],-qx,-qy,-qz,qw);
303
    }
304

  
305
///////////////////////////////////////////////////////////////////////////////////////////////////
306
// rotate vec by quat ( i.e. return quat*vector*(quat^-1) )
307

  
308
  public static void rotateVectorByQuat(float[] output, float[] vec, float[] quat)
309
    {
310
    float[] tmp = new float[4];
311

  
312
    quatMultiply(tmp,quat,vec);
313

  
314
    quat[0] = -quat[0];
315
    quat[1] = -quat[1];
316
    quat[2] = -quat[2];
317

  
318
    quatMultiply(output,tmp,quat);
319

  
320
    quat[0] = -quat[0];
321
    quat[1] = -quat[1];
322
    quat[2] = -quat[2];
323
    }
324

  
325
///////////////////////////////////////////////////////////////////////////////////////////////////
326
// rotate vec by quat ( i.e. return quat*vector*(quat^-1) )
327

  
328
  public static void rotateVectorByQuat(float[] output, float[] vec, Static4D quat)
329
    {
330
    float[] tmp = new float[4];
331

  
332
    quatMultiply(tmp,quat,vec);
333

  
334
    float x1 = quat.get0();
335
    float y1 = quat.get1();
336
    float z1 = quat.get2();
337
    float w1 = quat.get3();
338
    quat.set(-x1,-y1,-z1,w1);
339

  
340
    quatMultiply(output,tmp,quat);
341

  
342
    float x2 = quat.get0();
343
    float y2 = quat.get1();
344
    float z2 = quat.get2();
345
    float w2 = quat.get3();
346
    quat.set(-x2,-y2,-z2,w2);
347
    }
348

  
349
///////////////////////////////////////////////////////////////////////////////////////////////////
350
// rotate 'vector' by quat  ( i.e. return quat*vector*(quat^-1) )
351

  
352
  public static Static4D rotateVectorByQuat(Static4D vector, Static4D quat)
353
    {
354
    float qx = quat.get0();
355
    float qy = quat.get1();
356
    float qz = quat.get2();
357
    float qw = quat.get3();
358

  
359
    Static4D tmp = quatMultiply(qx,qy,qz,qw,vector);
360

  
361
    return quatMultiply(tmp,-qx,-qy,-qz,qw);
362
    }
363

  
364
///////////////////////////////////////////////////////////////////////////////////////////////////
365
// rotate 'vector' by quat^(-1)  ( i.e. return (quat^-1)*vector*quat )
366

  
367
  public static Static4D rotateVectorByInvertedQuat(Static4D vector, Static4D quat)
368
    {
369
    float qx = quat.get0();
370
    float qy = quat.get1();
371
    float qz = quat.get2();
372
    float qw = quat.get3();
373

  
374
    Static4D tmp = quatMultiply(-qx,-qy,-qz,qw,vector);
375

  
376
    return quatMultiply(tmp,qx,qy,qz,qw);
377
    }
378

  
379
///////////////////////////////////////////////////////////////////////////////////////////////////
380
// rotate 'vector' by quat^(-1)  ( i.e. return (quat^-1)*vector*quat )
381

  
382
    public static void rotateVectorByInvertedQuat(float[] output, float x, float y, float z, float w, float[] quat)
383
      {
384
      float[] tmp = new float[4];
385

  
386
      float qx = quat[0];
387
      float qy = quat[1];
388
      float qz = quat[2];
389
      float qw = quat[3];
390

  
391
      quatMultiply(tmp,-qx,-qy,-qz,qw,x,y,z,w);
392
      quatMultiply(output,tmp[0],tmp[1],tmp[2],tmp[3],qx,qy,qz,qw);
393
      }
394

  
395
///////////////////////////////////////////////////////////////////////////////////////////////////
396
// rotate 'vector' by quat^(-1)  ( i.e. return (quat^-1)*vector*quat )
397

  
398
  public static void rotateVectorByInvertedQuat(float[] output, float x, float y, float z, float w, Static4D quat)
399
    {
400
    float[] tmp = new float[4];
401

  
402
    float qx = quat.get0();
403
    float qy = quat.get1();
404
    float qz = quat.get2();
405
    float qw = quat.get3();
406

  
407
    quatMultiply(tmp,-qx,-qy,-qz,qw,x,y,z,w);
408
    quatMultiply(output,tmp[0],tmp[1],tmp[2],tmp[3],qx,qy,qz,qw);
409
    }
410

  
411
///////////////////////////////////////////////////////////////////////////////////////////////////
412

  
413
  public static Static4D quatFromDrag(float dragX, float dragY)
414
    {
415
    float axisX = dragY;  // inverted X and Y - rotation axis is perpendicular to (dragX,dragY)
416
    float axisY = dragX;  // Why not (-dragY, dragX) ? because Y axis is also inverted!
417
    float axisZ = 0;
418
    float axisL = (float)Math.sqrt(axisX*axisX + axisY*axisY + axisZ*axisZ);
419

  
420
    if( axisL>0 )
421
      {
422
      axisX /= axisL;
423
      axisY /= axisL;
424
      axisZ /= axisL;
425

  
426
      float ratio = axisL;
427
      ratio = ratio - (int)ratio;     // the cos() is only valid in (0,Pi)
428

  
429
      float cosA = (float)Math.cos(Math.PI*ratio);
430
      float sinA = (float)Math.sqrt(1-cosA*cosA);
431

  
432
      return new Static4D(axisX*sinA, axisY*sinA, axisZ*sinA, cosA);
433
      }
434

  
435
    return new Static4D(0f, 0f, 0f, 1f);
436
    }
437

  
438
///////////////////////////////////////////////////////////////////////////////////////////////////
439

  
440
  public static double computeCos(double oldX, double oldY, double newX, double newY, double len1, double len2)
441
    {
442
    double ret= (oldX*newX+oldY*newY) / (len1*len2);
443
    if( ret<-1.0 ) return -1.0;
444
    if( ret> 1.0 ) return  1.0;
445

  
446
    return ret;
447
    }
448

  
449
///////////////////////////////////////////////////////////////////////////////////////////////////
450
// sin of (signed!) angle between vectors 'old' and 'new', counterclockwise!
451

  
452
  public static double computeSin(double oldX, double oldY, double newX, double newY, double len1, double len2)
453
    {
454
    double ret= (newX*oldY-oldX*newY) / (len1*len2);
455
    if( ret<-1.0 ) return -1.0;
456
    if( ret> 1.0 ) return  1.0;
457

  
458
    return ret;
459
    }
460

  
461
///////////////////////////////////////////////////////////////////////////////////////////////////
462
// return quat Q that turns 3D vector A=(ax,ay,az) to another 3D vector B=(bx,by,bz)
463
// take care of double-cover by ensuring that always Q.get3() >=0
464

  
465
  public static Static4D retRotationQuat(float ax, float ay, float az, float bx, float by, float bz)
466
    {
467
    float nx = ay*bz - az*by;
468
    float ny = az*bx - ax*bz;
469
    float nz = ax*by - ay*bx;
470

  
471
    float sin = (float)Math.sqrt(nx*nx + ny*ny + nz*nz);
472
    float cos = ax*bx + ay*by + az*bz;
473

  
474
    if( sin!=0 )
475
      {
476
      nx /= sin;
477
      ny /= sin;
478
      nz /= sin;
479
      }
480

  
481
    // Why sin<=0 and cos>=0 ?
482
    // 0<angle<180 -> 0<halfAngle<90 -> both sin and cos are positive.
483
    // But1: quats work counterclockwise -> negate cos.
484
    // But2: double-cover, we prefer to have the cos positive (so that unit=(0,0,0,1))
485
    // so negate again both cos and sin.
486
    float sinHalf =-(float)Math.sqrt((1-cos)/2);
487
    float cosHalf = (float)Math.sqrt((1+cos)/2);
488

  
489
    return new Static4D(nx*sinHalf,ny*sinHalf,nz*sinHalf,cosHalf);
490
    }
491
  }

Also available in: Unified diff