Перекос растрового изображения только в вертикальном направлении - PullRequest
8 голосов
/ 18 марта 2011

Я хочу исказить (поправьте меня, если это не правильное слово) растровое изображение, чтобы оно имело глубину.Хороший способ визуализировать то, о чем я прошу, - это то, как титры «Звездных войн» направлены на то, чтобы показать глубину.

Я пробовал следующее:

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 ]

12 голосов
/ 19 мая 2011

Я потратил много времени, работая над этим сегодня (столкнулся с той же проблемой), и придумал код ниже.

Ключевой момент, на который следует обратить внимание, вам нужно установить 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();    
}
6 голосов
/ 18 марта 2011

Вы не можете достичь желаемого эффекта с помощью skew (). Однако вы можете использовать объект «Камера» и трехмерные повороты для достижения этого эффекта. Камера сгенерирует для вас Матрицу, которую вы затем сможете применить на холсте. Обратите внимание, что результат не будет правильным, но достаточно хорошим для вашей цели. Вот как, например, 3D вращение выполняется в Launcher Honeycomb (и многих других приложениях)

1 голос
/ 18 марта 2011

Я не думаю, что "эффект Звездных войн" - это аффинное преобразование , которое, я думаю, является единственной операцией, поддерживаемой Matrix.

...