ultimatepp/bazaar/SurfaceCtrl/Transform.cpp
xemuth d350aeade7 SurfaceCtrl: Refactorisation of Camera class, start of new camera named magic camera
git-svn-id: svn://ultimatepp.org/upp/trunk@14801 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2020-08-12 14:46:49 +00:00

407 lines
No EOL
13 KiB
C++

//#include "Transform.h"
/*
Transform object from UltimateOpenGL
*/
/*
namespace Upp{
Transform::Transform(){
Up = glm::vec3(0.0f,1.0f,0.0f);
Right = glm::vec3(1.0f,0.0f,0.0f);
}
Transform::Transform(const Transform& _transform){
position = _transform.position;
quaterion = _transform.quaterion;
secondQuaterion = _transform.secondQuaterion;
scale= _transform.scale;
modelMatrix = _transform.modelMatrix;
Front = _transform.Front;
Up =_transform.Up;
Right = _transform.Right;
WorldUp = _transform.WorldUp;
}
Transform& Transform::operator=(const Transform& _transform){
position = _transform.position;
quaterion = _transform.quaterion;
secondQuaterion = _transform.secondQuaterion;
scale= _transform.scale;
modelMatrix = _transform.modelMatrix;
Front = _transform.Front;
Up =_transform.Up;
Right = _transform.Right;
WorldUp = _transform.WorldUp;
return *this;
}
//******************Setter/Getter*******************
Transform& Transform::SetFront(const glm::vec3& _front){
Front = _front;
return *this;
}
Transform& Transform::SetUp(const glm::vec3& _up){
Up = _up;
return *this;
}
Transform& Transform::SetRight(const glm::vec3& _right){
Right = _right;
return *this;
}
Transform& Transform::SetWorldUp(const glm::vec3& _worldUp){
WorldUp = _worldUp;
return *this;
}
const glm::vec3& Transform::GetFront()const{
return Front;
}
const glm::vec3& Transform::GetUp()const{
return Up;
}
const glm::vec3& Transform::GetRight()const{
return Right;
}
const glm::vec3& Transform::GetWorldUp()const{
return WorldUp;
}
const glm::vec3& Transform::GetPosition()const{
return position;
}
const glm::quat& Transform::GetQuaterion()const{
return quaterion;
}
const glm::quat& Transform::GetSecondQuaterion()const{
return secondQuaterion;
}
const glm::vec3& Transform::GetScallabeMatrix()const{
return scale;
}
const glm::mat4 Transform::GetModelMatrixScaller()const{
return modelMatrix;
}
const Upp::Vector<Transform*>& Transform::GetChildrens()const{
return childrens;
}
//******************Childs part********************
Transform& Transform::ClearChildrens(){
childrens.Clear();
return *this;
}
Transform& Transform::AddChildren(Transform& _ptr){
bool trouver =false;
for(Transform* t : childrens){
if(t == &_ptr){
trouver = true;
break;
}
}
if(!trouver) childrens.Add(&_ptr);
else LOG("Warning : Transform& Transform::AddChild(Transform&) Transform adresse " + Upp::AsString(&_ptr) +" is still children of this transform");
return *this;
}
Transform& Transform::AddChildrens(const Upp::Vector<Transform*>& _childrens){
bool trouver =false;
for(Transform* t : _childrens){
trouver =false;
for(Transform* t2 : childrens){
if(t == t2){
trouver = true;
break;
}
}
if(!trouver) childrens.Add(t);
else LOG("Warning : Transform& Transform::AddChilds(const Upp::Vector<Transform*>&) Transform adresse " + Upp::AsString(t) +" is still children of this transform");
}
return *this;
}
Transform& Transform::RemoveChildrens(const Upp::Vector<Transform*>& _childrens){
int cpt = 0;
for(Transform* t : _childrens){
cpt=0;
for(Transform* t2 : childrens){
if(t == t2){
childrens.Remove(cpt,1);
break;
}
cpt++;
}
if(cpt > childrens.GetCount())LOG("Warning : Transform& Transform::RemoveChilds(const Upp::Vector<Transform*>&) Transform adresse " + Upp::AsString(t) +" is not a children of this transform");
}
return *this;
}
Transform& Transform::RemoveChildren(Transform& _ptr){
int cpt = 0;
for(Transform* t : childrens){
if(&_ptr == t){
childrens.Remove(cpt,1);
break;
}
cpt++;
}
if(cpt > childrens.GetCount()) LOG("Warning : Transform& Transform::RemoveChild(Transform&) Transform adresse " + Upp::AsString(&_ptr) +" is not child of this transform");
return *this;
}
int Transform::NumberOfChildrens(){
return childrens.GetCount();
}
glm::mat4 Transform::GetModelMatrice()const{
return glm::translate(glm::mat4(1.0f),position) * glm::mat4_cast(quaterion) * modelMatrix;
}
glm::mat4 Transform::GetViewMatrix()const{
return glm::lookAt(position,position + Front, Up);
/* glm::mat4 rotate = glm::mat4_cast(quaterion);
glm::mat4 translate = glm::mat4(1.0f);
translate = glm::translate(translate,-position);
return rotate * translate;*/
//}
//******************Position part******************
/*
Transform& Transform::Move(glm::vec3 move,bool updateChildrens){//Move the position from the vec3 arg
position += move;
if(updateChildrens){
for(Transform* ptr1 : childrens){
ptr1->Move(move,updateChildrens);
}
}
return *this;
}
Transform& Transform::MoveFromAngle(glm::vec3 move,bool updateChildrens ){//Move but care about the angle
glm::mat4 rotation = glm::mat4_cast(quaterion);
position = ExtractPositionFromModelMatrix(glm::translate(glm::mat4(1.0f),-move) * rotation);
if(updateChildrens){
for(Transform* ptr1 : childrens){
ptr1->MoveFromAngle(move,updateChildrens);
}
}
return *this;
}
Transform& Transform::SetNewPosition(glm::vec3 newPosition,bool updateChildrens){//set the new position of object //It update all the child by : newPose + (old parent pose - old child pos);
glm::vec3 buffer = position;
buffer +=newPosition;
position = newPosition;
if(updateChildrens){
for(Transform* ptr1 : childrens){
ptr1->Move(buffer,updateChildrens);
}
}
return *this;
}
//******************Scale part*********************
Transform& Transform::Scale(glm::vec3 scallar,bool updateChildrens){
scale = scallar;
modelMatrix = glm::scale(modelMatrix,scale);
if(updateChildrens){
for(Transform* ptr1 : childrens){
ptr1->Scale(scallar,updateChildrens);
}
}
return *this;
}
Transform& Transform::SetNewScale(glm::vec3 newScallar,bool updateChildrens){//we ensure the scall is made by mutiply 1.0f model matrix to new scallar
scale = newScallar;
modelMatrix = glm::scale(glm::mat4(1.0f),scale);
if(updateChildrens){
for(Transform* ptr1 : childrens){
ptr1->SetNewScale(scale,updateChildrens);
}
}
return *this;
}
//******************Rotation part******************
Transform& Transform::Rotate(glm::quat _quaterion,bool updateChildrens){
quaterion =quaterion *_quaterion ;
RecalculateFrontUpRight(false);
if(updateChildrens){
for(Transform* ptr1 : childrens){
ptr1->Rotate(_quaterion,updateChildrens);
}
}
return *this;
}
Transform& Transform::SetNewRotation(glm::quat newQuaterion,bool updateChildrens){
quaterion =newQuaterion;
RecalculateFrontUpRight(false);
if(updateChildrens){
for(Transform* ptr1 : childrens){
ptr1->SetNewRotation(newQuaterion,updateChildrens);
}
}
return *this;
}
Transform& Transform::RotateFromAngles(float angleInDegree,glm::vec3 EulerAngles,bool updateChildrens){
if(EulerAngles.x > 0){
Rotate(glm::angleAxis(glm::radians(angleInDegree), glm::vec3(1.0f,0.0f,0.0f)),updateChildrens);
}
if(EulerAngles.y > 0){
Rotate(glm::angleAxis(glm::radians(angleInDegree), glm::vec3(0.0f,1.0f,0.0f)),updateChildrens);
}
if(EulerAngles.z > 0){
Rotate(glm::angleAxis(glm::radians(angleInDegree), glm::vec3(0.0f,0.0f,1.0f)),updateChildrens);
}
return *this;
}
Transform& Transform::SetNewRotationFromAngles(float angleInDegree,glm::vec3 EulerAngles,bool updateChildrens){
if(EulerAngles.x > 0){
SetNewRotation(glm::angleAxis(glm::radians(angleInDegree), glm::vec3(1.0f,0.0f,0.0f)),updateChildrens);
}
if(EulerAngles.y > 0){
SetNewRotation(glm::angleAxis(glm::radians(angleInDegree), glm::vec3(0.0f,1.0f,0.0f)),updateChildrens);
}
if(EulerAngles.z > 0){
SetNewRotation(glm::angleAxis(glm::radians(angleInDegree), glm::vec3(0.0f,0.0f,1.0f)),updateChildrens);
}
return *this;
}
//******************Second Rotation part***********
Transform& Transform::SecondRotate(glm::quat _quaterion,bool updateChildrens){
secondQuaterion =secondQuaterion *_quaterion ;
if(updateChildrens){
for(Transform* ptr1 : childrens){
ptr1->SecondRotate(_quaterion,updateChildrens);
}
}
return *this;
}
Transform& Transform::SetNewSecondRotation(glm::quat newQuaterion,bool updateChildrens){
quaterion =newQuaterion;
if(updateChildrens){
for(Transform* ptr1 : childrens){
ptr1->SetNewSecondRotation(newQuaterion,updateChildrens);
}
}
return *this;
}
Transform& Transform::SecondRotateFromAngles(float angleInDegree,glm::vec3 EulerAngles,bool updateChildrens){
if(EulerAngles.x > 0){
SecondRotate(glm::angleAxis(glm::radians(angleInDegree), glm::vec3(1.0f,0.0f,0.0f)),updateChildrens);
}
if(EulerAngles.y > 0){
SecondRotate(glm::angleAxis(glm::radians(angleInDegree), glm::vec3(0.0f,1.0f,0.0f)),updateChildrens);
}
if(EulerAngles.z > 0){
SecondRotate(glm::angleAxis(glm::radians(angleInDegree), glm::vec3(0.0f,0.0f,1.0f)),updateChildrens);
}
return *this;
}
Transform& Transform::SetNewSecondRotationFromAngles(float angleInDegree,glm::vec3 EulerAngles,bool updateChildrens){
if(EulerAngles.x > 0){
SetNewSecondRotation(glm::angleAxis(glm::radians(angleInDegree), glm::vec3(1.0f,0.0f,0.0f)),updateChildrens);
}
if(EulerAngles.y > 0){
SetNewSecondRotation(glm::angleAxis(glm::radians(angleInDegree), glm::vec3(0.0f,1.0f,0.0f)),updateChildrens);
}
if(EulerAngles.z > 0){
SetNewSecondRotation(glm::angleAxis(glm::radians(angleInDegree), glm::vec3(0.0f,0.0f,1.0f)),updateChildrens);
}
return *this;
}
//******************Quick function part******************
Transform& Transform::LookAt(glm::vec3 const& lookTo,bool inverse,bool updateChildrens){
glm::quat buffer = QuatLookAt(position,lookTo,Up);
if(inverse) buffer = glm::inverse(buffer);
SetNewRotation(buffer,updateChildrens);
return *this;
}
Transform& Transform::ProcessMouseMouvement(float Yaw,float Pitch,float Roll,bool updateChildrens){
glm::quat key_quat = glm::quat(glm::vec3(-Pitch, Yaw, Roll));
quaterion = key_quat * quaterion;
quaterion = glm::normalize(quaterion);
RecalculateFrontUpRight(false);
if(updateChildrens){
for(Transform* ptr1 : childrens){
ptr1->ProcessMouseMouvement(Yaw,Pitch,Roll,updateChildrens);
}
}
return *this;
}
Transform& Transform::UpdateByEuler(float Yaw,float Pitch,float Roll,bool updateChildrens){
quaterion = EulerToQuaterion(Yaw,-Pitch,Roll);
quaterion = glm::normalize(quaterion);
RecalculateFrontUpRight(false);
if(updateChildrens){
for(Transform* ptr1 : childrens){
ptr1->UpdateByEuler(Yaw,Pitch,Roll,updateChildrens);
}
}
return *this;
}
Transform& Transform::RecalculateFrontUpRight(bool updateChildrens){
Front = glm::rotate(glm::inverse(quaterion), glm::vec3(0.0, 0.0,-1.0));
Right = glm::rotate(glm::inverse(quaterion), glm::vec3(1.0, 0.0, 0.0));
Up = glm::rotate(glm::inverse(quaterion), WorldUp);
if(updateChildrens){
for(Transform* ptr1 : childrens){
ptr1->RecalculateFrontUpRight(updateChildrens);
}
}
return *this;
}
//Taken from https://stackoverflow.com/questions/18172388/glm-quaternion-lookat-function
glm::quat Transform::QuatLookAt(glm::vec3 const& lookFrom,glm::vec3 const& lookTo,glm::vec3 const& up){
glm::vec3 direction = lookTo - lookFrom;
float directionLength = glm::length(direction);
if(!(directionLength > 0.0001))
return glm::quat(1, 0, 0, 0);
direction /= directionLength;
return glm::quatLookAt(direction, up);
}
//Taken from http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/index.htm
glm::vec3 Transform::QuaterionToEuler(glm::quat const& q1){
double heading = 0;
double attitude = 0;
double bank = 0;
double sqw = q1.w*q1.w;
double sqx = q1.x*q1.x;
double sqy = q1.y*q1.y;
double sqz = q1.z*q1.z;
double unit = sqx + sqy + sqz + sqw; // if normalised is one, otherwise is correction factor
double test = q1.x*q1.y + q1.z*q1.w;
if (test > 0.499*unit) { // singularity at north pole
heading = 2 * atan2(q1.x,q1.w);
attitude = glm::pi<double>() /2;
bank = 0;
return glm::vec3(heading,attitude,bank);
}
if (test < -0.499*unit) { // singularity at south pole
heading = -2 * atan2(q1.x,q1.w);
attitude = -glm::pi<double>() /2;
bank = 0;
return glm::vec3(heading,attitude,bank);
}
heading = atan2(2*q1.y*q1.w-2*q1.x*q1.z , sqx - sqy - sqz + sqw);
bank = asin(2*test/unit);
attitude = atan2(2*q1.x*q1.w-2*q1.y*q1.z , -sqx + sqy - sqz + sqw);
return glm::vec3(attitude,heading,bank);
}
//Taken from http://www.euclideanspace.com/maths/geometry/rotations/conversions/eulerToQuaternion/index.htm
glm::quat Transform::EulerToQuaterion(float Yaw,float Pitch,float Roll){
glm::quat q1 = CreateQuaterion((glm::radians(Pitch)/2.0f) * -1.0f ,glm::vec3(1.0f,0.0f,0.0f));
glm::quat q2 = CreateQuaterion(glm::radians(Yaw)/2.0f,glm::vec3(0.0f,1.0f,0.0f));
glm::quat q3 = CreateQuaterion(glm::radians(Roll)/2.0f,glm::vec3(0.0f,0.0f,1.0f));
return q1 * q2 * q3;
}
glm::vec3 Transform::ExtractPositionFromModelMatrix(const glm::mat4& modelMatrix){
glm::mat3 rotMat(modelMatrix);
glm::vec3 d(modelMatrix[3]);
glm::vec3 retVec = -d * rotMat;
return retVec;
}
glm::quat Transform::CreateQuaterion(float HalfAngleInRadians, glm::vec3 Dir){
float sinVal = glm::sin(HalfAngleInRadians);
float cosVal = glm::cos(HalfAngleInRadians);
float xVal = Dir.x * sinVal;
float yVal = Dir.y * sinVal;
float zVal = Dir.z * sinVal;
return glm::quat(cosVal,xVal, yVal, zVal);
}
}*/