Project

General

Profile

Download (6.34 KB) Statistics
| Branch: | Tag: | Revision:

magiccube / src / main / java / org / distorted / objectlib / QuatHelper.java @ 588ace55

1 b9d4aa3b Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2021 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube is free software: you can redistribute it and/or modify                            //
7
// it under the terms of the GNU General Public License as published by                          //
8
// the Free Software Foundation, either version 2 of the License, or                             //
9
// (at your option) any later version.                                                           //
10
//                                                                                               //
11
// Magic Cube 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                                 //
14
// GNU General Public License for more details.                                                  //
15
//                                                                                               //
16
// You should have received a copy of the GNU General Public License                             //
17
// along with Magic Cube.  If not, see <http://www.gnu.org/licenses/>.                           //
18
///////////////////////////////////////////////////////////////////////////////////////////////////
19
20 588ace55 Leszek Koltunski
package org.distorted.objectlib;
21 b9d4aa3b Leszek Koltunski
22
import org.distorted.library.type.Static4D;
23
24
///////////////////////////////////////////////////////////////////////////////////////////////////
25
26
public class QuatHelper
27
  {
28
///////////////////////////////////////////////////////////////////////////////////////////////////
29
// return quat1*quat2
30
31 7aa4c349 Leszek Koltunski
  public static Static4D quatMultiply( Static4D quat1, Static4D quat2 )
32
    {
33
    float qx = quat1.get0();
34
    float qy = quat1.get1();
35
    float qz = quat1.get2();
36
    float qw = quat1.get3();
37
38
    float rx = quat2.get0();
39
    float ry = quat2.get1();
40
    float rz = quat2.get2();
41
    float rw = quat2.get3();
42
43
    float tx = rw*qx - rz*qy + ry*qz + rx*qw;
44
    float ty = rw*qy + rz*qx + ry*qw - rx*qz;
45
    float tz = rw*qz + rz*qw - ry*qx + rx*qy;
46
    float tw = rw*qw - rz*qz - ry*qy - rx*qx;
47
48
    return new Static4D(tx,ty,tz,tw);
49
    }
50 b9d4aa3b Leszek Koltunski
51
///////////////////////////////////////////////////////////////////////////////////////////////////
52
// rotate 'vector' by quat  ( i.e. return quat*vector*(quat^-1) )
53
54 7aa4c349 Leszek Koltunski
  public static Static4D rotateVectorByQuat(Static4D vector, Static4D quat)
55
    {
56
    float qx = quat.get0();
57
    float qy = quat.get1();
58
    float qz = quat.get2();
59
    float qw = quat.get3();
60 b9d4aa3b Leszek Koltunski
61 7aa4c349 Leszek Koltunski
    Static4D quatInverted= new Static4D(-qx,-qy,-qz,qw);
62
    Static4D tmp = quatMultiply(quat,vector);
63 b9d4aa3b Leszek Koltunski
64 7aa4c349 Leszek Koltunski
    return quatMultiply(tmp,quatInverted);
65
    }
66 b9d4aa3b Leszek Koltunski
67
///////////////////////////////////////////////////////////////////////////////////////////////////
68
// rotate 'vector' by quat^(-1)  ( i.e. return (quat^-1)*vector*quat )
69
70 7aa4c349 Leszek Koltunski
  public static Static4D rotateVectorByInvertedQuat(Static4D vector, Static4D quat)
71
    {
72
    float qx = quat.get0();
73
    float qy = quat.get1();
74
    float qz = quat.get2();
75
    float qw = quat.get3();
76
77
    Static4D quatInverted= new Static4D(-qx,-qy,-qz,qw);
78
    Static4D tmp = quatMultiply(quatInverted,vector);
79
80
    return quatMultiply(tmp,quat);
81
    }
82
83
///////////////////////////////////////////////////////////////////////////////////////////////////
84
85
  public static Static4D quatFromDrag(float dragX, float dragY)
86
    {
87
    float axisX = dragY;  // inverted X and Y - rotation axis is perpendicular to (dragX,dragY)
88
    float axisY = dragX;  // Why not (-dragY, dragX) ? because Y axis is also inverted!
89
    float axisZ = 0;
90
    float axisL = (float)Math.sqrt(axisX*axisX + axisY*axisY + axisZ*axisZ);
91
92
    if( axisL>0 )
93 b9d4aa3b Leszek Koltunski
      {
94 7aa4c349 Leszek Koltunski
      axisX /= axisL;
95
      axisY /= axisL;
96
      axisZ /= axisL;
97
98
      float ratio = axisL;
99
      ratio = ratio - (int)ratio;     // the cos() is only valid in (0,Pi)
100 b9d4aa3b Leszek Koltunski
101 7aa4c349 Leszek Koltunski
      float cosA = (float)Math.cos(Math.PI*ratio);
102
      float sinA = (float)Math.sqrt(1-cosA*cosA);
103 b9d4aa3b Leszek Koltunski
104 7aa4c349 Leszek Koltunski
      return new Static4D(axisX*sinA, axisY*sinA, axisZ*sinA, cosA);
105 b9d4aa3b Leszek Koltunski
      }
106
107 7aa4c349 Leszek Koltunski
    return new Static4D(0f, 0f, 0f, 1f);
108
    }
109
110 b9d4aa3b Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
111
112 7aa4c349 Leszek Koltunski
  public static double computeCos(double oldX, double oldY, double newX, double newY, double len1, double len2)
113
    {
114
    double ret= (oldX*newX+oldY*newY) / (len1*len2);
115
    if( ret<-1.0 ) return -1.0;
116
    if( ret> 1.0 ) return  1.0;
117
118
    return ret;
119
    }
120
121
///////////////////////////////////////////////////////////////////////////////////////////////////
122
// sin of (signed!) angle between vectors 'old' and 'new', counterclockwise!
123 b9d4aa3b Leszek Koltunski
124 7aa4c349 Leszek Koltunski
  public static double computeSin(double oldX, double oldY, double newX, double newY, double len1, double len2)
125
    {
126
    double ret= (newX*oldY-oldX*newY) / (len1*len2);
127
    if( ret<-1.0 ) return -1.0;
128
    if( ret> 1.0 ) return  1.0;
129 b9d4aa3b Leszek Koltunski
130 7aa4c349 Leszek Koltunski
    return ret;
131
    }
132 b9d4aa3b Leszek Koltunski
133 7aa4c349 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
134
// return quat Q that turns 3D vector A=(ax,ay,az) to another 3D vector B=(bx,by,bz)
135
// take care of double-cover by ensuring that always Q.get3() >=0
136
137
  public static Static4D retRotationQuat(float ax, float ay, float az, float bx, float by, float bz)
138
    {
139
    float nx = ay*bz - az*by;
140
    float ny = az*bx - ax*bz;
141
    float nz = ax*by - ay*bx;
142 b9d4aa3b Leszek Koltunski
143 7aa4c349 Leszek Koltunski
    float sin = (float)Math.sqrt(nx*nx + ny*ny + nz*nz);
144
    float cos = ax*bx + ay*by + az*bz;
145 b9d4aa3b Leszek Koltunski
146 7aa4c349 Leszek Koltunski
    if( sin!=0 )
147
      {
148
      nx /= sin;
149
      ny /= sin;
150
      nz /= sin;
151 b9d4aa3b Leszek Koltunski
      }
152 7aa4c349 Leszek Koltunski
153
    // Why sin<=0 and cos>=0 ?
154
    // 0<angle<180 -> 0<halfAngle<90 -> both sin and cos are positive.
155
    // But1: quats work counterclockwise -> negate cos.
156
    // But2: double-cover, we prefer to have the cos positive (so that unit=(0,0,0,1))
157
    // so negate again both cos and sin.
158
    float sinHalf =-(float)Math.sqrt((1-cos)/2);
159
    float cosHalf = (float)Math.sqrt((1+cos)/2);
160
161
    return new Static4D(nx*sinHalf,ny*sinHalf,nz*sinHalf,cosHalf);
162
    }
163 b9d4aa3b Leszek Koltunski
  }