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

Last change on this file since 2639 was 2612, checked in by ldelgass, 13 years ago

Refactor vtkvis to support setting colormap fields by name/attribute type
rather than always using active scalars/vectors. Also convert common
graphics objects set methods in Renderer to template methods and separate
core and graphics object related methods to separate files.

  • 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) 2011, Purdue Research Foundation
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.