Перекос растрового изображения только в вертикальном направлении
Я хочу исказить (поправьте меня, если это не правильное слово) растровое изображение, чтобы оно имело глубину. Хороший способ визуализировать то, о чем я прошу, - это то, как титры "Звездных войн" направлены на то, чтобы показать глубину.
Я пробовал следующее:
canvas.getMatrix().postSkew(kx,ky,px,py);
а также
canvas.skew(sx,sy);
Но у меня не было большого успеха. Вышеуказанные методы, кажется, всегда преобразуют растровое изображение в параллелограмм. Есть ли способ превратить растровое изображение в трапецию вместо этого?
Вот фрагмент кода, который я взял из примеров, на которые указывал мне Ромен.
canvas.rotate(-mOrientation[0] + mHeading, mCenterX, mCenterY);
camera.save();
if (mReverse) {
camera.translate(0.0f, 0.0f, mDepthZ * interpolatedTime);
} else {
camera.translate(0.0f, 0.0f, mDepthZ * (1.0f - interpolatedTime));
}
camera.rotateX(mOrientation[1]);
camera.applyToCanvas(canvas);
canvas.drawPath(mPath, mPaint);
canvas.drawCircle(mCenterX, mCenterY, mRadius - 37, mPaint);
camera.restore();
3 ответа
Вы не можете достичь желаемого эффекта с помощью skew(). Однако вы можете использовать объект "Камера" и трехмерные повороты для достижения этого эффекта. Камера сгенерирует для вас Матрицу, которую вы затем сможете применить на холсте. Обратите внимание, что результат не будет правильным, но достаточно хорошим для вашей цели. Вот как 3D вращение выполняется в Launcher Honeycomb, например (и во многих других приложениях).
Я потратил много времени, работая над этим сегодня (столкнулся с той же проблемой) и придумал код ниже.
Важно отметить, что вы должны установить preTranslate() и postTranslate() в центр (или в другое место) вашей области Canvas. Кажется, это означает, что он использует центр изображения, чтобы применить преобразование, вместо верхнего левого угла (x=0,y=0) по умолчанию. Вот почему вы получите параллелограмм вместо того, что вы ожидаете, трапецию (спасибо, что научили меня их именам).
Другая важная вещь, которую я поднял, - это функции сохранения / восстановления на холсте / камере. По сути, если вы вызываете функции Поворот последовательно три раза, не восстанавливая состояние каждый раз, вы продолжаете вращать свой объект вокруг и вокруг каждый раз, когда рисуете. Это может быть то, что вы хотите, но я, конечно, не сделал в моем случае. То же самое относится и к холсту, поскольку вы в основном применяете матрицу из объекта "Камера" к холсту, и ее необходимо сбросить, иначе происходит то же самое.
Надеюсь, это кому-то поможет, это плохо документировано для начинающих. Совет всем, кто читает это, проверьте папку APIDemos в SDK Samples. Существует файл Rotate3dAnimation.java, который также демонстрирует это.
//Snippet from a function used to handle a draw
mCanvas.save(); //save a 'clean' matrix that doesn't have any camera rotation in it's matrix
ApplyMatrix(); //apply rotated matrix to canvas
Draw(); //Does drawing
mCanvas.restore(); //restore clean matrix
//
public void ApplyMatrix() {
mCamera.save();
mCamera.rotateX(-66);
mCamera.rotateY(0);
mCamera.rotateZ(0);
mCamera.getMatrix(mMatrix);
int CenterX = mWidth / 2;
int CenterY = mHeight / 2;
mMatrix.preTranslate(-CenterX, -CenterY); //This is the key to getting the correct viewing perspective
mMatrix.postTranslate(CenterX, CenterY);
mCanvas.concat(mMatrix);
mCamera.restore();
}
Я не думаю, что "эффект Звездных войн" - это аффинное преобразование, которое, я думаю, является единственной операцией, поддерживаемой Matrix
,