我有float[] newCoords
变量大小为9 。前3个条目表示一个顶点,后3个表示第二个顶点,后3个表示最后一个顶点。
我有一些代码可以在我提供坐标的时候在空间的任何地方旋转三角形。它看起来像这样:
float s = (float) Math.sin(0.5);
float c = (float) Math.cos(0.5);
float[] centroid = getCentroid(newCoords);
newCoords[0] -= centroid[0];
newCoords[1] -= centroid[1];
newCoords[3] -= centroid[0];
newCoords[4] -= centroid[1];
newCoords[6] -= centroid[0];
newCoords[7] -= centroid[1];
newCoords[0] = (newCoords[0] * c) - (newCoords[1] * s);
newCoords[1] = (newCoords[0] * s) + (newCoords[1] * c);
newCoords[3] = (newCoords[3] * c) - (newCoords[4] * s);
newCoords[4] = (newCoords[3] * s) + (newCoords[4] * c);
newCoords[6] = (newCoords[6] * c) - (newCoords[7] * s);
newCoords[7] = (newCoords[6] * s) + (newCoords[7] * c);
newCoords[0] += centroid[0];
newCoords[1] += centroid[1];
newCoords[3] += centroid[0];
newCoords[4] += centroid[1];
newCoords[6] += centroid[0];
newCoords[7] += centroid[1];
问题是,它没有正确旋转,三角形在旋转,越来越小,直到它们因某种原因消失,有人能看出为什么会发生这种情况吗?
编辑:哎呀,差点忘了,这是我的getCentroid()
方法。
private float[] getCentroid(float[] p1) {
float[] newCoords = new float[] {(p1[0] + p1[3] + p1[6]) / 3.0f,
(p1[1] + p1[4] + p1[7]) / 3.0f, 0};
return newCoords;
}
答案 0 :(得分:4)
我发现您的代码存在两个问题。两者都有一点变化。
您尝试应用旋转操作,将X和Y坐标作为输入并将新的X和Y作为输出。对于您旋转的每个顶点,您有两行代码:第一行计算X,第二行计算Y坐标。但是在计算Y坐标时,使用已旋转的 X坐标!那是错的。
还有一个数字问题。您可以反复重复使用旧值,从而产生旋转计算链值,因此数值误差总和。永远不要依赖这样的计算来按预期工作。相反,您应该使用原始值并增加每个帧中的角度。这可确保每个值仅参与单次轮换计算。
要解决这两个问题,请将原始坐标保留在代码中的某个位置,我将它们称为coords
,然后重写代码,以便将该数组作为输入(保持newCoords
作为输出)。增加每帧中的旋转角度以实现旋转动画。
这解决了这两个问题,因为你摆脱了这个链,你的旋转函数中也有不同的输入和输出数组。
的伪代码:
// initial:
angle = 0.0;
coords = (initial coordinates)
// per frame:
angle += 0.5;
newCoords = rotate(coords, angle);
draw(newCoords);
另外,请注意0.5
是一个大角度,如果你想逐帧旋转那个角度。数学函数需要以弧度(而不是度)为单位的角度,因此您可能希望使用较低的值,具体取决于您想要显示的内容。
你可能想知道为什么我在每一帧中重复使用旧角度,因为根据上面提到的问题2.它应该引入数值问题,因为它也是一个计算链。这不是旋转角度的问题,因为简单求和并未显示您应用旋转时遇到的这种不良数值误差。然而它有一些问题,但是当角度达到数十亿时,它们只会在非常长的运行时间出现。总的来说这样的求和并不是那么糟糕的原因是因为你在每个帧中改变了相同方向的变量,并且用户没有注意到略微偏离的旋转角度。