如何在PAWN/C中实现3D子点绕父3D点旋转并保留原有旋转信息
3D子点绕父点旋转PAWN实现方案
核心实现逻辑
整个计算分步骤走,不需要复杂矩阵知识,直接套公式即可:
- 计算子点相对于父点的初始相对坐标
- 对相对坐标依次应用父点的三个方向旋转(按偏航→俯仰→横滚的顺序,和你给出的角定义匹配)
- 旋转后的相对坐标叠加父点的世界坐标,得到子点的新世界坐标
- 子点最终的旋转属性直接叠加父点的旋转属性即可,完整保留自身原有旋转
可直接复用的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
相关产品推荐
相关产品推荐

