Aug 28, 2007 - .NET Framework 3.5のWPF
Tech・Edで川西さんのセッションに .NET Framework 3.5でのWPFの拡張の説明がありました。 この中のUIElement3Dって、もしかして3Dでボタンなどの部品を表示出来るのか!?と思ったのですが、 WPF3D Team Blogによるとそうではありませんでした。
3Dでボタンなどの部品を表示するときは、Viewport2DVisual3Dというクラスを使います。 使い方はModelVisual3Dと同様で、Visualプロパティにボタンやパネルなどを指定します。
from wpf import *
from System.Windows.Media.Media3D import *
from System.Windows.Media.Imaging import *
import math
rotX = lambda x: AxisAngleRotation3D( Vector3D( 1, 0, 0 ), x )
rotY = lambda x: AxisAngleRotation3D( Vector3D( 0, 1, 0 ), x )
rotZ = lambda x: AxisAngleRotation3D( Vector3D( 0, 0, 1 ), x )
class Control3D(Window):
def __init__( self, cx, rot, bg, fov=40, transparent=True, **keywords ):
self.canvas = Canvas( Width=cx, Height=cx, Background=bg )
self.rotation = rot
# ウィンドウの初期処理
Window.__init__( self, **keywords )
self.Width = self.Height = cx * 2
if transparent:
self.WindowStyle = WindowStyle.None
self.Background = Brushes.Transparent
self.AllowsTransparency = True
# 3Dビューの初期化
view = Viewport3D()
view.ClipToBounds = False
view.Camera = self.__getCamera( fov )
view.Children.Add( ModelVisual3D( Content=AmbientLight( Colors.White ) ) )
view.Children.Add( self.__getModel() )
self.Content = view
# カメラ設定の取得
def __getCamera( self, fov ):
cam = PerspectiveCamera( LookDirection=Vector3D(0,0,-1), UpDirection=Vector3D(0,1,0) )
cam.Position = Point3D( 0, 0, 1 + 1/math.tan(math.radians(fov)*.5) )
cam.FieldOfView = fov
cam.NearPlaneDistance = 0.5
cam.FarPlaneDistance = 100
return cam
# 物体の取得
def __getModel( self ):
material = DiffuseMaterial( Color=Color.FromArgb( 255,255,255,255 ) )
geometry = MeshGeometry3D()
for (x,y,z) in ((-1,1,0), (-1,-1,0), (1,-1,0), (1,1,0)):
geometry.Positions.Add( Point3D( x, y, z ) )
for i in (0, 1, 2, 0, 2, 3):
geometry.TriangleIndices.Add( i )
for (x,y) in ((0,0), (0,1), (1,1), (1,0)):
geometry.TextureCoordinates.Add( Point( x, y ) )
model = Viewport2DVisual3D( Material=material, Geometry=geometry )
model.Transform = RotateTransform3D( self.rotation )
model.SetIsVisualHostMaterial( material, True )
model.Visual = self.canvas
return model
# ウィンドウのドラッグ処理
def OnMouseLeftButtonDown( self, *args ):
self.DragMove()
# Canvasに要素を追加
def add( self, el, x, y ):
Canvas.SetLeft( el, x )
Canvas.SetTop( el, y )
self.canvas.Children.Add( el )
上記ソースを「control3d.py」という名前で保存してください。 ちなみに、↑でimportしているwpf.pyは私が独自に作ったモジュールです。
コマンドプロンプトでipy.exeを実行し、対話操作で次のようにコマンドを入力すると、スクリーンショットのような画面ができます。win.rotation.Angleプロパティの値を変えると、パネルの向きが変わります。
>>> from control3d import * >>> win = Control3D( 250, rotY(60), Brushes.Green ) >>> win.Show() >>> win.add( Label( Content='テキストを入力してください(_T):' ), 10, 0 ) >>> win.add( TextBox( Width=230, Height=200, AcceptsReturn=True ), 10, 20 ) >>> win.add( Button( Content='OK' ), 220, 220 ) >>> win.rotation.Angle=45
Perforatorで確認したところ、.NET 3.5であるにも関わらず、Windows XPの場合レイヤーウィンドウはソフトウェアレンダリングしていました。Vistaではちゃんとハードウェアでレンダリングされます。