Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C++: Apua kvaternion kanssa

Lahha [28.11.2012 06:48:03]

#

Sattuiskohan täällä olemaan ketään matikka neroa joka taitaisi kvaterniot ja osaisi kertoa mitä minä teen väärin?

Videolla liikkuvan pallon pitäisi pysyä aluksen keulan edessä mutta pyörii ihan omiaan.
http://youtu.be/UUmwFnLktjg

Piirto koodi

[&](std::shared_ptr<SimulationObject> obj)
{
	const vec3_dim & op = obj->getPosition();
	const quat_dim & or = obj->getAttitude();

	//object
	glm::mat4 modelMatrix(1.0f);
	modelMatrix = glm::translate((float)op.X(), (float)op.Y(), (float)op.Z()) * buildMatrix(or);
	testModel->draw(modelMatrix, viewMatrix, projectionMatrix, glm::normalize(glm::vec3(-1,1,0)));

	//1 small sphere in front of object;
	vec3_dim op2 = op + or.rotateVector(vec3_dim(10.0, 0.0, 0.0));
	modelMatrix = glm::translate((float)op2.X(), (float)op2.Y(), (float)op2.Z());
	sphereModel->draw(modelMatrix, viewMatrix, projectionMatrix, glm::normalize(glm::vec3(-1,1,0)));

	//4 small spheres around the object, static
	op2 = op + vec3_dim(12.0, 0.0, 0.0);
	modelMatrix = glm::translate((float)op2.X(), (float)op2.Y(), (float)op2.Z());
	sphereModel->draw(modelMatrix, viewMatrix, projectionMatrix, glm::normalize(glm::vec3(-1,1,0)));

	op2 = op + vec3_dim(-12.0, 0.0, 0.0);
	modelMatrix = glm::translate((float)op2.X(), (float)op2.Y(), (float)op2.Z());
	sphereModel->draw(modelMatrix, viewMatrix, projectionMatrix, glm::normalize(glm::vec3(-1,1,0)));

	op2 = op + vec3_dim(0.0, 0.0, 12.0);
	modelMatrix = glm::translate((float)op2.X(), (float)op2.Y(), (float)op2.Z());
	sphereModel->draw(modelMatrix, viewMatrix, projectionMatrix, glm::normalize(glm::vec3(-1,1,0)));

	op2 = op + vec3_dim(0.0, 0.0, -12.0);
	modelMatrix = glm::translate((float)op2.X(), (float)op2.Y(), (float)op2.Z());
	sphereModel->draw(modelMatrix, viewMatrix, projectionMatrix, glm::normalize(glm::vec3(-1,1,0)));
}

Vektorin pyöritys. Koitin myös tuolla annettua koodia: http://content.gpwiki.org/index.php/OpenGL:Tutorials:Using_Quaternions_to_represent_rotation mutta tulos oli aivan sama.

template <typename Tv>
Vec3<Tv> Quaternion::rotateVector(const Vec3<Tv>& vec) const
{
	Vec3<Tv> tmp = Vec3<Tv>(x, y, z).cross(vec) * 2.0;
	return vec + tmp * w + Vec3<Tv>(x, y, z).cross(tmp);
}

Matriisi piirtämistä varten

template <typename T>
glm::mat4 buildMatrix(const Quaternion<T>& v)
{
	glm::mat4 result;

	const T & x = v.X();
	const T & y = v.Y();
	const T & z = v.Z();
	const T & w = v.W();

	T x2 = x * x;
	T y2 = y * y;
	T z2 = z * z;
	T w2 = w * w;

	result[0][0] = 1.0 - 2.0 * (y2 + z2);
	result[0][1] = 2.0 * (x * y - w * z);
	result[0][2] = 2.0 * (x * z + w * y);
	result[0][3] = 0.0;

	result[1][0] = 2.0 * (x * y + w * z);
	result[1][1] = 1.0 - 2.0 * (x2 + z2);
	result[1][2] = 2.0 * (y * z - w * x);
	result[1][3] = 0.0;

	result[2][0] = 2.0 * (x * z - w * y);
	result[2][1] = 2.0 * (y * z + w * x);
	result[2][2] = 1.0 - 2.0 * (x2 + y2);
	result[2][3] = 0.0;

	result[3][0] = 0.0;
	result[3][1] = 0.0;
	result[3][2] = 0.0;
	result[3][3] = 1.0;

	return result;
}

User137 [28.11.2012 14:25:28]

#

Tein itsekin 3D-demon yks päivä.
http://www.youtube.com/watch?v=IKoE-JL7OXg
Tuolla videolla taidan käyttää vaan matriiseja mutta kokeilin quaternioiden toimivuuden tällä demolla monta kertaa.

Lähdekoodia 3D-matikkaan löytyy tuolta, esim vastaava funktio (pascal:lla):
http://code.google.com/p/nxpascal/source/browse/trunk/src/nxMath3D.pas#960
Hitusen työlästä verrata noita, en kerkeä nyt.

Muokkaus: Näyttäis kyllä + ja - merkit menevän ihan eri tavalla. Liekö DirectX-koodia tvs? He käyttää toispuoleisia matriiseja.

Lahha [28.11.2012 20:33:41]

#

User137 kirjoitti:

Muokkaus: Näyttäis kyllä + ja - merkit menevän ihan eri tavalla. Liekö DirectX-koodia tvs? He käyttää toispuoleisia matriiseja.

+ ja - merkkejä vaihtelemallahan se selvisi. Tälläinen järjestys näyttäisi toimivan oikein. Jännää tämä matikka kun piti vielä käydä vaihtamassa fysiikka koodista kvaternioiden kertomis järjestys että pyöritykset toimivat oikein muutoksen jälkeen.

result[0][0] = 1.0 - 2.0 * (y2 + z2);
result[0][1] = 2.0 * (x * y + w * z);
result[0][2] = 2.0 * (x * z - w * y);
result[0][3] = 0.0;

result[1][0] = 2.0 * (x * y - w * z);
result[1][1] = 1.0 - 2.0 * (x2 + z2);
result[1][2] = 2.0 * (y * z + w * x);
result[1][3] = 0.0;

result[2][0] = 2.0 * (x * z + w * y);
result[2][1] = 2.0 * (y * z - w * x);
result[2][2] = 1.0 - 2.0 * (x2 + y2);
result[2][3] = 0.0;

result[3][0] = 0.0;
result[3][1] = 0.0;
result[3][2] = 0.0;
result[3][3] = 1.0;

User137 [29.11.2012 09:45:19]

#

Sulla on kyllä paremmin optimoitu tuo funktio, taidan muuttaa omaakin.

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta