Các đối tượng MeshGeometry3D định nghĩa hình học của hình vẽ. Bạn cần xác định màu cho bề mặt của đối tượng. Đối với công việc này bạn sử dụng một đối tượng DiffuseMaterial.
Lớp DiffuseMaterial là nhằm cung cấp các Brush, xác định các giá trị màu của Brush, bạn sẽ thiết lập thuộc tính Brush của DiffuseMaterial với một trong những thuộc tính chỉ đọc
tĩnh của lớp Brushes:
<DiffuseMaterial Brush="Cyan" />
Các MeshGeometry3D và hai đối tượng Material thuộc GeometryModel3D, trong đó có
ba tính chất thiết yếu: Các Geometry là thuộc tính của MeshGeometry3D, cịn Material và
BackMaterial tơ màu cho mặt trước và mặt sau của các đối tượng. <GeometryModel3D> <GeometryModel3D.Geometry> <MeshGeometry3D Positions = "0 0 0, 0 1 -1, 0 0 -2" TriangleIndices = "0 1 2" /> </ GeometryModel3D.Geometry> <GeometryModel3D.Material>
Trang 31 <DiffuseMaterial Brush="Cyan"/> </ GeometryModel3D.Material> <GeometryModel3D.BackMaterial> <DiffuseMaterial Brush="Red"/> </ GeometryModel3D.BackMaterial> </ GeometryModel3D>
Trang 32
Ch ng 2: PHÉP BI N Đ I HÌNH VÀ HÌNH NH Đ NG
1. Hình nhđ ng
WPF có một hệ thống hỗ trợ hình ảnh động đa năng chủ yếu được xác định trong namespase
System.Windows.Media.Animation và truy cập thuận tiện nhất trong XAML bất cứ khi nào có thể, có thể bạn sẽ muốn sử dụng một trong nhiều lớp lấy ra từ AnimationTimeline để xác
định hình ảnh động đơn giản.
Hình ảnh động trong WPF xuất phát từ lớp AnimationTimeline trong namespase
System.Windows.Media.Animation. Các lớp này cho phép động những thuộc tính trong lớp
3D. Các thuộc tính sau cho phép động:
Point3D (thuộc tính Position của ProjectionCamera).
Vector3D (thuộc tính LookDirection và UpDirection của ProjectionCamera, hoặc thuộc tính Direction của DirectionalLight).
Double (thuộc tính FieldOfView của PerspectiveCamera hoặc thuộc tính Width
của OrthographicCamera).
Ví dụ sau sẽ cho thấy làm thế nào đểđộng thuộc tính Position: BackAndForth1.xaml
<!-- ================================================ BackAndForth1.xaml (c) 2007 by Charles Petzold ================================================ -->
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
WindowTitle="Back and Forth #1" Title="Back and Forth #1"> <Viewport3D> <ModelVisual3D> <ModelVisual3D.Content> <Model3DGroup> <GeometryModel3D> <GeometryModel3D.Geometry>
<!-- Unit cube: front, back, left,
right, top, bottom. --> <MeshGeometry3D
Positions="-0.5 0.5 0.5, 0.5 0.5 0.5, -0.5 -0.5 0.5, 0.5 -0.5 0.5, 0.5 0.5 -0.5,-0.5 0.5 -0.5, 0.5 -0.5 -0.5,-0.5 -0.5 -0.5,
Trang 33 -0.5 0.5 -0.5,-0.5 0.5 0.5, -0.5 -0.5 -0.5,-0.5 -0.5 0.5, 0.5 0.5 0.5, 0.5 0.5 -0.5, 0.5 -0.5 0.5, 0.5 -0.5 -0.5, -0.5 0.5 -0.5, 0.5 0.5 -0.5, -0.5 0.5 0.5, 0.5 0.5 0.5, 0.5 -0.5 -0.5,-0.5 -0.5 -0.5, 0.5 -0.5 0.5,-0.5 -0.5 0.5" TriangleIndices=" 0 2 1, 1 2 3 4 6 5, 5 6 7, 8 10 9, 9 10 11, 12 14 13, 13 14 15 16 18 17, 17 18 19 20 22 21, 21 22 23" /> </GeometryModel3D.Geometry> <GeometryModel3D.Material> <DiffuseMaterial Brush="Cyan" /> </GeometryModel3D.Material> </GeometryModel3D> <!-- Light sources. --> <AmbientLight Color="#404040" />
<DirectionalLight Color="#C0C0C0" Direction="2 -3 -1" /> </Model3DGroup> </ModelVisual3D.Content> </ModelVisual3D> <Viewport3D.Camera> <PerspectiveCamera x:Name="cam" Position="0 1 6" LookDirection="0 -1 -6" UpDirection="0 1 0" FieldOfView="45" /> </Viewport3D.Camera> </Viewport3D> <!-- Animation. --> <Page.Triggers> <EventTrigger RoutedEvent="Page.Loaded"> <BeginStoryboard>
<Storyboard TargetName="cam" TargetProperty="Position"> <Point3DAnimation From="-2 1 6" To="2 1 6"
Duration="0:0:2" AutoReverse="True" RepeatBehavior="Forever" /> </Storyboard> </BeginStoryboard> </EventTrigger> </Page.Triggers> </Page>
Trang 34
PerspectiveCamera được đặt tên là "cam" để nó có thể sử dụng trong Animation.
Animation được định nghĩa dưới cùng của file XAML. Nó được kích hoạt b i sự kiện Loaded
của lớp Page, mà xảy ra khi trang được chạy và kết xuất trên màn hình. Các thuộc tính mục tiêu
của Animation là Position, Position là thuộc tính của loại Point3D. Các lớp
Point3DAnimation thay đổi vị trí từ (-2, 1, 6) đến (2, 1, 6) trong hai giây, và sau đó đảo ngược hình ảnh động và lặp đi lặp lại mãi mãi hoặc cho đến khi tắt ứng dụng.
Sự thay đổi Position của camera từ (-2, 1, 6) đến (2, 1, 6) làm cho khối lập phương di chuyển từ bên phải sang bên trái của Viewport3D. Rất khó xác định xem những con số hay máy
ảnh thực sự di chuyển.
Bạn cũng có thể động với thuộc tính Direction của DirectionalLight, với một thuộc tính Vector3D. Các file XAML sau sẽ mơ phỏng bình minh và hồng hơn trên một hình lâ ̣p phương vng:
SunriseSunset.xaml
<!-- ================================================ SunriseSunset.xaml (c) 2007 by Charles Petzold ================================================ --> <Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" WindowTitle="Sunrise/Sunset" Title="Sunrise/Sunset"> <Viewport3D> <ModelVisual3D> <ModelVisual3D.Content> <Model3DGroup> <GeometryModel3D> <GeometryModel3D.Geometry> <!-- Square cuboid. --> <MeshGeometry3D Positions="0 1 0, 0 0 0, 1 1 0, 1 0 0, 0 1 -4, 0 0 -4, 0 1 0, 0 0 0, 1 1 -4, 0 1 -4, 1 1 0, 0 1 0, 1 1 0, 1 0 0, 1 1 -4, 1 0 -4, 1 0 0, 0 0 0, 1 0 -4, 0 0 -4, 1 1 -4, 1 0 -4, 0 1 -4, 0 0 -4" TriangleIndices=" 0 1 2, 1 3 2, 4 5 6, 5 7 6, 8 9 10, 9 11 10, 12 13 14, 13 15 14, 16 17 18, 17 19 18, 20 21 22, 21 23 22" /> </GeometryModel3D.Geometry> <GeometryModel3D.Material>
Trang 35 <DiffuseMaterial Brush="Cyan" /> </GeometryModel3D.Material> </GeometryModel3D> <!-- Light. --> <DirectionalLight x:Name="light" /> </Model3DGroup> </ModelVisual3D.Content> </ModelVisual3D> <!-- Camera. --> <Viewport3D.Camera> <PerspectiveCamera Position="-2 2 4" LookDirection="2 -1 -4" UpDirection="0 1 0" FieldOfView="45" /> </Viewport3D.Camera> </Viewport3D> <!-- Animations. --> <Page.Triggers> <EventTrigger RoutedEvent="Page.Loaded"> <BeginStoryboard> <Storyboard TargetName="light"> <Vector3DAnimationUsingKeyFrames Storyboard.TargetProperty="Direction"> <LinearVector3DKeyFrame KeyTime="0:0:0" Value="2 0 -1"/>
<LinearVector3DKeyFrame KeyTime="0:0:10" Value="0 -1 0"/> <LinearVector3DKeyFrame KeyTime="0:0:20" Value=" -2 0 -1"/> </Vector3DAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames
Storyboard.TargetProperty="Color"> <LinearColorKeyFrame KeyTime="0:0:0" Value="Black" />
<LinearColorKeyFrame KeyTime="0:0:3" Value="White" /> <LinearColorKeyFrame KeyTime="0:0:17" Value="White" /> <LinearColorKeyFrame KeyTime="0:0:20" Value="Black" /> </ColorAnimationUsingKeyFrames> </Storyboard> </BeginStoryboard> </EventTrigger> </Page.Triggers> </Page>
Hình ảnh động kéo dài 20 giây và không lặp lại. Các đối tượng
Vector3DAnimationUsingKeyFrames động với thuộc tính Direction của
DirectionalLight, DirectionalLight bắt đầu từ (2, 0, -1) mô phỏng ánh sáng trên đư ng chân tr i, đến điểm (0, -1, 0) ánh sáng đi thẳng xuống, và sau đó đến điểm (-2, 0, -1) là hình ảnh
Trang 36
Một phép động hình ảnh thứ hai là Color . DirectionalLight, đi từđen sang trắng trong
ba giây đầu tiên, và sau đó từ trắng đến đen trong ba giây cuối cùng.
2. Phép bi n đ i hình
Biến đổi là một phương pháp tiếp cận tổng quát và có hệ thống để sửa đổi. Một biến đổi về cơ
bản là một cơng thức tốn học áp dụng cho mỗi điểm trong một bộ sưu tập, chẳng hạn như bộ sưu
tập Positions của một đối tượng MeshGeometry3D. Những điểm thực tế trong bộ sưu tập
Positions không thay đổi, nhưng những này điểm được sử dụng để làm phép biến đổi cho đối
tượng.
Khi bạn sử dụng bản Windows Win32 API cho chương trình đồ họa hai chiều, các đồ họa chuyển đổi là đặc điểm của bối cảnh thiết bị, trong đó chủ yếu là đại diện cho một bề mặt hiển thị
như màn hình. Tất cả các đối tượng được vẽ trên thiết bị này chịu sự biến đổi có hiệu lực tại th i
điểm đối tượng đã được vẽ. Tương tự như vậy, trong Windows Forms, các biến đổi là một thuộc tính của lớp Graphics, đó là đóng gói của một bề mặt vẽ.
Trong WPF phép biến đổi luôn áp dụng cho các đối tượng hơn là với bề mặt vẽ. Nói cách khác, bạn khơng làm bất cứ điều gì Viewport3D để thiết lập biến đổi 3D. Đây có thể là một lo
ngại vì Viewport3D có thuộc tính RenderTransform và LayoutTransform của Transform.
Nhưng Viewport3D thừa hư ng những thuộc tính từ FrameworkElement. Đây là những biến
đổi hai chiều của loại Transform và điều chỉnh vị trí, kích thước, và vịng quay của
Viewport3D.
Đối với biến đổi ba chiều, bạn sử dụng các lớp lấy từ các lớp Transform3D trừu tượng. Chính xác ba lớp trong namespase System.Windows.Media.Media3D xác định tính chất chuyển đổi của loại Transform3D:
Camera.
Model3D.
ModelVisual3D.
Camera là lớp trừu tượng cho tất cả các lớp camera, bao gồm cả PerspectiveCamera và
Trang 37
Model3D là lớp trừu tượng của các lớp GeometryModel3D, Light, và Model3DGroup.
Các thuộc tính Transform cho phép bạn áp dụng một biến đổi đến một con số duy nhất hoặc nguồn ánh sáng, cũng như một bộsưu tập của các đối tượng Model3D.
ModelVisual3D là lớp chỉ xuất phát từ lớp Visual3D trừu tượng. Bằng cách thiết lập thuộc tính Transform của ModelVisual3D, bạn có thể áp dụng biến đổi mọi thứ trong
ModelVisual3D, có thể là một con số duy nhất, một tập hợp các số liệu, hoặc con số cùng với
các nguồn ánh sáng, và cũng có thể bao gồm các đối tượng con của ModelVisual3D. Lớp Transform3D hiện trong hệ thống cấp bậc các lớp sau:
Object
DispatcherObject (abstract) DependencyObject Freezable (abstract) Animatable (abstract) Transform3D(abstract) AffineTransform3D (abstract) TranslateTransform3D (sealed) ScaleTransform3D (sealed) RotateTransform3D (sealed) MatrixTransform3D (sealed) Transform3DGroup(sealed) Trong chương này chúng ta sẽđi vào bốn loại biến đổi:
Tên thu c tính Ho t đ ng
TranlateTransform3D Di chuyển vị trí của một vật thể
ScaleTransform3D Thay đổi kích thước của một vật thể
RotateTrasform3D Xoay vật thể xung quanh một trục MatrixTransform3D Biến đổi đối tượng bằng một ma trận
Trang 38
2.1. Phép d ch chuy n (TranslateTranform3D)
TranslateTransform3D là loại chuyển đổi mà đơn giản chỉ là di chuyển một vật thể vào một vị trí khác mà khơng thay đổi kích thước hoặc định hướng của nó. Lớp
TranslateTransform3D định nghĩa ba thuộc tính của loại double với giá trị mặc định là 0:
OffsetX, OffsetY, và OffsetZ. Bạn có thể áp dụng một TranslateTransform3D cho một yếu tố GeometryModel3D.
<GeometryModel3D> …
<GeometryModel3D.Transform>
<TranslateTransform3D OffsetX="2" OffsetY="0" OffsetZ=" -1" /;> </GeometryModel3D.Transform>
</GeometryModel3D>
Các con số được mô tả b i các GeometryModel3D là có hiệu quả nếu như khi bạn thêm vào tọa độ X là 2 và tọa độ Z là -1 của tất cả các điểm trong bộ sưu tập Positions của
MeshGeometry3D gắn liền với hình vẽ.
Nói chung, biến đổi một tính tốn một điểm (x', y', z') từ một điểm (x, y, z). Lớp
TranslateTranform3Dliên quan đến cơng thức sau:
Trang 39
Chương trình TranslateTransformExperimenter.xaml cho phép bạn thử nghiệm với
TranslateTransform3D. Chương trình vẽ ra một vật thể nối giữa các đoạn thẳng đơn giản như
hình sau:
Hình 2.1-2: Hình ảnh được vẽ bằng cách nói các đoạn thẳng.
Nó là một đơn vịcao, hai đơn vị rộng, và ba đơn vị sâu. Góc bên trái phía trước là gốc.
Chương trình có ba thanh trượt trên đầu trang để thay đổi OffsetX, OffsetY, và OffsetZ
thuộc tính của một TranslateTransform3D áp dụng cho GeometryModel3D. Ba thanh cuộn
thay đổi các thuộc tính phía dưới cùng của một TranslateTransform3D áp dụng cho
PerspectiveCamera.
TranslateTransformExperimenter.xaml
<!-- ================================================================= TranslateTransformExperimenter.xaml (c) 2007 by Charles Petzold ================================================================= --> <Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" WindowTitle="TranslateTransform3D Experimenter" Title="TranslateTransform3D Experimenter"> <DockPanel>
<ScrollBar Name="xMod" DockPanel.Dock="Top" Orientation="Horizontal" 1 (0, 0, -3) 5 (2, 1, -3) 4 (2, 1, 0) 3 (2, 0, 0) 2 (0, 0, 0) 6 (2, 0, -3)
Trang 40
Minimum="-5" Maximum="5" Value="0" ToolTip="Model X" />
<ScrollBar Name="yMod" DockPanel.Dock="Top" Orientation="Horizontal"
Minimum="-5" Maximum="5" Value="0" ToolTip="Model Y" />
<ScrollBar Name="zMod" DockPanel.Dock="Top" Orientation="Horizontal"
Minimum="-5" Maximum="5" Value="0" ToolTip="Model Z" />
<ScrollBar Name="zCam" DockPanel.Dock="Bottom" Orientation="Horizontal"
Minimum="-5" Maximum="5" Value="0" ToolTip="Camera Z" />
<ScrollBar Name="yCam" DockPanel.Dock="Bottom" Orientation="Horizontal"
Minimum="-5" Maximum="5" Value="0" ToolTip="Camera Y" />
<ScrollBar Name="xCam" DockPanel.Dock="Bottom" Orientation="Horizontal"
Minimum="-5" Maximum="5" Value="0" ToolTip="Camera X" /> <Viewport3D> <ModelVisual3D> <ModelVisual3D.Content> <Model3DGroup> <GeometryModel3D> <GeometryModel3D.Geometry>
<!-- Front, rear, top, right, bottom. --> <MeshGeometry3D Positions="0 0 0, 2 0 0, 2 1 0, 0 0 -3, 2 0 -3, 2 1 -3, 2 1 -3, 0 0 -3, 2 1 0, 0 0 0, 2 1 0, 2 0 0, 2 1 -3, 2 0 -3, 2 0 0, 0 0 0, 2 0 -3, 0 0 -3" TriangleIndices=" 0 1 2, 3 5 4, 6 7 8, 7 9 8, 10 11 12, 11 13 12, 14 15 16, 15 17 16" /> </GeometryModel3D.Geometry> <GeometryModel3D.Material> <DiffuseMaterial Brush="Cyan" /> </GeometryModel3D.Material> <GeometryModel3D.Transform> <Transform3DGroup> <TranslateTransform3D OffsetX="{Binding ElementName=xMod, Path=Value}" OffsetY="{Binding ElementName=yMod, Path=Value}" OffsetZ="{Binding ElementName=zMod, Path=Value}" /> </Transform3DGroup> </GeometryModel3D.Transform> </GeometryModel3D> <!-- Light sources. -->
Trang 41
<AmbientLight Color="#404040" />
<DirectionalLight Color="#C0C0C0" Direction="2 -3 -1"> <DirectionalLight.Transform>
<Transform3DGroup>
<!-- Placeholder for light transform. --> </Transform3DGroup>
</DirectionalLight.Transform> </DirectionalLight>
<Model3DGroup.Transform> <Transform3DGroup>
<!-- Placeholder for group transform. --> </Transform3DGroup> </Model3DGroup.Transform> </Model3DGroup> </ModelVisual3D.Content> <ModelVisual3D.Transform> <Transform3DGroup>
<!-- Placeholder for visual transform. --> </Transform3DGroup> </ModelVisual3D.Transform> </ModelVisual3D> <!-- Camera. --> <Viewport3D.Camera> <PerspectiveCamera Position="-2 2 4" LookDirection="2 -1 -4" UpDirection="0 1 0" FieldOfView="45"> <PerspectiveCamera.Transform> <Transform3DGroup> <TranslateTransform3D OffsetX="{Binding ElementName=xCam, Path=Value}" OffsetY="{Binding ElementName=yCam, Path=Value}" OffsetZ="{Binding ElementName=zCam, Path=Value}" /> </Transform3DGroup> </PerspectiveCamera.Transform> </PerspectiveCamera> </Viewport3D.Camera> </Viewport3D> </DockPanel> </Page>
Viewport3D đây là trung tâm của một DockPanel. phía trên là ba ScrollBar điều khiển, và dưới ba ScrollBar về độ sâu của vật thể. Sáu ScrollBar đều có khoảng từ -5 đến 5. Ba ScrollBar đầu trang có tên "xMod", "yMod", và "zMod", chuyển đổi về GeometryModel3D:
<GeometryModel3D.Transform> <Transform3DGroup>
Trang 42
<TranslateTransform3D
OffsetX="{Binding ElementName=xMod, Path=Value}" OffsetY="{Binding ElementName=yMod, Path=Value}" OffsetZ="{Binding ElementName=zMod, Path=Value}" /> </Transform3DGroup>
</GeometryModel3D.Transform>
TranslateTransform3D gồm có OffsetX, OffsetY, và OffsetZ thuộc tính của nó thiết lập để gán dữ liệu giá trị gia tăng của ba ScrollBar đầu trang. Một biến đổi áp dụng cho một
GeometryModel3D ảnh hư ng đến tất cảcác điểm trong bộsưu tập Positions được xác định b i MeshGeometry3D. Khi bạn di chuyển ScrollBar trên cùng về bên phải, sẽ biến đổi vật thể
về bên phải dọc theo trục X. Bạn cũng có thể thiết lập giá trị âm để OffsetX bằng cách di chuyển thanh cuộn về bên trái. Tương tự như vậy, các giá trị dương của OffsetY di chuyển vật thể lên, và các giá trịdương của OffsetZ di chuyển con số gần hơn về phía ngư i xem.
Các thanh cuộn dưới cùng của trang được liên kết với một TranslateTransform3D áp dụng cho Camera:
<PerspectiveCamera.Transform> <Transform3DGroup>
<TranslateTransform3D
OffsetX="{Binding ElementName=xCam, Path=Value}" OffsetY="{Binding ElementName=yCam, Path=Value}" OffsetZ="{Binding ElementName=zCam, Path=Value}" /> </Transform3DGroup>
</PerspectiveCamera.Transform>
Biến đổi này ảnh hư ng đến các thuộc tính Position của máy ảnh. Khi bạn di chuyển thanh cuộn đầu của ba thanh cuộn phía dưới sang bên phải, máy ảnh này sẽ di chuyển sang phải và con số này dư ng như di chuyển sang trái. Nói chung, một biến đổi áp dụng cho một máy ảnh thực
hiện kết quả nghịch đảo của so với một biến đổi áp dụng cho một vật thể 3D.
2.2. Phép bi n đ i kích th c (ScaleTransform3D)
ScaleTransform3D này làm cho một vật thể lớn hơn hoặc nhỏ hơn bằng cách nhân X, Y, và Z của nó tọa độ thuộc tính được đặt tên ScaleX, ScaleY, và ScaleZ, tất cả đều có giá trị mặc
định là 1. Dưới đây là cách ScaleTransform3D có thể xuất hiện trong XAML để biến đổi một
GeometryModel3D: <GeometryModel3D> …
Trang 43
<ScaleTransform3D ScaleX="3" ScaleY="1" ScaleZ="2" /> </GeometryModel3D.Transform>
</GeometryModel3D>
Vật thể này được m rộng kích thước theo trục X là 3 và tăng gấp đơi kích thước dọc theo trục Z. Thuộc tính ScaleY thiết lập giá trị mặc định của nó và có thể được gỡ bỏ. Cách thức chuyển đổi công thức là:
′ = �� � ∗
′ = �� � ∗
′ = �� � ∗
Tuy nhiên, đây không phải là cơng thức thay đổi kích thước hồn chỉnh. Bạn có thể thay đổi
kích thước bằng cách thay đổi ba thuộc tính của ScaleTransform3D tên CenterX, CenterY,
và CenterZ, tất cảđều có giá trị mặc định là 0. Cách thức chuyển đổi bằng các công thức: ′ =�� � ∗ − � � +� �
′= �� � ∗ − � � +� � ′ =�� � ∗ − � � + � �
Hãy lấy một ví dụ: Giả sử một đối tượng 3D có các giá trị X khoảng từ0 đến 2. Nếu ScaleX là 2, các giá trị này sẽ chuyển đổi khoảng từ 0 đến 4. Nhưng nếu CenterX được thiết lập là 1, X
ban đầu giá trị 0 là giảm đi b i 1 để được -1, sau đó nhân với 2 để được -2, và sau đó CenterX được thêm vào là -1. Giá trị X của 2 là giảm đi b i CenterX được 1, nhân với 2 được 2, và sau đó được thêm một lần nữa CenterX được 3. Các đối tượng chuyển bây gi kéo dài dọc theo trục X từ -1 đến 3. Nó vẫn cịn tăng gấp đơi kích thước, nhưng đó là một phần của đối tượng trong đó X là giá trị của 1 CenterX.
Bạn có thể thêm trực tiếp các thuộc tính sau đây vào ScaleTransform3D trong file XAML:
CenterX = "1" CenterY = "0,5" CenterZ = "-1,5"
K t h p phép d ch chuy n và phép bi n đ i
Ngư i ta thư ng áp dụng nhiều biến đổi trong cùng một mơ hình hay hình ảnh. Để làm điều này, bạn cần phải xác định các biến đổi để biến đổi trong Transform3DGroup: