BlackBerry - изображение 3D-трансформации - PullRequest
3 голосов
/ 31 июля 2009

Я знаю, как повернуть изображение на любой угол с помощью drawTexturePath :

int displayWidth = Display.getWidth();
int displayHeight = Display.getHeight();
int[] x = new int[] { 0, displayWidth, displayWidth, 0 };
int[] x = new int[] { 0, 0, displayHeight, displayHeight };
int angle = Fixed32.toFP( 45 );
int dux = Fixed32.cosd(angle );
int dvx = -Fixed32.sind( angle );
int duy = Fixed32.sind( angle );         
int dvy = Fixed32.cosd( angle );       
graphics.drawTexturedPath( x, y, null, null, 0, 0, dvx, dux, dvy, duy, image);

но мне нужна 3D-проекция простого изображения с 3D-преобразованием (что-то вроде this )

Можете ли вы дать мне совет, как это сделать с drawTexturedPath (я почти уверен, что это возможно)?
Есть ли альтернативы?

Ответы [ 4 ]

6 голосов
/ 07 августа 2009

Метод, используемый этой функцией (2 вектора обхода), аналогичен трюкам кодирования oldskool, используемым для знаменитого эффекта «rotozoomer». Пример видео ротозоомера

Этот метод является очень быстрым способом поворота, масштабирования и перекоса изображения. Вращение осуществляется простым вращением векторов ходьбы. Увеличение осуществляется простым масштабированием векторов ходьбы. Перекос выполняется путем вращения векторов ходьбы относительно друг друга (например, они больше не образуют угол 90 градусов).

Nintendo создала аппаратное обеспечение в своих SNES, чтобы использовать тот же эффект на любом из спрайтов и / или фонов. Это дало возможность получить очень интересные эффекты.

Один большой недостаток этой техники заключается в том, что нельзя перспективно деформировать текстуру. Для этого на каждой новой горизонтальной линии векторы ходьбы должны быть слегка изменены. (трудно объяснить без рисунка).

На снимках они преодолевали это, изменяя каждую линию сканирования векторами ходьбы (в те дни можно было установить прерывание, когда монитор рисовал какую-либо линию сканирования). Этот режим позже был назван MODE 7 (поскольку он вел себя как новый виртуальный вид графического режима). Самыми известными играми, использующими этот режим, были Mario Kart и F-zero

Таким образом, чтобы заставить это работать на ежевике, вам нужно будет нарисовать ваше изображение "displayHeight" раз (например, каждый раз, когда одна линия сканирования изображения). Это единственный способ добиться желаемого эффекта. (Это, несомненно, будет стоить вам снижения производительности, поскольку теперь вы вызываете функцию drawTexturedPath много раз с новыми значениями, а не один раз).

Полагаю, что, немного погуглив, вы сможете найти некоторые формулы (или даже реализацию), как вычислять различные векторы ходьбы. С небольшим количеством бумаги (учитывая, что вы не так уж плохо разбираетесь в математике), вы можете сделать это и сами. Я тоже делал это, когда делал игры для Gameboy Advance, так что я знаю, что это можно сделать.

Обязательно предварительно все просчитайте! Скорость - это все (особенно на медленных машинах, таких как телефоны)

РЕДАКТИРОВАТЬ: сделал поиск в Google. Вот подробное объяснение, как создать эффект mode7. Это поможет вам добиться того же с помощью функции Blackberry. Реализация режима 7

2 голосов
/ 16 августа 2009

Спасибо за ответы и советы, +1 всем вам.
В MODE 7 я выбрал реализацию трехмерного преобразования, но, к сожалению, я не смог сделать drawTexturedPath, чтобы изменить размеры моих линий сканирования ... поэтому я перешел к простому drawImage.

Предполагая, что у вас есть Bitmap inBmp (входная текстура), создайте новый Bitmap outBmp (выходная текстура).

Bitmap mInBmp = Bitmap.getBitmapResource("map.png");
int inHeight = mInBmp.getHeight();
int inWidth = mInBmp.getWidth();

int outHeight = 0;
int outWidth = 0;
int outDrawX = 0;
int outDrawY = 0;
Bitmap mOutBmp = null;

public Scr() {
    super();
    mOutBmp = getMode7YTransform();
    outWidth = mOutBmp.getWidth();
    outHeight = mOutBmp.getHeight();
    outDrawX = (Display.getWidth() - outWidth) / 2;
    outDrawY = Display.getHeight() - outHeight;
}

Где-то в коде создайте Graphics outBmpGraphics для outBmp.
Затем выполните следующее в итерации от начала y до (высота текстуры) * y коэффициент преобразования:
1.создать растровое изображение lineBmp = новое растровое изображение (ширина, 1) для одной строки
2. создать графическую линиюBmpGraphics из lineBmp
3. нарисовать линию от текстуры до линииBmpGraphics
4. закодировать строкуBmp в EncodedImage img
5. Масштаб IMG в соответствии с режимом 7
6.красить img в outBmpGraphics
Примечание: Порт BB PNGEncoder Ричарда Пакетта, используемый в моем коде

private Bitmap getMode7YTransform() {
    Bitmap outBmp = new Bitmap(inWidth, inHeight / 2);
    Graphics outBmpGraphics = new Graphics(outBmp);
    for (int i = 0; i < inHeight / 2; i++) {
        Bitmap lineBmp = new Bitmap(inWidth, 1);
        Graphics lineBmpGraphics = new Graphics(lineBmp);
        lineBmpGraphics.drawBitmap(0, 0, inWidth, 1, mInBmp, 0, 2 * i);
        PNGEncoder encoder = new PNGEncoder(lineBmp, true);
        byte[] data = null;
        try {
            data = encoder.encode(true);
        } catch (IOException e) {
            e.printStackTrace();
        }
        EncodedImage img = PNGEncodedImage.createEncodedImage(data, 
                0, -1);
        float xScaleFactor = ((float) (inHeight / 2 + i))
                / (float) inHeight;
        img = scaleImage(img, xScaleFactor, 1);
        int startX = (inWidth - img.getScaledWidth()) / 2;
        int imgHeight = img.getScaledHeight();
        int imgWidth = img.getScaledWidth();
        outBmpGraphics.drawImage(startX, i, imgWidth, imgHeight, img, 
                0, 0, 0);
    }
    return outBmp;
}

Тогда просто нарисуйте его краской ()

protected void paint(Graphics graphics) {
    graphics.drawBitmap(outDrawX, outDrawY, outWidth, outHeight, mOutBmp,
            0, 0);
}

Для масштабирования я сделал нечто похожее на метод, описанный в Изменение размера растрового изображения с использованием .scaleImage32 вместо .setScale

private EncodedImage scaleImage(EncodedImage image, float ratioX,
        float ratioY) {

    int currentWidthFixed32 = Fixed32.toFP(image.getWidth());
    int currentHeightFixed32 = Fixed32.toFP(image.getHeight());

    double w = (double) image.getWidth() * ratioX;
    double h = (double) image.getHeight() * ratioY;
    int width = (int) w;
    int height = (int) h;

    int requiredWidthFixed32 = Fixed32.toFP(width);
    int requiredHeightFixed32 = Fixed32.toFP(height);

    int scaleXFixed32 = Fixed32.div(currentWidthFixed32,
            requiredWidthFixed32);
    int scaleYFixed32 = Fixed32.div(currentHeightFixed32,
            requiredHeightFixed32);

    EncodedImage result = image.scaleImage32(scaleXFixed32, scaleYFixed32);
    return result;
}

Смотри также
J2ME Mode 7 Floor Renderer - нечто гораздо более подробное и захватывающее, если вы пишете 3D-игру!

2 голосов
/ 04 августа 2009

С помощью следующего кода вы можете исказить изображение и получить эффект в перспективе:

        int displayWidth = Display.getWidth();
        int displayHeight = Display.getHeight();
        int[] x = new int[] { 0, displayWidth, displayWidth, 0 };
        int[] y = new int[] { 0, 0, displayHeight, displayHeight };                

        int dux = Fixed32.toFP(-1);
        int dvx = Fixed32.toFP(1);
        int duy = Fixed32.toFP(1);
        int dvy = Fixed32.toFP(0);
        graphics.drawTexturedPath( x, y, null, null, 0, 0, dvx, dux, dvy, duy, image);

Это изменит ваше изображение под углом 45º, если вам нужен определенный угол, вам просто нужно использовать некоторую тригонометрию для определения длин ваших векторов.

1 голос
/ 08 августа 2009

Вы хотите сделать наложение текстуры, и эта функция не обрежет его. Может быть, вы можете обойти это, но лучше использовать алгоритм наложения текстур.

Это включает в себя для каждой строки пикселей определение краев фигуры и того, где на фигуре отображаются эти пиксели экрана (пиксели текстуры). Это не так сложно на самом деле, но может занять немного работы. И вы будете рисовать рис только один раз.

GameDev имеет кучу статей с исходным кодом здесь:

http://www.gamedev.net/reference/list.asp?categoryid=40#212

В Википедии также есть хорошая статья:

http://en.wikipedia.org/wiki/Texture_mapping

Еще один сайт с 3d учебниками:

http://tfpsly.free.fr/Docs/TomHammersley/index.html

На вашем месте я бы искал простую демонстрационную программу, которая сделала что-то похожее на то, что вы хотите, и использовал их источники в качестве основы для разработки своей собственной - или даже нашел бы переносимую библиотеку исходников, я уверен, что должна некоторые из них.

...