diff --git a/examples/common/matrix.cc b/examples/common/matrix.cc index 4d905c6..0bc16db 100644 --- a/examples/common/matrix.cc +++ b/examples/common/matrix.cc @@ -99,6 +99,28 @@ void Matrix::LookAt(float m[4][4], float eye[3], float lookat[3], #endif } +void Matrix::Identity(float m[4][4]) { + m[0][0] = 1.0f; + m[0][1] = 0.0f; + m[0][2] = 0.0f; + m[0][3] = 0.0f; + + m[1][0] = 0.0f; + m[1][1] = 1.0f; + m[1][2] = 0.0f; + m[1][3] = 0.0f; + + m[2][0] = 0.0f; + m[2][1] = 0.0f; + m[2][2] = 1.0f; + m[2][3] = 0.0f; + + m[3][0] = 0.0f; + m[3][1] = 0.0f; + m[3][2] = 0.0f; + m[3][3] = 1.0f; +} + void Matrix::Inverse(float m[4][4]) { /* * codes from intel web @@ -195,7 +217,16 @@ void Matrix::Inverse(float m[4][4]) { } } -void Matrix::Mult(float dst[4][4], float m0[4][4], float m1[4][4]) { +void Matrix::Add(float dst[4][4], const float m0[4][4], const float m1[4][4]) { + for (int i = 0; i < 4; ++i) { + for (int j = 0; j < 4; ++j) { + dst[i][j] += m0[i][j] + m1[i][j]; + } + } +} + + +void Matrix::Mult(float dst[4][4], const float m0[4][4], const float m1[4][4]) { for (int i = 0; i < 4; ++i) { for (int j = 0; j < 4; ++j) { dst[i][j] = 0; @@ -206,7 +237,7 @@ void Matrix::Mult(float dst[4][4], float m0[4][4], float m1[4][4]) { } } -void Matrix::MultV(float dst[3], float m[4][4], float v[3]) { +void Matrix::MultV(float dst[3], const float m[4][4], const float v[3]) { // printf("v = %f, %f, %f\n", v[0], v[1], v[2]); dst[0] = m[0][0] * v[0] + m[1][0] * v[1] + m[2][0] * v[2] + m[3][0]; dst[1] = m[0][1] * v[0] + m[1][1] * v[1] + m[2][1] * v[2] + m[3][1]; @@ -214,3 +245,10 @@ void Matrix::MultV(float dst[3], float m[4][4], float v[3]) { // printf("m = %f, %f, %f\n", m[3][0], m[3][1], m[3][2]); // printf("dst = %f, %f, %f\n", dst[0], dst[1], dst[2]); } + +void Matrix::MultV4(float dst[4], const float m[4][4], const float v[4]) { + dst[0] = m[0][0] * v[0] + m[1][0] * v[1] + m[2][0] * v[2] + m[3][0] * v[3]; + dst[1] = m[0][1] * v[0] + m[1][1] * v[1] + m[2][1] * v[2] + m[3][1] * v[3]; + dst[2] = m[0][2] * v[0] + m[1][2] * v[1] + m[2][2] * v[2] + m[3][2] * v[3]; + dst[3] = m[0][3] * v[0] + m[1][3] * v[1] + m[2][3] * v[2] + m[3][3] * v[3]; +} diff --git a/examples/common/matrix.h b/examples/common/matrix.h index 5f0e47a..e463a83 100644 --- a/examples/common/matrix.h +++ b/examples/common/matrix.h @@ -10,8 +10,11 @@ public: static void LookAt(float m[4][4], float eye[3], float lookat[3], float up[3]); static void Inverse(float m[4][4]); - static void Mult(float dst[4][4], float m0[4][4], float m1[4][4]); - static void MultV(float dst[3], float m[4][4], float v[3]); + static void Identity(float m[4][4]); + static void Add(float dst[4][4], const float m0[4][4], const float m1[4][4]); + static void Mult(float dst[4][4], const float m0[4][4], const float m1[4][4]); + static void MultV(float dst[3], const float m[4][4], const float v[3]); + static void MultV4(float dst[4], const float m[4][4], const float v[4]); }; #endif // diff --git a/examples/common/trackball.cc b/examples/common/trackball.cc index 069fe7b..27642e8 100644 --- a/examples/common/trackball.cc +++ b/examples/common/trackball.cc @@ -52,11 +52,6 @@ #include #include "trackball.h" -#ifdef _MSC_VER -#pragma warning(disable : 4244) -#pragma warning(disable : 4305) -#endif - /* * This size should really be based on the distance from the center of * rotation to the point on the object underneath the mouse. That @@ -173,11 +168,11 @@ void trackball(float q[4], float p1x, float p1y, float p2x, float p2y) { /* * Avoid problems with out-of-control values... */ - if (t > 1.0f) - t = 1.0f; - if (t < -1.0f) - t = -1.0f; - phi = 2.0f * asinf(t); + if (t > 1.0) + t = 1.0; + if (t < -1.0) + t = -1.0; + phi = 2.0 * asin(t); axis_to_quat(a, phi, q); } diff --git a/examples/skinning/main.cc b/examples/skinning/main.cc index 41b8d22..e1efbe0 100644 --- a/examples/skinning/main.cc +++ b/examples/skinning/main.cc @@ -12,7 +12,10 @@ #define GLFW_INCLUDE_GLU #include -#include "trackball.h" +#include "../common/trackball.h" +#include "../common/matrix.h" + +#include "skinning.h" #define TINYGLTF_IMPLEMENTATION #define STB_IMAGE_IMPLEMENTATION @@ -718,6 +721,44 @@ static void PrintNodes(const tinygltf::Scene &scene) { } } +static void SetupSkinningState(const tinygltf::Model &model) +{ + for (auto &s : model.skins) { + if (s.inverseBindMatrices > -1) { + + if (s.joints.size() > 0) { + for (auto const &j : s.joints) { + std::cout << j << std::endl; + } + + std::vector inverse_bind_matrices(s.joints.size()); + + const tinygltf::Accessor &accessor = model.accessors[s.inverseBindMatrices]; + assert(accessor.type == TINYGLTF_TYPE_MAT4); + + const tinygltf::BufferView &bufferView = model.bufferViews[accessor.bufferView]; + + const tinygltf::Buffer &buffer = model.buffers[bufferView.buffer]; + + const float *ptr = reinterpret_cast(buffer.data.data() + bufferView.byteOffset); + + for (size_t j = 0; j < s.joints.size(); j++) { + example::mat4 m; + memcpy(m.m, ptr + j * 16 * sizeof(float), 16 * sizeof(float)); + + inverse_bind_matrices[j] = m; + + std::cout << "j[" << j << "] = " << std::endl; + Matrix::Print(inverse_bind_matrices[j].m); + + } + + } + } + + } +} + int main(int argc, char **argv) { if (argc < 2) { std::cout << "glview input.gltf \n" << std::endl; @@ -779,6 +820,8 @@ int main(int argc, char **argv) { // DBG PrintNodes(model.scenes[scene_idx]); + SetupSkinningState(model); + if (!glfwInit()) { std::cerr << "Failed to initialize GLFW." << std::endl; return -1; diff --git a/examples/skinning/premake5.lua b/examples/skinning/premake5.lua index 4233f29..8d3a969 100644 --- a/examples/skinning/premake5.lua +++ b/examples/skinning/premake5.lua @@ -18,7 +18,7 @@ solution "skinning" kind "ConsoleApp" language "C++" cppdialect "C++11" - files { "main.cc", "skinning.cc", "trackball.cc" } + files { "main.cc", "skinning.cc", "../common/trackball.cc", "../common/matrix.cc" } includedirs { "./" } includedirs { "../../" } @@ -45,7 +45,7 @@ solution "skinning" includedirs { "/usr/local/include" } buildoptions { "-Wno-deprecated-declarations" } libdirs { "/usr/local/lib" } - links { "glfw3", "GLEW" } + links { "glfw", "GLEW" } linkoptions { "-framework OpenGL", "-framework Cocoa", "-framework IOKit", "-framework CoreVideo" } configuration "Debug" diff --git a/examples/skinning/skinning.cc b/examples/skinning/skinning.cc index e5d5a5f..725804c 100644 --- a/examples/skinning/skinning.cc +++ b/examples/skinning/skinning.cc @@ -1,9 +1,152 @@ +#include "skinning.h" -#if 0 +#include "../common/matrix.h" +#include "../common/trackball.h" // for quaternion -jointMatrix(j) = - globalTransform^-1 * // The "^-1" here means the inverse of this transform - globalJointTransform * - inverseBindMatrix(j); +#include +#include -#endif +namespace example { + +void BuildTransofrmMatrix( + const float translate[3], + const float rotation[4], // as quaternion in glTF + const float scale[3], + mat4 *transform_matrix) { + + float T[4][4]; + T[0][0] = 1.0f; + T[0][1] = 0.0f; + T[0][2] = 0.0f; + T[0][3] = 0.0f; + + T[1][0] = 0.0f; + T[1][1] = 1.0f; + T[1][2] = 0.0f; + T[1][3] = 0.0f; + + T[2][0] = 0.0f; + T[2][1] = 0.0f; + T[2][2] = 1.0f; + T[2][3] = 0.0f; + + T[3][0] = translate[0]; + T[3][1] = translate[1]; + T[3][2] = translate[2]; + T[3][3] = 1.0f; + + float R[4][4]; + + build_rotmatrix(R, rotation); + + float S[4][4]; + S[0][0] = scale[0]; + S[0][1] = 0.0f; + S[0][2] = 0.0f; + S[0][3] = 0.0f; + + S[1][0] = 0.0f; + S[1][1] = scale[1]; + S[1][2] = 0.0f; + S[1][3] = 0.0f; + + S[2][0] = 0.0f; + S[2][1] = 0.0f; + S[2][2] = scale[2]; + S[2][3] = 0.0f; + + S[3][0] = 0.0f; + S[3][1] = 0.0f; + S[3][2] = 0.0f; + S[3][3] = 1.0f; + + float RS[4][4]; + + Matrix::Mult(RS, R, S); + + Matrix::Mult(transform_matrix->m, T, RS); +} + +void ComputeJointMatrices( + const std::vector global_transform_of_nodes, + const std::vector global_transform_of_joint_nodes, + const std::vector inverse_bind_matrix_for_joints, + std::vector *output_joint_matrices) { + + const size_t n = global_transform_of_nodes.size(); + + output_joint_matrices->resize(n); + + for (size_t i = 0; i < n; i++) { + mat4 g_inv = global_transform_of_nodes[i]; + Matrix::Inverse(g_inv.m); + + mat4 g_joint = global_transform_of_joint_nodes[i]; + mat4 inverse_bind_matrix = inverse_bind_matrix_for_joints[i]; + + float a[4][4]; // temp matrix + Matrix::Mult(a, g_joint.m, inverse_bind_matrix.m); + + Matrix::Mult((*output_joint_matrices)[i].m, g_inv.m, a); + } +} + + +void Skining(const std::vector vertices, + const std::vector weights, const std::vector joints, + const size_t num_skinning_weights, + const std::vector joint_matrices, + const float t, + std::vector *skinned_vertices) { + + assert((vertices.size() % 4) == 0); + const size_t num_vertices = vertices.size() / 4; + + skinned_vertices->resize(vertices.size()); + + // TODO(syoyo): Ensure sum(weights) = 1.0; + + for (size_t v = 0; v < num_vertices; v++) { + const float *w_p = weights.data() + v * num_skinning_weights; + const size_t *j_p = joints.data() + v * num_skinning_weights; + + mat4 skin_mat; + memset(skin_mat.m, 0, sizeof(float) * 4 * 4); + + for (size_t k = 0; k < num_skinning_weights; k++) { + const float w = w_p[k]; + const mat4 &m = joint_matrices[j_p[k]]; + + for (size_t j = 0; j < 4; j++) { + for (size_t i = 0; i < 4; i++) { + skin_mat.m[j][i] += w * m.m[j][i]; + } + } + } + + // M = lerp I and skin_mat + mat4 M; + + mat4 I; + Matrix::Identity(I.m); + + for (size_t j = 0; j < 4; j++) { + for (size_t i = 0; i < 4; i++) { + M.m[j][i] = I.m[j][i] * t + (1.0f - t) * skin_mat.m[j][i]; + } + } + + + float vtx[4]; + vtx[0] = vertices[4 * v + 0]; + vtx[1] = vertices[4 * v + 1]; + vtx[2] = vertices[4 * v + 2]; + vtx[3] = vertices[4 * v + 3]; + + float ret[4]; + Matrix::MultV4(ret, M.m, vtx); + } +} + + +} // namespace example diff --git a/examples/skinning/trackball.cc b/examples/skinning/trackball.cc deleted file mode 100644 index 86ff3b3..0000000 --- a/examples/skinning/trackball.cc +++ /dev/null @@ -1,292 +0,0 @@ -/* - * (c) Copyright 1993, 1994, Silicon Graphics, Inc. - * ALL RIGHTS RESERVED - * Permission to use, copy, modify, and distribute this software for - * any purpose and without fee is hereby granted, provided that the above - * copyright notice appear in all copies and that both the copyright notice - * and this permission notice appear in supporting documentation, and that - * the name of Silicon Graphics, Inc. not be used in advertising - * or publicity pertaining to distribution of the software without specific, - * written prior permission. - * - * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS" - * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR - * FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON - * GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT, - * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY - * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION, - * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF - * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN - * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE - * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE. - * - * US Government Users Restricted Rights - * Use, duplication, or disclosure by the Government is subject to - * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph - * (c)(1)(ii) of the Rights in Technical Data and Computer Software - * clause at DFARS 252.227-7013 and/or in similar or successor - * clauses in the FAR or the DOD or NASA FAR Supplement. - * Unpublished-- rights reserved under the copyright laws of the - * United States. Contractor/manufacturer is Silicon Graphics, - * Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311. - * - * OpenGL(TM) is a trademark of Silicon Graphics, Inc. - */ -/* - * Trackball code: - * - * Implementation of a virtual trackball. - * Implemented by Gavin Bell, lots of ideas from Thant Tessman and - * the August '88 issue of Siggraph's "Computer Graphics," pp. 121-129. - * - * Vector manip code: - * - * Original code from: - * David M. Ciemiewicz, Mark Grossman, Henry Moreton, and Paul Haeberli - * - * Much mucking with by: - * Gavin Bell - */ -#include -#include "trackball.h" - -/* - * This size should really be based on the distance from the center of - * rotation to the point on the object underneath the mouse. That - * point would then track the mouse as closely as possible. This is a - * simple example, though, so that is left as an Exercise for the - * Programmer. - */ -#define TRACKBALLSIZE (0.8) - -/* - * Local function prototypes (not defined in trackball.h) - */ -static float tb_project_to_sphere(float, float, float); -static void normalize_quat(float[4]); - -static void vzero(float *v) { - v[0] = 0.0; - v[1] = 0.0; - v[2] = 0.0; -} - -static void vset(float *v, float x, float y, float z) { - v[0] = x; - v[1] = y; - v[2] = z; -} - -static void vsub(const float *src1, const float *src2, float *dst) { - dst[0] = src1[0] - src2[0]; - dst[1] = src1[1] - src2[1]; - dst[2] = src1[2] - src2[2]; -} - -static void vcopy(const float *v1, float *v2) { - register int i; - for (i = 0; i < 3; i++) - v2[i] = v1[i]; -} - -static void vcross(const float *v1, const float *v2, float *cross) { - float temp[3]; - - temp[0] = (v1[1] * v2[2]) - (v1[2] * v2[1]); - temp[1] = (v1[2] * v2[0]) - (v1[0] * v2[2]); - temp[2] = (v1[0] * v2[1]) - (v1[1] * v2[0]); - vcopy(temp, cross); -} - -static float vlength(const float *v) { - return sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); -} - -static void vscale(float *v, float div) { - v[0] *= div; - v[1] *= div; - v[2] *= div; -} - -static void vnormal(float *v) { vscale(v, 1.0 / vlength(v)); } - -static float vdot(const float *v1, const float *v2) { - return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2]; -} - -static void vadd(const float *src1, const float *src2, float *dst) { - dst[0] = src1[0] + src2[0]; - dst[1] = src1[1] + src2[1]; - dst[2] = src1[2] + src2[2]; -} - -/* - * Ok, simulate a track-ball. Project the points onto the virtual - * trackball, then figure out the axis of rotation, which is the cross - * product of P1 P2 and O P1 (O is the center of the ball, 0,0,0) - * Note: This is a deformed trackball-- is a trackball in the center, - * but is deformed into a hyperbolic sheet of rotation away from the - * center. This particular function was chosen after trying out - * several variations. - * - * It is assumed that the arguments to this routine are in the range - * (-1.0 ... 1.0) - */ -void trackball(float q[4], float p1x, float p1y, float p2x, float p2y) { - float a[3]; /* Axis of rotation */ - float phi; /* how much to rotate about axis */ - float p1[3], p2[3], d[3]; - float t; - - if (p1x == p2x && p1y == p2y) { - /* Zero rotation */ - vzero(q); - q[3] = 1.0; - return; - } - - /* - * First, figure out z-coordinates for projection of P1 and P2 to - * deformed sphere - */ - vset(p1, p1x, p1y, tb_project_to_sphere(TRACKBALLSIZE, p1x, p1y)); - vset(p2, p2x, p2y, tb_project_to_sphere(TRACKBALLSIZE, p2x, p2y)); - - /* - * Now, we want the cross product of P1 and P2 - */ - vcross(p2, p1, a); - - /* - * Figure out how much to rotate around that axis. - */ - vsub(p1, p2, d); - t = vlength(d) / (2.0 * TRACKBALLSIZE); - - /* - * Avoid problems with out-of-control values... - */ - if (t > 1.0) - t = 1.0; - if (t < -1.0) - t = -1.0; - phi = 2.0 * asin(t); - - axis_to_quat(a, phi, q); -} - -/* - * Given an axis and angle, compute quaternion. - */ -void axis_to_quat(float a[3], float phi, float q[4]) { - vnormal(a); - vcopy(a, q); - vscale(q, sin(phi / 2.0)); - q[3] = cos(phi / 2.0); -} - -/* - * Project an x,y pair onto a sphere of radius r OR a hyperbolic sheet - * if we are away from the center of the sphere. - */ -static float tb_project_to_sphere(float r, float x, float y) { - float d, t, z; - - d = sqrt(x * x + y * y); - if (d < r * 0.70710678118654752440) { /* Inside sphere */ - z = sqrt(r * r - d * d); - } else { /* On hyperbola */ - t = r / 1.41421356237309504880; - z = t * t / d; - } - return z; -} - -/* - * Given two rotations, e1 and e2, expressed as quaternion rotations, - * figure out the equivalent single rotation and stuff it into dest. - * - * This routine also normalizes the result every RENORMCOUNT times it is - * called, to keep error from creeping in. - * - * NOTE: This routine is written so that q1 or q2 may be the same - * as dest (or each other). - */ - -#define RENORMCOUNT 97 - -void add_quats(float q1[4], float q2[4], float dest[4]) { - static int count = 0; - float t1[4], t2[4], t3[4]; - float tf[4]; - - vcopy(q1, t1); - vscale(t1, q2[3]); - - vcopy(q2, t2); - vscale(t2, q1[3]); - - vcross(q2, q1, t3); - vadd(t1, t2, tf); - vadd(t3, tf, tf); - tf[3] = q1[3] * q2[3] - vdot(q1, q2); - - dest[0] = tf[0]; - dest[1] = tf[1]; - dest[2] = tf[2]; - dest[3] = tf[3]; - - if (++count > RENORMCOUNT) { - count = 0; - normalize_quat(dest); - } -} - -/* - * Quaternions always obey: a^2 + b^2 + c^2 + d^2 = 1.0 - * If they don't add up to 1.0, dividing by their magnitued will - * renormalize them. - * - * Note: See the following for more information on quaternions: - * - * - Shoemake, K., Animating rotation with quaternion curves, Computer - * Graphics 19, No 3 (Proc. SIGGRAPH'85), 245-254, 1985. - * - Pletinckx, D., Quaternion calculus as a basic tool in computer - * graphics, The Visual Computer 5, 2-13, 1989. - */ -static void normalize_quat(float q[4]) { - int i; - float mag; - - mag = (q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]); - for (i = 0; i < 4; i++) - q[i] /= mag; -} - -/* - * Build a rotation matrix, given a quaternion rotation. - * - */ -void build_rotmatrix(float m[4][4], const float q[4]) { - m[0][0] = 1.0 - 2.0 * (q[1] * q[1] + q[2] * q[2]); - m[0][1] = 2.0 * (q[0] * q[1] - q[2] * q[3]); - m[0][2] = 2.0 * (q[2] * q[0] + q[1] * q[3]); - m[0][3] = 0.0; - - m[1][0] = 2.0 * (q[0] * q[1] + q[2] * q[3]); - m[1][1] = 1.0 - 2.0 * (q[2] * q[2] + q[0] * q[0]); - m[1][2] = 2.0 * (q[1] * q[2] - q[0] * q[3]); - m[1][3] = 0.0; - - m[2][0] = 2.0 * (q[2] * q[0] - q[1] * q[3]); - m[2][1] = 2.0 * (q[1] * q[2] + q[0] * q[3]); - m[2][2] = 1.0 - 2.0 * (q[1] * q[1] + q[0] * q[0]); - m[2][3] = 0.0; - - m[3][0] = 0.0; - m[3][1] = 0.0; - m[3][2] = 0.0; - m[3][3] = 1.0; -} diff --git a/examples/skinning/trackball.h b/examples/skinning/trackball.h deleted file mode 100644 index b1f9437..0000000 --- a/examples/skinning/trackball.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * (c) Copyright 1993, 1994, Silicon Graphics, Inc. - * ALL RIGHTS RESERVED - * Permission to use, copy, modify, and distribute this software for - * any purpose and without fee is hereby granted, provided that the above - * copyright notice appear in all copies and that both the copyright notice - * and this permission notice appear in supporting documentation, and that - * the name of Silicon Graphics, Inc. not be used in advertising - * or publicity pertaining to distribution of the software without specific, - * written prior permission. - * - * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS" - * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR - * FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON - * GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT, - * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY - * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION, - * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF - * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN - * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE - * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE. - * - * US Government Users Restricted Rights - * Use, duplication, or disclosure by the Government is subject to - * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph - * (c)(1)(ii) of the Rights in Technical Data and Computer Software - * clause at DFARS 252.227-7013 and/or in similar or successor - * clauses in the FAR or the DOD or NASA FAR Supplement. - * Unpublished-- rights reserved under the copyright laws of the - * United States. Contractor/manufacturer is Silicon Graphics, - * Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311. - * - * OpenGL(TM) is a trademark of Silicon Graphics, Inc. - */ -/* - * trackball.h - * A virtual trackball implementation - * Written by Gavin Bell for Silicon Graphics, November 1988. - */ - -/* - * Pass the x and y coordinates of the last and current positions of - * the mouse, scaled so they are from (-1.0 ... 1.0). - * - * The resulting rotation is returned as a quaternion rotation in the - * first paramater. - */ -void trackball(float q[4], float p1x, float p1y, float p2x, float p2y); - -void negate_quat(float *q, float *qn); - -/* - * Given two quaternions, add them together to get a third quaternion. - * Adding quaternions to get a compound rotation is analagous to adding - * translations to get a compound translation. When incrementally - * adding rotations, the first argument here should be the new - * rotation, the second and third the total rotation (which will be - * over-written with the resulting new total rotation). - */ -void add_quats(float *q1, float *q2, float *dest); - -/* - * A useful function, builds a rotation matrix in Matrix based on - * given quaternion. - */ -void build_rotmatrix(float m[4][4], const float q[4]); - -/* - * This function computes a quaternion based on an axis (defined by - * the given vector) and an angle about which to rotate. The angle is - * expressed in radians. The result is put into the third argument. - */ -void axis_to_quat(float a[3], float phi, float q[4]);