黑莓 - 图像3D转换(BlackBerry - image 3D transform)

2019-06-27 09:09发布

我知道如何在任何角度旋转图像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变换简单的图像的(像这样 )

能否请你指点我如何与drawTexturedPath做到这一点(我几乎可以肯定这是可能的)?
是否有其它方法吗?

Answer 1:

通过该功能(步行2个载体)所使用的方法是一样的OLDSKOOL编码用于著名的“rotozoomer”效果技巧。 rotozoomer例如视频

这种方法是旋转,缩放和倾斜图像非常快速的方式。 旋转由旋转行走载体简单地完成。 变焦是通过缩放矢量走简单地完成。 歪斜是关于旋转walkvectors彼此(例如,它们不作90度角了)来完成。

任天堂在他们的SNES制造硬件上使用任何精灵和或背景相同的效果。 这对于一些非常酷的效果让路。

该技术的一个大缺点是一个无法透视翘曲质感。 要做到这一点,每一个新的水平线,步行载体应略有改变。 (硬而不的图解释)。

在SNES,他们通过改变每个扫描线克服这个walkvectors(在那些日子里,人们可以设置中断时的班长被绘制任意扫描线)。 这种模式下,后来被称为MODE 7 (因为它表现得像一个新的虚拟种图形模式)。 最有名的游戏采用这种模式是马里奥赛车和F-零

因此,为了得到这个工作的黑莓,你必须画出你的形象“displayHeight”倍(图像例如每次一个扫描线)。 这是为了达到预期效果的唯一途径。 (这无疑会花费你的性能损失,因为你现在是调用drawTexturedPath功能很多的新值倍,而不仅仅是一个时间)。

我想有一点谷歌搜索,你可以找到一些公式(甚至实现)如何calc下的不同walkvectors的。 随着一张纸(给你的不是数学太差),你可能自己演绎它。 我已经做到了我自己太当我正在为音乐游戏机游戏,所以我知道这是可以做到。

一定要precalc一切! 速度就是一切(特别是在慢的机器就像手机)

编辑:做了一些谷歌上搜索你。 下面是详细解释了如何创建mode7效果。 这将帮助你实现与黑莓功能相同。 模式7实施



Answer 2:

用下面的代码,你可以倾斜你的形象,并得到这样的效果的透视:

        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度角图像,如果你想有一个特定的角度,你只需要使用一些三角来确定您的向量的长度。



Answer 3:

感谢您的解答和指导,+1到大家。
MODE 7是我选择来实现3D变换的方式,但遗憾的是我不能让drawTexturedPath来调整我的扫描线......所以我来到了简单的drawImage。

假设你有一个位图inBmp(输入纹理),创建新的位图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;
}

某处在代码中创建一个图形outBmpGraphics为outBmp。
那么就在下面的迭代从开始y以(纹理高度)* Y转换因子:
1.创建位图lineBmp =新位图(宽度,1)用于一行
2.创建从一个lineBmp图形lineBmpGraphics
3.paint i。从纹理lineBmpGraphics线
4.encode lineBmp到EncodedImage IMG
根据MODE 7 5.scale IMG
6.paint IMG到outBmpGraphics
注: 在我的代码使用的理查德·帕克特的包括PNGEncoder BB端口

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;
}

然后,只需把它收回去的paint()

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模式7楼渲染 -这是更详细的&如果你写一个3D游戏精彩!



Answer 4:

你想要做的纹理贴图,并且该功能将不会削减它。 也许你可以杂牌的办法解决它,但更好的选择是使用一个纹理映射算法。

这涉及到,对于每行像素,确定所述形状的那些屏幕像素映射到(纹理像素)的形状,并且其中的边缘。 这不是那么难,但实际上可能需要一些工作。 你会被绘制PIC只有一次。

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

在你的地方,我会寻找那些做了接近你想要的一个简单的演示程序,并使用他们的来源基地,大力发展我自己的 - 甚至是找到一个便携式源库,我敢肯定一定有几个。



文章来源: BlackBerry - image 3D transform