5
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Kivy Language で3Dテニスコートを描く

Last updated at Posted at 2019-05-31

#はじめに

こんにちは。
テニスのラリーを3Dシミュレーションするツールを実装することをモチベーションに、
Kivy Languageで3Dのテニスコートを描くスクリプトをご紹介します。
申し訳ありませんが、ここではKivy Languageの環境設定の仕方は割愛させていただきますm(_ _)m

https://github.com/kpiorno/kivy3dgui
↑こちらに掲載されているコードを大いに参考にさせていただきました。ありがとうございますm(_ _)m

https://github.com/miyabb/share_tennis_court.git
↑実装で扱うディレクトリはこちらに載せてあります。

#マウスでぐりぐり動かせるテニスコートを描く
##ディレクトリ構造
上記の参考にしたサイトをforkし、構造はほぼ変えずに使っています。
今回紹介するKivy Languageの3Dモデルでは、描きたいオブジェクト(ここではテニスコート)をメッシュという概念を使って設計しています。.objファイル(3Dモデルデータフォーマット)はそのメッシュのリストを記載しているものです。

Tennis/
    ┠ tennis_court.py  #実行するスクリプト
    ┃
    ┠ data/
    ┃    ┠ imgs/  #オブジェクトにコーティングするイメージ画像
    ┃    ┗ obj/   #各オブジェクトのメッシュリスト
    ┃
    ┗ kivy3dgui/  #kivyで3Dを描くためのパッケージ

##出力イメージ
メインスクリプトを実行すると、以下の画像のようなテニスコートをマウスでぐりぐり動かせるものが出力されることが、今回のゴールです。

スクリーンショット 2019-05-16 22.45.02.png

##アプリケーション設計

実行するスクリプト(tennis_court.py)の解釈です。
mainで走らせるアプリケーションクラス Tennis3dAppの中身について見ていきます。

build関数はアプリケーションに表示するオブジェクトの配置や機能を定義する関数です。

この部分では、マウスで視点を動かす機能を付与する際の、カメラの向きや位置情報の初期値(ここでいうユーザからの視点)を設定しています。後に出てくるon_touch_move関数で使われるものです。

tennis_court.py
 
class Tennis3dApp(App):
    
    def build(self):
        #カメラ(視点の向き)
        self.move_camera = True   
        self.cam_distance = 10
        self.super = []
        
        init_dist = []
        rad = 70.0
        azimuth = 0 #0 to 2PI
        polar = 90 #0 to PI
        
        self.m_sx = 0

        x = rad * math.cos(azimuth) * math.sin(polar)                     
        y = rad * math.sin(azimuth) * math.sin(polar)                     
        z = rad * math.cos(polar)

        self.rad = rad
        self.azimuth = azimuth
        self.polar = polar                  

その後に続くlayout3d_strには何やらながーいstringが格納されていますが、ここにはウィンドウ内の空間に設置するオブジェクト(テニスコートの面、ネット、ボール等)の色や配置などの情報が全て書かれています。

Layout3Dが空間全体のレイアウト、その下にあるNodeたちがその空間の中に配置するオブジェクトを表します。今回描いたNodeのオブジェクトは上から順に

  • 手前の壁(Player A)
  • 奥の壁(Player B)
  • ボール
  • ネット
  • テニスコートの面
  • テニスコートのライン

となっています。

tennis_court.py
        self.layout3d_str = '''
                    #:kivy 1.0
                    #: import Layout3D kivy3dgui.layout3d
                    #: import Animation kivy.animation.Animation
                    
                    Layout3D:  #空間の情報。この下は光と影の調節
                        id: board3d
                        #look_at: [0, 0, 10, 0, 0, -20, 0, 1, 0]
                        canvas_size: (1920, 1080)
                        light_position: [-24.5, 150, 100]
                        post_processing: True  

                        shadow_threshold: 0.3 
                        post_processing: True

                        Node:  #手前の壁
                            id: front
                            rotate: (0, 0, 1, 0)     #回転    
                            scale: (1.0, 1.2, 0.8)   #サイズの増減
                            translate: (0, 0, -80)   #移動する向きと大きさ
                            min_light_intensity: 1.0
                            receive_shadows: True                            
                            meshes: ("./data/obj/2dbox.obj",)  
                            Button:
                                id: bottom_floor
                                text: "Player B"
                                font_size: 50
                                background_normal: ''
                                background_color: 0.000 , 0.000 , 0.000, 1.000

                       
                             #######以下省略######
                        '''

Nodeオブジェクトで主にいじることの多い属性について、こちらでの解説と日本語での解釈をまとめます。

Attribute Description 解釈
rotate Angle and x, y, z axis of the rotation matrix 回転角度と回転軸 (θ, x, y, z)
scale x, y, z of scaling matrix スケールの増減 (x, y, z)
translate x, y, z of translation matrix 移動距離と方向(重心を動かす。Defaultは(0, 0, 0)) (x, y, z)
meshes List of meshes (obj only) 形状を定めるobjファイル

build関数の続きです。

tennis_court.py

        layout3d = Builder.load_string(dedent(self.layout3d_str)) #①
        layout3d.bind(on_touch_move = self.on_touch_move) #②    
        self.layout3d = layout3d
        
        instance = GridLayout(cols=2)  #③
        instance.add_widget(self.layout3d)
        self.instance = instance
        
        return self.instance

①では先ほど定義した layout3d(空間のレイアウト)をBuilderでロードし、
②では、マウスで視点を動かす機能をbindで付加しています。
instanceは最終的にアプリケーションクラスが返すインスタンスとなります。

その後にある関数2つ(get_camera_poson_touch_move)はマウスでぐりぐり動かすためのおまじない関数で、参考元を全くいじらずに使ってます。

最後にmainでクラスを呼び出して終わりです。

最後に

Kivyを使ってテニスコートを描くコードを紹介しました。
私自身Kivyの初心者で理解が行き届いていないところもありますが、ほとんど参考元に掲載されているもので描くことができたので、こちらも参考にしていただければと思います。
もっと説明がほしいところ、解釈の仕方が間違っているところ、ありましたらコメントいただきたいですm(_ _)m

参考

5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?