Graphics 黑莓-图像三维变换
我知道如何使用以下工具以任意角度旋转图像: 但我需要的是一个带有3d转换的简单图像(类似于) 您能告诉我如何使用drawTexturedPath执行此操作吗(我几乎确信这是可能的)?Graphics 黑莓-图像三维变换,graphics,blackberry,java-me,3d,Graphics,Blackberry,Java Me,3d,我知道如何使用以下工具以任意角度旋转图像: 但我需要的是一个带有3d转换的简单图像(类似于) 您能告诉我如何使用drawTexturedPath执行此操作吗(我几乎确信这是可能的)? 有其他选择吗?使用以下代码,您可以扭曲图像并获得类似透视图的效果: int displayWidth = Display.getWidth(); int displayHeight = Display.getHeight(); int[] x = new int[]
有其他选择吗?使用以下代码,您可以扭曲图像并获得类似透视图的效果:
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个行走向量)与用于著名的“rotozoomer”效果的oldskool编码技巧相同 此方法是旋转、缩放和扭曲图像的一种非常快速的方法。旋转只需旋转行走向量即可完成。缩放只需缩放行走向量即可完成。倾斜是通过相对于彼此旋转行走矢量来完成的(例如,它们不再形成90度角) 任天堂已经在他们的SNE中制造了硬件,以便在任何精灵和/或背景上使用相同的效果。这为一些非常酷的效果让路 这种技术的一个大缺点是不能透视扭曲纹理。要做到这一点,每一条新的水平线,行走向量都应该稍微改变。(没有图纸很难解释) 在SNE上,他们通过改变每一条扫描线(在那些日子里,当监视器绘制任何扫描线时,可以设置一个中断)来克服这一问题。这种模式后来被称为(因为它的行为类似于一种新的虚拟图形模式)。使用这种模式的最著名的游戏是马里奥卡丁车和F-zero 因此,要在blackberry上运行此功能,您必须多次绘制图像“显示高度”(例如,每次图像的一条扫描线)。这是达到预期效果的唯一途径。(这无疑会降低性能,因为您现在使用新值多次调用drawTexturedPath函数,而不是只调用一次) 我想通过谷歌搜索,你可以找到一些公式(甚至是一个实现)如何计算不同的向量。用一点纸(考虑到你的数学不太差),你也可以自己推断出来。当我为Gameboy Advance制作游戏时,我自己也做过,所以我知道这是可以做到的 一定要做好一切准备!速度就是一切(特别是在像手机这样的低速机器上)
编辑:为你做了一些谷歌搜索。下面是如何创建mode7效果的详细说明。这将帮助您通过黑莓功能实现同样的功能 您想要进行纹理贴图,但该函数无法将其剪切。也许你可以绕着它走,但更好的选择是使用纹理映射算法 这涉及到,对于每一行像素,确定形状的边缘以及这些屏幕像素在形状上映射到的位置(纹理像素)。其实这并不难,但可能需要一些工作。你只能画一次照片 GameDev在这里有一系列包含源代码的文章: 维基百科也有一篇很好的文章: 另一个包含3d教程的网站:
在你的位置上,我会寻找一个简单的演示程序,它做了一些接近你想要的事情,并使用它们的源代码作为基础来开发我自己的-或者甚至找到一个便携式源代码库,我相信一定有一些。谢谢你的回答和指导,+1感谢大家。
模式7是我选择实现3D转换的方式,但不幸的是,我无法使用drawTexturedPath来调整扫描线的大小。。。所以,我把问题归结为简单的绘画形象 假设您有一个位图inBmp(输入纹理),创建新的位图outBmp(输出纹理) 在代码中的某个地方,为outBmp创建图形outBmpGraphics。
然后在从开始y到(纹理高度)*y变换因子的迭代中执行以下操作:
1.为一行创建位图线条BMP=新位图(宽度,1)
2.创建图形线条BMP从线条BMP创建图形
3.在纹理与线条之间绘制线条图形
4.encode lineBmp到EncodedImage img
5.根据模式7缩放img
6.从img到outBmpGraphics绘制图像
注意: 为了扩展,我做了一些类似于中描述的方法的事情 另见
-如果你在写一个3D游戏的话,那就更详细、更刺激了 嗨,卢卡斯,谢谢你的回答。您提供的是一个简单的倾斜。坦率地说,我需要能够做任何组合三维变换(旋转,倾斜,调整大小)。仔细看看,它的大小部分调整了,而不仅仅是倾斜。正如我所说的,应该有办法做到这一点,因为:1)-它们提供了dvx,dux,dvy,duy args,它们的行为类似于一些trans-matrix;2) 在net.rim.device.api.ui.Graphics类中有未记录的setMatrix()和setIdentity()方法(不幸的是无法使它们工作)Reinier,感谢您的回答!说真的,我数学不好,这就是为什么我把这个问题交给邦蒂。。。您的回答非常有趣,虽然它可能会解决性能问题,但如果您为模式7提供Blackberry代码,我会接受它。不幸的是,我没有Blackberry。当我在客户端做一些移植工作时(这也涉及到黑莓),我确实可以访问它。不过,我想我下周不会在那里=^|我想我添加的链接解释了它背后涉及的很多数学问题。。。你读过了吗?嗯,有免费的模拟器。你们能至少写一个算法来得到那个些xv-yv-xu-yu值吗?嗨,克里斯托芬,谢谢你们的回答!据我所知,我可以按像素绘制颜色,在位图中保存一次,并在每次刷新时绘制位图。这是缓慢的,比每y画一条线还多,但也可以是一个解决方案。为了证明概念,您可以提供用于透视变换的blackberry代码吗?手动纹理映射(一次1个像素)是j2me的一种慢动作。只有当J2me可以使用API函数来进行数据挖掘时,它才是“快速的”
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);
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;
}
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);
}
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;
}