在画布上绘制两个3D字符串?

5

我需要在画布上绘制2个字符串。这两个字符串必须使用相同的坐标进行绘制,并且第二个字符串必须是将第一个字符串绕Y轴旋转45度的结果。最终效果应该如下图所示:

enter image description here

以下是我的代码:

Matrix matrix = new Matrix();
matrix = canvas.getMatrix();
mCamera = new Camera();


canvas.drawText("In the name of God", 30, 100, redPaint);
mCamera.rotateY(45);
mCamera.getMatrix(matrix);

matrix.preTranslate(30, 100);
//      matrix.postTranslate(-30, -100);

canvas.setMatrix(matrix);
canvas.drawText("In the name of God", 0, 0, greenPaint);

但上述代码的结果是:

enter image description here

你可以看到字符串的坐标不同。那我做错了什么呢?我猜测是matrix.preTranslate()使用了错误的参数。

更新:

我把代码改成了:

canvas.drawText("In the name of God", 30, 100, redPaint);
mCamera.rotateY(45);
mCamera.getMatrix(matrix);
matrix.preTranslate(-30, -100);
matrix.postTranslate(30, 100);
canvas.setMatrix(matrix);
canvas.drawText("In the name of God", 0, 0, greenPaint);

或者像这样:

canvas.drawText("In the name of God", 30, 100, redPaint);
mCamera.rotateY(45);
mCamera.getMatrix(matrix);
matrix.preTranslate(-30, -100);
//matrix.postTranslate(30, 100);
canvas.setMatrix(matrix);
canvas.drawText("In the name of God", 0, 0, greenPaint);

或者像这样:
canvas.drawText("In the name of God", 30, 100, redPaint);
mCamera.rotateY(45);
mCamera.getMatrix(matrix);

matrix.preTranslate(-30, -100);
//      matrix.postTranslate(30, 100);
canvas.setMatrix(matrix);
canvas.drawText("In the name of God", 30, 100, greenPaint);

对于上述三个代码,结果如下:

enter image description here

我猜测第二段文字超出了范围或在状态栏后面,因此不可见。

那么,将我的代码更改为:

mCamera.rotateY(45);
mCamera.getMatrix(matrix);
matrix.preTranslate(-30, -100);
matrix.postTranslate(30, 100);
canvas.setMatrix(matrix);
canvas.drawText("In the name of God", 30, 100, greenPaint);

结果:

这里输入图片描述


(注:这是一张图片,无法翻译内容)

这个问题与https://dev59.com/cVjUa4cB1Zd3GeqPWfsn有关。 - eh9
@eh9,我看到了上面的问题(如何在特定点旋转画布...),但我不明白他为什么要使用canvas.translate。正如你之前所说,我认为当我们使用Matrix.preTranslate()时,我们将旋转的支点更改为新原点。那么他为什么要使用canvas.translate呢? - hasanghaforian
3个回答

3

感谢回复。我已解决问题。我必须使用 canvas.concat() 而不是 canvas.setMatrix。这是正确的代码:

Matrix matrix = new Matrix();
mCamera = new Camera();

canvas.drawText("In the name of God", 30, 100, redPaint);
mCamera.rotateY(60);
mCamera.getMatrix(matrix);

matrix.preTranslate(-30, -100);
matrix.postTranslate(30, 100);
canvas.concat(matrix);
canvas.drawText("In the name of God", 30, 100, greenPaint);

恭喜你找到了它。那一定是最糟糕的API命名选择中最差的1%。 - eh9
@eh9 我有一个新问题,你有任何想法吗?我尝试自己解决,但是我无法解决。我在这个问题中写了它:http://stackoverflow.com/questions/13548192/drawing-two-orthogonal-strings-in-3d-space-in-android-canvas - hasanghaforian

2

试着这样做:

Matrix matrix = new Matrix();
matrix = canvas.getMatrix();
mCamera = new Camera();


canvas.drawText("In the name of God", 30, 100, redPaint);
mCamera.translate(30, 100);
mCamera.rotateY(45);
mCamera.getMatrix(matrix);

canvas.setMatrix(matrix);
canvas.drawText("In the name of God", 0, 0, greenPaint);

我从不涉及pre和post翻译,但您可以尝试调试并尝试使用post翻译而不是pre翻译,并提供(30、100),看看是否有效。


我将 mCamera.translate(30, 100); 改为了 mCamera.translate(30, 100,0); - hasanghaforian
我尝试了没有绘制红色文本的代码,结果中也没有绿色文本。我猜测第二个文本被绘制在范围之外或状态栏后面,因此不可见。 - hasanghaforian
你提到了状态栏,也许你没有考虑到状态栏。Canvas不知道任何关于状态栏的信息,所以当你输入原始的X和Y坐标时,它会用带有状态栏的坐标(这是真正的X和Y坐标)。你可以尝试通过偏移你的Y值来解决这个问题,例如进行preTranslate(-30, -(100 + STATUS_BAR_HEIGHT))操作,然后进行postTranslate(30, 100 + STATUS_BAR_HEIGHT)操作。 - Michael Dotson
如果这样没有任何变化,请尝试只执行postTranslate(30, 100 + STATUS_BAR_HEIGHT),看看是否能得到您想要的结果。 - Michael Dotson
我的目的是在相同的坐标系中绘制两个字符串。始终显示红色文本,并且在绘制红色文本时,我们将忽略状态栏及其高度。如果绿色文本在正确的坐标处绘制,则必须可见一些绿色字符,但是没有绿色字符可见。此外,当我们增加红色文本的高度时,绿色文本不会被状态栏遮挡。 - hasanghaforian
显示剩余2条评论

1
矩阵对象描述的旋转始终具有其旋转轴通过原点的属性。旋转轴上的每个点在旋转下都是不变的,这是一种花哨(且紧凑)的说法,即它不会改变。根据您所描述的期望结果,您希望文本的左边缘不移动。这意味着文本的左边缘必须位于该不变轴上。
这就是 pretranslate() 的作用。您需要进行一个将文本位置移到原点的平移。该平移的坐标为相反数:
matrix.preTranslate(-30, -100);

这个翻译是应用于文本而不是旋转轴的。这种混淆似乎是你问题的根源。要将文本放回原来的位置,请使用postTranslate与预先翻译的负值,也就是原始坐标。

为了更好地理解这一点,请阅读相似变换


我将 matrix.preTranslate(30, 100); 更改为 matrix.preTranslate(-30, -100);matrix.postTranslate(30, 100); 并尝试了 canvas.drawText("...", 0, 0, greenPaint);canvas.drawText("...", 30, 100, greenPaint);,但都不正确。 - hasanghaforian
结果是什么样的?请编辑您的问题。我完全有可能误读了Android文档;这些东西在坐标系统方面常常很随意。 - eh9
请再看一下我的问题,我添加了一些代码片段和它们的结果。 - hasanghaforian

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接