Как Canvas определяет границы клипа?
я делал некоторые работы с Android в Canvas
, специально пытаясь определить, как его getClipBounds
результаты определяются. Я понимаю!--5--> внутренне поддерживает преобразование Matrix
, которая обновляется, как я называю translate
, scale
, etc. но попытка воспроизвести это Matrix
результаты озадачили меня.
@Override
public void onDraw(Canvas canvas) {
Rect clipBounds;
RectF viewport;
canvas.save();
canvas.concat(translationMatrix);
//viewportMatrix.preConcat(canvas.getMatrix());
viewportMatrix.set(canvas.getMatrix());
clipBounds = canvas.getClipBounds();
viewport = GetViewport();
Log.d("clipBounds", clipBounds.toString() + " (" + clipBounds.width() + ", " + clipBounds.height() + ")");
Log.d("viewport", viewport.toString() + " (" + viewport.width() + ", " + viewport.height() + ")");
//drawing is done here
canvas.restore();
}
//viewport code modeled after http://stackoverflow.com/a/17142856/2245528
private RectF GetViewport() {
RectF viewport = new RectF();
viewportMatrix.mapRect(viewport, originalViewport);
return viewport;
}
private void Translate(float x, float y) {
translationMatrix.postTranslate(x, y);
invalidate();
}
private void Scale(float scaleFactor, PointF focusPoint) {
if (focusPoint == null) {
translationMatrix.postScale(scaleFactor, scaleFactor);
}
//keep the focus point in focus if possible
else {
translationMatrix.postScale(scaleFactor, scaleFactor, focusPoint.x, focusPoint.y);
}
invalidate();
}
private final Matrix translationMatrix = new Matrix();
private final RectF originalViewport = new RectF();
private final Matrix viewportMatrix = new Matrix();
originalViewport
установлено значение 0, 0, canvas.getWidth(), canvas.getHeight()
. Translate
и Scale
вызываются из обработчиков событий жестов, которые работают правильно.
часть это меня смущает viewportMatrix
. Не имеет значения, знаю я или нет.--37-->
viewportMatrix.set(canvas.getMatrix());
или
viewportMatrix.preConcat(canvas.getMatrix());
или даже одноразовый звонок в
viewportMatrix.set(canvas.getMatrix());
в начале следуют бок о бок Translate
/Scale
вызовы двух матриц. Я даже пытался полностью игнорировать Canvas
в своем Matrix
и рерайтинг GetViewport
as
//viewport code modeled after http://stackoverflow.com/a/17142856/2245528
private RectF GetViewport() {
RectF viewport = new RectF();
translationMatrix.mapRect(viewport, originalViewport);
return viewport;
}
я никогда не могу сравниться getClipBounds()
, и расхождения достаточно серьезно:
С viewportMatrix.set(canvas.getMatrix)
:
clipBounds: Rect(-97, -97 - 602, 452) (699, 549)
видовое окно: RectF(97.04178, 97.06036, 797.04175, 647.06036) (700.0, 550.0)
С viewportMatrix.preConcat(canvas.getMatrix)
:
clipBounds: Rect(-97, -96 - 602, 453) (699, 549)
видовое окно: RectF(2708.9663, 2722.2754, 3408.9663, 3272.2754) (700.0, 550.0)
С translationMatrix.mapRect
:
clipBounds: Rect(-96, -96 - 603, 453) (699, 549)
видовое окно: RectF(96.73213, 96.85794, 796.7321, 646.8579) (700.0, 550.0)
С одним выстрелом вызова viewportMatrix.preConcat(canvas.getMatrix())
затем бок-о-бок Translate
/Scale
вызовы:
clipBounds: Rect(-96, -97 - 603, 452) (699, 549)
видовое окно: RectF(96.57738, 97.78168, 796.5774, 647.7817) (700.0, 550.0)
С a один выстрел вызов viewportMatrix.set(canvas.getMatrix())
затем бок-о-бок Translate
/Scale
вызовы:
clipBounds: Rect(-96, -96 - 603, 453) (699, 549)
видовое окно: RectF(96.40051, 96.88153, 796.4005, 646.88153) (700.0, 550.0)
я даже не могу проверить the Canvas
источник, как все Matrix
код исчезает в частные собственные вызовы, код которых не отображается.
почему GetViewport
вызовы так грубо, и что происходит за кулисами с getClipBounds
?
1 ответов
Я прочитал до конца этот ответ на GameDev SE, который использует инверсию матрицы для обмена между экраном и мировыми системами координат:
чтобы перейти от экрана к мировому пространству просто использовать Vector2.Преобразиться. Это обычно используется для получения местоположения мыши в мире для выбора объекта.
Vector2.Transform(mouseLocation, Matrix.Invert(Camera.TransformMatrix));
чтобы перейти от мира к экрану, просто сделайте наоборот.
Vector2.Transform(mouseLocation, Camera.TransformMatrix);
вдохновленный этим подходом, я попытался перевернуть матрица преобразования выглядит так:
private RectF GetViewport() {
RectF viewport = new RectF();
Matrix viewportMatrix = new Matrix();
translationMatrix.invert(viewportMatrix);
viewportMatrix.mapRect(viewport, originalViewport);
return viewport;
}
это окно просмотра правильно соответствует результатам, возвращенным getClipBounds
.
эта матрица учебник объясняет, что я заметил по результатам transform
звонки, но не применялись к моей матрице:
в компьютерной программе камера вообще не движется, и на самом деле мир просто движется в противоположном направление и ориентация о том, как вы хотели бы камеру двигаться в реальности.
чтобы понять это правильно, мы должны думать в терминах двух разных вещей:
- Матрица Преобразования Камеры: преобразование, которое помещает камеру в правильное положение и ориентацию в мировом пространстве (это преобразование, которое вы бы применили к 3D-модели камеры, если бы вы хотели представить ее в сцене).
- Матрица Просмотра: это матрица преобразования вершин мира-пространстве-пространстве. эта матрица является обратной матрице преобразования камеры, описанной выше.