3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Boost QVM(Quaternions, Vectors, Matrices)に触ってみた

Last updated at Posted at 2016-12-29

Boostのバージョンを上げたらBoost QVMが入ってました."QVM: Quaternions, Vectors, Matrices"だそうです.
低次元のベクトル演算を対象にしており,2D/3Dの回転や並進がサクッと実装できそうなライブラリです.
ここ見ると他のライブラリ依存や自作のクラスに対して演算を定義しやすいようなので,「あー,こっちのVector型とこっちのvec3型の間で内積がほしい・・・」みたいなときに使えるはずです.

ちょっと触ってみたので,基本操作をメモついでに書いておきます.
書きやすく,Eigenほどコンパイル遅くならないあたり良さげ.Boostに入っているので共用コードでも使いやすいかと.
(MSVC 14.0(VS 2015), Boost 1.62.0で動作確認)

#include <iostream>
#include <boost/qvm/all.hpp>

//円周率
template<typename T> constexpr const T pi() { return static_cast<T>(std::atan2(0.0, -1.0)); }

// ベクトル表示用
template <typename T, int D>
std::ostream& operator<<(std::ostream& os, const boost::qvm::vec<T, D>& v)
{
	os << "[ ";
	for (int i = 0; i < D - 1; ++i) os << v.a[i] << ", ";
	if (D > 0) os << v.a[D - 1];
	os << " ]";
	return os;
}

// 行列表示用
template <typename T, int Rows, int Cols>
std::ostream& operator<<(std::ostream& os, const boost::qvm::mat<T, Rows, Cols>& m)
{
	os << "[ ";
	for (int r = 0; r < Rows - 1; ++r)
	{
		for (int c = 0; c < Cols - 1; ++c) os << m.a[r][c] << ", ";
		if (Cols > 0) os << m.a[r][Cols - 1];
		os << "\n  ";
	}
	if (Rows > 0)
	{
		for (int c = 0; c < Cols - 1; ++c) os << m.a[Rows - 1][c] << ", ";
		if (Cols > 0) os << m.a[Rows - 1][Cols - 1];
	}
	os << " ]";
	return os;
}

// ここから
int main()
{
	using namespace boost::qvm;

	// ゼロベクトル
	vec<float, 3> vec_1 = zero_vec<float, 3>();
	std::cout << "vec_1: " << vec_1 << std::endl;
	
	// Initializer Listでベクトルの初期化
	vec<float, 3> vec_2 { 0.3f, 0.4f, 0.5f };
	std::cout << "vec_2: " << vec_1 << std::endl;

	//ベクトルの要素アクセス
	A<0>(vec_1) = 0.1f; // A<k>(v)でk要素目にアクセス
	A1(vec_1) = 0.2f;   // A1(v)でA<1>(v)にアクセスもできる(k = [0 ... 9])
	Z(vec_1) = 0.3f;    // X, Y, Z, WでA0, A1, A2, A3にアクセスできる
	std::cout << "vec_1: " << vec_1 << std::endl;
	std::cout << "vec_1(ZYX): " << vec<float, 3>(ZYX(vec_1)) << std::endl; // アクセス順を変える


	// ------------------------
	std::cout << std::endl;
	// ------------------------

	// 色々べクトルの演算
	std::cout << "スカラー倍: " << vec_1 * 2.0f << std::endl;
	std::cout << "和: " << vec_1 + vec_2 << std::endl;
	std::cout << "内積: " << dot(vec_1, vec_2) << std::endl;
	std::cout << "外積: " << cross(vec_1, vec_2) << std::endl;
	std::cout << "大きさ(2-ノルム): " << mag(vec_1) << std::endl;
	std::cout << "大きさの2乗: " << mag_sqr(vec_1) << std::endl;
	std::cout << "正規化: " << normalized(vec_1) << std::endl;
	std::cout << "対角行列: \n" << mat<float, 3, 3>(diag_mat(vec_1)) << std::endl;

	// ------------------------
	std::cout << std::endl;
	// ------------------------

	// 単位行列で初期化
	mat<float, 3, 3> mat_1 = identity_mat<float, 3>();
	std::cout << "mat_1: \n" << mat_1 << std::endl;

	// Initializer Listで行列の初期化
	mat<float, 3, 3> mat_2 = {
		0.1f, 0.2f, 0.3f,
		0.4f, 0.5f, 0.6f,
		0.7f, 0.8f, 0.9f,
	};
	std::cout << "mat_2: \n" << mat_2 << std::endl;

	//行列の要素アクセス
	A<0, 1>(mat_1) = 0.1f;
	A12(mat_1) = 0.2f;
	std::cout << "mat_1: " << mat_1 << std::endl;

	// ------------------------
	std::cout << std::endl;
	// ------------------------

	// 色々行列の演算
	std::cout << "スカラー倍: \n" << mat_1 * 2.0f << std::endl; // スカラー倍は各要素に作用
	std::cout << "行列積: \n" << mat_1 * mat_2 << std::endl;
	std::cout << "行列とベクトルの積: " << mat_1 * vec_1 << std::endl;
	std::cout << "転置: \n" << mat<float, 3, 3>(transposed(mat_1)) << std::endl;
	std::cout << "行列式: " << determinant(mat_1) << std::endl;

	// ------------------------
	std::cout << std::endl;
	// ------------------------

	// 回転行列
	// vec_1軸回りにpi/6回転する回転行列(回転軸-回転角)
	mat<float, 3, 3> rmat_1 = rot_mat<3, decltype(vec_1), float>(vec_1, pi<float>() / 6);
	std::cout << "rmat_1: \n" << rmat_1 << std::endl;

	// x軸回りにpi/4回転する回転行列
	mat<float, 3, 3> rmat_2 = rotx_mat<3, float>(pi<float>() / 4);
	std::cout << "rmat_2: \n" << rmat_2 << std::endl;

	// ------------------------
	std::cout << std::endl;
	// ------------------------

	//クォータニオンで回転を補完する
	quat<float> quat_begin = identity_quat<float>();
	quat<float> quat_end = rotx_quat(pi<float>() / 2) * roty_quat(pi<float>() / 3);

	for (float t = 0.0f; t < 1.0f; t += 0.1f)
	{
		const auto& rmat = convert_to<mat<float, 3, 3>>(slerp(quat_begin, quat_end, t));
		std::cout << "t: " << t << ", rmat: \n" << rmat << std::endl;
	}
}

うーん,正直Eigen使えば良くねって感じが

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?