Eclipse アプリ作成 Lv4〜3Dグラフ用Cubeに高さを与える〜

参照コード:Chapter7-1(Gitです)

参照サイト:https://lwjglgamedev.gitbooks.io/3d-game-development-with-lwjgl/content/chapter07/chapter7.html

イントロダクション

前回は、Cubeを使って7 x 5マスを作りました。これだけではグラフになりませんのでこれに高さを与えてやる必要があります。

現状のソースは以下にようになってます。

@Override
    public void init(Window window) throws Exception {
        renderer.init(window);
        // Cubeのサイズ(たて、横、高さが同じなので値は1つ)
        final float cubeSize = 0.1f;
        // x軸の初期値
        final float xInit = 0;
        // y軸の初期値
        final float yInit = 0;
        // z軸の初期値
        final float zInit = -2;
        // x軸の増減幅
        final float xWidth = 0.185f;
        // y軸の増減幅
        final float yWidth = 0.033f;
        // z軸の増減幅
        final float zWidth = 0.1f;

        ArrayList arr = new ArrayList();
        for(int i = 1; i <= 7; i++) {
    		arr.add(createCube(
    				cubeSize, xInit + (xWidth * i), yInit + (yWidth * i), zInit - (zWidth * i)));
        }
        // 配列の要素数を指定する
        GameItem[] items = new GameItem[arr.size()];
        // 配列の取り出し
        gameItems = arr.toArray(items);
    }

    /* 追加したメソッドです */
    private GameItem createCube(float cubeSize, float posX, float posY, float posZ) {
        // Create the Mesh
        float[] positions = new float[]{
            // VO
            -1 * cubeSize,  cubeSize,  cubeSize,
            // V1
            -1 * cubeSize, -1 * cubeSize,  cubeSize,
            // V2
            cubeSize, -1 * cubeSize,  cubeSize,
            // V3
            cubeSize,  cubeSize,  cubeSize,
            // V4
            -1 * cubeSize,  cubeSize, -1 * cubeSize,
            // V5
            cubeSize,  cubeSize, -1 * cubeSize,
            // V6
            -1 * cubeSize, -1 * cubeSize, -1 * cubeSize,
            // V7
            cubeSize, -1 * cubeSize, -1 * cubeSize,
        };
        float[] colours = new float[]{
            0.5f, 0.0f, 0.0f,
            0.0f, 0.5f, 0.0f,
            0.0f, 0.0f, 0.5f,
            0.0f, 0.5f, 0.5f,
            0.5f, 0.0f, 0.0f,
            0.0f, 0.5f, 0.0f,
            0.0f, 0.0f, 0.5f,
            0.0f, 0.5f, 0.5f,
        };
        int[] indices = new int[]{
            // Front face
            0, 1, 3, 3, 1, 2,
            // Top Face
            4, 0, 3, 5, 4, 3,
            // Right face
            3, 2, 7, 5, 3, 7,
            // Left face
            6, 1, 0, 6, 0, 4,
            // Bottom face
            2, 1, 6, 2, 6, 7,
            // Back face
            7, 6, 4, 7, 4, 5,
        };
        Mesh mesh = new Mesh(positions, colours, indices);
        GameItem gameItem = new GameItem(mesh);
        gameItem.setPosition(posX, posY, posZ);
        gameItem.setRotation(20, 30, 0);
        return gameItem;
    }

現状のソースを修正する

現在の処理は次のような処理を行なっています。

  1. Cubeを作成するのに必要な値を初期化、作成の開始点を設定
  2. Cubeを複製するのに必要な値(Cube1つ分の移動する幅)を定義
  3. ループで7回、createCubeを呼ぶ処理を回す
  4. createCubeでCubeを作成する時にcubeSizeを渡す
  5. 上の赤字の部分を修正して次のように変更します。
  6. Cubeの高さを持っているArrayListを作成
  7. Cubeを作成するのに必要な値を初期化、作成の開始点を設定
  8. 1ヶ月分のマス(Cube)を作成するために5回ループを作成
  9. 「2」で指定した開始点にループした回数分ずらす処理を追加(1回目は変更なし)
  10. Cubeを複製するのに必要な値(Cube1つ分の移動する幅)を定義
  11. createCubeでCubeを作成する時にcubeSizeと高さを渡す
  12. ループで7回、createCubeを呼ぶ処理を回す

<今回のソース>

    @Override
    public void init(Window window) throws Exception {
        renderer.init(window);
        // Cubeの高さ
        ArrayList<float[]> floats = new ArrayList<>();
        floats.add(new float[] {0.2f, 0.12f, 0.3f, 0.001f, 0.1f, 0.25f, 0.1f});
        floats.add(new float[] {0.15f, 0.19f, 0.23f, 0.2f, 0.08f, 0.13f, 0.12f});
        floats.add(new float[] {0.1f, 0.2f, 0.4f, 0.001f, 0.2f, 0.05f, 0.15f});
        floats.add(new float[] {0.11f, 0.12f, 0.3f, 0.001f, 0.1f, 0.25f, 0.1f});
        floats.add(new float[] {0.12f, 0.13f, 0.14f, 0.015f, 0.16f, 0.17f, 0.18f});
        // Cubeの底面のサイズ(正方形)
        final float cubeSize = 0.1f;
        // x軸の初期値
        final float xInit = -0.5f;
        // y軸の初期値
        final float yInit = -0.8f;
        // z軸の初期値
        final float zInit = -2;
        // x軸の増減幅
        final float xWidth = 0.185f;
        // y軸の増減幅
        final float yWidth = 0.033f;
        // z軸の増減幅
        final float zWidth = 0.1f;
        ArrayList arr = new ArrayList();
        // 1ヶ月分(5週間分のマスを作る)
        for(int j = 1; j <= 5; j++) {
        	// 開始点より一列文ずらす
        	// X軸の開始点
        	float xStart = xInit - (0.1f * j);
        	// Y軸の開始点
        	float yStart = yInit + (0.06f * j) ;
        	// Z軸の開始点
        	float zStart = zInit - (0.16f * j);
            // 1週間分
        	float[] week = floats.get(j-1);
            for(int i = 1; i <= 7; i++) {
            	float val = week[i - 1];
        		arr.add(createCube(val,
        				cubeSize, xStart + (xWidth * i), yStart + (yWidth * i), zStart - (zWidth * i)));
            }
        }
        // 配列の要素数を指定する
        GameItem[] items = new GameItem[arr.size()];
        // 配列の取り出し
        gameItems = arr.toArray(items);
    }

    /* 追加したメソッドです */
    private GameItem createCube(float height, float cubeSize, float posX, float posY, float posZ) {
        // Create the Mesh
        float[] positions = new float[]{
            // VO
            -1 * cubeSize,  height,  cubeSize,
            // V1
            -1 * cubeSize, -1 * cubeSize,  cubeSize,
            // V2
            cubeSize, -1 * cubeSize,  cubeSize,
            // V3
            cubeSize,  height,  cubeSize,
            // V4
            -1 * cubeSize,  height, -1 * cubeSize,
            // V5
            cubeSize,  height, -1 * cubeSize,
            // V6
            -1 * cubeSize, -1 * cubeSize, -1 * cubeSize,
            // V7
            cubeSize, -1 * cubeSize, -1 * cubeSize,
        };
        float[] colours = new float[]{
            0.5f, 0.0f, 0.0f,
            0.0f, 0.5f, 0.0f,
            0.0f, 0.0f, 0.5f,
            0.0f, 0.5f, 0.5f,
            0.5f, 0.0f, 0.0f,
            0.0f, 0.5f, 0.0f,
            0.0f, 0.0f, 0.5f,
            0.0f, 0.5f, 0.5f,
        };
        int[] indices = new int[]{
            // Front face
            0, 1, 3, 3, 1, 2,
            // Top Face
            4, 0, 3, 5, 4, 3,
            // Right face
            3, 2, 7, 5, 3, 7,
            // Left face
            6, 1, 0, 6, 0, 4,
            // Bottom face
            2, 1, 6, 2, 6, 7,
            // Back face
            7, 6, 4, 7, 4, 5,
        };
        Mesh mesh = new Mesh(positions, colours, indices);
        GameItem gameItem = new GameItem(mesh);
        gameItem.setPosition(posX, posY, posZ);
        gameItem.setRotation(20, 30, 0);
        return gameItem;
    }

実行結果です


色がみんな同じなのでわかりづらいですね(笑)

続きは次回

でわでわ。。。

関連ページ一覧

<今回のやっていること>

  1. Eclipse アプリ作成 Lv1〜家計簿を作る準備〜
  2. Eclipse アプリ作成 Lv2〜家計簿を作る土台作り〜
  3. Eclipse アプリ作成 Lv3〜3Dグラフ用Cube作り〜

<Java Basic>

  1. Java Basic for文 〜Step1_3_1〜
  2. Java Basic Level8 〜How to use for statement〜
  3. Java Basic Level 9〜Training of for statement〜
  4. Java 3DGame LWJGL GitBook chapter7-1〜Cube作成〜「動画あり」

<サイトマップ>

Mapping of Java Bassic etc …~Java Basicなど記事一覧~

Eclipse アプリ作成 Lv3〜3Dグラフ用Cube作り〜

参照コード: Chapter7-1

イントロダクション

前回は、Cubeを作成して3つ並べるところまでやりました。

今回は、3つではなく7つ並べてみようと思います。

<前回のコード>

    @Override
    public void init(Window window) throws Exception {
        renderer.init(window);
        gameItems = new GameItem[] { createCube(0.1f, 0, 0, -2) };
        
    }

    /* 追加したメソッドです */
    private GameItem createCube(float cubeSize, float posX, float posY, float posZ) {
        // Create the Mesh
        float[] positions = new float[]{
            // VO
            -1 * cubeSize,  cubeSize,  cubeSize,
            // V1
            -1 * cubeSize, -1 * cubeSize,  cubeSize,
            // V2
            cubeSize, -1 * cubeSize,  cubeSize,
            // V3
            cubeSize,  cubeSize,  cubeSize,
            // V4
            -1 * cubeSize,  cubeSize, -1 * cubeSize,
            // V5
            cubeSize,  cubeSize, -1 * cubeSize,
            // V6
            -1 * cubeSize, -1 * cubeSize, -1 * cubeSize,
            // V7
            cubeSize, -1 * cubeSize, -1 * cubeSize,
        };
        float[] colours = new float[]{
            0.5f, 0.0f, 0.0f,
            0.0f, 0.5f, 0.0f,
            0.0f, 0.0f, 0.5f,
            0.0f, 0.5f, 0.5f,
            0.5f, 0.0f, 0.0f,
            0.0f, 0.5f, 0.0f,
            0.0f, 0.0f, 0.5f,
            0.0f, 0.5f, 0.5f,
        };
        int[] indices = new int[]{
            // Front face
            0, 1, 3, 3, 1, 2,
            // Top Face
            4, 0, 3, 5, 4, 3,
            // Right face
            3, 2, 7, 5, 3, 7,
            // Left face
            6, 1, 0, 6, 0, 4,
            // Bottom face
            2, 1, 6, 2, 6, 7,
            // Back face
            7, 6, 4, 7, 4, 5,
        };
        Mesh mesh = new Mesh(positions, colours, indices);
        GameItem gameItem = new GameItem(mesh);
        gameItem.setPosition(posX, posY, posZ);
        gameItem.setRotation(20, 30, 0);
        return gameItem;
    }

前回のコードではCubeを作成するのに、いちいちX〜Zまでの値を設定していました。これは、コードを書き間違えやすく修正点も多いのでイマイチなコードです。なので、これを一般化して作成するCubeの数を与えるようなコードに修正します。

<修正したコード>

    @Override
    public void init(Window window) throws Exception {
        renderer.init(window);

        final float cubeSize = 0.1f;
        // x軸の初期値
        final float xInit = 0;
        // y軸の初期値
        final float yInit = 0;
        // z軸の初期値
        final float zInit = -2;
        // x軸の増減幅
        final float xWidth = 0.185f;
        // y軸の増減幅
        final float yWidth = 0.033f;
        // z軸の増減幅
        final float zWidth = 0.1f;

        ArrayList arr = new ArrayList();
        for(int i = 1; i <= 7; i++) {
    		arr.add(createCube(
    				cubeSize, xInit + (xWidth * i), yInit + (yWidth * i), zInit - (zWidth * i)));
        }
        // 配列の要素数を指定する
        GameItem[] items = new GameItem[arr.size()];
        // 配列の取り出し
        gameItems = arr.toArray(items);
    }

    /* 追加したメソッドです */
    private GameItem createCube(float cubeSize, float posX, float posY, float posZ) {
        // Create the Mesh
        float[] positions = new float[]{
            // VO
            -1 * cubeSize,  cubeSize,  cubeSize,
            // V1
            -1 * cubeSize, -1 * cubeSize,  cubeSize,
            // V2
            cubeSize, -1 * cubeSize,  cubeSize,
            // V3
            cubeSize,  cubeSize,  cubeSize,
            // V4
            -1 * cubeSize,  cubeSize, -1 * cubeSize,
            // V5
            cubeSize,  cubeSize, -1 * cubeSize,
            // V6
            -1 * cubeSize, -1 * cubeSize, -1 * cubeSize,
            // V7
            cubeSize, -1 * cubeSize, -1 * cubeSize,
        };
        float[] colours = new float[]{
            0.5f, 0.0f, 0.0f,
            0.0f, 0.5f, 0.0f,
            0.0f, 0.0f, 0.5f,
            0.0f, 0.5f, 0.5f,
            0.5f, 0.0f, 0.0f,
            0.0f, 0.5f, 0.0f,
            0.0f, 0.0f, 0.5f,
            0.0f, 0.5f, 0.5f,
        };
        int[] indices = new int[]{
            // Front face
            0, 1, 3, 3, 1, 2,
            // Top Face
            4, 0, 3, 5, 4, 3,
            // Right face
            3, 2, 7, 5, 3, 7,
            // Left face
            6, 1, 0, 6, 0, 4,
            // Bottom face
            2, 1, 6, 2, 6, 7,
            // Back face
            7, 6, 4, 7, 4, 5,
        };
        Mesh mesh = new Mesh(positions, colours, indices);
        GameItem gameItem = new GameItem(mesh);
        gameItem.setPosition(posX, posY, posZ);
        gameItem.setRotation(20, 30, 0);
        return gameItem;
    }

こちらのコードでは、Cubeの初期値(を指定しています、この初期値から何個並べるのかを指定できるようにしてあります。赤字の部分が初期値を設定している部分になります。

処理概要DummyGame#init()

  1. 初期値を設定(初期化)
  2. 7回Cube作成メソッドを呼び出す
  3. ループするたびに「増減幅」文を初期値に追加(+, -)する

<実行結果>

初期値を画面の中心に指定しているのでこのようになります。

次は?

3Dグラフを表示するのに、グラフが右に寄りすぎ、、、位置が悪いので修正します。

        // x軸の初期値
        final float xInit = -0.8f;
        // y軸の初期値
        final float yInit = -0.8f;
        // z軸の初期値
        final float zInit = -2;

修正したのは赤字の部分の値だけです。表示結果は以下のようになります。

なんかイマイチですが、これを1ヶ月分(7 x 5マス)並べてみます。

修正した部分は以下になります。For文が1つだったのを2つにして以下のような手順に変更しました。

  1. 5回ループする
  2. 7つCubeを作成するときの初期値を変更する
  3. 初期値を元にCubeを7つ並べる



コードは以下になります。いわゆる2次元ループってやつですね(笑)

        // 1ヶ月分(5週間分のマスを作る)
        for(int j = 1; j <= 5; j++) {
        	// 開始点より一列文ずらす
        	// X軸の開始点
        	float xStart = xInit - (0.1f * j);
        	// Y軸の開始点
        	float yStart = yInit + (0.06f * j) ;
        	// Z軸の開始点
        	float zStart = zInit - (0.16f * j);
            // 1週間分
            for(int i = 1; i <= 7; i++) {
        		arr.add(createCube(
        				cubeSize, xStart + (xWidth * i), yStart + (yWidth * i), zStart - (zWidth * i)));
            }
        }

でわでわ。。。

関連ページ一覧

  1. Java Basic for文 〜Step1_3_1〜
  2. Java Basic Level8 〜How to use for statement〜
  3. Java Basic Level 9〜Training of for statement〜
  4. Java 3DGame LWJGL GitBook chapter7-1〜Cube作成〜「動画あり」

<サイトマップ>

Mapping of Java Bassic etc …~Java Basicなど記事一覧~

 

 

Eclipse アプリ作成 Lv2〜家計簿を作る土台作り〜

前提

LWJGLのセットアップが完了して、Eclipseのプロジェクトも作成済みであること。→前回をみてください。

インントロダクション

前回はプロジェクトをEclipse上に作成し、開発の準備をしました。

重要なことなので今一度、以下を確認してください。

  1. 作成した、プログラム「Hello World」が動くことを確認 → 前回
  2. LWJGLに必要なライブラリがBuildPathに繋がっていることを確認 → LWJGLのセットアップ


3Dグラフを作る

Chapter7-1で作成したCubeをベースに作成します。

初めにCubeを小さくします。変更するのは各頂点の位置を狭くします。

<DummyGame#init()>

        // Create the Mesh
        float[] positions = new float[]{
            // VO
            -0.1f,  0.1f,  0.1f,
            // V1
            -0.1f, -0.1f,  0.1f,
            // V2
             0.1f, -0.1f,  0.1f,
            // V3
             0.1f,  0.1f,  0.1f,
            // V4
            -0.1f,  0.1f, -0.1f,
            // V5
             0.1f,  0.1f, -0.1f,
            // V6
            -0.1f, -0.1f, -0.1f,
            // V7
             0.1f, -0.1f, -0.1f,
        };

上記のように「0.5f」の部分を「0.1f」に変更します。

それで表示できるのが下のようなイメージです。

これができたら、大きさを調節できるように各頂点を定義している部分をメソッドに切り出します。そして、サイズを指定できるように変数に変えます。

<DummyGame#createCube()>

    /* 追加したメソッドです */
    private GameItem createCube(float cubeSize, float posX, float posY, float posZ) {
        // Create the Mesh
        float[] positions = new float[]{
            // VO
            -1 * cubeSize,  cubeSize,  cubeSize,
            // V1
            -1 * cubeSize, -1 * cubeSize,  cubeSize,
            // V2
            cubeSize, -1 * cubeSize,  cubeSize,
            // V3
            cubeSize,  cubeSize,  cubeSize,
            // V4
            -1 * cubeSize,  cubeSize, -1 * cubeSize,
            // V5
            cubeSize,  cubeSize, -1 * cubeSize,
            // V6
            -1 * cubeSize, -1 * cubeSize, -1 * cubeSize,
            // V7
            cubeSize, -1 * cubeSize, -1 * cubeSize,
        };
        float[] colours = new float[]{
            0.5f, 0.0f, 0.0f,
            0.0f, 0.5f, 0.0f,
            0.0f, 0.0f, 0.5f,
            0.0f, 0.5f, 0.5f,
            0.5f, 0.0f, 0.0f,
            0.0f, 0.5f, 0.0f,
            0.0f, 0.0f, 0.5f,
            0.0f, 0.5f, 0.5f,
        };
        int[] indices = new int[]{
            // Front face
            0, 1, 3, 3, 1, 2,
            // Top Face
            4, 0, 3, 5, 4, 3,
            // Right face
            3, 2, 7, 5, 3, 7,
            // Left face
            6, 1, 0, 6, 0, 4,
            // Bottom face
            2, 1, 6, 2, 6, 7,
            // Back face
            7, 6, 4, 7, 4, 5,
        };
        Mesh mesh = new Mesh(positions, colours, indices);
        GameItem gameItem = new GameItem(mesh);
        gameItem.setPosition(posX, posY, posZ);
        gameItem.setRotation(20, 30, 0);
        return gameItem;
    }

そして呼び出し部分を以下のように修正します。

<DummyGame#init()>

    @Override
    public void init(Window window) throws Exception {
        renderer.init(window);
        gameItems = new GameItem[] { createCube(0.1f, 0, 0, -2), createCube(0.1f, 0.185f, 0.033f, -2.1f) , createCube(0.1f, 0.37f, 0.066f, -2.2f) };
    }

ここまできたら、現在3つ並んでいるCubeをカレンダーのように並べます。が今回はここまでにします。ロジックを考える時間が欲しいのです。。。

でわでわ。。。

関連ページ一覧

<開発ツールのインストール>

<プロジェクトの作成(はじめ方)>

<GitからのPULL方法>

<Javaの基本から応用など>

 

Java 3DGame LWJGL Retry Lv2 〜動かして理解する2〜

イントロダクション

LWJGLのGitBookを読み進めChapter8まできましたが、ここからよく解らなくなってしまいました。

原因は、3Dモデル描画(レンダリング)の部分をちゃんと理解していないためです。

なので、Chapter5-2からやり直します。

幸いにも、GitからPULLしてきたファイルがあるのでそいつをカスタムして理解していきます。

前回は、色の指定方法について解析ました。

今回は、形の変形に関してやります。

変形について

修正したJavaクラス一式に関してはGitにアップロードしてあります。PULLしたらChapter5というパッケージがありますのでそれが今回のソースになります。

元々のソース(GitBookにあるソースより少し修正しています)

<DummyGame#init()>いじって遊ぶ部分です。

 float[] positions = new float[]{
         // V0
         0.0f, 0.25f, 0.0f,
         // V1
         -0.0f, -0.0f, 0.0f,
         // V2
         0.5f, -0.0f, 0.0f,
         // V3
         0.5f, 0.25f, 0.0f,};

この状態での表示結果は下のように表示されます。

コメントにあるV0〜V3までのfloat型の値、3個で1セットになります。

V0「 0.0f, 0.25f, 0.0f,」

V1「-0.0f, -0.0f, 0.0f,」

V2「0.5f, -0.0f, 0.0f,」

V3「0.5f, 0.25f, 0.0f,」

こんな感じです。

<各点のイメージ>

2次元なので2次関数の理解があれば難しくはありません。

問題は3次元での位置

アップロードしたファイル(Git)のChapter7-1に移動します。

<DummyGame#init()>点(Vertexの「V」) が増えて8つになります。

元々のソースです。

        // Create the Mesh
        float[] positions = new float[]{
            // VO
            -0.5f,  0.5f,  0.5f,
            // V1
            -0.5f, -0.5f,  0.5f,
            // V2
             0.5f, -0.5f,  0.5f,
            // V3
             0.5f,  0.5f,  0.5f,
            // V4
            -0.5f,  0.5f, -0.5f,
            // V5
             0.5f,  0.5f, -0.5f,
            // V6
            -0.5f, -0.5f, -0.5f,
            // V7
             0.5f, -0.5f, -0.5f,
        };

ちょいといじってみました。元々はinit()の中でpositions, colours, indicesを設定していたのを変更して、positionsのみ変数で値を変更できるようjにしてみました。

   @Override
    public void init(Window window) throws Exception {
        renderer.init(window);
        // キューブの大きさキューブの位置
        gameItems = new GameItem[] { createCube(0.1f, 0, 0, -2) };
        
    }
    /* 追加したメソッドです */
    private GameItem createCube(float cubeSize, float posX, float posY, float posZ) {
        // Create the Mesh
        float[] positions = new float[]{
            // VO
            -1 * cubeSize,  cubeSize,  cubeSize,
            // V1
            -1 * cubeSize, -1 * cubeSize,  cubeSize,
            // V2
            cubeSize, -1 * cubeSize,  cubeSize,
            // V3
            cubeSize,  cubeSize,  cubeSize,
            // V4
            -1 * cubeSize,  cubeSize, -1 * cubeSize,
            // V5
            cubeSize,  cubeSize, -1 * cubeSize,
            // V6
            -1 * cubeSize, -1 * cubeSize, -1 * cubeSize,
            // V7
            cubeSize, -1 * cubeSize, -1 * cubeSize,
        };
        float[] colours = new float[]{
            0.5f, 0.0f, 0.0f,
            0.0f, 0.5f, 0.0f,
            0.0f, 0.0f, 0.5f,
            0.0f, 0.5f, 0.5f,
            0.5f, 0.0f, 0.0f,
            0.0f, 0.5f, 0.0f,
            0.0f, 0.0f, 0.5f,
            0.0f, 0.5f, 0.5f,
        };
        int[] indices = new int[]{
            // Front face
            0, 1, 3, 3, 1, 2,
            // Top Face
            4, 0, 3, 5, 4, 3,
            // Right face
            3, 2, 7, 5, 3, 7,
            // Left face
            6, 1, 0, 6, 0, 4,
            // Bottom face
            2, 1, 6, 2, 6, 7,
            // Back face
            7, 6, 4, 7, 4, 5,
        };
        Mesh mesh = new Mesh(positions, colours, indices);
        GameItem gameItem = new GameItem(mesh);
        gameItem.setPosition(posX, posY, posZ);
        gameItem.setRotation(20, 30, 0);
        return gameItem;
    }

Cubeを作成するための座標(8点)を指定して、中点(0.0f, 0.0f, 0.0f0)を起点としたモデルを作成した後にsetPosition()でCubeを移動、setRotation()で傾きをつけてやることで、3Dモデルのようにみることができます。傾きを与えないと正方形にしか見えません。。。

作成したコードで遊んでみる

上のソース「 gameItems = new GameItem[] { createCube(0.1f, 0, 0, -2) }; 」

の行について、gameItemsにGameItemの配列を作成していますが、今回は1つだけ作成しているのであまり意味のないものになっています。がこれの意味をもたせます。

Cubeを3つに増やしてみます。コードを下のように修正します。

gameItems = new GameItem[] { createCube(0.1f, 0, 0, -2), createCube(0.1f, 1, 0, -2) };

名付けて「キューブ三兄弟」!

更に並べてみた。

gameItems = new GameItem[] { createCube(0.1f, 0, 0, -2), createCube(0.1f, 0.185f, 0.033f, -2.1f) , createCube(0.1f, 0.37f, 0.066f, -2.2f) };



お後がよろしいようで。

関連ページ一覧

<開発ツールのインストール>

Java Install Eclipse〜開発ツールのインストール〜

<プロジェクトの作成(はじめ方)>

Eclipse Meven 開発手順〜プロジェクトの作成〜

<GitからのPULL方法>

Eclipse Gitリポジトリの取得 〜GitからソースをPullしよう〜

<Javaの基本から応用など>

Mapping of Java Bassic etc …~Java Basicなど記事一覧~

 

Java 3DGame LWJGL Retry Lv1 〜動かして理解する〜

イントロダクション

LWJGLのGitBookを読み進めChapter8まできましたが、ここからよく解らなくなってしまいました。

原因は、3Dモデル描画(レンダリング)の部分をちゃんと理解していないためです。

なので、Chapter5-2からやり直します。

幸いにも、GitからPULLしてきたファイルがあるのでそいつをカスタムして理解していきます。

余談

EclipseでGitからPULLする場合は、ChapterX("X"には数字)のフォルダをPULLするとプロジェクトが作成されてちょうど良い感じです。

フォルダ(ディレクトリ)の直下に「.project」ファイルがあるとEclipseはそのフォルダを「プロジェクト」として読み込んでくれます。

今回のGitリポジトリは「pom.xml」ファイルがあるのでそれはMevenプロジェクトとして読み込んでくれるようです。

*****************************************


*****************************************

Chapter5-2で表示

***************************************


***************************************

  ソースで遊ぶ

前回表示したのは、シンプルに四角でした。こいつを以下のようにしてみます。

1.色を色々と変えてみる

色を決めているであろう、ソースコードは下の部分になります。

DummtGame#init()

       // 追記 2018/10/27
        float[] colors = new float[] {
        	    0.5f, 0.0f, 0.0f, // T01
        	    0.0f, 0.5f, 0.0f, // T02
        	    0.0f, 0.0f, 0.5f, // T03
        	    0.0f, 0.5f, 0.5f,}; // T04

これのT01行の値(「0.5f, 0.0f, 0.0f,」)を変更してみます。

「0.0f, 0.0f, 0.0f,」

「0.0f, 0.5f, 0.0f,」

「0.0f, 0.0f, 0.5f,」

どうやら「0.0f」は黒「0.5f」はRGBの3つ並んだうちの色を出すようです。

→「0.0f, 0.0f, 0.0f,」黒、「0.5f, 0.0f, 0.0f,」赤、「0.0f, 0.5f, 0.0f,」緑、「0.0f, 0.0f, 0.5f,」青

逆に1.0fの値は白になるだろうか?

「1.0f(R), 0.0f(G), 0.0f(B),」は左上が白くなるであろうと仮説を立てます。

<実行結果>

明るい赤でした。。。でも上記の配列はRGBの順番でそれぞれの色の強さを示していることがわかりました。

次は二段目、T02行の値(「0.0f, 0.5f, 0.0f,」)を変更してみます。T01の行と同様に値を変えていきます。

「0.5f, 0.0f, 0.0f,」

「0.5f, 0.0f, 0.0f,」

「0.0f, 0.0f, 0.5f,」

ここまでやって、はっきりしました。

 

       // 追記 2018/10/27
        float[] colors = new float[] {
        	    0.5f, 0.0f, 0.0f, // T01:左上(赤)
        	    0.0f, 0.5f, 0.0f, // T02:左下(緑)
        	    0.0f, 0.0f, 0.5f, // T03:右下(青)
        	    0.8f, 0.8f, 0.0f,}; // T04:(黄)

 

こんな感じで、color部分に関しては理解できました。

次回

今度は、positionをいじって遊ぼうと思います。

関連ページ一覧

Java 3DGame LWJGL GitBook chapter5-2〜レンダリング詳細〜

<開発準備>

Java Install Eclipse〜開発ツールのインストール〜

<LWJGLのGitBokに関して>

  1. Chapter1[外枠の表示のみ]
  2. Chapter2-1〜クラスの構成〜
  3. Chapter2-2〜インターフェースの使い方と詳細〜
  4. Chapter2-3〜GameEngineクラス(サンプルクラス)〜/li>
  5. Chapter2-4〜Windowクラス(サンプルクラス)〜
  6. Chapter3〜描画処理を読む〜
  7. Chapter4〜シェーダについて〜
  8. Chapter5-1〜レンダリングについて〜

<Java Basic>

  1. Java Basic Level 1 〜Hello Java〜
  2. Java Basic Level2 〜Arithmetic Calculate〜
  3. Java Basic Level3 〜About String class〜
  4. Java Basic Level 4〜Boolean〜
  5. Java Basic Level 5〜If Statement〜
  6. Java Basic Summary from Level1 to 5
  7. Java Basic Level 6 〜Traning of If statement〜
  8. Java Basic Level8 〜How to use for statement〜
  9. Java Basic Level 8.5 〜Array〜
  10. Java Basic Level 8.5 〜Array〜
  11. Java Basic Level 10 〜While statement 〜
  12. Java Basic Swing〜オブジェクト指向〜
  13. Java Basic Swing Level 2〜オブジェクト指向2〜


Eclipse アプリ作成 Lv1〜家計簿を作る準備〜

イントロダクション

今までLWJGLを学んできました。これはOpenGLとOpenAL(オーディオ関連ライブラリ)を含んだフレームワークです。本当はまだまだ続きがあります(chapter7/chapter28)

駄菓子菓子!Matrix(行列)が出てきたあたりから解らなくなってきたので、今一度理解するためにアプリを作って理解しようというわけです。

  1.  Chapter1[外枠の表示のみ]
  2. Chapter2-1〜クラスの構成〜
  3. Chapter2-2〜インターフェースの使い方と詳細〜
  4. Chapter2-3〜GameEngineクラス(サンプルクラス)〜/li>
  5. Chapter2-4〜Windowクラス(サンプルクラス)〜
  6. Chapter3〜描画処理を読む〜
  7. Chapter4〜シェーダについて〜
  8. Chapter5-1〜レンダリングについて〜
  9. Chapter5-2〜レンダリング詳細〜
  10. Chapter6〜Projection(投影)〜
  11. Chapter7-1〜Cubeを作る〜
  12. Chapter7-2〜Texture〜

家計簿アプリを作る準備

セットアップ

1.まずはMavenプロジェクトを作成します。

2.そして、プロジェクトのセットアップを行います。

今回は、フレームワークとしてLWJGLを使用します。必要なライブラリをMevenで落としてくるのも良いのですが、バージョンが沢山あるので、今使用しているライブラリを使用します。LWJGLのセットアップ

プロジェクトを右クリックして、properties

Build Pathを選択

ライブラリを追加しますので、ライブラリ(Libraries)を開き「Add Library」

そして、「User libraries」をクリック

「New」でUserLibraryを作成します。

「Add External Jar」で外部(Eclipseの外)ライブラリ(JAR)を読み込みます。

今回はLWJGLなのでダウンロードした、頭に「lwjgl」とついているJARファイルを全てパスに繋ぎます。そしてOK。

Javaのバージョンを1.8以上にします。

Project右クリック > Properties > Java Compiler

でJavaのバージョンを1.8以上にします。

トドメに、「Hello World」を実行

とりあえずは、ここまでで一区切りです。

でわでわ。。。

 関連ページ一覧

<開発ツールのインストール>

<プロジェクトの作成(はじめ方)>

<GitからのPULL方法>

<Javaの基本から応用など>

 


Java 3DGame LWJGL GitBook chapter8〜Camera〜

イントロダクション

LWJGL GitBookChapterを写経しながら理解していきます。Git(ソース)はこちら。。。

前回は、Chapter7-2をやりました。今回は画面を表示するときの「カメラ」に付いてやります。

ゲームで表示されている領域を変えたり、ズームアップしたりするアレです。

コードを読む(Read Code)

今までに見て来た部分は割愛します。

  1.  Chapter1[外枠の表示のみ]
  2. Chapter2-1〜クラスの構成〜
  3. Chapter2-2〜インターフェースの使い方と詳細〜
  4. Chapter2-3〜GameEngineクラス(サンプルクラス)〜/li>
  5. Chapter2-4〜Windowクラス(サンプルクラス)〜
  6. Chapter3〜描画処理を読む〜
  7. Chapter4〜シェーダについて〜
  8. Chapter5-1〜レンダリングについて〜
  9. Chapter5-2〜レンダリング詳細〜
  10. Chapter6〜Projection(投影)〜
  11. Chapter7-1〜Cubeを作る〜
  12. Chapter7-2〜Texture〜

https://ahbejarano.gitbook.io/lwjglgamedev/chapter8

今回の追加ソース

  1. MouseInput
  2. Camera

大きな修正部分

  1. Transformation#getWorldMatrix()を修正していました。
  2. DummyGame#init()
  3. Renderer#render()

写経後に起動するアプリ

*************************************


*************************************

改めてソースを読む

Main: DummyGame, GameEngineをインスタンス化してGameEngine#start()を実行

DummyGame: Renderer, Camera, Vector3fをインスタンス化して各フィールドに設定

GameEngine:

  1. スレッドを立ち上げ(new Thread(this))、フィールドにWindow, MounseInput, DummyGameのインスタンスを設定する
  2. OSの種類に応じて、GameEngine#run() or GameEngine#start()を切り替えて実行する
  3. フィールドにセットした各クラスの初期処理(init())を起動する
  4. gameLoopを回しながらinput, renderを繰り返し実行する

大雑把にこんな感じの処理をしていました。

今回のキモ

ズバリ、カメラワークでしょう!そして、因縁の三角関数!!

そして、GitBookの説明を読んでもよくわからなかったので、デバッカーを作って実行

スクリーンショット 2018-10-31 20.38.06.png

入力があったときのみコンソールに出力する様に処理を追加→欠陥品でした。。。1回目しか出力しません。。。

スクリーンショット 2018-10-31 21.47.10.png

出力結果

2018-10-31 21.46.55

とりあえずはここまでやったのだけど、入力した値が逆方向に向いている(-0.05)こと以外はわからなかった次第でございます。

続きはまた後日。

でわでわ。。。

 

Java 3DGame LWJGL GitBook chapter7-2〜Texture〜

イントロダクション

LWJGL GitBookChapterを写経しながら理解していきます。Git(ソース)はこちら。。。

前回は、Chapter7-1をやりました。

今回は前回作詞したCubeにテクスチャを貼り付けます。

コードを読む(Read Code)

今までに見て来た部分は割愛します。

  1.  Chapter1[外枠の表示のみ]
  2. Chapter2-1〜クラスの構成〜
  3. Chapter2-2〜インターフェースの使い方と詳細〜
  4. Chapter2-3〜GameEngineクラス(サンプルクラス)〜/li>
  5. Chapter2-4〜Windowクラス(サンプルクラス)〜
  6. Chapter3〜描画処理を読む〜
  7. Chapter4〜シェーダについて〜
  8. Chapter5-1〜レンダリングについて〜
  9. Chapter5-2〜レンダリング詳細〜
  10. Chapter6〜Projection(投影)〜
  11. Chapter7-1〜Cubeを作る〜

https://ahbejarano.gitbook.io/lwjglgamedev/chapter7

写経前の準備

上のリンクにあるGitBookを読んでみるとMavenでのライブラリ追加に関して記載があります。なのでライブラリの追加(依存関係の追加)を行います。

依存関係の追加(Maven、POMファイル)

上のキャプチャの様にPOMファイルを開きます。

そして、GitBookのページからPOMファイルの記載部分をコピって「ぺっ」ってやります。

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  
  <modelVersion>4.0.0modelVersion>
  <groupId>zenryokuservicegroupId>
  <artifactId>gui.mtmartifactId>
  <version>0.0.1-SNAPSHOTversion>
  <packaging>jarpackaging>
  <name>gui.mtmname>
  <url>http://maven.apache.orgurl>
  <properties>
    <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
  properties>
  
  <dependencies>
    <dependency>
      <groupId>junitgroupId>
      <artifactId>junitartifactId>
      <version>3.8.1version>
      <scope>testscope>
    dependency>
    
    <dependency>
         <groupId>org.jomlgroupId>
         <artifactId>jomlartifactId >
         <version>1.9.6version >
    dependency>
    
    <dependency>
      <groupId>org.l33tlabs.twlgroupId>
      <artifactId>pngdecoderartifactId>
      <version>バージョンを記載version>
    dependency>
  dependencies>
project>

上記の様な感じでPOMファイルができると思いますが、「バージョン」に関しては調べる必要あります。今回追加するのは

PNGDecoder

なのでそのサイトへいきバージョンを調べます。

ちょっとわかりづらいけど「1.0」と記載してありました。

上の様にpom.xmlを右クリック→Maven→Maven installでインストール完了です。

そして実行結果は以下の様になりました。

中身を見る

今回は、前回作成したCube(立方体)にテクスチャを貼り付ける作業になります。

ソースの差分を見るのでなく面倒なのでソースをそのまま読みます。

Main: 変化なし(やってることは変わらない)

DummyGame:Textureクラスを生成、Meshクラスに渡す

Texture texture = new Texture("/textures/grassblock.png");
Mesh mesh = new Mesh(positions, textCoords, indices, texture);

GitBookの説明には以下の様にありました。


次のステップは、テクスチャをグラフィックスカードメモリにアップロードすることです。まず、新しいテクスチャ識別子を作成する必要があります。テクスチャに関連する各操作はその識別子を使用するため、バインドする必要があります。

//新しいOpenGLテクスチャを作成する 
int textureId = glGenTextures ; 
//テクスチャをバインドする
glBindTexture GL_TEXTURE_2D textureId ;

次に、RGBAバイトを解凍する方法をOpenGLに伝える必要があります。各コンポーネントのサイズは1バイトなので、次の行を追加する必要があります。

glPixelStorei GL_UNPACK_ALIGNMENT 1 ; 

最後にテクスチャデータをアップロードすることができます:

glTexImage2D GL_TEXTURE_2D, 0, GL_RGBA,cgetWidth, 
    decoder.getHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf; 

Mesh: TextureのVBOのIDを取得して〜とCubeと同じ処理をする

textCoordsBuffer = MemoryUtil.memAllocFloat(textCoords.length);
textCoordsBuffer.put(textCoords).flip();
glBindBuffer(GL_ARRAY_BUFFER, vboId);
glBufferData(GL_ARRAY_BUFFER, textCoordsBuffer, GL_STATIC_DRAW);
glVertexAttribPointer(1, 2, GL_FLOAT, false, 0, 0);

※詳細はChapter5-2を参照してください。

Cubeを作成した時と同様に各頂点(V0〜V7)までの点に対して順序を指定します。

<頂点イメージ>

<テクスチャとモデルの関係>

<テクスチャ>

grassblock

テクスチャをCubeの頂点とOpenGLに結びつけてやる。

        // Load Texture file=>Mavenで追加したライブラリのクラス
        PNGDecoder decoder = new PNGDecoder(Texture.class.getResourceAsStream(fileName));

        // Load texture contents into a byte buffer
        ByteBuffer buf = ByteBuffer.allocateDirect(
                4 * decoder.getWidth() * decoder.getHeight());
        decoder.decode(buf, decoder.getWidth() * 4, Format.RGBA);
        buf.flip();

        // Create a new OpenGL texture 
        int textureId = glGenTextures();
        // Bind the texture
        glBindTexture(GL_TEXTURE_2D, textureId);

        // Tell OpenGL how to unpack the RGBA bytes. Each component is 1 byte size
        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

        //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

        // Upload the texture data
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, decoder.getWidth(), decoder.getHeight(), 0,
                GL_RGBA, GL_UNSIGNED_BYTE, buf);
        // Generate Mip Map
        glGenerateMipmap(GL_TEXTURE_2D);

Cubeの頂点とテクスチャの頂点をセットした配列を用意して、OpenGLに結びつける(Bind)

        // Create the Mesh
        float[] positions = new float[] {
            // V0
            -0.5f, 0.5f, 0.5f,
            // V1
            -0.5f, -0.5f, 0.5f,
            // V2
            0.5f, -0.5f, 0.5f,
            // V3
            0.5f, 0.5f, 0.5f,
            // V4
            -0.5f, 0.5f, -0.5f,
            // V5
            0.5f, 0.5f, -0.5f,
            // V6
            -0.5f, -0.5f, -0.5f,
            // V7
            0.5f, -0.5f, -0.5f,
            
            // For text coords in top face
            // V8: V4 repeated
            -0.5f, 0.5f, -0.5f,
            // V9: V5 repeated
            0.5f, 0.5f, -0.5f,
            // V10: V0 repeated
            -0.5f, 0.5f, 0.5f,
            // V11: V3 repeated
            0.5f, 0.5f, 0.5f,

            // For text coords in right face
            // V12: V3 repeated
            0.5f, 0.5f, 0.5f,
            // V13: V2 repeated
            0.5f, -0.5f, 0.5f,

            // For text coords in left face
            // V14: V0 repeated
            -0.5f, 0.5f, 0.5f,
            // V15: V1 repeated
            -0.5f, -0.5f, 0.5f,

            // For text coords in bottom face
            // V16: V6 repeated
            -0.5f, -0.5f, -0.5f,
            // V17: V7 repeated
            0.5f, -0.5f, -0.5f,
            // V18: V1 repeated
            -0.5f, -0.5f, 0.5f,
            // V19: V2 repeated
            0.5f, -0.5f, 0.5f,
        };
        float[] textCoords = new float[]{
            0.0f, 0.0f,
            0.0f, 0.5f,
            0.5f, 0.5f,
            0.5f, 0.0f,
            
            0.0f, 0.0f,
            0.5f, 0.0f,
            0.0f, 0.5f,
            0.5f, 0.5f,
            
            // For text coords in top face
            0.0f, 0.5f,
            0.5f, 0.5f,
            0.0f, 1.0f,
            0.5f, 1.0f,

            // For text coords in right face
            0.0f, 0.0f,
            0.0f, 0.5f,

            // For text coords in left face
            0.5f, 0.0f,
            0.5f, 0.5f,

            // For text coords in bottom face
            0.5f, 0.0f,
            1.0f, 0.0f,
            0.5f, 0.5f,
            1.0f, 0.5f,
        };
        int[] indices = new int[]{
            // Front face
            0, 1, 3, 3, 1, 2,
            // Top Face
            8, 10, 11, 9, 8, 11,
            // Right face
            12, 13, 7, 5, 12, 7,
            // Left face
            14, 15, 6, 4, 14, 6,
            // Bottom face
            16, 18, 19, 17, 16, 19,
            // Back face
            4, 6, 7, 5, 4, 7,};

テクスチャをアクティブにする(と思う)

        // Activate firs texture bank
        glActiveTexture(GL_TEXTURE0);

他のクラスは変わりなし。。。多分(実行結果からその様に予測。。。)

まとめ

大まかな流れが読めて来ました。テクスチャもCubeなど3DモデルもOpenGLに頂点座標を渡して描画する様です。

  1. 必要な頂点座標(配列)を用意する
  2. 各頂点をOpenGLにバインド(結びつける)
  3. 描画用に使用する値を「シェーダプログラム」に渡す
    1.         // Create uniforms for world and projection matrices and texture
              shaderProgram.createUniform("projectionMatrix");
              shaderProgram.createUniform("worldMatrix");
              shaderProgram.createUniform("texture_sampler");
  4. 描画

の様な順序で処理していました。実際に触って見るのが良いと思います。

Gitにソースアップしています。(上のリンクからもダウンロードできます。)わかりやすい方でどうぞ。

追伸:自分の写経したソースは、resourcesフォルダにfs, vsファイルがあるのでそちらもダウンロードされたし。。。。

次のChapterが楽しみです。

でわでわ。。。



Java 3DGame LWJGL GitBook chapter6〜Projection(投影)〜

イントロダクション

LWJGL GitBookChapterを写経しながら理解していきます。Git(ソース)はこちら。。。

前回は、Chapter5-2をやりました。

Introduction

LWJGL We will understand GitBook ‘s chapter while shooting. Git (source) is here. . . Last time I did Chapter 5-2so We will do Chapter 6 this time. Let’s get sarted!.

https://ahbejarano.gitbook.io/lwjglgamedev/chapter6

コードを読む(Read Code)

今までに見て来た部分は割愛します。

  1.  Chapter1[外枠の表示のみ]
  2. Chapter2-1〜クラスの構成〜
  3. Chapter2-2〜インターフェースの使い方と詳細〜
  4. Chapter2-3〜GameEngineクラス(サンプルクラス)〜/li>
  5. Chapter2-4〜Windowクラス(サンプルクラス)〜
  6. Chapter3〜描画処理を読む〜
  7. Chapter4〜シェーダについて〜
  8. Chapter5-1〜レンダリングについて〜
  9. Chapter5-2〜レンダリング詳細〜

今回は、いきなりコードではなくドキュメントから読んでいきます。ちょっと難しくなって来ました。

今までと同様に、プロジェクトのコードを起動します。

スクリーンショット 2018-10-28 13.46.42.png

こんな色の四角を描画します(プログラムが)。この描画はChapter5-2でやりました。

次です。

このチャプターの目玉機能「Transformation」です。どうやら以下の様なイメージで動かすことの様です。

そして、上の様な操作を行うためのクラスを作成します。その名も

Transformationクラス

package zenryokuservice.gui.lwjgl.tutoriral.gitbook.chapter6.engine.graph;

import org.joml.Matrix4f;
import org.joml.Vector3f;

public class Transformation {
	private final Matrix4f projectionMatrix;
	private final Matrix4f worldMatrix;

	public Transformation() {
		projectionMatrix = new Matrix4f();
		worldMatrix = new Matrix4f();
	}

	public final Matrix4f getProjectionMatrix(float fov, float wid, float hei, float zNear, float zFar) {
		float aspectRatio = wid / hei;
		projectionMatrix.identity();
		projectionMatrix.perspective(fov, aspectRatio, zNear, zFar);
		return projectionMatrix;
	}

	public Matrix4f getWorldMatrix(Vector3f offset, Vector3f rotation, float scale) {
		worldMatrix.identity().translate(offset)
			.rotateX((float) Math.toRadians(rotation.x))
			.rotateY((float) Math.toRadians(rotation.y))
			.rotateZ((float) Math.toRadians(rotation.z))
			.scale(scale);
		return worldMatrix;
	}
}

写経して見て「ああ、なるほど」と思うことは各クラスの繋がりとか役割に関して頭の中でイメージが描けることです。メソッドとか気がついたら覚えているしね(笑)。

結果

スクリーンショット 2018-10-28 21.42.59.png

初めの表示とかわりませんでした。。。

けど、追加で作成したTrasformationクラスを使用してprojectionMatrix, worldMatrixの使い方が少しわかった様な気がします。ShaderProgramに関しても少しずつわかって来た様な気がします。

今回の実装では。GameItemを追加してから表示するためのデータセットのコードが参照したページにはありませんでしたので、自分で考えて実装しました。

DummyGame#init()に処理を追加してやりました。
結局のところ、画面の描画部分には何も変化がなかったのですが、3Dモデルを作成してからモデルを回転したりするときに使用するロジックの様です。でわまた次回。。。