Bạn có thể cộng và trừ số phức bằng cách đơn giản là cộng và trừ hai phần tương ứng phần thực và phần ảo với nhau.
M rộng số phức ra không gian ba chiều với ba vector đơn vị i, j, k với i = (1, 0 , 0), j = (0, 1,
0), k = (0, 0, 1). Và phép nhân vector như sau: i x j = k = - j x i
j x k = i = -k x j k x i = j = - i x k
Tốn Qua tec non có qui tắc nhân tương tự, tuy nhiên, trong phép nhân quaternion thì một
vector nhân với chính nó bằng -1. Và tổng của một qua tec non là tổng của một số thực cộng với ba con số ảo:
q = a + bi + cj + dk
Từ đó ta xác định được cấu trúc của một quaternion. Trong namespace
System.Windows.Media.Media3D thì các thuộc tính có tên là w, x, y, z và q được xác định như sau:
q = w + xi + yj + zk
Bạn có thể khai báo một quaternion như sau:
Trang 55
Quaternion là phép biến đổi phức tạp nhất, để tính tốn quaternion của một vịng quay vector
trục và các góc quay, vectơ trục phải là vector bình thư ng. Bạn có thể tính tốn quaternion thành
phần từ một đơn vị trục quay và góc quay. Giả sử trục quay cho một vòng quay 3D được ký hiệu là một đơn vị Vector3D đối tượng (ax, ay, az) và góc quay là θ. Bạn có thể tìm thấy những
quaternion gồm có 4 giá trị (x, y, z, w) bằng cách sử dụng công thức sau:
x = ax.sin(θ/2) y = ay.sin(θ/2) z = az.sin(θ/2) w = cos(θ/2)
Cấu trúc toán qua tec non bao gồm một constructor tạo ra một toán quaternion quay từ một trục quay và một góc:
Quaternion qRotate = new Quaternion(vectAxis, angle);
Lớp RotateTransform3D định nghĩa một thuộc tính có tên Rotation mà được thiết lập
cho một đối tượng của loại Rotation3D, và là một lớp trừu tượng cho AxisAngleRotation3D và QuaternionRotation3D. QuaternionRotation3D có một thuộc tính duy nhất có tên Quaternion của loại Quaternion. Trong XAML, nó được mơ tả như sau:
<RotateTransform3D>
<RotateTransform3D.Rotation>
<QuaternionRotation3D Quaternion="0 0 0.5 0.866" /> </RotateTransform3D.Rotation>
</RotateTransform3D>
Đó là một vịng quay 60 độ quanh trục Z, số 0.5 là sin 30 độ, và 0.866 là cosin của 30 độ.
Trong XAML, w đứng cuối cùng. Bạn có thể tùy chọn chỉ định tâm cho việc luân chuyển trong thẻ RotateTransform3D.
Chương trình sau làm cho hình ảnh động bằng Quaternion dựa vào đối tượng RotateTranform3D: <Window x:Class="Transform1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" mc:Ignorable="d" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup -compatibility/2006" Height="350" Width="524" WindowState="Maximized" >
Trang 56
<Viewport3D>
<Viewport3D.Camera>
<PerspectiveCamera Position="-2 1 4" LookDirection="2 -1 -4" UpDirection="0 1 0" FieldOfView="90"/>
</Viewport3D.Camera> <ModelVisual3D>
<ModelVisual3D.Content> <Model3DGroup>
<DirectionalLight Color="White" Direction="2 -1 0"/> <GeometryModel3D> <GeometryModel3D.Geometry> <MeshGeometry3D Positions="0 1 0, 0 0 0, 1 1 0, 1 0 0, 0 1 -1, 0 0 -1, 0 1 0, 0 0 0, 1 1 -1, 0 1 -1, 1 1 0, 0 1 0, 1 1 0, 1 0 0, 1 1 -1, 1 0 -1, 1 0 0, 0 0 0, 1 0 -1, 0 0 -1, 1 1 -1, 1 0 -1, 0 1 -1, 0 0 -1" 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> <DiffuseMaterial Brush="Cyan"/> </GeometryModel3D.Material> <GeometryModel3D.Transform> <Transform3DGroup> <RotateTransform3D> <RotateTransform3D.Rotation> <QuaternionRotation3D x:Name="qQuaternion"/> </RotateTransform3D.Rotation> </RotateTransform3D> </Transform3DGroup> </GeometryModel3D.Transform> </GeometryModel3D> </Model3DGroup> </ModelVisual3D.Content> </ModelVisual3D> <Viewport3D.Triggers> <EventTrigger RoutedEvent="Viewport3D.Loaded"> <BeginStoryboard> <Storyboard> <QuaternionAnimation Storyboard.TargetName="qQuaternion"
Storyboard.TargetProperty="Quaternion" From="0,0,1,0" To="0.3, 0.3, 1, 0" Duration="0:0:7" />
</Storyboard> </BeginStoryboard> </EventTrigger>
Trang 57
</Viewport3D.Triggers> </Viewport3D>
</Window>
Hình ảnh động dựa vào thuộc tính Rotation của RotateTransform3D.
2.4. Phép bi n đ i bằng ma tr n (MatrixTransform3)
Matrix quan đại diện đóng một vai trị quan trọng trong chuyển đổi và hoạt động trên các đối tượng đồ họa, ma trận là một mảng đa chiều. Tổng 3D biến đổi khá phức tạp, bạn có thể xây dựng một biến đổi với sự kết hợp của các biến đổi cơ bản, bao gồm cả di chuyển vật thể, thay đổi kích thướt và xoay vật thể. Những phần sau đây mô tả những biến đổi cơ bản. Một khi bạn hiểu làm thế nào để sử dụng các chuyển đổi 3D cơ bản, bạn ln có thể kết hợp chúng để tạo ra 3D biến đổi tổng quát hơn.
2.4.1. Đi m vƠ vector 3D
WPF xác định hai điểm cấu trúc 3D, Point3D và Point4D.Point3D xác định tọa độ X, Y, và Z của một điểm trong không gian 3D. Point4D xác định tọa độ X, Y, Z, và W của một điểm trong một 3D đồng nhất.Cơ cấu Vector3D định nghĩa các thành phần X, Yvà Z trong không gian 3D.
Một vectơ trong không gian 3D được đại diện b i một dãy hàng với ba yếu tố X, Y, và Z. Ví dụ, bạn có thể tạo một đối tượng Vector 3D bằng cách sử dụng đoạn mã sau đây:
Vector3D v = new Vector3D (1, 2, 3);
Lưu ý rằng một đối tượng Vector3D và một đối tượng Point3D trong WPF là hai đối tượng khác nhau các đối tượng.
Cách khai báo sau đây là không hợp lệ:
Vector3D v = new Point3D (1, 2, 3);
Tuy nhiên, bạn có thể xác định một đối tượng Vector3D sử dụng Point3D, hoặc ngược lại.
Cách khai báo sau đây là hợp lệ:
Vector3D v1 = new Point3D (2, 3, 4) - new Point3D (1, 2, 3); Vector3D v2 = (Vector3D) new Point3D (1, 2, 3);
Point3D pt = (Point3D) new Vector3D (1, 2, 3);
Có thể chuyển một đối tượng Point3D sang một đối tượng Point4D, như sau:
Trang 58 Hoặc:
Point4D pt4 = (Point4D) (Point3D) new Vector3D (10, 15, 20);
Có đối tượng Vector3D có thể tạo ra một đối tượng Point3D, mà sau đó sẽ tạo đượcmột đối tượng Point4D. Trong quá trình đúc trên, các đối tượng Point4D có giá trị: pt4 = (10, 15, 20, 1). Nó chỉ đơn giản là thêm các thành phần W có giá trị là 1.
2.4.2. C u trúc c a ma tr n 3D
WPF định nghĩa một cấu trúc ma trận 3D, Matrix3D. Đó là một ma trận 4x4 trong mơi trư ng tọa độđồng nhất 3D và có cú pháp vector sau đây:
M11 M12 M13 M14
M21 M22 M23 M24
M31 M32 M33 M34
OffsetX OffsetY OffsetZ M44
Cột cuối cùng, M14, M24, M34 đều có giá trị bằng 0 ,M44 có giá trị bằng 1.
Các giá trị M11, M22, M33 tương ứng với các giá trị ScaleX, ScaleY, ScaleZ của đối tượng
ScaleTransform3D. Các giá trị OffsetX, OffsetY, OffsetZ tương ứng với các giá trị của đối tượng
TranslateTranfrom3D.
Tọa độ của một điểm bao gồm 4 thành phần (x, y, z, w) thay vì chỉ có (x, y, z). Nếu w ≠ 0, ta có thể chuẩn hóa bằng cách chia tọa độ của điểm này cho w để có một tọa độ mới tương đương
(x/w, y/w, z/w, 1), và các con số x/w, y/w, z/w được gọi là tọa độ điểm trong môi trư ng tọa độ đồng nhất. Nếu w = 0, điểm này được xem như nằm ∞. Tọa độ điểm bao gồm 4 thành phần cũng địi hỏi ma trận biến đổi cũng phải có kích thức là 4x4.
Các yếu tố của OffsetX, OffsetY, và OffsetZ nhận và thiết lập giá trị của biến đổi X, Y, và Z.
Các thuộc tính nào khác liên kết với Matrix3Dcấu trúc cũng hữu ích trong việc thực hiện các hoạt động ma trận:
• Determinant - Lấy yếu tố quyết định trong Matrix3D.
• HasInverse - Lấymột giá trị cho biết có phải Matrix3D là ma trậnnghịchđảo.
Trang 59
• IsAffine –Lấymột giá trị cho biết có phải là cấu trúc Matrix3D afin.
• IsIdentity - Xác định xem cơ cấu Matrix3D có thay đổi.
Point3D xác định cấutrúc một đối tượng Point3D sang một đối tượng Point4D, các thuộc
tính X, Y,và Z sẽ chỉ sao chép trực tiếp vào đối tượng Point4D, và các thuộc tính W được thiết lập là 1.Cấu trúc Matrix3D và lớp Tranform3D xác định phương pháp để biến đổi các đối tượng Point4D và phép ma trận như sau:
M11 M12 M13 M14
M21 M22 M23 M24
|x y z w| X = |x’ y’ z’ w’|
M31 M32 M33 M34
OffsetX OffsetY OffsetZ M44
Với:
x′ = M11·x + M21·y + M31·z + OffsetX·w
y′ = M12·x + M22·y + M32·z + OffsetY·w
z′ = M13·x + M23·y + M33·z + OffsetZ·w
w′ = M14·x + M24·y + M34·z + M44·w
Cấu trúc Matrix3D định nghĩa một constructor 16 đối số cho phép bạn chỉ định tất cả các yếu tố của ma trận bắt đầu với dòng đầu tiên. Cấu trúc Matrix3D cũng định nghĩa nhiều phương pháp, cho phép bạn áp dụng các loại biến đổi vào các ma trận, và để biến đổi điểm và vectơ bằng cách sử dụng ma trận.
Trong XAML, lớp Matrix3DConverter được sử dụng phía sau để bạn có thể thiết lập thuộc
tính Matrix của một nguyên tố MatrixTransform3D sử dụng một chuỗi bao gồm nhận dạng
"identity" hoặcthiết lập tất cả 16 giá trị. Ví dụ, biến đổi sau bằng 2 theo hướng X và 3 theo hướng
Z:
<MatrixTransform3D Matrix="2 0 0 0, 0 1 0 0, 0 0 3 0, 0 0 0 1" />
Lớp Transform3D định nghĩa một thuộc tính Value của loại Matrix3D cung cấp các ma trận tương ứng với biến đổi của đối tượng.
Trang 60
2.4.3. Bi n đ i ma tr n
Cơ cấu Matrix3D trong WPF cũng cung cấp các phương pháp để xoay, biến đổi, và dịch chuyển các ma trận. Dưới đây là một số phương pháp thư ng xuyên nhất được sử dụng cho Matrix3D hoạt động:
Scale - Gắn thêm biến đổi Vector3D cho cấu trúc Matrix3D.
ScaleAt – Biến đổicác Matrix3D do Vector3D quy định về các Point3D.
Translate - Gắn thêm một bản dịch của các hiệu số quy định cho hiện tại Matrix3D cấu
trúc.
Rotate - Gắn thêm một biến đổi xoay cho các Matrix3D hiện hành.
RotateAt - Xoay các Matrix3D theo Point3D quy định.
Invert - Đảo ngược cấu trúc Matrix3D.
Multiply - Nhân với các quy định cụ thể các ma trận.
Transform – Biến đổi các Point3D quy định, mảng của các đối tượng Point3D, Point4D, mảng của đối tượng Point4D, Vector3D, hay mảng các đối tượng Vector3D do Matrix3D.
Sử dụng lớp MatrixTransform3D để tạo ra biến đổi khơng sẵn có từ các lớp RotateTransform3D, TranslateTransform3D, và ScaleTransform3D.
Ta có thể nhóm nhiều biến đổi lại trong một Transform3DGroup, nhưng đó là thứ tự của các biến đổi làm cho một sự khác biệt trong kết quả. Tập hợp các biến đổi tương đương với phép nhân ma trận, nhưngthực tế không phải là phép nhân ma trận giao hoán.
Hãy xem một ví dụ của phép nhân ma trận. Giả sử bạn có một biến đổi vật thể mà biến đổi theo hướng X bằng 1.5, theo hướng Y bằng 2, và theo hướng Z bằng 2.5. Một biến đổi chuyển dịch dọc theo trục X bằng 10, trục Y bằng 20, và trục Z bằng 30. Đây là cách bạn có thể đại diện
cho một biến đổi kết hợp trong XAML với biến đổi vật thểđầu tiên:
<Transform3DGroup>
<ScaleTransform3D ScaleX="1.5" ScaleY="2" ScaleZ="2.5" />
<TranslateTransform3D OffsetX="10" OffsetY="20" OffsetZ="30" /> </Transform3DGroup>
Trang 61
Các kết hợp chuyển đổi áp dụng cho các điểm (x, y, z) như sau: 1.5 0 0 0 1 0 0 0 0 2 0 0 0 1 0 0
|x y z 1| x 0 0 2.5 0 x 0 0 1 0 = |x’ y’ z’ 1|
0 0 0 1 10 20 30 1
Ma trận không nhân giao hốn nhưng nó là kết hợp. Bạn có thể bắt đầu bằng cách nhân điểm của ma trận đầu tiên và sau đó nhân kết quả của ma trận thứ hai, hoặc bạn có thể bắt đầu bằng cách nhân hai ma trận với nhau. Đây là những gì bạn nhận được trong trư ng hợp đó:
1.5 0 0 0 0 2 0 0
|x y z 1| x 0 0 2.5 0 = |x’ y’ z’ 1|
10 20 30 1
Nếu ma trận được theo thứ tự ngược lại (dịch chuyển trước và sau đó là biến đổi), kết quả sẽ
là:
1.5 0 0 0
0 2 0 0
|x y z 1| x 0 0 2.5 0 = |x’ y’ z’ 1|
15 40 75 1
Khi có dịch chuyển đầu tiên, cơ bản các yếu tố dịch chuyểncuối cùng nhận được nhân với yếu tố biến đổi.
Nếu bạn định nghĩa một Transform3DGroup có chứa nhiều biến đổi, bạn có thể muốn giữ các biến đổi riêng biệt cho hoạt động hoặc dữ liệu nhằm mục đích ràng buộc. Nhưng cũng có thể bạn tạo các biến đổi trong một Transform3DGroup trong một cách mà có ý nghĩa với bạn. Bạn có thể nhận được một số hiệu quả cải thiện bằng cách thay thế Transform3DGroup với một MatrixTransform3D duy nhất.
Bạn cần phải thực hiện các phép nhân ma trận để xác định ma trận cho MatrixTransform3D.
Trang 62
tính này được thừa kế tất cả các dẫn xuất của Transform3D, bao gồm Transform3DGroup. Bạn có thể truy cập vào thuộc tínhnày trực tiếp trong XAML bằng cách đặt tên cho Transform3DGroup: <Transform3DGroup x:Name="xform">
Sau đó, một nơi khác trong file XAML, bạn có thể tham chiếu các thuộc tính Value của đối tượng với một dữ liệu ràng buộc sau:
<Label Name="lbl" Content="{Binding ElementName=xform, Path=Value}" />
Thuộc tính Content của Label là loại đối tượng, và nếu đối tượng đặt để Content không xuất phát từ UIElement, Label chỉ sử dụng phương pháp ToString để có được một chuỗi biểu diễn của đối tượng. Các phương pháp ToString của Transform3D chuyển đổi Value thành một chuỗi để Label hiển thị 16 số của ma trận kết hợp:
1.5,0,0,0,0,2,0,0,0,0,2.5,0,10,20,30,1
Bạn không thể chọn văn bản này và sao chép nó, mà bạn có thể định nghĩa một ràng buộc từ
Label cho một Text Box:
<TextBox Text="{Binding ElementName=lbl, Path=Content}" />
Bạn có thể khơng ràng buộc TextBox trực tiếp cho Transform3DGroup vì thuộc tính text là
một chuỗi thực sự chứ không phải là một đối tượng với một phương thức ToString. Nhưng với sự trung gian Label bạn có thể chọn văn bản trong TextBox và nhấn Ctrl + C để sao chép. Sau đó bạn có thể thay thế tồn bộ Transform3DGroup với một MatrixTransform3D đơn và dán văn bản vào sự đánh dấu:
<MatrixTransform3D Matrix="1.5,0,0,0,0,2,0,0,0,0,2.5,0,10,20,30,1" />
Trong code, bạn cũng có thể sử dụng một Transform3DGroup nếu bạn muốn giữ các từng biến đổi riêng biệt cho dữ liệu biến đổi hoặc các mục đích ràng buộc. Nếu bạn chỉ muốn tạo ra một biến đổi kết hợp, bạn có thể sử dụng các phương pháp trong cơ cấu Matrix3D:
Matrix3D matx = new Matrix3D();
matx.Scale(new Vector3D(1.5, 2, 2.5)); matx.Translate(new Vector3D(10, 20, 30));
Sau khi bạn đã hoàn tất một biến đổi trong đối tượng Matrix3D bạn có thể đặt các đối tượng
Trang 63
Đối với mỗi phương pháp như biến đổi và dịch chuyển, cấu trúc Matrix3D cũng định nghĩa các phương pháp đặt tên ScalePrepend và TranslatePrepend. Những phương pháp này thực hiện phép nhân để xảy ra như là nếu chuyển đổi quy định là bên trái và những biến đổi hiện tại là bên phải. Ví dụ, mã sau là tương đương với đoạn code trước:
Matrix3D matx = new Matrix3D();
matx.Translate(new Vector3D(10, 20, 30)); matx.ScalePrepend(new Vector3D(1.5, 2, 2.5));
Trang 64
Ch ng 3: TƠ MÀU CHO HÌNH 3D
Nói chung thế giới của đồ họa hai chiều và đồ họa ba chiều được lưu giữ cách xa nhau. Mỗi thế giới có mơ hình riêng của mình, các lớp riêng của mình để xác định các đối tượng có thể nhìn thấy, và biến đổi riêng của mình.
Trong chương này chúng ta sẽ tìm hiểu cách sử dụng cọ vẽ gradient và tile, trong đó bao gồm các hình ảnh bitmap, bản vẽ, và thậm chí cả hình ảnh thu được từ các đối tượng ngư i sử dụng giao diện như điều khiển. Thậm chí có thể bao gồm một con số 3D bằng bút vẽ bắt nguồn từ một
hình ảnhba chiều.
1. Sử d ng c v Gradient
Cú pháp để khai báo thuộc tính Brush của đối tượng DiffuseMaterial. Khai báo với một màu sắc đặc:
<DiffuseMaterial Brush="Cyan" /> Cú pháp này là một cách khai báo tắt cho:
Brush="{x:Static Brushes.Cyan}"
Bruhes là một lớp trong namespace System.Windows.Media có chứa một tập hợp các thuộc tính tĩnh chỉ đọc các loại Brush. (Các thuộc tính này thực sự trả về đối tượng của loại SolidColorBrush), một trong những thuộc tínhcủa loại SolidColorBrush này Cyan.
Hoặc có thể sử dụng cú pháp sau sử dụng màu RGB:
<DiffuseMaterial Brush="#80FF00C0" />
Đây cũng là cú pháp tắt. Một khai báo rõ ràng hơn cho một yếu tố của loại SolidColorBrush: <DiffuseMaterial> <DiffuseMaterial.Brush> <SolidColorBrush Color="#80FF00C0" </DiffuseMaterial.Brush> </DiffuseMaterial>
Và nếu bạn thực sự muốn có được khai báo rõ ràng hơn về nó, đó cũng là một cách khai báo
tắt cho các cú pháp đó bao gồm một nguyên tố Color:
<DiffuseMaterial>
<DiffuseMaterial.Brush> <SolidColorBrush>
Trang 65 <SolidColorBrush.Color> <Color A="128" R="255" G="0" B="192" /> </SolidColorBrush.Color> </SolidColorBrush> </DiffuseMaterial.Brush> </DiffuseMaterial>
Cú pháp như vậy có thể khai báo tắt được cho việc thực hiện b i các lớp BrushConverter