Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Quaternions go over value #3

Closed
JesseLeeuwen opened this issue Aug 11, 2015 · 9 comments
Closed

Quaternions go over value #3

JesseLeeuwen opened this issue Aug 11, 2015 · 9 comments
Assignees

Comments

@JesseLeeuwen
Copy link

the values in Quaternion class go over the max value resulting in scaling of the object

quaternions over value

@giawa
Copy link
Owner

giawa commented Aug 11, 2015

Hi JesseLeeuwen, thanks for posting this issue! Does normalizing the value of the quaternion before use fix this issue?

@JesseLeeuwen
Copy link
Author

I tried it but the rotation will vary in speed because of the normalization

@giawa
Copy link
Owner

giawa commented Aug 12, 2015

Thanks for the update! I'll start looking into this more closely - can you please give me some information on which tutorial you found the issue in? Is there a particular line in that tutorial you can trace the issue to? Do you have a minimum set of code the exhibits the issue?

@giawa giawa self-assigned this Aug 12, 2015
@JesseLeeuwen
Copy link
Author

oh it's not from the tutorials its, oeps wrong github project uhm it's about the quaternions in general sorry

@giawa
Copy link
Owner

giawa commented Aug 13, 2015

Hey no worries - we'll get it sorted out still. Can you please link to some example code or provide a method to reproduce this? Thanks!

@JesseLeeuwen
Copy link
Author

sure, to test this just call the rotate and Render Func

In the beginning there will be not much deformation but it'll slowly increase the more the object rotates.

class testObject
{
    private Vector3 position;
    private Quaternion rotation;
    private ShaderProgram shader;
    private Texture texture;

    private VBO<Vector3> vertices;
    private VBO<Vector3> normals;
    private VBO<Vector2> uvs;
    private VBO<int> indices;

    public TestObject(ShaderProgram shader, Texture texture)
    {
        this.position = Vector3.Zero;
        this.rotation = Quaternion.identity;

        this.shader = shader;
        this.texture = texture;

        Vector3[] verts = new Vector3[] {
                new Vector3(1, 1, -1), new Vector3(-1, 1, -1), new Vector3(-1, 1, 1), new Vector3(1, 1, 1),
                new Vector3(1, -1, 1), new Vector3(-1, -1, 1), new Vector3(-1, -1, -1), new Vector3(1, -1, -1),
                new Vector3(1, 1, 1), new Vector3(-1, 1, 1), new Vector3(-1, -1, 1), new Vector3(1, -1, 1),
                new Vector3(1, -1, -1), new Vector3(-1, -1, -1), new Vector3(-1, 1, -1), new Vector3(1, 1, -1),
                new Vector3(-1, 1, 1), new Vector3(-1, 1, -1), new Vector3(-1, -1, -1), new Vector3(-1, -1, 1),
                new Vector3(1, 1, -1), new Vector3(1, 1, 1), new Vector3(1, -1, 1), new Vector3(1, -1, -1) 
            };
            Vector2[] uvs = new Vector2[] {
                new Vector2(0.55, 0.55), new Vector2(0.95, 0.55), new Vector2(0.95, 0.95), new Vector2(0.55, 0.95), 
                new Vector2(0.55, 0.55), new Vector2(0.95, 0.55), new Vector2(0.95, 0.95), new Vector2(0.55, 0.95),
                new Vector2(0.55, 0.55), new Vector2(0.95, 0.55), new Vector2(0.95, 0.95), new Vector2(0.55, 0.95),
                new Vector2(0.55, 0.55), new Vector2(0.95, 0.55), new Vector2(0.95, 0.95), new Vector2(0.55, 0.95),
                new Vector2(0.55, 0.55), new Vector2(0.95, 0.55), new Vector2(0.95, 0.95), new Vector2(0.55, 0.95),
                new Vector2(0.55, 0.55), new Vector2(0.95, 0.55), new Vector2(0.95, 0.95), new Vector2(0.55, 0.95)
            };
            Vector3[] normals = new Vector3[] {
                new Vector3(0, 1, 0), new Vector3(0, 1, 0), new Vector3(0, 1, 0), new Vector3(0, 1, 0), 
                new Vector3(0, -1, 0), new Vector3(0, -1, 0), new Vector3(0, -1, 0), new Vector3(0, -1, 0), 
                new Vector3(0, 0, 1), new Vector3(0, 0, 1), new Vector3(0, 0, 1), new Vector3(0, 0, 1), 
                new Vector3(0, 0, -1), new Vector3(0, 0, -1), new Vector3(0, 0, -1), new Vector3(0, 0, -1), 
                new Vector3(-1, 0, 0), new Vector3(-1, 0, 0), new Vector3(-1, 0, 0), new Vector3(-1, 0, 0), 
                new Vector3(1, 0, 0), new Vector3(1, 0, 0), new Vector3(1, 0, 0), new Vector3(1, 0, 0)
            };
            int[] indices = new int[] { 
                0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23 
            };

        this.vertices = new VBO<Vector3>(verts);
        this.normals = new VBO<Vector3>(normals);
        this.uvs = new VBO<Vector2>(uvs);
        this.indices = new VBO<int>(indices);
    }

    public void Rotate(Quaternion )
    {
        // make rotation quaternion
        Quaternion rotate = new Quaternion(rotateAmount.x / 360.0f, rotateAmount.y / 360.0f, rotateAmount.z / 360.0f, 1);
        rotation = rotate * rotation;
    }

    public void Render()
    {
         Gl.UseProgram(shader.ProgramID);
         Gl.BindTexture(texture);

         shader["model_matrix"].SetValue(GetModelMatrix());
         shader["Color"].SetValue(new Vector3(1,1,1));
         shader["enable_lighting"].SetValue(true);

         Gl.BindBufferToShaderAttribute(vertices, shader, "vPosition"); // sets vertex position in "vPosition in shader input (vertexPosition in tutorial shader)"
         Gl.BindBufferToShaderAttribute(normals, shader, "vNormal"); // sets Normals in "vNormal" in shader input
         Gl.BindBufferToShaderAttribute(uvs, shader, "UV"); // sets uvs in "UV" in shader input
         Gl.BindBuffer(BufferTarget.ElementArrayBuffer, indices.vboID);

         Gl.DrawElements(BeginMode.Quads, indices.Count, DrawElementsType.UnsignedInt, IntPtr.Zero);

         Gl.UseProgram(0);
    }

    private Matrix4 GetModelMatrix()
    {
         Matrix4 transform = new Matrix4();
         // make rotation matrix
         Vector3[] mat3 = new Vector3[3] ={
             rotation * Vector3.Right,
             rotation * Vector3.Up,
             rotation * Vector3.Backward
         };

         transform[0] = new Vector4(mat3[0].x * scale.x, mat3[0].y * scale.y, mat3[0].z * scale.z, 0.0f);
         transform[1] = new Vector4(mat3[1].x * scale.x, mat3[1].y * scale.y, mat3[1].z * scale.z, 0.0f);
         transform[2] = new Vector4(mat3[2].x * scale.x, mat3[2].y * scale.y, mat3[2].z * scale.z, 0.0f);
         transform[3] = new Vector4(position.x, position.y, position.z, 1.0f);            

         return transform;
    }
}

@giawa
Copy link
Owner

giawa commented Aug 14, 2015

The quaternion values are calculated a bit differently than you are using in your demo code. x, y, z are not the x, y, z rotation angles. Instead you must calculate the x, y, z and w components using a conversion from axis/angle into quaternion space.

        /// <summary>
        /// Creates an orientation Quaternion using an angle and arbitrary axis.
        /// </summary>
        public static Quaternion FromAngleAxis(float Angle, Vector3 Axis)
        {
            if (Axis.SquaredLength == 0.0f)
                return Identity;

            return new Quaternion(new Vector4(Axis.Normalize() * (float)Math.Sin(Angle * 0.5f), (float)Math.Cos(Angle * 0.5f)));
        }

The opengl4csharp library builds a lot of this functionality in (it also has methods to convert a Quaternion to a Matrix4 automatically). Here's an example replacement for your rotate method. Simply increase 'angle':

        public void Rotate(float dt)
        {
            angle += 1f * dt;
            rotation = Quaternion.FromAngleAxis(angle, new Vector3(0.5, 0.2, 0.8).Normalize());
        }

Here's an example of using the built-in method for converting a Quaternion to a Matrix4:

        private Matrix4 GetModelMatrix()
        {
            Matrix4 transform = rotation.Matrix4;
            transform[0] = transform[0] * new Vector4(scale, 0);
            transform[1] = transform[1] * new Vector4(scale, 0);
            transform[2] = transform[2] * new Vector4(scale, 0);
            transform[3] = new Vector4(position.x, position.y, position.z, 1.0f);

            return transform;
        }

Let me know if this helps! You can read more about conversion between axis/angle and quaterion here: http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/

Cheers,

Giawa

@JesseLeeuwen
Copy link
Author

thanks!!! Giawa, it works !!!!!!

@giawa
Copy link
Owner

giawa commented Aug 14, 2015

Glad to hear it! I'm closing the issue now as resolved, but please feel free to open another issue if you run into a problem. Happy coding!

@giawa giawa closed this as completed Aug 14, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants