C++ DirectX 2D绕点旋转异常:绘制图形形状怪异问题求助
解决DirectX中点绕中心旋转后图形形状异常的问题
看起来你在DirectX里实现点绕窗口中心旋转并连线时,遇到了图形形状异常的问题。先帮你梳理下可能的问题点,再给出修正后的实现思路和代码:
可能的问题根源
从你给出的代码片段来看,大概率是以下几个细节没处理好:
- 旋转坐标变换逻辑错误:绕中心旋转时,没先把点平移到旋转中心的局部坐标系(原点),旋转后再平移回去,导致旋转中心偏移。
- 角度单位不匹配:DirectX相关的数学函数大多用弧度计算,如果你的循环变量是角度值直接代入,会导致旋转角度偏差,图形变形。
- 静态变量初始化不当:
vecOldLocation作为静态变量只会初始化一次,若第一次循环的点未正确旋转,第一条连线就会出错。
正确的实现步骤
绕任意点(cx, cy)旋转θ的标准坐标变换步骤是:
- 将目标点平移到以旋转中心为原点的局部坐标系:
x' = x - cx,y' = y - cy - 应用旋转公式(注意DirectX窗口坐标系Y轴向下,和数学坐标系相反,需要适配):
- 数学右手系旋转:
x'' = x'*cosθ - y'*sinθ,y'' = x'*sinθ + y'*cosθ - 适配DirectX左手系窗口:
x'' = x'*cosθ + y'*sinθ,y'' = -x'*sinθ + y'*cosθ
- 数学右手系旋转:
- 将旋转后的点平移回原坐标系:
x_final = x'' + cx,y_final = y'' + cy
修正后的代码示例
#include <d3dx9.h> // 假设你的vec2_t结构体定义如下 struct vec2_t { float x, y; vec2_t(float x_ = 0.f, float y_ = 0.f) : x(x_), y(y_) {} }; // 绘制线段的辅助函数(根据你的DirectX环境调整) void DrawLine(LPDIRECT3DDEVICE9 pDevice, float x1, float y1, float x2, float y2, D3DCOLOR color) { // 这里实现DirectX线段绘制逻辑,比如用顶点缓冲区或者D3DXLine ID3DXLine* pLine = nullptr; D3DXCreateLine(pDevice, &pLine); D3DXVECTOR2 points[] = { {x1, y1}, {x2, y2} }; pLine->Begin(); pLine->Draw(points, 2, color); pLine->End(); pLine->Release(); } void DrawRotatedCircleShape(LPDIRECT3DDEVICE9 pDevice) { // 获取窗口中心 vec2_t vecCenter(gui.iWindowSize[0] / 2.f, gui.iWindowSize[1] / 2.f); const float radius = 100.f; // 旋转半径 const float stepAngle = 2.f; // 每次旋转2度 // 初始化第一个点(中心正上方) vec2_t vecOldPoint(vecCenter.x, vecCenter.y - radius); // 遍历360度,注意转成弧度 for (float angle = 0.f; angle < 360.f; angle += stepAngle) { float theta = D3DXToRadian(angle); // 角度转弧度 // 1. 计算相对于中心的局部坐标 vec2_t localPoint(0.f, -radius); // 2. 应用旋转(适配DirectX窗口Y轴向下) vec2_t rotatedLocal( localPoint.x * cos(theta) + localPoint.y * sin(theta), -localPoint.x * sin(theta) + localPoint.y * cos(theta) ); // 3. 平移回窗口坐标系 vec2_t vecCurrentPoint( rotatedLocal.x + vecCenter.x, rotatedLocal.y + vecCenter.y ); // 绘制当前点和上一个点的连线 DrawLine(pDevice, vecOldPoint.x, vecOldPoint.y, vecCurrentPoint.x, vecCurrentPoint.y, D3DCOLOR_XRGB(255, 0, 0)); // 更新上一个点为当前点 vecOldPoint = vecCurrentPoint; } // 最后闭合图形,连接最后一个点和第一个点 vec2_t vecFirstPoint(vecCenter.x, vecCenter.y - radius); DrawLine(pDevice, vecOldPoint.x, vecOldPoint.y, vecFirstPoint.x, vecFirstPoint.y, D3DCOLOR_XRGB(255, 0, 0)); }
额外排查点
- 如果图形旋转方向和预期相反,可以调整旋转公式中的正弦符号;
- 若存在图形拉伸,检查窗口宽高比是否在绘制时做了适配,比如用正交投影矩阵确保坐标比例正确;
- 浮点数精度导致的最后一个点和第一个点间隙,可以把循环条件改为
angle <= 360.f,或者手动闭合连线。
内容的提问来源于stack exchange,提问作者user6821023
相关产品推荐
相关产品推荐

