首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >BlackBerry -图像3D变换

BlackBerry -图像3D变换
EN

Stack Overflow用户
提问于 2009-07-31 13:49:03
回答 4查看 4.8K关注 0票数 3

我知道如何用drawTexturePath在任何角度上旋转图像

代码语言:javascript
复制
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 projection (类似于this)

你能建议我如何用drawTexturedPath做到这一点吗(我几乎肯定这是可能的)?

还有别的选择吗?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2009-08-07 13:42:26

此函数使用的方法(2个漫游向量)与用于著名的“旋转变焦”效果的旧代码技巧相同。rotozoomer example video

此方法是旋转、缩放和倾斜图像的一种非常快速的方式。旋转只需旋转漫游向量即可。缩放只需缩放漫游向量即可。倾斜是通过相对于彼此旋转漫游向量来完成的(例如,它们不再形成90度角)。

任天堂已经在他们的SNES中制作了硬件,以便在任何精灵和/或背景上使用相同的效果。这为一些非常酷的效果让路。

这种技术的一大缺点是不能透视性地扭曲纹理。要做到这一点,每一条新的水平线,漫游向量都应该稍微改变一下。(没有图画很难解释)。

在snes上,他们通过改变每条扫描线来克服这一点(在那个时代,当显示器绘制任何扫描线时,人们可以设置一个中断)。这种模式后来被称为MODE 7 (因为它的行为方式类似于一种新的虚拟图形模式)。使用这种模式的最著名的游戏是马里奥卡丁车和F-zero。

因此,为了在黑莓上工作,你必须绘制你的图像"displayHeight“次(例如,每次图像的一条扫描线)。这是达到预期效果的唯一方法。(这无疑会影响您的性能,因为您现在使用新值多次调用drawTexturedPath函数,而不是只调用一次)。

我猜想,通过一点谷歌搜索,你可以找到一些公式(甚至是一个实现),如何计算不同的走向量。用一点纸(考虑到你的数学不是很差),你自己也可以推断出来。当我为Gameboy Advance制作游戏时,我自己也做过,所以我知道这是可以做到的。

一定要预先计算所有东西!速度就是一切(特别是在像手机这样速度很慢的机器上)

编辑:为你做了一些谷歌搜索。下面是如何创建mode7效果的详细说明。这将帮助您实现与黑莓功能相同的功能。Mode 7 implementation

票数 6
EN

Stack Overflow用户

发布于 2009-08-04 18:53:31

使用以下代码,您可以倾斜您的图像,并获得类似透视的效果:

代码语言:javascript
复制
        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度角,如果你想要一个特定的角度,你只需要使用一些三角来确定你的向量的长度。

票数 2
EN

Stack Overflow用户

发布于 2009-08-16 11:08:28

感谢你的回答和指导,+1对你们所有人。

模式7是我选择实现3D转换的方式,但不幸的是我不能让drawTexturedPath来调整扫描线的大小……所以我最终选择了简单的drawImage。

假设您有一个位图inBmp (输入纹理),创建新的位图outBmp (输出纹理)。

代码语言:javascript
复制
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;
}

在代码中的某处为outBmp创建一个图形outBmpGraphics。

然后在从开始y到(纹理高度)*y转换因子的迭代中执行以下操作:

1.为一行创建一个位图lineBmp = new位图(宽度,1

2.从lineBmp创建图形lineBmpGraphics

3.绘制纹理到lineBmpGraphics的线条

4.将lineBmp编码为EncodedImage img

5.根据模式7缩放img

6.将img绘制为outBmpGraphics

备注: Richard Puckett's PNGEncoder BB port used in my code

代码语言:javascript
复制
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()中绘制它

代码语言:javascript
复制
protected void paint(Graphics graphics) {
    graphics.drawBitmap(outDrawX, outDrawY, outWidth, outHeight, mOutBmp,
            0, 0);
}

为了进行扩展,我做了一些类似于Resizing a Bitmap using .scaleImage32 instead of .setScale中描述的方法

代码语言:javascript
复制
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
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1212651

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档