source: trunk/packages/vizservers/vtkvis/RpMath.h @ 3492

Last change on this file since 3492 was 3177, checked in by mmc, 12 years ago

Updated all of the copyright notices to reference the transfer to
the new HUBzero Foundation, LLC.

  • Property svn:eol-style set to native
File size: 5.5 KB
Line 
1/* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2/*
3 * Copyright (C) 2004-2012  HUBzero Foundation, LLC
4 *
5 * Author: Leif Delgass <ldelgass@purdue.edu>
6 */
7
8#ifndef __RAPPTURE_VTKVIS_MATH_H__
9#define __RAPPTURE_VTKVIS_MATH_H__
10
11#include <cmath>
12#include <cstring>
13
14#include <vtkMath.h>
15#include <vtkMatrix4x4.h>
16
17namespace Rappture {
18namespace VtkVis {
19
20/**
21 * \brief Convert a quaternion to an axis/angle rotation
22 *
23 * \param[in] quat Quaternion with scalar first: wxyz
24 * \param[out] angleAxis axis/angle rotation with angle in degrees first
25 */
26inline void quatToAngleAxis(const double quat[4], double angleAxis[4])
27{
28    angleAxis[0] = vtkMath::DegreesFromRadians(2.0 * acos(quat[0]));
29    if (angleAxis[0] < 1.0e-6) {
30        angleAxis[1] = 1;
31        angleAxis[2] = 0;
32        angleAxis[3] = 0;
33    } else {
34        double denom = sqrt(1. - quat[0] * quat[0]);
35        angleAxis[1] = quat[1] / denom;
36        angleAxis[2] = quat[2] / denom;
37        angleAxis[3] = quat[3] / denom;
38    }
39}
40
41/**
42 * \brief Convert an axis/angle rotation to a quaternion
43 *
44 * \param[in] angleAxis axis/angle rotation with angle in degrees first
45 * \param[out] quat Quaternion with scalar first: wxyz
46 */
47inline void angleAxisToQuat(const double angleAxis[4], double quat[4])
48{
49    quat[0] = cos(vtkMath::RadiansFromDegrees(angleAxis[0]) / 2.0);
50    double sinHalfAngle = sin(vtkMath::RadiansFromDegrees(angleAxis[0]) / 2.0);
51    quat[1] = angleAxis[1] * sinHalfAngle;
52    quat[2] = angleAxis[2] * sinHalfAngle;
53    quat[3] = angleAxis[3] * sinHalfAngle;
54}
55
56/**
57 * \brief Fill a vtkMatrix4x4 from a quaternion
58 *
59 * \param[in] quat Quaternion with scalar first: wxyz
60 * \param[out] mat Matrix to be filled in
61 */
62inline void quaternionToMatrix4x4(const double quat[4], vtkMatrix4x4& mat)
63{
64    double ww = quat[0]*quat[0];
65    double wx = quat[0]*quat[1];
66    double wy = quat[0]*quat[2];
67    double wz = quat[0]*quat[3];
68
69    double xx = quat[1]*quat[1];
70    double yy = quat[2]*quat[2];
71    double zz = quat[3]*quat[3];
72
73    double xy = quat[1]*quat[2];
74    double xz = quat[1]*quat[3];
75    double yz = quat[2]*quat[3];
76
77    double rr = xx + yy + zz;
78    // normalization factor, just in case quaternion was not normalized
79    double f = double(1)/double(sqrt(ww + rr));
80    double s = (ww - rr)*f;
81    f *= 2;
82
83    mat[0][0] = xx*f + s;
84    mat[1][0] = (xy + wz)*f;
85    mat[2][0] = (xz - wy)*f;
86
87    mat[0][1] = (xy - wz)*f;
88    mat[1][1] = yy*f + s;
89    mat[2][1] = (yz + wx)*f;
90
91    mat[0][2] = (xz + wy)*f;
92    mat[1][2] = (yz - wx)*f;
93    mat[2][2] = zz*f + s;
94}
95
96/**
97 * \brief Fill a vtkMatrix4x4 from a quaternion, but with the matrix
98 * transposed.
99 *
100 * \param[in] quat Quaternion with scalar first: wxyz
101 * \param[out] mat Matrix to be filled in
102 */
103inline void quaternionToTransposeMatrix4x4(const double quat[4], vtkMatrix4x4& mat)
104{
105    double ww = quat[0]*quat[0];
106    double wx = quat[0]*quat[1];
107    double wy = quat[0]*quat[2];
108    double wz = quat[0]*quat[3];
109
110    double xx = quat[1]*quat[1];
111    double yy = quat[2]*quat[2];
112    double zz = quat[3]*quat[3];
113
114    double xy = quat[1]*quat[2];
115    double xz = quat[1]*quat[3];
116    double yz = quat[2]*quat[3];
117
118    double rr = xx + yy + zz;
119    // normalization factor, just in case quaternion was not normalized
120    double f = double(1)/double(sqrt(ww + rr));
121    double s = (ww - rr)*f;
122    f *= 2;
123
124    mat[0][0] = xx*f + s;
125    mat[0][1] = (xy + wz)*f;
126    mat[0][2] = (xz - wy)*f;
127
128    mat[1][0] = (xy - wz)*f;
129    mat[1][1] = yy*f + s;
130    mat[1][2] = (yz + wx)*f;
131
132    mat[2][0] = (xz + wy)*f;
133    mat[2][1] = (yz - wx)*f;
134    mat[2][2] = zz*f + s;
135}
136
137/**
138 * \brief Multiply two quaternions and return the result
139 *
140 * Note: result can be the same memory location as one of the
141 * inputs
142 */
143inline double *quatMult(const double q1[4], const double q2[4], double result[4])
144{
145    double q1w = q1[0];
146    double q1x = q1[1];
147    double q1y = q1[2];
148    double q1z = q1[3];
149    double q2w = q2[0];
150    double q2x = q2[1];
151    double q2y = q2[2];
152    double q2z = q2[3];
153    result[0] = (q1w*q2w) - (q1x*q2x) - (q1y*q2y) - (q1z*q2z);
154    result[1] = (q1w*q2x) + (q1x*q2w) + (q1y*q2z) - (q1z*q2y);
155    result[2] = (q1w*q2y) + (q1y*q2w) + (q1z*q2x) - (q1x*q2z);
156    result[3] = (q1w*q2z) + (q1z*q2w) + (q1x*q2y) - (q1y*q2x);
157    return result;
158}
159
160/**
161 * \brief Compute the conjugate of a quaternion
162 *
163 * Note: result can be the same memory location as the input
164 */
165inline double *quatConjugate(const double quat[4], double result[4])
166{
167    if (result != quat)
168        result[0] = quat[0];
169    result[1] = -quat[1];
170    result[2] = -quat[2];
171    result[3] = -quat[3];
172    return result;
173}
174
175/**
176 * \brief Compute the reciprocal of a quaternion
177 *
178 * Note: result can be the same memory location as the input
179 */
180inline double *quatReciprocal(const double quat[4], double result[4])
181{
182    double denom =
183        quat[0]*quat[0] +
184        quat[1]*quat[1] +
185        quat[2]*quat[2] +
186        quat[3]*quat[3];
187    Rappture::VtkVis::quatConjugate(quat, result);
188    for (int i = 0; i < 4; i++) {
189        result[i] /= denom;
190    }
191    return result;
192}
193
194/**
195 * \brief Compute the reciprocal of a quaternion in place
196 */
197inline double *quatReciprocal(double quat[4])
198{
199    return Rappture::VtkVis::quatReciprocal(quat, quat);
200}
201
202/**
203 * \brief Deep copy a quaternion
204 */
205inline void copyQuat(const double quat[4], double result[4])
206{
207    memcpy(result, quat, sizeof(double)*4);
208}
209
210inline double min2(double a, double b)
211{
212    return ((a < b) ? a : b);
213}
214
215inline double max2(double a, double b)
216{
217    return ((a > b) ? a : b);
218}
219
220}
221}
222
223#endif
Note: See TracBrowser for help on using the repository browser.