凪瀬 Blog
Programming SHOT BAR

目次

Blog 利用状況
  • 投稿数 - 260
  • 記事 - 0
  • コメント - 48909
  • トラックバック - 192
ニュース
広告
  • Java開発者募集中
  • 経歴不問
  • 腕に自信のある方
  • 富山市内
  • (株)凪瀬アーキテクツ
アクセサリ
  • あわせて読みたい
凪瀬悠輝(なぎせ ゆうき)
  • Java技術者
  • お茶好き。カクテル好き。
  • 所属は(株)凪瀬アーキテクツ
  • Twitter:@nagise

書庫

日記カテゴリ

 

プログラミングの動画を作ろうと思って 試しに作ってみたのが前回のワイヤーフレームのデモ でした。今回はソースコード解説となります。

sample3d.zip (3,997 bytes)

ZIP圧縮してあります。展開するとパッケージinfo.nagise.sample3dに以下の5つのjavaファイルがあります。 なお、ソースの文字コードはUTF-8となっています。

Line.java 29行 613 bytes 直線を表すクラス
Matrix1x3.java 41行 915 bytes 1行3列の行列を表すクラス
Matrix3x3.java 65行 1,518 bytes 3行3列の行列を表すクラス
Sample3D.java 129行 3,308 bytes 起動用のApplet本体
Vertex.java 62行 1,488 bytes 頂点を表すクラス
合計 326行 7,842 bytes  

動画用に書いたソースにコメントなどを足して整形してあります。 この分量で約40分かかりました。早送りしないでプログラミング動画を作る場合、 10分程度の尺におさめようとすれば100行以下の行数である必要があるのではないでしょうか。

座標計算

座標の計算には数学の行列という概念を利用しています。Matrix1x3および、Matrix3x3が該当します。 wikipediaによると行列の教育課程は 高等学校での数学Cでの範囲ですから、理系のコースを取らない人はそもそも習わないことが多いのでしょうね。

(x, y, z)で表される3次元空間での座標は、1行3列(もしくは3行1列)の行列で表現します。この座標に対し、 回転などの変換を3行3列の行列で表現することが出来、行列の掛け算で座標変換を行うことができます。 今回は3次元空間での回転に用いていますが、2次元空間での平面の変形に用いた例が アフィン変換です。

Javaの標準APIでアフィン変換はサポートされていますが、javadocを見ると行列での変換が説明されています。 数学に詳しくない人でも、行列の掛け算で座標変換(回転とか変形とか平行移動とか)ができるんだ、 と覚えておくといざ調べるときに役に立ちます。(そんなことを思い立つかは甚だ疑問ですけどね:-)

数学の行列というと身構えてしまいがちですが、プログラムとは相性がよい。 アルゴリズム的に手順を踏んで計算することが容易 なのでポリゴンなどでの作業計算にはよく用いられます。以下に行列の掛け算を行っている箇所のソースを掲載します。

  public Matrix3x3 mul(Matrix3x3 val) {
    Matrix3x3 ret = new Matrix3x3();
    for (int y=0; y) {
      for (int x=0; x) {
        for (int i=0; i) {
          ret.value[y][x+= this.value[y][i* val.value[i][x];
        }
      }
    }
    return ret;
  }

いかがでしょうか。非常に機械的な手順で計算できることがわかるのではないでしょうか。

頂点の扱い方

座標は行列によって表現していますが、頂点を表すクラスは別途存在します。 これは、変換前の座標と、変換後の座標を持ちたいためです。 今回はワイヤーフレームですが、グローシェーディングとかやる場合は頂点の向きとか さらに情報を足さないといけないので、座標 = 頂点という単純な作りにすると嵌ります。

非オブジェクト指向式にやるのであれば、元になるモデルの座標のListと、 変換後の座標のListを用意してやることになりますね。ソースを短く簡単に済ませたいならばそのほうが楽かもしれません。

座標計算のための行列クラスは出来ていますが、適切なパラメータを与えないと回転はできません。以下が回転・平行移動の処理部分。

  public void calculate(Matrix1x3 offset,
      double rx, double ry, double rz) {
    
    // X軸の回転
    Matrix3x3 mx = new Matrix3x3(
        100,
        0, Math.cos(rx), -Math.sin(rx),
        0, Math.sin(rx), Math.cos(rx));
    // y軸の回転
    Matrix3x3 my = new Matrix3x3(
        Math.cos(ry)0, Math.sin(ry),
        010,
        -Math.sin(ry)0, Math.cos(ry));
    // z軸の回転
    Matrix3x3 mz = new Matrix3x3(
        Math.cos(rz), -Math.sin(rz)0,
        Math.sin(rz), Math.cos(rz)0,
        001);

    // 行列の合成
    Matrix3x3 m33 = mx.mul(my).mul(mz);
    Matrix1x3 m13 = m33.mul(this.point);
    // 平行移動
    this.mapping = m13.add(offset);
  }

sinやcosといった三角関数が並んでいますが、回転変換の際の行列は定型で決まっていますので カンペを用意して計算式をそのまま記載すればOKです。 このように数式をプログラムに落とすのが簡単なのが行列のよいところ。

描画ルーチン

今回はAppletのswing実装であるJAppletクラスを使用しています。 このJAppletにJPanelをaddして、実際の描画はJPanelに行わせます。

  /**
   * 描画用のPanel
   */
  class ExPanel extends JPanel {
    Matrix1x3 offset = new Matrix1x3(1601200);
    // 回転角
    double rx;
    double ry;
    double rz;

    @Override
    protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      for (Vertex v : vlist) {
        v.calculate(this.offset, this.rx, this.ry, this.rz);
        v.paint(g);
      }
      for (Line l : llist) {
        l.paint(g);
      }
    }
  };

(0, 0, 0)を中心とした座標で計算していますから、画面の中央が(0, 0, 0)となるようにオフセットを与えています。 また、現在のモデルの回転角をここに持たせています。 実際の描画はVertexクラスとLineクラスに委譲しますので、ここではループをまわすだけ。

  /**
   * Appletの開始時に呼び出される
   @see java.applet.Applet#start()
   */
  @Override
  public void start() {
    // アニメーション用スレッドの作成
    this.t = new Thread(){
      @Override
      public void run() {
        // 割り込みされるまでループ
        while(!this.isInterrupted()) {
          panel.rx += 0.05;
          panel.ry += 0.07;
          panel.rz += 0.01;
          panel.repaint();
          try {
            Thread.sleep(20);
          catch (InterruptedException e) {
            this.interrupt();
          }
        }
      }
      
    };
    this.t.setDaemon(true);
    this.t.start();
  }

  /**
   * Appletの停止時に呼ばれる
   @see java.applet.Applet#stop()
   */
  @Override
  public void stop() {
    // アニメーションスレッドに割り込んで停止させる
    this.t.interrupt();
  }

Applet#start()をオーバーライドしてアニメーション用のThreadを生成して起動します。 Applet#stop()の際にはThreadが停止するようにThread#interrupt()で割り込みを行います。

世の中のサンプルコードでは簡単のためかThread内でのループをwhile(true)としているケースが多いですが、 作法的には本ソースのようにwhile(!this.isInterrupted())とするほうがよいでしょう。

こうすることで、Thread#sleep()がthrowするInterruptedExceptionの処理が自然に記述できますし、 また、Applet#stop()で行っているように、Threadの外部から停止させる処理が自然に記述できます。 このThreadでは適当に回転させて再描画を行うだけですが、座標変換は描画ルーチン内ではなく、 このThreadで行うべきだったなぁと設計を反省。

終わりに

プログラミングの動画をとる場合、早送りナシで10分程度の尺に納めるには100行程度のプログラムではないと厳しいということが分かりました。
こういったビジュアル的にインパクトのあるデモのほうが受けはよいと思ったのですが、色気を出しすぎましたね。

3Dのプログラムをやりたいという人はこういった自力で回転するようなサンプルを書くとよい勉強になります。 今時はAPIが回転とか面倒くさいところはやってくれるのですが、基礎を疎かにすると後で必ず嵌ることになります。
私の場合は学生の頃に「ライブラリを使わずに自力でポリゴンを書けるなら雇ってあげる」とゲーム業界の人に言われ、 ポリゴンの基礎を独習したのですが、実際のところこういった基礎ができるということは大きな売り文句になりますよ。

投稿日時 : 2007年9月29日 10:59
コメント
  • # xBzkdXtzpYOpD
    http://www.luckyvitamin.com/p-123061-yes-to-carrot
    Posted @ 2012/01/07 13:33
    Heartfelt thanks..!
  • # jpBCEgVNmOTxEnsKFpS
    http://crorkz.com/
    Posted @ 2014/08/04 4:26
    BNqa4q Very neat article.Thanks Again. Much obliged.
  • # 誕生日
    gkcuyafc@hotmail.co.jp
    Posted @ 2021/11/21 22:43
    ブランド激安市場大特価
    当店には、ルイヴィトン、シャネル、グッチ、コーチ、ロレックス、プラダ、 ディオール、ブルガリ財布 その他小物等、
    買う多いです、恵みの多いです、
    一回注文5件以上、贈呈ルイヴィトンキーケース1個
    注文は期待しています。。。
    各種海外有名ブランド品を豊富に取り揃え、しかもお客様を第一と考えて、驚きの低価格で提供しております
    ■スタイルが多い、品質がよい、価格が低い!
    ■ 送料無料(日本全国) ご注文を期待しています!
    ■信用第一、良い品質、低価格は
    ■当社の商品は絶対の自信が御座います。
    激安、安心、安全にお届けします.品数豊富な商
    商品数も大幅に増え、品質も大自信です100%品質保証!
    満足保障!リピーター率100%!
  • # A品コーチ
    xjzvid@docomo.ne.jp
    Posted @ 2021/11/22 1:57
    Sランクほぼ未使用という事で購入しましたが画像にない汚れがありランクとして悪い物だと思いました。
    返品の送料や手数料、手間を考えて今回返品しませんでしたが残念で仕方ありません。
    やはり現物を見ないと信用できないのでもう買いません。
  • # ロレックス チェリーニ クォーツ
    ryircmhs@livedoor.com
    Posted @ 2021/12/20 21:25
    どちらも新品同様のお品で価格は驚きの安さ!
    梱包も過剰でなく丁寧で商品をとても大切にされている気持ちが伝わります。
    手書きのお手紙も入っていて、またお世話になりたいと思いました。
    ロレックス チェリーニ クォーツ https://www.kopijp.com/product/detail.aspx?id=7919
  • # ロレックス 値上げ 2016
    ihvbqzhfu@live.jp
    Posted @ 2022/09/03 14:17
    【祝開店!大放出セール開催中】
    あなたは自由船積みを楽しむことができます
    新品入荷大特価!限定SALE!
    激安専門オンラインストア
    激安 おすすめSALE!
    『2022年春夏新作』5☆大好評!
    SALE賛発売!
    【正規品!】☆安心の全品国内発送!
    人気【新品】店里最受迎!
    業界最高峰!全国一律送料無料!
    最良の取引店へようこそ
    お急ぎ便利用で当日、翌日にお届け。
    【送料無料市場】今季★大特恵
    『上品な』激安本物
    オフ75%安いが貯まる!
    ロレックス 値上げ 2016 https://www.gmt78.com/product/detail/13262.htm
  • # ロレックス 中古 群馬
    freztr@hotmail.co.jp
    Posted @ 2022/09/03 14:21
    ダイヤモンドリングを購入しました。その直後にこんなメールが。
    > こんばんは、プレミアです。
    >
    > 大変申し訳ございませんが、 ご注文いただきました下記商品ですが、
    > 目玉品であったため、店頭にて売り切れてしまいました。
    >
    > 誠の勝手ながら、 ご注文は当店サイドのキャンセル扱いとさせて
    > 頂きますことを、ご了承くださいませ。
    >
    > ご迷惑をおかけして、大変申し訳ございませんでした。
    >
    > 今後も、予告なくですが目玉商品等を出品させていただきますので
    > どうぞ宜しくお願い申し上げます。
    一体どういう意味でしょうか?キャンセルとか言っておきながら、まだ9800円で購入出来ますけど?単に販売価格の設定を間違えただけでしょう?何が目玉商品なんでしょうか。苦しい言い訳を書くくらいなら、素直に間違えたと謝罪すべきです。ショップとして信じられない対応です。
    ロレックス 中古 群馬 https://www.kopijp.com/product/detail.aspx?id=11575
  • # ロレックス 時計 box 特大
    sdagtiqtn@ezwen.ne.jp
    Posted @ 2022/09/17 1:08
    ロレックス 時計 デイトナ
    弊店は経済的、魅力的、機能的な時計を揃える時計の通販ネットショップです。
    弊店成立以来、お客様に安心と信頼、自分に信用第一を目標としてずっと頑張っています。ロレックス 人気 ランキング ボーイズ,ロレックス 時計 デイトナ,ロレックス ブログは独自の合金で、特有の光沢と高貴な雰囲気を醸している。
    静寂と活力、冷静さと大胆さの融合は圧倒的な魅力を発揮し、強い個性を時計にもたらしている。
    広大愛好者簡単に手に入るために当店は全ての商品が最安値に挑戦します。珍しいのでこのチャンスを見逃さないでください?
    ロレックス 時計 box 特大 https://www.2bcopy.com/product/product.aspx-id=2338.htm
  • # ロレックス 時計 バンド
    kaeipzdqlyl@docomo.ne.jp
    Posted @ 2022/09/17 1:13
    急ぎではなかったのですが、素早いご対応ありがとうございます。
    丁寧に梱包されていて、手書きのお手紙も入っていました。
    配送がゆうパックのみ、というのも個人的には気に入りました。
    ロレックス 時計 バンド https://www.gmt78.com/product/detail/3686.htm
  • # レビューが遅くなってしまい、申し訳ございません。ショップの方の対応もよく、梱包も丁寧にしていただきました。型崩れしないように、バッグの中にも詰め物をしてくださっていて、とても嬉しかったです。また機会がありましたら、是非利用させていただきたいと思います。どうもありがとうございました。
    ivksmkva@live.jp
    Posted @ 2022/10/12 19:03
    2022年人気の商品を超えて、当店が売買する中.
    すべての商品はすべて新しく着きます.
    すべての商品の品質がすべて検査するのが合格です.
    みんなを歓迎して選り取りで買います.
    ■主要取扱商品 バッグ、財布、腕時計、マフラー!
    ○ スタイルが多い、品質がよい、価格が低い!
    ○ S品質 シリアル付きも有り 付属品完備!
    ○必ずご満足頂ける品質の商品のみ販売しております.

    品質の承諾:
    ◆入金の後で3-7日高い府に到着する
    ◆もし、税関に止まられた場合、再びに無料で再送いたします。到着してまで。
    当社の商品は絶対の自信が御座います。
    S品質 シリアル付きも有り 付属品完備!
    レビューが遅くなってしまい、申し訳ございません。ショップの方の対応もよく、梱包も丁寧にしていただきました。型崩れしないように、バッグの中にも詰め物をしてくださっていて、とても嬉しかったです。また機会がありましたら、是非利用させていただきたいと思います。どうもありがとうございました。 https://www.gooshop001.com/product/detail/11803.htm
  • # ロレックス 偽物 オーバーホール
    gywdgcttr@ocn.ne.jp
    Posted @ 2022/11/22 3:36
    超人気【楽天市場】
    高品質とリーズナブルで販売
    超安値登場!品質保証、最安値に挑戦!
    オンラインストアオファー激安輸出
    オンラインストアは、ご来店ありがとうございます.
    【超人気新品】即日発送,品質100%保証!
    【新商品!】☆安心の全品国内発送!
    激安通販!☆安心の全品国内発送!
    激安全国送料無料!100%正規品!
    激安販売中!
    高品質と最高の専門の顧客サービスと
    手頃な価格でお好きなもの
    芸能人愛用『大注目』
    今、私たちは安価な高級品海外通販しています。
    私たちは、デザイナーの多数な選択を運ぶ
タイトル
名前
Url
コメント