Transform3D.h 8.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
//=============================================================================
//
//  Copyright (c) Kitware, Inc.
//  All rights reserved.
//  See LICENSE.txt for details.
//
//  This software is distributed WITHOUT ANY WARRANTY; without even
//  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
//  PURPOSE.  See the above copyright notice for more information.
//
11
//  Copyright 2016 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
12 13 14
//  Copyright 2016 UT-Battelle, LLC.
//  Copyright 2016 Los Alamos National Security.
//
15
//  Under the terms of Contract DE-NA0003525 with NTESS,
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
//  the U.S. Government retains certain rights in this software.
//  Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
//  Laboratory (LANL), the U.S. Government retains certain rights in
//  this software.
//
//=============================================================================
#ifndef vtk_m_Transform3D_h
#define vtk_m_Transform3D_h

// This header file contains a collection of math functions useful in the
// linear transformation of homogeneous points for rendering in 3D.

#include <vtkm/Matrix.h>
#include <vtkm/VectorAnalysis.h>

31 32
namespace vtkm
{
33 34 35 36 37 38

/// \brief Transform a 3D point by a transformation matrix.
///
/// Given a 4x4 transformation matrix and a 3D point, returns the point
/// transformed by the given matrix in homogeneous coordinates.
///
39 40 41 42 43 44
/// This method ignores any change in the fourth component of the transformed
/// homogeneous coordinate, assuming that it is always 1 (that is, the last row
/// of the matrix is 0, 0, 0, 1). This will be true for affine transformations
/// (such as translate, scale, and rotate), but not for perspective
/// transformations.
///
45 46 47
template <typename T>
VTKM_EXEC_CONT vtkm::Vec<T, 3> Transform3DPoint(const vtkm::Matrix<T, 4, 4>& matrix,
                                                const vtkm::Vec<T, 3>& point)
48
{
49
  vtkm::Vec<T, 4> homogeneousPoint(point[0], point[1], point[2], T(1));
50 51 52
  return vtkm::Vec<T, 3>(vtkm::Dot(vtkm::MatrixGetRow(matrix, 0), homogeneousPoint),
                         vtkm::Dot(vtkm::MatrixGetRow(matrix, 1), homogeneousPoint),
                         vtkm::Dot(vtkm::MatrixGetRow(matrix, 2), homogeneousPoint));
53 54
}

55
/// \brief Transform a 3D point by a transformation matrix with perspective.
56 57 58 59
///
/// Given a 4x4 transformation matrix and a 3D point, returns the point
/// transformed by the given matrix in homogeneous coordinates.
///
60
/// Unlike Transform3DPoint, this method honors the fourth component of the
luz.paz's avatar
luz.paz committed
61
/// transformed homogeneous coordinate. This makes it applicable for perspective
62 63
/// transformations, but requires some more computations.
///
64 65 66
template <typename T>
VTKM_EXEC_CONT vtkm::Vec<T, 3> Transform3DPointPerspective(const vtkm::Matrix<T, 4, 4>& matrix,
                                                           const vtkm::Vec<T, 3>& point)
67
{
68
  vtkm::Vec<T, 4> homogeneousPoint(point[0], point[1], point[2], T(1));
69 70 71 72
  T inverseW = 1 / vtkm::Dot(vtkm::MatrixGetRow(matrix, 3), homogeneousPoint);
  return vtkm::Vec<T, 3>(vtkm::Dot(vtkm::MatrixGetRow(matrix, 0), homogeneousPoint) * inverseW,
                         vtkm::Dot(vtkm::MatrixGetRow(matrix, 1), homogeneousPoint) * inverseW,
                         vtkm::Dot(vtkm::MatrixGetRow(matrix, 2), homogeneousPoint) * inverseW);
73 74 75 76 77 78 79 80
}

/// \brief Transform a 3D vector by a transformation matrix.
///
/// Given a 4x4 transformation matrix and a 3D vector, returns the vector
/// transformed by the given matrix in homogeneous coordinates. Unlike points,
/// vectors do not get translated.
///
81 82 83
template <typename T>
VTKM_EXEC_CONT vtkm::Vec<T, 3> Transform3DVector(const vtkm::Matrix<T, 4, 4>& matrix,
                                                 const vtkm::Vec<T, 3>& vector)
84
{
85
  vtkm::Vec<T, 4> homogeneousVector(vector[0], vector[1], vector[2], T(0));
86
  homogeneousVector = vtkm::MatrixMultiply(matrix, homogeneousVector);
87
  return vtkm::Vec<T, 3>(homogeneousVector[0], homogeneousVector[1], homogeneousVector[2]);
88 89 90 91 92 93 94
}

/// \brief Returns a scale matrix.
///
/// Given a scale factor for the x, y, and z directions, returns a
/// transformation matrix for those scales.
///
95
template <typename T>
96 97
VTKM_EXEC_CONT vtkm::Matrix<T, 4, 4> Transform3DScale(const T& scaleX,
                                                      const T& scaleY,
98
                                                      const T& scaleZ)
99
{
100 101 102 103 104
  vtkm::Matrix<T, 4, 4> scaleMatrix(T(0));
  scaleMatrix(0, 0) = scaleX;
  scaleMatrix(1, 1) = scaleY;
  scaleMatrix(2, 2) = scaleZ;
  scaleMatrix(3, 3) = T(1);
105 106 107 108 109 110 111 112
  return scaleMatrix;
}

/// \brief Returns a scale matrix.
///
/// Given a scale factor for the x, y, and z directions (defined in a Vec),
/// returns a transformation matrix for those scales.
///
113 114
template <typename T>
VTKM_EXEC_CONT vtkm::Matrix<T, 4, 4> Transform3DScale(const vtkm::Vec<T, 3>& scaleVec)
115 116 117 118 119 120 121 122 123
{
  return vtkm::Transform3DScale(scaleVec[0], scaleVec[1], scaleVec[2]);
}

/// \brief Returns a scale matrix.
///
/// Given a uniform scale factor, returns a transformation matrix for those
/// scales.
///
124 125
template <typename T>
VTKM_EXEC_CONT vtkm::Matrix<T, 4, 4> Transform3DScale(const T& scale)
126 127 128 129 130 131
{
  return vtkm::Transform3DScale(scale, scale, scale);
}

/// \brief Returns a translation matrix.
///
132 133
template <typename T>
VTKM_EXEC_CONT vtkm::Matrix<T, 4, 4> Transform3DTranslate(const T& x, const T& y, const T& z)
134
{
135
  vtkm::Matrix<T, 4, 4> translateMatrix;
136
  vtkm::MatrixIdentity(translateMatrix);
137 138 139
  translateMatrix(0, 3) = x;
  translateMatrix(1, 3) = y;
  translateMatrix(2, 3) = z;
140 141
  return translateMatrix;
}
142 143
template <typename T>
VTKM_EXEC_CONT vtkm::Matrix<T, 4, 4> Transform3DTranslate(const vtkm::Vec<T, 3>& v)
144 145 146 147 148 149
{
  return vtkm::Transform3DTranslate(v[0], v[1], v[2]);
}

/// \brief Returns a rotation matrix.
///
150
/// Given an angle (in degrees) and an axis of rotation, returns a
151 152 153 154
/// transformation matrix that rotates around the given axis. The rotation
/// follows the right-hand rule, so if the vector points toward the user, the
/// rotation will be counterclockwise.
///
155 156 157
template <typename T>
VTKM_EXEC_CONT vtkm::Matrix<T, 4, 4> Transform3DRotate(T angleDegrees,
                                                       const vtkm::Vec<T, 3>& axisOfRotation)
158
{
159
  T angleRadians = vtkm::Pi_180<T>() * angleDegrees;
160
  const vtkm::Vec<T, 3> normAxis = vtkm::Normal(axisOfRotation);
161 162 163
  T sinAngle = vtkm::Sin(angleRadians);
  T cosAngle = vtkm::Cos(angleRadians);

164
  vtkm::Matrix<T, 4, 4> matrix;
165

166 167 168 169
  matrix(0, 0) = normAxis[0] * normAxis[0] * (1 - cosAngle) + cosAngle;
  matrix(0, 1) = normAxis[0] * normAxis[1] * (1 - cosAngle) - normAxis[2] * sinAngle;
  matrix(0, 2) = normAxis[0] * normAxis[2] * (1 - cosAngle) + normAxis[1] * sinAngle;
  matrix(0, 3) = T(0);
170

171 172 173 174
  matrix(1, 0) = normAxis[1] * normAxis[0] * (1 - cosAngle) + normAxis[2] * sinAngle;
  matrix(1, 1) = normAxis[1] * normAxis[1] * (1 - cosAngle) + cosAngle;
  matrix(1, 2) = normAxis[1] * normAxis[2] * (1 - cosAngle) - normAxis[0] * sinAngle;
  matrix(1, 3) = T(0);
175

176 177 178 179
  matrix(2, 0) = normAxis[2] * normAxis[0] * (1 - cosAngle) - normAxis[1] * sinAngle;
  matrix(2, 1) = normAxis[2] * normAxis[1] * (1 - cosAngle) + normAxis[0] * sinAngle;
  matrix(2, 2) = normAxis[2] * normAxis[2] * (1 - cosAngle) + cosAngle;
  matrix(2, 3) = T(0);
180

181 182 183 184
  matrix(3, 0) = T(0);
  matrix(3, 1) = T(0);
  matrix(3, 2) = T(0);
  matrix(3, 3) = T(1);
185 186 187

  return matrix;
}
188 189
template <typename T>
VTKM_EXEC_CONT vtkm::Matrix<T, 4, 4> Transform3DRotate(T angleDegrees, T x, T y, T z)
190
{
191
  return vtkm::Transform3DRotate(angleDegrees, vtkm::Vec<T, 3>(x, y, z));
192 193 194 195 196 197
}

/// \brief Returns a rotation matrix.
///
/// Returns a transformation matrix that rotates around the x axis.
///
198 199
template <typename T>
VTKM_EXEC_CONT vtkm::Matrix<T, 4, 4> Transform3DRotateX(T angleDegrees)
200
{
201
  return vtkm::Transform3DRotate(angleDegrees, T(1), T(0), T(0));
202 203 204 205 206 207
}

/// \brief Returns a rotation matrix.
///
/// Returns a transformation matrix that rotates around the y axis.
///
208 209
template <typename T>
VTKM_EXEC_CONT vtkm::Matrix<T, 4, 4> Transform3DRotateY(T angleDegrees)
210
{
211
  return vtkm::Transform3DRotate(angleDegrees, T(0), T(1), T(0));
212 213 214 215 216 217
}

/// \brief Returns a rotation matrix.
///
/// Returns a transformation matrix that rotates around the z axis.
///
218 219
template <typename T>
VTKM_EXEC_CONT vtkm::Matrix<T, 4, 4> Transform3DRotateZ(T angleDegrees)
220
{
221
  return vtkm::Transform3DRotate(angleDegrees, T(0), T(0), T(1));
222 223 224 225 226
}

} // namespace vtkm

#endif //vtk_m_Transform3D_h