//============================================================================= // // 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. // // Copyright 2016 Sandia Corporation. // Copyright 2016 UT-Battelle, LLC. // Copyright 2016 Los Alamos National Security. // // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, // 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 #include namespace vtkm { /// \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. /// /// 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. /// template VTKM_EXEC_CONT_EXPORT vtkm::Vec Transform3DPoint(const vtkm::Matrix &matrix, const vtkm::Vec &point) { vtkm::Vec homogeneousPoint(point[0], point[1], point[2], T(1)); return vtkm::Vec( vtkm::dot(vtkm::MatrixGetRow(matrix,0), homogeneousPoint), vtkm::dot(vtkm::MatrixGetRow(matrix,1), homogeneousPoint), vtkm::dot(vtkm::MatrixGetRow(matrix,2), homogeneousPoint)); } /// \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. /// template VTKM_EXEC_CONT_EXPORT vtkm::Vec Transform3DVector(const vtkm::Matrix &matrix, const vtkm::Vec &vector) { vtkm::Vec homogeneousVector(vector[0], vector[1], vector[2], T(0)); homogeneousVector = vtkm::MatrixMultiply(matrix, homogeneousVector); return vtkm::Vec( homogeneousVector[0], homogeneousVector[1], homogeneousVector[2]); } /// \brief Returns a scale matrix. /// /// Given a scale factor for the x, y, and z directions, returns a /// transformation matrix for those scales. /// template VTKM_EXEC_CONT_EXPORT vtkm::Matrix Transform3DScale(const T &scaleX, const T &scaleY, const T &scaleZ) { vtkm::Matrix scaleMatrix(T(0)); scaleMatrix(0,0) = scaleX; scaleMatrix(1,1) = scaleY; scaleMatrix(2,2) = scaleZ; scaleMatrix(3,3) = T(1); 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. /// template VTKM_EXEC_CONT_EXPORT vtkm::Matrix Transform3DScale(const vtkm::Vec &scaleVec) { 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. /// template VTKM_EXEC_CONT_EXPORT vtkm::Matrix Transform3DScale(const T &scale) { return vtkm::Transform3DScale(scale, scale, scale); } /// \brief Returns a translation matrix. /// template VTKM_EXEC_CONT_EXPORT vtkm::Matrix Transform3DTranslate(const T &x, const T &y, const T &z) { vtkm::Matrix translateMatrix; vtkm::MatrixIdentity(translateMatrix); translateMatrix(0,3) = x; translateMatrix(1,3) = y; translateMatrix(2,3) = z; return translateMatrix; } template VTKM_EXEC_CONT_EXPORT vtkm::Matrix Transform3DTranslate(const vtkm::Vec &v) { return vtkm::Transform3DTranslate(v[0], v[1], v[2]); } /// \brief Returns a rotation matrix. /// /// Given an angle (in radians) and an axis of rotation, returns a /// 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. /// /// Note that, unlike with OpenGL, the angle is given in radians, not degrees. /// template VTKM_EXEC_CONT_EXPORT vtkm::Matrix Transform3DRotate(T angleRadians, const vtkm::Vec &axisOfRotation) { const vtkm::Vec normAxis = vtkm::Normal(axisOfRotation); T sinAngle = vtkm::Sin(angleRadians); T cosAngle = vtkm::Cos(angleRadians); vtkm::Matrix matrix; 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); 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); 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); matrix(3,0) = T(0); matrix(3,1) = T(0); matrix(3,2) = T(0); matrix(3,3) = T(1); return matrix; } template VTKM_EXEC_CONT_EXPORT vtkm::Matrix Transform3DRotate(T angleRadians, T x, T y, T z) { return vtkm::Transform3DRotate(angleRadians, vtkm::Vec(x,y,z)); } /// \brief Returns a rotation matrix. /// /// Returns a transformation matrix that rotates around the x axis. /// template VTKM_EXEC_CONT_EXPORT vtkm::Matrix Transform3DRotateX(T angleRadians) { return vtkm::Transform3DRotate(angleRadians, T(1), T(0), T(0)); } /// \brief Returns a rotation matrix. /// /// Returns a transformation matrix that rotates around the y axis. /// template VTKM_EXEC_CONT_EXPORT vtkm::Matrix Transform3DRotateY(T angleRadians) { return vtkm::Transform3DRotate(angleRadians, T(0), T(1), T(0)); } /// \brief Returns a rotation matrix. /// /// Returns a transformation matrix that rotates around the z axis. /// template VTKM_EXEC_CONT_EXPORT vtkm::Matrix Transform3DRotateZ(T angleRadians) { return vtkm::Transform3DRotate(angleRadians, T(0), T(0), T(1)); } } // namespace vtkm #endif //vtk_m_Transform3D_h