Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/g-truc/glm into matrix-int
Browse files Browse the repository at this point in the history
  • Loading branch information
Groovounet committed Mar 5, 2020
2 parents a4bf886 + efbfeca commit 2a65978
Show file tree
Hide file tree
Showing 11 changed files with 400 additions and 5 deletions.
6 changes: 6 additions & 0 deletions .appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,5 +77,11 @@ build_script:

test_script:
- ctest -j4 -C %CONFIGURATION%
- cd ..
- ps: |
mkdir build_test_cmake
cd build_test_cmake
cmake ..\test\cmake\ -G "$env:generator" -Dglm_DIR="$env:APPVEYOR_BUILD_FOLDER/cmake/glm/"
- cmake --build . --config %CONFIGURATION% -- /m /v:minimal

deploy: off
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ CMakeFiles
cmake_install.cmake
install_manifest.txt
*.cmake
!glmConfig.cmake
!glmConfig-version.cmake
# ^ May need to add future .cmake files as exceptions

# Test logs
Expand All @@ -56,3 +58,4 @@ build*
/.vscode
/CMakeSettings.json
.DS_Store
*.swp
195 changes: 190 additions & 5 deletions .travis.yml

Large diffs are not rendered by default.

13 changes: 13 additions & 0 deletions cmake/glm/glmConfig-version.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
set(PACKAGE_VERSION 0.9.9)

if(${PACKAGE_FIND_VERSION_MAJOR} EQUAL 0)
if (${PACKAGE_FIND_VERSION} VERSION_LESS ${GLM_VERSION})
set(PACKAGE_VERSION_COMPATIBLE 1)
endif()
if(${PACKAGE_FIND_VERSION} VERSION_EQUAL ${GLM_VERSION})
set(PACKAGE_VERSION_EXACT 1)
endif()
else()
set(PACKAGE_VERSION_UNSUITABLE 1)
endif()

22 changes: 22 additions & 0 deletions cmake/glm/glmConfig.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
cmake_minimum_required(VERSION 3.2 FATAL_ERROR)
cmake_policy(VERSION 3.2)

set(GLM_VERSION 0.9.9)

get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH)
get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH)
get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH)
if (_IMPORT_PREFIX STREQUAL "/")
set(_IMPORT_PREFIX "")
endif()

# Set the old GLM_INCLUDE_DIRS variable for backwards compatibility
set(GLM_INCLUDE_DIRS ${_IMPORT_PREFIX})

add_library(glm::glm INTERFACE IMPORTED)
set_target_properties(glm::glm PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES ${GLM_INCLUDE_DIRS})

mark_as_advanced(glm_DIR)
set(_IMPORT_PREFIX)

15 changes: 15 additions & 0 deletions glm/ext/quaternion_common.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,21 @@ namespace glm
template<typename T, qualifier Q>
GLM_FUNC_DECL qua<T, Q> slerp(qua<T, Q> const& x, qua<T, Q> const& y, T a);

/// Spherical linear interpolation of two quaternions with multiple spins over rotation axis.
/// The interpolation always take the short path when the spin count is positive and long path
/// when count is negative. Rotation is performed at constant speed.
///
/// @param x A quaternion
/// @param y A quaternion
/// @param a Interpolation factor. The interpolation is defined beyond the range [0, 1].
/// @param k Additional spin count. If Value is negative interpolation will be on "long" path.
///
/// @tparam T A floating-point scalar type
/// @tparam S An integer scalar type
/// @tparam Q A value from qualifier enum
template<typename T, typename S, qualifier Q>
GLM_FUNC_DECL qua<T, Q> slerp(qua<T, Q> const& x, qua<T, Q> const& y, T a, S k);

/// Returns the q conjugate.
///
/// @tparam T A floating-point scalar type
Expand Down
37 changes: 37 additions & 0 deletions glm/ext/quaternion_common.inl
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,43 @@ namespace glm
}
}

template<typename T, typename S, qualifier Q>
GLM_FUNC_QUALIFIER qua<T, Q> slerp(qua<T, Q> const& x, qua<T, Q> const& y, T a, S k)
{
GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'slerp' only accept floating-point inputs");
GLM_STATIC_ASSERT(std::numeric_limits<S>::is_integer, "'slerp' only accept integer for spin count");

qua<T, Q> z = y;

T cosTheta = dot(x, y);

// If cosTheta < 0, the interpolation will take the long way around the sphere.
// To fix this, one quat must be negated.
if (cosTheta < static_cast<T>(0))
{
z = -y;
cosTheta = -cosTheta;
}

// Perform a linear interpolation when cosTheta is close to 1 to avoid side effect of sin(angle) becoming a zero denominator
if (cosTheta > static_cast<T>(1) - epsilon<T>())
{
// Linear interpolation
return qua<T, Q>(
mix(x.w, z.w, a),
mix(x.x, z.x, a),
mix(x.y, z.y, a),
mix(x.z, z.z, a));
}
else
{
// Graphics Gems III, page 96
T angle = acos(cosTheta);
T phi = angle + k * glm::pi<T>();
return (sin(angle - a * phi)* x + sin(a * phi) * z) / sin(angle);
}
}

template<typename T, qualifier Q>
GLM_FUNC_QUALIFIER qua<T, Q> conjugate(qua<T, Q> const& q)
{
Expand Down
5 changes: 5 additions & 0 deletions manual.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
+ [1.2. Using separated headers](#section1_2)
+ [1.3. Using extension headers](#section1_3)
+ [1.4. Dependencies](#section1_4)
+ [1.5. Finding GLM with CMake](#section1_5)
+ [2. Preprocessor configurations](#section2)
+ [2.1. GLM\_FORCE\_MESSAGES: Platform auto detection and default configuration](#section2_1)
+ [2.2. GLM\_FORCE\_PLATFORM\_UNKNOWN: Force GLM to no detect the build platform](#section2_2)
Expand Down Expand Up @@ -274,6 +275,10 @@ glm::mat4 transform(glm::vec2 const& Orientation, glm::vec3 const& Translate, gl

GLM does not depend on external libraries or headers such as `<GL/gl.h>`, [`<GL/glcorearb.h>`](http://www.opengl.org/registry/api/GL/glcorearb.h), `<GLES3/gl3.h>`, `<GL/glu.h>`, or `<windows.h>`.

### <a name="section1_5"></a> 1.5. Finding GLM with CMake

GLM packages a `glmConfig.cmake` and `glmConfig-version.cmake` in the root of the repository and the release archives. To find GLM with CMake you can pass `-Dglm_DIR=<path to glm root>/cmake/glm/` when running CMake. You can then either add `${GLM_INCLUDE_DIRS}` to your target's include directories, or link against the imported `glm::glm` target.

---
<div style="page-break-after: always;"> </div>

Expand Down
8 changes: 8 additions & 0 deletions test/cmake/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
cmake_minimum_required(VERSION 3.2 FATAL_ERROR)
project(test_find_glm)

find_package(glm REQUIRED)

add_executable(test_find_glm test_find_glm.cpp)
target_link_libraries(test_find_glm glm::glm)

22 changes: 22 additions & 0 deletions test/cmake/test_find_glm.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#include <iostream>
#include <glm/glm.hpp>
#include <glm/ext.hpp>

glm::mat4 camera(float Translate, glm::vec2 const& Rotate)
{
glm::mat4 Projection = glm::perspective(glm::pi<float>() * 0.25f, 4.0f / 3.0f, 0.1f, 100.f);
glm::mat4 View = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -Translate));
View = glm::rotate(View, Rotate.y, glm::vec3(-1.0f, 0.0f, 0.0f));
View = glm::rotate(View, Rotate.x, glm::vec3(0.0f, 1.0f, 0.0f));
glm::mat4 Model = glm::scale(glm::mat4(1.0f), glm::vec3(0.5f));
return Projection * View * Model;
}

int main()
{
const glm::mat4 m = camera(1.f, glm::vec2(1.f, 0.5f));
std::cout << "matrix diagonal: " << m[0][0] << ", "
<< m[1][1] << ", " << m[2][2] << ", " << m[3][3] << "\n";
return 0;
}

79 changes: 79 additions & 0 deletions test/gtc/gtc_quaternion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,84 @@ int test_quat_slerp()
return Error;
}

int test_quat_slerp_spins()
{
int Error = 0;

float const Epsilon = 0.0001f;//glm::epsilon<float>();

float sqrt2 = std::sqrt(2.0f) / 2.0f;
glm::quat id(static_cast<float>(1), static_cast<float>(0), static_cast<float>(0), static_cast<float>(0));
glm::quat Y90rot(sqrt2, 0.0f, sqrt2, 0.0f);
glm::quat Y180rot(0.0f, 0.0f, 1.0f, 0.0f);

// Testing a == 0, k == 1
// Must be id
glm::quat id2 = glm::slerp(id, id, 1.0f, 1);
Error += glm::all(glm::equal(id, id2, Epsilon)) ? 0 : 1;

// Testing a == 1, k == 2
// Must be id
glm::quat id3 = glm::slerp(id, id, 1.0f, 2);
Error += glm::all(glm::equal(id, id3, Epsilon)) ? 0 : 1;

// Testing a == 1, k == 1
// Must be 90° rotation on Y : 0 0.7 0 0.7
// Negative quaternion is representing same orientation
glm::quat Y90rot2 = glm::slerp(id, Y90rot, 1.0f, 1);
Error += glm::all(glm::equal(Y90rot, -Y90rot2, Epsilon)) ? 0 : 1;

// Testing a == 1, k == 2
// Must be id
glm::quat Y90rot3 = glm::slerp(id, Y90rot, 8.0f / 9.0f, 2);
Error += glm::all(glm::equal(id, Y90rot3, Epsilon)) ? 0 : 1;

// Testing a == 1, k == 1
// Must be 90° rotation on Y : 0 0.7 0 0.7
glm::quat Y90rot4 = glm::slerp(id, Y90rot, 0.2f, 1);
Error += glm::all(glm::equal(Y90rot, Y90rot4, Epsilon)) ? 0 : 1;

// Testing reverse case
// Must be 45° rotation on Y : 0 0.38 0 0.92
// Negative quaternion is representing same orientation
glm::quat Ym45rot2 = glm::slerp(Y90rot, id, 0.9f, 1);
glm::quat Ym45rot3 = glm::slerp(Y90rot, id, 0.5f);
Error += glm::all(glm::equal(-Ym45rot2, Ym45rot3, Epsilon)) ? 0 : 1;

// Testing against full circle around the sphere instead of shortest path
// Must be 45° rotation on Y
// certainly not a 135° rotation
glm::quat Y45rot3 = glm::slerp(id, -Y90rot, 0.5f, 0);
float Y45angle3 = glm::angle(Y45rot3);
Error += glm::equal(Y45angle3, glm::pi<float>() * 0.25f, Epsilon) ? 0 : 1;
Error += glm::all(glm::equal(Ym45rot3, Y45rot3, Epsilon)) ? 0 : 1;

// Same, but inverted
// Must also be 45° rotation on Y : 0 0.38 0 0.92
// -0 -0.38 -0 -0.92 is ok too
glm::quat Y45rot4 = glm::slerp(-Y90rot, id, 0.5f, 0);
Error += glm::all(glm::equal(Ym45rot2, Y45rot4, Epsilon)) ? 0 : 1;

// Testing q1 = q2 k == 2
// Must be 90° rotation on Y : 0 0.7 0 0.7
glm::quat Y90rot5 = glm::slerp(Y90rot, Y90rot, 0.5f, 2);
Error += glm::all(glm::equal(Y90rot, Y90rot5, Epsilon)) ? 0 : 1;

// Testing 180° rotation
// Must be 90° rotation on almost any axis that is on the XZ plane
glm::quat XZ90rot = glm::slerp(id, -Y90rot, 0.5f, 1);
float XZ90angle = glm::angle(XZ90rot); // Must be PI/4 = 0.78;
Error += glm::equal(XZ90angle, glm::pi<float>() * 1.25f, Epsilon) ? 0 : 1;

// Testing rotation over long arc
// Distance from id to 90° is 270°, so 2/3 of it should be 180°
// Negative quaternion is representing same orientation
glm::quat Neg90rot = glm::slerp(id, Y90rot, 2.0f / 3.0f, -1);
Error += glm::all(glm::equal(Y180rot, -Neg90rot, Epsilon)) ? 0 : 1;

return Error;
}

static int test_quat_mul_vec()
{
int Error(0);
Expand Down Expand Up @@ -260,6 +338,7 @@ int main()
Error += test_quat_normalize();
Error += test_quat_euler();
Error += test_quat_slerp();
Error += test_quat_slerp_spins();
Error += test_identity();

return Error;
Expand Down

0 comments on commit 2a65978

Please sign in to comment.