You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在PAWN/C中实现3D子点绕父3D点旋转并保留原有旋转信息

3D子点绕父点旋转PAWN实现方案

核心实现逻辑

整个计算分步骤走,不需要复杂矩阵知识,直接套公式即可:

  1. 计算子点相对于父点的初始相对坐标
  2. 对相对坐标依次应用父点的三个方向旋转(按偏航→俯仰→横滚的顺序,和你给出的角定义匹配)
  3. 旋转后的相对坐标叠加父点的世界坐标,得到子点的新世界坐标
  4. 子点最终的旋转属性直接叠加父点的旋转属性即可,完整保留自身原有旋转

可直接复用的PAWN代码

你可以直接套用下方代码,已适配你提供的三角函数接口:

// 3D坐标+旋转结构体,如果你已有现成的结构体可以直接替换
struct Vector3DRot {
    Float: x,
    Float: y,
    Float: z,
    Float: rx, // 俯仰Pitch
    Float: ry, // 横滚Roll
    Float: rz  // 偏航Yaw
};

// 计算子点绕父点旋转后的最终坐标与旋转
stock CalculateChildRelativePos(const Vector3DRot: parent, const Vector3DRot: originChild, Vector3DRot: outChild) {
    // 第一步:计算子点相对于父点的初始相对坐标
    new Float: relX = originChild.x - parent.x;
    new Float: relY = originChild.y - parent.y;
    new Float: relZ = originChild.z - parent.z;
    new Float: tempX, tempY, tempZ;

    // 第二步:应用父点偏航角RZ(绕Z轴旋转,控制左右转向)
    new Float: cosRZ = floatcos(parent.rz, degrees);
    new Float: sinRZ = floatsin(parent.rz, degrees);
    tempX = relX * cosRZ - relY * sinRZ;
    tempY = relX * sinRZ + relY * cosRZ;
    relX = tempX;
    relY = tempY;

    // 第三步:应用父点俯仰角RX(绕X轴旋转,控制抬头低头)
    new Float: cosRX = floatcos(parent.rx, degrees);
    new Float: sinRX = floatsin(parent.rx, degrees);
    tempY = relY * cosRX - relZ * sinRX;
    tempZ = relY * sinRX + relZ * cosRX;
    relY = tempY;
    relZ = tempZ;

    // 第四步:应用父点横滚角RY(绕Y轴旋转,控制左右倾斜)
    new Float: cosRY = floatcos(parent.ry, degrees);
    new Float: sinRY = floatsin(parent.ry, degrees);
    tempX = relX * cosRY + relZ * sinRY;
    tempZ = -relX * sinRY + relZ * cosRY;
    relX = tempX;
    relZ = tempZ;

    // 第五步:叠加父点坐标得到子点最终世界坐标
    outChild.x = parent.x + relX;
    outChild.y = parent.y + relY;
    outChild.z = parent.z + relZ;

    // 第六步:叠加旋转属性,保留子点原有旋转
    outChild.rx = parent.rx + originChild.rx;
    outChild.ry = parent.ry + originChild.ry;
    outChild.rz = parent.rz + originChild.rz;

    // 可选:如果你的引擎要求角度范围在0-360度,可以放开下面的归一化代码
    /*
    outChild.rx = (outChild.rx % 360.0 + 360.0) % 360.0;
    outChild.ry = (outChild.ry % 360.0 + 360.0) % 360.0;
    outChild.rz = (outChild.rz % 360.0 + 360.0) % 360.0;
    */
}

调用示例

new Vector3DRot parentPoint = {100.0, 200.0, 50.0, 10.0, 0.0, 30.0}; // 父点坐标与旋转
new Vector3DRot originChildPoint = {102.0, 200.0, 50.0, 0.0, 0.0, 0.0}; // 子点原始坐标(示例为父点右侧2单位)
new Vector3DRot finalChildPoint;

CalculateChildRelativePos(parentPoint, originChildPoint, finalChildPoint);
// 此时finalChildPoint存储的就是父点旋转后子点的正确坐标与旋转

适配说明

如果测试发现旋转方向和预期相反,把对应旋转计算步骤里sin值前面的正负号调换即可;如果你的引擎欧拉角旋转顺序和上述不同,调换第二步到第四步的计算顺序即可,绝大多数游戏引擎都是上述偏航→俯仰→横滚的默认顺序。

内容的提问来源于stack exchange,提问作者Nickk888

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 16:15:01