Introduce the Transform class and use it in the gpu api and for rendering models

- add the Transform class files in the Shared library. mostly inspired by Andrezj design, this is encapsulating the standard translation, rotation and scale of a rigid/uniform/nonuniform transformation matrix represented by a glm::mat4. the class manage a hidden cache Mat4. We will be able to improve on this and support projection matrix in the near future.
 
-- THe accuracy of transform composition is not necessarily better with this object now but we will be able to improve on the accuracy of transform stacks inside the class while preserving simple float vec and quat parameters for the interface... this is definitely a TODO.

- add a Transform stage to the gpu::Batch interface that can take a projection, view and model Transform. This will do the right thing for rendering the shape at the MVP matrix defined just like in fixed pipeline of OpenGL. When we will switch to non fixed piepeline we will be able to make these transform matrices available to the shaders through generic uniforms.

- Introduce a "viewTransform" to the application in order to mimic the current "untranslatedViewMatrix" and use it for rendering the models. With this change, the models don't use the glMatrix calls anymore but instead the new Transform stage of the gpu::Batch

- Performance wise this last change doesn't change things much. we definitely still do a lot extra works while creating the gpu::batch creating new Transform for each entities. One of the goal of this work is also to be soon able to replay the same batch several times just changing the viewTransform upfront and avoid redoing the traversal for several frames, to be continued....
Yes, good point.
Thanks

S

On Wed, Nov 12, 2014 at 5:03 PM, AndrewMeadows <notifications@github.com>
wrote:

> In libraries/shared/src/Transform.cpp:
>
> > +                         fabs(rotationMat[0][i] - nextRotation[0][i]) +
> > +                         fabs(rotationMat[1][i] - nextRotation[1][i]) +
> > +                         fabs(rotationMat[2][i] - nextRotation[2][i]));
> > +            norm = (norm > n ? norm : n);
> > +        }
> > +        rotationMat = nextRotation;
> > +    } while (count < 100 && norm > ACCURACY_THREASHOLD);
> > +
> > +
> > +    // extract scale of the matrix as the length of each axis
> > +    Mat3 scaleMat = glm::inverse(rotationMat) * rotationScaleMatrix;
> > +
> > +    scale = Vec3(scaleMat[0][0], scaleMat[1][1], scaleMat[2][2]);
> > +    if (scale.x < ACCURACY_THREASHOLD) scale.x = ACCURACY_THREASHOLD;
> > +    if (scale.y < ACCURACY_THREASHOLD) scale.y = ACCURACY_THREASHOLD;
> > +    if (scale.z < ACCURACY_THREASHOLD) scale.z = ACCURACY_THREASHOLD;
>
> Since ACCURACY_THREASHOLD is a float the max clamp can be achieved as
> follows:
>
> scale = glm::min(glm::vec3(ACCURACY_THREASHOLD), scale);
>
> While it seems like a convoluted way to go about things, it is definitely
> faster when SIMD math is being employed because the cost of populating a
> SIMD array on the stack (and the single-op max) is quite cheap compared to
> pulling each individual float value out of an existing SIMD array (not to
> mention the branch caused by the if check).
>
> —
> Reply to this email directly or view it on GitHub
> <https://github.com/highfidelity/hifi/pull/3778/files#r20266122>.
>