C++ 如何在三维世界中获取对象相对于父对象的绝对位置?

C++ 如何在三维世界中获取对象相对于父对象的绝对位置?,c++,math,3d,C++,Math,3d,我正在构建一个3D引擎只是为了学习,我有一个对象是另一个对象的父对象。并且该父对象相对于父对象具有位置。所以我想知道,如果父对象具有旋转和缩放,如何获得该对象的位置 我已经进入了统一体,来看看这是怎么回事,我看到了旋转时他们使用正弦和余弦,但我不知道怎么做。 我想使用父对象的前向,但只有当子对象的位置为(0,0,1)时才有效,对吗?因为如果它的位置不是那样的话,它应该是什么?空间中两个位置之间唯一剩下的操作是相乘(矩阵相乘)(因为相加不会得到我们想要的结果),但我想我只是讨论了选项 我没有代码,

我正在构建一个3D引擎只是为了学习,我有一个对象是另一个对象的父对象。并且该父对象相对于父对象具有位置。所以我想知道,如果父对象具有旋转和缩放,如何获得该对象的位置

我已经进入了统一体,来看看这是怎么回事,我看到了旋转时他们使用正弦和余弦,但我不知道怎么做。 我想使用父对象的前向,但只有当子对象的位置为(0,0,1)时才有效,对吗?因为如果它的位置不是那样的话,它应该是什么?空间中两个位置之间唯一剩下的操作是相乘(矩阵相乘)(因为相加不会得到我们想要的结果),但我想我只是讨论了选项

我没有代码,因为我不知道从哪里开始,但主要是复制了Unity的类和结构名称。 为了对相机进行投影,我使用了Wikipedia()中的3D投影页面

我使用四元数进行旋转(维基百科页面也讨论了euler到四元数和四元数到euler:)

我认为关于代码的信息已经足够了

最后,我想让(0,0,1)中的子对象成为(0,0,0)中旋转到(0,90,0)的对象的父对象。子世界位置为(1,0,0)

我使用3x3矩阵而不是4x4矩阵的这种方法,功能如下:

inline Vector3 getPositionAbsoluteFromRelative(const Vector3 &relativeposition, const Vector3 &parentrotation) {
    return Vector3(
        relativeposition.x * (1 - 2 * (parentrotation.y * parentrotation.y + parentrotation.z * parentrotation.z)) + relativeposition.y * 2 * (parentrotation.x * parentrotation.y - parentrotation.w * parentrotation.z) + relativeposition.z * 2 * (parentrotation.x * parentrotation.z + parentrotation.w * parentrotation.y),
        relativeposition.x * 2 * (parentrotation.x * parentrotation.y + parentrotation.w * parentrotation.z) + relativeposition.y * (1 - 2 * (parentrotation.x * parentrotation.x + parentrotation.z * parentrotation.z)) + relativeposition.z * 2 * (parentrotation.y * parentrotation.z - parentrotation.w * parentrotation.x),
        relativeposition.x * 2 * (parentrotation.x * parentrotation.z - parentrotation.w * parentrotation.y) + relativeposition.y * 2 * (parentrotation.y * parentrotation.z + parentrotation.w * parentrotation.x) + relativeposition.z * (1 - 2 * (parentrotation.x * parentrotation.x + parentrotation.y * parentrotation.y))
    );
};

inline Vector3 getPositionAbsoluteFromRelative(const Vector3 &relativeposition, const Vector3 &parentrotation, const Vector3 &parentposition) {
    Vector3 absolute(
        relativeposition.x * (1 - 2 * (parentrotation.y * parentrotation.y + parentrotation.z * parentrotation.z)) + relativeposition.y * 2 * (parentrotation.x * parentrotation.y - parentrotation.w * parentrotation.z) + relativeposition.z * 2 * (parentrotation.x * parentrotation.z + parentrotation.w * parentrotation.y),
        relativeposition.x * 2 * (parentrotation.x * parentrotation.y + parentrotation.w * parentrotation.z) + relativeposition.y * (1 - 2 * (parentrotation.x * parentrotation.x + parentrotation.z * parentrotation.z)) + relativeposition.z * 2 * (parentrotation.y * parentrotation.z - parentrotation.w * parentrotation.x),
        relativeposition.x * 2 * (parentrotation.x * parentrotation.z - parentrotation.w * parentrotation.y) + relativeposition.y * 2 * (parentrotation.y * parentrotation.z + parentrotation.w * parentrotation.x) + relativeposition.z * (1 - 2 * (parentrotation.x * parentrotation.x + parentrotation.y * parentrotation.y))
    );

    return Vector3(
        absolute.x + parentposition.x,
        absolute.y + parentposition.y,
        absolute.z + parentposition.z
    );
};

inline Vector3 getPositionAbsoluteFromRelative(const Vector3 &relativeposition, const Vector3 &parentrotation, const Vector3 &parentposition, const Vector3 &parentscale) {
    Vector3 absolute(
        relativeposition.x * (1 - 2 * (parentrotation.y * parentrotation.y + parentrotation.z * parentrotation.z)) + relativeposition.y * 2 * (parentrotation.x * parentrotation.y - parentrotation.w * parentrotation.z) + relativeposition.z * 2 * (parentrotation.x * parentrotation.z + parentrotation.w * parentrotation.y),
        relativeposition.x * 2 * (parentrotation.x * parentrotation.y + parentrotation.w * parentrotation.z) + relativeposition.y * (1 - 2 * (parentrotation.x * parentrotation.x + parentrotation.z * parentrotation.z)) + relativeposition.z * 2 * (parentrotation.y * parentrotation.z - parentrotation.w * parentrotation.x),
        relativeposition.x * 2 * (parentrotation.x * parentrotation.z - parentrotation.w * parentrotation.y) + relativeposition.y * 2 * (parentrotation.y * parentrotation.z + parentrotation.w * parentrotation.x) + relativeposition.z * (1 - 2 * (parentrotation.x * parentrotation.x + parentrotation.y * parentrotation.y))
    );

    return Vector3(
        absolute.x * parentscale.x + parentposition.x,
        absolute.y * parentscale.y + parentposition.y,
        absolute.z * parentscale.z + parentposition.z
    );
};

inline Vector3 getPositionRelativeFromAbsolute(const Vector3 &absoluteposition, const Vector3 &parentrotation) {
    return Vector3(
        absoluteposition.x * (1 - 2 * (parentrotation.y * parentrotation.y + parentrotation.z * parentrotation.z)) + absoluteposition.y * 2 * (parentrotation.x * parentrotation.y + parentrotation.w * parentrotation.z) + absoluteposition.z * 2 * (parentrotation.x * parentrotation.z - parentrotation.w * parentrotation.y),
        absoluteposition.x * 2 * (parentrotation.x * parentrotation.y - parentrotation.w * parentrotation.z) + absoluteposition.y * (1 - 2 * (parentrotation.x * parentrotation.x + parentrotation.z * parentrotation.z)) + absoluteposition.z * 2 * (parentrotation.y * parentrotation.z + parentrotation.w * parentrotation.x),
        absoluteposition.x * 2 * (parentrotation.x * parentrotation.z + parentrotation.w * parentrotation.y) + absoluteposition.y * 2 * (parentrotation.y * parentrotation.z - parentrotation.w * parentrotation.x) + absoluteposition.z * (1 - 2 * (parentrotation.x * parentrotation.x + parentrotation.y * parentrotation.y))
    );
};

inline Vector3 getPositionRelativeFromAbsolute(const Vector3 &absoluteposition, const Vector3 &parentrotation, const Vector3 &parentposition) {
    Vector3 __position = {
        absoluteposition.x - parentposition.x,
        absoluteposition.y - parentposition.y,
        absoluteposition.z - parentposition.z
    };

    return Vector3(
        __position.x * (1 - 2 * (parentrotation.y * parentrotation.y + parentrotation.z * parentrotation.z)) + __position.y * 2 * (parentrotation.x * parentrotation.y + parentrotation.w * parentrotation.z) + __position.z * 2 * (parentrotation.x * parentrotation.z - parentrotation.w * parentrotation.y),
        __position.x * 2 * (parentrotation.x * parentrotation.y - parentrotation.w * parentrotation.z) + __position.y * (1 - 2 * (parentrotation.x * parentrotation.x + parentrotation.z * parentrotation.z)) + __position.z * 2 * (parentrotation.y * parentrotation.z + parentrotation.w * parentrotation.x),
        __position.x * 2 * (parentrotation.x * parentrotation.z + parentrotation.w * parentrotation.y) + __position.y * 2 * (parentrotation.y * parentrotation.z - parentrotation.w * parentrotation.x) + __position.z * (1 - 2 * (parentrotation.x * parentrotation.x + parentrotation.y * parentrotation.y))
    );
};

inline Vector3 getPositionRelativeFromAbsolute(const Vector3 &absoluteposition, const Vector3 &parentrotation, const Vector3 &parentposition, const Vector3 &parentscale) {
    Vector3 __position = {
        absoluteposition.x - parentposition.x,
        absoluteposition.y - parentposition.y,
        absoluteposition.z - parentposition.z
    };

    Vector3 relative(
        __position.x * (1 - 2 * (parentrotation.y * parentrotation.y + parentrotation.z * parentrotation.z)) + __position.y * 2 * (parentrotation.x * parentrotation.y + parentrotation.w * parentrotation.z) + __position.z * 2 * (parentrotation.x * parentrotation.z - parentrotation.w * parentrotation.y),
        __position.x * 2 * (parentrotation.x * parentrotation.y - parentrotation.w * parentrotation.z) + __position.y * (1 - 2 * (parentrotation.x * parentrotation.x + parentrotation.z * parentrotation.z)) + __position.z * 2 * (parentrotation.y * parentrotation.z + parentrotation.w * parentrotation.x),
        __position.x * 2 * (parentrotation.x * parentrotation.z + parentrotation.w * parentrotation.y) + __position.y * 2 * (parentrotation.y * parentrotation.z - parentrotation.w * parentrotation.x) + __position.z * (1 - 2 * (parentrotation.x * parentrotation.x + parentrotation.y * parentrotation.y))
    );

    return Vector3(relative.x / parentscale.x, relative.y / parentscale.y, relative.z / parentscale.z);
};

3d对象的位置和方向可以组合并存储在4x4矩阵中,同时

  • 位置是从世界原点到对象原点的转换
  • 方向是围绕对象原点的旋转
为什么是4x4矩阵

所有常用的变换(平移、旋转、缩放、剪切、投影)都可以表示为这样的矩阵

变换的串联等价于相应矩阵的乘法

虽然将一系列变换函数组合成一个函数可能很难(且不灵活),但很容易对矩阵(表示变换序列)进行预乘,以便可以一次应用所有变换(通过一个矩阵乘法)

这就是为什么4×4矩阵在3D comp中如此常见的原因。图形

OP的示例:

poschild'=Mparent·poschild

Mparent=Tparent·Rparent

代码:

#include <iostream>

#include "linmath.h"

int main()
{
  Vec3f posChild(0.0f, 0.0f, 1.0f);

  Vec3f posParent(0.0f, 0.0f, 0.0f);
  float abcParent[] = { 0.0f, 90.0f, 0.0f };

  // child pos as homogeneous coordinate
  Vec4f posChildH(posChild, 1.0f);

  // compose parent matrix of pos and ori
  Mat4x4f matParent
    = Mat4x4f(InitTrans, posParent)
    * makeEuler(RotZYX,
      degToRad(abcParent[0]),
      degToRad(abcParent[1]),
      degToRad(abcParent[2]));

  // make posChildH global
  Vec4f posChildHW = matParent * posChildH;

  // homogeneous coordinate -> pos in 3d
  Vec3f posChildW(
    posChildHW.x / posChildHW.w,
    posChildHW.y / posChildHW.w,
    posChildHW.z / posChildHW.w);

  // print result
  std::cout << "posChild in WCS: " << std::fixed << posChildW << '\n';
}


linmath
可在上找到

有关部分:

三维矢量:

template <typename VALUE>
struct Vec3T {
  typedef VALUE Value;
  Value x, y, z;
  Vec3T(Value x, Value y, Value z): x(x), y(y), z(z) { }
};

typedef Vec3T<float> Vec3f;
4×4矩阵的欧拉角:

enum ArgInitTrans { InitTrans };
enum ArgInitRot { InitRot };

template <typename VALUE>
struct Mat4x4T {
  union {
    VALUE comp[4 * 4];
    struct {
      VALUE _00, _01, _02, _03;
      VALUE _10, _11, _12, _13;
      VALUE _20, _21, _22, _23;
      VALUE _30, _31, _32, _33;
    };
  };

  // constructor to build a matrix for translation
  Mat4x4T(ArgInitTrans, const Vec3T<VALUE> &t):
    _00((VALUE)1), _01((VALUE)0), _02((VALUE)0), _03((VALUE)t.x),
    _10((VALUE)0), _11((VALUE)1), _12((VALUE)0), _13((VALUE)t.y),
    _20((VALUE)0), _21((VALUE)0), _22((VALUE)1), _23((VALUE)t.z),
    _30((VALUE)0), _31((VALUE)0), _32((VALUE)0), _33((VALUE)1)
  { }
  // constructor to build a matrix for rotation about axis
  Mat4x4T(ArgInitRot, const Vec3T<VALUE> &axis, VALUE angle):
    _03((VALUE)0), _13((VALUE)0), _23((VALUE)0),
    _30((VALUE)0), _31((VALUE)0), _32((VALUE)0), _33((VALUE)1)
  {
    //axis.normalize();
    const VALUE sinAngle = sin(angle), cosAngle = cos(angle);
    const VALUE xx = axis.x * axis.x, xy = axis.x * axis.y;
    const VALUE xz = axis.x * axis.z, yy = axis.y * axis.y;
    const VALUE yz = axis.y * axis.z, zz = axis.z * axis.z;
    _00 = xx + cosAngle * ((VALUE)1 - xx) /* + sinAngle * 0 */;
    _01 = xy - cosAngle * xy - sinAngle * axis.z;
    _02 = xz - cosAngle * xz + sinAngle * axis.y;
    _10 = xy - cosAngle * xy + sinAngle * axis.z;
    _11 = yy + cosAngle * ((VALUE)1 - yy) /* + sinAngle * 0 */;
    _12 = yz - cosAngle * yz - sinAngle * axis.x;
    _20 = xz - cosAngle * xz - sinAngle * axis.y;
    _21 = yz - cosAngle * yz + sinAngle * axis.x;
    _22 = zz + cosAngle * ((VALUE)1 - zz) /* + sinAngle * 0 */;
  }
  // multiply matrix with matrix -> matrix
  Mat4x4T operator * (const Mat4x4T &mat) const
  {
    return Mat4x4T(
      _00 * mat._00 + _01 * mat._10 + _02 * mat._20 + _03 * mat._30,
      _00 * mat._01 + _01 * mat._11 + _02 * mat._21 + _03 * mat._31,
      _00 * mat._02 + _01 * mat._12 + _02 * mat._22 + _03 * mat._32,
      _00 * mat._03 + _01 * mat._13 + _02 * mat._23 + _03 * mat._33,
      _10 * mat._00 + _11 * mat._10 + _12 * mat._20 + _13 * mat._30,
      _10 * mat._01 + _11 * mat._11 + _12 * mat._21 + _13 * mat._31,
      _10 * mat._02 + _11 * mat._12 + _12 * mat._22 + _13 * mat._32,
      _10 * mat._03 + _11 * mat._13 + _12 * mat._23 + _13 * mat._33,
      _20 * mat._00 + _21 * mat._10 + _22 * mat._20 + _23 * mat._30,
      _20 * mat._01 + _21 * mat._11 + _22 * mat._21 + _23 * mat._31,
      _20 * mat._02 + _21 * mat._12 + _22 * mat._22 + _23 * mat._32,
      _20 * mat._03 + _21 * mat._13 + _22 * mat._23 + _23 * mat._33,
      _30 * mat._00 + _31 * mat._10 + _32 * mat._20 + _33 * mat._30,
      _30 * mat._01 + _31 * mat._11 + _32 * mat._21 + _33 * mat._31,
      _30 * mat._02 + _31 * mat._12 + _32 * mat._22 + _33 * mat._32,
      _30 * mat._03 + _31 * mat._13 + _32 * mat._23 + _33 * mat._33);
  }
  // constructor to build a matrix for rotation about axis
  Mat4x4T(ArgInitRot, const Vec3T<VALUE> &axis, VALUE angle):
    _03((VALUE)0), _13((VALUE)0), _23((VALUE)0),
    _30((VALUE)0), _31((VALUE)0), _32((VALUE)0), _33((VALUE)1)
  {
    //axis.normalize();
    const VALUE sinAngle = sin(angle), cosAngle = cos(angle);
    const VALUE xx = axis.x * axis.x, xy = axis.x * axis.y;
    const VALUE xz = axis.x * axis.z, yy = axis.y * axis.y;
    const VALUE yz = axis.y * axis.z, zz = axis.z * axis.z;
    _00 = xx + cosAngle * ((VALUE)1 - xx) /* + sinAngle * 0 */;
    _01 = xy - cosAngle * xy - sinAngle * axis.z;
    _02 = xz - cosAngle * xz + sinAngle * axis.y;
    _10 = xy - cosAngle * xy + sinAngle * axis.z;
    _11 = yy + cosAngle * ((VALUE)1 - yy) /* + sinAngle * 0 */;
    _12 = yz - cosAngle * yz - sinAngle * axis.x;
    _20 = xz - cosAngle * xz - sinAngle * axis.y;
    _21 = yz - cosAngle * yz + sinAngle * axis.x;
    _22 = zz + cosAngle * ((VALUE)1 - zz) /* + sinAngle * 0 */;
}
  // multiply matrix with vector -> vector
  Vec4T<VALUE> operator * (const Vec4T<VALUE> &vec) const
  {
    return Vec4T<VALUE>(
      _00 * vec.x + _01 * vec.y + _02 * vec.z + _03 * vec.w,
      _10 * vec.x + _11 * vec.y + _12 * vec.z + _13 * vec.w,
      _20 * vec.x + _21 * vec.y + _22 * vec.z + _23 * vec.w,
      _30 * vec.x + _31 * vec.y + _32 * vec.z + _33 * vec.w);
  }
};

typedef Mat4x4T<float> Mat4x4f;
template <typename VALUE>
Mat4x4T<VALUE> makeEuler(
  EulerAngle mode, VALUE rot1, VALUE rot2, VALUE rot3)
{
  RotAxis axis1, axis2, axis3;
  decompose(mode, axis1, axis2, axis3);
  const static VALUE axes[3][3] = {
    { (VALUE)1, (VALUE)0, (VALUE)0 },
    { (VALUE)0, (VALUE)1, (VALUE)0 },
    { (VALUE)0, (VALUE)0, (VALUE)1 }
  };
  return
      Mat4x4T<VALUE>(InitRot,
        Vec3T<VALUE>(axes[axis1][0], axes[axis1][1], axes[axis1][2]),
        rot1)
    * Mat4x4T<VALUE>(InitRot,
        Vec3T<VALUE>(axes[axis2][0], axes[axis2][1], axes[axis2][2]),
        rot2)
    * Mat4x4T<VALUE>(InitRot,
        Vec3T<VALUE>(axes[axis3][0], axes[axis3][1], axes[axis3][2]),
        rot3);
}
模板
Mat4x4T makeEuler(
欧拉格模式,值旋转1,值旋转2,值旋转3)
{
旋转轴轴1、轴2、轴3;
分解(模式,axis1,axis2,axis3);
常量静态值轴[3][3]={
{(值)1,(值)0,(值)0},
{(值)0,(值)1,(值)0},
{(值)0,(值)0,(值)1}
};
返回
Mat4x4T(InitRot,
Vec3T(轴[axis1][0]、轴[axis1][1]、轴[axis1][2]),
(1)
*Mat4x4T(InitRot,
Vec3T(轴[axis2][0]、轴[axis2][1]、轴[axis2][2]),
(2)
*Mat4x4T(InitRot,
Vec3T(轴[axis3][0]、轴[axis3][1]、轴[axis3][2],
rot3);
}


提供了一个类似但更全面的库。

我可以为您提供一个不同的开始(如果您愿意):。它是C++(除了一个最小的QTGUI来管理鼠标输入和输出光栅化图像)。我不想使用一个库,只是数学来获得绝对的(我想它是)相对物体的位置。所有其他的事实在绘画和东西上我已经做了一些关于它的事,那不是图书馆——它是一个玩具项目。你想复制什么就复制什么
linmath
提供了一组基本的常用数学。公司的东西。哦!对不起,误会了。我来看看!非常感谢您的努力和时间!
extern const double Pi;

template <typename VALUE>
inline VALUE degToRad(VALUE angle)
{
  return (VALUE)Pi * angle / (VALUE)180;
}
// enumeration of rotation axes
enum RotAxis {
  RotX, // rotation about x axis
  RotY, // rotation about y axis
  RotZ // rotation about z axis
};

// enumeration of possible Euler angles
enum EulerAngle {
  RotXYX = RotX + 3 * RotY + 9 * RotX, // 0 + 3 + 0 = 3
  RotXYZ = RotX + 3 * RotY + 9 * RotZ, // 0 + 3 + 18 = 21
  RotXZX = RotX + 3 * RotZ + 9 * RotX, // 0 + 6 + 0 = 6
  RotXZY = RotX + 3 * RotZ + 9 * RotY, // 0 + 6 + 9 = 15
  RotYXY = RotY + 3 * RotX + 9 * RotY, // 1 + 0 + 9 = 10
  RotYXZ = RotY + 3 * RotX + 9 * RotZ, // 1 + 0 + 18 = 19
  RotYZX = RotY + 3 * RotZ + 9 * RotX, // 1 + 6 + 0 = 7
  RotYZY = RotY + 3 * RotZ + 9 * RotY, // 1 + 6 + 9 = 16
  RotZXY = RotZ + 3 * RotX + 9 * RotY, // 2 + 0 + 9 = 11
  RotZXZ = RotZ + 3 * RotX + 9 * RotZ, // 2 + 0 + 18 = 20
  RotZYX = RotZ + 3 * RotY + 9 * RotX, // 2 + 3 + 0 = 5
  RotZYZ = RotZ + 3 * RotY + 9 * RotZ, // 2 + 3 + 18 = 23
  RotHPR = RotZXY, // used in OpenGL Performer
  RotABC = RotZYX // used in German engineering
};

/* decomposes the combined EULER angle type into the corresponding
 * individual EULER angle axis types.
 */
inline void decompose(
  EulerAngle type, RotAxis &axis1, RotAxis &axis2, RotAxis &axis3)
{
  unsigned type_ = (unsigned)type;
  axis1 = (RotAxis)(type_ % 3); type_ /= 3;
  axis2 = (RotAxis)(type_ % 3); type_ /= 3;
  axis3 = (RotAxis)type_;
}
template <typename VALUE>
Mat4x4T<VALUE> makeEuler(
  EulerAngle mode, VALUE rot1, VALUE rot2, VALUE rot3)
{
  RotAxis axis1, axis2, axis3;
  decompose(mode, axis1, axis2, axis3);
  const static VALUE axes[3][3] = {
    { (VALUE)1, (VALUE)0, (VALUE)0 },
    { (VALUE)0, (VALUE)1, (VALUE)0 },
    { (VALUE)0, (VALUE)0, (VALUE)1 }
  };
  return
      Mat4x4T<VALUE>(InitRot,
        Vec3T<VALUE>(axes[axis1][0], axes[axis1][1], axes[axis1][2]),
        rot1)
    * Mat4x4T<VALUE>(InitRot,
        Vec3T<VALUE>(axes[axis2][0], axes[axis2][1], axes[axis2][2]),
        rot2)
    * Mat4x4T<VALUE>(InitRot,
        Vec3T<VALUE>(axes[axis3][0], axes[axis3][1], axes[axis3][2]),
        rot3);
}