2009-07-31 14 views
3

を3D変形私は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変換で(thisのようなもの)、簡単な画像の3d projectionある

缶drawTexturedPathを使ってこれを行う方法をアドバイスしてください(私はほとんどそれが可能であると確信しています)?
選択肢はありますか?あなたのイメージを歪曲し、効果などの視点を得ることができ、次のコードで

答えて

6

この関数で使用される方法(2歩行ベクトル)は、有名な「回転子」効果に使用されるoldskoolコーディングトリックと同じです。 rotozoomer example video

この方法は、画像を回転、ズーム、スキューする非常に高速な方法です。歩行ベクトルを回転させるだけで回転が行われます。ズームは単に歩行ベクトルをスケーリングすることによって行われます。スキューは、ウォークベクトルを互いに対して回転させることによって行われる(例えば、それらはもはや90度の角度をなしない)。

任天堂は、SNESでハードウェアを作って、スプライトや背景に同じ効果を使用していました。これはいくつかの非常にクールな効果のために作られました。

この手法の1つの大きな欠点は、テクスチャを視覚的に歪ませることができないということです。これを行うには、新しい水平線ごとに、歩行ベクトルを少し変更する必要があります。 (図面なしで説明するのは難しい)。

彼らは、すべてのスキャンラインをウォークベクトルに変更することでこれを克服しました(当時は、モニターがスキャンラインを描いていたときに割り込みを設定することができました)。このモードは後でMODE 7と呼ばれました(新しい仮想グラフィックスモードのように動作したため)。このモードを使用した最も有名なゲームはマリオカートとF-zeroです

これをブラックベリーで処理するには、画像を「displayHeight」回(たとえば、画像の1回のスキャンライン毎)に描画する必要があります。これは、望ましい効果を達成する唯一の方法です。 (これは間違いなく、drawTexturedPath関数を1回だけではなく新しい値で何度も呼び出しているため、パフォーマンスが低下することは間違いありません)。

私はちょっとしたグーグルで、さまざまな歩行者を計算する方法をいくつかの数式(または実装)で見つけることができます。少し紙を使って(あなたが数学であまりにも悪くないことを考えれば)、あなた自身もそれを推測するかもしれません。私はGameboy Advanceのためにゲームを作っていたので、私自身もそれをやっていました。

すべてを事前に確認してください!スピードはすべてです(特に携帯電話のような遅いマシンの場合)

EDIT:あなたのためにグーグルをしました。ここでは、mode7エフェクトを作成する方法を詳しく説明します。これにより、ブラックベリー機能でも同じことが達成されます。 Mode 7 implementation

+0

Reinier、ありがとう!真実であるために、私は数学では苦手です。なぜこの質問を賞金にあげましたか...答えは本当に面白いですが、パフォーマンス上の問題で解決できるかもしれませんが、ブラックベリーモード7のコード。 –

+0

残念ながら私はブラックベリーを所有していません。クライアントにポーティング作業をしているとき(ブラックベリーにも関係している)にアクセスできます。私は来週にそこにいるとは思わない。 =^| – Toad

+0

私の追加されたリンクは、それの背後にある数学の多くを説明したと思った...それを読もうとしましたか? – Toad

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°の角度であなたのイメージをゆがめるますベクトルの長さを決定します。

+0

こんにちはルーカス、お返事ありがとうございます。あなたが提供するものは単純な歪曲です。率直に言えば、私は3D変換(回転、スキュー、サイズ変更)を組み合わせることができる必要があります。 http://stackoverflow.com/questions/660304/4-point-transform-imagesを詳しく見てみましょう。歪んだだけでなく、部分的にサイズが変更されました。私が言ったように、これを行うにはいくつかの方法が必要です:1) - 彼らはdvx、dux、dvyを提供します。 2)net.rim.device.api.ui.Graphicsクラスの文書化されていないsetMatrix()メソッドとsetIdentity()メソッドがあります(unfortunatleyは機能しません) –

1

あなたはテクスチャマッピングを行いたいので、その機能はそれをカットしません。たぶんあなたの周りにあなたの方法をkludgeすることができますが、より良いオプションは、テクスチャマッピングアルゴリズムを使用することです。

これは、ピクセルの各行に対して、シェイプのエッジを決定し、シェイプのどこにシェイプピクセルピクセル(テクスチャピクセル)をマップするかを決定します。実際にはそれほど難しいことではありませんが、ちょっとした作業が必要です。そしてあなたは一度だけ絵を描くでしょう。

GameDevは、ここではソースコードとの記事の束を持っています

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

ウィキペディアにも素敵な記事があります。

http://tfpsly.free.fr/Docs/TomHammersley/index.html:3Dチュートリアルと

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

別のサイトを

あなたの場所では、自分が望むものに近いものを作って自分のソースをベースとして使って自分自身を開発する簡単なデモプログラムを探しています。ポータブルソースライブラリを見つけることもできますいくつか。

+0

こんにちはKristoffon、答えてくれてありがとう!私が理解しているように、ピクセルごとに色をペイントし、ビットマップに一度保存し、リフレッシュごとにビットマップを描画することができます。それはゆっくりで、yごとに線を引く以外にも解決策になります。概念の証明のために、http://www.wholetomato.com/images/tour/mondoPerspectiveTrans.gifのように、透視変換用のブラックベリーコードを提供できますか? –

+0

手でのテクスチャマッピング(一度に1ピクセルなので)は、j2meでは遅くなります。 J2MEは、API関数を使用して重い作業を行うことができる場合にのみ「高速」です。 – Toad

2

回答とガイダンスをお寄せいただき、ありがとうございます。
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; 
} 

コードのどこかで、outBmp用のグラフィックスoutBmpGraphicsを作成します。 lineBmp
から
1.createビットマップlineBmp =新しいビットマップ(幅、1)一列
2.create用グラフィックlineBmpGraphics:[開始yから(テクスチャ高さ)* yは係数変換するために反復で次の操作を行い
3.paint iは
4.encode lineBmp EncodedImageのIMGにlineBmpGraphicsにテクスチャからラインIMGモードに従って
5.scale 7
6.paint IMG outBmpGraphics
注:Richard Puckett's PNGEncoder BB port used in my code

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

それを描く、私はResizing a Bitmap using .scaleImage32 instead of .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ゲームを書く場合エキサイティング!

関連する問題