はじめに
本連載では、9月16日に株式会社カールよりプレスリリースされた『リッチクライアントCurlで開発した3Dアプリケーション「Curl 3D Gallery」の提供を開始』などでも使用されているCurlでの3次元表現の基礎的な部分について、3回にわたって解説しようと思います(参照:リッチクライアントCurlで開発した3Dアプリケーション「Curl 3D Gallery」の提供を開始・PDF)。
Curlは、標準で3次元グラフィック機能が実装されていますが、上記のようなアプリケーションを構築する場合、3次元グラフィックスに関する知識が必要となるケースも多々あります。紙面の都合上、すべてに関する解説を行うことはできませんが、他にも使えそうなトピック的な部分に絞って連載していく予定です。
Curlの3Dグラフィックス
まずはCurlの3次元グラフィックスについて、簡単に触れておきたいと思います。Curlの3次元表現には3D グラフィックス シーン グラフ パッケージを用います。このパッケージで使用されるクラスの関係をCurlのHelpドキュメントを元にまとめてみますと、
SceneGraphic
Sceneを含むGUIウィジェットです。Sceneの表示に使用されるGraphicのサブクラスであり、画面上には本Graphicを配置します。
Scene
Cameraを内包しており、SceneObjectの管理を行います。
Camera
CameraはSceneの表示方法を決定するクラスで、視点位置や視線方向、投影法、視野などを設定します。
SceneObject
SceneObjectを作成して、Sceneに配置します。SceneObjectには次のようなオブジェクトが用意されています。
- PolygonSet
- Quad
- Triangle
- SceneGroup
複数の面、線または点を描くオブジェクト。多角形から複雑なオブジェクトをモデル化するために使用します。
塗りつぶされた平面四角形。
塗りつぶされた三角形。
SceneObjectをグルーピングするためのオブジェクト。オブジェクトのグループを1つの単位として変換する際に、SceneGroupを使用します。
ではさっそく簡単な例を示したいと思います。以下の図のように、X、Y、Z軸の座標軸を表示するものです。また、SceneGraphicは左ボタンドラッグで回転動作、右ボタンドラッグで拡大・縮小動作が行えるようになっています。本サンプルでは「Reset Camera」ボタンを押下するとカメラを初期状態に戻せるようにしています。
以下が上記サンプルのソースコードになります。最初ということもあり、各行についてコメント形式で補足を書いてあります。
{curl 6.0 applet} || Applet指定 {curl-file-attributes character-encoding = "shift-jis"} || 文字コード指定 {import * from CURL.GRAPHICS.SCENE} || Sceneパッケージのインポート {define-proc public {make-axis-object scale:Distance}:PolygonSet || 座標軸オブジェクト生成処理 let constant scale-f:FloatDistance = scale asa FloatDistance || 引数の座標軸長さの型変換 let object:PolygonSet = {PolygonSet} || PolygonSetの生成 set object.primitive-type = PrimitiveType.lines || レンダリング方法は線分列指定 set object.vertices = || 座標軸の座標を指定 {new {Array-of FloatDistance3d}, {FloatDistance3d 0f(m), 0f(m), 0f(m)}, || X軸 {FloatDistance3d scale-f, 0f(m), 0f(m)}, {FloatDistance3d 0f(m), 0f(m), 0f(m)}, || Y軸 {FloatDistance3d 0f(m), scale-f, 0f(m)}, {FloatDistance3d 0f(m), 0f(m), 0f(m)}, || Z軸 {FloatDistance3d 0f(m), 0f(m), scale-f} } set object.colors = || 座標軸の始点、終点の色指定 {new {Array-of Pixel}, {Pixel.create 1, 0, 0}, || X軸 {Pixel.create 1, 0, 0}, {Pixel.create 0, 1, 0}, || Y軸 {Pixel.create 0, 1, 0}, {Pixel.create 0, 0, 1}, || Z軸 {Pixel.create 0, 0, 1} } set object.opaque-to-intersection? = false || 交点イベントを処理しない {return object} } {value let scene:Scene = {Scene} || Sceneの作成 let camera:Camera = scene.camera || SceneのCameraを取得 let camera-target:Distance3d = {Distance3d 0ft, 0ft, 0ft} || 注視点位置を設定 let camera-position:Distance3d = {Distance3d 5ft, -3ft, 5ft} || 視点位置を設定 let camera-direction:Direction3d = || 視線方向ベクトルを算出 {(camera-target - camera-position).direction} let up:Direction3d = {Direction3d 0, 0, 1} || 視線-上方向ベクトルを設定 {camera.set-orientation-and-position || Cameraに視線情報を設定 camera-direction, up, position = camera-position} set camera.projection = Projection.perspective || Cameraを透視投影法に設定 set camera.near-clipping-plane = 1in || Cameraの近クリップ面を設定 set camera.far-clipping-plane = 20ft || Cameraの遠クリップ面を設定 set camera.field-of-view = 90degrees || Cameraの視野角を設定 {scene.add-object {make-axis-object 1m}} || 座標軸オブジェクトを追加 let scene-graphic:SceneGraphic = || SceneGraphicを生成 {SceneGraphic scene, width=4in, || SceneGraphicの幅を設定 height=4in, || SceneGraphicの高さを設定 background = {FillPattern.get-black} || SceneGraphicの背景を設定 } let reset-camera:CommandButton = || 「Reset Camera」ボタンを生成 {CommandButton label = "Reset Camera", {on Action at b:CommandButton do || ボタン押下時のイベント処理 {camera.set-orientation-and-position || 押下時、Camera情報を元に戻す camera-direction, up, position = camera-position} {scene-graphic.update-drawable} || SceneGraphicを再表示 } } {VBox || 画面上に、 scene-graphic, || SceneGraphicと reset-camera || ボタンを配置 } }
Curlにおける3次元モデルの生成は、以下の3ステップで行います。
- Scene情報を生成し、属性を設定する。
- Sceneに配置するSceneObjectを定義し、Sceneに登録する。
- SceneをSceneGraphicに設定する。
非常に簡単なサンプルではありますが、Curlでの3次元表現の実装イメージがご理解いただけるのでないかと思います。基本はこの3ステップだけであり、ソースコードもほとんどがパラメータの設定関係となっています。
いかがでしょうか? OpenGLなどから比較すると直観的なソースコードになっていると思いませんか?