PhysX中PxTransform类的使用
physx中的PxTransForm类:https://github.com/NVIDIAGameWorks/PhysX/blob/4.1/pxshared/include/foundation/PxTransform.h
PxQuat类 https://github.com/NVIDIAGameWorks/PhysX/blob/4.1/pxshared/include/foundation/PxQuat.h
Summary:
PxTransform类用于表示刚体在一个坐标系的位姿,即,表示空间空的一个坐标系相对于另一个坐标系的位姿。
包括两个成员:
PxVec3 p;//原点位置
PxQuat q;//坐标系姿态
验证
亲自动手验证了:
//得到 "绕空间向量vec旋转angle弧度"这个动作对应的四元数 //angle:rad PxQuat getQuatFromVectorAndAngle(PxVec3 vec, float angle/*, float& x, float& y, float& z,float& real*/) { PxQuat result; //绕vec旋转angle 弧度对应的四元数的各个元素: float real = std::cosf(angle / 2.0f); float x = vec.x*std::sinf(angle / 2.0f); float y = vec.y*std::sinf(angle / 2.0f); float z = vec.z*std::sinf(angle / 2.0f); //return PxQuat(real,x,y,z);//wrong return PxQuat(x, y, z,real);//ok/----PxQuat::nw corresponds to real par!!! } float pi = 3.1415926; //test move---------------------------- PxTransform transform1(PxVec3(10.f, 0.f, 0.f), PxQuat(PxIdentity));//相对于全局系,沿x轴移动10得到transform1,transform1代表这一个坐标系。 PxTransform transform2(PxVec3(15.f, 0.f, 0.f), PxQuat(PxIdentity));//x轴移动15 //将transform2看做以transform1为参考,即其相对于transform1的原点移动了10,则transform2与全局系的关系: PxTransform transform2_to_glob = transform1 * transform2;//即transform2系在全局系下的位姿 //expeted result: PxVec3 vecExp = PxVec3(25.f, 0.f, 0.f);//另外,姿态是重合的 //设在transform2系下有一个向量(35,0,0),求其在全局系下的坐标 PxVec3 vecInTransform2 = PxVec3(35.f, 0.f, 0.f); PxVec3 vecInGlob = transform2_to_glob.transform(vecInTransform2);//与之前的认知一样:坐标系A经过一系列变化得到坐标系B,两者之间的关系为4*4矩阵Trans, //Trans的旋转矩阵部分在左上角,为3*3矩阵,其第一列为B系的x轴在A系下的表示.., //空间向量在B系下的表示为vec,则在A系下为Trans*vec //expeted result: PxVec3 vecInGlobExp = PxVec3(25.f+35.f, 0.f, 0.f); //设在全局系下有一个向量(5,0,0),求其在transform2系下的坐标: PxVec3 vecGbolTo2 = transform2_to_glob.transformInv(PxVec3(5.f, 0.f, 0.f));//OK //expeted result: PxVec3 vecGbolTo2Exp = PxVec3(-20.f, 0.f, 0.f); //test rotate---------------------------- PxTransform transformA(PxVec3(0.f, 0.f, 0.f), getQuatFromVectorAndAngle(PxVec3(0.f, 0.f, 1.0f), pi/2.0f));//相对于全局系,绕z轴转90度到transformA。 PxTransform transformB(PxVec3(0.f, 0.f, 0.f), getQuatFromVectorAndAngle(PxVec3(0.f, 0.f, 1.0f), pi/2.0f));//绕z轴转90度 //将transformB看做以transformA为参考,即其绕transformA的z轴转动了90度,则transformB与全局系的关系: PxTransform transformB_to_glob = transformA * transformB;////即transformB系在全局系下的位姿 //expeted result: PxQuat QuatExp = getQuatFromVectorAndAngle(PxVec3(0.f, 0.f, 1.0f), pi);//全局系绕自身z轴转180度 //设在transformB系下有一个向量(30,0,0),求其在全局系下的坐标 PxVec3 vecInTransformB = PxVec3(30.f, 0.f, 0.f); PxVec3 vecBInGlob = transformB_to_glob.transform(vecInTransformB); //expeted result: PxVec3 vecBInGlobExp = PxVec3(-30.f, 0.f, 0.f); //设在transformB系下有一个位姿:位置是PxVec3(30,0,0),姿态是绕z轴旋转-90度:getQuatFromVectorAndAngle(PxVec3(0.f, 0.f, 1.0f), -pi / 2.0f), //求其在全局系下的坐标 PxTransform TransformInB(PxVec3(30.f, 0.f, 0.f), getQuatFromVectorAndAngle(PxVec3(0.f, 0.f, 1.0f), -pi / 2.0f)); PxTransform TransformInBInGlob = transformB_to_glob.transform(TransformInB); //expeted result: PxTransform TransformInBInGlobExp(PxVec3(-30.f, 0.f, 0.f), getQuatFromVectorAndAngle(PxVec3(0.f, 0.f, 1.0f), pi / 2.0f)); //test rotate and move---------------------------- PxTransform transformAA(PxVec3(10.f, 0.f, 0.f), PxQuat(PxIdentity));//相对于全局系,沿x轴移动10得到transformAA。 PxTransform transformBB(PxVec3(0.f, 0.f, 0.f), getQuatFromVectorAndAngle(PxVec3(0.f, 0.f, 1.0f), pi / 2.0f));//绕z轴转90度 //将transformB看做以transformA为参考,即其绕transformA的z轴转动了90度,则transformB与全局系的关系: PxTransform transformBB_to_glob = transformAA * transformBB; //expeted result: PxQuat QuatBBExp = getQuatFromVectorAndAngle(PxVec3(0.f, 0.f, 1.0f), pi / 2.0f); PxVec3 vecBBExp = PxVec3(10.f, 0.f, 0.f); //设在transformBB系下有一个向量(30,0,0),求其在全局系下的坐标 PxVec3 vecInTransformBB = PxVec3(30.f, 0.f, 0.f); PxVec3 vecInBBGlob = transformBB_to_glob.transform(vecInTransformBB); //expeted result: PxVec3 vecBBInGlobExp = PxVec3(10.f, 30.f, 0.f);//drwa it
summary
summary:注意比较PxTransform类的这四个函数: //如上,设A系经过一系列变换得到B系,两者之间的关系已知,空间中一个固定点,其在B系中的表达为入参input,该函数据此求出该空间点在A系中的表示。 //因为B系的原点与A系可能不重合,所以要考虑加上p, p即为B系得原点在A系中得表示哦/。 PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3 transform(const PxVec3& input) const { PX_SHARED_ASSERT(isFinite()); return q.rotate(input) + p; } //如上,设A系经过一系列变换得到B系,两者之间的关系已知,空间中一个固定点,其在A系中的表达为入参input,该函数据此求出该空间点在B系中的表示。 //对于input - p,其中input和p都是在A系中得表达式,input - p即为以B系原点为起点指向空间点的向量在A系中的表示 , //然后旋转input - p即可得到空间点在B系中的表示./ PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3 transformInv(const PxVec3& input) const { PX_SHARED_ASSERT(isFinite()); return q.rotateInv(input - p); } //如上,设A系经过一系列变换得到B系,两者之间的关系已知. rotate和rotateInv函数相当于仅仅考虑两个坐标系的姿态关系。 //rotate(const PxVec3& input)函数的入参为B系中的向量,该函数将其转换为A系中的表达式。--想象A B两系原点重合。 //rotateInv(const PxVec3& input)函数的入参为A系中的向量,该函数将其转换为B系中的表达式. PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3 rotate(const PxVec3& input) const { PX_SHARED_ASSERT(isFinite()); return q.rotate(input); } PX_CUDA_CALLABLE PX_FORCE_INLINE PxVec3 rotateInv(const PxVec3& input) const { PX_SHARED_ASSERT(isFinite()); return q.rotateInv(input); } //如上,设A系经过一系列变换得到B系,两者之间的关系已知.该函数的入参为B系中的一个刚体的位姿src,该函数将刚体在B系下的位置src.p转换为 //A系下表示, 将刚体在B系下的姿态src.q转换为A系下表示, 并将两者组合起来以一个PxTransform对象返回。 operator*函数就是基于此函数的。 //由此函数的实现部分可以推知:两个四元数连乘法的意义,B系得姿态在A系中为q,刚体在B系中的姿态为src.q,q * src.q即为刚体在A系统下的姿态。 //! Transform transform to parent (returns compound transform: first src, then *this) PX_CUDA_CALLABLE PX_FORCE_INLINE PxTransform transform(const PxTransform& src) const { PX_SHARED_ASSERT(src.isSane()); PX_SHARED_ASSERT(isSane()); // src = [srct, srcr] -> [r*srct + t, r*srcr] return PxTransform(q.rotate(src.p) + p, q * src.q); } PX_CUDA_CALLABLE PX_FORCE_INLINE PxTransform operator*(const PxTransform& x) const { PX_SHARED_ASSERT(x.isSane()); return transform(x); } //该函数应该是用4*4坐标变换矩阵实例化一个PxTransform,体现了如何将3*3旋转矩阵转换为四元数。 PX_CUDA_CALLABLE PX_FORCE_INLINE explicit PxTransform(const PxMat44& m); // defined in PxMat44.h