{"action":"opened","issue":{"url":"https://api.github.com/repos/amethyst/amethyst/issues/1134","repository_url":"https://api.github.com/repos/amethyst/amethyst","labels_url":"https://api.github.com/repos/amethyst/amethyst/issues/1134/labels{/name}","comments_url":"https://api.github.com/repos/amethyst/amethyst/issues/1134/comments","events_url":"https://api.github.com/repos/amethyst/amethyst/issues/1134/events","html_url":"https://github.com/amethyst/amethyst/issues/1134","id":380071961,"node_id":"MDU6SXNzdWUzODAwNzE5NjE=","number":1134,"title":"Quaternion rotation issue with nalgebra","user":{"login":"JamesAngstrom","id":44684728,"node_id":"MDQ6VXNlcjQ0Njg0NzI4","avatar_url":"https://avatars0.githubusercontent.com/u/44684728?v=4","gravatar_id":"","url":"https://api.github.com/users/JamesAngstrom","html_url":"https://github.com/JamesAngstrom","followers_url":"https://api.github.com/users/JamesAngstrom/followers","following_url":"https://api.github.com/users/JamesAngstrom/following{/other_user}","gists_url":"https://api.github.com/users/JamesAngstrom/gists{/gist_id}","starred_url":"https://api.github.com/users/JamesAngstrom/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/JamesAngstrom/subscriptions","organizations_url":"https://api.github.com/users/JamesAngstrom/orgs","repos_url":"https://api.github.com/users/JamesAngstrom/repos","events_url":"https://api.github.com/users/JamesAngstrom/events{/privacy}","received_events_url":"https://api.github.com/users/JamesAngstrom/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":0,"created_at":"2018-11-13T06:00:20Z","updated_at":"2018-11-13T06:00:20Z","closed_at":null,"author_association":"NONE","body":"I was already using it for some procedural geometry and with ncollide, so my code was a bit of a mess using both cgmath and nalgebra and converting between the two - so naturally I wanted to use the new nalgebra stuff!\r\n\r\nHowever, once I translated my code to use nalgebra, I ended up with:\r\n![bad1](https://user-images.githubusercontent.com/44684728/48392493-94132180-e703-11e8-9a27-cb9d55bd9a75.png)\r\n\r\nHmm, not so good. That was using the following code to rotate the camera's transform, where point is the location of the pink teapot it should be looking.\r\n```rust\r\ntransform.look_at(point, Vector3::new(0.0, 1.0, 0.0));\r\n```\r\nSo I'd already had some issues with rotations with cgmath, specifically it only providing a left-handed look at method. Before I switched to nalgebra I had do do either of the following:\r\n```rust\r\n// cgmath\r\nlet look = Quaternion::look_at(dir, Vector3::new(0.0, 1.0, 0.0));\r\ntransform.rotation = Quaternion::new(look.v.y, look.v.z, look.s, -look.v.x);\r\n// converting cgmath to nalgebra_glm (right-handed)\r\nlet glm_rh = glm::quat_look_at_rh(&glm::vec3(dir.x, dir.y, dir.z), &glm::vec3(0.0, 1.0, 0.0));\r\nlet rh = Quaternion::new(glm_rh.coords.w, -glm_rh.coords.x, -glm_rh.coords.y, -glm_rh.coords.z);\r\n// or using quat_look_at_lh cgmath to nalgebra_glm (left-handed)\r\nlet lh = Quaternion::new(-glm_lh.coords.y, -glm_lh.coords.z, -glm_lh.coords.w, glm_lh.coords.x);\r\n```\r\nNote how I have to flip the signs for x, y and z when converting between nalgebra and cgmath. As far as I can tell if nalgebra stores it's quaternion as (w, x, y, z) then the equivalent cgmath quaternion is (w, -x, -y, -z). I think these two representations are isomorphic, but suspecting this might be the issue I try changing my new camera rotation code to:\r\n```rust\r\nlet q = UnitQuaternion::look_at_rh(&dir, &Vector3::new(0.0, 1.0, 0.0));\r\ntransform.set_rotation(Unit::new_unchecked(Quaternion::new(q.coords.w, -q.coords.x, -q.coords.y, -q.coords.z)));\r\n```\r\nThat gives me:\r\n![bad2](https://user-images.githubusercontent.com/44684728/48393142-477d1580-e706-11e8-8794-44a84780954f.png)\r\nIt's hard to see because the debug lines are very thin, but the teapot should be flat on the terrain, rotated in a specific direction (self.rotation in the below code):\r\n```rust\r\nlet angle = glm::rotate_vec3(&(up.cross(&normal)), -(0.5 * PI), &normal);\r\nlet rotation = glm::quat_angle_axis(self.rotation, &normal);\r\nlet dir = glm::quat_cross_vec(&rotation, &angle);\r\n\r\ndebugline.add_direction(Point3::new(p.x, p.y + 2.0, p.z), angle * 2.0, Rgba::green());\r\ndebugline.add_direction(Point3::new(p.x, p.y + 2.0, p.z), angle * -2.0, Rgba::green());\r\ndebugline.add_direction(Point3::new(p.x, p.y + 2.0, p.z), dir * 2.0, Rgba::red());\r\ndebugline.add_direction(Point3::new(p.x, p.y + 2.0, p.z), dir * -2.0, Rgba::white());\r\n\r\ntransform.look_at(Vector3::new(p.x, p.y, p.z) + dir, up);\r\n```\r\nEssentially angle represents the steepest path down the terrain, and dir is a vector also tangent to the terrain offset by self.rotation. It's super hard to see in the image, but when I use quat_cross_vec with dir and then plot the red and white debug lines they are correct, but making the teapot look in that direction doesn't work.\r\n\r\nHowever, I don't think the problem is look_at, the code for that looks fine to me. What I did is change:\r\n```rust\r\n    /// Returns the local object matrix for the transform.\r\n    ///\r\n    /// Combined with the parent's `GlobalTransform` component it gives\r\n    /// the global (or world) matrix for the current entity.\r\n    #[inline]\r\n    pub fn matrix(&self) -> Matrix4<f32> {\r\n        self.iso\r\n            .to_homogeneous()\r\n            .prepend_nonuniform_scaling(&self.scale)\r\n    }\r\n```\r\nto\r\n```rust\r\n    /// Returns the local object matrix for the transform.\r\n    ///\r\n    /// Combined with the parent's `GlobalTransform` component it gives\r\n    /// the global (or world) matrix for the current entity.\r\n    #[inline]\r\n    pub fn matrix(&self) -> Matrix4<f32> {\r\n        Isometry3::from_parts(self.iso.translation, self.iso.rotation.conjugate())\r\n            .to_homogeneous()\r\n            .prepend_nonuniform_scaling(&self.scale)\r\n    }\r\n```\r\nin local_transform.rs in amethyst_core, and this fixes all my issues (screenshot below) by doing the (w, x, y, z) <-> (w, -x, -y, -z) thing for every transform... but it _feels_ like a hack.\r\n\r\n![good](https://user-images.githubusercontent.com/44684728/48393813-ee62b100-e708-11e8-9bab-37f8ce5e7e9f.png)\r\n\r\nApologies for not having a minimal example, I can try to build one tomorrow if that would be useful."}}
{"actor":{"display_login":"JamesAngstrom"}}