571
Lập trình đồ họa trên Java 2D và 3D Phần 1 ............................................................................................................................. 9 Lập trình đồ họa với Java 2D .......................................................................................... 9 Chương 1 .................................................................................................................. 10 Tổng quan về Java 2D API ....................................................................................... 10 1.1 Enhanced Graphics, Text, and imaging .......................................................... 10 1.2 Rendering Model ............................................................................................ 11 1.2.1 Coordinate Systems ................................................................................. 12 1.2.1.1 User Space ....................................................................................... 12 1.2.1.2 Device Space .................................................................................... 13 1.2.2 Transforms ............................................................................................... 14 1.2.3 Fonts ........................................................................................................ 15 1.2.4 Images ...................................................................................................... 16 1.2.5 Fills and Strokes ....................................................................................... 17 1.2.6 Composites ............................................................................................... 18 Backward Compatibility and Platform independence .......................................... 19 1.3.1 Backward Compatibility .......................................................................... 19 1.3.2 Platform independence ............................................................................ 21 1.4 The Java 2D™ API Packages ......................................................................... 21 Chương 2: ................................................................................................................. 25 Rendering with Graphics2D ..................................................................................... 25 2.1 Các lớp và giao diện. ...................................................................................... 26 2.2 Rendering Concepts ........................................................................................ 27 2.2.1 Rendering Process .................................................................................... 28 2.2.2 Controlling Rendering Quality ................................................................ 29 2.2.3 Stroke Attributes ...................................................................................... 31 2.2.4 Fill Attributes ........................................................................................... 32 Quá trình xử lý theo phiên ............................................................................ 34 2.2.5 Clipping Paths .......................................................................................... 34 2.2.6 Transformations ....................................................................................... 35 2.2.6.1 Constructing an AffineTransform .................................................... 37 2.2.7 Composite Attributes ............................................................................... 38 2.2.7.1 Managing Transparency .................................................................. 39 2.2.7.2 Transparency and images ................................................................. 40 2.3 Thiết lập Graphics2Context ............................................................................ 40 2.3.1 Setting Rendering Hints ........................................................................... 40 2.3.2 Specifying Stroke Attributes .................................................................... 41 2.3.2.1 Setting the Stroke Width .................................................................. 41 2.3.2.2 Specifying Join and Endcap Styles .................................................. 42 2.3.2.3 Setting the Dashing Pattern .............................................................. 42 2.3.3 Specifying Fill Attributes ......................................................................... 44 2.3.3.1 Filling a Shape with a Gradient ....................................................... 44 2.3.3.2 Filling a Shape with a Texture ......................................................... 45 2.3.4 Setting the Clipping Path ......................................................................... 46 2.3.5 Setting the Graphics2D Transform .......................................................... 48 2.3.6 Specifying a Composition Style .............................................................. 51 2.3.6.1 Using the Source Over Compositing Rule ....................................... 51 2.3.6.2 Increasing the Transparency of Composited Objects ...................... 51 2.4 Rendering Graphics Primitives ....................................................................... 53 2.4.1 Drawing a Shape ...................................................................................... 53 2.4.2 Filling a Shape ......................................................................................... 55 http://tailieuhay.com 1

Lap Trinh Java2D and 3D

Embed Size (px)

Citation preview

Page 1: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Phần 1 ............................................................................................................................. 9 Lập trình đồ họa với Java 2D .......................................................................................... 9

Chương 1 .................................................................................................................. 10 Tổng quan về Java 2D API ....................................................................................... 10

1.1 Enhanced Graphics, Text, and imaging .......................................................... 10 1.2 Rendering Model ............................................................................................ 11

1.2.1 Coordinate Systems ................................................................................. 12 1.2.1.1 User Space ....................................................................................... 12 1.2.1.2 Device Space .................................................................................... 13

1.2.2 Transforms ............................................................................................... 14 1.2.3 Fonts ........................................................................................................ 15 1.2.4 Images ...................................................................................................... 16 1.2.5 Fills and Strokes ....................................................................................... 17 1.2.6 Composites ............................................................................................... 18

Backward Compatibility and Platform independence .......................................... 19 1.3.1 Backward Compatibility .......................................................................... 19 1.3.2 Platform independence ............................................................................ 21

1.4 The Java 2D™ API Packages ......................................................................... 21 Chương 2: ................................................................................................................. 25 Rendering with Graphics2D ..................................................................................... 25

2.1 Các lớp và giao diện. ...................................................................................... 26 2.2 Rendering Concepts ........................................................................................ 27

2.2.1 Rendering Process .................................................................................... 28 2.2.2 Controlling Rendering Quality ................................................................ 29 2.2.3 Stroke Attributes ...................................................................................... 31 2.2.4 Fill Attributes ........................................................................................... 32

Quá trình xử lý theo phiên ............................................................................ 34 2.2.5 Clipping Paths .......................................................................................... 34 2.2.6 Transformations ....................................................................................... 35

2.2.6.1 Constructing an AffineTransform .................................................... 37 2.2.7 Composite Attributes ............................................................................... 38

2.2.7.1 Managing Transparency .................................................................. 39 2.2.7.2 Transparency and images ................................................................. 40

2.3 Thiết lập Graphics2Context ............................................................................ 40 2.3.1 Setting Rendering Hints ........................................................................... 40 2.3.2 Specifying Stroke Attributes .................................................................... 41

2.3.2.1 Setting the Stroke Width .................................................................. 41 2.3.2.2 Specifying Join and Endcap Styles .................................................. 42 2.3.2.3 Setting the Dashing Pattern .............................................................. 42

2.3.3 Specifying Fill Attributes ......................................................................... 44 2.3.3.1 Filling a Shape with a Gradient ....................................................... 44 2.3.3.2 Filling a Shape with a Texture ......................................................... 45

2.3.4 Setting the Clipping Path ......................................................................... 46 2.3.5 Setting the Graphics2D Transform .......................................................... 48 2.3.6 Specifying a Composition Style .............................................................. 51

2.3.6.1 Using the Source Over Compositing Rule ....................................... 51 2.3.6.2 Increasing the Transparency of Composited Objects ...................... 51

2.4 Rendering Graphics Primitives ....................................................................... 53 2.4.1 Drawing a Shape ...................................................................................... 53 2.4.2 Filling a Shape ......................................................................................... 55

http://tailieuhay.com 1

Page 2: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

2.4.3 Rendering Text ........................................................................................ 56 2.4.4 Rendering images .................................................................................... 56

2.5 Defining Custom Composition Rules ............................................................. 56 2.6 Rendering in a Multi-Screen Environment ..................................................... 57

Chương 3 .................................................................................................................. 75 Các đối tượng hình họa ............................................................................................. 75

3.1 Giao diện và lớp. ............................................................................................. 75 3.2 Các khái niệm hình học: ................................................................................. 78

3.2.1 Constructive Area Geometry ................................................................... 79 3.2.2 Bounds and Hit Testing ........................................................................... 80

3.3 Combining Areas to Create New Shapes ........................................................ 88 Chương 4: ................................................................................................................. 94 Hiển thị Font và văn bản ........................................................................................... 94

4.1.Giao diện và lớp. ............................................................................................. 94 4.2.Các khái niệm về Font .................................................................................... 96 4.3 Các khái niệm về Text Layout. ....................................................................... 98

4.3.1 Vẽ chữ. ..................................................................................................... 99 4.3.2 Ordering Text ......................................................................................... 101 4.3.3 Đo và định vị văn bản ............................................................................ 103 4.3.4 Hỗ trợ thao tác với văn bản. ................................................................... 104

4.3.4.1 Hiển thị dấu nhắc ............................................................................ 104 4.3.4.2 Di chuyển dấu nhắc. ....................................................................... 106 4.3.4.3 Hit Testing ..................................................................................... 107 4.3.4.4 Đánh dấu vùng lựa chọn. ............................................................... 108

4.3.5 Thực thi việc hiển thị văn bản trong ứng dụng Java™ . ........................ 109 Quản lý việc hiển thị văn bản. ............................................................................ 110

4.4.1 Trình bày văn bản. ................................................................................. 111 Hiển thị dấu nhắc kép. .................................................................................... 112 4.4.3 Di chuyển dấu nhắc. ............................................................................... 113 4.4.4 Hit Testing ............................................................................................. 114 4.4.5 Đánh dấu vùng lựa chọn. ....................................................................... 115 4.4.6 Querying Layout Metrics ....................................................................... 115 4.4.7 Vẽ văn bản trên nhiều dòng. .................................................................. 116

Chương 5 ................................................................................................................ 126 Tạo ảnh ....................................................................................................................... 126

5.1 Các giao diện và các lớp .......................................................................... 126 5.1.1 Các giao diện imaging (imaging interfaces) ......................................... 127 5.1.2 Các lớp dữ liệu ảnh(image Data Classes) .............................................. 127 5.1.3 image Operation Classes ........................................................................ 129 5.1.4 Sample Model Classes ........................................................................... 130 Color Model Classes ....................................................................................... 131 5.1.6 Exception Classes .................................................................................. 132

5.2 Immediate Mode imaging Concepts ............................................................. 133 5.2.1 Terminology ........................................................................................... 135

5.3 Using Bufferedimages .................................................................................. 136 5.3.1 Creating a Bufferedimage ...................................................................... 136 5.3.2 Drawing in an Offscreen Buffer ............................................................ 137

5.3.2.1 Creating an Offscreen Buffer ......................................................... 138 5.3.2.2 Drawing in an Offscreen Buffer .................................................... 140

5.3.3 Manipulating Bufferedimage Data Directly .......................................... 141

http://tailieuhay.com 2

Page 3: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

5.3.4 Filtering a Bufferedimage ...................................................................... 142 5.3.5 Rendering a Bufferedimage .................................................................. 142

5.4 Managing and Manipulating Rasters ............................................................ 150 5.4.1 Creating a Raster .................................................................................... 150 5.4.2 Parent and Child Rasters ........................................................................ 151 5.4.4 The WritableRaster Subclass ................................................................. 151

5.5 Image Data and DataBuffers ......................................................................... 152 5.6 Extracting Pixel Data from a SampleModel ................................................. 153 5.7 ColorModels and Color Data ........................................................................ 154

5.7.1 Lookup Table ......................................................................................... 155 5.8 image Processing and Enhancement ............................................................. 155

5.8.1 Using an image Processing Operation ................................................... 158 Chương 6 ................................................................................................................ 162 Mầu sắc ................................................................................................................... 162

6.1 Các lớp ......................................................................................................... 163 6.2 Những định nghĩa về mầu sắc. ...................................................................... 163

6.2.1 Không gian mầu .................................................................................... 164 6.2.1 Biểu diễn màu ....................................................................................... 167

Chương 7 ............................................................................................................... 171 In ấn ........................................................................................................................ 171

7.1 Các giao diện và các lớp ............................................................................... 171 7.2.1 Supporting Printing ................................................................................ 174

7.2.1.1 Điều khiển in (Job Control) ........................................................... 174 7.2.2 Page Painters .......................................................................................... 175 7.2.3 Printable Jobs and Pageable Jobs ........................................................... 177

7.2.4 Typical Life-Cycle of a PrinterJob ................................................................ 178 7.3 Printing with Printables ................................................................................ 181

7.3.2 Printing a File ......................................................................................... 185 7.4.1 Using a Pageable Job ............................................................................. 191 7.4.2 Using Multiple Page Painters ................................................................ 193

Phần 2 ......................................................................................................................... 206 Lập trình đồ họa với Java 3D ...................................................................................... 206

CHƯƠNG 1 ............................................................................................................ 207 NHẬP MÔN LẬP TRÌNH TRÊN JAVA 3D ......................................................... 207

1.1 Tổng quan về Java 3D API ™ ...................................................................... 207 1.2 Các vấn đề cơ bản về Java 3D API™ .......................................................... 208 1.3 Xây dựng đồ thị khung cảnh ......................................................................... 208

1.3.1 Thừa kế cấp cao từ Java 3D API .......................................................... 214 1.4 Cách thức để viết một chương trình Java 3D .................................................... 216

1.4.1 Công thức đơn giản để viết một chương trình Java 3D ........................ 216 1.5 Một vài thuật ngữ trong Java 3D ................................................................. 221 1.6 Ví dụ đơn giản: HelloJava3Da ..................................................................... 223 1.6.1 Các lớp của Java 3D Classes được sử dụng trong HelloJava3Da .............. 229

Tạo nên hình lập phương có kích thước được định ra bởi các giá trị cho trước. .... 233 1.7 Quay hình lập phương ................................................................................. 233

1.7.1 Sự kết hợp của các phép biến hình: HelloJava3Db ............................... 235 1.8 Khả năng và hoạt động ................................................................................. 236

1.8.1 Dịch các nội dung .................................................................................. 236 1.8.2 Khả năng ............................................................................................... 237

1.9 Thêm vào các hành vi animation .................................................................. 239

http://tailieuhay.com 3

Page 4: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

1.9.1 Định nghĩa các hành vi animation ......................................................... 240 1.9.2 Các hàm biến đổi về thời gian: Ánh xạ một hành vi với thời gian ........ 241 1.9.3 Lập danh mục các vùng ......................................................................... 242 1.9.4 Ví dụ về hành vi: HelloJava3Dc ........................................................... 243 1.9.5 Phép biến hình và kết hợp các hành vi .Ví dụ: HelloJava3Dd ............. 246

CHƯƠNG 2 ............................................................................................................ 251 Tạo các hình ............................................................................................................ 251

2.1 Hệ tọa độ thế giới ảo ..................................................................................... 251 2.2 Visual Object Definition Basics ................................................................... 252

2.2.1 An Instance of Shape3D Defines a Visual Object ................................ 252 2.2.2 Node Components .................................................................................. 254 2.2.3 Defining Visual Object Classes ............................................................. 255

2.3 Các lớp tiện ích hình học ............................................................................. 256 2.3.1 Box ......................................................................................................... 257 2.3.2 Cone ...................................................................................................... 259 2.3.3 Cylinder ................................................................................................. 259 2.3.4 Sphere .................................................................................................... 260 2.3.5 More About Geometric Primitives ........................................................ 261 2.3.6 ColorCube ............................................................................................. 261 2.3.7 Example: Creating a Simple Yo-Yo From Two Cones ........................ 261

2.4 Các lớp toán học ........................................................................................... 267 2.4.1 Point Classes ............................................................................................. 271

2.4.2 Color Classes ......................................................................................... 272 2.4.3 Vector Classes ........................................................................................ 274 2.4.4 TexCoord Classes .................................................................................. 275

2.5 Các lớp hình học ........................................................................................... 276 2.5.1 GeometryArray Class ........................................................................... 277 2.5.2 Subclasses of GeometryArray .............................................................. 284 2.5.3 Subclasses of GeometryStripArray ........................................................ 286 2.5.4 Subclasses of IndexedGeometryArray ................................................... 293 2.5.5 Axis.java is an Example of IndexedGeometryArray ............................ 296

2.6 Appearance and Attributes ............................................................................ 296 2.6.1 Appearance NodeComponent ................................................................ 298 2.6.2 Sharing NodeComponent Objects ........................................................ 298 2.6.3 Attribute Classes ................................................................................... 299 2.6.4 Example: Back Face Culling ................................................................ 310

2.7 Bounds and Scope ........................................................................................ 320 2.7.1 Bounds Node Components ................................................................... 321 2.7.2 BoundingLeafa Node ............................................................................ 325 2.7.3 Scope ...................................................................................................... 327

2.8 Hình học nâng cao ........................................................................................ 329 2.8.1 Multiple Geometries in a Single Shape3D ........................................... 329 2.8.2 GeometryArray ..................................................................................... 332 2.8.4 AlternateAppearance <new in 1.2> ...................................................... 340

2.9 Clipping – Cắt xén ........................................................................................ 343 2.9.1 View Defines a Frustum ........................................................................ 343 2.9.2 Clip Node .............................................................................................. 345 2.9.4 ModelClip Example .............................................................................. 346

CHƯƠNG 3 ............................................................................................................ 350 TẠO NỘI DUNG .................................................................................................... 350

http://tailieuhay.com 4

Page 5: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

3.1 Nội dung chính .............................................................................................. 350 3.1.1 GeometryInfo ......................................................................................... 351

3.2.1 Một ví dụ đơn giản về GeometryInfo ........................................................ 351 3.2.2 Sử dụng GeometryInfo .......................................................................... 352 3.2.3 Một số lớp thông dụng có liên quan đến GeometryInfo ........................ 353

Loaders ................................................................................................................ 358 Một ví dụ đơn giản sử dụng leader. ................................................................ 359

Các loader phổ biến ........................................................................................... 360 3.3.3 Giao diện của gói Loader và lớp cơ sở ............................................... 361

Viết một loader ................................................................................................... 365 Công việc của một loader ............................................................................... 365 Hàm tạo lớp Loader ........................................................................................ 366 Viết một File Loader đơn giản ........................................................................ 368

Text2D ................................................................................................................ 379 3.5.1 Ví dụ Text2D đơn giản .......................................................................... 380 3.5.2 Lớp Text2D ............................................................................................ 380

Text3D ................................................................................................................ 382 Một ví dụ Text3D ........................................................................................... 382 Những lớp liên quan để tạo ra đối tượng Text3D ........................................... 384

Nền không gian đồ họa ...................................................................................... 391 Một ví dụ background ..................................................................................... 391 Lớp Background ............................................................................................. 392

CHƯƠNG 4 ............................................................................................................ 396 TƯƠNG TÁC ......................................................................................................... 396

4.1 Hành vi: Cơ sở của tương tác và hoạt hình ................................................... 397 4.1.1 Ứng dụng của hành vi ............................................................................ 397 4.1.2 Tổng quan lớp Behaviour ...................................................................... 399

4.2 Cơ bản về hành vi ......................................................................................... 399 4.2.1 Viết một lớp Behaviour ......................................................................... 400 4.2.2 Sử dụng một lớp Behaviour ................................................................... 405 4.2.3 Các hàm API trong lớp Behaviour ......................................................... 409

4.3 Điều kiện kích hoạt: Cách kích hoạt các hành vi .......................................... 412 4.3.1 Điều kiện kích hoạt ................................................................................ 413 4.3.2 WakeupCriterion .................................................................................... 414 4.3.3 Quy định lớp WakeupCriterion ............................................................. 414 4.3.4 Thành phần của WakeupCondition ....................................................... 430

4.4 Lớp Behaviour tiện ích xử lý bàn phím ........................................................ 432 4.4.1 Một ví dụ đơn giản ................................................................................. 433 4.4.2 Lớp KeyNavigatorBehaviour và KeyNavigator .................................. 435

4.5 Lớp tiện ích tương tác với chuột ................................................................... 437 4.5.1 Sử dụng lớp MouseBehaviour .............................................................. 437 4.5.2 Mouse Behaviour Foundation ................................................................ 442 4.5.3 Các lớp MouseBehaviour ..................................................................... 444 4.5.4 Mouse Navigation .................................................................................. 447

4.6 Picking Object ............................................................................................... 450 4.6.1 Using Picking Utility Classes ................................................................ 454 4.6.2 Các hàm API cơ bản trong các lớp Picking .......................................... 458 4.6.3 Các lớp picking ...................................................................................... 467 4.6.4 Các lớp Picking Behavior ..................................................................... 471

CHƯƠNG 5 ............................................................................................................ 474

http://tailieuhay.com 5

Page 6: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Hoạt Hình ................................................................................................................ 474 Animation - Hoạt hình: ....................................................................................... 476 Đối tượng Interpolator và Alpha với hoạt ảnh dựa thời gian ............................. 477 Alpha ................................................................................................................... 477 Sử dụng các đối tượng Interpolator và Alpha: ................................................... 480 Ví dụ sử dụng lớp Alpha và RotationInterpolator: ............................................. 480 Alpha API: .......................................................................................................... 486 Các lớp hành vi Interpolator : ............................................................................. 489 Core Interpolator API: ....................................................................................... 504 Các lớp đối tượng nội suy đường: ...................................................................... 513

Lớp Billboard : ........................................................................................................ 522 Sử dụng đối tượng Billboard ............................................................................. 523 Chương trình ví dụ sử dụng Billboard ............................................................... 525 Giao diện lập trình ứng dụng của Billboard (Billboard API) ........................... 529 OrientedShape3D ................................................................................................ 531 Giao diện lập trình ứng dụng của OrientedShape3D .......................................... 532 Ví dụ sử dụng OrientedShape3D ........................................................................ 533 Hoạt ảnh mức chi tiết (Level Of Detail Animations) ......................................... 535 Sử dụng đối tượng DistanceLOD ....................................................................... 536

Các lỗi thường gặp khi sử dụng LOD ............................................................ 537 Ví dụ sử dụng DistanceLOD .............................................................................. 537 Giao diện lập trình ứng dụng DistanceLOD API ............................................... 544 Morph ................................................................................................................. 545 Sử dụng đối tượng Morph .................................................................................. 546 Ví dụ sử dụng Morph ......................................................................................... 547 Giao diện lập trình ứng dụng Morph API .......................................................... 553

Giao diện GeometryUpdater ................................................................................... 554 Sử dụng GeometryUpdater ................................................................................. 555 Chương trình ví dụ hệ thống phân tử đài phun nước sử dụng GeometryUpdater ............................................................................................................................ 556

Lời nói đầu

Sự phát triển của khoa học, kĩ thuật, nghệ thuật, kinh doanh, và

công nghệ luôn luôn phụ thuộc vào khả năng truyền đạt thông tin của

chúng ta, hoặc thông qua các bit dữ liệu lưu trữ trong microchip hoặc

thông qua giao tiếp bằng tiếng nói. Câu châm ngôn từ xa xưa “một hình

ảnh có giá trị hơn cả vạn lời" hay "trăm nghe không bằng một thấy" cho

thấy ý nghĩa rất lớn của hình ảnh trong việc chuyển tải thông tin. Hình

ảnh bao giờ cũng được cảm nhận nhanh và dễ dàng hơn, đặc biệt là trong

trường hợp bất đồng về ngôn ngữ. Do đó không có gì ngạc nhiên khi mà

ngay từ khi xuất hiện máy tính, các nhà nghiên cứu đã cố gắng sử dụng

nó để phát sinh các ảnh trên màn hình. Trong suốt gần 50 năm phát triển

http://tailieuhay.com 6

Page 7: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

của máy tính, khả năng phát sinh hình ảnh bằng máy tính của chúng ta đã

đạt tới mức mà bây giờ hầu như tất cả các máy tính đều có khả năng đồ

họa.Đồ họa máy tính là một trong những lĩnh vực lí thú nhất và phát triển

nhanh nhất của tin học. Ngay từ khi xuất hiện, đồ họa máy tính đã có sức

lôi cuốn mãnh liệt, cuốn hút rất nhiều người ở nhiều lĩnh vực khác nhau

như khoa học, nghệ thuật, kinh doanh, quản lí, ... Tính hấp dẫn và đa dạng

của đồ họa máy tính có thể được minh họa rất trực quan thông qua việc

khảo sát các ứng dụng của nó.

Ngày nay, đồ họa máy tính được sử dụng trong rất nhiều lĩnh vực

khác nhau như công nghiệp, thương mại, quản lí, giáo dục, giải trí, … Số

lượng các chương trình đồ họa ứng dụng thật khổng lồ và phát triển liên

tục.Trong lĩnh vực công nghiệp,CAD(computer-aided design) đã được sử

dụng hầu hết trong việc thiết kế các cao ốc, ô tô, máy bay, tàu thủy, tàu vũ

trụ, máy tính,…Trong lĩnh vực giải trí,nghệ thuật, đồ họa máy tính giúp ta

tạo ra các chương trình trò chơi,các kĩ xảo điện ảnh cho các nhà làm

phim,hay ngay chính giao diện đồ họa đã làm nâng cao khả năng giao tiếp

giữa người và máy tính.

Để có thể làm được những ứng dụng đồ họa hữu ích cho cuộc

sống,trước hết chúng ta cần phải có một nền tảng vững chắc về lập trình

đồ họa.Có rất nhiều ngôn ngữ hỗ trợ lập trình đồ họa máy tính,mỗi ngôn

ngữ được xây dưng trên những thư viện đồ họa riêng,có những thế mạnh

riêng.Và khi nói về lập trình đồ họa,chúng ta không thể không nói đến

ngôn ngữ Java,một ngôn ngữ rất mạnh trong lĩnh vực này.Với mục đích

nghiên cứu,tìm hiểu và mang đến cho những ai muốn tìm hiều về lập trình

đồ họa một tài liệu thiết thực,nhóm chúng em đã chọn đề tài làm tutorial

về lập trình đồ họa trên nền tảng ngôn ngữ lâp trình Java,dựa trên các tài

liệu training trên mạng của hãng Sun.Vì là lần đầu làm tài liệu tham khảo

http://tailieuhay.com 7

Page 8: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

nên chúng em không tránh khỏi sai sót.Chúng em mong thầy xem xét và

góp ý cho tài liệu này.Chúng em chân thành cảm ơn.

http://tailieuhay.com 8

Page 9: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Phần 1

Lập trình đồ họa với Java 2D

http://tailieuhay.com 9

Page 10: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Chương 1

Tổng quan về Java 2D API

Java 2D™ API tăng cường về khả năng đồ hoạ, văn bản và ảnh của

Abstract Windowing Toolkit (AWT), giúp phát triển về giao diện người

sủ dụng và ứng dụng về JAVA trong một số lĩnh vực mới.Cùng với khả

năng mạnh về đồ hoạ ,phông chữ và ảnh trong các API, thì Java 2D API

còn hỗ trợ những thuộc tính và thành phần màu sắc đã được nâng cao, và

thành công trong việc biểu diễn các bề mặt hình học tuỳ ý và một kiểu tô

trát chuẩn cho máy in và thiết bị hiển thị. Java 2D API cũng cho phép tạo

ra các thư viện đồ hoạ mở rộng,như các thư viện của CAD-CAM và các

thư viện tạo hiệu ứng đặc biệt cho ảnh và đồ hoạ, cũng như việc tạo ra các

bộ lọc đọc/viết file ảnh và đồ hoạ.Khi được sử dụng kết hợp với Java

Media Framework Java Media APIs khác ,thì Java 2D APIs có thể được

sử dụng để tạo ra và hiển thị hiện thực ảo và các dạng đa phương tiện

khác. Java Animation và Java Media Framework APIs dưa trên Java 2D

API để hỗ trợ việc tô trát(rendering).

1.1 Enhanced Graphics, Text, and imaging

Nếu các phiên bản trước của AWT chỉ cung cấp các gói tô

trát(rendering) đơn giản chỉ phù hợp cho việc rendering các trang HTML

đơn giản,mà không đáp ứng đủ cho các dạng đồ hoạ,văn bản và ảnh phức

http://tailieuhay.com 10

Page 11: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

tạp. Thì Java 2D™ API cung cấp gói tô trát đẩy đủ các tính năng bằng

cách mở rộng AWT để hỗ trợ cho đồ hoạ và các thao tác rendering. Ví dụ

như thông qua các lớp đồ hoạ cho phép vẽ hình chữ nhật,hình ôval,và các

đa giác. Đồ hoạ 2D tăng cường về khái niệm của phép tô trát hình học

bằng cách cung cấp một cơ chế cho phép rendering ảo của bất kì bề mặt

hình học nào.Tương tư như vậy với Java 2D API bạn có thể vẽ các dạng

đường với bất kì độ rộng và dạng hình học nào.

Dạng hình học được cung cấp thông qua các phần thực thi

implementations của Shape interface trong Graphic class, như hình chữ

nhật 2D và Elip 2D. Các đường cong và hình cung cũng thuộc phần

implementations của Shape. Các kiểu vẽ và tô cũng được cung cấp thông

qua phần thực thi implementations của giao tiếp Paint và Stroke

interfaces, ví dụ BasicStroke, GradientPaint, TexturePaint,và Color.

AffineTransform định nghĩa các phép biến đổi trong toạ độ 2 chiều,

gồm có phép lấy tỉ lệ,phép chuyển đổi toạ độ ,phép quay và phép xén cắt.

Khung nhìn được định nghĩa bởi các phương thức giống nhau của lớp

Shape mà chúng được dùng để định nghĩa các khung nhìn chung,ví dụ

như Rectangle2D và GeneralPath.

Thành phần màu sắc được cung cấp bởi các phương thức của lớp

Composite, ví dụ AlphaComposite.

Một kiểu Font chữ thì được định nghĩa bởi các collection của Glyphs.

1.2 Rendering Model

Kiểu tô trát đồ họa đơn giản không có gì thay đổi khi thêm vào Java

2D™ APIs. Để tô trát đồ họa thì phải thiết lập các thông số về đồ họa và

gọi phương thức của đối tượng Graphics.

Trong Java 2D API, lớp Graphics2D mở rộng lớp Graphics để hỗ trợ

thêm nhiều thuộc tính đồ họa và cung cấp thêm các phương thức cho quá

trình tô trát.

http://tailieuhay.com 11

Page 12: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

The Java 2D API tự động cân chỉnh những sai khác trong các thiết bị tô

trát và cung cấp một kiểu tô trát thống nhất cho các dạng thiết bị khác

nhau. Tại tầng ứng dụng,quá trình tô trát là giống nhau cho dù thiết bị

cuối đó là màn hình hay máy in.

Với Java 2 SDK, version 1.3 , Java 2D API còn hỗ trợp cho các môi

trường đa màn hình (multi-screen environments).

1.2.1 Coordinate Systems

Java 2D API bao hàm hai hệ tọa độ:

1. Không gian người sủ dụng là hệ tọa độ logic và độc lập với thiết bị.

Các ứng dụng thường sủ dụng hệ tọa độ này,tất cả các dạng hình

học được tô trát bằng Java 2D đều được xác định trong hệ tọa độ

này.

2. Không gian thiết bị là hệ tọa độ phụ thuộc thiết bị,ứng với từng loại

thiết bị cuối mà có hệ tạo độ khác nhau.

Bằng ứng dụng máy ảo một cửa sổ hiển thị có thể mở rộng thêm nhiều

thiết bị hiển thị vậy lý tạo nên môi trường đa màn hiển thị, hệ tọa độ của

thiết bị này được sủ dụng làm hệ tọa độ của máy ảo sẽ được lấy làm hệ

tọa độ cho tất cả các màn hiể thị còn lại.

Hệ thống Java 2D sẽ tự động thực hiện những phép chuyển đổi cần

thiết giữa không gian người sử dụng và không gian thiết bị . Mặc dù hệ

tọa độ cho màn hình rất khác đối với hệ tọa độ cho máy in nhưng sự khác

biệt này trong suốt đối với các ứng dụng.

1.2.1.1 User Space

Hệ tọa độ này được chỉ ra trong hình 1-1.

(0,0) x

http://tailieuhay.com 12

Page 13: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

y

Figure 1-1 User Space Coordinate System

Không gian người sử dụng biểu diễn một cách trừu tượng đồng nhất

cho các hệ tạo độ của tất cả các thiết bị có liên quan.Còn không gian thiết

bị cho một thiết bị cụ thể có thể có cùng gốc tọa độ và hướng của các trục

hoặc là có thể không.Ngoài ra các tọa độ của không gian người sử dụng

có thể chuyển đổi một cách tự động vào không gian thiết bị phù hợp mỗi

khi một đối tượng đồ họa được tô trát,thường thì các chương trình driver

của các thiết bị thực hiện điều này.

1.2.1.2 Device Space

Java 2D API định nghĩa 3 mức thông tin cấu hình để hỗ trợ cho việc

chuyển đổi từ không gian người sử dụng sang không gian thiết bị. Thông

tin này được chứa trong 3 lớp :

• GraphicsEnvironment

• GraphicsDevice

• GraphicsConfiguration

Hai trong số chúng sẽ biểu diễn tất cả các thông tin cần thiết cho việc

xác định thiết bi tô trát và cho việc chuyển đổi tọa độ từ không gian người

http://tailieuhay.com 13

Page 14: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

sử dụng sang không gian thiết bị. Ứng dụng có thể truy cập thông tin này

nhưng không nhất thiết phải thực hiện bất kì phép chuyển đổi nào giũa hai

hệ tọa độchuyển .

Lớp GraphicsEnvironment mô tả tập các thiết bị mà đựợc chấp nhận bởi

các ứng dụng Java trong một môi trường cụ thể.Các thiết bị sử dụng cho

quá trình tô trát gồm có màn hình , má in và các bộ đệm ảnh.Lớp

GraphicsEnvironment cũng bao gồm tập các font phù hợp trong môi

trường đó.

Lớp GraphicsDevice mô tả thiết bị tô trát như màn hình hoặc máy in.Mỗi

cấu hình phù hợp của thiết bị được biểu diễn bởi lớp

GraphicsConfiguration. Ví dụ,một thiết bị hiển thị SVGA có thể thực

hiện trong một số chế độ màu như : 640x480x16 colors, 640x480x256

colors, and 800x600x256 colors.

Màn hình SVGA được biểu diễn bởi một đối tượng GraphicsDevice

và ứng với mỗi chế độ màu của màn hình SVGA sẽ được biểu diễn bởi

một đối tượng GraphicsConfiguration.Một đối tượng kiểu

GraphicsEnvironment có thể bao gồm 1 hay nhiều đối tượng

GraphicsDevices. Ngược lại ,mỗi đối tượng GraphicsDevice có thể có 1

hay nhiều đối tượng kiểu GraphicsConfigurations.

1.2.2 Transforms

Java 2D API có một chế độ chuyển tọa độ thống nhất. Tất cả các phép

chuyển tọa độ,bao gồm các phép chuyển từ không gian người sử dụng

đến không gian của thiết bị,đều được biểu diễn bởi đối tượng kiểu

AffineTransform .AffineTransform định nghĩa các luật cho những thao

tác trên các hệ tọa độ bằng các ma trận(các phép biến đổi ảnh bằng các bộ

lọc).

Cũng có thể thêm đối tượng AffineTransform cho các dạng đồ họa bằng

các phép xoay ,lấy tỉ lệ ,chuyển đổi hoặc cắt tọa độ cho một mặt hình học

http://tailieuhay.com 14

Page 15: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

,văn bản hay ảnh khi chúng được tô trát.Các phép biến đổi được thêm vào

này sẽ được ứng dụng cho các đối tượng đồ họa được tô trát trong trường

hợp đó phép bién đổi này được thực hiện khi chuyển từ tọa độ không gian

người sử dụng sang không gian của thiết bị.

1.2.3 Fonts

Một xâu thường được hiểu là tập các kí tự tao thành.Khi một xâu

được vẽ, hình dạng của nó sẽ được xác định bởi font mà chúng ta

chọn.Tuy nhiên, hình dạng mà font sử dụng để hiển thị lên màn hình xâu

đó không phải lúc nào cũng giống với hình dáng của mỗi kí tự riêng biệt.

ví dụ sự kết hợp của 2 hay nhiều kí tự thường được thay thế bởi một hình

dạng kí hiêu nào đó được gọi là ligature.

Các hình dạng mà một phông chữ sử dụng để biểu diễn các kí tự trong

một xâu được gọi là glyphs. Một font có thể biểu diễn một kí tự như chữ

thường hoặc chữ hoa bằng cách sử dụng nhiều glyphs, hoặc biểu diễn các

liên kết kí tự như fi chỉ biểu diễn bởi 1 glyph. Trong Java 2D API, một

glyph chỉ đơn giản là một dạng (Shape) mà có thể đựoc thao tác và tô trát

một cách giống nhau như bất kì với các dạng khác Shape.

Một font có thể được xem như tập các glyph. Một font đơn có thể có

rất nhiều kiểu khác nhau như kểi chữ đậm ,vừa,nghiêng ,gôtích…tất cả

các kiểu chữ này trong một font có cùng thiết kế in và có thể ví như

chúng là các thành viên trong cùng một gia đình. Hay nói cách khác ,một

nhóm các glyphs với các kiểu riêng biệt tạo nên một dạng font,nhóm các

dạng font tao nên môt họ font ,họ các font tạo nên một tập font và tập này

có sẵn trong một đối tượng GraphicsEnvironment cụ thể nào đó.

Trong Java 2D API, các font được xác định bởi một tên mà mô tả một

dạng font riêng biệt nào đó,ví dụ Helvetica Bold. Nhưng điều này lại khác

với fần mềm JDK 1.1 ,các font được mô tả bằng các tên lôgíc mà ánh xạ

trên các dạng font khác nhau fụ thuộc liệu các dạng font đó có sắn trong

http://tailieuhay.com 15

Page 16: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

môi trường đang xét không.Như để tương thích cho điều đó ; the Java 2D

API hỗ trợ việc xác định các font bằng tên lôgíc cũng như bằng tên dạng

font.

Sử dụng Java 2D API, có thể soạn thảo và tô rát các xâu bao gồm

nhiều font thuộc các họ font,hình dạng,kich thước, và thâm chí cả ngôn

ngữ khác nhau. Các dạng của văn bản được lưu riêng biệt một cách lôgíc

với sự sắp xếp các văn bản.Các đối tượng Font được sử dụng để mô tả các

hình dạng hiển thị của font, và thông tin sắp xếp được lưu trong đối tượng

TextLayout và TextAttributeSet . Việc lưu giứ các font và thông tin sắp

xếp riêng biệt nhau làm dễ dàng hơn cho việc sử dụng cùng font chữ

nhưng khác về cấu hình sắp xếp.

1.2.4 Images

Ảnh được tạo nên từ tập các pixel . Một điểm ảnh hay một pixel sẽ

định nghĩa thể hiện của một ảnh tại vùng quan sát của màn hình . Một

mảng hai chiều của điểm ảnh được gọi là một raster.

Thể hiện của một điểm ảnh có thể được định nghĩa một cách trực tiếp

hoặc như là một chỉ số trong bảng màu dành cho ảnh.

Trong ảnh màu đa màu (hơn 256 màu) các điểm ảnh thường trực tiếp

biểu diễn luôn màu sắc và các đặc trưng khác cho mỗi vùng hiển thị của

ảnh. Những ảnh như vậy sẽ có kích thước lớn hơn ảnh màu mà hiển thị

bằng chỉ số(indexed-color images), nhưng chúng nhìn sẽ thật hơn .

Trong ảnh màu hiển thị bằng chỉ số (indexed-color image), những

màu sắc của ảnh sẽ bị giới hạn bởi bảng màu , và thường số lượng màu

trong bảng màu sẽ ít hơn sovới ảnh thật. Tuy nhiên các ảnh khi được lưu

như tập các chỉ số màu sẽ làm cho kích thước ảnh nhỏ đi.Định dạng này

thường được dùng cho những ảnh có 256 màu.

Ảnh trong Java 2D API có hai thành phần chính

• Dữ liệu ảnh thô(các điểm ảnh)

http://tailieuhay.com 16

Page 17: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

• Những thông tin cần thiết cho quá trình chuyển đổi các điểm ảnh

Các luật cho việc chuyển đổi các điểm ảnh được lưu bởi đối tượng

ColorModel. Đối với một điểm ảnh để hiển thị cần phải đi kèm với một

kiểu màu sắc.

Một dải màu là một thành phần của không gian màu sắc dành cho

ảnh.Ví dụ các thành phần màu đỏ là các daỉ màu trong ảnh RGB . Một

điểm ảnh trong ảnh dùng màu trực tiếp có thể được hiểu như một tập .

Gói java.awt.image bao gồm một số phương thức ColorModel cho

các biểu diễn thành phần điểm ảnh.

Một đối tượng ColorSpace chứa các luật để sao cho tập các giá trị

màu tương ứng với một màu sắc nhất định .Các phương thức của

ColorSpace trong java.awt.color sẽ biẻu diễn các không gian màu sắc

thông dụng, gồm có không gian màu RGB và gray scale. Lưu ý rằng một

không gian màu không phải là một tập các màu sắc mà tập này định nghĩ

các luật để có thể chuyển đổi các giá trị màu thành các màu tương ứng

thông dịch.

Việc chia không gian màu sắc thành các chế độ màu sẽ tạo nên sự linh

hoạt hơn trong việc biểu diễn và chuyển đổi từ phép biểu diễn màu này

sang một phếp biểu diẽn màu khác.

1.2.5 Fills and Strokes

Với Java 2D API, có thể tô các hình băng cách sử dụng các kiểu but

khác nhau và các kiểu tô khác nhau. Vì các chữ xét cho cùng cũng được

biểu diễn bằng tập các glyph, nên các xâu kí tự cũng có thể được vẽ và tô.

Các kiểu bút được định nghĩa băng các đối tượng kiểu Stroke.Có thể

xác định độ rộng cũng như các nét cho các đường thẳng và đường cong.

Các kiểu tô được định nghĩa bởi các phương thức thuộc đối tượng

Paint. Lớp Color có sắn trong các phiên bản trước của AWT đây là một

http://tailieuhay.com 17

Page 18: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

dạng đơn giản của đối tượng Paint được sử dụng để định nghĩa tô màu

trơn (solid color). Java 2D API cung cấp thêm hai phương thức mới cho

Paint là TexturePaint và GradientPaint. TexturePaint định nghĩa kiểu

tô dùng mẩu ảnh đơn giản(simple image fragment ) mà được lặp như

nhau. GradientPaint định nghĩa một kiểu tô màu loang(gradient) giữa

hai màu.

Trong Java 2D, rendering một đường nét của một hình và tô hình đó

bằng một kiểu nào đó được thực hiên hai thao tác riêng biệt:

• Sử dụng một trong các thuật toán draw để render các đường nét

của hình sử dụng các kiểu bút được xác định bởi các thuộc tính của

Stroke và kiểu tô được xác định bởi thuộc tính Paint.

• Sử dụng phương thức fill để tô các vùng trong của hình với kiểu

tô đã dược xác định.

Khi một chuỗi kí tự được render,các thuộc tính hiện tại của Paint

đựơc áp dụng cho các glyphs tạo nên chuỗi đó.Lưu ý thực chất đối tượng

drawString sẽ tô các glyphs mà được render. Để vẽ các nét của các glyphs

trong chuỗi kí tự cần phải chọn các đường nét và render chúng như đối

với các hình sử dụng phương thức draw .

1.2.6 Composites

Khi render một đối tượng mà chồng lên một đối tượng đã tồn tai trước

đó cần phải xác định làm thế nào để kết hợp màu của các đối tuợng. Java

2D API có các luật cho việc kết hợp màu trong trường hợp này trong đối

tượng Composite.

Tuy nhiên có một số vấn đề trong cách tiếp cận này:

• Sẽ thật khó trong trường hợp nếu màu Red và màu Blue được thêm

vào hây không được thêm vào.

• Việc kết hợp lôgíc sẽ không được hỗ trợ trong trường hợp cácmàu

thuộc các không gian màu khác nhau.

http://tailieuhay.com 18

Page 19: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

• Sự kết hợp sẽ không có ý nghĩa trong trường hợp màu được biểu

diễn bằng các gia trị màu thì khi đó sự kết hợp hai điểm ảnh là sự kết hợp

của hai giá trị màu.

Java 2D API tránh các loĩi này bằng cách thực hiện các luật pha trộn

alpha mà sẽ đưa vào các thông tin về kiểu biểu diễn điểm ảnh mỗi khi

thực hiện kết hợp màu. Một đối tượng AlphaComposite bao gồm các

kiểu về màu sắc của các màu sắc của nguồn và đích.

Backward Compatibility and Platform independence

Như đã nói,Java 2D™ API có sự tương thích đối với phần mềm JDK

1.1 . Và Java 2D™ API là một kiến trúc chính vì vậy mà các ứng dụng

của nó có tính độc lập về môi trường

1.3.1 Backward Compatibility

Để tương thích với các tính năng đã tồn tại trong đồ họa JDK .Java

2D API tăng cường thêm một số tính năng cho AWT bằng cách thêm các

phương thức mới vào các lớp đã tồn tại,mở rộng thêm các lớp đã tồn tại

và đồng thời thêm các lớp mới và các interface mới mà không ảnh hưởng

tới các API hợp lệ.

Ví dụ,Có rất nhiều tính năng củaJava 2D API được bắt nguồn từ việc

mở rộng các thuộc tính về đồ họa trong Graphics2D. Để cung cấp các

thuộc tính mở rộng về đồ họa trong đó bao gồm cả yếu tố tương thích với

các phần mềm đồ họa khác, Graphics2D mở rộng các lớp Graphics

trong JDK1.1.

• paint

• paintAll

• update

• print

http://tailieuhay.com 19

Page 20: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

• printAll

• getGraphics

JDK 1.1 applet thông dịch ngữ cảnh đồ họa mà được đưa vào như là

một thể hiện của lớp Graphics. Để có thể truy nhập những chức năng

được thực thi trong đối tượng Graphics2D, thì một applet tương thích với

Java 2D API sẽ đưa ngữ cảnh đồ họa tới đối tượng Graphics2D:

public void Paint (Graphics g) {

Graphics2D g2 = (Graphics2D) g;

...

...

g2.setTransform (t);

}

Trong môt vài trường hợp , hay đúng hơn là mở rộng một lớp thừa kế,

Java 2D API khái quat hóa nó. Có hai kĩ thuật đã được sử dụng để khái

quat hóa các lớp kế thừa:

• Một hay nhiều lớp cha được chèn vào biểu đồ phân cấp của lớp , và

các lớp thừa kế được cập nhật để mở rộng các lớp cha mới. Kĩ thuật này

được sử dụng để thêm các phương thức và các dữ liệu thể hiện cho lớp kế

thừa.

• Một hay nhiều triển khai các interface được thêm vào lớp kế thừa .

Kĩ thuật này được sử dụng để thêm các phương thức ảo tổng quát(general

abstract methods) cho lớp kế thừa .

Ví dụ, Java 2D API khái quát hóa lớp AWT Rectangle bằng cách sử

dụng cả hai kĩ thuật Sự phân cấp cho hình chữ nhật giống như:

http://tailieuhay.com 20

Page 21: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Trong phần mềm JDK 1.1 , Rectangle là một đối tuợng mở rộng đơn

giản. Bây giờ mở rộng các lớp Rectangle2D mới và triển khai cả hai

interface Shape và Serializable. Hai lớp cha được thêm vào phân cấp của

lớp Rectangle là RectangularShape và Rectangle2D. Các Applet được

viết cho phần mềm JDK 1.1 không truy cập được các lớp mới và các phần

triển khai của các interface,nhưng điều này không ảnh hưởng bởi vì lớp

Rectangle vẫn bao gồm các phương thức và các thành phần có trong các

phiên bản trước.

1.3.2 Platform independence

Có khả năng pháp triển các ứng dụng độc lập với môi trường. Java 2D

API không đảm đương về không gian màu sắc hay là chế độ màu của

thiết bị rendering và Java 2D API có bất kì định dạng ảnh cụ thể nào.

Và chỉ độc lập về font khi các font đó đã được xây dựng sẵn(được

cung cấp như là một phần của phần mềm JDK ),hay là khi chúng được

gởi tạo bằng lập trình. Java 2D API không hỗ trợ các font xây dựng sẵn

và các font được tạo nên nhờ chương trình tạo font nhưng nó lại hỗ trợ

việc định nghĩa các font thông qua tập các glyph của nó. Mỗi glyph lại có

thể được định nghĩa bởi Shape mà bao gồm các đoạn đường thẳng và các

đường cong. Có rất nhiều kiểu font với nhiều hình dang và kich thước

được bắt nguồn từ tập các glyph đơn lẻ.

1.4 The Java 2D™ API Packages

Các lớp Java 2D API được tổ chức trong các package sau:

http://tailieuhay.com 21

Page 22: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

• java.awt

• java.awt.geom

• java.awt.font

• java.awt.color

• java.awt.image

• java.awt.image.renderable

• java.awt.print

Package java.awt bao gồm các lớp Java 2D API đã đề cập ở trên và

các interface đã tồn tại trước đó và các interface fát triển thêm. (Rõ dàng

là không phải tất cả các lớp trong java.awt là các lớp của Java 2D )

Package java.awt.geom bao gồm các classe và interface có liên quan đến

việc định nghĩa các dạng hình học nguyên thủy:

http://tailieuhay.com 22

Page 23: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Có nhiều dạng hình học nguyên thủy ứng với các phần

implementation. Float và Double

Điều này cho phép các implementation có thể ở hai mức chính xác là

giá trị single và double.

Gói java.awt.font chứa các lớp và các giao diện được sử dụng cho

việc bố trí văn bản và định nghĩa các kiểu font:

Gói java.awt.color chứa các lớp và các giao diện cho việc định nghĩa

các không gian màu và các mẫu màu:

Các gói java.awt.image và java.awt.image.renderable chứa các lớp

và các giao diện cho việc định nghĩa và tạo bóng của ảnh.

http://tailieuhay.com 23

Page 24: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Package java.awt.image tồn tại trong các version trước đó của AWT.

Java 2D API tăng cường thêm các lớp ảnh kế thừa từ AWT sau đây:

• ColorModel

• DirectColorModel

• indexColorModel

Các lớp chế độ màu sắc này vẫn tồn tại trong package

java.awt.image package cho sự tương thích .Để đảm bảo tính thống

nhất,các lớp cho chế độ màu mới cũng có trong package java.awt.image .

Package java.awt.print bao gồm các lớp và các interface cho phép in

tất cả các dạng văn bản ,đồ họa và ảnh dựa trên công nghệ Java 2D.

http://tailieuhay.com 24

Page 25: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Chương 2:

Rendering with Graphics2D

Graphics2D mở rộng java.awt.Graphics để tạo ra điều khiển tinh vi

hơn về biểu diễn các hình ,văn bản và ảnh .Quá trình tô trát Java 2D™

được điều khiển thông qua đối tượng Graphics2D và các thuộc tính

trạng thái của nó.

Các thuộc tính tạng thái Graphics2D , như là các kiểu đường thẳng và

các phép biến đổi,được áp dụng cho các đối tượng đồ họa khi chúng được

tô trát. Tập các thuộc tính trạng thái kết hợp với Graphics2D được tham

chiếu tới như là Graphics2DContext.

Để tô trát văn bản ,hình và ảnh,cần thiết lập Graphics2D context và sau

đó gọi một trong các phương thức tô trát Graphics2D như draw hay fill.

http://tailieuhay.com 25

Page 26: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

2.1 Các lớp và giao diện.

Bảng cho sau đây sẽ liêt kê các giao diện và lớp trong việc kết hợp

với ngữ cảnh Graphics2D context,bao gồm các lớp biểu diễn các thuộc

tính trạng thái. Hầu hết các lớp này là một phần của package java.awt.

Các giao diện và mô tả chúng:

Giao diện Mô tảComposite Định nghĩa các phương thức cho việc kết hợp một

đối tượng vẽ gốc với cùng đồ họa được đánh dấu.

Được thực thi bởi phương thức AlphaComposite.CompositeContex

t

Định nghĩa một môi trương tối ưu và độc lập cho

việc thực hiện các phép kết hợp .Việc thực hiện các

luật kết hợp tùy chọn được thực hiện bơit người lập

trình.Paint Mở rộng: Transparency

Định nghĩa các màu sắc cho việc tô hoặc vẽ. Được

thực thi bởi đối tượng Color,Gradient-Paint và

TexturePaint.PaintContext Định nghĩa một môi trương tối ưu và độc lập cho

việc vẽ.Các thao tác vẽ được tùy chọn bởi người lập

trình.Stroke Tạo ra một đối tượng Shape mà các đường viền của

nó đựoc tạo bóng.Được thực thi bởi phương thức

BasicStroke.

Các lớp và mô tả sơ lược về chúng:

Lớp Mô tảAffineTransform

(java.awt.geom)

Miêu tả một phép biến đổi 2D affine ,mà thực hiện

việc ánh xạ tuyến tính từ tọa độ 2D này đến tọa độ

2D khác.

http://tailieuhay.com 26

Page 27: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

AlphaComposite Thực thi : Composite

Thực hiện các luật kết hợp các giá trị alpha cơ bản cho

các đối tượng Shape,Text và Image.BasicStroke Thực thi :Stroke

Định nghĩa kiểu bút vẽ( “pen style”) được áp dụng

cho các đường bao của đối tượng Shape.

Color Thực thi: Paint

Định nghĩa một kiểu tô màu đồng nhất cho đối tượng

Shape.GradientPaint Thực thi: Paint

Định nghĩa một mẫu tô màu loang tuyến tính cho đối

tượng Shape.Mẫu này sẽ thay đổi từ màu C1 (tại điểm

P1) tới màu C2(tai điểm P2).Graphics2D Mở rộng: Graphics

Lớp cơ sở cho quá trình tạo bóng trong không gian

2D.Mở rộng lớp gốc java.awt.GraphicsTexturePaint Thực thi: Paint

Định nghĩa một kiểu tô theo mẫu cho đối tượng

Shape.Mẫu tô được tạo ra từu đối tượng

BufferedImage.

2.2 Rendering Concepts

Để tô trát một đối tượng đồ họa sử dụng Java 2D™ API, cần thiết lập

ngữ cảnh Graphics2DContext và sử dụng một trong các phương thức tô

trát Graphics2D đối với đối tượng.

Có thể thay đổi các thuộc tính trạng thái mà tạo nên ngữ cảnh

Graphics2D như :

• Thay đổi độ rộng của nét bút

• Thay đổi cho các nét bút kết hợp với nhau như thế nào.

http://tailieuhay.com 27

Page 28: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

• Thiết lập một khung cắt để giới hạn vùng được tô trát.

• Chuyển đổi tọa độ ,xoay,lấy tỉ lệ hoặc cắt cá đối tượng khi

chúng được render.

• Định nghĩa các màu và các kiểu để tô các hình.

• Xác định các đối tượng đa đồ họa(multiple graphics objects) cần

phải được tạo ra như thế nào.

Graphics2D định nghĩa một số phương thức để thêm và thay đổi các

thuộc tính trong ngữ cảnh đồ họa . Hầu hết những phương thức này là

những đối tượng biểu diễn các thuộc tính riêng biệt như đối tựơng Paint

hay Stroke .

Ngữ cảnh Graphics2D cất giữ các tham chiếu tới các đối tương thuộc

tính . Nếu biến đổi một đối tượng thuộc tính mà là một phần của ngữ cảnh

Graphics2D ,thì cần phải gọi phương thức thiết lập phù hợp để khai báo

ngữ cảnh.Thay đổi một đối tượng trong quá trình thao tác render sẽ gây

nên một số biểu hiện bất thương thường và không ổn định .

2.2.1 Rendering Process

Khi một đối tượng đồ họa được render, thông tin về hình học ,ảnh và

thuộc tính được kết hợp để tính toán những giá trị điểm ảnh cần phải thay

đổi trên màn hiển thị.

Quá trình render cho một đối tượng Shape có thể được chia thành 4 bước

:

1. Nếu đối tượng Shape được taọ nét ,đối tượng Stroke quy vào ngữ

cảnh Graphics2D được sử dụng để tạo nên một đối tượng Shape mới

bao quanh những đường nét đó .

2. Tọa độ của đường thuộc đối tượng Shape được biến đổi từ không

gian người sử dụng sang không gian của thiết bị theo các thuộc tính biến

đổi trong ngữ cảng đồ họa Graphics2D .

http://tailieuhay.com 28

Page 29: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

3. Đường (path)của đối tượng Shape được cắt bỏ bằng cách sử dụng

các thuộc tính cắt trong ngữ cảnh Graphics2D.

4. Phần còn lại của đối tượng Shape được tô băng cách sử dụng

thuộc tính của đối tượng Paint và Composite thuộc tính trong ngữ cảnh

của đối tượng Graphics2D.

Tạo bóng (Rendering) văn bản tương đương với việc tạo bóng các đối

tượng thuộc kiểu Shape, khi đó văn bản được tạo bóng với từng glyph và

mỗi glyph là một đối tượng thuộc kiểu Shape. Chỉ có điều khác là Java

2D API phải xác định đối tượng Font nào sử dụng cho văn bản và lấy

kiểu glyph tương ứng từ đối tượng Font trước khi tạo bóng.

Đối với ảnh thì có sự khác biệt , sự chuyển đổi và thực hiện các phép

cắt bỏ với hộp xác định biên ảnh( image’s bounding box). Thông tin về

màu sắc lấy từ chính ảnh đó và nguồn alpha(alpha channel) được sử dụng

kết hợp với thuộc tính hiện tại của Composite khi các điểm ảnh được

hợp trên bề mặt tạo bóng.

2.2.2 Controlling Rendering Quality

Java 2D API đưa ra các lựa chọn cho phép người sử dụng tạo bóng

nhanh hay tạo bóng với chất lượng cao. Những tham chiếu của người su

dụng được xác định như là các chỉ dẫn thông qua thuộc tính của đối tượng

RenderingHints trong ngữ cảnh của đối tượng Graphics2D . Không phải

tất cả các môi trường đều hỗ trợ việc thay đổi chế độ tạo bóng vì vậy xác

định các chỉ dẫn cho quá trình tạo bóng sẽ không được đảm bảo chúng sẽ

được sử dụng hay không .

Lớp RenderingHints hỗ trợ cá kiểu chỉ dẫn sau đây:

• Alpha interpolation - có thể thiết lập tùy chọn default, quality,

speed.

• Antialiasing - có thể thiết lập tùy chọn default :on hoặc off.

http://tailieuhay.com 29

Page 30: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

• Color Rendering - có thể thiết lập tùy chọn default, quality, hoặc

speed.

• Dithering - có thể thiết lập tùy chọn default:disable, enable.

• Fractional Metrics - có thể thiết lập tùy chọn default, on, hoặc off.

• Interpolation- có thể thiết lập tùy chọn nearest-neighbor, bilinear,

hoặc bicubic.

• Rendering - có thể thiết lập tùy chọn default, quality, hoặc speed.

• Text antialiasing - có thể thiết lập tùy chọn default: on hoặc off.

Để thiết lập hoặc thay đổi các thuộc tính RenderingHints trong ngữ

cảnh của đối tượng Graphics2D thì gọi phương thức setRenderingHints.

Khi một chỉ dẫn được thiết lập măc định ,môi trường tạo bóng mặc định

sẽ được sử dụng .

Kĩ thuật làm trơn(Antialiasing)

Khi các thực thể cơ sở được tạo bóng trên thiết bị hiển thị ,các

biên(cạnh) của chúng có thể không trơn hay nhám là do thuộc tính

aliasing. Các đường cung và đường chéo có dạng nhám bởi vì chúng

được xấp xỉ bởi các điểm ảnh mà gần nhất về hìn dạng với chúng . Đây là

điều mà chúng ta có thể nhận thấy với các thiết bị trước đây với các cạnh

nhám xuất hiện trái ngược hoàn toàn với các cạnh trơn của đườgn nằm

ngang hay thẳng đứng.

Antialiasing là một kĩ thuật được sử dụng để tạo bóng các đối tượng

với các cạnh trơn hơn. Thay vì sử dụng các điểm ảnh gẩn giống với các

đường chéo và đường cong ,tăng mật độ các điểm ảnh bao quanh tới các

vùng được tạo bóng. Điều này làm cho cách cạnh trơn hơn và trải rộng sự

chuyển tiếp bật/tắt với các pixel đa điểm(multi pixel) . Tuy nhiên kĩ thuật

antialiasing đòi hỏi nhiều về tài nguyên máy tính và làm tăng thời gian tạo

bóng.

http://tailieuhay.com 30

Page 31: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

2.2.3 Stroke Attributes

Tạo nét một đối tượng thuộc kiểu Shape như đối tượng GeneralPath

tương đươnng với việc sử dụng một bút lôgíc theo các đoạn của đối tượng

GeneralPath. Thuộc tính của Graphics2DStroke định nghĩa các tính

chất của nét bút vẽ.

Đối tượng BasicStroke được sử dụng để định nghĩa các thuộc tính

đường nét cho một ngữ cảnh của Graphics2D. BasicStroke đinh nghĩa

các thuộc tính như độ rộng cuả nét vẽ ,mẫu tô…

Để thiết lập hay thay đổi các thuộc tính Stroke trong ngữ cảnh của

Graphics2D thì gọi phương thức setStroke.

Như ví du,ảnh đầu tiên trong hình 2-3 sử dụng miter join-style,và hình

thứ hai sử dụng kiểu round join-style, a round endcap style, and a dashing

pattern.

http://tailieuhay.com 31

Page 32: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Các phương thức tạo bóng Graphics2D có sử dụng thuộc tính của

Stroke để vẽ như drawArc, drawLine, drawOval, drawPolygon,

drawPolyline, drawRect, và

drawRoundRect.Khi một trong các phương thức được gọi thì các đường

nét của đối tượng Shape đã xác định sẽ được tậo bóng. Thuộc tính

Stroke định nghĩa các tính chất của đường thẳng và các thuộc tính của

Paint định nghĩa màu sắc hay mẫu của nét bút. Ví dụ phương thức

draw(myRectangle) được gọi:

1. Thuộc tính của Stroke sẽ quy định cho đường nét của hình chữ nhật .

2. Các đường nét này sẽ được biến đổi thành một đối tượng kiểu Shape

.

3. Đối tượng Paint is được áp dụngcác điểm ảnh thuộc miền giới hạn

bởi đường bao của đối tựơng Shape.

Quá trình xử lý này được minh hạo trong hình 2-4:

2.2.4 Fill Attributes

Thuộc tính tô màu trong ngữ cảnh Graphics2D được biểu diễn bởi

đối tượng Paint. Có thể thêm một đối tượng vào ngữ cảnh của đối tượng

Graphics2D (Graphics2D context) bằng cách gọi phương thức setPaint.

Khi một đối tượng Shape hay là các glyph được vẽ (bởi các phương thức

Graphics2D.draw, Graphics2D.drawString),

http://tailieuhay.com 32

Page 33: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Đối tượng Paint này sẽ được áp dụng tới tất cả các pixel nằm trong

đối tượng Shape mà biểu diễn các đường nét bao quanh đối tượng . Khi

một đối tượng Shape được tô màu (Graphics2D.fill), đối tượng Paint

được áp dụng tới tất cả các điểm ảnh nằm trong đường bao của đối tượng

Shape.

Các kiểu tô màu đồng nhất đơn giản (solid color) được khởi tạo bởi

phương thức setColor.Color là phần triển khai (implementation) đơn giản

nhất của giao tiếp Paint (Paint interface).

Để tô các hình với các kiểu tô phức tạp hơn như là tô loang(gradient)

và tô dệt ( texture) bằng cách sử dụng các lớp trong Java 2D Paint là

GradientPaint và TexturePaint. Các lớp này sẽ loại bỏ các công việc

tiêu tốn thời gian để tạo các kiểu tô phức tạp bằng cách sử dụng các kiểu

tô mầu đồng nhất đơn giản .

Khi gọi phưong thức fill để tạo bóng một đối tượng Shape,thì hệ

thống sẽ:

1. Xác định các điểm ảnh nào để thể hiện đối tượng đó.

2. Xác định màu cho mỗi điểm ảnh từ đối tựợng Paint.

3. Chuyển các màu này tới giá trị điểm ảnh tương ứng cho các

thiết bị hiển thị.

4. Ghi các điểm ảnh ra thiết bị hiển thị đó.

http://tailieuhay.com 33

Page 34: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Quá trình xử lý theo phiên

Để tổ chức hợp lý quá trình xử lý các điểm ảnh , Java 2D API tổ chức

chúng theo từng phiên.

Mỗi phiên có thể là tập các điểm ảnh kề nhau trên một đường quét

hay là một khối (block)các điểm ảnh. Quá trình xử lý theo phiên được

thực hiện theo 2 bước:

1. Phương thức createContext của đối tượng paint được gọi để tạo

một đối tượng PaintContext. Đối tượng PaintContext này sẽ lưu thông

tin ngữ cảnh về thao tác tạo bóng hiện thời và những thông tin cần thiết

để tạo ra các màu. Phương thức createContext method is passed the

bounding boxes of thegraphics object being filled in user space and in

device space,đối tượng ColorModel là nơi để tạo các màu sắc,và thực

hiện quá trình chuyển đổi để ánh xạ từ không gian người sử dụng vào

không gian của thiết bị. Đối tượng ColorModel xem như một chỉ dẫn

không phải tất cả các đối tượng Paint có thể hỗ trợ một đối tượng

ColorModel bất kỳ.

2. Phương thức getColorModel được gọi để nhận giá trị của đối tượng

ColorModel cho màu vẽ từ đối tượng PaintContext.

Phương thức getRaster sau đó được gọi lặp lại nhiều lần để nhận giá

trị của đối tựợng Raster mà bao gồm dữ liệu màu thật cho mỗi phiên.

Thông tin này passed to the next stage in the rendering pipeline, mà vẽ

các màu đã được tạo bằng cách sử dụng đối tựợng Composite hiện thời .

2.2.5 Clipping Paths

Một khung nhìn sẽ xác định phần của đối tượng Shape hay Image

cần được tạo bóng . Khi một khung nhìn là một phần của ngữ cảnh của

đối tượng Graphics2D, thì chỉ những phần của đối tượng Shape hay

image nằm trong khung nhìn đó mới được tạo bóng.

http://tailieuhay.com 34

Page 35: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Để thêm khung nhìn cho ngữ cảnh của Graphics2D thì goị phương

thức setClip. Bất kì đối tượng Shape cũng có thể được sử dụng để định

nghĩa một khung nhìn.

Để thành đổi khung nhìn cần phải sử dụng phương thức setClip để

xác định một khung nhìn mới hay là gọi phương thức clip để thay đổi

khung nhìn cho phần giao nhau giữa khung nhìn cũ và một đối tượng

Shape.

2.2.6 Transformations

Ngữ cảnh của đối tượng Graphics2D bao gồm một phép bién đổi mà

được sử dụng để biến đổi những đối tượng từ không gian người sử dụng

vào không gian thiết bị trong quá trình tạo bóng. Để thực hiện các phép

biến đổi khác như phép quay hay lấy tỉ lệ thì cần phải thêm các phép biến

đổi khác vào ngữ cảnh của đối tượng.Các phép biến đổi được thêm vào

này sẽ trở thành một phần của ống biến đổi (pipeline of transformations)

mà được ápdụng trong suôt qua trình tạo bóng.

Graphics2D cung cấp một vài cách khác để thay đổi phép biến đổi

trong ngữ cảnh của đối tượng Graphics2D . Cách đơn giản nhất là gọi

một trong các phương thức biến đổi trong đối tượng Graphics2D như :

rotate, scale, shear, hay translate. Xác định các tính chất của phép biến

đổi để áp dụng trong suốt qúa trình tạo bóng và Graphics2D tự động tạo

ra các thay đổi phù hợp.

Cũng có thể nối một phép biến đổi AffineTransform với phép biến

đổi Graphics2D hiện tại. Phép biến đổi AffineTransform thực hiện các

phép biến đổi cho đường như phép dịch,tỉ lệ ,quay và cắt bỏ với tập các

hình cơ bản.

Khi một phép biến đổi được nối vào phép biến đổi đã tồn tại trước đó

thì phép biến đổi sau cùng sẽ được xác định như là phép biến đổi được

http://tailieuhay.com 35

Page 36: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

thực hiện đầu tiên. Để tiếp nối một phép biến đổi với phép biến đổi hiện

tại , you pass an AffineTransform to Graphics2D.transform.

Lớp Graphics2D cũng bao gồm phương thức setTransform , nhưng

phương thức này không bao giờ được sử dụng để nối với các phép biến

đổi tọa độ khác của phép biến đổi đang tồn tại. Phương thức setTransform

sẽ ghi đè lên phép biến đổi hiện thời của đối tượng Graphics2D, nhưng

phương thức này cần cho môt số mục đích khác như:

• Áp dụng phép biến đổi tỉ lệ điều chỉnh cho máy in.

• Vẽ một đối tượng JComponent non-zero translation from its

parent’s origin

• Phóng to một thành phần để dễ dàng quan sát.

• Các tình huống khác mà người cung cấp đối tượng Graphics2D

muốn chuyển đổi cho quá trình tạo bóng hiệu quả .

Phương thức setTransform method được xem như để thiết lập đối

tượng Graphics2D trở lai phép biến đổi ban đầu sau quá trình tạo bóng

đồ họa ,văn bản và ảnh đã được chuyển đổi:

AffineTransform aT = g2d.getTransform();

g2d.transform(...);

g2d.draw(...);

g2d.setTransform(aT);

Graphics2D cũng cung câp một phiên bản về drawimage mà trong đó

đối tượng AffineTransform

Được xem như một tham số . Điều này cho phép áp dụng một phép

biến đổi cho đối tượng ảnh khi nó được vẽ mà không cần chỉnh sửa

đường ống cuả phép biến đổi. Ảnh này được được vẽ như khi kết nối

http://tailieuhay.com 36

Page 37: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

phép biến đôit này với phép biến đôit hiện tại trong ngữ cảnh của

Graphics2D

Các phép biến đổi quan hệ(Affine Transforms)

Java 2D API cung cấp một lớp biến đổi là AffineTransform.

AffineTransforms được sử dụng để biến đổi văn bản ,hình và các ảnh

khi chúng được tạo bóng.

Cũng có thể ứng dụng các phép biến đổi cho đối tượng Font để tạo ra

các dẫn xuất font mới(new font derivations).

Một phép biến đổi đồng nhất (affine transformation) thực hiện một phép

biến đổi tuyến tính trên tập đồ hạo cơ bản. Nó luôn biến các đường thẳng

thành các đường thẳng và các đường thẳng song song thành các đường

thẳng song song,tuy nhiên khoảng cách giữa các điểm và các góc của các

đường thẳng không song song có thể thay đổi.

Các phép biến đổi có thể kết hợp để tạo ra đường ống các phép biến

đổi một cách hiệu quả nhằm áp dụng cho một đối tượng nào đó. Sự kết

hợp này xem như là sự móc nối. Khi một phép biến đổi được kết nối với

một phép biến đổi đang tồn tại như với AffineTransform.concatenate,

thì phép biến đổi cuối cùng được xác định là phép biến đổi đầu tiên được

áp dụng . Một phép biến đổi cũng có thể được móc nối trước với một

phép biến đổi đang tồn tại . Trong trường hợp này thì phép biến đổi cuối

cùng sẽ được thực hiện cuối cùng . Phép móc nối trước được được áp

dụng để thực hiện các phép biến đổi có liên quan với không gian thiết bị

thay vì không gian người sử dụng. Ví dụ có thể sử dụng phương thức

AffineTransform.preConcatenate để thực hiện phép chuyển đổi có liên

quan tới không gian các điểm ảnh..

2.2.6.1 Constructing an AffineTransform

http://tailieuhay.com 37

Page 38: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

AffineTransform cung cấp một tập các phương thức cho việc xây

dựng các đối tượng AffineTransform.

• getTranslateinstance

• getRotateinstance

• getScaleinstance

• getShearinstance

Để sử dụng các phương thức này cần phải xác định các tính chất của

phép biến đổi mà cần tạo ra và lớp AffineTransform sẽ tạo ra các ma

trận chuyển đổi phù hợp. Cũng có thể xây dựng phép biến đổi đòng nhất

một cách trực tiếp mà không cần thông qua lớp AffineTransform bằng

cách xác định các thành phần của phép biến đổi đó.

2.2.7 Composite Attributes

Khi hai đối tượng đồ họa trồng lên nhau thì điều cần thiết là phải xác

định những màu nào sẽ được tạo bóng cho các điểm ảnh chồng lên nhau.

Ví dụ nếu một hình chữ nhật màu đỏ và một hình chữ nhật màu xanh

chồng lên nhau thì các điểm ảnh đó sẽ có màu đỏ hoặc màu xanh hay là

sự kết hợp của cả hai màu. Màu của những điểm ảnh trong vùng chồng

nhau đó sẽ xác định hình chữ nhật nào nằm trên và bị che khuất như thế

nào. Quá trình xử lý để xác định màu nào tạo bóng cho các điểm ảnh sẽ

được chia sẽ cho các đối tượng chồng (overlaping objects)được gọi

compositing.

Có hai interface tạo các kiểu kết hợp cơ bản trong Java 2D là :

Composite và CompositeContext.

Để xác định các kiểu kết hợp sẽ được sử dụng thì cần phải thêm vào

một đối tượng AlphaComposite cho ngữ cảnh của đối tượng

Graphics2D bằng cách gọi phương thức setComposite.

AlphaComposite,và một triển khai(implementation) của interface

Composite , có hỗ trợ một số kiểu kết hợp khác nhau . Mỗi đối tượng của

http://tailieuhay.com 38

Page 39: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

lớp này là một luật kết hợp để mô tả sự pha trộn một màu mới với màu

đang tồn tại..

Một trong những luật kết hợp trong lớp AlphaComposite là SRC_OVER,

luật này chỉ ra màu mới (màu nguồn) sẽ được pha trộn với màu đang tồn

tại (màu đích ) như thế nào.

2.2.7.1 Managing Transparency

Giá trị alpha của một màu là giá trị đo đọ trong suôt của màu đó ,nó

chỉ ra (theo phần trăm) bao nhiêu phần trăm màu trước khi tô được hiển

thị ra khi các màu chồng lên nhau. Các màu tối (co giá tri alpha=1.0) thì

các màu tô đè lên chúng sẽ không được hiển thị, trong khi đó các màu

trong suốt (có giá trị alpha=0.0) cho phép các màu tô đè lên nó được hiển

thị.

Khi văn bản và hình được tạo bóng thì giá trị alpha sẽ bắt nguồn từ

thuộc tính của đối tượng Paint trong ngữ cảnh của đối tượng

Graphics2D . Khi các hình và văn bản được làm trơn thì giá trị alpha từ

thuộc tính Paint (trong ngữ cảnh của Graphics2D) được kết hợp với

thông tin về các điểm ảnh bị che từ “rasterized path”. Các ảnh lưu thông

tin về giá trị alpha của chính nó .

Khi tạo một đối tượng AlphaComposite , có thể xác định được giá trị

alpha được thêm vào . Khi thêm đối tượng AlphaComposite này tới ngữ

http://tailieuhay.com 39

Page 40: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

cảnh của Graphics2D ,giá trị alpha thêm vào này sẽ làm tăng giá trị trong

suốt của bất kì đối tượng đồ họa nào khi chúng được tạo bóng - giá trị

alpha của mỗi đối tượng đồ họa được nhân lên bởi giá trị alpha của đối

tượng AlphaComposite.

2.2.7.2 Transparency and images

Các ảnh có thể lưu thông tin về độ trong suốt cho mỗi điểm ảnh của

nó. Thông tin này đựoc gọi là kênh alpha( alpha channel,) ,nó được sử

dụng kêts hợp với đối tượng Composite trong ngữ cảnh của Graphics2D

để pha trộn màu của ảnh đó các đồ họa đang tồn tại.

2.3 Thiết lập Graphics2Context

Để cấu hình ngữ cảnh Graphics2D cho quá trình tạo bóng phải sử

dụng các phương thức khởi tạo cho đối tượng Graphics2D để xác định

các thuộc tính như RenderingHints, Stroke, Paint,Clipping path,

Composite, and Transform.

2.3.1 Setting Rendering Hints

Đối tượng RenderingHints đóng gói tất các tham chiếu để xác định

một đối tượng sẽ được tạo bóng như thế nào . Để tạo các chỉ dẫn cho quá

http://tailieuhay.com 40

Page 41: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

trình tạo bóng trong ngữ cảnh Graphics2D ,thì cần tạo một đối tượng

RenderingHints và chuyển nó vào lớp Graphics2D.setRendering

Tạo chỉ dẫn cho quá trình tạo bóng sẽ không đảm bảo việc sẽ sử dụng

một thuật toán tạo bóng cụ thể: không phải môi trường cũng hỗ trợ chế độ

tạo bóng .

Trong ví dụ cho sau đây thì cho phép sử dụng kĩ thuật làm trơn

(antialiasing) và tạo ra các tham chiếu để xác định chất lượng cho quá

trình tạo bóng:

qualityHints = new

RenderingHints(RenderingHints.KEY_ANTiALiAS

iNG,

RenderingHints.VALUE_ANTiALiAS_ON);

qualityHints.put(RenderingHints.KEY_RENDERi

NG,

RenderingHints.VALUE_RENDER_QUALiTY);

g2.setRenderingHints(qualityHints);

2.3.2 Specifying Stroke Attributes

Một đối tượng BasicStroke sẽ định nghĩa các tính chất đuwoc áp

dụng cho đường viền bao quanh một đối tượng Shape, gồm có độ rộng và

kiểu đường (dashing pattern),để làm thế nào các đoạn thẳng được kết hợp

với nhau. Để khởi tạo các thuộc tính về đường nét trong ngữ cảnh

Graphics2D ,thì khởi tạo một đối tượng BasicStroke và chuyền nó vào

phương thức setStroke

2.3.2.1 Setting the Stroke Width

Để khởi tạo độ rộng đường nét thì khởi tạo đối tượng BasicStroke với

độ rộng mong muốn và sau đó gọi phương thức setStroke

http://tailieuhay.com 41

Page 42: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Trong ví dụ cho sau đây ,độ rộng đường nét được khởi tạo với 12

điểm và giá trị mặc định được sử dụng cho việc bố trí kiểu jont và kiểu

endcap.

wideStroke = new BasicStroke(12.0f);

g2.setStroke(wideStroke);

2.3.2.2 Specifying Join and Endcap Styles

Để khởi tạo cho các kiểu join và endcap ,cần tạo một đối tượng

BasicStroke với các thuộc tính mong muốn .

Trong ví dụ cho sau đây,độ rộng đường nét được khởi tạo với 12 điểm

và các kiểu join và endcap được sử dụng thay cho các gia tri mặc định:

roundStroke = new BasicStroke(4.0f,

BasicStroke.CAP_ROUND,

BasicStroke.JOiN_ROUND);

g2.setStroke(roundStroke);

2.3.2.3 Setting the Dashing Pattern

Các kiểu đường phức tạp có thể dễ dàng được định nghĩa với một đối

tượng BasicStroke.

Khi tạo một đối tượng BasicStroke ,phải xác định 2 tham số để kiểm

soát kiểu đường:

• dash - là một mảng biểu diễn kiểu đường. Các phần tử xen kẽ

của mảng biểu diễn kích thước nét gạch và khoảng cách giữa các nét

gạch .

Phần tử 0 biểu diễn nét gạch đầu tiên, phần tử thứ 1 biểu diễn khoảng

trắng đầu tiên.

http://tailieuhay.com 42

Page 43: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

• dash_phase - là một offset định nghĩa nơi bắt đầu của mẫu nét

gạch.

Trong ví dụ sau đây, hai mẫu nét gạch được áp dụng cho một đường

thẳng. Trong mẫu thứ nhất ,kích thước của các nét gạch và khoảng trống

giữa chúng là không thay đổi. Mẫu thứ hai thì phức tạp hơn ,sử dụng

mảng sáu phần tử để định nghĩa

float dash1[] = {10.0f};

BasicStroke bs = new BasicStroke(5.0f,

BasicStroke.CAP_BUTT,

BasicStroke.JOiN_MiTER, 10.0f, dash1,

0.0f);

g2.setStroke(bs);

Line2D line = new Line2D.Float(20.0f,

10.0f, 100.0f, 10.0f);

g2.draw(line);

float[] dash2 = {6.0f, 4.0f, 2.0f,

4.0f, 2.0f, 4.0f};

bs = new BasicStroke(5.0f,

BasicStroke.CAP_BUTT,

BasicStroke.JOiN_MiTER, 10.0f, dash2,

0.0f);

g2.setStroke(bs);

g2.draw(line)

Cả hai mẫu đều sử dụng offset(địa chỉ bắt đầu của hai mẫu) 0 khi đó

các nét gạch đầu tiên sẽ ổ vị trí đầu của mẫu. Hai mẫu này được minh họa

trong hình2-7

http://tailieuhay.com 43

Page 44: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

2.3.3 Specifying Fill Attributes

Thuộc tính cảu đối tượng Paint trong ngữ cảnh Graphics2D xác

định các màu tô hay các mẫu (kiểu )tô khi một đối tượng văn bản và

Shape được tạo bóng.

2.3.3.1 Filling a Shape with a Gradient

Lớp GradientPaint cung cấp một cách đơn giản để tô một hình bằng

kiểu tô loang . Khi khởi tạo đối tượng GradientPaint, cần xác định vị trí

đầu tiên cùng với màu tô và vị trí cuối cùng một màu tô. Kiểu tô này sẽ

thay đổi tỉ lệ từ màu này sang màu khác dọc theo đường nối của hai vị trí

đã chọn, minh họa trong hình 2-8.

Trong ngôi sao thứ ba,cả hai điểm đều nằm trong cùng một hình.Tất

cả các điểm dọc theo đường tô loang mở rộng qua điểm P1 sẽ nhận được

màu ban đầu và các điểm dọc theo đường tô loang được mở rộng ngoài

điểm P2 sẽ nhận màu kết thúc.

Các bước cần thực hiện để tô loang theo hai màu:

1. Khởi tạo đối tượng GradientPaint .

2. Gọi phương thức Graphics2D.setPaint.

3. Khởi tạo đối tượng Shape.

http://tailieuhay.com 44

Page 45: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Trong ví dụ sau đây, một hình chữ nhật được tô với mẫu dệt đơn giản

từ một đối tượng buffered image.

GradientPaint gp = new

GradientPaint(50.0f, 50.0f, Color.blue

50.0f, 250.0f, Color.green);

g2.setPaint(gp);

g2.fillRect(50, 50, 200, 200);

2.3.3.2 Filling a Shape with a Texture

Lớp TexturePaint cung cấp một cách đơn giản để tô hình bằng mẫu lặp.

Khi tạo một đối tượng Bufferedimage để sử dụng như là một mẫu tô. Cần

chuyển hàm khởi tạo một hình chữ nhật để định nghĩa tần số lặp cho

mẫu ,được chi ra trong hình 2-9.

Để tô hình theo mẫu dệt:

1. Tạo đối tượng TexturePaint

2. Gọi phương thức Graphics2D.setPaint.

3. Tạo đối tượng Shape.

4. Gọi phương thức Graphics2D.fill(shape).

Trong ví dụ sau đây, một hình chữ nhật được tô với mẫu dệt

đơn giản từ một đối tượng bufferedimage.

// Create a buffered image texture patch

of size //5x5

Bufferedimage bi = new Bufferedimage(5, 5,

Bufferedimage.TYPE_iNT_RGB);

Graphics2D big = bi.createGraphics();

big.setColor(Color.green);

http://tailieuhay.com 45

Page 46: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

big.fillRect(0,0,5,5);

big.setColor(Color.lightGray);

big.fillOval(0,0,5,5);

// Create a texture paint from the

buffered image

Rectangle r = new Rectangle(0,0,5,5);

TexturePaint tp = new

TexturePaint(bi,r,TexturePaint.NEAREST_NEiGHBOR);

// Add the texture paint to the graphics

context. g2.setPaint(tp);

// Create and render a rectangle filled

with the texture. g2.fillRect(0,0,200,200);

}

2.3.4 Setting the Clipping Path

Để định nghĩa một khung nhìn:

1. Khởi tạo một đối tượng Shape mà biểu diễn vùng muốn tạo

bóng.

2. Gọi phương thức Graphics2D.setClip để sử dụng đối tuợng

shape như là một khung nhìn cho ngữ cảnh Graphics2D .

Để thu hẹp khung nhìn:

1. Khởi tạo đối tượng Shape mà giao với khung hnìn hiện tại.

2. Gọi phương thức clip để thay đổi khung nhìn cho phần giao

nhau của khung nhìn hiện tại và đối tượng Shape mới.

Trong ví dụ cho sau đây, một khung nhìn được tạo ra từ một elip và

sau đó được thay đổi băng cách gọi phương thức clip.

public void paint(Graphics g) {

http://tailieuhay.com 46

Page 47: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Graphics2D g2 = (Graphics2D) g;

// The width and height of the canvas

int w = getSize().width;

int h = getSize().height;

// Create an ellipse and use it as

the clipping path

Ellipse2D e = new

Ellipse2D.Float(w/4.0f,h/4.0f,

w/2.0f,h/2.0f);

g2.setClip(e);

// Fill the canvas. Only the area

within the clip is rendered

g2.setColor(Color.cyan);

g2.fillRect(0,0,w,h);

// Change the clipping path, setting

it to the intersection of

// the current clip and a new

rectangle.

Rectangle r = new

Rectangle(w/4+10,h/4+10,w/2-20,h/2-20);

g2.clip(r);

// Fill the canvas. Only the area

within the new clip

// is rendered

http://tailieuhay.com 47

Page 48: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

g2.setColor(Color.magenta);

g2.fillRect(0,0,w,h);

2.3.5 Setting the Graphics2D Transform

Để biến đổi đối tượng Shape,xâu văn bản, hay ảnh cần phải thêm vào

một phép biến đổi mới AffineTransform cho đường ống phép biến đổi

tronh ngữ cảnh của Graphics2D trước khi tạo bóng . phép biến đổi được

áp dụng khi đối tượng đồ họa được tạo bóng .

Ví dụ để vẽ một hình chữ nhật nghiêng 45 độ:

1. Lấy một phép biến đổi Graphics2D trước khi thực hiện bất

kì phép biến đổi nào . Luôn gọi phương thức getTransform

trong đối tượng Graphics2D trước khi thêm vào một phép biến

đổi cho ngữ cảnh đồ họa bởi vì ngữ cảnh đồ họa có thể đã tồn

tại một phép biến đổi cho một lí do khác ,định vị Swing và các

thành phần trong một cửa sổ.

2. Lấy phép quay bằng cách gọi AffineTransform.

getRotateinstance.

3. Gọi phương thức Graphics2D.transform để thêm vào các

phép biến đổi mới cho đường ống biến đổi. Không được sử

dụng phương thức setTransform để thêm một phép biến đổi tọa

độ mới,bởi vì setTransform sẽ ghi đè lên phép biến đổi hiện tại

trong ngữ cảnh đồ họa

1. 4.Tạo đối tượng Rectangle2D.Float .

4. Gọi phươn thức Graphics2D.draw để tạo bóng hình chữ

nhật.

5. Sau khi tạo bóng cho hình chữ nhật đã được biến đổi , thì

reset phép biến đổi của Graphics2D trở về phép biến đổi ban

http://tailieuhay.com 48

Page 49: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

đầu mà đã lưu trong bước 1 bằng cách gọi phương thức

setTransform cho phép biến đổi ban đầu .

Trong ví dụ sau đây, một thể hiện của AffineTransform được sử

dụng để quay hình chữ nhật đi 45 độ khi nó được tạo bóng.

AffineTransform aT = g2.getTransform();

Rectangle2D rect = new

Rectangle2D.Float(1.0,1.0,2.0,3.0);

AffineTransform rotate45 =

AffineTransform.getRotateinstance(Math.Pi

/4.0,0.0,0.0)

g2.transform(rotate45);

g2.draw(rect);

g2.setTransform(aT);

Còn trong ví dụ này,một đối tượng AffineTransform được sử dụng

để quay các câu text xung quang một điểm trung tâm.

// Define the rendering transform

AffineTransform at = new

AffineTransform();

// Apply a translation transform to

make room for the

// rotated text.

http://tailieuhay.com 49

Page 50: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

at.setToTranslation(400.0, 400.0);

g2.transform(at);

// Create a rotation transform to

rotate the text

at.setToRotation(Math.Pi / 2.0);

// Render four copies of the string

“Java” at 90 degree angles

for (int i = 0; i < 4; i++) {

g2.drawString(“Java”, 0.0f, 0.0f);

g2.transform(at);

}

Có thể biến đổi ảnh trong cách tương tự -phép biến đổi trong ngữ

cảnh Graphics2D được áp dụng trong quá trình tạo bóng mà không cần

quan tâm đến kiểu đối tượng đồ hạo đang được tạo bóng

Để áp dụng phép biến đổi cho ảnh mà không cần thay đổi phép biến

đổi trong ngữ cảnh Graphics2D , thì chuyển AffineTransform sang

drawimage:

AffineTransform rotate45 =

AffineTransform.getRotateinstance(Math.Pi

/4.0,0.0,0.0)

g2.drawimage(myimage, rotate45);

Các phép biến đổi cũng được áp dụng cho đối tượng Font để tạo ra

một kiểu.

http://tailieuhay.com 50

Page 51: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

2.3.6 Specifying a Composition Style

Một đối tượng AlphaComposite chứa các luật kết hợp để xác định

các màu sẽ được tạo bóng như thế nào khi đối tượng nàu đè lên đối tượng

khác . Để xác định các kiểu kết hợp cho ngữ cảnh Graphics2D , cần tạo

một đối tượng AlphaComposite và chuyền nó vào phương thức

setComposite. Kiểu thông dụng nhất là SRC_OVER.

2.3.6.1 Using the Source Over Compositing Rule

Luật kết hợp SRC_OVER sẽ kết hợp các điểm ảnh nguồn (source

pixel) với các điểm ảnh đích (destination pixel). Ví dụ ,nếu tạo bóng một

hình chữ nhật màu xanh nước biển (blue) và sau đó tạo bóng một hình

chữ nhật màu đỏ mà đè lên một phần của hình chữ nhật kia,thì vùng giao

nhau đó sẽ có màu đỏ. Hay nói cách khác ,đối tương mà được tạo bóng

cuối cùng sẽ xuất hiện ở trên cùng .

Để sử dụng luật kết hợp SRC_OVER :

1. Tạo một đối tượng AlphaComposite bằng cách gọi phương

thức getinstance và xác định luật

SRC_OVER .

AlphaComposite ac

=AlphaComposite.getinstance(AlphaComposite.SRC_OV

ER);

2. Gọi phương thức setComposite để thêm đối tuợng

AlphaComposite cho ngữ cảnh của Graphics2D.

g2.setComposite(ac);

Mỗi khi đối tượng kết hợp này được thiết lập ,thì đối tượng đè lên

được tạo bóng bằng cách sử dụng luật kết hợp đã xác định.

2.3.6.2 Increasing the Transparency of Composited Objects

http://tailieuhay.com 51

Page 52: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

AlphaComposite cho phép xác định một giá trị hằng số alpha thêm

vào mà được nhân với giá trị alpha của các điểm ảnh nguồn để tăng độ

trong suốt.

Ví dụ ,để khởi tạo một đối tượng AlphaComposite mà tạo bóng đối

tượng nguồn có độ trong suốt là 50% ,xác định một giá trị alpha là .5:

AlphaComposite ac

=AlphaComposite.getinstance(AlphaComposite.SRC_OV

ER, .5f);

Trong ví dụ cho sau đây, a source over alpha composite object is

created with an alpha of .5 and added to the graphics context, causing

subsequent shapes to be

rendered 50% transparent.

public void paint(Graphics g) {

Graphics2D g2 = (Graphics2D) g;

g2.setColor(Color.red);

g2.translate(100,50);

// radians=degree * pie / 180

g2.rotate((45*java.lang.Math.Pi)/180);

g2.fillRect(0,0,100,100);

g2.setTransform(new AffineTransform()); //

set to identity

// Create a new alpha composite

AlphaComposite ac =

http://tailieuhay.com 52

Page 53: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

AlphaComposite.getinstance(AlphaComposite.SR

C_OVER,0.5f);

g2.setComposite(ac);

g2.setColor(Color.green);

g2.fillRect(50,0,100,100);

g2.setColor(Color.blue);

g2.fillRect(125,75,100,100);

g2.setColor(Color.yellow);

g2.fillRect(50,125,100,100);

g2.setColor(Color.pink);

g2.fillRect(-25,75,100,100);

}

2.4 Rendering Graphics Primitives

Graphics2D cung cấp các phương thưc tạo bóng cho các cơ sở đồ

họa như Shapes, Text, và images:

• draw—tạo nét cho đường viền của đối tựợng Shape bằng cách sử

dụng các đối tượng Stroke và Paint trong ngữ cảnh Graphics2D .

• fill—tô một đối tượng Shape bằng cách sử dụng đối tượng Paint

trong ngữ cảnh Graphics2D .

• drawString—tạo bóng các xâu văn bản đã dược xác định bằng cách

sư dụng đối tượng Paint trong ngữ cảnh Graphics2D .

• drawimage—tạo bóng các ảnh đã được xác định

2.4.1 Drawing a Shape

Đường biên của bất kì đối tượng Shape cũng được tạo bóng bằng

phương thức Graphics2D.draw.

http://tailieuhay.com 53

Page 54: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Phương thức vẽ từ các phiên bản trước cũng được hỗ trợ : drawLine,

drawRect, drawRoundRect, drawOval, drawArc,drawPolyline,

drawPolygon, draw3DRect.

Khi một đối tượng Shape được vẽ , thì đường biên của nó sẽ được tạo

nét bằng đối tượng Stroke trong ngữ cảnh Graphics2D

Bằng việc thiét lập đối tượng BasicStroke phù hợp trong ngữ cảnh

Graphics2D ,thò có thể vẽ đường thẳng với độ rộng và mẫu nét gạch bất

kì . Đối tượng BasicStroke cũng định nghĩa các thuộc tính endcap và

join của đường thẳng .

Để tạo bóng cho các đường biên của đối tượng shape:

1. Khởi tạo cho đối tượng BasicStroke

2. Gọi phương thức Graphics2D.setStroke

3. Khởi tạo cho đối tượng Shape.

4. Gọi phương thức Graphics2D.draw(shape).

Trong ví dụ sau,đối tượng GeneralPath được sử dụng để định nghĩa

một ngôi sao và một đối tượng BasicStroke được thêm vào ngữ cảnh

Graphics2D để định nghĩa cho các cạnh của ngôi sao với các thuộc tính

join .

public void paint(Graphics g) {

Graphics2D g2 = (Graphics2D) g;

// create and set the stroke

g2.setStroke(new BasicStroke(4.0f));

// Create a star using a general path

object

http://tailieuhay.com 54

Page 55: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

GeneralPath p = new

GeneralPath(GeneralPath.NON_ZERO);

p.moveTo(- 100.0f, - 25.0f);

p.lineTo(+ 100.0f, - 25.0f);

p.lineTo(- 50.0f, + 100.0f);

p.lineTo(+ 0.0f, - 100.0f);

p.lineTo(+ 50.0f, + 100.0f);

p.closePath();

// translate origin towards center of

canvas g2.translate(100.0f, 100.0f);

// render the star's path

g2.draw(p);

}

2.4.2 Filling a Shape

Phương thức Graphics2D.fill có thể được sử dụng để tô bất kì đối

tượng Shape. Khi một đối tượng Shape được tô, thì phần bị giới hạn bởi

đương bao của đối tượng sẽ được tạo bóng với ngữ cảnh Graphics2D của

thuộc tính Paint attribute—như Color, TexturePaint, or GradientPaint.

Phương thức tô từ các phiên bản trước đó của phần mềm JDK cũng

được hỗ trợ: fillRect, fill3DRect, fillRoundRect, fillOval, fillArc,

fillPolygon,clearRect.

Để tô một đối tượng Shape:

1. Xác định màu tô và kiểu tô trong ngữ cảnh đồ họa bằng

cách sử dụng Graphics2D.setColor hay

Graphics2D.setPaint.

http://tailieuhay.com 55

Page 56: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

1. Khởi tạo đối tượng Shape.

2. Gọi phương thức Graphics2D.fill để tạo bóng đối tựơng

Shape.

Trong ví dụ sau đây ,phương thức setColor được gọi để định nghĩa

màu tô là green fill cho một đối tượng Rectangle2D.

public void paint(Graphics g) {

Graphics2D g2 = (Graphics2D) g;

g2.setPaint(Color.green);

Rectangle2D r2 = new

Rectangle2D.Float(25,25,150,150);

g2.fill(r2);

}

2.4.3 Rendering Text

Để tạo bóng văn bản ,cần gọi Graphics2D.drawString, sau đó chuyển

vào xâu mà bạn muốn tạo bóng

2.4.4 Rendering images

Để tạo bóng văn bản ,cần gọi Graphics2D.drawimage, sau đó chuyển

vào xâu mà bạn muốn tạo bóng .

2.5 Defining Custom Composition Rules

Có thể tạo một kiểu mới hoàn toàn của phép kết hợp băng cách thực

thi các interface Composite và CompositeContext . Một đối tượng

Composite cung cấp một đối tượng CompositeContext mà thực chất là

lưu trạng thái và thưc hiện công việc kết hợp. Nhiều đối tượng

http://tailieuhay.com 56

Page 57: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

CompositeContext có thể được tạo từ một đối tượng Composite để lưu

các trạng thái riêng biệt trong môi trường đa luồng (multithreaded

environment.)

2.6 Rendering in a Multi-Screen Environment

TrongJavaTM 2 SDK, version 1.3, Java 2DTM API hỗ trợ những cấu

hình đa màn hiển thi khác nhau mà có thể được cấu hình bởi một môi

trường mà :

• Có hai hoặc nhiều màn hình độc lập

• Có hai hoặc nhiều màn hình nơi chỉ có một màn hình chính và

các màn hiển thị khác sẽ copy những hình ảnh xuát hiện trên màn

hình chính

• Hai hoặc nhiều màn hình mà có dạng như một máy ảo và nó cho

phép gọi các thiết bị ảo.

Java 2D API cho phép tạo các đối tượng Frame, JFrame, Window,

hoặc Jwindow .Với một đối tượng GraphicsConfiguration để xác định

các thiết bị hiển thị cho quá trình tạo bóng. Trong cả ba cấu hình,mỗi thiết

bị hiển thị được biểu diễn bởi một đối tượng GraphicsDevice.Một đối

tượng GraphicsDevice có nhiều đối tượng GraphicsConfiguration kết

hợp với nó .

Khi hai hoặc nhiều màn hình được sử dụng để tạo một thiết bị ảo ,hệ

tọa độ ảo (mà tồn tại độc lập với thiết bị hiển thị vật lý )được sử dụng để

biểu diễn thiết bị ảo đó . Các biên cảu mỗi đối tượng

GraphicsConfiguration trong cấu hình đa màn hiển thị có quan hệ với

hệ tọa độ ảo . Một màn hiển thị trong môi trường này được xác định như

là màn hiển thị chính và tạ vị trí (0, 0) của hệ tọa độ ảo . Dựa trên vị trí

của màn hiển thị chính ,thiết bị ảo có thể có tọa độ âm ,như trong hình 2-

10:

http://tailieuhay.com 57

Page 58: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Để xác định nếu là môi trường thiết bị ảo nơi mà một đối tượng

Window

hay Frame có thể xuất hiện trên hai hay nhiều màn hình vật lý ,thì gọi

phương thức getBounds trên mỗi đối tượng GraphicsConfiguration

trong hệ thống và kiểm tra nếu gốc tọa độ khác vị trí (0, 0). Phương thức

getBounds của đối tượng GraphicsConfiguration trả về một đối tượng

hình Rectangle trong hệ tọa độ ảo .Vì vậy ,nếu một gốc tọa độ không phải

vị trí (0, 0), thì môi trường đó chính là môi trường ảo.

Trong môi trường thiết bị ảo ,các tọa độ của các đối tượng

GraphicsConfiguration có quan hệ với hệ tọa độ ảo . Vì vậy, phải sử

dụng tọa độ ảo khi gọi phương thức setLocation của đối tượng Frame

hay Window. Cho ví dụ,Đoạn mã này sẽ lấy đường bao của một đối

tượng GraphicsConfiguration và sử dụng các đường bao để thiết lập vị

trí của đối tượng Frame tại tọa độ (10, 10) trong hệ tọa độ của màn hiển

thị vật lý .

Frame f = new Frame(GraphicsConfiguration

gc);

Rectangle bounds = gc.getBounds();

http://tailieuhay.com 58

Page 59: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

f.setLocation(10 + bounds.x, 10 +

bounds.y);

Nếu các đường bao của đối tượng GraphicsConfiguration không

được tính đến , thì đối tượng Frame được hiển thị tại vị trí (10, 10) trên

mà hình vật lý chính , điều này có thể khác với mà hình vật lý của đối

tượng GraphicsConfiguration đã được xác định .

Phương thức getBounds có thể được sử dụng để xác định các đường

biên cảu thiết bị ảo. Gọi phương thức getBounds trên mỗi đối tượng

GraphicsConfiguration trong hệ thống . Để xác dịnh các đường bao cảu

thiết bị ảo , tính toán sự kết hợp của các đường bao. Kĩ thuật này được sử

dụng trong ví dụ sau.

Rectangle virtualBounds = new

Rectangle();

GraphicsEnvironment ge =

GraphicsEnvironment.getLocalGraphicsEnviron

ment();

GraphicsDevice[] gs =

ge.getScreenDevices();

for (int j = 0; j < gs.length; j+

+) {

GraphicsDevice gd = gs[j];

GraphicsConfiguration[] gc =

gd.getConfigurations();

http://tailieuhay.com 59

Page 60: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

for (int i = 0; i < gc.length; i+

+) {

virtualBounds =

virtualBounds.union(gc[i].getBounds());

}

}

Applet sau sẽ tạo một đối tượng JFrame với mỗi đối tượng

GraphicsConfiguration của mỗi đối tượng GraphicsDevice trong đối

tượng GraphicsEnvironment. Mỗi đối tượng JFrame hiển thị một tập

các vạch đỏ, xanh đậm ,xanh nhạt,số lượng các màn hiển thị số lượng các

đối tượng GraphicsConfiguration và các đường bao cuả đối tượng

GraphicsConfiguration. Đoạn mã sau phải được chạy với JavaTM 2

SDK, version 1.3 hoặc cao hơn.

/*

* Transform.java

* 1.0

* 27/03/06

* Day la doan chuong trinh mieu ta cac phep bien

doi.

*/

import java.awt.*;

import javax.swing.*;

http://tailieuhay.com 60

Page 61: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

/*

* Chuong trinh nay tao bong mot hinh duoc chon

boi nguoi su dung.Voi cac phuong

* thuc paint,stroke, va rendering cung duoc lua

chon boi nguoi su dung.

*/

/**

* @author Administrator

*

*/

public class Transform extends JApplet implements

itemListener, ActionListener {

/**

*

*/

private static final long serialVersionUiD =

-2514519718222913151L;

JLabel primLabel, lineLabel, paintLabel,

transLabel, strokeLabel;

TransPanel display;

static JComboBox primitive, line, paint,

trans, stroke;

JButton redraw;

public static boolean no2D = false;

http://tailieuhay.com 61

Page 62: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

public void init() {

GridBagLayout layOut = new

GridBagLayout();

getContentPane().setLayout(layOut);

GridBagConstraints c = new

GridBagConstraints();

c.weightx = 1.0;

c.fill = GridBagConstraints.BOTH;

primLabel = new JLabel();

primLabel.setText("Hình g c");ố

Font newFont = getFont().deriveFont(1);

primLabel.setFont(newFont);

primLabel.setHorizontalAlignment(JLabel.CENTER);

layOut.setConstraints(primLabel, c);

getContentPane().add(primLabel);

lineLabel = new JLabel();

lineLabel.setText("Các ng");đườ

lineLabel.setFont(newFont);

lineLabel.setHorizontalAlignment(JLabel.CENTER);

layOut.setConstraints(lineLabel, c);

getContentPane().add(lineLabel);

paintLabel = new JLabel();

paintLabel.setText("Ki u v ");ể ẽ

http://tailieuhay.com 62

Page 63: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

paintLabel.setFont(newFont);

paintLabel.setHorizontalAlignment(JLabel.CENTER);

layOut.setConstraints(paintLabel, c);

getContentPane().add(paintLabel);

c.gridwidth =

GridBagConstraints.RELATiVE;

transLabel = new JLabel();

transLabel.setText("Các phép bi n i");ế đổ

transLabel.setFont(newFont);

transLabel.setHorizontalAlignment(JLabel.CENTER);

layOut.setConstraints(transLabel, c);

getContentPane().add(transLabel);

c.gridwidth =

GridBagConstraints.REMAiNDER;

strokeLabel = new JLabel();

strokeLabel.setText("Tô trát");

strokeLabel.setFont(newFont);

strokeLabel.setHorizontalAlignment(JLabel.CENTER)

;

layOut.setConstraints(strokeLabel, c);

getContentPane().add(strokeLabel);

http://tailieuhay.com 63

Page 64: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

GridBagConstraints ls = new

GridBagConstraints();

ls.weightx = 1.0;

ls.fill = GridBagConstraints.BOTH;

primitive = new JComboBox(new Object[]

{ "Hình ch nh t", "Hình elip",ữ ậ

"V n b n" });ă ả

primitive.additemListener(this);

newFont = newFont.deriveFont(0, 14.0f);

primitive.setFont(newFont);

layOut.setConstraints(primitive, ls);

getContentPane().add(primitive);

line = new JComboBox(new Object[]

{ "M nh", " m", "Nét t" });ả Đậ đứ

line.additemListener(this);

line.setFont(newFont);

layOut.setConstraints(line, ls);

getContentPane().add(line);

paint = new JComboBox(new Object[]

{ " ng nh t", "Tô loang", "polka" });Đồ ấ

paint.additemListener(this);

paint.setFont(newFont);

layOut.setConstraints(paint, ls);

getContentPane().add(paint);

ls.gridwidth =

GridBagConstraints.RELATiVE;

http://tailieuhay.com 64

Page 65: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

trans = new JComboBox(new Object[]

{ "identity", "Quay", "T l ",ỉ ệ

"shear" });

trans.additemListener(this);

trans.setFont(newFont);

layOut.setConstraints(trans, ls);

getContentPane().add(trans);

ls.gridwidth =

GridBagConstraints.REMAiNDER;

stroke = new JComboBox(new Object[]

{ " ng nét", "Tô y",Đườ đầ

" ng nét va Tô y" });Đườ đầ

stroke.additemListener(this);

stroke.setFont(newFont);

layOut.setConstraints(stroke, ls);

getContentPane().add(stroke);

GridBagConstraints button = new

GridBagConstraints();

button.gridwidth =

GridBagConstraints.REMAiNDER;

redraw = new JButton("V l i");ẽ ạ

redraw.addActionListener(this);

redraw.setFont(newFont);

layOut.setConstraints(redraw, button);

getContentPane().add(redraw);

GridBagConstraints tP = new

GridBagConstraints();

http://tailieuhay.com 65

Page 66: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

tP.fill = GridBagConstraints.BOTH;

tP.weightx = 1.0;

tP.weighty = 1.0;

tP.gridwidth =

GridBagConstraints.REMAiNDER;

display = new TransPanel();

layOut.setConstraints(display, tP);

display.setBackground(Color.white);

getContentPane().add(display);

validate();

}

public void itemStateChanged(itemEvent e) {

}

public void actionPerformed(ActionEvent e) {

display.setTrans(trans.getSelectedindex());

display.renderShape();

}

@SuppressWarnings("deprecation")

public static void main(String[] argv) {

if (argv.length > 0 && argv[0].equals("-

no2d")) {

Transform.no2D = true;

}

http://tailieuhay.com 66

Page 67: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

JFrame frame = new JFrame("Các phép

chuy n i");ể đổ

frame.addWindowListener(new

WindowAdapter() {

public void

windowClosing(WindowEvent e) {

System.exit(0);

}

});

JApplet applet = new Transform();

frame.getContentPane().add(BorderLayout.CENTER,

applet);

applet.init();

frame.setSize(550, 400);

frame.show();

}

}

@SuppressWarnings("serial")

class TransPanel extends JPanel {

AffineTransform at = new AffineTransform();

int w, h;

http://tailieuhay.com 67

Page 68: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Shape shapes[] = new Shape[3];

Bufferedimage bi;

boolean firstTime = true;

public TransPanel() {

setBackground(Color.white);

shapes[0] = new Rectangle(0, 0, 100,

100);

shapes[1] = new Ellipse2D.Double(0.0,

0.0, 100.0, 100.0);

TextLayout textTl = new

TextLayout("Brother Hood", new Font("Tomaha",

1, 76), new

FontRenderContext(null, false, false));

AffineTransform textAt = new

AffineTransform();

textAt.translate(0, (float)

textTl.getBounds().getHeight());

shapes[2] = textTl.getOutline(textAt);

}

public void setTrans(int transindex) {

switch (transindex) {

case 0:

at.setToidentity();

at.translate(w / 2, h / 2);

break;

http://tailieuhay.com 68

Page 69: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

case 1:

at.rotate(Math.toRadians(45));

break;

case 2:

at.scale(0.5, 0.5);

break;

case 3:

at.shear(0.5, 0.0);

break;

}

}

public void renderShape() {

repaint();

}

public void paintComponent(Graphics g) {

super.paintComponent(g);

if (!Transform.no2D) {

Graphics2D g2 = (Graphics2D) g;

Dimension d = getSize();

w = d.width;

h = d.height;

String instruct = "Nh p m t hình cậ ộ ơ

s ban u, ki u ng,ki u v , phép bi n i,";ở đầ ể đườ ể ẽ ế đổ

TextLayout thisTl = new

TextLayout(instruct, new Font("Helvetica",

http://tailieuhay.com 69

Page 70: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

0, 10),

g2.getFontRenderContext());

float width = (float)

thisTl.getBounds().getWidth();

float height = (float)

thisTl.getBounds().getHeight();

thisTl.draw(g2, w / 2 - width / 2,

15);

instruct = "và các ph ng th c t oươ ứ ạ

bóng sau ó nh n nút VE LAi.";đ ấ

thisTl = new TextLayout(instruct,

new Font("Helvetica", 0, 10), g2

.getFontRenderContext());

width = (float)

thisTl.getBounds().getWidth();

thisTl.draw(g2, w / 2 - width / 2,

height + 17);

// initialize the transform.

if (firstTime) {

at.setToidentity();

at.translate(w / 2, h / 2);

firstTime = false;

}

// Sets the Stroke.

Stroke oldStroke = g2.getStroke();

http://tailieuhay.com 70

Page 71: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

switch

(Transform.line.getSelectedindex()) {

case 0:

g2.setStroke(new

BasicStroke(3.0f));

break;

case 1:

g2.setStroke(new

BasicStroke(8.0f));

break;

case 2:

float dash[] = { 10.0f };

g2.setStroke(new

BasicStroke(3.0f, BasicStroke.CAP_BUTT,

BasicStroke.JOiN_MiTER,

10.0f, dash, 0.0f));

break;

}

// Sets the Paint.

Paint oldPaint = g2.getPaint();

switch

(Transform.paint.getSelectedindex()) {

case 0:

g2.setPaint(Color.blue);

break;

case 1:

g2.setPaint(new GradientPaint(0,

0, Color.lightGray, w - 250,

http://tailieuhay.com 71

Page 72: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

h, Color.blue, false));

break;

case 2:

Bufferedimage buffi = new

Bufferedimage(15, 15,

Bufferedimage.TYPE_iNT_RGB);

Graphics2D buffig =

buffi.createGraphics();

buffig.setColor(Color.blue);

buffig.fillRect(0, 0, 15, 15);

buffig.setColor(Color.lightGray);

buffig.translate((15 / 2) - (5 /

2), (15 / 2) - (5 / 2));

buffig.fillOval(0, 0, 7, 7);

Rectangle r = new Rectangle(0,

0, 25, 25);

g2.setPaint(new

TexturePaint(buffi, r));

break;

}

// Sets the Shape.

Shape shape =

shapes[Transform.primitive.getSelectedindex()];

Rectangle r = shape.getBounds();

// Sets the selected Shape to the

center of the Canvas.

http://tailieuhay.com 72

Page 73: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

AffineTransform saveXform =

g2.getTransform();

AffineTransform toCenterAt = new

AffineTransform();

toCenterAt.concatenate(at);

toCenterAt.translate(-(r.width / 2),

-(r.height / 2));

g2.transform(toCenterAt);

// Sets the rendering method.

switch

(Transform.stroke.getSelectedindex()) {

case 0:

g2.draw(shape);

break;

case 1:

g2.fill(shape);

break;

case 2:

Graphics2D tempg2 = g2;

g2.fill(shape);

g2.setColor(Color.darkGray);

g2.draw(shape);

g2.setPaint(tempg2.getPaint());

break;

}

g2.setStroke(oldStroke);

g2.setPaint(oldPaint);

http://tailieuhay.com 73

Page 74: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

g2.setTransform(saveXform);

}

}

}

Kết quả sau khi chạy chương trình :

http://tailieuhay.com 74

Page 75: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Chương 3

Các đối tượng hình họa

Java 2D™ API cung cấp một số lớp để định nghĩa các đối tượng

geometric (hình học),chẳng hạn như điểm,đường thẳng,đường

cong,hình chữ nhật.Những lớp hình học mới đó là một phần của gói

java.awt.geom.Để có thể tương thích với các phiên bản cũ,các lớp

geometry có chứa trong các phiên bản trước đó của bộ JDK software,như

rectangle,point và polygon,được chứa trong gói java.awt.

Các đối tượng hình học trong Java 2D API như GenneralPath,Arc2D

và Rectangle2D cho phép thực thi việc tạo giao diện bệ mặt được định nghĩa trong

gói java.awt.Hình dáng cụ thể cung cấp cho ta một phương thức chung cho việc

miêu tả và kiểm tra đường dẫn của các đối tượng hình học.Một giao diện mới

Pathlterator,cung cấp các phương thức định nghĩa việc khôi phục các phần tử từ

một đối tượng hình học. Sử dụng các lớp hình học bạn có thể dễ dàng xác định và

thao tác với nhiều đối tượng hai chiều.

3.1 Giao diện và lớp.

Bảng dưới đây liệt kê những giao diện và các lớp chính của các đối

tượng hình học.Hầu hết trong sô các giao diện và các lớp là thành phần

của gói java.awt.geom.Một số,chẳng hạn như Shape,là thành phần của

gói java.awt,thành phần chính để có thể tương thích với các phiên bản

trước đây của bộ JDK.

Các lớp và giao diện của java.awt.geom

http://tailieuhay.com 75

Page 76: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Giao diện Mô tảPathIterator Định nghĩa các phương thức cho việc phục hồI các

phần tử từ một đường dẫn.Shape

(java.awt)

Cung cấp một tập các phương thức cho việc miêu tả

và kiểm tra đường dẫn hình học.Được thực thi bởI

GaneralPath và các lớp hình học khác.

Các lớp

Arc2D Arc2D.Double

Arc2D.Float

Mở rộng:RectangularShape

Miêu tả một đường cong được định nghĩa bằng

một hình chữ nhật có giớI hạn,góc ban đầu,và

một kiểu đóng kín.Việc thực thi chỉ rõ những

đường cong trong kiểu số float và double.

Chính xác:Arc2D.Float và Arc2D.Double.AreaArea Lớp thực thi:Shape,Cloneable.

Miêu tả một diện tích hình học mà hỗ trợ các

phép toán nhị phân.

CubicCurve2D

CubicCurve2D.Doubl

e

CubicCurve2D.Float

Implements: Shape

Lớp thực thi:Shape.

Miêu tả các đoạn đường cong tham số bậc ba

trong không gian tọa độ.Việc thực thi để chỉ rõ

các đường cong bậc ba vớI độ chính xác float và

double do hai lớp: CubicCurve2D.Float and

CubicCurve2D.Double.

Dimension2D Đóng gói cả chiều rộng và chiều cao.Một siêu

lớp trìu tượng cho tất cả các đốI tượng lưu trữ

dùng để lưu trữ các đốI tượng hai chiều.

http://tailieuhay.com 76

Page 77: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Ellipse2D

Ellipse2D.Double

Ellipse2D.Float

Mở rộng: RectangularShape

Miêu tả việc định nghĩa đường e-lip bằng các

hình chữ nhật giớI hạn.Công cụ để chỉ rõ các

đường cong elip vớI độ chính xác float và

double: Ellipse2D.Float và Ellipse2D.DoubleFlatteningPathIterator Trả về một flattened view của một đối tượng

PathLterator.

Có thể sử dụng để cung cấp các flattening

behavior cho các đối tượng Shape mà nó không

thực hiện việc tính toán các thành phần thêm vào.GeneralPath Thực thi đối tượng Shape

Miêu tả một khung hinhg được xây dựng từ các

đường thẳng và các đường bậc hai và bậc baLine2D

Line2D.Double

Line2D.Float

Thực thi đối tượng Shape.

Miêu tả một đoạn thẳng trong không gian tọa độ

(x,y) .Được thưc thi để xác định các đường thẳng

với độ chính xác float và double:: Line2D.Float

và Line2D.Double.Point2D

Point2D.Double

Point2D.Float

Một điểm miêu tả một vị trí trong không gian tọa

độ (x,y).Được thực thi để xác đinh các điểm với

độ chính xác float và double: Point2D.Float và

Point2D.Double.QuadCurve2D

QuadCurve2D.Doubl

e

QuadCurve2D.Float

Thực thi đối tượng Shape.

Miêu tả một đoạn đường cong tham số bậc hai

trong không gian tọa độ (x,y).Được thực thi để

xác định các đường bậc hai với độ chính xác

float và double: QuadCurve2D.Float và

QuadCurve2D.Double.Rectangle2D Mở rộng: RectangularShape

http://tailieuhay.com 77

Page 78: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Rectangle2D.Double

Rectangle2D.Float

Miêu tả một hình chữ nhật được định nghĩa bởi

một vị trí (x,y) và kích thước(w,x,h). Được thực

thi để xác đinh các hình chũ nhật với độ chính

xác float và double: Rectangle2D.Float và

Rectangle2D.Double.RectangularShape Thực thi đối tượng Shape.

Cung cấp sự thao tác chung cho các tác động lên

các đối tượng Shape mà nó có các hình chữ nhật

biên.RoundRectangle2D

RoundRectangle2D.D

ouble

RoundRectangle2D.Fl

oat

Mở rộng: RectangularShape

Miêu tả một hình chữ nhật các góc được làm tròn

được định nghĩa bằng một vị trí (x, y),một kích

thước (w x h),và chiều rộng và chiều cao của

góc cung. Được thực thi để xác đinh các hình chữ

nhật có góc tròn với độ chính xác float và double:

RoundRectangle2D.Float và

RoundRectangle2D.Double.

3.2 Các khái niệm hình học:

Shape là một thể hiện của nhiều lớp mà nó thực thi Shape

interface,như

GeneralPath or Rectangle2D .Float . Đường viền (outline) còn được

định nghĩa là path.

Khi một Shape được vẽ,kiểu đường nét vẽ được địng nghĩa bởi đối

tượng Stroke trong thư viện đồ họa 2D,được áp dụng cho Shape’s

path.Khi một Shape được phủ đầy,Paint trong thư viện đồ họa 2D được

áp dụng cho phần diện tích bên trong đường viền của nó.Để biết thêm

thông tin,bạn xem thêm phần “Rendering with Graphics2D”.

http://tailieuhay.com 78

Page 79: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Đường viền của một hình cũng có thể được sử dụng để định nghĩa

một clipping path.Một clipping path xác định những điểm ảnh nào được

đưa ra(render). clipping path là một phần của Graphics 2D. Để biết thêm

thông tin,bạn xem thêm phần “Setting the Clipping Path”.

Một GeneralPath là một shape mà nó có thể được sử dụng

để miêu tả một số đối tượng 2 chiều có thể được vẽ từ các đường

và các đường bậc hai hoặc bậc ba.Để thuận lợi, java.awt.geom

cung cấp thêm các thành phần thực thi của giao tiếp Shape mà

nó miêu tả các đối tượng đồ họa phổ biến như hình chữ

nhật,hình elip,cung tròn và các đường cong. The Java2D™ API còn

cung cấp một kiểu shape đặc biệt hỗ trợ cho việc xây dựng diện tích hình

học.

3.2.1 Constructive Area Geometry

Constructive Area Geometry (CAG) là một quá trình tạo ra các đối

tượng hình học mới bằng việc thực hiện các phép toán nhị phân trong các

đối tượng đã tồn tại.Trong Java 2D API một kiểu đặc biệt của Shape

được gọi là Area hỗ trợ các phép toán nhị phân.Bạn có thể tạo ra một đối

tượng Area từ một số Shape.

Các Area hỗ trợ các phép toán nhị phân sau:

• Union(hợp)

• intersection(giao)

• Subtraction(trừ)

• Exclusive OR (XOR) (OR dành riêng)

Các phép toán đó được miêu tả như hình 3-1 dưới đây:

http://tailieuhay.com 79

Page 80: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

3.2.2 Bounds and Hit Testing

Một bounding box là một hình chữ nhật bao bọc hoàn toàn một một

thể thiện hình học. bounding box được sử dụng để quết định một đối

tượng có được chọn hay không hoặc được “hit” bởi người sử dụng.

Giao diện Shape xác định hai phương thức cho việc truy lại một

shape’s bounding box,đó là getBounds và getBounds2D.Phương thức

getBounds2D trả về một đối tượng Rectangle2D , một thể hiện của

Rectangle .Cung cấp một độ chính xác cao hơn trong việc miêu tả

shape’s bounding box.

Shape cũng cung cấp nhiều phương thức cho việc xác định :

• Một điểm cụ thể bên trong bao đóng của hình

thể(contains )

• Một hình chữ nhật cụ thể nằm hoàn toàn bên trong một

bao đóng của hình thể. (contains )

• Một hình chữ nhật cụ thể phân cắt hình thể (intersects )

/*

* Composite.java

* 1.0

* 20/03/06

*/

import java.awt.*;

http://tailieuhay.com 80

Page 81: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

import javax.swing.*;

/*

* Chuong trinh nay la mot vi du ve cac luat ket

hop giua cac hinh.

*/

@SuppressWarnings("serial")

public class Composite extends JApplet implements

itemListener {

CompPanel comp;

JLabel alphaLabel, rulesLabel;

JComboBox alphas, rules;

String alpha = "1.0";

int rule = 0;

public void init() {

GridBagLayout layOut = new

GridBagLayout();

getContentPane().setLayout(layOut);

GridBagConstraints l = new

GridBagConstraints();

l.weightx = 1.0;

http://tailieuhay.com 81

Page 82: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

l.fill = GridBagConstraints.BOTH;

l.gridwidth =

GridBagConstraints.RELATiVE;

alphaLabel = new JLabel();

alphaLabel.setText("C ng m u");ườ độ ầ

Font newFont = getFont().deriveFont(1);

alphaLabel.setFont(newFont);

alphaLabel.setHorizontalAlignment(JLabel.CENTER);

layOut.setConstraints(alphaLabel, l);

getContentPane().add(alphaLabel);

getContentPane().setLayout(layOut);

l.gridwidth =

GridBagConstraints.REMAiNDER;

rulesLabel = new JLabel();

rulesLabel.setText("Các lu t k t h p.");ậ ế ợ

newFont = getFont().deriveFont(1);

rulesLabel.setFont(newFont);

rulesLabel.setHorizontalAlignment(JLabel.CENTER);

layOut.setConstraints(rulesLabel, l);

getContentPane().add(rulesLabel);

GridBagConstraints a = new

GridBagConstraints();

a.gridwidth =

GridBagConstraints.RELATiVE;

a.weightx = 1.0;

http://tailieuhay.com 82

Page 83: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

a.fill = GridBagConstraints.BOTH;

alphas = new JComboBox();

layOut.setConstraints(alphas, a);

alphas.additem("1.0");

alphas.additem("0.75");

alphas.additem("0.50");

alphas.additem("0.25");

alphas.additem("0.0");

alphas.additemListener(this);

getContentPane().add(alphas);

a.gridwidth =

GridBagConstraints.REMAiNDER;

rules = new JComboBox();

layOut.setConstraints(rules, a);

rules.additem("SRC");

rules.additem("DST_iN");

rules.additem("DST_OUT");

rules.additem("DST_OVER");

rules.additem("SRC_iN");

rules.additem("SRC_OVER");

rules.additem("SRC_OUT");

rules.additem("CLEAR");

rules.additemListener(this);

getContentPane().add(rules);

GridBagConstraints fC = new

GridBagConstraints();

fC.fill = GridBagConstraints.BOTH;

fC.weightx = 1.0;

http://tailieuhay.com 83

Page 84: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

fC.weighty = 1.0;

fC.gridwidth =

GridBagConstraints.REMAiNDER;

comp = new CompPanel();

layOut.setConstraints(comp, fC);

getContentPane().add(comp);

validate();

}

public void itemStateChanged(itemEvent e) {

if (e.getStateChange() !=

itemEvent.SELECTED) {

return;

}

Object choice = e.getSource();

if (choice == alphas) {

alpha = (String)

alphas.getSelecteditem();

} else {

rule = rules.getSelectedindex();

}

comp.changeRule(alpha, rule);

}

public static void main(String s[]) {

JFrame f = new JFrame("K t h p");ế ợ

f.addWindowListener(new WindowAdapter() {

http://tailieuhay.com 84

Page 85: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

public void

windowClosing(WindowEvent e) {

System.exit(0);

}

});

JApplet applet = new Composite();

f.getContentPane().add("Center", applet);

applet.init();

f.pack();

f.setSize(new Dimension(300, 300));

f.show();

}

}

class CompPanel extends JPanel {

AlphaComposite ac =

AlphaComposite.getinstance(AlphaComposite.SRC);

float alpha = 1.0f;

public CompPanel() {

}

public void changeRule(String a, int rule) {

alpha = Float.valueOf(a).floatValue();

ac =

AlphaComposite.getinstance(getRule(rule), alpha);

repaint();

}

http://tailieuhay.com 85

Page 86: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

public int getRule(int rule) {

int alphaComp = 0;

switch (rule) {

case 0:

alphaComp = AlphaComposite.SRC;

break;

case 1:

alphaComp = AlphaComposite.DST_iN;

break;

case 2:

alphaComp = AlphaComposite.DST_OUT;

break;

case 3:

alphaComp = AlphaComposite.DST_OVER;

break;

case 4:

alphaComp = AlphaComposite.SRC_iN;

break;

case 5:

alphaComp = AlphaComposite.SRC_OVER;

break;

case 6:

alphaComp = AlphaComposite.SRC_OUT;

break;

case 7:

alphaComp = AlphaComposite.CLEAR;

break;

}

return alphaComp;

http://tailieuhay.com 86

Page 87: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

}

public void paintComponent(Graphics g) {

super.paintComponent(g);

Graphics2D g2 = (Graphics2D) g;

Dimension d = getSize();

int w = d.width;

int h = d.height;

Bufferedimage buffimg = new

Bufferedimage(w, h,

Bufferedimage.TYPE_iNT_ARGB);

Graphics2D gbi =

buffimg.createGraphics();

g2.setColor(Color.white);

g2.fillRect(0, 0, d.width, d.height);

int rectx = w / 4;

int recty = h / 4;

gbi.setColor(new Color(0.0f, 0.0f, 1.0f,

1.0f));

gbi.fill(new Rectangle2D.Double(rectx,

recty, 150, 100));

gbi.setColor(new Color(1.0f, 0.0f, 0.0f,

1.0f));

gbi.setComposite(ac);

gbi.fill(new Ellipse2D.Double(rectx +

rectx / 2, recty + recty / 2,

http://tailieuhay.com 87

Page 88: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

150, 100));

g2.drawimage(buffimg, null, 0, 0);

}

}

Kết quả của chương trình :

3.3 Combining Areas to Create New Shapes

Các Area có thể được sử dụng để tạo ra một cách nhanh chóng

các Shape phức tạp như các hình tròn và các hình vuông.Tạo một

hình thể phức tạp mới bằng cách kết hợp các Area như sau:

1.Sử dụng các Shape,tạo ra các Area để kết hợp lại.

2.Gọi các toán tử nhị phân thích hợp: add,subtract ,intersect ,

exclusiveOr

Ví dụ,CAG có thể được sử dụng để tạo ra quả lê giống như hình 3-2 dưới

đây:

http://tailieuhay.com 88

Page 89: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Cách thực hiện:

Thân của quả lê được tạo ra bằng cách kết hợp các thao tác trong 2

over- lapping Areas : circle và oval.Cái lá được tạo ra bằng cách thực

hiện một phép giao trên hai vòng tròn chồng lên nhau và sau đó được đưa

vào một Shape đơn thông qua phép hợp.Việc nạp chồng các vòng tròn

còn được sử dụng để tạo cuống lá thông qua hai phép trừ.

Chương trình:

/*

* @(#)Pear.java 1.0 27/03/06

*/

import java.awt.Color;

import java.awt.Dimension;

import java.awt.Graphics;

import java.awt.Graphics2D;

import java.awt.event.WindowAdapter;

import java.awt.event.WindowEvent;

import java.awt.geom.Area;

import java.awt.geom.Ellipse2D;

import javax.swing.JApplet;

import javax.swing.JFrame;

http://tailieuhay.com 89

Page 90: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

/*

* Chuong trinh nay ve mot qua le,su dung phuong

thuc ket hop giua cac vung.

*/

@SuppressWarnings("serial")

public class Pear extends JApplet {

Ellipse2D.Double circle, oval, leaf, stem;

Area circ, ov, leaf1, leaf2, st1, st2;

public void init() {

circle = new Ellipse2D.Double();

oval = new Ellipse2D.Double();

leaf = new Ellipse2D.Double();

stem = new Ellipse2D.Double();

circ = new Area(circle);

ov = new Area(oval);

leaf1 = new Area(leaf);

leaf2 = new Area(leaf);

st1 = new Area(stem);

st2 = new Area(stem);

setBackground(Color.white);

}

public void paint(Graphics g) {

Graphics2D g2 = (Graphics2D) g;

Dimension d = getSize();

http://tailieuhay.com 90

Page 91: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

int w = d.width;

int h = d.height;

double ew = w / 2;

double eh = h / 2;

g2.setColor(Color.green);

leaf.setFrame(ew - 16, eh - 29, 15.0,

15.0);

leaf1 = new Area(leaf);

leaf.setFrame(ew - 14, eh - 47, 30.0,

30.0);

leaf2 = new Area(leaf);

leaf1.intersect(leaf2);

g2.fill(leaf1);

leaf.setFrame(ew + 1, eh - 29, 15.0,

15.0);

leaf1 = new Area(leaf);

leaf2.intersect(leaf1);

g2.fill(leaf2);

g2.setColor(Color.black);

stem.setFrame(ew, eh - 42, 40.0, 40.0);

st1 = new Area(stem);

stem.setFrame(ew + 3, eh - 47, 50.0,

50.0);

st2 = new Area(stem);

st1.subtract(st2);

g2.fill(st1);

g2.setColor(Color.yellow);

circle.setFrame(ew - 25, eh, 50.0, 50.0);

oval.setFrame(ew - 19, eh - 20, 40.0,

70.0);

http://tailieuhay.com 91

Page 92: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

circ = new Area(circle);

ov = new Area(oval);

circ.add(ov);

g2.fill(circ);

}

public static void main(String s[]) {

JFrame f = new JFrame("Qu lê");ả

f.addWindowListener(new WindowAdapter() {

public void

windowClosing(WindowEvent e) {

System.exit(0);

}

});

JApplet applet = new Pear();

f.getContentPane().add("Center", applet);

applet.init();

f.pack();

f.setSize(new Dimension(600, 400));

f.show();

}

}

Kết quả của chương trình:

http://tailieuhay.com 92

Page 93: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

http://tailieuhay.com 93

Page 94: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Chương 4:

Hiển thị Font và văn bản

Bạn có thể sử dụng các phép biến đổi và các công cụ drawing của

Java 2D™ API với văn bản.Hơn nữa, Java 2D™ API còn cung cấp các

lớp liên quan tới văn bản hỗ trợ các điều khiển font và các cách bố trí văn

bản phức tạp.Nó còn bao gồm cả lớp Font và lớp TextLayout.

Chương này tập chung vào khả năng hỗ trợ các kiểu font và các cách

bố trí văn bản(text layout) bằng việc sử dụng các giao diện và các lớp

trong java.awt và java.awt.font.

Để có thêm thông tin về phân tích văn bản,bạn tham khảo thêm văn

bản hướng dẫn về java.text và theo dõi phần “Writing Global Programs”

trong bộ Java Tutorial.

Để có thêm thông tin về cách sử dụng công cụ bố trí văn bản bằng cách

sử dụng Swing,bạn xem thêm phần java.awt.swing.text và “Using the

JFC/Swing Packages” trong Java Tutorial.

4.1.Giao diện và lớp.

Bảng dưới đây liệt kê các giao diện và các lớp chính sử dụng cho font

và textlayout.Hầu hết trong số giao diện và lớp này là thành phần của gói

ava.awt.font.Một số,như Font,là một phần của gói java.awt được sử

dụng để đảm bảo tính tương thích với các phiên bản trước đó của bộ JDK.

Bảng mô tả giao diện và lớp :

Giao diện Miêu tảMultipleMaste

r

Miêu tả các font kiểu 1 với nhiều đường.Được thực thi

bởi các đối tượng Font mà chúng là các kiểu font nhiều

đường để có thể truy cập đến các thiết kế điều khiển.OpenType Miêu tả các font kiểu mở(Open Type)và kiểu thực(True

http://tailieuhay.com 94

Page 95: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Type).Được thực thi bởi các đối tượng Font mà chúng là

các font Open Type hoặc True Type có thể truy cập đến

các bảng font’s sfnt.

Lớp Mô tảFont

(java.awt)

Miêu tả một thể hiện của bề mặt font(font face)

từ tập hợp các font face đã có sẵn trong máy.Hỗ

trợ việc đặc tả chi tiết về thông tin font và cung

cấp khả năng truy cập tới các thông tin về các

kiểu font và các đường nét của nó.FontRenderContext Đóng gói thông tin cần thiết cho các phép đo văn

bản một cách chính xác.GlyphJustificationInfo Miêu tả các thông tin về đặc tính căn lề của một

đường nét,như trọng lượng (chữ),độ ưu tiên,sự

thu hút và giới hạn.GlyphMetrics Cung cấp các phép đo cho một đường nét đơn.GlyphVector Một tập hợp các đường nét và các vị trí.GraphicAttribute Là lớp cơ sở cho thuộc tính TextLayout mà nó

đặc tả một đối tượng Graphics để được nhungd

vào văn bản.Được thực thi bởi

ShapẻGaphicAttribute và

ImageGraphicAttribute,mà nó có thể cho phép

các đối tượng Shape và đối tượng Image nhúng

vào một đối tượng TextLayout.Có thể phân lớp

để thực thi kí tự tùy chọn để thay thế các

graphic.ImageGraphicAttribute Mở rộng:GraphicAttribute

Một đối tượng GraphicsAttribute được sử dụng

để vẽ các ảnh bên trong một TextLayout.LineBreakMeasurer Chia một khối văn bản thành nhiều dòng trong

các đối tượng TextLayout mà nó khit bên trong

một dong.

http://tailieuhay.com 95

Page 96: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

LineMetrics Cung cấp khả năng truy cập đến các thước đo

font cần thiết để hiển thị các kí tự trên một hàng

và hiển thị tập các hàng đó.Các thước đo bao

gồm phần nhô lên,phần phía dưới,phần mũ,chiều

cao và thông tin đường cơ bản(ascent, descent,

leading, height, and baseline information).ShapeGraphicAttribute Mở rộng:GraphicAttribute

Một đối tượng GraphicsAttribute được sử

dụng để vẽ các đối tượng Shape trong một đối

tượng TextLayoutTextAttribute Định nghĩa các thuộc tính quan trọng và các giá

trị được sử dụng cho việc tạo bóng văn bản(text

rendering).TextHitInfo Miêu tả thông tin hit test cho các kí tự trong một

đối tượng TextLayoutTextLayout Thực thi:Cloneable

Cung cấp một sự biểu diễn đồ họa cố định của

các dữ liệu kí tự đã được định kiểu,bao gồm cả

các văn bản hai chiều.

4.2.Các khái niệm về Font

Lớp Font đã được cải tiến để hỗ trợ việc đặc tả chi tiết thông tin về

kiểu font và có thể sử dụng các đặc tính phức tạp.

Một đối tượng Font miêu tả một thể hiện của kiểu font trong tập hợp

các font của hệ thống.Các font thương hay được sử dụng như font Helvet

Bold và Courier Bold italic.

Có ba kiểu tên cho một đối tượng Font-đó là logical name, family

name, và font face name:

http://tailieuhay.com 96

Page 97: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Một logical name của đối tượng Font là tên được ánh xạ đến một

trong nhiều font cụ thể đã có sẵn trong platform. logical name là tên font

được sử dụng để chỉ rõ một đối tượng Font trong JDK 1.1 và các phiên

bản trước đó.Khi chỉ định một đối tượng Font trong Java™ 2 SDK bạn

nên sử dụng font face name thay cho logical name.Bạn có thể nhận

logical name từ đối tượng font bằng cách goi j phương thức getName.Để

nhận được danh sách các logical name,hãy gọi

java.awt.Toolkit.getFontList.

Một family name của đối tượng Font là tên trong họ font mà nó định

nghĩa cách thiết kế việc in thông qua một số bề mặt,chẳng hạn như kiểu

chữ Helvetica.Bạn lấy họ tên font bằng cách sử dụng phương thức

getFamily.

Một font face name của đối tượng Font dùng để ám chỉ kích thước

thật của font được cài đặt trong hệ thống.Đó là tên mà bạn có thể sử dụng

khi chỉ rõ một kiểu font trong Java 2 SDK.Nó cũng thường được ám chỉ

cho font name.Bạn có thể lấy tên font bằng cách gọi phương thức

geFontName.Để xác định kiểu font nào được sử dụng trong hệ thống,bạn

có thể gọi phương thức GraphicsEnvironment.getAllFonts.

Bạn có thể truy xuất các thông tin về một đối tượng Font bằng việc

gọi phương thức getAttributes. Các thuộc tính của Font bao gồm tên,kích

cỡ font,transform,đặc tính font như hình dáng font.

Một đối tượng LineMetrics đóng gói các thông tin về các số đo của

Font,như ascent,descent và khoảng cách giữa các dòng chữ.

• Ascent là khoảng cách từ đường baseline đến đường

ascender.Khoảng cách này miêu tả chiều cao của các chữ viết hoa,nhưng

một số kí tự có thể mở rộng về phía trên của đường ascender.

• Descent là khoảng cách từ đường baseline đến đường

descender.Điểm thấp nhất của hầu hết các kí tự sẽ nằm bên trong

http://tailieuhay.com 97

Page 98: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

descent,nhưng có một số kí tự có thể mở rộng về phía dưới của đường

descender.

• Leading được nói tới như là khoảng cách từ đáy của đường

descender đến đỉnh của dòng tiếp theo.

Thông tin này được sử dụng để định vị một cách chính xác các kí

tự dọc theo một dòng,và các đường có thể liên quan đến các đường khác.

Bạn có thể truy xuất những phép đo các line bằng việc sử dụng các

phương thức getAscent, getDescent, và getLeading .Bạn cũng có thể

truy xuất thông tin vê weight, baseline và underline của Font thông qua

LineMetrics.

4.3 Các khái niệm về Text Layout.

Trước khi một đoạn chữ có được hiển thị,nó cần phải được chỉ rõ về

hình dáng cũng như vị trí hiển thị bằng việc sử dụng các nét chữ và các

cách kết hợp một thích hợp.Quá trình này được gọi là text layout,bao gồm

các giai đoạn sau:

• Sắp đặt các chữ sử dụng các nét chữ và các cách kết hợp thích

hợp.

• Ordering các đoạn text thích hợp.

• Đánh giá và bố trí các đoạn text.

http://tailieuhay.com 98

Page 99: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Các thông tin cho được sử dụng để hiển thị text cũng rất cần thiết cho

việc biểu diễn text như caret positioning, hit detection, và highlighting.

Để phát triển các phần mềm có thể triển khai trên toàn cầu,text phải được

thể hiện trên nhiều ngôn ngữ khác nhau bằng nhiều để có thể thích hợp

với quy tắc của các hệ thống văn bản thích hợp.

4.3.1 Vẽ chữ.

Gyph(nét chữ) là một cách hiển thị trực quan cho một hay nhiều kí

tự.Hình dáng,kích thước,và vị trí của glyph phụ thuộc vào văn cảnh của

nó.Rất nhiều loại glyph có thể được sử dụng để miêu tả một kí tự đơn

hoặc nhiêu kí tự kết hợp với nhau,phụ thuộc vào font và kiểu dáng(style).

Ví dụ như trong đoạn text viết bằng tay,các kí tự đặc biệt có thể thể

hiện các hình dáng chữ khác nhau phụ thuộc vào cách nó kết hợp với các

kí tự liền kề với nó.

Trong một số hệ thống văn bản,đặc biệt là chữ Ả Rập, the context of a

glyph must always be taken into account .Không giống tiếng Anh,các

cursive form có tính bắt buộc trong chữ Ả Rập.

Phụ thuộc vào từng context,các cursive form có thể khác nhau hoàn

toàn về hình dáng.Ví dụ,chữ heh trong tiếng Ả Rập có bốn cursive form

http://tailieuhay.com 99

Page 100: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

như trong hình 4-2 dưới đây:

Mặc dù bốn kiểu form này chỉ khác nhau đôi chút so với cá form

khác,nhưng những sự thay đổi về hình dáng không phải là sự khác biệt cơ

bản về cursive trong tiêng Anh.

Trong một số ngữ cảnh,hai glyph có thể thay đổi hình dáng một cách

cơ bản và kết hợp vào form một glyph đơn.Kiểu kết hợp này được gọi là

ligature.Ví dụ,hầu hết các font tiếng anh chứa ligature như trong hình 4-

3.Việc hòa hợp glyph đưa vào tính toán phần nhô ra trong kí tự f và kết

hợp các kí tự theo một cách tự nhiên,thay vì các kí tự kề nhau

http://tailieuhay.com 100

Page 101: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Các chữ ghép cũng được sử dụng trong tiếng Ả rập và cách sử dụng

của một số chữ ghép is mandatory-nó không được chấp nhận để hiển thị

các kí tự kết hợp chính xác mà không sử dụng chữ ghép thích hợp.Khi các

chữ ghép được tạo thành từ các kí tự Ả Rập,hình dáng thay đổi một cách

cơ bản hơn so với tiếng Anh.Ví dụ,như trong hình 4-4 miêu tả cách hai

chữ cái Ả rập kết hợp với nhau thành một chữ ghép khi chúng xuất hiện

cùng nhau.

4.3.2 Ordering Text

Trong ngôn ngữ lập trình Java,văn bản được mã hóa bằng cách sử

dụng các kí tự mã hóa Unicode.Văn bản sử dụng kí tự mã hóa Unicode

được lưu trữ trong bộ nhớ trong logical order. logical order là nơi mà

trong đó các kí tự và các từ được đọc và ghi. logical order không nhất

thiết phải giống như visual order,là nơi mà trong đó các glyph tương ứng

được hiển thị.

Visual order cho các glyph trong hệ thống ghi cụ thể(script) được gọi

là script order.Ví dụ, script order cho văn bản kiểu Roman được bố trí từ

trái qua phải và script order cho các văn bản Arabic và Hebrew được bố

trí từ phải sang trái.

Một số hệ thống ghi(writing systems) có các nguyên tắc trong việc thêm

các script order cho việc sắp xếp các glyph và các từ trong nhiều dòng của

văn bản.Ví dụ, các số Arabic và Hebrew chạy từ trái qua phải,mặc dú các

http://tailieuhay.com 101

Page 102: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

kí tự chạy từ phải qua trái.(Điều này có nghĩa Arabic và Hebrew,ngay cả

khi không có các văn bản bằng tiếng Anh nhúng vào,chúng vẫn thực sự là

(kĩ thuật) hai chiều)

Một hệ thống ghi visual order phải không được thay đổi ngay cả khi

các ngôn ngữ hòa trộn với nhau.Điều này được mô tả trong hình 4-5,miêu

tả một nhóm từ Arabic nhúng vào một câu văn bản tiếng Anh.

Chú ý:Trong ví dụ này và trong các ví dụ sau, các văn bản Arabic và

Hebrew được hiển thị bằng các chữ cái in hoa và các khoảng cách giữa

các chữ được hiển thị bằng dấu gạch dưới.Mỗi phần miêu tả chia thành

hai phần:việc hiển thị của các kí tự được lưu trữ trong bộ nhớ(các kí tự

trong logical order) sau đó là cách hiển thị của những kí tự được hiển

thị(các kí tự trong visual order).Các số bên dưới khung kí tự chỉ định

insertion offsets.

Hình 4-5 Bidirectional Text

Cho dù chúng là một phần trong một câu tiếng Anh,các từ Arabic

được hiển thị trong các Arabic script,từ phải qua trái.

Khi một dòng văn bản với một sự pha trộn hai cách bố trí từ trái qua

phải và từ phải qua trái được hiển thị, base direction sẽ được chỉ

định.Base direction là một script order của hệ thống ghi.Ví dụ,nếu văn

http://tailieuhay.com 102

Page 103: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

bản gốc là tiếng Anh với một số chữ Arabic được nhúng vào,thì base

direction sẽ là từ trái qua phải.Ngược lại,nếu văn bản gốc là tiếng Arabic

với một số chữ Anh nhúng vào hoặc các con số,thì base direction sẽ là từ

phải qua trái.

Base direction xác định các bố trí trong mỗi đoạn của văn bản với một

common direction được hiển thị.Trong ví dụ 5-4, base direction là từ trái

qua phải.Có ba hướng bố trí văn bản trong ví dụ này,văn bản tiếng Anh ở

đoạn đầu của câu chạy từ trái qua phải,văn bản Arabic chạy từ phải qua

trái,và các văn bản khác chạy từ trái qua phải.

4.3.3 Đo và định vị văn bản

Trừ khi bạn làm việc với font đơn cách,các kí tự khác nhau trong kiểu

font có chiều rộng khác nhau.Điều này có nghĩa tất cả các vị trí và kích

thước của các văn bản phải được tính toán một cách chính xác với các kí

tự được sử dụng.Ví dụ, một cột các chữ số được căn lề phải được hiển thị

trong kiêu font cân xứng,bạn không thể dễ dàng sử dụng các không gian

mở rộng cho vị trí của các văn bản.Đẻ căn lề các cột một cách đúng

đắn,bạn cần phải biết chính xác chiều rộng của mỗi số mà bạn có thể điều

chỉnh sao cho phù hợp.

Các văn bản thường sử dụng cách hiển thị theo nhiều dòng và nhiều

kiểu dáng,như theo kiểu nét đậm và in nghiêng.Trong trường hợp này,các

kí tự giống nhau có thể có các hình dáng khác nhau về chiều rộng,phụ

thuộc vào cách nó thể hiện kiể u dáng.Để có vị trí ,kích thước và render

text chính xác,bạn cần phải kiểm tra mỗi kí tự riêng lẻ và kiểu dáng được

sử dụng cho kí tự đó.Thật may là lớp TextLayout đã làm điều này cho

bạn.

Để hiển thị các văn bản đúng trong nhiều ngôn ngũ chẳng hạn như

Hebrew và Arabic,mỗi kí tự cần phải được cân nhắc và đặt vào bên trong

một ngữ cảnh với các kí tự bên cạnh.Bởi vì hình dáng và vị trí của các kí

http://tailieuhay.com 103

Page 104: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

tự có thể thay đổi được phụ thuộc vào từng ngữ cảnh,việc cân nhắc và sắp

đặt các đoạn văn bản mà không cần xét đến văn cảnh là một điều không

được tán thành.

4.3.4 Hỗ trợ thao tác với văn bản.

Để cho phép người dùng có thể sửa đổi text đã được hiển thị,bạn phải:

• Hiển thị dấu caret mà nó chỉ địn nơi một kí tự mới sẽ được thêm

vào khi người dùng thêm vào text.

• Di chuyển dấu caret và điểm chèn trong câu trả lời khi người dùng

đưa vào.

• Phát hiện sự lựa chọn của người dùng(hit detection).

• Làm nổi bật đoạn text được lựa chọn.

4.3.4.1 Hiển thị dấu nhắc

Trong các text có thể chỉnh sửa được,dấu caret được sử dụng để hiển

thị điểm chèn hiện tại,vị trí trong đoạn text nơi mà các kí tự mới sẽ được

chèn vào.Thông thường,một dấu caret được thể hiện là một thanh thẳng

đứng nhấp nháy giữa hai glyph.Kí tự mới được chèn vào và được hiển thị

tại vị trí của dấu caret.

Việc tính toán vị trí dấu caret có thể rất phức tạp,đặc biệt là trong các

text hai chiều.Các đoạn chèn vào trong các đường biên định hướng có hai

vị trí có thể chèn bởi vì hai glyph đó phù hợp với khoảng kí tự không

được hiển thị sát ngay các kí tự khác.Điều này được miêu tả trong hình 4-

6.Trong hình vẽ này,các dấu caret được thể hiện là các dấu ngoặc vuông.

http://tailieuhay.com 104

Page 105: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Hình 4-6 Dual Carets

Kí tự ở vị trí thứ 8 nằm sau dấu _ và nằm trước kí tự A.Nếu người

dùng muốn thêm một kí tự Arabic vào chỗ đó,glyph của nó được hiển thị

bên phải(phía trước) của kí tự A.Còn nếu người dùng muốn chèn một kí

tự English,glyph của nó được hiển thị bên trái(phía sau) của dấu _.

Để làm đươc điều này một số hệ thống hiển thị hai dấu caret,một

dấu là chính (primary) còn một dấu là phụ (secondary).Dấu caret chính

chỉ định nơi mà một kí tự chèn vào được hiển thị khi hướng của kí tự đó

cùng với hướng cơ sở của cả đoạn text.Còn dấu caret phụ cho biết một kí

tự chèn vào sẽ được hiển thị khi hướng của kí tự đó ngược với hướng cơ

sở của đoạn text.Lớp TextLayOut tự động hỗ trợ cả hai dấu caret,còn lớp

JtextComponent thì không.

Khi làm việc với văn bản hai chiều,bạn không thể đơn giản thêm vào

bề rộng của các glyph trước một khoảng trống của kí tự để tính toán vị trí

dấu caret.Nếu bạn làm vậy,dấu caret có thể hiện ra tại vị trí sai như bạn

thấy trong hình 4-7:

Figure 4-7 Caret Drawn incorrectly

Để dấu caret có thể hiển thị ở một vị trí hợp lý,bề rộng của các glyph

ở phía bên trái của khoảng trống cần phải được thêm vào và ngữ cảnh

http://tailieuhay.com 105

Page 106: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

hiện tại đưa vào tính toán.Trừ khi ngữ cảnh được đưa vào tính toán,các

phép đo glyph sẽ không cần thiết khớp với việc hiển thị.

4.3.4.2 Di chuyển dấu nhắc.

Tất cả các trình biên soạn văn bản đều cho phép người sử dụng di

chuyển dấu caret với các phím mũi tên.Người sử dụng mong muốn dấu

caret sẽ di chuyển theo hướng của các phím mũi tên đước ấn.Từ trái qua

phải của đoạn text,việc di chuyển các khoảng trống thêm vào rất đơn

giản:Phím mũi tên phải làm tăng khoảng trống được thêm vào bằng còn

phím mũi tên trái làm giảm đi.Trong các văn bản hai chiều hoặc các văn

bản có nhiều chữ ghép,cách làm này có thể khiến dấu caret nhẩy qua các

glyph theo hướng của đường biên và di chuyển trong theo hướng ngược

lại.

Để di chuyển dấu caret một cách mượt mà(smoothly) qua văn bản hai

chiều,bạn cần phải tính toán hướng của văn bản thi hành..Bạn ko thể đơn

giản tăng khoảng trống thêm vào khi phím mũi tên phải được ấn và giảm

nó khí phím mũi tên trái được ấn.Nếu khoảng trống thêm vào hiện tại

nằm bên trong một thi hành của các kí tự từ phải qua trái,thì phím mũi

tên phải có thể làm giảm khoảng trống thêm vào và phím mũi tên trái sẽ

làm tăng nó.

Di chuyển dấu caret ngang qua hướng đường biên là một việc khá

phức tạp như trong hình 4-8 dưới đây:

http://tailieuhay.com 106

Page 107: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Figure 4-8 Caret Movement

Chắc chắn các glyph sẽ không bao giờ có dấu caret giữa chúng.thay

vào đó dấu caret di chuyển qua các hiển thị của glyph một kí tự đơn.Ví

dụ,không bao giờ có một dấu caret bên trong chữ o và một sự biến âm(an

umlaut) nếu chúng được hiển thị bằng hai kí tự phân cách.Lớp

TextLayOut cung cấp các phương thức getNextRightHit and

getNextLeftHit để có thể dễ dàng di chuyển dấu caret một cách mượt mà

qua các văn bản hai chiều.

4.3.4.3 Hit Testing

Thông thường,một vị trí trong không gian của công cụ phải được

chuyển thành không gian trống của text.Ví dụ như,khi người sử dụng

nhấn chuột vào văn bản được chọn,vị trí của chuột được chuyển thành

khoảng trống và được sử dụng như điểm cuối của vùng lựa chọn.Theo

một cách logic,nó được chuyển ngược thành vị trí của dấu caret.

Khi bạn làm việc với văn bản hai chiều,một vị trí trực quan trong

phần hiển thị có thể đáp ứng cho hai offset khác nhau trong đoạn văn bản

gốc,như trong hình 4-9 dưới đây:

Hình 4-9 Hit Testing Bidirectional Text

Bởi vì một vị trí trực quan có thể đáp ứng cho hai offset khác nhau,

hit testing các văn bản hai chiều không phải là quan trọng của các phép đo

bề rộng của các đường nét (measuring glyph widths) trừ glyph tại các vị

http://tailieuhay.com 107

Page 108: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

trí chính xác được tìm thấy và sau đó ánh xạ vị trí đó đến một character

offset.

Bạn có thể thực hiên hit testing bằng việc sử dụng lớp

TextLayout.hitTestChar. Thông tin về hit được đóng gói trong đối

TextHitinfo bao gồm các thông tin về cạnh mà việc hit được thấy trên đó.

4.3.4.4 Đánh dấu vùng lựa chọn.

Một vùng các kí tự được lực chọn được hiển thị đồ họa bằng một

vùng được tô sáng,đó là vùng mà mỗi đường nét được hiển thị với màu

trái ngược với màu nền.

Vùng được tô sáng,giống như dấu caret,có nhiều phức tạp trong các văn

bản hai chiều hơn là trong các văn bản một chiều(monodirectional

text).Trong văn bản hai chiều,một dải liên tục các kí tự có thể không có

một vùng được tô sáng liên tục khi hiển thị.Ngược lại,một vùng sáng liên

tục cho thấy một cách trực quan một dải liên tục các nét có thể không phù

hợp với một kí tự đơn,dải liên tiếp của các kí tự.

Có hai cách để lựa chọn vùng sáng trong văn bản hai chiều:

• Logical highlighting(vùng sáng logic) - Với vùng sáng logic,các

kí tự được lựa chọn thường liên tiếp nhau trong mo hình văn bản(text

model),và vùng sáng được lựa chọn một cách liên tiếp.Xem ví dụ về

logical highlighting,xem hình 4-10.

• Visual highlighting(vùng sáng trực quan) - với visual

highlighting,bạn có thể có nhiều dải các kí tự được lựa chọn,nhưng vùng

sáng thông thường liên tiếp nhau.Ví dụ về visual highlighting,xem hình 4-

11.

http://tailieuhay.com 108

Page 109: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Hình 4-10 Logical Highlighting (contiguous characters)

Hình 4-11 Visual Highlighting (contiguous highlight region)

Logical highlighting đơn giản hơn trong việc thực thi,các kí tự được lựa

chọn thường liên tiếp nhau.

4.3.5 Thực thi việc hiển thị văn bản trong ứng dụng Java™ .

Phụ thuộc vào Java™ APIs mà bạn sử dụng,bạn có thể có ít hoặc

nhiều các điều khiển về text layout (hiển thị văn bản) như bạn cần:

1. • Nếu bạn muốn hiển thị cả một khối text hoặc cần các điều khiển

chỉnh sửa text,bạn có thể sử dụng JtextComponent,nó sẽ thực hiện

text layout cho bạn. JtextComponent được thiết kế để điều khiển

việc cần thiết của hầu hết các ứng dụng và hỗ trợ cho các văn bản

hai chiều.Để thêm thông tin về JtextComponent bạn xem thêm

phần “Using the JFC/Swing Packages” của bộ Java Tutorial.

2. • Nếu bạn muốn hiển thị một đoạn chuỗi kí tự đơn giản,bạn có thể

gọi đối tượng Graphics2D.drawString và yêu cầu Java 2D hiển thị

chuỗi kí tự cho bạn.Bạn cũng có thể sử dụng drawString để

http://tailieuhay.com 109

Page 110: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

render(trả về) kiểu của xâu kí tự và các xâu kí tự đó chứa kiểu văn

bản hai chiều.Để có thêm thông tin về rendering text qua lớp

Graphics2D,bạn xem thêm phần “Rendering Graphics Primitives”.

3. • Nếu bạn muốn thực thi việc chỉnh sửa văn bản của bạn,bạn có thể

sử dụng TextLayout để điều khiển việc hiển thị văn bản(text

layout),tô sáng( highlighting),và hit detection.Các tiện lợi được

cung cấp bởi lớp TextLayout cho hầu hết các trường hợp phổ

biến,bao gồm các xâu văn bản với việc pha trộn các kiểu Font,pha

trộn các kiểu ngôn ngữ,và văn bản hai chiều.Để có thêm thông tin

về cách sử dụng TextLayout,bạn xem thêm phần Managing Text

Layout.

4. •Nếu bạn muốn điều khiển toàn bộ việc làm thế nào để text được

shape và được định vị trí,bạn có thể xây dựng lớp Glyphvector của

bạn bằng cách sử dụng Font và sau đó render chúng dựa trên lớp

Graphics2D.Để có thêm thông tin về cách thực thi công cụ text

layput của bạn,bạn xem thêm phần “implementing a Custom Text

Layout Mechanism” .

Thông thường,bạn không cần phải thực hiện text layout.Cho hầu hết

các ứng dụng,JtextComponent là giải pháp tốt nhất cho việc hiển thị các

văn bản tĩnh và văn bản có thể chỉnh sửa.Tuy nhiên, JtextComponent

không hỗ trợ việc hiển thị dấu caret kép hoặc các đoạn lựa chọn liên tiếp

trong văn bản hai chiều.Nếu ứng dụng của bạn yêu cầu những đặc tính

trên,hoặc bạn thích thực hiện việc chỉnh sửa văn bản của bạn,bạn có thể

sử dụng Java 2D text layout APIs.

Quản lý việc hiển thị văn bản.

Lớp TextLayout hỗ trợ các text mà nó chứa đựng nhiều kiểu

dáng(style) và nhiều kí tự từ các hệ thống writing khác nhau,bao gồm

http://tailieuhay.com 110

Page 111: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Arabic và Hebrew(Arabic và Hebrew là các kiểu đặc biệt khó để hiển thị

bởi vì bạn phải reshape và reorder văn bản để được chấp nhận hiển thị).

Lớp TextLayout làm đơn giản việc sử lý cách hiển thị mà các phép

đo văn bản nếu bạn làm việc với các văn bản chỉ có tiếng Anh.Bằng việc

sử dụng TextLayout bạn có thể đạt được việc tạo chữ với chất lượng cao

mà không tốn nhiều công sức.

Text Layout Performance

Lớp TextLayout giúp bạn trong việc xác định vị trí và thứ tự của các

đường nét.Bạn có thể dùng TextLayout để:

• Hiển thị các văn bản một hướng và văn bản hai hướng.

• Hiển thị và di chuyển dấu caret.

• Thực hiện hit testing trên văn bản.

• Tô sáng vùng văn bản được lựa chọn.

ờng hợp,bạn có thể tính toán cách bố trí văn bản của bạn bằng cách

điều khiển một cách chính xác các đường nét mà bạn sử dụng và nơi

chúng sẽ được đặt(vào văn bản).Việc sử dụng các thông tin như các kích

cỡ đường nét(glyph sizes),các bảng co kéo(kerning tables),và cách ghép

chữ(ligature information),bạn có thể xây dựng giải thuật của bạn để tính

toán cách bố trí văn bản,bypassing công cụ bố trí của hệ thống(bypassing

the sys- tem’s layout mechanism).Để có thêm thông tin bạn xem thêm

phần “implementing a Custom Text Layout Mechanism”.

4.4.1 Trình bày văn bản.

Lớp TextLayout sẽ đặt văn bản một cách tự động,kể cả các văn bản

một hướng(BiDi-bidirectional),với việc tạo hình dáng(shaping) và

ordering chính xác.Để shape và order một cách chính xác,các đường nét

phải miêu tả các đường(line) của văn bản, TextLayout phải biết toàn bộ

ngữ cảnh của văn bản:

http://tailieuhay.com 111

Page 112: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

• Nếu văn bản nằm trên một đường đơn(single line) ,chẳng hạn như

một từ đơn của nhãn(label) cho một nút lệnh hoặc một đường trong hộp

thoại(dialog box),bạn có thể xây dựng một đối tượng TextLayout trực

tiếp từ văn bản.

• Nếu bạn có nhiều văn bản hơn là chỉ có một dòng hoặc bạn muốn

chia văn bản từ các single line thành các đoạn,bạn không thể xây dựng

đối tượng TextLayout một cách trực tiếp.Bạn phải sử dụng đối tượng

LineBreakMeasure để đáp ứng đủ các ngữ cảnh.

Hướng cơ bản của một văn bản thường được thiết lập bằng các thuộc

tính(kiểu dáng) trên văn bản.Nếu thuộc tính đó bị thiếu,lớp TextLayout

sử dụng giải thuật của bảng mã hai chiều Unicode,và nhận được hướng

cơ bản từ các kí tự bắt đầu trong đoạn.

Hiển thị dấu nhắc kép.

Lớp TextLayout chứa các thông tin về dấu caret như hình dáng của

dấu(caret shape),vị trí và góc(angle).Bạn có thể sử dụng các thông tin này

để dễ dàng hiển thị dấu caret trong cả văn bản một hướng và hai

hướng.Khi bạn vẽ dấu caret cho văn bản một chiều,việc sử dụng lớp

TextLayout sẽ đảm bảo dấu caret được đặt vị trí một cách chính xác.

TextLayout cung cấp cho ta nhiều hình dáng mặc định của dấu caret

và hỗ trợ một cách tự động dấu caret kép,như bạn thấy trong hình 4-

12.Các ví trí của dấu caret đó cũng được sử dụng như đường biên giữa

các đường nét cho việc tô sáng và hit testing.

Hình 4-12 Angled Carets

http://tailieuhay.com 112

Page 113: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Căn cứ vào khoảng trống được thêm vào,phương thức

getCaretShapes trả về một mảng hai phần tử của shape:phần tử thứ nhất

chứa dấu caret chính và phần tử thứ hai chứa dấu caret phụ,nếu chúng

cùng tồn tại.Để hiển thị cả hai dấu caret(dấu caret kép),bạn đơn giản chỉ

là vẽ cả hai shape của dấu caret;các dấu caret sẽ được render một cách tự

động tại những vị trí chính xác.

Nếu bạn muốn sử dụng shape của dấu caret một cách tùy thích,bạn có

thể tìm đến vị trí và góc của các dấu caret bằng đối tượng TextLayout và

vẽ chúng theo cách của bạn.

Trong ví dụ dưới đây,hình dáng của dấu caret chính và phụ mặc định

được vẽ trên các màu khác nhau.Đây là cách phổ biến để tạo sự khác biệt

của hai dấu caret .

Shape[] caretShapes =

layout.getCaretShapes(hit);

g2.setColor(PRiMARY_CARET_COLOR);

g2.draw(caretShapes[0]);

if (caretShapes[1] != null){

g2.setColor(SECONDARY_CARET_COLOR);

g2.draw(caretShapes[1]);

}

4.4.3 Di chuyển dấu nhắc.

Bạn cũng có thể sử dụng lớp TextLayout để xác định kết quả của

việc thêm vào các khoảng trống khi người sử dụng ấn các phím mũi tên

trái hoặc phải.Dựa vào đối tượng TextHitinfo,nó cho ta biết vị trí hiện tại

của khoảng trống thêm vào,phương thức getNextRightHit trả về kiểu đối

tượng TextHitinfo mà nó cho biết chính xác vị trí của khoảng trống thêm

http://tailieuhay.com 113

Page 114: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

vào khi phím mũi tên phải được nhấn.Còn phương thức getNextLeftHit

cho ta thông tin như vậy khi phím mũi tên trái được nhấn.

Trong ví dụ dưới đây,vị trí hiện tại của khoảng trống chèn vào được

di chuyển đến nơi tương ứng khi mà phím phải được ấn.

TextHitinfo newinsertionOffset =

layout.getNextRightHit(insertionOffset);

if (newinsertionOffset != null)

{

Shape[] caretShapes =

layout.getCaretShapes(newinsertionOffset);

// draw carets

...

insertionOffset = newinsertionOffset;

}

4.4.4 Hit Testing

Lớp TextLayout cho ta một công cụ đơn giản để hit testing văn

bản.Phương thức hitTestChar sẽ lấy tọa độ x và y từ chuột(takes x and y

coordinates from the mouse) như các đối số và trả về kiểu đối tượng

TextHitinfo.Đối tượng TextHitinfo chứa khoảng trống chèn vào cho vị

trí và cạnh mà việc hit was on.

Trong ví dụ dưới đây,phương thức hitTestChar được gọi trong đối tượng

TextLayout và sau đó phương thức getinsertindex được sử dụng để lấy

lại khoảng chứa trống.

TextHitinfo hit = layout.hitTestChar(x, y);

int insertindex = hit.getinsertindex();

http://tailieuhay.com 114

Page 115: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

4.4.5 Đánh dấu vùng lựa chọn.

Bạn có thể nhận một đối tượng Shape mà nó hiển thị vùng sáng từ đối

tượng TextLayout. Đối tượng TextLayout sẽ tự động giữ ngữ cảnh trong

một mảng khi tính toán số chiều của vùng được tô sáng.Lớp TextLayout

hỗ trợ cả vùng sáng logic và vùng sáng trực quan.

Trong ví dụ dưới đây,vùng sáng được điền với màu sáng và sau đó

đối tượng TextLayout sẽ vẽ toàn bộ vùng được điền đó.Đây là một cách

đơn giản để hiển thị đoạn văn bản được tô sáng.

Shape highlightRegion =

layout.getLogicalHighlightShape(hit1,

hit2);

graphics.setColor(HiGHLiGHT_COLOR);

graphics.fill(highlightRegion);

graphics.drawString(layout, 0, 0);

4.4.6 Querying Layout Metrics

Lớp TextLayout cung cấp cách truy cập đến các phép đo đồ họa cho

toàn bộ dải văn bản hiển thị.Các phép đo đã có sẵn trong lớp TextLayout

bao gồm ascent,descent,leading(khoảng cách giữa các dòng chữ so với

dòng cơ sở), advance, visible advance và bounding rectangle (giới hạn

của khung hình chữ nhật).

Có nhiều hơn một đối tượng Font có thể được liên kết với một đối

tượng TextLayout:sự khác nhau về kiểu dáng khi thực thi có thể sử dụng

các kiều font khác nhau.Các giá trị ascent và descent của toàn bộ kiểu

font được sử dụng trong đối tượng TextLayout.Việc tính toán giá trị

leading của đối tượng TextLayout thì phức tạp hơn nhiều,nó không có giá

trị leading cực đại.

http://tailieuhay.com 115

Page 116: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Giá trị advance của đối tượng TextLayout chính là chiều dài của

nó:đó là khoảng cách từ cạnh bên trái của nét bên trái nhất đến cạnh bên

phải của nét bên phải nhất.Giá trị advance thường được chỉ định là total

advance.Còn giá trị visible advance là chiều dài của đối tượng

TextLayout mà không có các khoảng trắng.

Khung giới hạn của một đối tượng TextLayout bao quanh toàn bộ

văn bản trong phần bố trí..Nó bao gồm toàn bộ các đườn nét trực

quan(thấy được) và các dấu caret biên.(Một số trong đó có thể được lấy từ

gốc hoặc gốc + advance).Khung giới hạn có quan hệ với nguồn gốc của

đối tượng TextLayout,không liên quan đến vị trí trên màn hình.

Trong ví dụ dưới đây,văn bản trong một đối tượng TextLayout được

vẽ bên trong một khung giới hạn.

graphics.drawString(layout, 0, 0);

Rectangle2D bounds = layout.getBounds();

graphics.drawRect(bounds.getX()-1,

bounds.getY()-1,

bounds.getWidth()+2, bounds.getHeight()+2);

4.4.7 Vẽ văn bản trên nhiều dòng.

Lớp TextLayout còn có thể được sử dụng để hiển thị đoạn text mà

nó có nhiều dòng.Ví dụ như,bạn có thể lấy một đoạn của văn bản,chồng

các line của văn bản đó một bề rộng nào đó,và hiển thị các đoạn như

nhiều dòng của văn bản.

Để làm được điều này,bạn không phải làm trực tiếp bằng việc tạo ra

nhiều đối tượng TextLayout mà bạn hiển thị mỗi dòng của văn bản-

phương thức LineBreakMeasure sẽ làm điều đó cho bạn.Các kiểu văn bản

hai chiều không thể thực hiện điều này một cách chính xác trừ khi tất cả

http://tailieuhay.com 116

Page 117: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

văn bản trong một đoạn đã có sẵn.Phương thức LineBreakMeasure đóng

gói toàn bộ thông tin về ngữ cảnh để tạo ra các đối tượng TextLayout

chính xác.

Khi văn bản được hiển thị qua nhiều dòng,chiều dài của những dòng

đó thường được xác định bằng chiều rộng của vùng hiển thị.Sự chia

dòng(Line breaking hay line wrapping) là việc xác định nơi mà những

dòng bắt đầu và kết thúc.

/*

* FontSelection.java

* 1.0

* 12/03/06

*/

import java.awt.BorderLayout;

import java.awt.Color;

import java.awt.Dimension;

import java.awt.Font;

import java.awt.FontMetrics;

import java.awt.Graphics;

import java.awt.Graphics2D;

import java.awt.GraphicsEnvironment;

import java.awt.GridLayout;

import java.awt.event.itemEvent;

import java.awt.event.itemListener;

import java.awt.event.WindowAdapter;

import java.awt.event.WindowEvent;

import java.util.Vector;

import javax.swing.JApplet;

http://tailieuhay.com 117

Page 118: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

import javax.swing.JComboBox;

import javax.swing.JFrame;

import javax.swing.JLabel;

import javax.swing.JPanel;

/*

* Applet nay hien thi mot xau voi lua chon cua

nguoi su dung.

*/

public class FontSelection extends JApplet

implements itemListener {

/**

*

*/

private static final long serialVersionUiD =

5469031020823166920L;

JLabel fontLabel, sizeLabel, styleLabel;

FontPanel fontC;

JComboBox fonts, sizes, styles;

int index = 0;

String fontchoice = "L a ch n Font";ự ọ

int stChoice = 0;

http://tailieuhay.com 118

Page 119: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

String siChoice = "10";

@SuppressWarnings("unchecked")

public void init() {

getContentPane().setLayout(new

BorderLayout());

JPanel topPanel = new JPanel();

JPanel fontPanel = new JPanel();

JPanel sizePanel = new JPanel();

JPanel stylePanel = new JPanel();

JPanel sizeAndStylePanel = new JPanel();

topPanel.setLayout(new BorderLayout());

fontPanel.setLayout(new GridLayout(2,

1));

sizePanel.setLayout(new GridLayout(2,

1));

stylePanel.setLayout(new GridLayout(2,

1));

sizeAndStylePanel.setLayout(new

BorderLayout());

topPanel.add(BorderLayout.WEST,

fontPanel);

sizeAndStylePanel.add(BorderLayout.WEST,

sizePanel);

http://tailieuhay.com 119

Page 120: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

sizeAndStylePanel.add(BorderLayout.CENTER,

stylePanel);

topPanel.add(BorderLayout.CENTER,

sizeAndStylePanel);

getContentPane().add(BorderLayout.NORTH,

topPanel);

fontLabel = new JLabel();

fontLabel.setText("Fonts");

Font newFont = getFont().deriveFont(1);

fontLabel.setFont(newFont);

fontLabel.setHorizontalAlignment(JLabel.CENTER);

fontPanel.add(fontLabel);

sizeLabel = new JLabel();

sizeLabel.setText("Kích C ");ỡ

sizeLabel.setFont(newFont);

sizeLabel.setHorizontalAlignment(JLabel.CENTER);

sizePanel.add(sizeLabel);

styleLabel = new JLabel();

styleLabel.setText("Ki u ch ");ể ữ

styleLabel.setFont(newFont);

styleLabel.setHorizontalAlignment(JLabel.CENTER);

http://tailieuhay.com 120

Page 121: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

stylePanel.add(styleLabel);

GraphicsEnvironment gEnv =

GraphicsEnvironment

.getLocalGraphicsEnvironment();

String envfonts[] =

gEnv.getAvailableFontFamilyNames();

Vector vector = new Vector();

for (int i = 1; i < envfonts.length; i++)

{

vector.addElement(envfonts[i]);

}

fonts = new JComboBox(vector);

fonts.setMaximumRowCount(9);

fonts.additemListener(this);

fontchoice = envfonts[0];

fontPanel.add(fonts);

sizes = new JComboBox(new Object[]

{ "10", "12", "14", "16", "18" });

sizes.setMaximumRowCount(9);

sizes.additemListener(this);

sizePanel.add(sizes);

styles = new JComboBox(new Object[]

{ "PLAiN", "BOLD", "iTALiC",

"BOLD & iTALiC" });

styles.setMaximumRowCount(9);

styles.additemListener(this);

sizes.setMaximumRowCount(9);

http://tailieuhay.com 121

Page 122: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

stylePanel.add(styles);

fontC = new FontPanel();

fontC.setBackground(Color.white);

getContentPane().add(BorderLayout.CENTER,

fontC);

}

public void itemStateChanged(itemEvent e) {

if (e.getStateChange() !=

itemEvent.SELECTED) {

return;

}

Object list = e.getSource();

if (list == fonts) {

fontchoice = (String)

fonts.getSelecteditem();

} else if (list == styles) {

index = styles.getSelectedindex();

stChoice = index;

} else {

siChoice = (String)

sizes.getSelecteditem();

}

fontC.changeFont(fontchoice, stChoice,

siChoice);

}

http://tailieuhay.com 122

Page 123: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

public static void main(String s[]) {

JFrame f = new JFrame("Ch n ki u Font");ọ ể

f.addWindowListener(new WindowAdapter() {

public void

windowClosing(WindowEvent e) {

System.exit(0);

}

});

JApplet fontSelection = new

FontSelection();

f.getContentPane().add(fontSelection,

BorderLayout.CENTER);

fontSelection.init();

f.setSize(new Dimension(550, 250));

f.setVisible(true);

}

}

class FontPanel extends JPanel {

/**

*

*/

private static final long serialVersionUiD =

7850814263388447528L;

Font thisFont;

public FontPanel() {

http://tailieuhay.com 123

Page 124: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

thisFont = new Font("Arial", Font.PLAiN,

10);

}

public void changeFont(String f, int st,

String si) {

integer newSize = new integer(si);

int size = newSize.intValue();

thisFont = new Font(f, st, size);

repaint();

}

public void paintComponent(Graphics g) {

super.paintComponent(g);

Graphics2D g2 = (Graphics2D) g;

int w = getWidth();

int h = getHeight();

g2.setColor(Color.darkGray);

g2.setFont(thisFont);

String change = "Ch n Font ,c ch vàọ ỡ ữ

ki u ch .";ể ữ

FontMetrics metrics =

g2.getFontMetrics();

int width = metrics.stringWidth(change);

int height = metrics.getHeight();

g2.drawString(change, w / 2 - width / 2,

h / 2 - height / 2);

}

}

http://tailieuhay.com 124

Page 125: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Kết quả của chương trình:

http://tailieuhay.com 125

Page 126: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Chương 5

Tạo ảnh

Java 2D™ API hỗ trợ 3 model vẽ ảnh.

•Model khách chủ (producer/consumer) đã hỗ trợ trong phiên bản

trước củan bản JDK.

•Model trung gian (immediate mode model) được giới thiệu tr

ong Java™ 2 SDK release.

•Model đường ống tương thích với model trung gian và sex được

cài đặt đầy đủ trong bản Java Advanced imaging API sắp tới.

Trong chương này chúng ta tập trung vào các đối tượng và các công

nghệ của model tạo ảnh mode trung gian(immediate mode). Các lớp mode

trung gian và các giao diện củan Java 2D API cuang cấp các công nghệ

cho việc xử lý ánh xạ các điểm với dữ liệ của nó trong bộ nhớ. Hàm API

này hỗ trợ cho việc truy nhập dữ liệu ảnh tỏng các định dạng lưu trữ khác

nhau và thao tác với dữ liệu ảnh qua vàiloại phép toán lọc.

5.1 Các giao diện và các lớp

Các API tạo ảnh mode trung gian trong Java 2D™ API có thể

được nhóm lại trong 6

Cataloge sau: Các giao diện, các lớp dữ liệu ảnh, các lớp thao toán tử ảnh,

các lớp model mẫu, các lớp model màu, các ngoại lệ (exceptions).

http://tailieuhay.com 126

Page 127: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

5.1.1 Các giao diện imaging (imaging interfaces)

Interface DescriptionBufferedImageOp Mô tả các thao tác vào đơn ra đơn thực hiện

trên đối tượng Bufferedimage. Được cài đặt

bởi AffineTransformOp, ColorConvertOp,

ConvolveOp, LookupOp và RescaleOp.RasterOp Định nghĩa các thao tác vào ra đơn thực hiện

trên các đôi tượng Raster Được cài đặt bởi

AffineTransformOp, BandCombineOp,

ColorConvertOp, ConvolveOp, LookupOp và

RescaleOp.

RenderedImage Định nghĩa giao thức cho các đối tượng chứa

hoặc có thể sản sinh dữ liệu ảnh trong kiểu

RastersWritableRenderedImag

e

Mở rộng Renderedimage

Định nghĩa cac giao thức cho các đói tượng

chứa hoặc sản sinh dữ liệu ảnh trong kiêu

Raster có thể được thay đổi.

TileObserver Định nghĩa các đối tượng muốn được báo khi

trang thái chỉnh sủa của một

WritableRenderedimage thay đổi.

.

5.1.2 Các lớp dữ liệu ảnh(image Data Classes)

Clases DescriptionBufferedimage Mở rông image cài đặt WriteableRenderedimage

Một ảnh với một bộ đệm dữ liệu có thể truy cập.

http://tailieuhay.com 127

Page 128: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Một Bufferedimage có một ColorModel và một

Raster dữ liệu ảnh.ByteLookupTable Mở rộng LookupTable

Một LookupTable chứa các bye dữ liệu.DataBuffer Bao bọc một hay nhiều các mảng dữ liệu chứa dữ

liệu điểm. Mỗi mảng được gọi là “bank”DataBufferByte Mở rộng DataBuffer. Một bộ đệm dữ liệu chứa các

byte dữ liệu. (đã dùng trong Java Advanced

imaging API)DataBufferint Mở rộng DataBuffer (Final))

Một bộ đệm dữ liệu chứa dữ liệu số nguyên (đa

dùng trong Java Ađvance imaging API)DataBufferShort Mở rộng DataBuffer (Final)

Một bộ đệm dữ liệu chứa dữ liệu số nguyên short

(đã dùng trong Java Advanced imanging API). DataBufferUShort Mở rộng DataBuffer (Final)

Một bộ đệm dữ liệu chứa dữ liệu số nguyên short

không dấu.

Kernel Một ma trận mô tả cách nhập một dữ

liệu và các điểm biên của nó tác động đến giá trị

của điểm trong bộ lọc ConvolveOPLookupTable Mở rộng Object

Một bảng ánh xạ các giá trị từ dữ liệu điểm đơn

băng tới các giá trị màu.Raster Một mảng các điểm góc từ đó bạn có thể nhận về

các dữ liệu điểm. Một Raster chứa một DataBuffer

và một SampleModel.ShortLookupTable Mở rộng LookupTable

Một bảng tham chiếu chứa các dữ liệu số nguyên

shortWritableRaster Mở rộng Raster

Một Raster có thể chỉnh sửa.

http://tailieuhay.com 128

Page 129: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

5.1.3 image Operation Classes

Clases DescriptionAffineTransformOp Cài đặt : BufferedimageOp, RasterOp

Một lớp định nghĩa một biến đổi affine để thực

hiện một sự ánh xạ tuyến tính từ các toạ độ 2D

trong một ảnh nguồn hoặc Raster sang các toạ độ

2D trong ảnh đích hoặc Raster. Lớp này có thể thực

hiện cả ánh xạ song ánh và các phép toán biến đổi

láng giềng gần nhất.BandCombineOp Cài đặt RasterOp

Dùng một ma trận xác định, thao tác này thực hiện

một sự kết hợp tuyến tính tuỳ ý của các dải band

trong một Raster.BufferedimageFilter Mở rộng imageFilter

Một imageFilter cung cấp một cách đơn giản của

việc sùng một BufferedimageOp(toán tử một

nguồn đơn /một đích đơn) để lọc một

Bufferedimage hoặc Raster.ColorConvertOp Cài đặt BufferedimageOp, RasterOp

Thực hiên sự chuyển đổi dữ liệu màu điểm theo

điểm trong ảnh nguồn. ConvolveOp Cài đặt BufferedimageOp, RasterOp

Dùng một Kernel để thực hiện cải thiện ảnh nguồn.

Một sự cải thiện là một sự tao tác không gian nơi

các điểm cận biên vào được nhân bội bởi một giá

trị Kernel để tạo giá trị của điểm ra. Kernel định

nghĩa một cách toán học quan hệ giữa các điểm

trong quan hệ láng giềng trung gian của điểm vào

và điểm ra.

http://tailieuhay.com 129

Page 130: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

LookupOp Cài đặt BufferedimageOp, RasterOp

Thực hiện thao tác tham chiếu từ nguồn tới đích.

Với các Raster, các thao tác tham chiếu trên các giá

trị mẫu, các Bufferedimage, thao tác tham chiếu

trên thành phần màu và thành phần alpha.RescaleOp Cài đặt BufferedimageOp, RasterOp

Thực hiện việc vẽ lại điểm bởi điểm (pixel by pixel

rescaling) của dữ liệ trong ảnh nguồn bởi việc nhân

mỗi giá trị điểm với hệ số và sau đó thêm vào một

phần chênh (an offset).

5.1.4 Sample Model Classes

Clases DescriptionBandedSampleModel Mở rộng ComponentSampleModel

(Final)

Cung cấp truy cập dữ liệu ảnh đã chứa

giống như các mẫu đã chứa như những

dải (bands) trong các bank riêng biệt

của DataBuffer. Một điểm bao gồm

một mẫu từ mỗi dải (band)ComponentSampleModel Mở rộng SampleModel

Cung cấp truy cạp tới dữ liệu ảnh chứa

với mỗt mẫu của môt điểm tâp trung

trong mỗi phần tử riêng biệt của

DataBuffer. Các loại chèn điểm khác

nhau được hỗ trợMultiPixelPackedSampleModel Mở rộng SampleModelPixelinterleavedSampleModel Mở rộng ComponentSampleModel

Cung cấp truy nhập tới dữ liệu ảnh đã

chứa dữ liệu mẫu cho mỗi điểm trong

http://tailieuhay.com 130

Page 131: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

các phần tử hiệu chỉnh của mảng dữ

liệu, và tất cả các phần tử trong bank

đơn của một DataBuffer.SampleModel Một lớp trừu tượng định nghĩa một cơ

chế cho viễc xuất ra dữ liệu mẫu từ một

ảnh mà không biết cách dữ liệu được

chứa trong một DataBuffer.SinglePixelPackedSampleMode

l

Mở rộng SampleModel

Cung cấp truy nhập tới dữ liệu ảnh đã

được bảo quản với tất cả các mẫu phụ

thuộc vào các điểm riêng lẻ đã gói vào

trong một phần tử của một DataBuffer.

Color Model Classes

Clases DescriptionColorModel Cài đặt lớp trong suốt định nghĩa các

phương thức cho việc chuyển đổi từ các giá

trị điểm ánh tới các thành phần màu như đỏ,

xanh lá cây, xanh da trời (red, green, blue).ComponentColorModel Mở rộng ColorModel

Một ColorModel có thể giữ một ColorSpace

có thể thay đổi, một mảng các thành phần

màu ứng với ColorSpace. Lớp này có thể

được dùng để biểu diễn hầu hết các model

màu trên hầu hết các loại thiết bị đồ hoạ

(GraphicsDevices)

http://tailieuhay.com 131

Page 132: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

DirectColorModel Mở rộng lớp PackedColorModel JDK1.1 .

Một ColorModel biểu diễn các giá trị có

các thành phần màu RGB đã nhúng trực tiếp

trong các bit của điểm. Model màu này

tương tự với một X11 TrueColor. RGB

ColorModel mặc định được trả về bởi

ColorModel.getRGBdefault như một

DirectColorModel. indexColorModel

Extends: ColorModelPackedColorModel Mở rộng ColorModel.

Một ColorModel trừu tượng biểu diễn các

giá trị điểm có các thành phần nhúng trực

tiếp trong các bit của một điểm.

DirectColorModel mở rộng

PackedColorModel để hỗ trợ các điểm chứa

các thành phần màu RGB.SampleModel Một lớp trừu tượng định nghĩa một cơ chế

cho viễc xuất ra dữ liệu mẫu từ một ảnh mà

không biết cách dữ liệu được chứa trong

một DataBuffer.

5.1.6 Exception Classes

Clases DescriptionimagingOpException Mở rộng RuntimException.

Đưa ra nếu một trong các phương thức

BufferedimageOp hoặc RasterOp không thể

xử lý ảnh.RasterFormatException Mở rộng RuntimException.

http://tailieuhay.com 132

Page 133: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Tạo ra nếu có một thông tin bố trí không

hợp lệ trong Raster.

5.2 Immediate Mode imaging Concepts

Model tạo ảnh mode trung gian hỗ trợ các phân giải cố định đã chứa

trong bộ nhớ. Model cũng hỗ trợ các thao tác lọc trên dữ liệu ảnh. Một số

các lớp và các giao diện được dùng trong model này

Hình 5-1 Bufferedimage và các lơp hỗ trợ.

Như hình 5-1, Bufferedimage cung cấp việc quản lý ảnh chung. Một

Bufferimage có thể được tạo trực tiếp trong bộ nhớ và được dùng để giữ

và thao tác dữ liệu ảnh đã nhận từ một file hoặc URL. Một

Bufferedimage có thể được hiển thì dùng bất cứ đối tượng Graphics2D

nào cho một thiết bị màn hình, hoặc đẩy tới bất cứ đích nào khác dùng

ngữ cảnh tương thích Graphics2D. Một đối tượng Bufferedimage chứa 2

đối tượng khác: một Raster và một ColorModel.

Lớp Raster cung cấp quản lý dữ liệu ảnh. Nó biểu diễn toạ độ de-cac

của ảnh và duy trì dữ liệu ảnh trong bộ nhớ, và cung cáp một cơ chế cho

http://tailieuhay.com 133

Page 134: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

tao ảnh vớ nhiều ảnh nhỏ từ một bộ đệm dữ liệu ảnh đơn. Nó cũng cung

cấp các phương thức cho việc truy cập các điểm xác định với một

ảnh(image). Một đới tượng Raster chứa hai đối tượng khác, một

DataBuffer và một SampleModel.

Lớp DataBuffer giữ dữ liệu điểm trong bộ nhớ.

Lớp SampleModel thể hiện dữ liệu trong bộ đệm và cung cấp no như

các điểm riêng rẽ hoặc dải điểm chữ nhật.

image Package cung cấp thêm các lớp định nghĩa các thao tác lọc

trên các đối tượng Bufferedimage và Raster. MỖi thao tác xử lý ảnh

được nhúng trong lớp cài đặt giao diện BufferedimageOp, giao diện

RasterOp, hoặc cả hai giao diện. lớp thao tác định nghĩa các phương thức

lọc (filter) thực hiện thao tác ảnh thực sự.

Hình 5-2 minh hoạ model cơ bản cho Java 2D™ API image xử lý

ảnh.

Các thao tác đã hỗ trợ bao gồm:

• Biến đổi Affine

• Amplitude scaling

• Lookup-table modification

• Linear combination of bands

• Color conversion

http://tailieuhay.com 134

Page 135: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

• Convolution

Chú ý rằng nếu bạn thích hiển thị và thao tác các ảnh, bạn chỉ cần

hiểu lớp Bufferedimage và các lớp thao tác lọc. Mặt khác, nếu bạn có ý

định viết các bộ lọc hoặc trực tiếp truy nhập dữ liệu ảnh, bạn cần phải

hiểu các lớp liên quan với Bufferedimage.

5.2.1 Terminology

Ở đây có vài khái niệm được dùng qua các thảo luận dưới đây:

Các phần tử dữ liệu-Data Elements: các loại nguyên tố dùng như là các

đơn vị lưu trữ dữ liệu ảnh. Các Data element là các thành viên riêng lẻ

của một mảng DataBuffer. Bố trí (layout)của các phần tử trong bộ đệm dữ

liệu là độc lập với cách biểu điễn của dữ liệu như là các điểm bởi một

SampleModel của ảnh.

Các mẫu - Samples: Các thành viên riêng biệt của các điểm của một

ảnh. Một SampleModel cung cấp một cơ chế cho việc chuyển đổi các

phần tử trong DataBuffer sang các điểm và các mẫu của nó. Các mẫu của

một điểm có thể biểu diễn các giá trị nguyên thuỷ trong model màu cụ

thể. Ví dụ, một điểm trong model màu RGB bao gồm 3 mẫu : red, green

và blue.

Các thành phần - Components: Các giá trị của các điểm độc lập với

sự biểu diễn màu. Sự phân biệt giữa thành phần(component) và

mẫu(sample) là hữu ích với indexColorModel, nơi mà các thành phần

điểm được đánh chỉ số sang LookupTable.

Dải - Band: Tập tất cả các mẫu của một loại trong một ảnh, giống như

tất cả các mẫu màu đỏ hoặc tất cả các mẫu màu xanh lá cây. Dữ liệu điểm

có thể được chứa trong một số cách, hỗ trợ hai trong Java 2D API đang

được tụ họp và thêm vào. Lưu trữ tập hợp tổ chức dữ liệu ảnh bởi các dải

(bands), và một điểm được trang bị mọt dữ liệu mẫu từ vị trí mẫu với

http://tailieuhay.com 135

Page 136: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

mảng đơn chứa tất cả các điểm, và các dải bao gồm tập các mẫu cùng chỉ

số vị trí trong mỗi điểm.

Các nguyên tố - Primaries: Các thành viên phân biệt của một giá trị

màu trong một model màu xác định, ví dụ model RGB dạng các giá trị

màu từ các nguyên tố red, green, và blue.

5.3 Using Bufferedimages

Lớp Bufferedimage là lớp chính hỗ trợ mode tạo ảnh trung gian. Nó

cũng quản lý mọt ảnh trong bộ nhớ, cung cấp các cách để lưu các dữ liệu

điểm, biểu diễn dữ liệu điểm, và đẩy dữ liệu điểm tới một Graphics hoặc

ngữ cảnh Graphics2D.

5.3.1 Creating a Bufferedimage

Để tạo một Bufferedimage, gọi Component.createimaget, hàm này

trả về mọt Bufferedimage các đặc tính vẽ của nó tương ứng các thành

phần đã dùng tạo nó. Ảnh được tạo là không rõ , phần nổi và phần nền

có các màu của các thành phần bạn không thể hiệu chỉnh độ trong của

một ảnh.Bạn có thể dùng kỹ thuật này khi bạn muốn làm gấp đôi bộ đêm

vẽ ảnh cho sự động trong một thành phần.

public Graphics2D createDemoGraphics2D(Graphics

g) {

Graphics2D g2 = null;

int width = getSize().width;

int height = getSize().height;

if (offimg == null || offimg.getWidth() !=

width ||

offimg.getHeight() != height) {

http://tailieuhay.com 136

Page 137: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

offimg = (Bufferedimage) createimage(width,

height);

}

if (offimg != null) {

g2 = offimg.createGraphics();

g2.setBackground(getBackground());

}

// .. clear canvas .. g2.clearRect(0, 0,

width, height);

return

}

Bạn cũng có thể tạo một Bufferedimage trống trong bộ nhớ dùng

một vài hàm tạo đã được cung cấp.

5.3.2 Drawing in an Offscreen Buffer

Lớp Bufferedimage có thể đuợc đùng để chuẩn bị các phần tử đồ hoạ

không hiêển thị (offscreen )sau đó copy chúng ra màn hình. Kỹ thuật này

hữu ích đặc biệt khi một graphic phức tạp hoặc dùng lặp lại. Ví dụ, nếu

bạn muốn hiển thị`hình ảnh tinh vi trong vài lần, bạn có thể vẽ nó một lần

trong bộ đệm offscreen và sau đó copy nó tới các vị trí khác nhau trên cửa

sổ. Bằng việc vẽ các hình một lần và việc sao chép nó bạn có thể hiển thị

đồ hoạ nhanh hơn.

Java.awt package có khả năng dùng các bộ đệm offsceam bởi điều

này bạn vẽ một đối tượng ảnh cùng cách mà bạn vẽ ra cửa sổ. Tất cả các

http://tailieuhay.com 137

Page 138: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

tính năng đẩy (rendering) ở Java 2D™ API có thể được dùng khi vẽ các

ảnh offscreen.

Các bộ đệm offscreen thường được dùng cho hoạt hoạ. Ví dụ, bạn có

thể dùng một bộ đệm offscreen để vẽ một đối tượng một lần và sau đó

cho nó chuyển động trong một cửa sổ. Tương tự, bạn có thể dùng một bộ

đệm offscreen để cung cấp sự hồi tiếp như khi người dùng di chuyển một

hình dùng chuột. Thay vào việc vẽ lại hình tại mỗi vị trí, bạn có thể vẽ

hình một lần ra bộ đệm offscreen và sau đó copy nó tới vị trí chuột như

khi người dùng thả chuột(drag the mouse).

Hình 5-3Using an Offscreen Buffer

Hình 5-3 mô tả cách một chương trình có thể vẽ ra một offscreen

image sau đó sao chép nó ra một cửa sổ nhiều lần. Lần cuối cùng ảnh

được sao chép, nó đã được biến đổi. Chú ý rằng sự biến đổi ảnh thay cho

việc vẽ lại nó với sự biến đổi có thể kết quả không được thoả mãn.

5.3.2.1 Creating an Offscreen Buffer

http://tailieuhay.com 138

Page 139: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Cách đơn giản nhất để tạo ra một image mà bạn có thể dùng như một

offscreen buffer là dùng phương thức Component.createimage.

Bằng việc tạo một image mà không gian màu của nó, sâu, và bố trí

các điểm chính xác với cửa sổ trong đó bạn đang vẽ, image có thể được

đưa tới (blitted) thiết bị đồ hoạ một cách hiệu quả. Điều này cho phép

hàm drawimage làm việc nhanh chóng.

Bạn cũng có thể tạo một đối tượng Bufferedimage trực tiếp để dùng như

là một offscreen buffer. Điều này rất hữu ích khi bạn cần điều khiển qua

kiểu của offscreen hoặc trong suốt.

Bufferedimage hỗ trợ vài kiểu định nghĩa trước:

• TYPE_3BYTE_BGR

• TYPE_4BYTE_ABGR

• TYPE_4BYTE_ABGR_PRE

• TYPE_BYTE_BiNARY

• TYPE_BYTE_GRAY

• TYPE_BYTE_iNDEXED

• TYPE_CUSTOM

• TYPE_iNT_ARGB_PRE

• TYPE_iNT_ARGB

• TYPE_iNT_BGR

• TYPE_iNT_RGB

• TYPE_USHORT_555_RGB

• TYPE_USHORT_565_RGB

• TYPE_iNT_GRAY

Một đối tượng Bufferedimage có thể chứa một kênh alpha. Trong

hình 5-3, một kênh alpha được dùng để phân biệt các vùng được vẽ và

không được vẽ, cho phép một hình dạng bất quy tắc xuất hiện qua các

hình mà bạn đã vẽ (trong trường hợp này, một hình chữ nhật bóng). Trong

http://tailieuhay.com 139

Page 140: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

vài trường hợp khác, bạn có thể dùng một kênh alpha để trộn các màu của

một ảnh mới vào nó trong một ảnh đã tồn tại.

Chú ý : trừ khi bạn cần một dữ liệu ảnh alpha cho rõ ràng, như với

một hình ảnh dạng bất thường biểu diễn trong hình 5-2, bạn nên tránh

tạo một bộ đệm offscreem alpha. Dùng alpha ở nơi nó không cần làm

chậm hiệu năng render.

GraphicsConfiguration cung cấp các phương thức thuận tiện tự động tạo

các bộ đệm ảnh trong định dạng tương thích với cấu hình của bạn. Bạn

cũng có thể lấy về cấu hình đồ hoạ liên kết với thiết bị đồ hoạ trên đó cửa

sổ tập trung để lấy thông tin, bạn cần khởi tạo một đối tượng

Bufferedimage thích hợp

5.3.2.2 Drawing in an Offscreen Buffer

Để vẽ trong một bộ đệm ảnh, Gọi Bufferimage.createGraphics() , tra

về một đối tượng Graphics2D. Với đối tượng này, có thể gọi tát cả các

phương thức Graphics2D để vẽ các hình ảnh nguyên tố, text, và render

các hình ảnh khác trong image. Kỹ thuật vẽ này hỗ trợ việc rung động và

các cải thiện khác được cung cấp bởi 2D imaging package.

Đoạn code dưới đây minh hoạ sử dụng offscreen buffering :

public void update(Graphics g){

Graphics2D g2 = (Graphics2D)g;

if(firstTime){

Dimension dim = getSize();

int w = dim.width;

int h = dim.height;

area = new Rectangle(dim);

bi = (Bufferedimage)createimage(w, h);

big = bi.createGraphics();

http://tailieuhay.com 140

Page 141: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

rect.setLocation(w/2-50, h/2-25);

big.setStroke(new BasicStroke(8.0f));

firstTime = false;

}

// Clears the rectangle that was previously

drawn. big.setColor(Color.white);

big.clearRect(0, 0, area.width, area.height);

// Draws and fills the newly positioned

rectangle to the buffer.

big.setPaint(strokePolka);

big.draw(rect); big.setPaint(fillPolka);

big.fill(rect);

// Draws the buffered image to the screen.

g2.drawimage(bi, 0, 0, this);

}

5.3.3 Manipulating Bufferedimage Data Directly

Cùng với việc vẽ ảnh trực tiếp trong Bufferedimage, bạn có thể truy

cập trực tiếp và xử lý dữ liệu điểm ảnh trong 2 cách. Những cách này hữu

ích nếu vạn đang cài đặt giao diện bộ lọc BufferedimageOp như đã được

mô tả trong chương xử lý và cải thiện ảnh.

Bạn cũng có thể dùng phương thức Bufferedimage.setRGB để đặt

trực tiếp giá trị của một điểm hoặc một mảng các điểm tới một giá trị

RGB xác định. Chú ý rằng, không có sự lay động khi bạn modify các

http://tailieuhay.com 141

Page 142: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

điểm một cách trực tiếp. Bạn cũng có thể xử lý dữ liệu điểm ảnh bởi việc

xử lý một đối tượng WritableRaster liên kết với một Bufferedimage

5.3.4 Filtering a Bufferedimage

Bạn có thể ứng dụng một bộ lọc cho một Bufferedimage dùng một

đối tượng cài đặt BufferedimageOp. Việc lọc và các lớp cung cấp giao

diện lọc đã thảo luân trong phần Xử lý và cải thiện ảnh (image Processing

and Enhancement).

5.3.5 Rendering a Bufferedimage

Để render một bộ đệm ảnh vào trong một ngữ cảnh cụ thể, gọi hàm

drawiamge của ngữ cảnh của đối tượng Graphics. Ví dụ khi rendering

trong phương thức Component.paint, bạn gọi drawimage() trên đối

tượng đồ hoạ đã truyền cho phương thức.

public void paint(Graphics g) {

if (getSize().width <= 0 || getSize().height

<= 0)

return;

Graphics2D g2 = (Graphics2D) g;

if (offimg != null && isShowing()) {

g2.drawimage(offimg, 0, 0, this);

}

}

Chương trình ví dụ:

http://tailieuhay.com 142

Page 143: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

import java.awt.*;

import java.awt.event.*;

import java.applet.Applet;

import java.awt.image.*;

public class BufferedShapeMover extends Applet {

static protected Label label;

public void init() {

setLayout(new BorderLayout());

add(new BSMCanvas());

label = new Label("Đặt hình chữ nhật này

xung quanh vùng frame.");

add("South", label);

}

public static void main(String s[]) {

Frame f = new

Frame("BufferedShapeMover");

f.addWindowListener(new WindowAdapter() {

public void

windowClosing(WindowEvent e) {

System.exit(0);

}

});

Applet applet = new BufferedShapeMover();

f.add("Center", applet);

http://tailieuhay.com 143

Page 144: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

applet.init();

f.pack();

f.setSize(new Dimension(550, 250));

f.show();

}

}

class BSMCanvas extends Canvas implements

MouseListener, MouseMotionListener {

Rectangle rect = new Rectangle(0, 0, 100,

50);

Bufferedimage bi;

Graphics2D big;

int last_x, last_y;

boolean firstTime = true;

TexturePaint fillPolka, strokePolka;

Rectangle area;

boolean pressOut = false;

public BSMCanvas() {

http://tailieuhay.com 144

Page 145: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

setBackground(Color.white);

addMouseMotionListener(this);

addMouseListener(this);

bi = new Bufferedimage(5, 5,

Bufferedimage.TYPE_iNT_RGB);

big = bi.createGraphics();

big.setColor(Color.pink);

big.fillRect(0, 0, 7, 7);

big.setColor(Color.cyan);

big.fillOval(0, 0, 3, 3);

Rectangle r = new Rectangle(0, 0, 5, 5);

fillPolka = new TexturePaint(bi, r);

big.dispose();

bi = new Bufferedimage(5, 5,

Bufferedimage.TYPE_iNT_RGB);

big = bi.createGraphics();

big.setColor(Color.cyan);

big.fillRect(0, 0, 7, 7);

big.setColor(Color.pink);

big.fillOval(0, 0, 3, 3);

r = new Rectangle(0, 0, 5, 5);

strokePolka = new TexturePaint(bi, r);

big.dispose();

}

public void mousePressed(MouseEvent e) {

last_x = rect.x - e.getX();

http://tailieuhay.com 145

Page 146: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

last_y = rect.y - e.getY();

if (rect.contains(e.getX(), e.getY())) {

updateLocation(e);

} else {

BufferedShapeMover.label

.setText("Đầu tiên đặt con

trỏ lên hình chữ nhật và kéo.");

pressOut = true;

}

}

public void mouseDragged(MouseEvent e) {

if (!pressOut) {

updateLocation(e);

} else {

BufferedShapeMover.label

.setText("Đầu tiên đặt con

trỏ lên hình chữ nhật và kéo.");

}

}

public void mouseReleased(MouseEvent e) {

if (rect.contains(e.getX(), e.getY())) {

updateLocation(e);

} else {

BufferedShapeMover.label

http://tailieuhay.com 146

Page 147: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

.setText("Đầu tiên đặt con

trỏ lên hình chữ nhật và kéo.");

pressOut = false;

}

}

public void mouseMoved(MouseEvent e) {

}

public void mouseClicked(MouseEvent e) {

}

public void mouseExited(MouseEvent e) {

}

public void mouseEntered(MouseEvent e) {

}

public void updateLocation(MouseEvent e) {

rect.setLocation(last_x + e.getX(),

last_y + e.getY());

if (checkRect()) {

BufferedShapeMover.label.setText("Hình chữ

nhật ở vị trí : "

+ rect.getX() + "- " +

rect.getY());

} else {

http://tailieuhay.com 147

Page 148: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

BufferedShapeMover.label

.setText("Đừng cố gắng đưa

hình ra ngoài frame.");

}

repaint();

}

public void paint(Graphics g) {

update(g);

}

public void update(Graphics g) {

Graphics2D g2 = (Graphics2D) g;

if (firstTime) {

Dimension dim = getSize();

int w = dim.width;

int h = dim.height;

area = new Rectangle(dim);

bi = (Bufferedimage) createimage(w,

h);

big = bi.createGraphics();

rect.setLocation(w / 2 - 50, h / 2 -

25);

big.setStroke(new

BasicStroke(8.0f));

firstTime = false;

}

http://tailieuhay.com 148

Page 149: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

big.setColor(Color.white);

big.clearRect(0, 0, area.width,

area.height);

big.setPaint(strokePolka);

big.draw(rect);

big.setPaint(fillPolka);

big.fill(rect);

g2.drawimage(bi, 0, 0, this);

}

boolean checkRect() {

if (area == null) {

return false;

}

if (area.contains(rect.x, rect.y, 100,

50)) {

return true;

}

int new_x = rect.x;

int new_y = rect.y;

if ((rect.x + 100) > area.width) {

new_x = area.width - 99;

}

if (rect.x < 0) {

new_x = -1;

}

if ((rect.y + 50) > area.height) {

http://tailieuhay.com 149

Page 150: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

new_y = area.height - 49;

}

if (rect.y < 0) {

new_y = -1;

}

rect.setLocation(new_x, new_y);

return false;

}

}

5.4 Managing and Manipulating Rasters

Một đối tượng Bufferedimage dùng một Raster để quản lý mảng dữ

liệu điểm 2 chiều. Lớp Raster định nghĩa các trường cho toạ độ hệ thống

của ảnh- độ rộng , độ cao, và gốc toạ độ. Một đối tượng Raster tự nó dùng

2 đối tượng để quản lý dữ liệu điểm, một DataBuffer và một

SampleModel. DataBuffer là đối tượng lưu giữ dữ liệu điểm cho raster

cung cấp sự biểu diễn bên trong của dữ liệu điểm từ DataBuffer.

5.4.1 Creating a Raster

Trong hầu hết các trường hợp, không cần phải tạo một Raster trực

tiếp, bởi vì một Raster được cung cấp với bất cứ Bufferedimage bạn tạo

trong bộ nhớ. Tuy nhiên, một trong những hàm khởi tạo của

Bufferedimage cho phép tạo một Raster bởi truyền vào trong một

WritableRaster.

Lớp Raster cung cấp một số sản sinh (factory) hàm tĩnh cho tạo ra

các Raster với DataBuffers và SampleModels bạn xác định. Bạn cũng có

thể dùng các bộ sản sinh này khi cài đặt các lớp bộ lọc RasterOp.

http://tailieuhay.com 150

Page 151: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

5.4.2 Parent and Child Rasters

Lớp Raster kết hợp ý tưởng các raster cha và con. Điều này có thể cải

tiến hiệu quả lưu trữ bằng việc cho phép tạo bất kỳ số bộ đệm ảnh từ cùng

một cha. Cha và các con của nó tham chiếu tới cùng một bộ đệm dữ liệu,

và mỗi con có một (độ lệch) offset xách định và danh giới chỉ định tới vị

trí ảnh của nó trong bộ đệm. Một con xác định cha của nó qua bằng hàm

getParent().

Để tạo ra một Raster con (subraster), dùng phương thức

Raster.createSubRaster. Khi tạo một subraster, xác định vùng của cha

của nó mà nó chiếm và xác định offset của nó từ góc toạ độ của cha.

Operations on a Raster

Lớp Raster định nghĩa một số cách để truy cập trực tiếp các điểm và

dữ liệu điểm. Điều đó rất hữu ích khi khi bạn cài đặt giao diện RasterOp,

nó cung cấp bộ lọc cấp và xử lý dữ liệu của ảnh, hoặc khi cài đặt bất cứ

một phương thức nào mà cần thực hiện xử lý điểm ở mức thấp.

Các phương thức Raster.getPixel cho phép lấy về một điểm riêng

biệt, nó trả về như là một mẫu riêng biệt trong một mảng. Các phương

thức Raster.getDataElements trả về một phần tử thực thi cụ thể của diễn

dữ liệu ảnh không thể hiện từ DataBuffer. Phương thức

Raster.getSample() trả về mẫu của một điểm cụ thể. Phương thức

getSamples trả về một dải (band) cho một vùng cụ thể của một image.

Cùng với các phương thức đó, Cũng có thể truy cập dữ bộ đệm và

model mẫu qua các biến thể nghiệm (instance variables) của lớp Raster .

Các đối tượng này cung cấp thêm các cách truy cập và biểu diễn dữ liệu

điểm của Raster.

5.4.4 The WritableRaster Subclass

Lớp con WritableRaster cung cáp các phương thức để đặt dữ liệu

điểm và các mẫu. Raster liên kết với một Bufferedimage thực ra là một

http://tailieuhay.com 151

Page 152: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

WritableRaster vì cung cấp truy cập đầy đủ để xử lý dữ liệu điểm của

nó.

5.5 Image Data and DataBuffers

DataBuffer phụ thuộc vào một Raster biểu diễn một mảng các dữ

liệu ảnh. Khi bạn tạo một Raster trực tiếp hoặc qua các hàm tạo

Bufferedimage, bạn xác định độ rộng và chiều cao trong các pixel, cùng

với một SampleModel cho dữ liệu ảnh. Các thông tin đó cũng được dùng

để tạo một DataBuffer với dữ liệu và kiểu và kích thước phù hợp.

Có 3 lớp con của DataBuffer, mỗi lớp biểu diễn một loại khác nhau

của một phần tử dữ liệu:

• DataBufferByte (represents 8-bit values)

• DataBufferint (represents 32-bit values)

• DataBufferShort (represents 16-bit values)

• DataBufferUShort (represents unsigned short values)

Như đã định nghĩa từ trước, các phần tử là các thành phần rời rạc của

mảng dữ liệu bộ đệm, và các thành phần hoặc các mẫu là các giá trị rời

rạc kết hợp với nhau tạo nên một điểm. Có nhiều cách ánh xạ giữa kiểu

của phần tử trong một DataBuffer và kiểu của điểm được biểu diễn bởi

một SampleModel. Các lớp con SampleModel cũng có khả năng cài đặt

ánh xạ và cung cấp cách để lấy các điểm xác định từ một DataBuffer cụ

thể.

Các hàm tạo DataBuffer cung cấp các cách để tạo các bộ đệm với

một cỡ xác định và một số các bank xác định.

Bạn có thể truy cập dữ liệu của một ảnh trong DataBuffer một cách

trực tiếp, bạn cũng dễ dàng và thuận tiện làm điều đó hơn qua các phương

thức của các lớp Raster và WritableRaster.

http://tailieuhay.com 152

Page 153: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

5.6 Extracting Pixel Data from a SampleModel

Lớp trừu tượng SampleModel định nghĩa các phương thức cho

extracting các mẫu của một ảnh mà không cần biết cách dữ liệu được lưu

trữ ở bên dưới. Lớp cung cấp các trường cho việc ghi lại chiều cao và

chiều rộng cả dữ liệu ảnh trong DataBuffer liên kêt nó , và cho việc mô

tả số lượng các band và kiểu dữ liệu đệm. Các phương thức SampleModel

cung cấp dữ liệu ảnh như tập(collection) các điểm, với mỗi điểm bao gồm

có một số các mẫu hoặc các thành phần.

java.awt.image package cung cấp năm loại model mẫu:

• ComponentSampleModel— Được dùng để extract các điểm từ các

image chứa các mẫu dữ liệu trong các phần tử mảng dữ liệu riêng trong

một bank của một DataBuffer

• BandedSampleModel— Được dùng để extract các điểm từ các

image chứa mỗi mẫu trong một phần tử dữ liệu riêng với các band chứa

trong một dãy các phần tử dữ liệu.

• PixelinterleavedSampleModel— Được dùng để extract các điểm từ

các image chứa mỗi sample trong một phần tử riêng vói các điểm được

lưu trong một dãy tuân tự (sequence) của các phần tử dữ liệu.

• MultiPixelPackedSampleModel— Được dùng để extract các điểm

từ các iamge đơn band chứa nhiều mẫu một các điểm trong một phần tử

dữ liệu( used to extract pixels from single banded images that store

multiple one-sample pixels in one data element ).

• SinglePixelPackedSampleModel—used to extract samples from

images

that store sample data for a single pixel in one data array element in the

first

bank of a DataBuffer.

Dữ liệu điểm được biểu diễn bởi SampleModel có hoặc không thể

liên quan trực tiếp tới một dữ liệu màu biểu diễn một model màu cụ thể.

http://tailieuhay.com 153

Page 154: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

phụ thuộc vào dữ liệu nguồn. Ví dụ, trong dữ liệu ảnh đồ hoạ photo, các

mẫu có thể biểu diễn dữ liệu RGB. Trong dữ liệu ảnh từ một thiết bị ảnh y

tế, các mẫu có thể biểu diễn các loại dữ liệu khác nhau giông như nhiệt độ

hoặc mật độ xương.

Có ba category của các phương thức cho truy cập dữ liệu ảnh. Các

phương thức getPixel trả về cả một điểm trong một mảng, với mỗi đầu

vào cho mỗi mẫu. Các phương thức getDataElement cung cấp truy cập tới

dữ liệu thô, không thể hiện được chứa trong DataBuffer. Các phương

thức getSample cung cấp truy nhập tới các thành phần điểm cho một band

xác định.

5.7 ColorModels and Color Data

Cùng với Raster cho quản lý dữ liệu ảnh, lớp Bufferedimage bao

gồm một ColorModel cho biểu diễn dữ liệu như các giá trị điểm màu.

Lớp trừu tượng ColorModel định nghĩa các phương thức cho việc đặt các

điểm của image một giá trị màu trong ColorSpace liên kết với nó.

Gói java.awt.image cung cấp bốn loại model màu:

• PackedColorModel— Một ColorModel trừu tượng biểu diễn các

giá trị điểm có các thành phần màu được nhúng trực tiếp trong các bit của

một điểm nguyên. DirectColorModel là một lớp con (subclass) của

PackedColorModel.

• DirectColorModel—một ColorModel biểu diễn các giá trị điểm có

các thành phần màu RGB được nhúng trực tiếp trong các bit của điêm.

DirectColorModel model tương tự với một X11 TrueColor visual.

• ComponentColorModel—một ColorModel có thể handle một

ColorSpace thay đổi và một mảng các thành phần màu tương ứng với

ColorSpace.

• indexColorModel— Một ColorModel biểu diễn các giá trị màu vào

trong bản đồ màu trong không gian màu sRGB.

http://tailieuhay.com 154

Page 155: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Dựa trên dữ liệu trong DataBuffer, SampleModel cung cấp

ColorModel cho điểm, ColorModel sau đó biểu diễn như một màu.

5.7.1 Lookup Table

Một bảng tham chiếu (lookup table) chứa dữ liệu cho một hoặc nhiều

kênh hoặc các thành phần, ví dụ, các mảng riêng R, G và B. Goi

java.awt.image định nghĩa 2 kiểu bảng tham chiếu mở rộng lớp

LookupTable trừu tượng, một chứa byte dữ liệu và một chứa short data

(ByteLookupTable and ShortLookupData).

5.8 image Processing and Enhancement

Image package cung cấp một cặp giao diện định nghĩa các thao tác

trên Bufferedimage và Raster : BufferedimageOP và RasterOp.

Các lớp cài đặt những giao diện này bao gồm AffineTransformOp,

BandCombineOp, ColorConvertOp, ConvolveOp, LookupOp,

RescaleOp. Các lớp này có thể được dùng để biến đổi hình học, làm mờ,

làm sắc, thiện độ tương phản, ngưỡng, và làm đúng màu.( blur, sharpen,

enhance contrast, threshold, and color correct images).

Hình 5-4 minh hoạ phát hiện biên và cải thiện , một thao tác làm bóng

,thay đổi tăng cường độ trong một ảnh. Phát hiện biên thường được dùng

trong xử lý ảnh y tế và các ứng dụng bản đồ. Phát hiện biên được dùng

tăng độ tương phản giữa cấu trúc kề trong một ảnh, cho phép viewer để

phân biệt chi tiết hơn.

http://tailieuhay.com 155

Page 156: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Figure 5-4 Phát hiện biên và cải thiện ảnh

Đoạn code sau đây minh hoạ phát hiện biên:

float[] elements = { 0.0f, -1.0f, 0.0f,

-1.0f, 4.f, -1.0f,

0.0f, -1.0f, 0.0f};

...

Bufferedimage bimg = new

Bufferedimage(bw,bh,Bufferedimage.TYPE_iNT_RGB);

Kernel kernel = new Kernel(3, 3, elements);

ConvolveOp cop = new ConvolveOp(kernel,

ConvolveOp.EDGE_NO_OP, null);

cop.filter(bi,bimg);

Hình 5 -5 demo xử lý bảng tham chiếu. Xử lý bảng tham chiếu có thể

được dùng để thay cho các thành phần riêng lẻ của một điểm.

Hình 5-5 Xử lý Lookup-Table

Đoạn code sau demo thao tác Lookup-table:

http://tailieuhay.com 156

Page 157: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

byte reverse[] = new byte[256];

for (int j=0; j<200; j++){

reverse[j]=(byte)(256-j);

}

ByteLookupTable blut=new ByteLookupTable(0,

reverse);

LookupOp lop = new LookupOp(blut, null);

lop.filter(bi,bimg);

Hình 5-6 minh hoạ rescaling. Rescaling có thể tăng hoặc giảm cường

độ của tất cả các điểm. Rescaling có thể được dùng để tăng dải động của

các ảnh tự nhiên khác, đưa ra chi tiết trong các vùng tự nhiên hoặc

phẳng.

Hình 5-6 Rescaling

Đoạn Code dưới đây minh hoạ rescaling:

http://tailieuhay.com 157

Page 158: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

RescaleOp rop = new RescaleOp(1.5f, 1.0f,

null);

rop.filter(bi,bimg);

5.8.1 Using an image Processing Operation

Convolution là quá trình bên dưới hầu hết các thoật toán lọc không

gian. Convolution la quá trình đánh giá (weighting) hoặc làm đều

(averaging) giá trị của mỗi điểm trong một ảnh với các gía trị điểm lân

cận. Điều này cho phép mỗi điểm ra được đạt bởi lân cận trung gian

trong cách màd có thể được xác định với một nhân (kernel)

Hình 5 -7 minh hoạ Convolution

Đoạn mã sau minh hoạ cách dùng một trong các lớp xử lý hình ảnh,

lớp ConvolveOp. Trong ví dụ này, mỗi điểm tỏng ảnh nguồn được làm

cân bằng với 8 điểm xung quanh nó.

float weight = 1.0f/9.0f;

float[] elements = new float[9]; // create

2D array

// fill the array with nine equal elements

for (i = 0; i < 9; i++) {

elements[i] = weight;

}

http://tailieuhay.com 158

Page 159: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

// use the array of elements as argument

to create a Kernel

private Kernel myKernel = new Kernel(3, 3,

elements);

public ConvolveOp simpleBlur = new

ConvolveOp(myKernel);

// sourceimage and destimage are instances

of Bufferedimage

simpleBlur.filter(sourceimage, destimage) //

blur the image

Biến simpleBlur chứa một thể nghiệm mới của ConvolveOP cài đặt

toán tử blur trên một Bufferedimage hoặc một Raster. Giả định rằng

sourceimage và destimage là 2 thể nghiệm của Bufferedimage. Khi bạn

gọi filter, các phương thức chính của lớp ConvolveOp đặt giá trị của mỗi

điểm trong ảnh đích bởi việc bằng giá trị trung bình của 8 điểm xung

quanh điểm tương ứng với nó trong ảnh nguồn.

Nhân convolution trong ví dụ này có thể được biểu diễn bởi ma trận

dưới đây, với các phần tử đã xác định tới 4 phần:

Khi một ảnh được vonvolved, giá trị của mỗi điểm trong ảnh đích

được tính toán bới việc dùng một nhân như là một tập với trung bình của

các giá trị xung quanh mỗi điểm tương ứng trong ảnh nguồn. Việc xử lý

này được thực hiện dựa trên mỗi kênh của ảnh.

http://tailieuhay.com 159

Page 160: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Công thức sau biểu diễn cách các trọng số trong nhân được liên hệ với

các điểm trong ảnh nguồn khi thực hiện convolution. Mỗi giá trị tỏng

nhân được tied tới các vị trí trong hình ảnh.

Giá trị của điểm đích tỏng tổng các kết quả của trọng số trong nhân

được nhân với giá trị của các điểm nguồn tương ứng. Với nhiều bộ lọc

đơn giản, kernel là một ma trận vuông

Convolution kernel trong ví dụ này liên quan đơn giản. Nó đo

(weights) mỗi điểm từ hình ảnh nguồn bởi chọn một nhân đo (weights)

ảnh nguồn ở mức cao hơn hoặc thấp hơn, một chương trình có thể tăng

hoặc giảm cường độ của ảnh đích. Đối tượng Kernel, được đặt trong khởi

tạo của ConvolveOP , xác định kiểu bộ lọc nó thực thi. Bởi việc đặt các

gía trị khác, bạn có thể thực hiện các kiểu convolution khác nhau bao gồm

blurring (như Gaussian blur, radial blur, và motion blur), sharpening, và

smoothing

Hình 5-8 minh hoạ sharpening dùng Convolution.

Hình 5-8 Sharpening with Convolution

Đoạn code dưới đây minh hoạ sharpening với

float[] elements = { 0.0f, -1.0f, 0.0f,

http://tailieuhay.com 160

Page 161: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

-1.0f, 5.f, -1.0f,

0.0f, -1.0f, 0.0f };

...

Kernel kernel = new Kernel(3,3,elements);

ConvolveOp cop = new ConvolveOp(kernel,

ConvolveOp.EDGE_NO_OP,

null);

cop.filter(bi,bimg);

http://tailieuhay.com 161

Page 162: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Chương 6

Mầu sắc

Vẽ ảnh màu là một trong những thành phần nền tảng của các hệ thống

đồ họa và nó luôn là nguồn gốc của sự phức tạp trong những ô hình tạo

ảnh.Thư viện Java 2D™ API cung cấp

Sự hỗ trợ cho sự tạo ảnh màu chất lượng cao nhưng lại dễ dàng sử dụng

Các lớp quản lý màu trong Java 2D API gôm CorlorSpace, Color.

Một ColorSpace biểu diễn cho một hệ thông cho việc định lượng

màu, Tiêu biểu như biểu diễn bằng 3 giá trị số(RGB) họăc các thành

phần.. Lớp ColorSoace chứa các phương thức cho chuyển đổi các không

gian màu và hai không gian màu chuẩn là CiEYZ và GRB.

Một Color là một màu cố định đa được xác định trong định nghĩa

của các thành phần của nó trong một ColorSpace cụ thể. Để vẽ một

Shape với một màu. chẳng hạn màu đỏ. bạn phải truyền mọt đối tượngc

Color bỉêu diễn màu với ngữ cảnh đồ hoạ 2D. Color được đinh nghĩa

trong java.awt.ColorModel miêu tả một cách cụ thể những điểm được

ánh xạ tới các màu.

ColorModel đựoc hệ tiêu biểu với một image hoặc một Bộ đệm hình

ảnh(Bufferimage) và cung cấp thông tin cần thiêt thíc hợp để biểu diễn

các gía trị đỉêm. ColorModel được định nghĩa trong java.awt.image

http://tailieuhay.com 162

Page 163: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

6.1 Các lớp

Clases DescriptionColorSpace Identifies the color space of a Color object,

Image, BufferedImage, or GraphicsDevice.

Has methods to transform between RGB and

CIEXYZ color spaces.ICC_ColorSpace Extends: ColorSpace

Represents device-independent and device-

dependent color spaces based on the ICC

Profile Format Specification.ICC_Profile A representation of color profile data for

device independent and device dependent

color spaces based on the ICC Profile

Format Specification. ICC_ProfileGray Extends: ICC_Profile

A representation of color space type gray.ICC_ProfileRGB Extends: ICC_Profile

A representation of color space type RGB.

6.2 Những định nghĩa về mầu sắc.

Một ColorModel được sử dụng để biểu diễn một dữ liệu diểm trong

ảnh. Điều này bao gồm cả ánh xạ các thành phần trong những dải(bands)

của một ảnh tới các thành phần của một không gian màu cụ thể. Nó có thể

cũng bao hàm cả xuất các thành phần điểm từ một dữ liệu diểm dóng gói

hay nhận về nhiều thành phần từ một dải đơn bằng sử dụng các mặt nạ. và

chuyển dữ liệu điểm qua một bảng tham chiếu(lookup table)

Để xác định được giá trị màu của một điểm cụ thể trong ảnh bạn phải

biết các mã hoá thông tin cho mỗi điểm. ColorModel liên hệ với một ảnh

sẽ đóng gói dữ liệu và các phương thức cần thiết cho việc chuyển đổi giá

trị điểm tới và từ các đơn vị thành phần màu.

http://tailieuhay.com 163

Page 164: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Java 2D™ API cung cấp 2 color model va thêm vào DirectColor –

Model và indexColorModel được định nghĩa trong JDK 1.1 release.:

ComponentColorModel co thể giữ một ColorSpace không hạn

chế và một mảng thành phần màu ứng với ColorSpace. Model này có thể

sử dụng để biểu diễn hầu hết các model màu trến hầu hết các loại Thiết bị

đồ hoạ(GrphicsDevices ).

PackedColorModel là lớp cơ sở cho các model biểu diễn giá trị

điểm bao gồm các thành phần màu nhúng trực tiếp trong các bit của một

điểm nguyên.

PackedColorModel chứa cac thông tin gói mô tả cách các thành phần

màu và alpha được xuất ra từ một kênh. ĐirectColorModel trong JDK 1.1

release la một PackedColorModel.

6.2.1 Không gian mầu

Đối tượng ColorSpace biểu diễn một hệ thống cho việc định lượng

các màu, tiêu biểu như việc sử dụng 3 giá trị số riêng biệt.Ví dụ RGB,

CMYK là các không gian màu.(ColorSpace).

Một đối tượng ColorSpace dùng như là thẻ một colorspace xác định

không gian màu cụ thể của đối tưọng màu hoặc qua một đối tượng

ColorModel , của một imae , một Bufferedimage, hoặc một

GraphicsConfiguration. ColorSpace cung cấp các phương thức chuyển

đổi các màu trong không gian xác định tới và từ RGB và tới và từ không

gian CiEXYZ.

Tất cả đối tượng ColorSpace phải có thể ánh xạ một màu từ không

gian biểu diễn sang sRGB và chuyển đổi một màu sRGB sang không gian

biểu diễn màu đó. Vì mỗi Color chứa một đối tượng ColorSpace đặt

tường minh hoặc mặc định. mỗi Color cũng có thể chuyển từ sRGB, Mỗi

GraphicsConfiguration dược liên hệ với một đối tượng ColorSpace khi

có được liên hệ với ColorSpace. Một màu được xác định trong bất cứ

http://tailieuhay.com 164

Page 165: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

không gian màu nào cung có thể hiển thị được bởi bất cứ thiết bị nào bởi

việc ánh xạ nó tới sRGB như một không gian màu trung gian.

Các phương thức được dùng cho quá trình này là toRGB() và

fromRGB(), toRGB chuyển một Color trong không gian màu tới một màu

trong sRGB fromRGB nhận một màu trong sRGB và chuyển nó sang

không gian mầu

Mặc dù việc ánh xạ qua sRGB luôn thực hiện nhưng nó không luôn

luôn la pháp tốt nhất.

Ví dụ. sRGB không thể biểu diễn mọi màu trong cả giải màu CiEXYZ.

Nếu một màu đựơc xác định trong một vài không gian có giải phổ

màu khác nhau hơn sRGB

Thì việc sử dụng sRGB như là một không gian trung gian và ở đó bị mất

thông tin. để giải quyết vấn đề này, lớp ColorSpace có thể ánh xạ các

màu tới và từ không gian màu khác , như CiEXYZX

Các phương thức toCiEXYZ và fromCiEXYZ ánh xạ giá trị màu từ

không gian màu tới không gian khác (CiEXYZ). Các phương thức này bổ

trợ chuyển đổi giữa hai không gian màu bất kỳ với mật độ và cấp độ cao,

với một Color một lúc.Tuy nhiên cũng hi vọng rằng cài đặt Java 2D API

se bổ trợ cho chuyển đổi với hiệu năng cao dựa trên hệ thông quản lý

màu, thao tác trên toàn ảnh.( Xem ColorConvertOp trong imaging trang

67)

Hình 6-1 và 6-2 minh hoạ quá trình translating một màu được xác

định trong không gian màu CMYK để hiển thị trên màn hình RGB. Hình

6-1 biểu diễn mapping qua sRGB. Như hình minh hoạ, sự chuyển đổi của

màu CMYK sang màu RGB không chính xác bởi sự không tương ứng

hoàn toàn.

Tất nhiên, những màu được sử dụng trong các này mang tính chất

biểu đồ minh hoạ và không chính xác. Những điêm màu sẽ không được

http://tailieuhay.com 165

Page 166: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

ánh xạ đúng giữa các không gian màu trừ khi có một sự chuyển đổi không

gian phù hợp được sử dụng.

Hình 6-2 biểu diễn cùng quá trình sử dụng CiEXYZ như là không

gian màu chuyển đổi. Khi CiEXYZ được sử dụng, màu được chuyển qua

một cách đứng đắn.

ColorSpace la thực ra là một lớp trừu tượng. Java 2D API cung cấp

sự cài đặt iCC_Profile lớp dựa trên dữ liệu iCC Profile như được biểu

diễn bởi lớp iCC_Profile. Bạn có thể định nghĩa lớp con của bạn để biểu

diễn các không gian màu chuyển đổi miễn là các phương thức được thảo

luận trên được cài đặt. Tuy nhiên hầu hết các developers có thể sử dụng

một cách đơn giản lớp ColorSpace mặc định hoặc các không gian màu

được biểu diễn bởi các iCC Profiles thông thường, giống như các thông

tin cho màn hình và máy in, hoặc thông tin được nhứng trong dữ liệu ảnh.

ColorSpace trong trang 90 miêu tả cách đối tượng ColorSpace biểu

diễn một không gian màu và biểu diễn các màu trong không gian màu có

thể ánh xạ tới và từ một không gian chuyển đổi. Các hệ thống quản lý

màu thường được sử dụng để giữ ánh xạ giữa các không gian màu. Tiêu

http://tailieuhay.com 166

Page 167: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

biểu như hệ thông quản lý màu (CMS) quản lý các thông tin iCC (iCC

profiles) nó giông như đối tượng ColorSpace; iCC profiles mô tả một

không gian vào và không gian kết nối, và định nghĩa cách ánh xạ giữ

chúng. Hệ thống quản lý màu rất tốt ở việc chỉ ra cách ánh xạ một màu

được gắn với một profile vào trong không gian màu của một profile khác.

Java 2D API định nghĩa một lớp gọi là iCC_Profile giữ dữ liệu cho

một bộ chuyển đổi iCC profile. iCC_ColorSpace là một sự cài đặt của lớp

trừu tượng ColorSpace. Các đối tượng iCC_ColorSpace có thể được khởi

tạo từ các iCC_Profile.(Có một số giới hạn – không phải tất cả các iCC

Profile là thích hợp cho việc định nghĩa một

iCC_ColorSpace)iCC_Profile có vài lớp con tương ứng với các loại

không gian màu như iCC_ProfileRGB và iCC_ProfileGray. Mỗi lớp con

của nó có một không gian vào được định nghĩa thích hợp(giông như

không gian RGB) và không gian kết nối thích hợp (không gian CiEXYZ).

Java 2D API có thể sử dụng hệ thông nền CMS (platform’s CMS ) để truy

nhập các thông tin màu co nhiều loại thiết bị đa dạng giông như

scanner ,máy in, màn hình. Cũng có thể sử dụng CMS để tìm sự ánh xạ

tốt nhất giữa các profiles

6.2.1 Biểu diễn màu

Lớp Color cung cấp sự mô tả màu trong không gian màu cụ thể. một

thể nghiệm của Color chứa giá trị các thành phần màu và một đối tượng

ColorSpace. Bởi một đối tượng ColorSpace có thể được xác định thêm

vào các thành phần màu khi một thể nghiệm mới của mà được tạo ra nên

lớp Color có thể giữ các màu trong bất cứ không gian màu nào.

Lớp Color có một số phương thức bổ trợ cho không gian màu chuẩn

RGB được gọi là sRGB(tham khảo http:// www. W3.

org/pub/www/Graphics/color/sRGB.html). sRGB la không gian màu mặc

định cho Java 2D API. Vai hàm khởi tạo được định nghĩa bởi lớp Color

http://tailieuhay.com 167

Page 168: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

cho phép bỏ qua tham số ColorSpace. Các khởi tạo này mặc định rằng

giá trị màu RGB được định nghĩa trong sRGB, và sử dụng thể nghiệm

mặc định của ColorSpace để biểu diễn cho không gian đó.

Java 2D API dùng sRGB tạo thuận lơi cho các lập trình viên lập trình

ứng dụng, không phải là tham chiếu không gian màu cho sự chuyển đổi

màu. Nhiều ứng dụng chủ yếu tập trung vào anh RGB và màn hình và việc

định nghĩa không gian màu RGB lam cho việc viết chúng dễ dàng hơn.

Lóp ColorSpace định nghĩa các phương thức toRGB và frỏmGB làm cho

các developers có thể nhận các màu một cách đễ dàng trong không gian

chuẩn này. Các phương thức này không mong đợi sử dụng cho màu với độ

chính xác cao hay việc chuyển đổi. (xem ColorSpace trang 90 )

Để tạo ra một màu (color) trong một không gian màu không phải là sRGB,

ban dùng hàm tạo Color với đối tượng ColorSpace và một mảng so thực

biểu diễn các thành phần màu tương ứng với không gian đó. Đối tượng

ColorSpace xác định không gian màu.

Để hiển thị một hình chữ nhật đúng màu giống như màu cyan, bạn

cần một cách để mô tả màu này cho hệ thống. Có một số cách khác nhau

để mô tả một màu, ví dụ một màu có thể được mô tả bằng một tập hợp

các thành phần (RGB) đỏ(red), xanh lá cây(green), xanh da trời(blue) hay

tập hợp các thành phần(CMYK) Cyan, Magenta, Yellow, Black . Các kỹ

thuật khác nhau này cho việc xác định màu được gọi là các không gian

màu (color spaces).

Như bạn biết, các màu trên một màn hình máy tình được tạo bởi sự pha

trộn lượng khác nhau của ba thành phần đỏ (Red), xanh lá cây (Green), xanh

da trời (Blue). Vì thế nên dùng không gian màu RGB làm chuẩn cho vẽ ảnh

trên man hình máy tính. Tương tự, quá trình in 4 màu dùng cyan, magenta,

yellow, black để tạo ra màu trên trang giây in ,các màu in được xác định

bằng tỉ lệ phần trăm trong không gian màu CMYK.

http://tailieuhay.com 168

Page 169: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Để thích hợp vơi sự phổ biến của cả màn hình và máy in màu, cả hai

không gian màu RGB và CMYK được dùng để biểu diễn màu. Tuy nhiên,

cả 2 loại không gian màu có một hạn chế là phụ thuộc thiết bị. mực cẩm

thạch(cyan) được sử dụng bởi một máy in có thể không tương ứng với

mực cyan của một máy in khác. Tương tự, một màu biểu diễn bằng một

màu RGB có thể trông giông màu xanh da trời (blue) trên một màn hình

và màu đỏ tía (purplish) trên một màn hình khác .

Mapping Colors qua sRGB và CiEXYZ

Java 2D API dùng RGB và CMYK la 2 loại không gian màu. Một

model màn hình phôt pho cụ thể xác định một không gian màu RGB của

nó. Tương tự, môt model máy in cũng có không gian CMYK của nó.

Không gian khác nhau , Không gian RGB hoặc không gian CMYK có thể

liên hệ với nhau qua không màu gian độc lập thiết bị

Các chuẩn cho việc xác đinh màu độc lập thiết bị đã được định nghĩa

bởi international Commission on illumination (CiE). Không gian màu độc

lập thiết bị thường đựơc dùng nhất là không gian 3 thành phần màu

(three-component XYZ ) được phát triển bởi CiE. Khi bạn xác định một

màu dùng CiEXYZ, bạn được cách ly với độc lập thiết bị.

Thật không may mắn, không phải lúc nào cũng dùng không gian màu

CiEXYZ, có một số lý do cho việc biểu diễn màu trong các không gian

màu khác. Để đạt được kết quả ổn định khi một màu đựơc biểu diễn dung

không gian phụ thuộc thiết bị như không gian RGB, cần biểu diễn chác

không gian RGB liên hệ vớ không gian độc lập thiết bị giống như

CiEXYZ.

Một cách để ánh xạ giữa các không gian màu là thêm thông tin vào

cách không gian phụ thuộc thiết bị liên hệ với không gian độc lập thiết bị.

Những thông tin thêm này được gọi là profile. Color profile thường sử

dụng là iCC Color Profile, được định nghĩa bởi international Color

http://tailieuhay.com 169

Page 170: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Consortium. Chi tiết xem iCC Color Format Specification, phiên bản 3.4

trên trang http:// www.color. Org.

Hình 6-3 minh hoạ một màu đơn (Solid color) và một ảnh quét được

truyền cho Java 2D API và cách chúng hiển thị bởi các thiết bị ra đa dạng.

Như bạn thấy trong 6-3 cả màu vào và ảnh có các profile được gắn vào.

Khi API có một màu xác định một cách chính xác, nó phải tạo lại màu

trên thiết bị ra, như màn hình và máy in. Các thiết bị này có các đặc tính

tạo ảnh của nó đảm bảo rằng kết quả tạo ra là chính xác. Một profile được

liên kết với mỗi thiết bị ra để mô tả cách các màu cần được chuyển đổi để

tạo ra kết quả chính xác.

Việc đạt được màu ổn định và chính xác yêu cầu cả màu vào và thiết

bị ra đưa thêm thông tin trở lại cho không gian màu chuẩn. Ví dụ, một

màu vào có thể ánh xạ từ không gian màu gốc của nó sang không gian

màu độc lập thiết bị chuẩn, và sau đó từ không gian đó sang không gian

màu thiết bị ra. Trong nhiều khía cạnh, sự chuyển đổi màu bắt chước sự

chuyển đổi của đối tượng đồ hoạ trong không gian toạ độ x, y. Cả 2

trường hợp, sự chuyển đổi được dùng để xác định toạ độ trong không gian

http://tailieuhay.com 170

Page 171: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

chuẩn và sau đó ánh xạ toạ độ đó sang không gian thiết bị xác định cho

đầu ra.

Chương 7

In ấn

Java Printing API cho phép ứng dụng cho:

1. In với AWT và đồ hoạ Java 2D™ , bao gồm đồ hoạ đa hợp

(composited graphics) và hình ảnh.

2. Các hàm điều khiển các hàm tài liệu đa hợp như so sánh mềm,

thứ tự in, và booklet printing.

3. Các hàm in xác định trợ giúp như in duplex (duplex printing)

và stapling.

4. In với tất cả các platform, cả Windows và Solaris. Điều này bao

gồm máy in đã được gắn trực tiếp với máy tính cũng như với

platform software cho phép truy cập sử dụng các giao thức in

qua mạng.

Không phải tất cả các tính năng đó được bổ trợ và được cài đặt trong

in ấn với Java™ 2 SDK API. Nhưng API sẽ được mở rộng để bộ trợ cho

tất cả các thuộc tính này ở các bản release trong tương lai.

7.1 Các giao diện và các lớp

http://tailieuhay.com 171

Page 172: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Interface DescriptionPrintable The Printable interface is implemented by each page

painter, the application class(es) called by the

printing system to render a page. The system calls the

page painter’s print method to request that a page be

rendered.Pageable The Pageable interface is implemented by a

document that is to be printed by the printing system.

Through the Pageable methods, the system can

determine the number of pages in the document, the

format to use for each page, and the page painter to

use to render each page.PrinterGraphics The Graphics2D objects that a page painter uses to

render a page implement the PrinterGraphics

interface. This enables an application to get the

PrinterJob object that is controlling the printing.Printable The Printable interface is implemented by each page

painter, the application class(es) called by the

printing system to render a page. The system calls the

page painter’s print method to request that a page be

rendered.

Class DescriptionBook Implements: Pageable

Represents a document in which pages can have

different page

formats and page painters. This class uses the

Pageable

interface to interact with a PrinterJob.PageFormat Describes the size and orientation of a page to be

http://tailieuhay.com 172

Page 173: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

printed, as

well as the Paper used to print it. For example,

portrait

and landscape paper orientations are rep- resented by

PageFormat.Paper Describes the physical characteristics of a piece of

paper.PrinterJob The principal class that controls printing. The

application calls PrinterJob methods to set up a job,

display a print dialog to the user (optional), and to

print the pages in the job.

Các định nghĩa về in

Java Printing API dựa trên mô hình in callback trong đó hệ thông in,

không phải úng dụng sẽ điều khiển khi các trang được in. Ứng dụng cung

cấp thông tin về tài liệu được in và hệ thống in sẽ yêu cầu ứng dụng đẩy

tới các trang in khi nó cần chúng.

Hệ thống in có thể yêu cầu rằng một trang in riêng biệt được đưa ra

hơn một lần hoặc yêu cầu các trang được đưa ra ngoài theo thứ tự. Ứng

dụng phải cho phép tạo ra hình ảnh đúng của trang, không phụ thuộc

trang nào hệ thống in yêu cầu. Trong khía cạnh đó, hệ thống in giông như

window toolkit, có thể yêu cầu các thành phần để vẽ lại bât cư lúc nào

trong thứ tự nào.

Mô hình in callback mềm dẻo hơn các mô hình ứng dụng điều khiển in

truyền thống và bổ trợ cho việc in trên dải rộng hơn các hệ thống và các

máy in.

http://tailieuhay.com 173

Page 174: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Ví dụ, nếu một máy in thực hiện đưa ra các trang trong thứ tự đảo ngược,

hệ thống in có thể yêu cầu ứng dụng tạo các trang trong thứ tự đảo ngược

sao cho tác vụ cuối cùng là đúng thứ tự đọc .

Mô hình này cũng cho phép ứng dụng để in ra các máy in ảnh nhị

phân từ máy tính mà không có đủ bộ nhớ hày không gian đĩa để đệm cho

toàn trang bitmap. Trong tình huống này, một trang được in như là một

dãy cá bitmap nhỏ hay các dải (bands). Ví dụ, nều bộ nhớ chỉ đủ đệm cho

1/10 trang in, thi trang sẽ được chỉ thành 10 dải. Hệ thống in đòi hỏi ứng

dụng đẩy mỗi trang 10 lần, mỗi lần điền vào mỗi dải. Ứng dụng không

cần biết số lượng hay cỡ của các dải, nó chỉ đơn giản khả đẩy mỗi trang

khi được yêu cầu.

7.2.1 Supporting Printing

Một ứng dụng phải thực hiện 2 tác vu để bổ trợ cho việc in là:

1. Điều khiển in(Job control)- Khởi tạo và quản lý việc in.

2. In (imaging) – Đẩy (rendering) dữ liệu ra mỗi trang khi hệ thống in

yêu cầu nó

7.2.1.1 Điều khiển in (Job Control)

Người sử dụng thường khởi tạo việc in bởi việc kích một nút hoặc

chọn mục in trên menu trong một ứng dụng. Khi một thao tác in được

kích hoạt bởi người sử dụng, ứng dụng tạo ra một đối tượng PrinterJob

và dùng nó để quản lý quá trình in.

Ứng dụng có khả năng đáp ứng cho việc cài đặt điều khiển in, hiển thị

các hộp thoại cho người sử dụng, và bắt đầu quá trình in.

imaging

Khi một tài liệu được in, ứng dụng phải đẩy dữ liệu mỗi trang khi hệ

thống in yêu cầu nó. Để bổ trợ cho kỹ thuật này, ứng dụng cung cấp một

http://tailieuhay.com 174

Page 175: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

page painter cài đặt giao diện Printable. Khi hệ thống in cần một trang

được đây ra, nó gọi phương thức in của page painter.

Khi một phương thức của page painter được gọi, nó được truyền cho

một ngữ cảnh đồ hoạ (Graphics context) dùng để đẩy hình anh trang. Nó

cũng được truyền cho một đối tượng PageFormat xác định (specifies)

hình hiện ra của trang, và chỉ số xác định thứ tự vị trí của trang trong việc

in.

Hệ thống in hỗ trợ cả việc đẩy Graphics và Graphics2D, để in Java

2D™ Shapes ,Text và images, bạn đưa một đối tượng Graphics cho

phương thức in cho raphics2D

Để in các tài liệu trong đó các trang dùng các page painter khác nhau

và có các định dạng khác nhau, bạn dùng một pageablejob. Để tạo một

pageable job, bạn có thể dùng lớp Book hoặc cài đặt giao diện Pageable

của bạn.

Để cài đặt các thao tác in đơn giản, bạn không cần dùng một pageable

print job, Print- able có thể được dùng miễn là tất cả các trang chia sẻ cùn

một định dạng và một máy in

7.2.2 Page Painters

Việc chủ yếu của một page painter là đẩy ra một trang dùng ngữ cảnh

đồ hoạ được cung cấp bởi hệ thống in. Một page painter cài đặt phưong

thức Printable.print:

public int print(Graphics g, PageFormat pf,

int pageindex)

Ngữ cảnh đồ hoạ được truyền cho phương thức in là một thể nghiệm

của Graphics hoặc Graphics2D, phụ thuộc vào các package được load

trong Java Vỉtual Machine của bạn. Để dùng các tính năng Graphics2D ,

http://tailieuhay.com 175

Page 176: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

bạn có thể thay đối tượng Graphics bằng Graphics2D. Thể nghiệm

Graphics được truyền để in cũng cài đặt giao diện PrinterGraphics.

PageFormat được truyền cho một Printable mô tả hình ảnh của một

trang được in. Hệ tọa độ của ngữ cảnh đồ hoạ được truyền để in được

fixed với trang : gốc toạ độ của hệ thống là góc trái trên của trang, X tăng

theo chiều phải sang trái, Y theo chiều từ trên xưống dưới, với đơn vì là

1/72 inch.

Nếu trang trong hướng portrait, trục x căn theo chiều rộng của trang giấy,

và trục y theo chiều cao của trang. (Thông thường, nhưng không phải

luôn luôn, chiều cao của trang dài hơn với chiều rộng của nó). Nếu trang

theo hướng landscape, thì ngược lại: trục x căn theo chiều cao của trang

còn trục y căn theo chiều rộng của nó.

Bởi nhiều máy in không thể trên cả bề mặt trang, PageFormat xác

định (specifies) vùng in (imageable area) của trang: phần của trang mà nó

đẩy ra an toàn. Sự xác định của vùng in không thay đổi theo toạ độ hệ

thống, nó được cung cấp sao cho nội dung của trang có thể được đẩy ra

sao cho chúng không thể mở rông vào trong vung mà máy in không thể

in.

Ngữ cảnh đồ hoạ được truyền để in có một miền xén mô tả phần miền

có thể in mà cần được in. Nó cũng luôn an toàn để in toàn bộ trang vào

trong ngữ cảnh đó, hệ thống in sẽ nắm dữ vùng xén cần thiết.

Tuy nhiên, để loại overhead của các phần vẽ của trang không được in,

bạn có thể dùng miền cắt xén để giới hạn vùng đẩy ra. Để lấy vùng cắt

xén từ ngữ cảnh đồ hoạ, gọi hàm Graphics.getClip. Vùng cắt xén rất

mạnh mẽ để giảm bớt rendering overhead.

Đôi khi mong muốn cả thao tác in thực hiện ngầm để cho người dùng

có thể tiếp tục tao tác vói úng dụng trong khi các trang đang được đẩy ra

(đang in). Để làm điều này, gọi hàm PrinterJob.print trong một tuyến

riêng.

http://tailieuhay.com 176

Page 177: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Nếu có thể, bạn nên tránh các thao tác đồ hoạ mà yêu cầu thông tin về

nội dung của image trước đó, giống như copyArea, setXOR, và sự liên

hợp (compositing).

Các thao tác này có thể đẩy ra chậm và các kết quả có thể không ổn

định.

7.2.3 Printable Jobs and Pageable Jobs

Một Printable job cung cấp cách đơn giản nhất để in. Chỉ một page

painter được dùng , ứng dụng cung cấp một lớp đơn cài đặt giao diện

Printable. Khi in, hệ thống goi phương thức in của page painter để đẩy ra

mỗi trang. Các trang được yêu cầu theo thứ tự, bắt đầu với trang có chỉ số

là 0. Tuy nhiên, page painter có thể được yêu cầu để đẩy mỗi trang vài lần

trước khi nó sang trang tiếp. Khi trang cuối cùng được in, phương thức in

của page painter trả về NO_SUCH_PAGE.

Trong một Printable job:

1. Tất cả các trang dùng cung một page painter và PageFormat. Nếu

một hộp thoại in được hiển thị, nó cũng sẽ không hiển thị số trang

trong tài liệu vì thông tin đó không có với hệ thống in.

2. Hệ thống in luôn đòi hỏi page painter để in mỗi trang đúng thứ tự,

bắt đầu với trang có chỉ số là 0. Không trang nào bị quên. Ví dụ,

nếu người dùng yêu cầu in trang 2 và trang 3 của một tài liệu, thì

page painter sẽ được gọi với các chỉ số 0, 1, 2. Hệ thống in có thể

yêu cầu một trang được đẩy ra nhiều lần trước khi chuyển sang

trang kế.

3. Page painter báo cho hệ thống in khi nó đã đến cuối tài liệu.

4. Tất cả các page painter được gọi trong cùng một tuyến.

5. Đôi khi hệ thống in có thể không có khả năng biết được mục đích

đưa ra. Ví dụ, tác vụ của các trang hiện ra từ máy in có thể là thứ tự

http://tailieuhay.com 177

Page 178: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

sai, hoặc các trang có thể không được kiểm tra thứ tự nếu nhiều bản

sao được yêu cầu.

6. Một Pageable job linh hoạt hơn một Printable job. Không giống

như các trang trong Printable job, các trang trong Pageable job có

thể khác về cách bố trí và cài đặt.

Để quản lý một Pageable job, bạn có thể dùng lớp Book hay cài đặt

lớp Pageable của bạn. Qua Pageable, hệ thống in có thể xác định số

lượng trang để in, và page painter dùng cho mỗi trang, và PageFormat

cho mỗi trang. Các ứng dụng cần in các tài liệu có một cấu trúc đã định và

định dạng nên dùng các Pageable job.

Trong một Pageable job:

Các trang khác nhau có thể dùng các page painter và các

PageFormat khác nhau.

Hệ thống in có thể đòi hỏi các page painter để in các trang trong

một thứ tự tuỳ ý và một trang có thể được bỏ qua. Ví dụ, Nếu người dùng

yêu cầu in các trang 2 và 3 của một tài liệu, thì page painter se được gọi

với chỉ số 1 và 2 còn trang chỉ số 0 sẽ được bỏ qua.

Pageable job không cần biết có bao nhiêu trang tiếp theo trong tài

liệu. Tuy nhiên, không giống với Printable job, chúng phải có khả năng

đẩy ra các trang trong bất kỳ thứ tự. Có thể có các chỗ trống trong thứ tự

và hệ thống in có thể yêu cầu một trang được đẩy ra nhiều lần trước khi

chuyển sang trang tiếp theo. Ví dụ, yêu cầu để in trang 2 và 3 của một tài

liệu có thể kết quả trong dãy lời gọi là các trang yêu cầu với chỉ số 2, 2, 1,

1 và 1.

7.2.4 Typical Life-Cycle of a PrinterJob

Một ứng dụng hướng theo đối tượng PrinterJob qua một dãy các

bước để hoàn thành công việc in. Thứ tự đơn giản nhất được dùng bởi

ứng dụng là:

http://tailieuhay.com 178

Page 179: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Lấy một đối tượng PrinterJob mới bởi việc gọi

PrinterJob.getPrintJob

Xác định PageFormat để dùng cho việc in. Một PageFormat mặc

định có thể lấy về bởi gọi hàm defaultPage. hoặc bạn có thể gọi

một hộp thoại cho phép người dùng xác định định dạng .

Xác định các đặc điểm của công việc để in cho PrinterJob. Cho

một Printable job, gọi setPrintable; với Pageable job, gọi

setPageable. Chú ý một đối tượng Book là một mẫu truyền cho

setPageable.

Xác định các thuộc tính thêm cho việc in, giống như số bản sao để

in hay tên của công việc trên đầu đề trang.

Gọi hàm printDialog để hiển thị hộp thoại cho người dùng. Điều này

là tuỳ chọn. Những nội dung và hình dạng của hộp thoại có thể đa

dạng với các platform và các máy in khác nhau. Trên hầu hết các

platform, người dùng có thể dùng hộp thoại này để thay đổi các lựa

chọn của máy in. Nếu người dùng huỷ việc in, phương thức

printDialog trả về FALSE.

Gọi Printerjob.print để in. Phương thức này khi trả về gọi print

trên các page painter tương ứng.

Một công việc có thể bị ngắt quá trình in nếu:

Một PrinterException được đưa vào ngoại lệ được bắt boẻi

phương thức in và công việc sẽ bị dừng. Một page painter đưa ra

một PrinterException nếu nó phát hiện một trầm trọng lỗi (fatal

error).

PrinterJob.cancel được gọi. vòng lặp in sẽ bị chấm dứt và công

việc bị huỷ bỏ. Phương thức cancel có thể được gọi từ một tuyến

riêng biệt cái hiển thị một hộp thoại và cho phép người dùng hủy

bỏ việc in bởi bấm vào một nút trên hộp thoại đó.

http://tailieuhay.com 179

Page 180: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Các trang phân ra trước khi một công việc in bị dừng có thể là không

được in hoặc được in. Việc in thường không kêt thúc (finished) khi

phương thức in tra về. Việc này thường vẫn đang được thực hiện bởi trình

điều khiến máy in.

Trạng thái của đối tượng PrinterJob có thể không phản ánh trạng thái

thực tế của công việc đang được in.

Do trạng thái của một PrinterJob thay đổi trong quá trình vòng đời

của nó. Không hợp lý yêu cầu các phương thức vào nhiều lúc. Ví dụ, việc

gọi setPageable sau khi bạn đã gọi hàm print là không hợp lý. Khi có các

lời gọi không hợp lý được phát hiện PrinterJob sẽ đưa vào một ngoại lệ

java.lang.illegalStatException.

Dialogs

Java Printing API yêu cầu các ứng dụng cần đến hộp thoại giao tiếp

với người dùng một cách tường minh. Các hộp thoại này có thể được

cung cấp bởi hệ điều hành (platform software) hoặc bởi sự cài đặt phần

mềm Java™ 2 SDK . Với các ứng dụng tương tác, nên dùng hộp thoại.

Tuy nhiên, các ứng dụng in kết qủa(production printing application), các

hộp thoại không cần thiết, ví dụ như, bạn không cần hiển thị hộp thoại khi

tự động tạo và in một báo cáo cơ sở dữ liệu. Một việc in không yêu cầu

tương tác với người dùng đôi khi được gọi là “silent print job”.

Page setup dialog

Bạn có thể cho phép người dung thay đổi thông tin cài đặt trang(page

setup information) chứa trong PageFormat bởi hiển thị hộp thoại page

setup. Để hiển thị một hộp thoại page setup bạn gọi hàm

PrinterJob.pageDialog. Hộp thoại page setup được khởi tạo dùng tham

số truyền cho pageDialog. Nếu người dùng click vào nút OK trong hộp

thoại, thị một thể nghiệm của PageFormat được tạo(cloned), và thay đổi

http://tailieuhay.com 180

Page 181: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

theo tới các chọn lựa của người dùng rồi trả về. Nều người dùng ấn

cancel, thì pageDialog trả về PageFormat chưa bị thay đổi.

Print dialog

Thông thường, một ứng dụng hiển thị một hộp thoại in cho người

dung khi được kích hoạt ở thực đơn hay bởi nút bấm. Để hiển thị hộp

thoại in này, bạn gọi hàm printDialog của PrinterJob. Các lựa chọn của

người dùng trong hộp thoại được ràng buộc dựa trên số và định dạng của

các trang trong Printable hoặc Pageable đã được cung cấp cho

PrinterJob. Nếu người dùng click OK trong hộp thoại in, printDialog trả

về TRUE. Còn click vào Cancel nó trả về FALSE và việc in coi như bỏ

qua.

7.3 Printing with Printables

Cung cấp bổ hỗ trợ in cơ bản:

1. Cài đặt giao diện Printable để cung cấp một page painter có thể

đẩy mỗi trang ra để in.

2. Tạo một PrinterJob.

3. Gọi setPrintable để thông báo cho PrinterJob cách thức in tài liệu.

Gọi hàm print của đối tượng PrinterJob để bắt đầu công việc.

Trong ví dụ dưới đây, một Printabble job được dùng để in 5 trang,

mỗi cái hiển thị một số trang màu xanh. Điều khiển công việc được quản

lý trong phương thức chính, phương thức lấy về và điều khiển PrinterJob.

Việc đẩy ra (Rendering) được thực hiện trong phương thức print của page

painter.

import java.awt.*; import java.awt.print.*;

public class SimplePrint implements Printable

{

http://tailieuhay.com 181

Page 182: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

private static Font fnt = new

Font("Helvetica",Font.PLAiN,24);

public static void main(String[] args)

{

// Get a PrinterJob

PrinterJob job = PrinterJob.getPrinterJob();

// Specify the Printable is an instance of

SimplePrint job.setPrintable(new SimplePrint());

// Put up the dialog box if

(job.printDialog())

{

// Print the job if the user didn't

cancel printing

try { job.print(); }

catch (Exception e)

{ /* handle exception */ }

}

System.exit(0);

}

public int print(Graphics g, PageFormat pf,

int pageindex)

throws PrinterException

{

// pageindex 0 to 4 corresponds to page

numbers 1 to 5.

http://tailieuhay.com 182

Page 183: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

if (pageindex >= 5) return

Printable.NO_SUCH_PAGE;

g.setFont(fnt);

g.setColor(Color.green);

g.drawString("Page " + (pageindex+1), 100,

100);

return Printable.PAGE_EXiSTS;

}

}

Using Graphics2D for Rendering

Bạn có thể cần các hàm Graphics2D trong phương thức print của

page painter bởi trước tiên chuyển ngữ cảnh Graphics tới một

Graphics2D

Trong ví dụ dưới đây, các số trang được đẩy ra dùng một hướng red-

green(red-green gradient). Để làm điều này, một GradientPaint được đặt

trong ngữ cảnh Graphics2D.

import java.awt.*; import java.awt.print.*;

public class SimplePrint2D implements

Printable

{

private static Font fnt = new

Font("Helvetica",Font.PLAiN,24);

private Paint pnt = new GradientPaint(100f,

100f, Color.red,

http://tailieuhay.com 183

Page 184: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

136f, 100f, Color.green, true);

public static void main(String[] args)

{

// Get a PrinterJob

PrinterJob job = PrinterJob.getPrinterJob();

// Specify the Printable is an instance of

SimplePrint2D

job.setPrintable(new SimplePrint2D());

// Put up the dialog box

if (job.printDialog())

{

// Print the job if the user didn't

cancel printing

try { job.print(); }

catch (Exception e) { /* handle exception

*/ }

}

System.exit(0);

}

public int print(Graphics g, PageFormat pf,

int pageindex)

throws PrinterException

{

// pageindex 0 to 4 corresponds to page

numbers 1 to 5.

if (pageindex >= 5) return

Printable.NO_SUCH_PAGE;

http://tailieuhay.com 184

Page 185: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Graphics2D g2 = (Graphics2D) g;

// Use the font defined above

g2.setFont(fnt);

// Use the gradient color defined above

g2.setPaint(pnt);

g2.drawString("Page " + (pageindex+1), 100f,

100f);

return Printable.PAGE_EXiSTS;

}

}

7.3.2 Printing a File

Khi môt phương thức in của page painter được yêu cầu vài lần cho

cùng trang, nó phải được sinh ra cùng đầu ra mỗi lần.

Có nhiều cách để chắc chắn rằng các yêu cầu lặp lại để đẩy ra một

trang thuận tiện ra cùng đầu ra. Ví dụ, để chắc chắn rằng cùng đầu ra

được sinh ra mỗi lần hệ thống in yêu cầu các trang cụ thể của một file

văn bản, page painter có thể lưu trữ và sử dụng lại các con trỏ file cho

mỗi trang hoặc chứa dữ trang thực tế.

Trong ví dụ dưới đây, một danh sách các file văn bản được in. Tên

của file được truyền như là đối số cho hàm main. Lớp

PrintListingPainter chứa con trỏ file thực tế ở lúc bắt đầu của mỗi trang

mới nó được yêu cầu để đẩy ra(to render). Khi cùng trang được đây ra lần

nữa, con trỏ file được reset tới vị trí đã nhớ.

import java.awt.*;

import java.awt.print.*;

import java.io.*;

http://tailieuhay.com 185

Page 186: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

public class PrintListing

{

public static void main(String[] args)

{

// Get a PrinterJob

PrinterJob job = PrinterJob.getPrinterJob();

// Ask user for page format (e.g.,

portrait/landscape)

PageFormat pf =

job.pageDialog(job.defaultPage());

// Specify the Printable is an instance of

// PrintListingPainter; also provide given

PageFormat

job.setPrintable(new

PrintListingPainter(args[0]), pf);

// Print 1 copy

job.setCopies(1);

// Put up the dialog box

if (job.printDialog())

{

// Print the job if the user didn't

cancel printing

try { job.print(); }

catch (Exception e) { /* handle exception

*/ }

}

System.exit(0);

}

http://tailieuhay.com 186

Page 187: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

}

class PrintListingPainter implements Printable

{

private RandomAccessFile raf;

private String fileName;

private Font fnt = new Font("Helvetica",

Font.PLAiN, 10);

private int rememberedPageindex = -1;

private long rememberedFilePointer = -1;

private boolean rememberedEOF = false;

public PrintListingPainter(String file)

{

fileName = file;

try{

// Open file

raf = new RandomAccessFile(file, "r");

}

catch (Exception e) { rememberedEOF = true;

}

}

public int print(Graphics g, PageFormat pf,

int pageindex)

throws PrinterException

{

try

{

http://tailieuhay.com 187

Page 188: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

// For catching iOException

if (pageindex != rememberedPageindex)

{

// First time we've visited this page

rememberedPageindex = pageindex;

// if encountered EOF on previous page,

done

if (rememberedEOF) return

Printable.NO_SUCH_PAGE;

// Save current position in input file

rememberedFilePointer = raf.getFilePointer();

}

else raf.seek(rememberedFilePointer);

g.setColor(Color.black);

g.setFont(fnt);

int x = (int) pf.getimageableX() + 10;

int y = (int) pf.getimageableY() + 12;

// Title line

g.drawString("File: " + fileName + ", page:

" +

(pageindex+1), x, y);

// Generate as many lines as will fit in

imageable area

y += 36;

while (y + 12 < pf.getimageableY()

+pf.getimageableHeight())

{

String line = raf.readLine();

if (line == null)

http://tailieuhay.com 188

Page 189: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

{

rememberedEOF = true;

break;

}

g.drawString(line, x, y);

y += 12;

}

return Printable.PAGE_EXiSTS;

}

catch (Exception e) { return

Printable.NO_SUCH_PAGE;}

}

}

Giao diện của chương trình:

http://tailieuhay.com 189

Page 190: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Printing with Pageables and Books

Các Pageable được làm phù hợp với các ứng dụng dựa trên biểu diễn lại

tương minh dữ liệu, trang bởi trang. Lớp Book là một cách thuận lợi để

dùng các Pageable, nhưng bạn cũng có thể xây dựng cầu trúc Pageable

của chính bạn nếu Book không phù hợp với cái của bạn cần. Phần này chỉ

cho bạn cách dùng Book.

Các Pageable job được đề cập qua các Printable job bởi vì hệ thống in

có khả năng linh hoạt hơn. Một cải tiến chính của Pageable là số trang

trong tài liệu thường được biết và có thể hiện thị cho người dùng trong

hộp thoại in. Điều này trợ giúp cho người dùng để chắc chắn rằng công

việc (job) được thực hiện (specified) chính xác hoặc chọn một dải các

trang để in.

Một Book biểu diễn một tập các trang. Các trang trong một book không

phải cũng cỡ, cùng hướng, hoặc page painter. Ví dụ, một Book có thể

chứa các trang với 2 cỡ chữ trong hướng portrait và một trang cỡ chữ

trong hướng landscape.

Khi một Book khởi tạo đàu tiên, nó trống rỗng. Để thêm các trang vào

một Book, bạn dùng phương thức append. Phương thức này nhận 2 đối

tượng PageFormat xác định (defines) cỡ trang, vùng có thể in, hướng và

một page painter cài đặt giao diện Printable.

Nhiều trang trong một Book có thể dùng chung cùng định dang và

painter. Phương thức append được nạp chồng để cho phép bạn thêm vào

một dãy các trang mf có cùng thược tính bởi việc xác định tham số thứ 3,

số lượng các trang.

Nếu bạn không biết tổng số trang trong một Book, bạn có thể chuyển

cho giá trị UNKNOW_NUMBER_OF_PAGES cho phương thức append.

Hệ thống in sau đó sẽ gọi các page painter của bạn theo thứ tụ tăng dần

chỉ số trang đế khi một trong chúng trả về NO_SUCH_PAGE.

http://tailieuhay.com 190

Page 191: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Phương thức setPage có thể được dùng để thay đổi định dạng trang

hoặc painter. Trang để thay đổi được xác định (identified) bởi chỉ số trang

cái chỉ ra vị trí của trang trong Book.

Ban gọi setPageable và truyền trong Book để chuẩn bị cho việc in.

Hàm setPageablbe và hàm setPrintable là loại trừ nhau. Do đó bạn gọi

một hoặc cái này hoặc cái kia chứ không thể cả hai khi đang chuẩn bị in

PrinterJob.

7.4.1 Using a Pageable Job

Ví dụ sau, một Book được dùng để tạo lại ví duj in đơn giản đầu

tiên( Do trường hợp này qúa đơn giản, có rất it lợi ích trong việc dùng

một Pageable job thay cho một Printable job, nhưng nó minh hoạ cơ bản

cách cùng một Book) Chú ý rằng bạn vẫn phải cài đặt giao diện Printable

và thực hiện page rendering trong phương thức print của page painter.

import java.awt.*;

import java.awt.print.*;

public class SimplePrintBook implements

Printable

{

private static Font fnt = new

Font("Helvetica",Font.PLAiN,24);

public static void main(String[] args)

{

// Get a PrinterJob

PrinterJob job = PrinterJob.getPrinterJob();

// Set up a book

Book bk = new Book();

http://tailieuhay.com 191

Page 192: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

bk.append(new SimplePrintBook(),

job.defaultPage(), 5);

// Pass the book to the PrinterJob

job.setPageable(bk);

// Put up the dialog box

if (job.printDialog())

{

// Print the job if the user didn't

cancel printing

try { job.print(); }

catch (Exception e) { /* handle exception

*/ }

}

System.exit(0);

}

public int print(Graphics g, PageFormat pf,

int pageindex)

throws PrinterException

{

g.setFont(fnt);

g.setColor(Color.green);

g.drawString("Page " + (pageindex+1), 100,

100);

return Printable.PAGE_EXiSTS;

}

}

Giao diện của chương trình:

http://tailieuhay.com 192

Page 193: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

7.4.2 Using Multiple Page Painters

Ví dụ dưới đây, có hai page painter khác nhau được sử dụng: một cho

bìa và một cho các trang bên trong. Trang bìa được in trong landscape

mode và nội dung in portrait mode.

import java.awt.*;

import java.awt.print.*;

public class PrintBook

{

public static void main(String[] args)

{

// Get a PrinterJob

PrinterJob job = PrinterJob.getPrinterJob();

// Create a landscape page format

PageFormat pfl = job.defaultPage();

pfl.setOrientation(PageFormat.LANDSCAPE);

// Set up a book

Book bk = new Book();

http://tailieuhay.com 193

Page 194: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

bk.append(new PaintCover(), pfl);

bk.append(new PaintContent(),

job.defaultPage(), 2);

// Pass the book to the PrinterJob

job.setPageable(bk);

// Put up the dialog box

if (job.printDialog())

{

// Print the job if the user didn't

cancel printing

try { job.print(); }

catch (Exception e) { /* handle exception

*/ }

}

System.exit(0);

}

}

class PaintCover implements Printable

{

Font fnt = new Font("Helvetica-Bold",

Font.PLAiN, 72);

public int print(Graphics g, PageFormat pf,

int pageindex)

throws PrinterException

{

g.setFont(fnt);

g.setColor(Color.black);

http://tailieuhay.com 194

Page 195: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

int yc = (int) (pf.getimageableY() +

pf.getimageableHeight()/2);

g.drawString("Widgets, inc.", 72, yc+36);

return Printable.PAGE_EXiSTS;

}

}

class PaintContent implements Printable

{

public int print(Graphics g, PageFormat pf,

int pageindex)

throws PrinterException

{

Graphics2D g2 = (Graphics2D) g;

int useRed = 0;

int xo = (int) pf.getimageableX();

int yo = (int) pf.getimageableY();

// Fill page with circles or squares,

alternating red & green

for (int x = 0; x+28 <

pf.getimageableWidth(); x += 36)

for (int y = 0; y+28 <

pf.getimageableHeight(); y += 36)

{

if (useRed == 0) g.setColor(Color.red);

else g.setColor(Color.green);

useRed = 1 - useRed;

http://tailieuhay.com 195

Page 196: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

if (pageindex % 2 == 0) g.drawRect(xo+x+4,

yo+y+4, 28, 28);

else g.drawOval(xo+x+4, yo+y+4, 28, 28);

}

return Printable.PAGE_EXiSTS;

}

Giao diện cua chương trình:

Ví dụ in một một chương trình.

import java.awt.geom.*;

import java.awt.event.ActionListener;

import java.awt.event.ActionEvent;

import java.awt.print.PrinterJob;

import java.awt.event.*;

import java.awt.*;

import javax.swing.*;

http://tailieuhay.com 196

Page 197: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

import java.awt.print.*;

public class ShapesPrint extends JPanel

implements Printable, ActionListener {

final static Color bg = Color.white;

final static Color fg = Color.black;

final static Color red = Color.red;

final static Color white = Color.white;

final static BasicStroke stroke = new

BasicStroke(2.0f);

final static BasicStroke wideStroke = new

BasicStroke(8.0f);

final static float dash1[] = { 10.0f };

final static BasicStroke dashed = new

BasicStroke(1.0f,

BasicStroke.CAP_BUTT,

BasicStroke.JOiN_MiTER, 10.0f, dash1, 0.0f);

final static JButton button = new

JButton("in");

http://tailieuhay.com 197

Page 198: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

public ShapesPrint() {

setBackground(bg);

button.addActionListener(this);

}

public void actionPerformed(ActionEvent e) {

if (e.getSource() instanceof JButton) {

PrinterJob printJob =

PrinterJob.getPrinterJob();

printJob.setPrintable(this);

if (printJob.printDialog()) {

try {

printJob.print();

} catch (Exception ex) {

ex.printStackTrace();

}

}

}

}

public void paintComponent(Graphics g) {

super.paintComponent(g);

Graphics2D g2 = (Graphics2D) g;

drawShapes(g2);

}

public void drawShapes(Graphics2D g2) {

Dimension d = getSize();

int gridWidth = 400 / 6;

http://tailieuhay.com 198

Page 199: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

int gridHeight = 300 / 2;

int rowspacing = 5;

int columnspacing = 7;

int rectWidth = gridWidth -

columnspacing;

int rectHeight = gridHeight - rowspacing;

Color fg3D = Color.lightGray;

g2.setPaint(fg3D);

g2.drawRect(80, 80, 400 - 1, 310);

g2.setPaint(fg);

int x = 85;

int y = 87;

g2.draw(new Line2D.Double(x, y +

rectHeight - 1, x + rectWidth, y));

x += gridWidth;

g2.setStroke(stroke);

g2.draw(new Rectangle2D.Double(x, y,

rectWidth, rectHeight));

x += gridWidth;

g2.setStroke(dashed);

g2

.draw(new

RoundRectangle2D.Double(x, y, rectWidth,

rectHeight,

10, 10));

x += gridWidth;

g2.setStroke(wideStroke);

g2.draw(new Arc2D.Double(x, y, rectWidth,

rectHeight, 90, 135,

http://tailieuhay.com 199

Page 200: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Arc2D.OPEN));

x += gridWidth;

g2.setStroke(stroke);

g2.draw(new Ellipse2D.Double(x, y,

rectWidth, rectHeight));

x += gridWidth;

int x1Points[] = { x, x + rectWidth, x, x

+ rectWidth };

int y1Points[] = { y, y + rectHeight, y +

rectHeight, y };

GeneralPath polygon = new

GeneralPath(GeneralPath.WiND_EVEN_ODD,

x1Points.length);

polygon.moveTo(x1Points[0], y1Points[0]);

for (int index = 1; index <

x1Points.length; index++) {

polygon.lineTo(x1Points[index],

y1Points[index]);

}

;

polygon.closePath();

g2.draw(polygon);

x = 85;

y += gridHeight;

int x2Points[] = { x, x + rectWidth, x, x

+ rectWidth };

int y2Points[] = { y, y + rectHeight, y +

rectHeight, y };

http://tailieuhay.com 200

Page 201: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

GeneralPath polyline = new

GeneralPath(GeneralPath.WiND_EVEN_ODD,

x2Points.length);

polyline.moveTo(x2Points[0],

y2Points[0]);

for (int index = 1; index <

x2Points.length; index++) {

polyline.lineTo(x2Points[index],

y2Points[index]);

}

;

g2.draw(polyline);

x += gridWidth;

g2.setPaint(red);

g2.fill(new Rectangle2D.Double(x, y,

rectWidth, rectHeight));

g2.setPaint(fg);

x += gridWidth;

GradientPaint redtowhite = new

GradientPaint(x, y, red, x + rectWidth,

y, white);

g2.setPaint(redtowhite);

g2

.fill(new

RoundRectangle2D.Double(x, y, rectWidth,

rectHeight,

10, 10));

g2.setPaint(fg);

x += gridWidth;

http://tailieuhay.com 201

Page 202: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

g2.setPaint(red);

g2.fill(new Arc2D.Double(x, y, rectWidth,

rectHeight, 90, 135,

Arc2D.OPEN));

g2.setPaint(fg);

x += gridWidth;

redtowhite = new GradientPaint(x, y, red,

x + rectWidth, y, white);

g2.setPaint(redtowhite);

g2.fill(new Ellipse2D.Double(x, y,

rectWidth, rectHeight));

g2.setPaint(fg);

x += gridWidth;

int x3Points[] = { x, x + rectWidth, x, x

+ rectWidth };

int y3Points[] = { y, y + rectHeight, y +

rectHeight, y };

GeneralPath filledPolygon = new

GeneralPath(GeneralPath.WiND_EVEN_ODD,

x3Points.length);

filledPolygon.moveTo(x3Points[0],

y3Points[0]);

for (int index = 1; index <

x3Points.length; index++) {

filledPolygon.lineTo(x3Points[index],

y3Points[index]);

}

;

http://tailieuhay.com 202

Page 203: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

filledPolygon.closePath();

g2.setPaint(red);

g2.fill(filledPolygon);

g2.setPaint(fg);

g2.draw(filledPolygon);

}

public int print(Graphics g, PageFormat pf,

int pi) throws PrinterException {

if (pi >= 1) {

return Printable.NO_SUCH_PAGE;

}

drawShapes((Graphics2D) g);

return Printable.PAGE_EXiSTS;

}

public static void main(String s[]) {

WindowListener l = new WindowAdapter() {

public void

windowClosing(WindowEvent e) {

System.exit(0);

}

public void windowClosed(WindowEvent

e) {

System.exit(0);

}

};

JFrame f = new JFrame();

http://tailieuhay.com 203

Page 204: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

f.addWindowListener(l);

JPanel panel = new JPanel();

panel.add(button);

f.getContentPane().add(BorderLayout.SOUTH,

panel);

f.getContentPane().add(BorderLayout.CENTER,

new ShapesPrint());

f.setSize(580, 500);

f.show();

}

}

Giao diện của chương trình:

http://tailieuhay.com 204

Page 205: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

http://tailieuhay.com 205

Page 206: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Phần 2

Lập trình đồ họa với Java 3D

http://tailieuhay.com 206

Page 207: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

CHƯƠNG 1

NHẬP MÔN LẬP TRÌNH TRÊN JAVA 3D

1.1 Tổng quan về Java 3D API ™

Java 3D API được thừa kế từ các lớp của java cho phép tạo các giao

diện phức tạp như hệ thống âm thanh và hình ảnh 3 chiều. Người lập trình

có thể sử dụng nó để xây dựng điều khiển các đối tượng hình học 3 chiều.

Những đối tượng này cư trú trên một môi trường ảo sau đó mới được

dựng hình lại. Các hàm API được thiết kế rất linh động cho phép tạo một

trường ảo đó chính xác với rất nhiều dạng kích cỡ từ lớn đến bé.

Dù có nhiều chức năng như vậy nhưng các hàm API vẫn có thể sử

dụng rõ ràng. Các chi tiết được dưng hình tự động. Sử dụng lợi thế của

các luồng trong java, việc dựng hình trong Java 3D cho phép làm song

song, đồng thời cũng cho phép tối hưu hóa việc dựng hình. Chương trình

Java 3D tạo các instances của các đối tượng và đưa chúng vào cơ sở dữ

liệu đồ thị khung cảnh. Đồ thị khung cảnh là một sắp xếp các đối tượng

Java 3D trên một cấu trúc cây cho phép chỉ ra nội dụng của một thế giới

ảo và chúng có thể được dựng hình như thế nào.

Chương trình Java 3D có thể được viết để chạy độc lập hay như là một

applet trên các trình duyệt hỗ trợ Java 3D hoặc cả 2.

http://tailieuhay.com 207

Page 208: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

1.2 Các vấn đề cơ bản về Java 3D API™

Java 3D API định nghĩa hơn 100 lớp trong gói javax.media.j3d

những lớp này được coi như là những lớp cơ bản nhất của Java 3D.

Có đến hàng trăm trường và phương thức trong các lớp của Java 3D

API tuy nhiên một môi trường ảo đơn giản chỉ cần dùng một vài lớp.

Chương này mô tả tập nhỏ nhất các đối tượng và tương tác giữa chúng để

dựng nên một môi trường ảo.

Chương này còn bao gồm ví dụ HelloJava3D hiển thi một khối lập

phương quay. Ví dụ này được phát triển theo từng bước lần lượt thể hiện

các phần xử lí trong lập trình Java 3D.

Ngoài gói nhân Java 3D chúng ta còn sử dụng thêm một gói nữa là

com.sun.j3d.utils thường gọi là các lớp tiện dụng, chúng bổ sung thêm

những tính năng hiệu quả và rất mạnh cho nhân.

Lớp utility gồm 4 mục: content loader(nạp nội dung), hỗ trợ xây dựng

đồ thị khung cảnh, các lớp hình học, và các công cụ tiện ích.

Tất nhiên là ngoài gói nhân và gói tiện ích thì mọi chương trình java

đều sử dụng các lớp từ gói java.awt và javax.vecmath. Gói java.awt

định nghĩa các lớp AWT cho phép tạo cửa sổ cho việc dựng hình. Gói

javax.vecmath định nghĩa các lớp cho điểm, vector ma trận và những đối

tượng toán học khác.

Trong phần còn lại của giáo trình này từ visual object(đối tượng quan sát)

được sử dụng thay cho “một đối tượng trong đồ thị khung cảnh”.(chẳng

hạn: một hình lập phương hay hình cầu). Từ object được sử dụng cho một

instance của một lớp. Content tương ứng với những đối tượng quan sát

trong một đồ thị khung cảnh.

1.3 Xây dựng đồ thị khung cảnh

Môi trường ảo trong Java 3D được tạo từ một đồ thị khung cảnh, một

đồ thị khung cảnh được tạo nên bởi các instance của các lớp Java 3D. Đồ

http://tailieuhay.com 208

Page 209: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

thị khung cảnh đó được ghép nối bởi các đối tượng được định nghĩa về

mặt hình học, âm thanh và ánh sáng, vị trí, hướng và bề ngoài về trực

quan cũng như âm thanh của đối tượng. Với một đồ thị bình thường thì

cấu trúc dữ liệu hay dùng là các nút và các cung. Một nút của đồ thị

khung cảnh là một instance của một lớp Java 3D. Các cung đại diện cho 2

dạng quan hệ giữa các instances của Java 3D.

Quan hệ hay gặp nhất là quan hệ cha con – một nút cha có rất nhiều nút

con. Một quan hệ khác là quan hệ tham chiếu. Một tham chiếu liên kết

một đối tượng NodeComponent với một nút của đồ thị khung cảnh.

NodeComponent định nghĩa về mặt hình học và các thuộc tính bề mặt

được sử dụng để dựng nên đối tượng quan sát.

Đồ thị khung cảnh trong Java 3D được cấu thành từ các nút đối tượng

trong các mối liên hệ cha con định ra một cấu trúc cây. Trong cây này chỉ

có một nút gốc. Các nút còn lại được truy cập tới thông qua các cung đi từ

nút gốc, các cung trên cây không tạo thành chu trình. Một đồ thị khung

cảnh được định dạng từ các cây mà gốc tại các đối tượng xảy ra.

NodeComponent và các cung tham chiếu không phải là một phần của đồ

thị khung cảnh.

Chỉ tồn tại một đường duy nhất từ gốc của cây đến một lá, từ đó chỉ có

một đường đi duy nhất từ gốc của một đồ thị khung cảnh đến mỗi nút lá.

Đường đi đó gọi là đường đi của đồ thị khung cảnh. Từ đó chỉ có một

đường đi đồ thị khung cảnh đến mỗi lá trong một đồ thị khung cảnh.

Mỗi dường đi đồ thị khung cảnh trong đồ thị khung cảnh của Java 3D

chỉ ra thông tin về trạng thái của lá. Thông tin trạng thái đó bao gồm địa

điểm, hướng, và kích thước của đối tượng quan sát. Kết quả là các thuộc

tính trực quan của mỗi đối tượng quan sát phụ thuộc vào mỗi đường đi

trên đồ thị khung cảnh của nó. Bộ dựng hình Java 3D dựa trên điểm này

để dựng nên các lá theo thứ tự hiệu quả nhất. Những người lập trình Java

3D thường không phải điều khiển quá trình này.

http://tailieuhay.com 209

Page 210: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Về mặt đồ họa thì một đồ thị khung cảnh được dùng như là một công

cụ thiết kế hoặc tài liệu hóa cho các trương trình Java 3D. Đồ thị khung

cảnh được vẽ trên các biểu tượng như hình 1.1. Chương trình Java 3D có

thể có nhiều đối tượng hơn so với những đối tượng ở trong đồ thị này.

Như vậy để thiết kế môi trường ảo, đồ thị khung cảnh được vẽ dựa

trên những biểu tượng chuẩn. Sau khi việc thiết kế hoàn thành, sơ đồ đồ

thị khung cảnh sẽ là tiêu chí của chương trình. Sau khi chương trình hoàn

thành, một đồ thị khung cảnh tương tự đại diện cho chương trình (giả sử

là những đặc điểm đó được tuân theo). Đồ thị được vẽ từ chương trình

minh chứng cho đồ thị mà chương trình tạo ra.

Mỗi một biểu tượng ở phía bên trái của hình 1.1 đại điện cho một đối

tượng đơn lẻ khi sử dụng trong đồ thị khung cảnh. 2 biểu tượng đầu tiên

đại diện cho các đối tượng của 2 lớp đặc biệt VirtualUniverse và Locale.

3 biểu tượng tiếp theo đại diện cho các đối tượng của các lớp Group,

Leaf và NodeComponent. 3 biểu tượng sau đó thường được dùng để chỉ

các lớp con của những đối tượng trên. Biểu tượng cuối cùng bên trái đại

diện cho bất cứ lớp của đối tượng nào.

Mũi tên liền đại diện cho một liên kết cha con giữa 2 đối tượng. Nét đứt

chỉ tham chiếu đến một đối tượng khác. Đối tượng được tham chiếu có

http://tailieuhay.com 210

Page 211: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

thể chia sẻ giữa các nhánh khác nhau của một đồ thị khung cảnh. Dưới

đây là một ví dụ (Hình 1.2)

Rất dễ xây dựng một đồ thị khung cảnh sai. Một ví dụ sai đơn giản có

thể xem ở hình 1-3. Đồ thị này sai bởi vì nó vi phạm những đặc tính của

DAG. Vấn đề nằm ở chỗ chỉ với 2 đối tượng TransformGroup có chung

một đối tượng lá Shape3D là con. Nhớ rằng một đối tượng lá chỉ có thể

có 1 cha duy nhất. Nói cách khác chỉ có một đường đi từ đối tượng

Locale đến 1 lá (hay là đường từ một lá đến một Locale).

Bạn có thể nghĩ cấu trúc xây dựng trong hình 1-3 định nghĩa 3 đối

tượng quan sát trong một môi trường ảo, Nó xuất hiện trên biểu đồ khung

cảnh dựa trên định nghĩa 2 đối tượng quan sát thông qua sử dụng đối

tượng quan sát Shape3D phía bên phải của đồ thị. Mà dựa trên các khái

niệm, mỗi đối tượng TransformGroup cha chung của đối tượng

Shape3D phải đặt một hình ảnh của đối tượng quan sát trên các vị trí

khác nhau. Tuy nhiên đây là một đồ thị không hợp lệ vì cung cha con

http://tailieuhay.com 211

Page 212: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

không định ra một cây. Trong ví dụ này, kết quả là đối tượng Shape3D có

hơn 1 cha.

Sự tranh cãi về cấu trúc của cây và DAG là chính xác. Tuy nhiên hệ

thống runtime của Java 3D đưa ra thông báo có lỗi trong mối quan hệ cha

con. Vì kết quả của sự giới hạn cấu trúc cây mà mỗi đối tượng Shape3D

bị hạn chế chỉ có một cha. Với ví dụ trong hình 1-3, lỗi thông báo là chính

là việc có nhiều cha. Trên hình 1-4 đưa ra giải pháp cho vấn đề này.

Chương trình Java 3D mà có đồ thị khung cảnh không hợp lệ có thể

dịch được nhưng không thể dịch được. Khi một chương trình Java 3D có

đồ thị khung cảnh không hợp lệ được chạy, hệ thông Java 3D sẽ phát hiện

ra vấn đề. Và khi vấn đề được phát hiện thì hệ thống Java 3D sẽ thông

báo lỗi. Chương trình có thể vẫn chạy nhưng vẫn cần phải dừng lại vì

chẳng có hình ảnh nào dựng nên cả.

Mỗi đồ thị khung cảnh chỉ có một môi trường ảo. Đối tượng môi trường

ảo có một danh sách các đối tượng Locale. Một đối tượng Locale cung

cấp một điểm tham chiếu trong môi trường ảo đó. Có thể coi như đối

http://tailieuhay.com 212

Page 213: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

tượng Locale là cột mốc sử dụng để xác định vị trí của các đối tượng

quan sát trong môi trường ảo.

thể có nhiều môi trường ảo trong một chương trình Java 3D, vì thế có

thể định nghĩa nhiều hơn một môi trường ảo. Tuy nhiên, không có cách

cố định nào cho việc liên lạc giữa các môi trường ảo này. Xa hơn, một đối

tượng đồ thị khung cảnh không thể tồn tại trong đa môi trường ảo cùng

một lúc. Do đó chỉ nên sử dụng một và chỉ một instance của môi trường

ảo trong mỗi chương trình Java 3D.

Trong khi một đối tượng môi trường ảo có thể tham chiếu đến nhiều đối

tượng Locale thì hầu hết các chương trình Java 3D chỉ có một đối tượng

Locale. Mỗi đối tượng Locale có thể phục vụ như là gốc của nhiều đồ thị

con của đồ thị khung cảnh. Theo ví dụ ở hình 1-2 có thể thấy đối tượng

Locale có 2 nhánh đồ thị con từ nó.

Các đồ thị con thì phân ra làm 2 loại nhánh hình thức và nhánh nội

dung. Nhánh nội dung chỉ ra nội dung của môi trường ảo – hình học, bề

mặt, hành vi, địa điểm, âm thanh, và ánh sáng. Nhánh hình thức chỉ ra các

tham số cho phép xem như địa điểm xem và hướng xem.

http://tailieuhay.com 213

Page 214: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

1.3.1 Thừa kế cấp cao từ Java 3D API

Có 3 cấp thừa kế từ Java 3D API thể hiện trong hình 5-1. Thông qua

cấu trúc này chúng ta sẽ hình dung được chương trình Java 3D như thế

nào.

Lớp node

Lớp node là lớp cha của 2 lớp Group và Leaf, định nghĩa những

phương thức chung và rất quan trọng cho các lớp con của nó. Thông tin

về các phương thức này sẽ được mô tả ở phần sau của tài liệu

Lớp Group

Lớp group là lớp gốc sử dụng để chỉ ra vị trí và hướng của đối tượng

quan sát trong một môi trường ảo. 2 lớp con của là BranchGroup và

TransformGroup. Trong đồ thị khung cảnh hình ảnh đại diện của 2 lớp

này có biểu tượng là hình tròn và thường được viết tắt thành BG và TG.

Lớp Leaf

http://tailieuhay.com 214

Page 215: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Lớp Leaf là lớp gốc để định nghĩa hình dạng, âm thanh, và hành vi

của đối tượng quan sát trong mội trường ảo. Một vài lớp con của lớp này

là Shape3D, Light, Behavior và Sound. Những đối tượng này có thể

không có lớp con nhưng phải tham chiếu đến NodeComponent.

Lớp NodeComponent

Lớp NodeComponent là lớp gốc sử dụng để mô tả về hình học, bề

mặt, texture và những thuộc tính của node Shape3D. NodeComponent

không phải là một phần của đồ thị khung cảnh nhưng lại được tham chiếu

đến. Một NodeComponent có thể được tham chiếu bới nhiều đối tượng

Shape3D.

http://tailieuhay.com 215

Page 216: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

1.4 Cách thức để viết một chương trình Java 3D

Việc xây dựng một chương trình Java 3D gồm có 7 bước được giới

thiệu trong hình 1-6. Đây là công thức hữu ích để xây dựng các ứng dụng

Java 3D.

Công thức này cũng bỏ qua môt vài chi tiết nhưng diễn tả phần lớn

những công việc cần làm trong đó việc tạo các nhánh đồ thị của đồ thị

khung cảnh là công việc quan trọng nhất của việc lập trình. Trong phần

tới chúng ta sẽ được biết làm thể nào để tạo một đồ thị khung cảnh mà

không phải lập trình nhiều.

1.4.1 Công thức đơn giản để viết một chương trình Java 3D

Các chương trình của Java 3D được viết sử dụng công thức trên có

nhánh đồ thị hình thức có cấu trúc đúng đắn, và cấu trúc này đã sẵn có

trong lớp SimpleUniverse. Mỗi instance của lớp này thực hiện các bước

2,3,4 trên công thức cơ bản trên điều đó giúp cho người lập trình giảm

thiểu thời gian và công sức để tạo nhánh hình thức qua đó tập trung vào

công việc chính là nội dung hơn. Công việc thực sự khi viết một chương

trình Java 3D là như vậy.

1. Create a Canvas3D object

2. Create a VirtualUniverse object

3. Create a Locale object, attaching it to the VirtualUniverse object

4. Construct a view branch graph

a. Create a View object

b. Create a ViewPlatform object

c. Create a PhysicalBody object

d. Create a PhysicalEnvironment object

e. Attach ViewPlatform, PhysicalBody, PhysicalEnvironment, and

Canvas3D objects to View object

http://tailieuhay.com 216

Page 217: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

5. Construct content branch graph(s)

6. Compile branch graph(s)

7. Insert subgraphs into the Locale

Việc sử dụng lớp này cho phép người lập trình tạm quên đi nhánh đồ

thị hình thức. Tuy nhiên nó không cho phép có nhiều view trong môi

trường ảo của nó.

SimpleUniverse Class

Hàm khởi tạo của đối tượng SimpleUniverse tạo nên đồ thị khung

cảnh bao gồm các đối tượng VirtualUniverse và Locale và một nhánh đồ

thị hình thức hoàn thiện.

Nhánh này sử dụng instances của các lớp ViewingPlatform và Viewer

trong nhân của lớp để tạo thành nhánh đồ thị hình thức. Đối tượng

SimpleUniverse cung cấp tất cả các chức năng được chỉ ra trong hình 1-

7.

Gói com.sun.j3d.utils.universe chứa các lớp SimpleUniverse,

ViewingPlatform và Viewer.

http://tailieuhay.com 217

Page 218: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Việc sử dụng lớp SimpleUniverse là cho công việc đơn giản hơn rất

nhiều. Hình 1-8 đưa ra công thức đơn giản hơn trong đó các bước 2,3,4 đã

được thay bằng bước 2 của công thức mới.

1. Create a Canvas3D Object

2. Create a SimpleUniverse object which references the earlier

Canvas3D object

a. Customize the SimpleUniverse object

3. Construct content branc h

4. Compile content branch graph

5. Insert content branch graph into the Locale of the SimpleUniverse

SimpleUniverse Constructor gói com.sun.j3d.utils.universe

Lớp tiện ích này cho phép dễ dàng cài đặt môi trường người dùng, tạo

các đối tượng cần thiết cho đồ thị nhánh hình thức. Lớp này tạo nên các

đối tượng Locale, VirtualUniverse, ViewingPlatform và Viewer (với tất

cả các giá trị mặc định của chúng). Các đối tượng này liên hệ với nhau để

tạo nên đồ thị nhánh hình thức.

Phương thức khởi tạo quan trọng

SimpleUniverse ()

Khởi tạo một môi trường ảo

SimpleUniverse (Canvas3D canvas3D)

Khởi tạo một môi trường ảo với tham chiếu đến đối tượng được đặt

tên là Canvas3D

Đối tượng SimpleUniverse tạo thành một đồ thị nhánh hình thức

hoàn thiện cho một môi trường ảo. Đồ thị này bao gồm một bảng hình

ảnh. Một bảng hình ảnh là một dạng hình chữ nhật là nơi mà nội dung của

được chiếu đến để định dạng hình ảnh cần dựng. Đối tượng Canvas3D

cung cấp hình ảnh trên một cửa sổ trên màn hình hiển thị của máy tính, có

thể coi như là một bảng hình ảnh vậy. Để rõ hơn chúng ta quan sát hình

http://tailieuhay.com 218

Page 219: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

ảnh dưới đây, hình 1-9 chỉ ra mối quan hệ giữa bảng hình ảnh (image

plate) và vị trí của mắt, môi trường ảo. Vị trí của mắt là đằng sau bảng

hình ảnh. Đối tượng quan sát đứng trước bảng hình ảnh được dựng trên

bảng hình ảnh. Việc dựng hình cũng ví như chiếu một đối tượng quan sát

lên bảng hình ảnh.

Mặc định bảng hình ảnh đặt trung tâm của SimpleUniverse ban đầu,

hướng mặc định là nhìn theo trục z,. Từ vị trí này trục x là đường biên

ngang của bảng hình ảnh với hướng dương là bên phải. Trục y là cạnh

ngang của bảng hình ảnh với giá trị dương hướng lên trên. Thông thường

thì vị trí (0,0,0) là tâm của bảng hình ảnh.

Chương trình Java 3D thông thường sẽ chuyển điểm nhìn ra phía sau

(hướng dương của trục z) để làm cho đối tượng ở vị trí hoặc gần so với vị

trí ban đầu giữa hướng nhìn. Lớp SimpleUniverse có một lớp thành viên

là ViewingPlatform, lớp này có phương thức

setNominalViewingTransform cho phép chuyển vị trí của mắt nhìn tới

trung tâm là (0,0, 2.41) nhìn từ phía âm của trục z so với vị trí ban đầu.

Lớp ViewingPlatform, phương thức setNominalViewingTransform ()

Package: com.sun.j3d.utils.universe

http://tailieuhay.com 219

Page 220: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Lớp ViewingPlatform được sử dụng để thiết lập đồ thị nhánh hình

thức của đồ thị khung cảnh Java 3D với đối tượng SimpleUniverse.

Phương thức này thường được sử dụng để kết nối với phương thức

getViewingPlatform của lớp SimpleUniverse.

void setNominalViewingTransform()

Set tầm nhìn khoảng cách khoảng 2.41 mét từ trong biến đổi tầm

nhìn của một SimpleUniverse. Tại khoảng cách này và thì đối tượng với

chiều cao khoảng 2 mét so thể vừa vặn với bảng hình ảnh.

Sau khi tạo xong các đối tượng Canvas3D và SimpleUniverse, bước

tiếp theo là tạo đồ thị nhánh nội dung. Quy tắc của cấu trúc được tìm thấy

trong đồ thị nhánh hình thức (do việc sử dụng lớp SimpleUniverse). Đồ

thị nhánh nội dung biến đổi khác nhau từ chương trình này đến chương

trình khác do đó có thể xây dựng chi tiết trong công thức. Điều đó có

nghĩa là không có những lớp nội dung đơn giản cho bất cứ môi trường

nào mà bạn muốn thiết lập.

Sau khi tạo xong đồ thị nhánh nội dung, nó được chèn vào môi trường sử

dụng phương thức addBranchGraph của SimpleUniverse. Phương thức

này lấy một instance của BranchGroup như là tham số duy nhất.

BranchGroup này chỉ được thêm vào như là một con của đối tượng

Locale được tạo bởi SimpleUniverse.

Các phương thức SimpleUniverse

Package: com.sun.j3d.utils.universe

void addBranchGraph(BranchGroup bg)

Sử dụng để thêm nút vào đối tượng Locale của đồ thị khung cảnh

được tạo bởi SimpleUniverse. Điều này sử dụng để thêm vào một đồ thị

nhánh nội dung tới môi trường ảo.

ViewingPlatform getViewingPlatform()

http://tailieuhay.com 220

Page 221: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Sử dụng để lấy thông tin từ đối tượng ViewingPlatform mà

SimpleUniverse chỉ ra. Phương thức này sử dụng với phương thức

setNominalViewingTransform () của lớp ViewingPlatform để điều chỉnh

vị trí quan sát.

1.5 Một vài thuật ngữ trong Java 3D

Hai thuật ngữ được nói trong phần này là “live” và “compiled”. Khi

chèn một đồ thị nhánh vào Locale làm cho nó có thể sống (“live”) và kết

quả là mỗi đối tượng của đồ thị nhánh trở thành sống. Những đối tượng

sống là những đối tượng mà chuẩn bị được dựng hình, cho nên những

tham số của một đối tượng sống không thể thay đổi trừ khi khả năng

tương ứng của nó được thiết lập trước khi đối tượng sống (capability được

mô tả trong phần 1.8.2).

Khi các đối tượng BranchGroup được dịch (compiled). Việc dịch

BrandGroup chuyển đối tượng BranchGroup và tất cả những hình thức

sơ khai của nó thành dạng phù hợp để dựng hình. Mục đích của công việc

này là chuẩn bị bước cuối cùng trước khi làm cho đối tượng đó sống.

Phương thức

BranceGroup compile ()

Void compile ()

Dịch nguồn BranchGroup tương ứng với đối tượng bằng cách tạo và

đệm một đồ thị khung cảnh đã được dịch.

Cơ sở của việc dịch và sống được bổ sung trong lớp

SceneGraphObject. 2 phương thức của SceneGraphObject được mô tả

dưới đây.

Danh sách các phương thức cơ bản của SceneGraphObject

SceneGraphObject là lớp cơ bản của tất cả các lớp lân cận dùng để tạo đồ

thị khung cảnh bao gồm Group, Leaf, và NodeComponent.

http://tailieuhay.com 221

Page 222: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

SceneGraphObject cung cấp khá nhiều phương thức và thuộc tính cho các

lớp con của nó, 2 phương thức được trình bày dưới đây.

boolean isCompiled()

Trả về một giá trị cờ chỉ ra khi nào thì node (là một phần của đồ thị

khung cảnh được dịch)

boolean isLive ()

Trả về giá trị cờ chỉ ra khi nào node là một phần của đồ thị khung

cảnh sống

Chú ý rằng không có bước “bắt đầu dựng hình”cả trong công thức cơ

bản lẫn công thức đơn giản đã nói ở trên. Bộ dựng hình của Java 3D bắt

đầu chạy trong một vòng lặp vô hạn khi một đồ thị nhánh chứa một

instance của View băt đầu sống trong một môi trường ảo. Khi đã bắt đầu,

bộ dựng hình Java 3D thực hiện hoạt động như hình 1-10

while(true) {

Process input

If (request to exit) break

Perform Behaviors

Traverse the scene graph

and render visual objects

}

Cleanup and exit

Phần trước đó đã giải thích cấu trúc của một môi trường ảo đơn giản

mà không có đồ thị nhánh nội dung. Việc tạo đồ thị nhánh nội dung là chủ

đề của một số phần tiếp theo. Những thảo luận xung quanh đồ thị nhánh

nội dung được xoay quanh các ví dụ của chương trình.

http://tailieuhay.com 222

Page 223: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

1.6 Ví dụ đơn giản: HelloJava3Da

Chương trình Java 3D bắt đầu bằng việc định nghĩa lớp mới mở rộng

từ lớp Applet. Trong ví dụ HelloJava3Da.java dưới đây ta cũng có lớp

HelloJava3Da được mở rộng từ lớp Applet, và việc sử dụng nó giúp đơn

giản đi rất nhiều so với chương trình Java 3D được viết như ứng dụng độc

lập.

Lớp chính của chương trình Java 3D thường định nghĩa phương thức

thiết lập đồ thị nhánh nộ dung. Trong ví dụ này phương thức như thế

được đặt tên là creatSceneGraph().

Mọi bước theo công thức phía trên đều được thể hiện trong lớp

HelloJava3Da. Bước 1,tạo đối tượng Canvas3D (dòng 4 đến dòng 6).

Bước 2 tạo đối tượng SimpleUniverse hoàn thành ở dòng 17.

Bước 3 tạo nhánh nội dung, được hoàn thành bằng lời gọi ở đến

phương thức creatSceneGraph().

Bước 4 dịch đồ thị nhánh nội dung được thực hiện trong dòng 10.

Cuối cùng bước thứ 5 chèn đồ thị nhánh nội dung vào Locale của

SimpleUniverse thực xong ở dòng 19.

public class HelloJava3Da extends Applet {

public HelloJava3Da() {

setLayout(new BorderLayout());

Canvas3D canvas3D = new Canvas3D(null);

add("Center", canvas3D);

BranchGroup scene = createSceneGraph();

// SimpleUniverse is a Convenience

Utility class

http://tailieuhay.com 223

Page 224: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

SimpleUniverse simpleU = new

SimpleUniverse(canvas3D);

// This will move the ViewPlatform back a

bit so the

// objects in the scene can be viewed.

simpleU.getViewingPlatform().setNominalViewingTra

nsform();

simpleU.addBranchGraph(scene);

} // end of HelloJava3Da (constructor)

Ta thấy bước 3 của công thức này là tạo đồ thị nhánh nội dung. Một

đồ thị nhánh nội dung được tạo trong đoạn mã 1-2. Đó là đồ thị nhánh nội

dung đơn giản nhất có thể. Nó chứa một đối tượng đồ họa tĩnh đó là hình

lập phương màu. Hình này được đặt ở vị trí ban đầu trong hệ thống thế

giới ảo. Với vị trí và hướng nhìn này, hình lập phương này xuất hiện như

hình chữ nhật khi được dựng lên.

public BranchGroup createSceneGraph() {

// Create the root of the branch graph

BranchGroup objRoot = new BranchGroup();

objRoot.addChild(new ColorCube(0.4));

return objRoot;

http://tailieuhay.com 224

Page 225: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

} // end of CreateSceneGraph method of

HelloJava3Da

Lớp HelloJava3Da được thừa kế từ Applet nhưng chương trình có

thể chạy như là một ứng dụng với việc sử dụng lớp MainFrame. Lớp

Applet được sử dụng là lớp cơ sở để dễ dàng cho việc viêt một chương

trình Java 3D chạy trên một cửa sổ. MainFrame cung cấp một AWT

frame (cửa sổ) cho một apple điều đó cho phép apple chạy như một ứng

dụng. Kích thước của cửa sổ được chỉ ra trong phần thiết lập của lớp

MainFrame. Đoạn mã 1-3 bên dưới sẽ chỉ ra cách sử dụng trong

HelloJava3Da.java.

MainFrame ConStructor

package: com.sun.j3d.utils.applet

MainFrame giúp cho một applet có thể chạy như một ứng dụng. Một

lớp thừa kế từ applet có thể có phương thức main() dùng để gọi hàm khởi

tạo của MainFrame. MainFrame mở rộng từ java.awt.Frame và bổ sung

thêm từ java.lang.Runnable, java.applet.AppletStub, và

java.applet.AppletContext.

Hàm

MainFrame(java.applet.Applet applet, int width, int height)

Tạo tạo đối tượng Mainframe cho phép applet chạy như ứng dụng độc

lập.

Tham số: Applet – Hàm tạo của một lớp thừa kế từ applet.

MainFrame cung cấp AWT frame

public static void main(String[] args) {

Frame frame = new MainFrame(new

HelloJava3Da(), 256, 256);

http://tailieuhay.com 225

Page 226: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

} // end of main (method of HelloJava3Da)

Ba đoạn mã 1-1, 1-2, 1-3 trên định nên một chương trình Java 3D

hoàn thiện khi các câu lệnh import được sử dụng. Hầu hết các lớp sử dụng

trong chương trình Java 3D ở trong các gói javax.media.j3d, hoặc

javax.vecmath. Trong ví dụ này lớp tiện ích ColorCube được tìm thấy

trong gói com.sun.j3d.utils.geometry kết quả là hầu hết chương trình

Java 3D đều có những câu lệnh để import các thư viện như hình 1-4,

ngoại trừ lớp tiện ích ColorCube.

import java.applet.Applet;

import java.awt.BorderLayout;

import java.awt.Frame;

import javax.media.j3d.BranchGroup;

import javax.media.j3d.Canvas3D;

import com.sun.j3d.utils.applet.MainFrame;

import com.sun.j3d.utils.geometry.ColorCube;

import com.sun.j3d.utils.universe.SimpleUniverse;

Trong ví dụ phía trên một đối tượng đồ họa đơn được đặt trong một vị

trí đơn. Ta có đồ thị khung cảnh như bên dưới:

http://tailieuhay.com 226

Page 227: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Mã nguồn của chương trình là:

package HelloJava3D;

import java.applet.Applet;

import java.awt.BorderLayout;

import java.awt.Frame;

import javax.media.j3d.BranchGroup;

import javax.media.j3d.Canvas3D;

import com.sun.j3d.utils.applet.MainFrame;

import com.sun.j3d.utils.geometry.ColorCube;

import com.sun.j3d.utils.universe.SimpleUniverse;

// HelloJava3Da renders a single, rotating cube.

public class HelloJava3Da extends Applet {

public HelloJava3Da() {

setLayout(new BorderLayout());

Canvas3D canvas3D = new Canvas3D(null);

add("Center", canvas3D);

BranchGroup scene = createSceneGraph();

// SimpleUniverse is a Convenience Utility class

SimpleUniverse simpleU = new SimpleUniverse(canvas3D);

// This will move the ViewPlatform back a bit so the

// objects in the scene can be viewed.

simpleU.getViewingPlatform().setNominalViewingTransform();

http://tailieuhay.com 227

Page 228: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

simpleU.addBranchGraph(scene);

} // end of HelloJava3Da (constructor)

public BranchGroup createSceneGraph() {

// Create the root of the branch graph

BranchGroup objRoot = new BranchGroup();

objRoot.addChild(new ColorCube(0.4));

return objRoot;

} // end of CreateSceneGraph method of HelloJava3Da

// The following allows this to be run as an application

// as well as an applet

public static void main(String[] args) {

Frame frame = new MainFrame(new HelloJava3Da(), 256,

256);

} // end of main (method of HelloJava3Da)

} // end of class HelloJava3Da

Kết quả của chương trình chạy là:

http://tailieuhay.com 228

Page 229: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

1.6.1 Các lớp của Java 3D Classes được sử dụng trong

HelloJava3Da

Để hiểu chi tiết hơn về các lớp Java 3D và ví dụ trên chúng ta quan

tâm đến những lớp sau:

Lớp BranchGroup

Đối tượng kiểu này thường được dùng để định dạng đồ thị khung cảnh.

Mỗi instance của BranchGroup là gốc của một đồ thị con. Đối tượng

BranchGroup chỉ được phép là con của đối tượng Locale.

BranchGroup có thể có nhiều con, con của nó có thể là Group hoặc

Leaf.

BranchGroup constructor

BranchGroup ()

Instance của BranchGroup được coi là gốc của một nhánh đồ thị, mỗi

đối tượng BranchGroup chỉ là đối tượng có thể chèn vào tập các đối

tượng của Locales.

http://tailieuhay.com 229

Page 230: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Lớp Canvas3D

Lớp Canvas3D được thừa kế từ Canvas của AWT. Tối thiểu một đối

tượng Canvas3D phải được tham chiếu đến trong một đồ thị nhánh hình

thức của đồ thị khung cảnh.

Canvas3D constructor

Canvas3D(GraphicsConfiguration graphicsconfiguration)

Khởi tạo và thiết lập một đối tượng Canvas3D mới cho phép Java 3D

có thể dựng nên cấu hình đúng đắn của đối tượng

(GraphicsConfiguration). Nó là phần mở rộng của lớp AWT Canvas.

Lớp Transform3D

Đối tượng Transform3D đại điện cho việc biến hình của hình học 3D

như dịch và quay. Những đối tượng này thường chỉ sử dụng để tạo một

đối tượng TransformGroup. Đầu tiên đối Transform3D được khởi tạo,

có khả năng liên kết với các đối tượng Transform3D khác. Sau đó

TransformGroup được khởi tạo sử dụng Transform3D vừa tạo.

Transform3D Default Constructor

Mội đối tượng tổng quan khi thay đổi hình dáng thông qua một ma

trận 4x4 với các điểm thực. Đối tượng Transform3D không được sử dụng

trong đồ thị khung cảnh. Nó chỉ được dùng để chỉ ra sự biến hình của một

đối tượng TransformGroup.

Transform3D()

Tạo đối tượng Transform3D mà đại diện cho ma trận ban đầu (không

có biến đổi)

Một đối tượng Transform3D có thể đại diện cho tịnh tiến, quay, biến

hình theo quy mô,hoặc là kết hợp các phương pháp trên lại. Khi có hiện

tượng quay, góc được thể hiện dưới dạng radians. Một vòng quay đầy đủ

http://tailieuhay.com 230

Page 231: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

là 2 PI radians. Một cách để chỉ ra góc quay là sử dụng hằng Math.PI, nếu

không thì có thể chỉ ra góc quay chính xác.

Các phương thức của Transform3D

Đối tượng Transform3D đại diện cho các phép biến đổi hình học như

quay,dịch phóng lớn thu nhỏ. Transform3D là một trong số it các lớp

không trực tiếp sử dụng trong đồ thị khung cảnh. Việc biến hình do

Transform3D điều khiển đều được tác động lên đối tượng

TransformGroup mà được sử dụng trên đồ thị khung cảnh.

void rotX(double angle)

Phép quay với trục X ngược chiều kim đồng hồ, với góc (angle) là giá

trị radian.

void rotY(double angle)

Phép quay với trục Y ngược chiều kim đồng hồ, với góc (angle) là giá

trị radian.

void rotZ(double angle)

Phép quay với trục Z ngược chiều kim đồng hồ, với góc (angle) là giá

trị radian.

void set(Vector3f translate)

Tạo giá trị biến đổi của ma trận cho giá trị của tham số Vertor3f, và

tạo các thành phần khác của ma trận nếu việc biến hình dựa trên ma trận.

Lớp TransformGroup

Đây là lớp con của lớp Group, mỗi instance của TransformGroup

được sử dụng để tạo đồ thị khung cảnh và có một tập các đối tượng nút

con. Đối tượng TransformGroup giữ giá trị biến hình. Việc biến hình

thường được tạo trên đối tượng Transform3D vốn không phải là một đối

tượng của đồ thị khung cảnh.

TransformGroup Constructors

http://tailieuhay.com 231

Page 232: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

TransformGroup()

Khởi tạo và thiết lập một đối tượng TransformGroup sử dụng phép

biến đổi đồng nhất

TransformGroup(Transform3D t1)

Khởi tạo và thiết lập một đối tượng TransformGroup từ một đối tượng

Transform3D

Tham số: t1 – đối tượng Transform3D

Phép biến hình lưu trong đối tượng Transform3D được copy vào một

đối tượng TransformGroup khi đối tượng TransformGroup được tạo hoặc

bằng cách sử dụng phương thức Transform ().

TransformGroup setTransform()

void setTransform(Transform3D t1)

Lập thành phần biến hình của TransformGroup cho giá trị của phép

biến hình trước đó

Tham số: T1 – phép biến hình cần sao chép

Lớp Vertor3f

Là lớp toán học trong gói javax.vecmath để định ra một vertor sử

dụng 3 điểm số thực. Các đối tượng vertor thường được sử dụng để chỉ ra

phép biến hình trong hình học. Đối tượng Vertor3f không được sử dụng

trực tiếp trong cấu trúc của đồ thị khung cảnh. Chúng thường được sử

dụng để chỉ ra các đặc đính biến đổi.

Vector3f Constructors

Vector3f()

Tạo và thiết lập các giá trị Vertor3f cho (0,0,0)

Vector3f(float x, float y, float z)

Tạo và thiết lập các giá trị Vertor3f cho (x,y,z)

ColorCube

http://tailieuhay.com 232

Page 233: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

ColorCube Constructors

Package: com.sun.j3d.utils.geometry

Là một hình lập phương các mặt có các màu khác nhau, được mở

rộng từ lớp Shape3D, từ đó là một nút lá. ColorCube rất dễ sử dụng khi

đưa vào trông một môi trường ảo.

ColorCube ()

Tạo một hình lập phương với kích thước mặc định, vị trí ở 1 mét cách

mỗi trục tọa xyz

ColorCube(double scale)

Tạo nên hình lập phương có kích thước được định ra bởi các

giá trị cho trước.

1.7 Quay hình lập phương

Để quay hình lập phương chúng ta vừa tạo thì bước đầu tiên là tạo

phép biến hình mong muốn sử dụng đối tượng Transform3D. Đoạn mã

1-5 đưa ra một đối tượng Transform3D trong đồ thị khung cảnh để quay

hình lập phương quanh trục x. Do đó phép biến hình đầu tiên là quay. Đối

tượng Transform3D được tạo ra ở dòng 6, sử dụng phương thức rotX() ở

dòng 8. Đối tương TransformGroup sau đó được tạo giữ thông tin quay

ở dòng thứ 10.

tham số chỉ ra phép quay này:là trục và góc quay. Trong đó góc quay

được xác định thông qua tham số đầu vào. Đối tượng Transform3D được

tạo xong thì được sử dụng để tạo đối tượng TransformGroup là

objRotate. Đối tượng Transform3D được sử dụng trong đồ thị khung

cảnh đối tượng objRotate sau đó lấy đối tượng ColorCube làm con của

nó. Đến lượt objRoot lại lấy objRotate làm con.

public BranchGroup createSceneGraph() {

http://tailieuhay.com 233

Page 234: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

// Create the root of the branch graph

BranchGroup objRoot = new BranchGroup();

// rotate object has composited

transformation matrix

Transform3D rotate = new Transform3D();

Transform3D tempRotate = new Transform3D();

rotate.rotX(Math.PI/4.0d);

tempRotate.rotY(Math.PI/5.0d);

rotate.mul(tempRotate);

TransformGroup objRotate = new

TransformGroup(rotate);

objRoot.addChild(objRotate);

objRotate.addChild(new ColorCube(0.4));

// Let Java 3D perform optimizations on this

scene graph.

objRoot.compile();

return objRoot;

}

Như vậy bên đồ thị nhánh nội dung có các đối tượng như hình dưới,

chú ý là đối tượng BranchGroup bao giờ cũng là con của một Locale.

http://tailieuhay.com 234

Page 235: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

1.7.1 Sự kết hợp của các phép biến hình: HelloJava3Db

Trong trường hợp có nhiều phép biến hình đồng thời xảy ra, ở ví dụ

của chúng ta là sẽ có 2 phép biến hình đồng thời, sẽ được chỉ trên một đối

tượng quan sát duy nhất. 2 phép biến đổi có thể thông qua một ma trận

biến đổi và được giữ bởi một đối tượng TransformGroup.

Trong ví dụ hình 1-6 chúng ta quan sát dưới đây thực hiện 2 phép

quay trên 2 trục x và y. 2 đối tượng Transform3D với mỗi phép quay

được tạo ra ở dòng 6 và 7. Sau đó 2 phép quay riêng rẽ này được chỉ ra

trên 2 đối tượng TransformGroup (dòng 9 và 10). Sau đó các phép quay

được nối lại với nhau bằng các nhân đối tượng

Dưới đây là đồ thị khung cảnh và kết quả chạy chương trình

Kết quả:

http://tailieuhay.com 235

Page 236: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

1.8 Khả năng và hoạt động

Đồ thị khung cảnh được tạo bởi chương trình Java 3D có thể sử dụng

trực tiếp trong việc dựng hình, tuy nhiên mô tả của nó lại không hiệu quả.

Với một miêu tả tốt hơn của môi trường ảo sẽ tăng cường khả năng dựng

hình rất nhiều.

1.8.1 Dịch các nội dung

Đối tượng BranchGroup có một phương thức dịch. Phương thức này

chuyển toàn bộ đồ thị nhánh dưới thành các mô tả Java 3D trong của đồ

thị nhánh. Thêm vào đó, những mô tả bên trong này có thể tối ưu hóa theo

cách này hay cách khác.

Một trong những cách đó là, kết hợp TransformGroups với đường đi đồ

thị khung cảnh . Ví dụ nếu một đồ thị khung cảnh có 2 đối tượng

TransformGroup trong một mối liên hệ cha con chũng có thể đại diện

bằng một đối tượng TransformGroup. Một cách khác là liên kết đối

tượng Shape3D vốn có mối liên hệ vật lí tĩnh.

Hình 1-16 dưới đây đưa ra một mô tả mới hiệu quả hơn.

http://tailieuhay.com 236

Page 237: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

1.8.2 Khả năng

Một khi đồ thị nhánh được làm cho sống và dịch, hệ thống dựng hình

của Java 3D chuyển đồ thị nhánh sang một mô tả bên trong hiệu quả hơn,

qua đó cũng tăng cao hiệu năng dựng hình.

Việc biến đổi qua mô tả bên trong có những tác động khác nhau. Một

trong số đó là cố định giá trị biến hình và các đối tượng trong đồ thị

khung cảnh. Trừ phi có chỉ ra chi tiết của chương trình, thì sẽ không có

khả năng thay đổi giá trị của các đối tượng đồ thị khung cảnh sau khi

chúng “sống”.

Có những trường hợp một chương trình vẫn cần khả năng thayđỏi giá

trị của chúng trong một đối tượng đồ thị khung cảnh sau khi nó “sống”.

Ví dụ như việc thay đổi giá trị của một đối tượng TransformGroup tạo

hoạt họa. Một danh sách các tham số có thể truy cập được và khi đó

người ta gọi là năng lực (capability) của một đối tượng.

Mỗi đối tượng SceneGraphObject có một tập các bit năng lực. Giá

trị của các bit này xác định khả năng có thể tồn tại cho đối tượng sau khi

http://tailieuhay.com 237

Page 238: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

nó được dịch hay sống. Tập các năng lực này biến đổi khác nhau trên các

lớp.

SceneGraphObject Methods

SceneGraphObject là lớp gốc thường được sử dụng để tạo một đồ thị

khung cảnh bao gồm cả Group, Leaf và NodeComponent.

void clearCapability(int bit)

Xóa các bit khả năng

boolean getCapability(int bit)

Phục hồi.

Như trong một ví dụ đã nói, để có thể đọc được giá trị biến hình đại

diện cho một đối tương TransformGroup, thì các khả năng của nó phải

được thiết lập trước khi hoặc nó được dịch hoặc trở nên sống.

Trong phần tới, các hoạt họa có thể được tạo ra tùy theo các thời gian

khác nhau của phép biến hình. Muốn có điều này TransformGroup phải

có tập khả năng ALLOW_TRANSFORM_WRITE trước khi nó được

dịch hoặc sốngViệc điều khiển khẳ năng truy cập đến các lĩnh vực khác

của đối tượng TransformGroup cũng như vậy. Đối tượng

TransformGroup.

TransformGroup Capabilities

khả năng dưới đây là một trong những khả năng được định nghĩa bởi

TransformGroup. TransformGroup thừa kế rất nhiều bit khẳ năng của lớp

tiền bối của nó là Group và Node. Các khả năng như set,reset hay retrieve

được địng nghĩa ở SceneGraphObject.

ALLOW_TRANSFORM_READ

Chỉ ra các nút cho phép truy cập tới thông tin biến hình của đối tượng

của nó.

ALLOW_TRANSFORM_WRITE

Cho phép ghi tới thông tin biến hình của đối tượng của nó.

http://tailieuhay.com 238

Page 239: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Group Capabilities

TransformGroup thừa kế các khả năng từ các lớp cha của nó.

ALLOW_CHILDREN_EXTEND

Thiết lập khả năng cho phép con có thể thêm vào nut Group sau khi nó

được dịch hoặc sống.

ALLOW_CHILDREN_READ

Thiết lập khả năng cho phép các tham chiếu đến con của nút Group có thể

được đọc sau khi nó được dịch hoặc sống.

ALLOW_CHILDREN_WRITE

Thiết lập khả năng cho phép them chiếu đến các con của nút Group để ghi

hay thay đổi sau khi nó được dịch hoặc sống.

1.9 Thêm vào các hành vi animation

Trong Java 3D, Behavior là một lớp quan trọng về animation với các

tương tác của các đối tượng. Người lập trình có thể thay đổi bất cứ thuộc

tính nào của một đối tượng quan sát.

Sự khác nhau giữa animation và interaction là khi nào thuộc tính được

kích hoạt khi phàn hồi qua thời gian hay phản hồi qua các hành động của

người sử dụng.

Với mỗi đối tượng quan sát trong một môi trường ảo có thể có những

hành vi sẵn có của nó. Thực tế thì thường có nhiều hành vi . Để chỉ ra một

hành vi cho một đối tượng quan sát, người lập trình tạo một đối tượng mà

chỉ ra hành vi đó, thêm vào các đối tượng quan sát tới đồ thị khung cảnh

và xây dựng những tham chiếu giữa các đối tượng đồ thị và các đối tượng

hành vi.

Trong một môi trường ảo với rất nhiều hành vi, thì cần một lượng tính

toán rất lớn. Khi cả việc dựng hình và các hành vi sử dụng cùng chung

nhiều process, thì thật khó có thể nâng cao hiệu năng hoạt động được.

http://tailieuhay.com 239

Page 240: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Java 3D cho phép lập trình viên có thểm quản lí vấn đề này bằng cách

chỉ ra vị trí của một hành vi. Khu vực này được gọi là scheduling region.

Một hành vi không hoạt động trì phi activation volume của

ViewPlatform phân cắt một vùng danh mục đó. Nói cách khác,không có

chỗ trong rừng để lá rơi thì sẽ không có lá rơi. Tính năng vùng danh mục

làm cho Java 3D hiệu qua hơn trong việc nắm bắt một môi trường ảo với

rất nhiều hành vi.

Hình 1-7 chỉ ra các bước bao gồm cả việc định ra một animation với

một đối tượng thêm vào.

1. Create a target TransformGroup

Set the ALLOW_TRANSFORM_WRITE capability

2. Create an Alpha5 object

Specify the time parameters for the alpha

3. Create the interpolator object

Have it reference the Alpha and TransformGroup objects

Customize the behavior parameters

4. Specify a scheduling region

Set the scheduling region for the behavior

5. Make the behavior a child of the TransformGroup

1.9.1 Định nghĩa các hành vi animation

Một hành vi có thể thay đổi trên địa điểm (PositionInterpolator),

hướng (RotationInterpolator), kích cỡ(ScaleInterpolator), màu

sắc(ColorInterpolator) hoặc độ trong suốt(TransparencyInterpolator) của

một đối tượng quan sát. Như đã nói ở phía trên Interpolator là các lớp

hành vi được định nghĩa trước. Tất cả các hành vi nói trên đều có thể sử

dụng mà không cần định trước tuy nhiên việc định trước cho phép việc

http://tailieuhay.com 240

Page 241: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

tạo các hành vi trở nên dễ dàng hơn rất nhiều. Các lớp định trước này

cung cấp các hành động khác nhau thậm chí kết nối các hành động đó.

Lớp RotationInterpolator

Lớp này sử dụng để chỉ ra một hành vi quay của một đối tượng quan sát

hoặc một nhóm các đối tượng như vậy. Một đối tượng

RotationInterpolator thay đổi một đối tượng TransformGroup qua một

phép quay khi phản hồi giá trị của một đối tượng Alpha. Khi giá trị của

đối tượng Alpha thay đổi qua thời gian việc thay đổi phép quay cũng dễ

dàng. Một đối tượng RotationInterpolator rất linh động trong việc chỉ ra

trục quay, góc quay ban đầu góc quay kết thúc.

RotationInterpolator Constructor

RotationInterpolator(Alpha alpha, TransformGroup target)

Hàm khởi tạo này sử dụng các giá trị mặc định cho một vài tham số

của hành vi mặc định để khởi tạo một phép quay đầy đủ trên trục y, bằng

đối tượng TransformGroup được chỉ ra bằng hành vi mặc định.

Tham số:

alpha – thời gian hàm thay đổi để tham chiếu

target – đối tượng TransformGroup cần thay đổi

5 Alpha là một lớp trong Java 3D để tạo ra các hàm biến đổi thời gian.

1.9.2 Các hàm biến đổi về thời gian: Ánh xạ một hành vi với thời gian

Việc ánh xạ một đối tượng với thời gian thông qua một đối tượng Alpha.

Lớp Alpha

Lớp này được sử dụng để tạo hàm biến đổi theo thời gian. Lớp này

cung cấp các giá trị giữa 0 và 1,. Giá trị này phụ thuộc vào thời điểm và

thông số của đối tượng Alpha. Đối tượng Alpha thường được sử dụng

với các đối tượng hành vi sẵn có để thực hiện các thay đổi hoạt họa của

các đối tượng quan sát.

http://tailieuhay.com 241

Page 242: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Có 10 tham số cho Alpha, do đó giúp cho người lập trình sử dụng

linh động. Mỗi instance của đối tượng Alpha có thể dễ dàng kết hợp với

một hành vi để đưa ra các phép quay đơn giản, cánh bay, cửa mở,hay bắn

rocket.

Alpha Constructor

Alpha()

Liên tục lặp với thời gian định kì là 1 giây

Alpha(int loopCount, long increasingAlphaDuration)

Hàm khởi tạo này lấy loopCount và increasingAlphaDuration như là

tham số và đăng kí giá trị mặc định cho tất cả các tham số còn lại. Đối

tượng Alpha tạo ra cung cấp giá trị khởi đầu từ 0 lên 1. Điều này lặp đi

lặp lại nhiều lần thông qua loopCount. Nếu loopCount = -1 đối tượng

alpha lặp đi lặp lại vô hạn.

Tham số:

loopCount – số lần chạy đối tượng alpha này, giá trị bằng -1 lặp

vô hạn

increasingAlphaDuration – thời gian tính bằng giây giữa bước

nhẩy từ 0 lên 1

1.9.3 Lập danh mục các vùng

Như đã nói ở phần 1-9 mỗi hành vi có một vùng danh mục. Vùng này

quanh các hành vi được thiết lập dựa trên phương thức

setSchedulingBounds của lớp Behavior.

Có rất nhiều cách để định nghĩa vùng danh mục này nhưng cách đơn giản

nhất là tạo đối tượng BoundSphere . Các tùy chọn khác như bounding

box, hoặc bouding polytope.

Behavior setSchedulingBounds method

void setSchedulingBounds(Bounds region)

http://tailieuhay.com 242

Page 243: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Xác định ranh giới cho vùng danh mục của hành vi

Parameters:

region – ranh giới chứa Behavior's scheduling region.

Lớp BoundingSphere

Việc định nghĩa một vùng cầu phải đi đôi với việc chỉ ra điểm trung

tâm và bán kính của nó. Cách thường làm là để tâm của hình cầu ở vị trí

trung tâm là (0,0,0). Bán kính sau đó được lựa chọn đủ sao cho hình cầu

chứa đối tượng quan sát, bao gồm tất cả các vị trí mà đối tượng có thể ở

đó.

Bounding Sphere Constructors

BoundingSphere()

Tạo một hình cầu bao mà tâm ở vị trí (0,0,0) với bán kính bằng 1

BoundingSphere(Point3d center, double radius)

2 tham số lần lượt là

center – tọa độ của tâm trong không gian

radius – bán kính của hình cầu

1.9.4 Ví dụ về hành vi: HelloJava3Dc

Đoạn mã hình 1-7 đưa ra một ví dụ hoàn thiện về việc sử dụng lớp

thêm vào để tạo animation. Animation được tạo trong đoạn mã này là

hình lập phương quay liên tục trong thời gian 4 giây.

Bước đầu tiên của công thức là tạo đối tượng TransformGroup để

sửa đổi tại thời điểm chạy. Đối tượng TransformGroup của môt hành vi

sẵn có phải có khả năng ghi. Đối tượng TransformGroup tên là objSpin

được tạo ở dòng 7. Khả năng của nó được thiết lập ở dòng thứ 8.

http://tailieuhay.com 243

Page 244: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Bước 2 là tạo đối tượng Alpha, rotationAlpha, được sử dụng để xác

định thời gian quay liên tục. 2 tham số chỉ ra trong dòng 16 của đoạn mã

là số vòng lặp và thời gian cho mỗi vòng . Giá trị “-1” của số vòng lặp thể

hiện việc lặp liên tục. Thời gian được tính theo mili giây giá trị 4000 được

sử dụng trong chương trình tương đương với 4 giây. Từ đó hành vi là

quay một lần trên 4 giâys.

Bước 3 là tạo đối tượng thêm vào. Đối tượng quay

RotationInterpolator được tạo ra ở dong 21 và 22. Đối tượng thêm vào

phải tham chiếu đến đối tượng biến hình và alpha. Điều này được mô tả

trong hàm khởi tạo. Trong ví dụ này hành vi mặc định

RotationInterpolator là được sử dụng, để thực hiện phép quay hoàn toàn

quanh trục y.

Bước 4 chỉ ra vùng danh mục. Trong đoạn mã, một đối tượng

BoundingSphere được sử dụng với giá trị mặc định, được tạo ra ở dòng

25. Vùng cầu này là vùng bao quanh của hành vi trong dòng 26.

Cuối cùng là bước 5 trong công thức, biến hành vi thành một con của

TransformGroup trên dòng 27.

public BranchGroup createSceneGraph() {

// Create the root of the branch graph

BranchGroup objRoot = new BranchGroup();

// Create the transform group node and

initialize it to the

// identity. Add it to the root of the

subgraph.

TransformGroup objSpin = new

TransformGroup();

objSpin.setCapability(TransformGroup.ALL

OW_TRANSFORM_WRITE);

http://tailieuhay.com 244

Page 245: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

objRoot.addChild(objSpin);

// Create a simple shape leaf node, add

it to the scene graph.

// ColorCube is a Convenience Utility

class

objSpin.addChild(new ColorCube(0.4));

// Create a new Behavior object that

will perform the desired

// operation on the specified transform

object and add it into

// the scene graph.

Alpha rotationAlpha = new Alpha(-1,

4000);

RotationInterpolator rotator =

new

RotationInterpolator(rotationAlpha, objSpin);

// a bounding sphere specifies a region

a behavior is active

// create a sphere centered at the

origin with radius of 100

BoundingSphere bounds = new

BoundingSphere();

rotator.setSchedulingBounds(bounds);

objSpin.addChild(rotator);

http://tailieuhay.com 245

Page 246: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

return objRoot;

} // end of CreateSceneGraph method

Code Fragment 1-7 createSceneGraph method with RotationInterpolator

Behavior

Đồ thị khung cảnh của chương trình và kết quả chạy trên màn hình.

Kết quả

1.9.5 Phép biến hình và kết hợp các hành vi .Ví dụ: HelloJava3Dd

Tất nhiên chúng ta có thể kết hợp các hành vi với các phép biến hình

quay với ví dụ dưới đây. Trong đồ thị nhánh nội dung có những đối tượng

http://tailieuhay.com 246

Page 247: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

objRotate và objSpin, phân biệt với những phép quay tĩnh và hành vi của

đối tượng hình lập phương.

Đồ thị khung cảnh

public BranchGroup createSceneGraph() {

// Create the root of the branch graph

BranchGroup objRoot = new BranchGroup();

// rotate object has composited

transformation matrix

Transform3D rotate = new Transform3D();

Transform3D tempRotate = new Transform3D();

rotate.rotX(Math.PI/4.0d);

tempRotate.rotY(Math.PI/5.0d);

rotate.mul(tempRotate);

TransformGroup objRotate = new

TransformGroup(rotate);

// Create the transform group node and

initialize it to the

// identity. Enable the TRANSFORM_WRITE

capability so that

// our behavior code can modify it at

runtime. Add it to the

// root of the subgraph.

TransformGroup objSpin = new

TransformGroup();

http://tailieuhay.com 247

Page 248: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

objSpin.setCapability(TransformGroup.ALLOW_TRANSF

ORM_WRITE);

objRoot.addChild(objRotate);

objRotate.addChild(objSpin);

// Create a simple shape leaf node, add it to

the scene graph.

// ColorCube is a Convenience Utility class

objSpin.addChild(new ColorCube(0.4));

// Create a new Behavior object that will

perform the desired

// operation on the specified transform

object and add it into

// the scene graph.

Transform3D yAxis = new Transform3D();

Alpha rotationAlpha = new Alpha(-1, 4000);

RotationInterpolator rotator =

new RotationInterpolator(rotationAlpha,

objSpin, yAxis,

0.0f, (float)

Math.PI*2.0f);

// a bounding sphere specifies a region a

behavior is active

// create a sphere centered at the origin

with radius of 1

http://tailieuhay.com 248

Page 249: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

BoundingSphere bounds = new BoundingSphere();

rotator.setSchedulingBounds(bounds);

objSpin.addChild(rotator);

return objRoot;

} // end of CreateSceneGraph method of

HelloJava3Dd

Kết quả

http://tailieuhay.com 249

Page 250: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

http://tailieuhay.com 250

Page 251: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

CHƯƠNG 2

Tạo các hình

2.1 Hệ tọa độ thế giới ảo

Trong chương 1 ta đã biết với mỗi instance của một lớp

VirtualUniverse có chức năng như một gốc của đồ thị khung cảnh trong

tất cả chương trình Java 3D. Từ khóa virtual universe là chỉ một không

gian ảo 3 chiều trong đó có các đối tượng 3D. Mỗi đối tượng Locale trong

một môi trường ảo thiết lập một thế giới ảo Cartesian. Đối tượng này

tương đương với một con trỏ tham chiếu cho một đối tượng quan sát

trong một môi trường ảo. Với một đối tượng Locale trong

SimpleUniverse có một hệ tọa độ duy nhất.

Hệ tọa độ của môi trường ảo Java 3D là thuận phải tức là trục X

hướng dương bên tay phải, trục Y hướng dương chỉ lên trên, trục Z hướng

dương chỉ vào người nhìn với đơn vị là mét. Hình 2-1 dưới đây chỉ ra

hướng nhìn trong SimpleUniverse.

http://tailieuhay.com 251

Page 252: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

2.2 Visual Object Definition Basics

Phần 2.2.1 giới thiệu lớp Chen code lai cho ro rang ., còn lớp Chen

code lai cho ro rang .được giới thiệu ở phần 2.2.2, sau khi đi vào những

định nghĩa cơ bản về hình học trong gói tiện ích, phần còn lại của chương

này sẽ thảo luận về góc độ hình học và hình dáng của các nút thành phần.

2.2.1 An Instance of Shape3D Defines a Visual Object

Nút đồ thị khung cảnh Shape3D định nghĩa một đối tượng quan sát.

Shape3D là một trong các lớp con của lớp Leaf từ đó đối tượng Shape3D

chỉ có thể là lá trong đồ thị khung cảnh. Đối tượng Shape3D không chứa

thông tin về hình dạng hay màu sắc của một đối tượng quan sát. Thông tin

này được lưu trong đối tượng NodeComponent được chuyển đến bới đối

tượng Shape3D. Một đối tương Shape3D có thể quy vào một nút thành

phần hình học và một nút thành phần giao diện.

Trong đồ thị khung cảnh Hellojava3D ở chương 1, biểu tượng hình tứ

giác dùng để đại diện cho đối tượng ColorCube. Đồ thị khung cảnh trong

hình 2-2 chỉ ra đối tượng quan sát được đại diện bởi một lá Shape3D

(hình tam giác) và 2 NodeComponent (ô van) thay cho hình dạng tứ giác.

http://tailieuhay.com 252

Page 253: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Một đối tượng quan sát có thể định nghĩa bằng cách sử dụng chỉ dối

tượng Shape3D và một nút thành phần hình học. Với tùy chọn này, đối

tượng Shape3D quy cho một nút Appearance. Hàm tạo cho đối tượng

Shape3D cho phép đối tượng Shape3D được tạo mà không cần tham

chiếu của nút thành phần, hoặc chỉ với tham chiếu thành phần hình học,

hoặc cả 2 dạng.

Shape3D Constructors

Shape3D()

Khởi tạo và thiết lập đối tượng Shape3D mà không có nút thành phần

hình học và giao diện

Shape3D(Geometry Geometry)

Khởi tạo và thiết lập chỉ với thành phần hình học

Shape3D(Geometry Geometry, Appearance Appearance)

Khởi tạo và thiết lập chỉ với cả 2 thành phần.

Cho đến khi đối tượng Shape3D không sống hoặc không được dịch

nữa thì tham chiếu nút thành phần có thể thay đổi với các phương thức

dưới đây.

Shape3D Methods

http://tailieuhay.com 253

Page 254: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Đối tượng Shape3D tham chiếu đến đối tượng nút thành phần hình

học và giao diện.

void setGeometry(Geometry Geometry)

void setAppearance(Appearance Appearance)

Shape3D Capabilities

Đối tượng Shape3D thừa kế các khả năng từ SceneGraphObject, Node và

Leaf.

ALLOW_GEOMETRY_READ | WRITE

ALLOW_APPEARANCE_READ | WRITE

ALLOW_COLLISION_BOUNDS_READ | WRITE

2.2.2 Node Components

Đối tượng NodeComponent chứa các định nghĩa chính xác về các

thuộc tính của một đối tượng quan sát. Với mỗi lớp con của

NodeComponent định nghĩa đích xác các thuộc tính quan sát. Hình 2-3

chỉ ra các phần thừa kế của Java 3D API chứa lớp NodeComponent và

lớp trước nó. Phần 2-5 sẽ giới thiệu về NodeComponent Germetry. Phần

2-6 giới thiệu về Appearance NodeComponent.

http://tailieuhay.com 254

Page 255: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

2.2.3 Defining Visual Object Classes

Cùng một đối tượng quan sát sẽ thường xuất hiện nhiều lần trong một

môi trường ảo. Điều đó gợi ý cho việc định nghĩa một lớp để tạo đối

tượng quan sát thay vì thiết lập mỗi đối tượng quan sát riêng lẻ. Có nhiều

cách để thiết kế một lớp để định nghĩa một đối tượng quan sát.

Tổ chức của lớp VisualObject cũng giống như lớp ColorCube mà

trong đó nó được thừa kế từ đối tượng VisualObject. Lớp VisualObject

là một điểm đề nghị đầu tiên cho việc định nghĩa các lớp nội dung để sử

dụng trong xây dựng đồ thị khung cảnh. Mỗi người lập trình Java 3D sẽ

tùy biến lớp VisualObject theo ý của họ. Chúng ta có thêm xem một ví

dụ đầy đủ về lớp ColorCube trong gói com.sun.j3d.utils.Geometry .

Sử dụng Shape3D như là lớp cơ bản cho việc tạo một đối tượng quan

sát cho phép dễ dàng sử dụng trong chương trình Java 3D. Lớp đối tượng

quan sát có thể được sử dụng dễ dàng như lớp ColorCube trong ví dụ

HelloJava3D từ chương, Hàm tạo có thể được gọi và những đối tượng

http://tailieuhay.com 255

Page 256: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

mới nhất được thêm vào như là con của một vài Group trên một dòng của

đoạn mã. Trong đoạn mã dưới đây objRoot là một instance của Group.

Đoạn mã này tạo một VisualObject và thêm nó vào như là cong của

objRoot trong đồ thị khung cảnh.

objRoot.addChild(new VisualObject());

Hàm tạo của VisualObject tạo đối tượng quan sát bằng cách tạp một

đối tượng Shape3D tham chiếu đến NodeComponent được tạo bởi

phương thức createGeometry()và createAppearance().

Phương thức createGeometry()tạo một nút thành phần hình học được

sử dụng trong đối tượng quan sát. Phương thức createAppearance()có

trách nhiệm cho việc tạo NodeComponent để định nghĩa bề ngoài cho

đối tượng quan sát.

Hàm tạo của VisualObject tạo đối tượng quan sát bằng cách định

nghĩa một lớp container không không thừa kế tù Java 3D API. Trong thiết

kế này lớp đối tượng quan sát sẽ chứa một Group Node hoặc Shape3D

như là gốc của một nhánh đồ thị nó định nghĩa. Lớp này phải định nghĩa

phương thức để trả về một tham chiếu đến gốc. Công nghệ này có thể có

nhiều việc hơn nhưng lại dễ dàng để hiểu. Ngoài ra còn có các lớp khác

trong gói về hình học như Box, Cone, Cylinder và Sphere. Mỗi lớp mở

rộng từ Primitive, vốn mở rộng từ Group.

2.3 Các lớp tiện ích hình học

Phần này bao gồm tất cả các lớp tiện ích dùng để tạo hình hộp, hình

nón, hình trụ, và hình cầu cơ bản. Các hình cơ bản này là cách dễ thứ hai

để tạo một môi trường ảo. Còn cách dễ nhất đương nhiên là dùng hình lập

phương.

Các lớp cơ bản này cung cấp cho người lập trình tính linh động hơn

rất nhiều so với lớp hình lập phương màu đưa ra. Lớp ColorCube định

http://tailieuhay.com 256

Page 257: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

nghĩa về mặt hình học và màu trên các nút thành phần hình học. Kết quả

là mọi thứ xung quanh nó trở nên cố định trừ kích thước của nó. Kích

thước hình lập phương chỉ được xác định khi đối tượng được tạo.

Một lớp cơ bản được gọi là linh động nếu nó xác định hình dạng mà

không phải xác định màu sắc đi kèm. Trong các lớp tiện ích cơ bản hình

học, người lập trình không thể thay đổi hình học nhưng có thể thay đổi bề

ngoài. Các lớp này cung cấp cho người lập trình tính linh động khi có

nhiều instance trên một hình cơ bản ở đó mỗi phần có một diện mạo khác

nhau bằng cách tham chiếu đến các NodeComponent Appearance khác

nhau.

Các lớp này được định nghĩa trong gói com.sun.j3d.utils.Geometry.

Lớp cơ bản nhất của các lớp này là lớp Primitive, dưới đây là hình2-4 thể

hiện cây thừa kế các lớp này.

2.3.1 Box

Lớp gốc Box (hình hộp) tạo đối tượng quan sát hình hộp 3D. Chiều

dài chiều rộng chiều cao mặc định là 2 met, với tâm ở gốc. Chiều dài

http://tailieuhay.com 257

Page 258: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

chiều rộng chiều cao được xác định trong thời gian đối tượng được tạo.

Tất nhiên TransformGroup, dọc theo đường đồ thị khung cảnh tới Box,

có thể được sử dụng để thay đổi vị trí và hướng của các instance của Box

và các đối tượng quan sát khác.

Box Constructors

Package: com.sun.j3d.utils.Geometry

Box mở rộng từ Primitive, một lớp khác trong gói

com.sun.j3d.utils.Geometry

Box()

Thiết lập một hình hộp với mặc định chiều cao chiều dài chiều rộng là 2

met, tâm ổ gốc.

Box(float xdim, float ydim, float zdim, Appearance Appearance)

Thiết lập hình hộp với hướng, bề ngoài, và tâm ở gốc.

Box, Cone, and Cylinder Methods

Package: com.sun.j3d.utils.Geometry

Các phương thức này được định nghĩa trong mối lớp cơ bản: Box, Cone,

và Cylinder. Các lớp cơ bản này được kết hợp từ các đối tượng Shape3D

trong một nhóm.

Shape3D getShape(int id)

Lấy một trong những mặt Shape3D từ lớp cơ bản chứa hình học và bề

mặt.Đối tượng Box, Cone, và Cylinder được tập hợp từ nhiều đối tượng

Shape3D, với nút thành phần hình học của nó. Giá trị đưa ra để xác định

nút thành phần nào được lấy.

void setAppearance(Appearance Appearance)

http://tailieuhay.com 258

Page 259: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

2.3.2 Cone

Hình nón định nghĩa đối tượng hình nón, bịt nắp tâm tại gốc tọa độ

với trục song song với trục Y.

Bán kính là 1 và chiều cao là 2. Tâm của hình nón được coi như là

tâm của hình bao củanó hơn là tâm thực.

Cone Constructors

Package: com.sun.j3d.utils.Geometry

Cone()

Hàm khởi tạo mặc định với bán kính là 1, đường kính là 2.

Cone(float radius, float height)

Hàm khởi tạo với 2 tham số bán kính và chiều cao

2.3.3 Cylinder

Lớp Cylinder (hình trụ) tạo một đối tượng hình trụ bị bịt tâm ở gốc

với trục dọc theo trục Y. Giá trị mặc định là bán kính là 1, chiều cao là 2.

Cylinder Constructors

Package: com.sun.j3d.utils.Geometry

Cylinder()

Hàm khởi tạo mặc định với bán kính là 1, chiều cao là 2.

Cylinder(float radius, float height)

Khởi tạo với tham số bán kính và chiều cao.

Cylinder(float radius, float height, Appearance Appearance)

Khởi tạo với bán kính, chiều cao và bề mặt.

http://tailieuhay.com 259

Page 260: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

2.3.4 Sphere

Lớp này tạo đối tượng hình cầu tâm ở gốc, bán kính mặc định là 1.

Sphere Constructors

Package: com.sun.j3d.utils.Geometry

Sphere()

Hàm khởi tạo mặc định, bán kính là 1.

Sphere(float radius)

Hàm khởi tạo với bán kính xác định

Sphere(float radius, Appearance Appearance)

Hàm khởi tạo với bán kính, bề mặt cho trước.

Sphere Methods

Package: com.sun.j3d.utils.Geometry

Shape3D getShape()

Lấy đối tượng Shape3D chứa dạng hình học và bề mặt.

Shape3D getShape(int id)

Phương thức này cũng được sử dụng với các lớp cơ bản phía trên. Tuy

nhiên 1 Sphere chỉ có một đối tượng Shape3D nên id =1.

void setAppearance(Appearance Appearance)

Lập bề mặt cho hình cầu.

http://tailieuhay.com 260

Page 261: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

2.3.5 More About Geometric Primitives

Các cơ bản chưa được định nghĩa về màu sắc. Các hình không định

nghĩa màu mà thừa kế màu từ nút thành phần bề mặt của nó. Nếu không

có tham chiếu đến nút thành phần bề mặt, đối tượng quan sát sẽ có màu

mặc định là trắng.

2.3.6 ColorCube

Lớp ColorCube được trình bày ở đây thể hiện sự tương phản với các

lớp hình cơ bản như Box, Cone, Cylinder và Sphere. Lớp này mở rộng

theo hướng thừa kế khác, nó là lớp con của Shape3D. Cây thừa kế được

chỉ ra trong hình 2-5.

Lớp này cũng là lớp duy nhất cung cấp với Java 3D API cho phép

người lập trình bỏ qua các phần như màu sắc và ánh sáng. Vì lí do này

nên nó thường được dùng để nhanh chóng tạo ra một đồ thị khung cảnh

để kiểm thử hình nguyên mẫu.

2.3.7 Example: Creating a Simple Yo-Yo From Two Cones

Phần này giới thiệu ví dụ đơn giản qua việc sử dụng lớp Cone, mục

tiêu của chương trình là dựng nên một con yo-yo. Chúng ta phải dùng 2

http://tailieuhay.com 261

Page 262: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

hình nón để tạo nên được Yo-Yo. Các hành của Java 3D API cho phép

yo-yo có thể di chuyển lên xuống nhưng trong phần này sẽ không trình

bày đến.

Hình 2-5 dưới đây hiển thị đồ thị khung cảnh của chương trình thiết

kế lớp ConeYoyo và ConeYoyoApp. Ví trị mặc định của một đối tượng

Cone thông qua hình bao của nó tâm ở gốc. Hướng của hình nón là hướng

dương, đỉnh nằm trên trục Y. Yo-yo định ra 2 hình nón mà được quay

quanh Z và dịch theo trụ X để đỉnh của chúng trùng nhau ở gốc. Những

kết hợp của phép quay và dịch cho phép ghép các đối tượng hình nón với

nhau.

Nhánh đồ tị này bắt đầu bằng đối tượng BranchGroup được tạo bơi

ConeYoyo, đường của đồ thị khung cảnh tới mỗi đối tượng Cone bắt đầu

bằng đối tượng TransformGroup chỉ ra phép dịch, theo đó là

TransformGroup xác định phép quay và hủy đối tượng Cone.

http://tailieuhay.com 262

Page 263: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Một vài đồ thị khung cảnh có thể đại diện cho cùng một môi trường

ảo. Trong ví dụ hình 2-6 có một vài thay đổi, thay đổi đầu tiên là đối

tượng BranchGroup có con là ConeYoyo và được chèn vào đối tượng

ConeYoyo trực tiếp trên Locale. BranchGroup này sau đó là để thêm vào

các đối tượng quan sát trong tương lai tới thế giới quan sát. Một thay đổi

khác là kết nối 2 đối tượng TransformGroup trong đối tượng

ConeYoyo. Phép biến đổi được mô tả đơn giản như dưới đây.

Nút Shape3D của đối tượng Cone tham chiếu đến nút thành phần

hình học. Đối tượng Shape3D của Cone là con của Group trong Cone.

Khi đối tượng Cone thừa kế từ Group, thì Cone còn lại không thể sử dụng

thêm lần nào nữa trong đồ thị khung cảnh. Hình 2- đưa ra một ví dụ về

thông báo lỗi khi cố gắng sử dụng cùng một đối tượng Cone trong đồ thị

khung cảnh. Lỗi này không tồn tại trong ví dụ chương trình đưa ra.

Hình 2-8 chỉ ra một hình ảnh được dịch với ví dụ vừa qua. Lớp

ConeYoyo được sửa lại như trong đoạn mã 2-2.

http://tailieuhay.com 263

Page 264: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Dòng 14 đến 21 tạo các đối tượngcủa ½ đồ thị yo-yo . Dòng 23 đến

25 tạo mối quan hệ giữa các đối tượng. Tiến trình này được lặp lại trên

một nửa đồ thị còn lại từ dòng 27 đến dòng 38.

Dòng 12 tạo yoyoApear, một nút thành phần bề mặt với giá trị mặc

định được sử dụng bởi đối tượng Cone. Dòng 21 đến 34 thiết lập bề mặt

cho 2 hình nón.

// //////////////////////////////////////

////

//

// create Shape3D with geometry and

appearance

// the geometry is created in method

yoyoGeometry

// the appearance is created in method

yoyoAppearance

//

public ConeYoyo() {

yoyoBG = new BranchGroup();

Appearance app = new Appearance();

// rotate object has composited

transformation matrix

Transform3D rotate = new

Transform3D();

Transform3D translate = new

Transform3D();

http://tailieuhay.com 264

Page 265: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

translate.set(new Vector3f(0.1f,

0.0f, 0.0f));

TransformGroup yoyoTGT1 = new

TransformGroup(translate);

yoyoBG.addChild(yoyoTGT1);

rotate.rotZ(Math.PI / 2.0d);

TransformGroup yoyoTGR1 = new

TransformGroup(rotate);

Cone cone1 = new Cone(0.6f, 0.2f);

cone1.setAppearance(app);

yoyoTGR1.addChild(cone1);

yoyoTGT1.addChild(yoyoTGR1);

translate.set(new Vector3f(-0.1f,

0.0f, 0.0f));

TransformGroup yoyoTGT2 = new

TransformGroup(translate);

yoyoBG.addChild(yoyoTGT2);

rotate.rotZ(-Math.PI / 2.0d);

TransformGroup yoyoTGR2 = new

TransformGroup(rotate);

Cone cone2 = new Cone(0.6f, 0.2f);

cone2.setAppearance(app);

yoyoTGR2.addChild(cone2);

yoyoTGT2.addChild(yoyoTGR2);

http://tailieuhay.com 265

Page 266: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

yoyoBG.compile();

} // end of ConeYoyo constructor

Code Fragment 2-2 Class ConeYoyo From ConeYoyoApp.java Example

Program

Advanced Topic: Geometric Primitive – Các dạng hình học cơ bản

Cây thừa kế trong hình 2-4 chỉ ra Primitive là lớp cha của tất cả các

lớp Cone, Box, Cylinder, và Spheres. Nó định nghĩa một lượng lớn các

trường và phương thức cũng như giá trị mặc định của các trường. Mỗi lớp

con của Primitive có một hàm khởi tạo cho phép thiết lập các cờ khi đối

tượng được xây dựng. Ví dụ như lớp Sphere có hàm khởi tạo Sphere (int).

Danh sách các cờ ở dưới đây:

GEOMETRY_NOT_SHARED Normals are generated along with the

positions.

GENERATE_NORMALS_INWARD Normals are flipped along the

surface.

GENERATE_TEXTURE_COORDS Texture coordinates are generated.

GEOMETRY_NOT_SHARED The Geometry created will not be

shared by another

node.

Lớp này cũng cho phép chia sẻ nút thành phần hình học giữa các instance

của một primitive với cùng một kích cỡ. Mặc định tất các các primitives

là cùng một kích thước, chia sẻ một nút thành phần hình học. Một ví dụ

của một trường được định nghĩa trong lớp Primitive là giá trị integer

GEOMETRY_NOT_SHARED. Trường này chỉ ra dạng hình học được

sẽ không được chia sẻ với những instance khác. Thiết lập cờ này để tránh

http://tailieuhay.com 266

Page 267: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

việc chia sẻ giữa các primitive của cùng một tham số (chẳng hạn với hình

cầu bán kính 1).

Cone myCone = new Cone(Primitive.GEOMETRY_NOT_SHARED);

Primitive Methods

Package: com.sun.j3d.utils.Geometry

Primitive mở rộng từ Group và là lớp cha của của các lớp Box, Cone,

Cylinder và Sphere.

public void setNumVertices(int num)

Thiết lập tổng số đỉnh trong primitive này.

void setAppearance(int partid, Appearance Appearance)

Thiết lập bề mặt của các phần con. Các đối tượng Box, Cone, Cylinder

được gom lại với hơn một đối tượng Shape3D, mỗi thứ có tiềm năng sử

dụng nút thành phần bề mặt của nó. Giá trị cho mỗi phần này được xác

định khi mỗi nút thành phần bề mặt được thiết lập.

void setAppearance()

Thiết lập bề mặt chính của primitive (tất cả các phần con) tới bề mặt trắng

mặc định.

2.4 Các lớp toán học

Để tạo đối tượng quan sát, cần cả lớp hình học và các lớp con của nó.

Rất nhiều lớp con của lớp hình họcmo tả dựa trên các hình cơ bản véc tơ,

như điểm đường thẳng và đa giác. Các lớp con của lớp hình học sẽ được

mô tả trong phần 2-5 nhưng trước đó chúng ta quan tâm đến các lớp toán

http://tailieuhay.com 267

Page 268: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

học như điểm, màu, vertor và textcord dùng để định nghĩa các dữ liệu liên

đỉnh.

Chú ý rằng với mỗi kí hiệu có “*” đằng sau đại diện cho một lớp tên.

Ví dụ Tuple* tương đương với Tuple2f, Tuple2d Tuple3i….

Trong đó các chữ số đằng sau chỉ ra số thành phần trong tuple, còn

các chữ cái nhỏ cuối cùng đại diện cho kiểu. ‘f’ chỉ float, ‘d’ chỉ double,

‘b’ đại diện cho byte, ‘i’ là integer. Vì thế lớp Tuple3f là một lớp mà quản

lí 3 giá trị điểm thực.

Tất cả các lớp toán học này đều nằm trong gói javax.vecmath.* Gói

này định nghĩa một số lớp Tuple như là các lớp trừu tượng. Rất nhìều các

lớp hữu ích thừa kế từ các lớp này. Dưới đây là hình 2-9 cây thừa kế.

http://tailieuhay.com 268

Page 269: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Mỗi đỉnh của một đối tượng quan sát có thể chỉ ra tới 4 đối tượng

trong javax.vecmath đại diện cho tọa độ, màu bề mặt bình thường và bề

mặt tọa độ. Các lớp thường được sử dụng:

Point* (for coordinates)

Color* (for colors)

Vector* (for surface normals)

TexCoord* (for texture coordinates, see Chapter 7)

Tuple2f Constructors

Chú ý rằng tọa độ (Point* object) là cần thiết để địa chỉ mỗi đỉnh.

Các dữ liệu khác là tùy chọn ,tùy thuộc vào các hình cơ bản được dựng

hình như thế nào. Ví dụ như một màu có thể được định nghĩa tại mỗi đỉnh

và các màu của các hình cơ bản là được thêm vào giữu các màu tại các

đỉnh. Nếu ánh ánh sáng được thiết lập, bề mặt bình thường (Vertor*

object) là cần thiết. Nếu bề mặt ánh xạ được thiết lập thì tọa độ bề mặt

cũng cần thiết vậy.

Tât cả các lớp cần thiết được trình bày bên dưới đây.

Tuple2f Constructors

Package: javax.vecmath

Các lớp Tuple* thường không được sử dụng trực tiếp trong chương trình

Java 3D nhưng cung cấp nền tảng cho Point*, Color*, Vector*,

TexCoord*. Ví dụ như Tuple2f cung cấp cơ sở cho Point2f, Color2f, và

TexCoord2f. Các hàm khởi tạo dưới đây đều đúng với các lớp con tương

tụ như Tuple3f và Tuple4f.

Tuple2f()

Khởi tạo và thiết lập đối tượng Tuple với tọa độ (0,0).

Tuple2f(float x, float y)

http://tailieuhay.com 269

Page 270: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Khởi tạo và thiết lập đối tượng Tuple với tọa độ (x,y).

Tuple2f(float t[])

Khởi tạo và thiết lập đối tượng Tuple từ một mảng đặc biệt.

Tuple2f(Tuple2f t)

Khởi tạo và thiết lập đối tượng Tuple từ dữ liệu của một Tuple khác

Tuple2f(Tuple2d t)

Khởi tạo và thiết lập đối tượng Tuple từ dữ liệu của một Tuple khác

Tuple2f Methods (partial list)

Package: javax.vecmath

Các lớp Tuple* thường không được sử dụng trực tiếp trong chương trình

Java 3D nhưng cung cấp nền tảng cho Point*, Color*, Vector*,

TexCoord*. Ví dụ như Tuple2f cung cấp cơ sở cho Point2f, Color2f, và

TexCoord2f. Các hàm khởi tạo dưới đây đều đúng với các lớp con tương

tụ như Tuple3f và Tuple4f. Các phương thức của chúng cũng tương tự

như vậy.

void set(float x, float y)

void set(float t[])

Lập giá trị của tuple này từ một giá trị định trước.

boolean equals(Tuple2f t1)

Trả về giá trị true nêu trong Tuple t1 bằng với giá trị sẵn có của tuple.

final void add(Tuple2f t1)

Lập giá trị của tuple này tới vertor tổng của nó và Tuple t1.

void add(Tuple2f t1, Tuple2f t2)

Lập giá trị của tuple này tới vertor tổng của nó và Tuple t1 và t2.

void sub(Tuple2f t1, Tuple2f t2)

http://tailieuhay.com 270

Page 271: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Lập giá trị của tuple này tới vertor khác của t1 và t2 (this = t1 - t2).

void sub(Tuple2f t1)

Lập giá trị của tuple này tới vertor khác của nó và t1 (this = this - t1).

void negate()

Loại bỏ giá trị của một vertor.

void negate(Tuple2f t1)

Lập giá trị cho tuple sau khi loại bỏ giá trị của nó

void absolute()

Đổi tất cả thành phần của tuple này thành giá trị tuyệt đối.

void absolute(Tuple2f t)

Lập giá trị của các thành phần thành giá trị tuyệt đối và ghi vào tuple.

2.4.1 Point Classes

Đối tượng Point* thường được đại diện cho tọa độ của một đỉnh,

chẳng hạn như một vạch quét ảnh, một điểm nguồn sáng, nguồn âm thanh

và các dữ liệu điểm khác. Hàm tạo cho lớp Point* giống như hàm tạo của

Tuple* ngoại trừ chúng trả về đối tượng Point*.

Point3f Methods (partial list)

Package: javax.vecmath

Lớp Point* được thừa kế từ lớp Tuple*. Mỗi instance của lớp Tuple* đại

diện cho một điểm đơn trong 2, 3 hoặc 4 không gian. Thêm vào các

phương thức của Tuple*, lớp Point* có thêm các phương thức riêng của

nó, được chỉ ra dưới đây.

float distance(Point3f p1)

Trả về khoảng cách giữa điểm này và điểm p1.

http://tailieuhay.com 271

Page 272: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

float distanceSquared(Point3f p1)

Trả về khoảng cách bình phương giữu 2 điểm p và p1.

float distanceL1(Point3f p1)

Trả về khoảng cách L1 (Manhattan) giữa điểm này và điểm p1. Khoảng

cách L1 là:

abs(x1 - x2) + abs(y1 - y2) + abs(z1 - z2)

2.4.2 Color Classes

Đối tượng lớp màu đại diện cho một màu, có thể là một đỉnh, thuộc

tính của chất liệu, sương mù hoặc các đối tượng quan sát khác. Các màu

được chỉ ra hoặc là Color3* hoặc Color4* kiểu dữ liệu thường là kiểu

thực. Color3* xác định màu thông qua 3 màu đỏ, xanh da trời và xanh

nước biển.Giá trị của màu là từ 0 đến 255, đối với giá trị alpha là từ 0.0

đến 1.0. Đối với đối tượng Color4* có thêm giá trị về độ sâu. Khi giá trị

alpha bằng 1 thì màu hiện nguyên vẹn. Giá trị của màu là kiểu byte có giá

trị [-128,127] tuy nhiên Java vẫn xử lí giá trị màu [0,255].

Ví dụ về một lớp màu:

import javax.vecmath.*;

class ColorConstants{

public static final Color3f red = new

Color3f(1.0f,0.0f,0.0f);

public static final Color3f green = new

Color3f(0.0f,1.0f,0.0f);

public static final Color3f blue = new

Color3f(0.0f,0.0f,1.0f);

http://tailieuhay.com 272

Page 273: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

public static final Color3f yellow = new

Color3f(1.0f,1.0f,0.0f);

public static final Color3f cyan = new

Color3f(0.0f,1.0f,1.0f);

public static final Color3f magenta = new

Color3f(1.0f,0.0f,1.0f);

public static final Color3f white = new

Color3f(1.0f,1.0f,1.0f);

public static final Color3f black = new

Color3f(0.0f,0.0f,0.0f);

}

Ta có thể thấy hàm tạo của lớp Color* giống như lớp Tuple*, ngoại

trừ là nó trả về đối tượng Color*. Lớp này chỉ có một hàm khởi tạo và 2

phương thức thêm vào so với lớp cha của nó Tuple*.

Color* Constructors (partial list)

Package: javax.vecmath

Mỗi instance trong lớp Color* đại diện cho một màu đơn trong 3 thành

phần đỏ, xanh lá cây và xanh nước biển (RGB), hoặc một trong bốn thành

phần 3 màu và thêm độ alpha (RGBA). Giá trị alpha bằng 0 là trong suốt

còn bằng 1 là hiện nguyên bản.

Color*(Color color) <new in 1.2>

Tạo đối tượng Java 3D Color*() (Color3b, Color3f, Color4b, Color4f)

sử dụng một đối tượng AWT Color. Khi khởi tạo đối tượng Color4* sử

dụng đối tượng AWT Color giá trị alpha được thiết lập bằng 1.

http://tailieuhay.com 273

Page 274: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Color* Methods

Package: javax.vecmath

Lớp Color* (Color3b, Color3f, Color4b, Color4f) thừa kế từ lớp Tuple*.

Mỗi instance của lớp này đại điện cho một màu trong 3 (RGB) hoặc 4

(RGBA) thành phần. Dưới đây là một vài phương thức trong Color3* và

Color4*.

void set(Color color) <new in 1.2>

Lập màu sử dụng mầu từ đối tượng AWT Color

Color get() <new in 1.2>

Lấy một màu coi là một màu của đối tượng AWT Color.

2.4.3 Vector Classes

Vector* objects often represent surface normals at vertices although

they can also represent the direction of a light source or sound source.

Again, the constructors for Vector* classes are similar to the Tuple*

constructors. However, Vector* objects add many methods that are not

found in the Tuple* classes.

Đối tượng Vertor* đại diện cho bề mặt bình thường tại các định dù

chúng cũng có thể đại diện cho hướng của một nguồn sáng hoặc nguồn

âm thanh. Một lần nữa ta có thể thấy các hàm tạo của Vertor* cũng tương

tự như Tuple*.

Vector3f Methods (partial list)

Package: javax.vecmath

http://tailieuhay.com 274

Page 275: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Lớp Vector* thừa kế từ Tuple*. Mỗi instances của lớp Vector* đại diện

cho một đỉnh vertor trong không gian 1,2,3,4 chiều. Ngoài ra nó còn có

thêm những phương thức như dưới đây.

float length()

Trả về độ dài của một vertor

float lengthSquared()

Trả về giá trị bình phương độ dài của một vertor.

void cross(Vector3f v1, Vector3f v2)

Lập một vertor trở thành vertor pháp tuyến của 2 vertor v1 và v2.

float dot(Vector3f v1)

Tính toán và trả về tích số điểm của product hiện tại và vertor v1.

void normalize()

Bình thường hóa vertor hiện tại

void normalize(Vector3f v1)

Lập giá trị của vertor này với giá trị của vertor v1 được bình thường hóa.

float angle(Vector3f v1)

Trả về góc radians giữa vertor hiện tại với vertor tham số, giá trị này được

rằng buộc trong khoảng [0,PI].

2.4.4 TexCoord Classes

Chỉ có 2 lớp TexCoord* được sử dụng như là một tập các kết cấu bề

mặt tọa độ tại một đỉnh, là TexCoord2f và TexCoord3f. Với TexCoord2f

có một cặp tọa độ là (s, t), với TexCoord3f thì có 3 tọa độ là (s, t, r). Hàm

tạo của lớp này cũng tương tự như lớp Tuple* và không có thêm phương

thức nào so với lớp cha của nó.

http://tailieuhay.com 275

Page 276: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

2.5 Các lớp hình học

Trong đồ họa 3D, mọi thứ từ hình tam giác đơn giản đến hình phức

tạp như một chiếc máy bay đều được mô hình hóa và dựng dưới dạng dữ

liệu theo đỉnh. Trong Java 3D mỗi đối tượng Shape3D có thể gọi phương

thức setGeometry() của nó để tham chiếu đến một hoặc chỉ một đối tượng

Geometry. Chính xác hơn Geometry là lớp trừu tượng, cho nên một đối

tượng tham chiếu là một instance của lớp con của Geometry.

Các lớp con của Geometry có những dạng sau:

1. Non-indexed vertex-based Geometry (mỗi khi đối tượng quan sát

được dựng các đỉnh của nó chỉ được sử dụng một lần)

2. Indexed vertex-based Geometry (mỗi khi đối tượng quan sát được

dựng các đỉnh của nó được sử dụng nhiều lần)

Các đối tượng quan sát khác (Các lớp Geometry, Text3D, và

CompressedGeometry)

Phần này chỉ nói về 2 dạng trên. Cây thừa kế được hiển thị dưới hình 2-10

http://tailieuhay.com 276

Page 277: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

2.5.1 GeometryArray Class

Như cái tên của lớp này cho bạn hình dung lớp con này của Geometry

được sử dụng để định nghĩa điểm đường và hình đa giác điền đầy. Những

thành phần nguyên tố dựa trên điểm này là lớp con của của lớp trừu tượng

GeometryArray, chỉ ra một mảng chứa các dữ liệu về đỉnh. Ví dụ như

một đối tượng dùng để chỉ một tam giác, 3 thành phần được định nghĩa,

mỗi thành phần cho mỗi đỉnh. Với mỗi thành phần của mảng này duy trì

một vị trí tọa độ cho đỉnh của nó (có thể định nghĩa bằng Point* với dữ

liệu tương tự) . Ngoài định ra tọa độ thì các giá trị này có thể định nghĩa

màu, bề mặt bình thường hoặc texture. Vì vậy những mảng nầy chứa tọa

độ, màu, bề mặt thường, và texture, dưới dạng dữ liệu mảng.

Có 3 bước trong vòng đời của một đối tượng GeometryArray

1. Tạo một đối tượng rỗng

2. Điền đầy đối tượng với dữ liệu

3. Đồng hóa (tham chiếu) đối tượng từ (1 hoặc nhiều) đối tượng

Shape3D.

Bước 1: Tạo một đối tượng GeometryArray rỗng

Khi một đối tượng GeometryArray vừa được khởi tạo thì cần thiết

phải định nghĩa 2 thứ

Số đỉnh, hay số thành phần cần thiết

Định dạng của dữ liệu (tọa độ, màu, bề mặt thường, và texture) được

lưu tại mỗi đỉnh. Còn được gọi là “vertex format” (định dạng đỉnh).

GeometryArray Constructor

GeometryArray(int vertexCount, int vertexFormat)

Hàm tạo này tạo đối tượng GeometryArray rỗng với những số đỉnh và

định dạng đỉnh cho trước. Một trong những cờ riêng là các bitwise “OR”

http://tailieuhay.com 277

Page 278: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

hợp với nhau để mô tả dữ liệu mỗi đỉnh. Những giá trị cờ để định dạng

các đỉnh là:

COORDINATES: Chỉ ra mảng các đỉnh chứa tọa độ. Bit này buộc phải

lập.

NORMALS: Chỉ ra mảng đỉnh chứa bề mặt thường.

COLOR_3: Chỉ ra mảng đỉnh chứa màu (không có thành phần trong suốt)

COLOR_4: Chỉ ra mảng đỉnh chứa màu (có thành phần trong suốt)

TEXTURE_COORDINATE_2: Chỉ ra mảng đỉnh chứa 2D texture

coordinates.

TEXTURE_COORDINATE_3: Chỉ ra mảng đỉnh chứa 3D texture

coordinates.

Với mỗi cờ định dạng được thiết lâp sẽ có một mảng tương ứng tạo trong

đối tượng GeometryArray. Mỗi mảng này là số đỉnh (vertexCount) về

kích cỡ.

Vì lớp GeometryArray là lớp trừu tượng nên ta chỉ gọi phương thức

thiết lập cho lớp con của nó như LineArray.

Chú ý lớp Axis trong AxisApp.java là khác với lớp Axis chúng ta tự

định nghĩa trong ví dụ này

Bước 2: Điền đầy dữ liệu vào đối tượng GeometryArray rỗng

Sau khi khởi tạo đối tượng GeometryArray, đăng kí dữ liệu cho

mảng tương ứng với tạo định dạng của các đỉnh. Có thể làm việc này trên

mỗi đỉnh hoặc sử dụng mảng để đăng kí dữ liệu cho nhiều đỉnh chỉ với

một lời gọi phương thức . Các phương thức sẵn có sau:

GeometryArray Methods (partial list)

http://tailieuhay.com 278

Page 279: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

GeometryArray là lớp trừu tượng cho PointArray, LineArray,

TriangleArray, QuadArray,

GeometryStripArray, và IndexedGeometryArray.

void setCoordinate(int index, float coordinate[])

void setCoordinate(int index, double coordinate[])

void setCoordinate(int index, Point* coordinate)

Lập tọa độ tương ứng với đỉnh với mỗi đỉnh được định nghĩa là một chỉ

mục cho đối tượng này. void setCoordinates(int index, float

coordinates[])

void setCoordinates(int index, double coordinates[])

void setCoordinates(int index, Point* coordinates[])

Lập các tọa độ tương ứng với đỉnh với các đỉnh được định nghĩa là chỉ

mục cho đối tượng này.

void setColor(int index, float color[])

void setColor(int index, byte color[])

void setColor(int index, Color* color)

Lập màu tương ứng với đỉnh với mỗi đỉnh được định nghĩa là một chỉ

mục cho đối tượng này. void setColors(int index, float colors[])

void setColors(int index, byte colors[])

void setColors(int index, Color* colors[])

Lập các màu tương ứng với các đỉnh ,với mỗi đỉnh được định nghĩa là

một chỉ mục cho đối tượng này.

void setNormal(int index, float normal[])

void setNormal(int index, Vector* normal)

Lập trực giao tương ứng với mỗi đỉnh tại vị trí chỉ mục được chỉ ra cho

đối tượng này.

void setNormals(int index, float normals[])

void setNormals(int index, Vector* normals[])

http://tailieuhay.com 279

Page 280: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Lập các trực giao tương ứng với các đỉnh tại vị trí chỉ mục được chỉ ra

cho đối tượng này.

void setTextureCoordinate(int texCoordSet, int index, float texCoord[])

void setTextureCoordinate(int texCoordSet, int index, TexCoord*

coordinate)

Lập texture coordinate ứng với mỗi đỉnh tại vị trí chỉ mục cho trước cho

một tập texture coordinate của đối tượng.

GeometryArray Methods (partial list, continued)

void setTextureCoordinates(int texCoordSet, int index, <new in 1.2>

float texCoords[])

void setTextureCoordinates(int texCoordSet, int index, <new in 1.2>

TexCoord* texCoords[])

Lập các texture coordinate ứng với các đỉnh tại vị trí chỉ mục cho trước

cho một tập texture coordinate của đối tượng.

void setInitialVertexIndex(int initialVertexIndex) <new in 1.2>

Lập chỉ mục cho đỉnh ban đầu với đối tượng GeometryArray. Cho phép

một vài đỉnh có thể bỏ qua trong việc dựng hình, và các hoạt động khác.

void setValidVertexCount(int validVertexCount) <new in 1.2>

Lạp các giá trị tính toán đỉnh đúng cho đối tượng GeometryArray.

Cho phép một vài dữ liệu đỉnh có thể bỏ qua khi dựng hình, chọn lọc và

các hoạt động khác.

Đoạn mã 2-5 chỉ ra trường hợp sử dụng phương thức của

GeometryArray để lưu giữ tạo độ và giá trị màu trong mảng LineArray.

Đối tượng trục X chỉ gọi phương thức setCoordinate() để lưu trữ dữ liệu

tọa độ. Đối tượng trục Y gọi cả 2 phương thức setColor() và

setCoordinate() để nạp giá trị màu RGB và giá trị tọa độ. Đối tượng trục

Z thì gọi 10 lần phương thức setCoordinate() cho mỗi đỉnh và gọi

setColors() một lần để nạp cho cả 10 đỉnh với 1 phương thức.

http://tailieuhay.com 280

Page 281: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

// //////////////////////////////////////

////

//

// create axis subgraph

//

public Axis() {

axisBG = new BranchGroup();

// create line for X axis

LineArray axisXLines = new

LineArray(2, LineArray.COORDINATES);

axisBG.addChild(new

Shape3D(axisXLines));

axisXLines.setCoordinate(0, new

Point3f(-1.0f, 0.0f, 0.0f));

axisXLines.setCoordinate(1, new

Point3f(1.0f, 0.0f, 0.0f));

Color3f red = new Color3f(1.0f,

0.0f, 0.0f);

Color3f green = new Color3f(0.0f,

1.0f, 0.0f);

Color3f blue = new Color3f(0.0f,

0.0f, 1.0f);

// create line for Y axis

http://tailieuhay.com 281

Page 282: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

LineArray axisYLines = new

LineArray(2, LineArray.COORDINATES

| LineArray.COLOR_3);

axisBG.addChild(new

Shape3D(axisYLines));

axisYLines.setCoordinate(0, new

Point3f(0.0f, -1.0f, 0.0f));

axisYLines.setCoordinate(1, new

Point3f(0.0f, 1.0f, 0.0f));

axisYLines.setColor(0, green);

axisYLines.setColor(1, blue);

// create line for Z axis

Point3f z1 = new Point3f(0.0f, 0.0f,

-1.0f);

Point3f z2 = new Point3f(0.0f, 0.0f,

1.0f);

LineArray axisZLines = new

LineArray(10, LineArray.COORDINATES

| LineArray.COLOR_3);

axisBG.addChild(new

Shape3D(axisZLines));

axisZLines.setCoordinate(0, z1);

axisZLines.setCoordinate(1, z2);

axisZLines.setCoordinate(2, z2);

http://tailieuhay.com 282

Page 283: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

axisZLines.setCoordinate(3, new

Point3f(0.1f, 0.1f, 0.9f));

axisZLines.setCoordinate(4, z2);

axisZLines.setCoordinate(5, new

Point3f(-0.1f, 0.1f, 0.9f));

axisZLines.setCoordinate(6, z2);

axisZLines.setCoordinate(7, new

Point3f(0.1f, -0.1f, 0.9f));

axisZLines.setCoordinate(8, z2);

axisZLines.setCoordinate(9, new

Point3f(-0.1f, -0.1f, 0.9f));

Color3f colors[] = new Color3f[9];

colors[0] = new Color3f(0.0f, 1.0f,

1.0f);

for (int v = 0; v < 9; v++) {

colors[v] = red;

}

axisZLines.setColors(1, colors);

} // end of axis constructor

Màu mặc định cho các đỉnh của một đối tượng mảng

GeometryArray là trắng, nếu cả COLOR_3 và COLOR_4 không được

định nghĩa. Khi các đường hoặc đa giác đầy được dựng với các màu khác

nhau tại mỗi đỉnh thì các màu sẽ mịn dần giữa các đỉnh sử dụng phép

đánh bóng Gouraud.

http://tailieuhay.com 283

Page 284: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Bước 3: Tạo đối tượng Shape3D tham chiếu đến đối tượng

GeometryArray

Đoạn mã dưới đây chỉ ra cách làm thế nào để đối tượng Shape3D

tham chiếu đến đối tượng GeometryArray. Đối tượng Shape3D được

thêm vào một BranchGroup sẽ được thêm vào ở nơi nào đó trên đồ thị

khung cảnh. (Shape3D là lớp con của Node, vì thế Shape3D có thể thêm

vào thành con của một đồ thị khung cảnh )

Đồ thị khung cảnh được chỉ ra ở dưới đây:

2.5.2 Subclasses of GeometryArray

Như đã nói ở phần trên do GeometryArray là lớp trừu tượng là lớp

cha của rất nhiều lớp con hữu dụng, chẳng hạn như LineArray. Hình 1-2

cho thấy cây thừa kế đối với lớp GeometryArray và các lớp con của nó.

Lí do tồn tại của các lớp con này là làm sao để trình dựng hình của Java

3D có thể quyết định dựng đối với các đỉnh của các lớp đó.

http://tailieuhay.com 284

Page 285: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Hình 2-13 chỉ ra một ví du về các lớp con của GeometryArray gồm:

PointArray, LineArray, TriangleArray, và QuadArray (các lớp này

không phải là lớp con của GeometryStripArray). Trong hình này, các

tập bên trái nhất của các đỉnh chỉ ra 3 điểm đỉnh dựng thành 6 điểm, 3

đường, hoặc 2 tam giác. Hình thứ 4 chỉ ra 4 đỉnh định nghĩa một tứ giác.

Chú ý rằng các định này không dùng chung: mỗi đường hoặc một đa giác

đầy được dựng độc lập với nhau.

GeometryArray Subclass Constructors

Tạo một đối tượng rỗng với số đỉnh và định dạng đỉnh cho trước.

PointArray(int vertexCount, int vertexFormat)

LineArray(int vertexCount, int vertexFormat)

TriangleArray(int vertexCount, int vertexFormat)

QuadArray(int vertexCount, int vertexFormat)

http://tailieuhay.com 285

Page 286: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Để tìm hiểu cách sử dụng hàm tạo và phương thức xem lại đoạn mã 2-

4 và 2-5,2-6 sử dụng đối tượng LineArray. Nếu bạn đang dựng một hình

tứ giác cẩn thận với các đỉnh có thể tạo thành hình lõm, tự cắt nhau hoặc

không phẳng. Nếu xảy ra, chúng không thể dựng đúng được.

2.5.3 Subclasses of GeometryStripArray

Phần trước mô tả 4 lớp con của GeometryArray, không cho phép sử

dụng lại các đỉnh, tuy nhiên có một vài trường hợp ta cần sử dụng lại các

đỉnh, để cho kết quả dựng hình tốt hơn.

Lớp GeometryStripArray là lớp trừu tượng từ đó mỗi thực thể hình

học cơ bản (để ghép tạo đường và bề mặt ) thừa kế.

GeometryStripArray là lớp cha của LineStripArray,

TriangleStripArray và TriangleFanArray. Ta có hình 2-14 chỉ ra một

instance của một dạng các đỉnh được sử dụng lại.

Lớp GeometryStripArray có hàm tạo khác với lớp GeometryArray.

Hàm tạo của nó có 3 tham số, một mảng cách đỉnh tính trên mỗi mảnh

cho phép một đối tượng có thể duy trì nhiều mảnh.

GeometryStripArray có 2 phương thức thường sử dụng đến là

getNumStrips() và getStripVertexCounts().

GeometryStripArray Subclass Constructors

http://tailieuhay.com 286

Page 287: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Tạo một đối tượng rỗng với giá trị các đỉnh và định dạng các đỉnh và một

mảng tính toán các đỉnh qua các mảnh. Định dạng là một hay nhiều các

bit cờ “OR” để mô tả cho mỗi dữ liệu đỉnh. Định dạng các cờ là giống

nhau như đã định nghĩa trong lớp GeometryArray. Nhiều mảnh cùng

một lúc cũng được hỗ trợ. Tổng các tính toán đỉnh cho tất cả các mảnh

phải bằng với tổng số các đỉnh

LineStripArray(int vtxCount, int vertexFormat, int stripVertexCounts[])

TriangleStripArray(int vtxCount, int vertexFormat, int

stripVertexCounts[])

TriangleFanArray(int vtxCount, int vertexFormat, int

stripVertexCounts[])

Chú ý rằng Java 3D không hỗ trợ các hình cơ bản đầy với nhiều hơn 4

mặt. Người lập trình phải có trách nhiệm trong việc sử dụng kĩ thuật tách

để tách hình phức tạp ra thành nhiều các đối tượng của Java 3D như mảng

tam giác hoặc hình quạt.

Triangulator Class

Package: com.sun.j3d.utils.Geometry

Sử dụng để chuyển các đa giác hình học không có dạng tam giác về các

tam giác để có thể dựng hình bằng Java 3D. Các đa giác phải là lồi, cùng

nằm trên một mặt phẳng các cạnh không giao nhau.

Triangulator Constructor Summary

Triangulator()

Tạo một đối tượng tam giác.

Triangulator Method Summary

void triangulate(GeometryInfo ginfo)

http://tailieuhay.com 287

Page 288: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Chương trình con này chuyển đối tượng GeometryInfo từ dạng cơ bản

POLYGON_ARRAY thành dạng TRIANGLE_ARRAY sử dụng kĩ thuật

tách đa giác

Tham số:

ginfo - com.sun.j3d.utils.Geometry.GeometryInfo to be triangulated.

Ví dụ về cách sử dụng: TRIANGLE_ARRAY

Triangulator tr = new Triangulator();

tr.triangulate(ginfo); // ginfo contains the Geometry

shape.setGeometry(ginfo.getGeometryArray()); // shape is a Shape3D

Yo-yo Code Demonstrates TriangleFanArray

Đối tượng Yoyo trong chương trình YoyoApp.java schỉ ra cách sử dụng

đối tượng TriangleFanArray để mô hình hóa con yo-yo

Hình 2-15 chỉ 3 hình dựng của TriangleFanArray.

Trong đoạn mã 2-7, phương thức yoyoGeometry()tạo và trả về đối tượng

TriangleFanArray mong muốn.

http://tailieuhay.com 288

Page 289: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Dòng 15-18 tính toán tâm điểm cho 4 hình nón. Mỗi hình nón có 18 đỉnh

được tính toán ở dòng 20-28. Dòng 30-32 tạo một đối tượng

TriangleFanArray và dòng 34 là nơi để tính toán dữ liệu tọa độ (từ dòng

15-28) để lưu đối tượng

1. private Geometry yoyoGeometry() {

2.

3. TriangleFanArray tfa;

4. int N = 17;

5. int totalN = 4*(N+1);

6. Point3f coords[] = new Point3f[totalN];

7. int stripCounts[] = {N+1, N+1, N+1, N+1};

8. float r = 0.6f;

9. float w = 0.4f;

10. int n;

11. double a;

12. float x, y;

13.

14. // set the central points for four triangle fan strips

15. coords[0*(N+1)] = new Point3f(0.0f, 0.0f, w);

16. coords[1*(N+1)] = new Point3f(0.0f, 0.0f, 0.0f);

17. coords[2*(N+1)] = new Point3f(0.0f, 0.0f, 0.0f);

18. coords[3*(N+1)] = new Point3f(0.0f, 0.0f, -w);

19.

20. for (a = 0,n = 0; n < N; a = 2.0*Math.PI/(N-1) * ++n){

21. x = (float) (r * Math.cos(a));

22. y = (float) (r * Math.sin(a));

23.

24. coords[0*(N+1)+N-n] = new Point3f(x, y, w);

25. coords[1*(N+1)+n+1] = new Point3f(x, y, w);

http://tailieuhay.com 289

Page 290: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

26. coords[2*(N+1)+N-n] = new Point3f(x, y, -w);

27. coords[3*(N+1)+n+1] = new Point3f(x, y, -w);

28. }

29.

30. tfa = new TriangleFanArray (totalN,

31. TriangleFanArray.COORDINATES,

32. stripCounts);

33.

34. tfa.setCoordinates(0, coords);

35.

36. return tfa;

37.} // end of method yoyoGeometry in class Yoyo

Code Fragment 2-7 yoyoGeometry() Method Creates TriangleFanArray

Object

Hình yo-yo trắng mới chỉ là điểm khởi đầu. Hình 2-16 chỉ ra một đối

tượng tương tự nhưng màu đã được thay đổi ở mỗi đỉnh. Phương thức

được yoyoGeometry()thay đổi. Dòng 23 qua 26, 36 tới 39, và dòng 46

chỉ định màu cho mỗi đỉnh.

1. private Geometry yoyoGeometry() {

2.

3. TriangleFanArray tfa;

4. int N = 17;

5. int totalN = 4*(N+1);

6. Point3f coords[] = new Point3f[totalN];

7. Color3f colors[] = new Color3f[totalN];

8. Color3f red = new Color3f(1.0f, 0.0f, 0.0f);

http://tailieuhay.com 290

Page 291: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

9. Color3f yellow = new Color3f(0.7f, 0.5f, 0.0f);

10. int stripCounts[] = {N+1, N+1, N+1, N+1};

11. float r = 0.6f;

12. float w = 0.4f;

13. int n;

14. double a;

15. float x, y;

16.

17. // set the central points for four triangle fan strips

18. coords[0*(N+1)] = new Point3f(0.0f, 0.0f, w);

19. coords[1*(N+1)] = new Point3f(0.0f, 0.0f, 0.0f);

20. coords[2*(N+1)] = new Point3f(0.0f, 0.0f, 0.0f);

21. coords[3*(N+1)] = new Point3f(0.0f, 0.0f, -w);

22.

23. colors[0*(N+1)] = red;

24. colors[1*(N+1)] = yellow;

25. colors[2*(N+1)] = yellow;

26. colors[3*(N+1)] = red;

27.

28. for(a = 0,n = 0; n < N; a = 2.0*Math.PI/(N-1) * ++n){

29. x = (float) (r * Math.cos(a));

30. y = (float) (r * Math.sin(a));

31. coords[0*(N+1)+n+1] = new Point3f(x, y, w);

32. coords[1*(N+1)+N-n] = new Point3f(x, y, w);

33. coords[2*(N+1)+n+1] = new Point3f(x, y, -w);

34. coords[3*(N+1)+N-n] = new Point3f(x, y, -w);

35.

36. colors[0*(N+1)+N-n] = red;

37. colors[1*(N+1)+n+1] = yellow;

http://tailieuhay.com 291

Page 292: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

38. colors[2*(N+1)+N-n] = yellow;

39. colors[3*(N+1)+n+1] = red;

40. }

41. tfa = new TriangleFanArray (totalN,

42. TriangleFanArray.COORDINATES|TriangleFanArray.COLOR_3,

43. stripCounts);

44.

45. tfa.setCoordinates(0, coords);

46. tfa.setColors(0,colors);

47.

48. return tfa;

49. } // end of method yoyoGeometry in class Yoyo

Code Fragment 2-8 Modified yoyoGeometry() Method with Added

Colors

http://tailieuhay.com 292

Page 293: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

2.5.4 Subclasses of IndexedGeometryArray

Các phần trước mô tả các lớp con của GeometryArray, cho thấy chỉ

lớp GeometryStripArray có thêm quyền hạn sử dụng lại các đỉnh. Ví dụ

để định nghĩa một hình lập phương mỗi đỉnh trong 8 đình của nó phải

được sử dụng bởi 3 hình vuông. Trong trường hợp xấu nhất chúng ta phải

định nghĩa 24 đỉnh mặc dù chỉ 8 đỉnh là đủ.

Đối tượng IndexedGeometryArray cung cấp một cấp bậc khác sao

cho có thể tránh việc sử dụng thừa. Với những mảng này cũng chứa tạo

độ, màu sắc, bề mặt thường và tạo độ bề mặt.

Tuy nhiên đối tượng IndexedGeometryArray cũng cần thêm các

mảng phụ gọi là mảng chỉ số chứa các chỉ mục đến mảng dữ liệu. Mảng

chỉ mục này có nhiều tham chiếu đến các đỉnh tương tự trong cùng một

mảng dữ liệu, từ đó cho phép sử dụng lại hiệu quả rõ ràng. Chúng ta có

thể xen ví dụ dưới đây.

Các lớp con của IndexedGeometryArray song song với các lớp con

của lớp GeometryArray. Cây thừa kế được vẽ dưới hình 2-18

http://tailieuhay.com 293

Page 294: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Hàm tạo cho IndexedGeometryArray,

IndexedGeometryStripArray cùng các lớp con của chúng dưới đây.

IndexedGeometryArray and Subclasses Constructors

Tạo một đối tượng rỗng với số đỉnh và định dạng đỉnh cho trước và số các

chỉ mục trong mảng này.

IndexedGeometryArray(int vertexCount, int vertexFormat, int

indexCount)

IndexedPointArray(int vertexCount, int vertexFormat, int indexCount)

IndexedLineArray(int vertexCount, int vertexFormat, int indexCount)

IndexedTriangleArray(int vertexCount, int vertexFormat, int indexCount)

IndexedQuadArray(int vertexCount, int vertexFormat, int indexCount)

IndexedGeometryStripArray and Subclasses Constructors

Tạo một đối tượng rỗng với số đỉnh và định dạng đỉnh cho trước và số các

chỉ mục trong mảng này và một mảng các tổng số các đỉnh mỗi mảnh.

IndexedGeometryStripArray(int vc, int vf, int ic, int

stripVertexCounts[])

IndexedLineStripArray(int vc, int vf, int ic, int stripVertexCounts[])

http://tailieuhay.com 294

Page 295: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

IndexedTriangleStripArray(int vc, int vf, int ic, int stripVertexCounts[])

IndexedTriangleFanArray(int vc, int vf, int ic, int stripVertexCounts[])

Các phương thức của chúng cho đưới dây:

IndexedGeometryArray Methods (partial list)

void setCoordinateIndex(int index, int coordinateIndex)

Tạo các chỉ mục tọa độ tương ứng với các đỉnh tại vị trí chỉ mục cho đối

tượng

void setCoordinateIndices(int index, int coordinateIndices[])

Tạo các chỉ mục các tọa độ tương ứng với các đỉnh tại vị trí chỉ mục cho

đối tượng

void setColorIndex(int index, int colorIndex)

Lập chỉ mục màu tương ứng với đỉnh tại vị trí chỉ mục đã cho với đối

tượng.

void setColorIndices(int index, int colorIndices[])

Lập các chỉ mục màu tương ứng với các đỉnh tại vị trí chỉ mục đã cho với

đối tượng.

void setNormalIndex(int index, int normalIndex)

Lập chỉ mục bình thường tương ứng với đỉnh tại chỉ mục định trước cho

đối tượng.

void setNormalIndices(int index, int normalIndices[])

Lập các chỉ mục bình thường tương ứng với các đỉnh tại chỉ mục định

trước cho đối tượng.

void setTextureCoordinateIndex(int texCoordSet, int index, <new in 1.2>

int texCoordIndex)

Lập chỉ mục toạ độ tương ứng với đỉnh tại chỉ mục định trước cho đối

tượng.

http://tailieuhay.com 295

Page 296: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

void setTextureCoordinateIndices(int texCoordSet, int index,

int texCoordIndices[])

Lập các chỉ mục toạ độ tương ứng với các đỉnh tại chỉ mục định trước cho

đối tượng.

2.5.5 Axis.java is an Example of IndexedGeometryArray

Ví dụ Axis về IndexedGeometryArray ta có định nghĩa 18 đỉnh và

30 chỉ mục cho 15 đường. Như vậy có 5 đường cho mỗi trục.

2.6 Appearance and Attributes

Đối tượng Shape3D có thể tham chiếu đến cả đối tượng Geometry và

Apperance. Như đã thảo nói ở phía trên trong phần 2.5, đối tượng

Geometry chỉ ra thông tin của mối đỉnh với một đốt tượng quan sát.

Thông tin mỗi đỉnh này có thể chỉ định ra màu của đối tượng. Dữ liệu

trong đối tượng Geometry thường không đủ để mô tả bề ngoài của một

bối tượng. Trong trường hợp đó rất cần thiết đối tượng Apperance.

Một đối tượng Appearance không chứa dữ liệu mô tả đối tượng quan sát

mà nó biết nơi nào có dữ liệu đó, do đó cách làm của nó là tham chiếu

đến một vài đối tượng khác như lớp con của NodeComponent .

http://tailieuhay.com 296

Page 297: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Một đối tượng Appearance có thể tham chiếu đến thuộc tính một vài đối

tượng lớp khác như:

PointAttributes

LineAttributes

PolygonAttributes

ColoringAttributes

TransparencyAttributes

RenderingAttributes

Material

TextureAttributes

Texture

TexCoordGeneration

Sáu thuộc tính được đề cập đến trong tài liệu này còn lại dành cho

chương 6 và chương 7.

Một đối tượng Appearance với các thuộc tính của đối tượng khác mà

nó tham chiếu đến gọi là một gói giao diện. Để tham chiếu đến nó dựa

trên phương thức với một cái tên chính xác. Ví dụ như tham chiếu đến đối

tượng ColoringAttributes nó sử dụng phương thức

Appearance.setColoringAttributes().

Trên đồ thị khung cảnh

http://tailieuhay.com 297

Page 298: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

2.6.1 Appearance NodeComponent

Appearance Constructor

Hàm tạo này tạo đối tượng Appearance với mọi thành phần chiếu nhận

giá trị null. Các giá trị mặc định có thể đoán được: điểm và đoạn thẳng

được vẽ với kích thước và độ dài 1 pixel và không có có khử răng cưa,

màu mặc định là màu trắng, khả năng xuyên qua vô hiệu hóa.

Appearance()

2.6.2 Sharing NodeComponent Objects

Việc tham chiếu đến một vài đối tượng là hợp lệ và cũng cần thiết vì

thế nên chia sẻ cùng các đối tượng NodeComponent. Ví dụ trong hình 2-

21 2 đối tượng Shape3D chia sẻ cùng thành phần LineAttributes.

Việc chia sẽ này giúp cho việc dựng hình nhanh hơn, hiệu quả càng

cao.

http://tailieuhay.com 298

Page 299: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Tuy nhiên cần chú ý rằng một node không được có nhiều hơn một cha từ

đó NodeComponent có thể chia sẻ hay tham chiếu đến bởi nhiều đối

tượng khác.

2.6.3 Attribute Classes

PointAttributes

Đối tượng PointAttributes quản lí việc mỗi điểm cơ bản được dựng

hình như thế nào. Mặc định một đỉnh được dựng như một điểm, bạn có

thể dùng setPointSize() để làm cho điểm đó to ra tuy nhiên mặc định một

điểm to sẽ trông như một hình vuông, trừ phi bạn dùng

setPointAntialiasingEnable(). Lúc đó điểm vuông được làm tròn đi.

PointAttributes Constructors

PointAttributes()

Tạo một đối tượng thành phần và mô tả kích thước 1 pixel không dùng

khử răng cưa

PointAttributes(float pointSize, boolean state)

Tạo một đối tượng thành phần và mô tả kích thước 1 pixel dùng khử răng

cưa

PointAttributes Methods

void setPointSize(float pointSize)

Mô tả kích thước pixel của các điểm

void setPointAntialiasingEnable(boolean state)

Thiết lập hoặc bỏ thiết lập chống răng cưa. Thường làm nếu pointSize >=

1 pixel.

http://tailieuhay.com 299

Page 300: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

LineAttributes

Đối tượng này thay đổi cách dựng các đường cơ bản theo 3 cách. Mặc

định đường được vẽ là nét liền, với độ rộng 1pixle không chống răng cửa.

Bạn có thể thay đổi điều này bằng cách sử dụng các phương thức

setLinePattern(), setLineWidth(), và setLineAntialiasingEnable().

Mẫu đường thẳng do người dùng tự định nghĩa

Một mẫu thường dược định nghĩa bằng một mặt nạ mẫu và một thành

phần quy mô.

Một giá trị 16 bit định nghĩa một mặt nạ mẫu. Mỗi bit trong 16 bit giá

trị định nghĩa khi nào 1 pixel trong mẫu được bật hay tắt (1/0). Sau khi cả

16 mẫu đều được sử dụng, thì mẫu được lặp lại. Bit 0 tương ứng với pixel

đầu tiên trong mẫu.

Ví dụ một mặt nạ của 0x00ff (0b0000000011111111) định nghĩa 8 pixel

mở sau đó là 8 pixel đóng.

Nhớ rằng,bit phóng đại bé nhất được sử dụng đầu tiên khi vẽ, nên

mẫu bit được đọc từ phải sang trái. Mặt nạ mẫu giá trị 0x0101 định nghĩa

một mẫu lặp của một pixel mở và 7pixel tắt. Mẫu này được lặp lại nhiều

lần tùy theo yêu cầu, mẫu khởi động lại trước mỗi đường mới của một

mảnh.

Các mẫu có thể mở rộng đến 240 pixel sử dụng nhân tố quy mô. Ví dụ

như quy mô của 3 x với một mặt nạ mẫu 0x001f tương đương với sản

sinh ra mẫu với 15 pixel mở theo bởi 33 pixel đóng. Khoảng cách đúng là

[1,15],giá trị bên ngoài khoảng này là không chấp nhận được.

LineAttributes Constructors

LineAttributes()

Tạo một đối tượng thành phần mô tả độ rộng 1 pixel, một đường thẳng

liền nét không khử răng cưa.

LineAttributes(float pointSize, int linePattern, boolean state)

http://tailieuhay.com 300

Page 301: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Tạo một đối tượng thành phần mô tả độ rộng 1 pixel cho một đường

thẳng, mẫu dùng để vẽ, có khử răng cưa.

LineAttributes Methods

void setLineWidth(float lineWidth)

Mô tả độ rộng pixel cho đường thẳng

void setLinePattern(int linePattern)

linePattern là một trong số các hằng sau:

PATTERN_SOLID (the default),

PATTERN_DASH, PATTERN_DOT, PATTERN_DASH_DOT, or

PATTERN_USER_DEFINED.

Mô tả làm sao một pixel của một đường được điền vào.

void setLineAntialiasingEnable(boolean state)

Bỏ hay có chống răng cưa với đường thẳng

void setPatternMask(int mask) <new in 1.2>

Lập một mặt nạ mẫu với một giá trị đặc biệt

void setPatternScaleFactor(int scaleFactor) <new in 1.2>

Sets the line pattern scale factor to the specified value.

Line Attributes Line Patterns

PATTERN_SOLID solid lines (no pattern). This is the default.

PATTERN_DASH dashed lines; ideally, a repeating pattern of 8 pixels

on and 8 pixels off.

PATTERN_DOT dotted lines; ideally, a repeating pattern of 1 pixel on

and 7 pixels off.

http://tailieuhay.com 301

Page 302: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

PATTERN_DASH_DOT dashed-dotted lines; ideally, a repeating

pattern of 7 pixels on, 4 pixels

off, 1 pixel on, and 4 pixels off.

PATTERN_USER_DEFINED lines with a user-defined line pattern.

See "User-defined Line Patterns,"above.

PolygonAttributes

PolygonAttributes chi phối việc dựng hình của các thành phần cơ

bản đa giác theo 3 cách: đa giác bị phân tách như thế nào, nếu nó được

chọn lọc và khi nào thì độ sâu bù được chấp nhận. Mặc định các đa giác

đều là đa giác lồi tuy nhiên khi đa giác bị tách thì đa giác được vẽ lại

thành các khung (đường) hoặc chỉ các điểm tại các đỉnh. Phương thức

setCullFace() dùng để loại bỏ các đa giác đã được dựng. Nếu phương

thức này thiết lập hoặc CULL_FRONT hoặc CULL_BACK thì một nửa

số đa giác không được dựng.

Tùy theo sự hiệu quả của hệ thống dựng hình mà các đỉnh được dựng

cả là các dây khung và các đa giác lồi luôn được phân tách với giá trị độ

sâu chính xác. Kết quả là các đa giác và các dây khung có thể được dựng

ở độ sâu khác nhau, gây ra hiện tượng đường khâu. Hiện tương stitching

này là do độ sâu khác nhau nên các dây khung xuất hiện lúc ẩn lúc hiện

trên đa giác. Với 2 thuộc tính PolygonOffset và PolygonOffsetFactor về

giá trị độ sâu cho phép đa giác lồi có thể hướng khửu tay về phía khung

hình ảnh. setBackFaceNormalFlip()được sử dụng để dựng một đa giác lồi

sáng với cả 2 mặt của đa giác đều mờ đi.

PolygonAttributes Constructors

PolygonAttributes()

http://tailieuhay.com 302

Page 303: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Tạo đối tượng thành phần với giá trị mặc định của đa giác lồi không có

cắt bề mặt không có rìa đa giác.

PolygonAttributes(int polygonMode, int cullFace, float

polygonOffset)

Tạo đối tượng thành phần với giá trị cho trước của giác lồi

PolygonAttributes(int polygonMode, int cullFace, float

polygonOffset,

boolean backFaceNormalFlip)

Tạo đối tượng thành phần giống như các hàm tạo phía trước nhưng cũng

cho phép chỉ ra mặt phía trước và phía sau của đa giác như thế nào

PolygonAttributes(int polygonMode, int cullFace, float

polygonOffset, boolean backFaceNormalFlip, float

polygonOffsetFactor) <new in 1.2>

Tạo đối tượng PolygonAttributes với giá trị cho trước.

PolygonAttributes Methods

void setCullFace(int cullFace)

cullFace là CULL_FRONT, CULL_BACK, or CULL_NONE. Cull

(không dựng) trước mặt và mặt sau của các đa giác hoặc không tách đa

giác nào.

void setPolygonMode(int polygonMode)

polygonMode là: POLYGON_POINT, POLYGON_LINE, or

POLYGON_FILL. Dựng polygons trên points, lines, or filled polygons

(mặc định).

void setPolygonOffset(float polygonOffset)

polygonOffset là screen-space offset thêm vào để hiệu chỉnh giá trị độ sâu

của polygon primitives.

http://tailieuhay.com 303

Page 304: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

void setPolygonOffsetFactor(float polygonOffsetFactor) <new in 1.2>

Lập polygon offset factor với giá trị cho trước.

void setBackFaceNormalFlip(boolean backFaceNormalFlip)

trong đó backFaceNormalFlip xác định khi nào đỉnh bình thường hoặc

mặt sau của đa giác cần khuất sáng. Khi cờ này được lập giá trị true mặt

sau bỏ lựa chọn mặt sau.

ColoringAttributes

Thuộc tính ColoringAttributes điều khiển chuyện tô màu. Phương

thức setColor() lập một màu bên trong trong đó tùy trường hợp mà để

màu đó vào. Thêm vao đó setShadeModel() xác định khi nào có khi cần

thêm ngang một màu vào.

ColoringAttributes Constructors

ColoringAttributes()

Tạo đối tượng thành phần sử sụng màu trắng cho màu bên trong và

SHADE_GOURAUD là mô hình đánh bóng.

ColoringAttributes(Color3f color, int shadeModel)

ColoringAttributes(float red, float green, float blue, int shadeModel)

shadeModel là một trong SHADE_GOURAUD, SHADE_FLAT,

FASTEST, or NICEST.

(trong hầu hết trường hợp, FASTEST là SHADE_FLAT, và NICEST là

SHADE_GOURAUD.)

ColoringAttributes Methods

void setColor(Color3f color)

void setColor(float red, float green, float blue)

cả 2 phương thức đều định nghĩa màu bên trong

void setShadeModel(int shadeModel)

http://tailieuhay.com 304

Page 305: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

shadeModel là một trong các hằng: SHADE_GOURAUD,

SHADE_FLAT, FASTEST,

or NICEST.

TransparencyAttributes

Thuộc tính này quản lí độ trong suốt của bất cứ hình cơ bản nào.

setTransparency() định nghĩa giá trị trong suốt (bằng 1 là trong suốt hoàn

toàn, bằng 0.0 là không trong suốt)

TransparencyAttributes Constructors

TransparencyAttributes()

Tạo đối tượng thành phần với độ trong suốt lập ở chế độ NONE.

TransparencyAttributes(int tMode, float tVal)

Trong đó tMode là một trong những BLENDED, SCREEN_DOOR,

FASTEST, NICEST, hoặc NONE, và tVal định nghĩa tính mờ của đối

tượng (0.0 không trong suốt và 1.0, trong suốt hoàn toàn).

TransparencyAttributes(int tMode, float tVal, int srcBlendFunction,

int dstBlendFunction) <new in 1.2>

Tạo một đối tượng TransparencyAttributes với giá trị định trước

TransparencyAttributes Methods

void setTransparency(float tVal)

tVal định nghĩa tính mờ của đối tượng (0.0 không trong suốt và 1.0, trong

suốt hoàn toàn).

void setTransparencyMode(int tMode)

http://tailieuhay.com 305

Page 306: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

tMode (one of BLENDED, SCREEN_DOOR, FASTEST, NICEST, or

NONE) chỉ ra nếu

có hoạt động làm trong suốt

void setDstBlendFunction(int blendFunction) <new in 1.2>

Lập địa chỉ chức năng pha trộn được sử dụng để trộn độ trong suốt và

chống răng cưa.

void setSrcBlendFunction(int blendFunction) <new in 1.2>

Lập tài nguyen hàm trộng sử dụng để trộn độ trong suốt và chống răng

cưa.

RenderingAttributes

RenderingAttributes điều khiển 2 hoạt động dựng hình trên từng

pixel: kiểm định độ sâu đệm, và kiểm tra alpha.

Hoạt động quét (Geometry) xác định xem việc dựng hình pixel ảnh

hướng đến màn ảnh thế nào. Mặc định là bỏ chọn Geometry thường được

sử dụng trong hầu hết các trường hợp

Độ sâu đệm là tập hợp các giá trị độ sâu của những pixel được dựng. Nó

được dùng đề xác định pixel được nhìn thấy hay bị khuất để chúng có thể

được dựng. Độ sâu đệm sử dụng khác khi dựng đối mờ và trong suốt. Kết

quả là đối tượng trong suốt không cập nhập giá trị độ sâu đêm không bình

thường. Có thể vô hiệu hóa hoặc dùng tính năng này đối với một đối

tượng thành phần RenderingAttributes. Việc vô hiệu hóa đảm bảo đối

tượng luôn luôn nhìn thấy, tuy nhiên mặc định là để nó enable.

RenderingAttributes Constructors

RenderingAttributes()

Tạo một đối tượng thành phần định nghĩa việc dựng trên pixel với việc

kích hoạt kiểm tra độ sâu đệm và vô hiệu hóa tính năng kiểm tra alpha.

http://tailieuhay.com 306

Page 307: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

RenderingAttributes(boolean depthBufferEnable, boolean

depthBufferWriteEnable, float alphaTestValue, int

alphaTestFunction)

Trong đó depthBufferEnable bật tắt so sánh độ sâu đệm (kiểm tra độ sâu),

depthBufferWriteEnable bật và tắt để ghi vào depth buffer,

alphaTestValue được sử dụng để kiểm tra. Đối với các nguồn alpha đi vào

, and alphaTestFunction là một trong những ALWAYS, NEVER,

EQUAL, NOT_EQUAL, LESS, LESS_OR_EQUAL, GREATER, hoặc

GREATER_OR_EQUAL, chỉ rõ loại alpha test nào được kích hoạt. Tạo

một đối tượng thành phần định nghĩa việc dựng trên pixel cho so sanh độ

sâu đệm và kiểm tra alpha.

RenderingAttributes(boolean depthBufferEnable, boolean

depthBufferWriteEnable, float alphaTestValue, int

alphaTestFunction,

boolean visible, boolean ignoreVertexColors,

boolean GeometryOpEnable, int GeometryOp) <new in 1.2>

Tạo một đối tượng RenderingAttributes với giá trị cho trước.

RenderingAttributes Methods

void setDepthBufferEnable(boolean state)

turns on and off the depth buffer testing.

void setDepthBufferWriteEnable(boolean state)

turns on and off writing to the depth buffer.

void setAlphaTestValue(float value)

specifies the value to be used for testing against incoming source alpha

values.

void setAlphaTestFunction(int function)

http://tailieuhay.com 307

Page 308: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

where function is one of ALWAYS, NEVER, EQUAL, NOT_EQUAL,

LESS, LESS_OR_EQUAL,

GREATER, or GREATER_OR_EQUAL, which denotes what type of

alpha test is active. If function is

ALWAYS (the default), then the alpha test is effectively disabled.

void setDepthBufferEnable(boolean state) <new in 1.2>

Enables or disables depth buffer mode for this RenderingAttributes

component object.

void setDepthBufferWriteEnable(boolean state) <new in 1.2>

Enables or disables writing the depth buffer for this object.

void setIgnoreVertexColors(boolean ignoreVertexColors) <new in

1.2>

Sets a flag that indicates whether vertex colors are ignored for this

RenderingAttributes object.

void setGeometryOp(int GeometryOp) <new in 1.2>

Sets the Geometry operation function for this RenderingAttributes

component object.

void setGeometryOpEnable(boolean GeometryOpEnable) <new in

1.2>

Sets the GeometryOp enable flag for this RenderingAttributes

component object.

void setVisible(boolean visible) <new in 1.2>

Sets the visibility flag for this RenderingAttributes component object.

Appearance Attribute Defaults

Hàm tạo Appearance khởi tạo đối tượng Appearance với các thuộc

tính tham chiếu đến các giá trị null. Bảng 2-1 là danh sách các giá trị mặc

định cho những thuộc tính tham chiếu đến giá trị null.

Attributes Class Parameter Default Value

http://tailieuhay.com 308

Page 309: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

ColoringAttributes color

shade model

white (1, 1, 1)

SHADE_GOURAUD

LineAttributes line width

line pattern

line antialiasing enable

1.0

PATTERN_SOLID

false

PointAttributes point size

point antialiasing enable

1.0

false

PolygonAttributes cull face

backFaceNormalFlip

polygon mode

polygonOffset

polygonOffsetFactor

CULL_BACK

false

POLYGON_FILL

0.0

0.0

RenderingAttributes depthBufferEnable

depthBufferWriteEnable

alphaTestFunction

alphaTestValue

visible

ignoreVertexColors

GeometryOpEnable

GeometryOp

true

true

ALWAYS

0.0

true

false

false

ROP_COPY

TextureAttributes textureMode

textureBlendColor

transform

perspectiveCorrectionMod

e

REPLACE

black (0, 0, 0, 0)

identity

NICEST

null

http://tailieuhay.com 309

Page 310: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

textureColorTable

TransparencyAttributes transparencyMode

transparencyValue

srcBlendFunction

dstBlendFunction

NONE

0.0

SRC_BLEND_ALPHA

BLEND_ONE_MINUS_ALPHA

2.6.4 Example: Back Face Culling

Đa giác có 2 mặt. Với nhiều đối tượng quan sát không chỉ một mặt

của đa giác cần được dựng. Để giảm công việc tính toán cần thiết phải

dựng bề mặt của đa diện, hệ thống dựng hình có thể chọn lọc những mặt

không cần thiết. Bề mặt trước của một đối tượng có thể là mặt cho các

đỉnh được định nghĩa theo thứ tự ngược chiều kim đồng hồ.

TwistStripApp.java tạo một đối tượng dải xoắn và quay nó quanh trục

y.

Khi dải xoắn quay các phần của nó xem như biến mất tuy nhiên

những mẩu biến mất có thể dễ dàng thấy ở hình 2-22. Thực tế chương

trình định nghĩa 2 đối tượng quan sát với cùng một hình. Một đối tượng

được dựng dưới dạng khung dây còn đối tượng còn lại dựng với bề mặt

liền. Qua đó khi quay chúng ta có thể quan sát được như vậy.

http://tailieuhay.com 310

Page 311: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Lí do có mất các đa giác là chế độ chọn lọc không chỉ ra, vì thế nó để

mặc định là CULL_BACK. Các tam giác của bề mặt biến mất khi phần

lưng của nó (phần sau) đối mặt với màn ảnh. Tính năng này cho phép hệ

thống dựng hình tránh không phải dựng phần bề mặt tam giác vốn không

cần thiết.

T uy nhiên trong một số trường hợp việc chọn lọc lại gây vấn đề, như

trong ví dụ TwistStripApp. Vấn đề có một cách giải quyết đơn giản đó là

tắt bỏ chế độ chọn lọc. Như đoạn mã trong hình 2-10:

public class TwistStripApp extends Applet {

// //////////////////////////////////////////

/////

//

// create Twist visual object

//

public class Twist extends Shape3D {

http://tailieuhay.com 311

Page 312: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

// //////////////////////////////////////

////

//

// create twist subgraph

//

public Twist() {

this.setGeometry(createGeometry());

this.setAppearance(createAppearance());

} // end of twist constructor

Geometry createGeometry() {

TriangleStripArray twistStrip;

Color3f blue = new Color3f(0.0f,

0.0f, 1.0f);

// create triangle strip for twist

int N = 80;

int stripCounts[] = { N };

twistStrip = new TriangleStripArray(

N,

TriangleStripArray.COORDINATES |

TriangleStripArray.COLOR_3,

stripCounts);

double a;

http://tailieuhay.com 312

Page 313: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

int v;

for (v = 0, a = 0.0; v < N; v += 2,

a = v * 2.0 * Math.PI / (N - 2)) {

twistStrip.setCoordinate(v, new

Point3d(0.7 * Math.sin(a) + 0.2

* Math.cos(a), 0.3 *

Math.sin(a), 0.7 * Math.cos(a)

+ 0.2 * Math.cos(a)));

twistStrip.setCoordinate(v + 1,

new Point3d(0.7 * Math.sin(a)

- 0.2 * Math.cos(a),

-0.3 * Math.sin(a), 0.7

* Math.cos(a) - 0.2 *

Math.cos(a)));

twistStrip.setColor(v, blue);

twistStrip.setColor(v + 1,

blue);

}

return twistStrip;

}

// create Appearance for Twist Strip

//

// this method creates the default

Appearance for the

// twist strip. The commented line of

code containting

http://tailieuhay.com 313

Page 314: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

// the setCullFace will fix the problem

of half of the

// Twisted Strip disappearing.

Appearance createAppearance() {

Appearance twistAppear = new

Appearance();

PolygonAttributes polyAttrib = new

PolygonAttributes();

//

polyAttrib.setCullFace(PolygonAttributes.CULL_NON

E);

twistAppear.setPolygonAttributes(polyAttrib);

return twistAppear;

}

} // end of class Twist

// //////////////////////////////////////////

/////

//

// create scene graph branch group

//

public BranchGroup createSceneGraph() {

http://tailieuhay.com 314

Page 315: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

BranchGroup contentRoot = new

BranchGroup();

// Create the transform group node and

initialize it to the

// identity. Add it to the root of the

subgraph.

TransformGroup objSpin = new

TransformGroup();

objSpin.setCapability(TransformGroup.ALLOW_TRANSF

ORM_WRITE);

contentRoot.addChild(objSpin);

Shape3D twist = new Twist();

objSpin.addChild(twist);

// Duplicate the twist strip geometry and

set the

// appearance of the new Shape3D object

to line mode

// without culling.

// Add the POLYGON_FILLED and

POLYGON_LINE strips

// in the scene graph at the same point.

// This will show the triangles of the

original Mobius strip that

// are clipped. The PolygonOffset is set

to prevent stitching.

http://tailieuhay.com 315

Page 316: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

PolygonAttributes polyAttrib = new

PolygonAttributes();

polyAttrib.setCullFace(PolygonAttributes.CULL_NON

E);

polyAttrib.setPolygonMode(PolygonAttributes.POLYG

ON_LINE);

polyAttrib.setPolygonOffset(0.001f);

Appearance polyAppear = new Appearance();

polyAppear.setPolygonAttributes(polyAttrib);

objSpin.addChild(new

Shape3D(twist.getGeometry(), polyAppear));

Alpha rotationAlpha = new Alpha(-1,

16000);

RotationInterpolator rotator = new

RotationInterpolator(rotationAlpha,

objSpin);

// a bounding sphere specifies a region a

behavior is active

// create a sphere centered at the origin

with radius of 1

BoundingSphere bounds = new

BoundingSphere();

http://tailieuhay.com 316

Page 317: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

rotator.setSchedulingBounds(bounds);

objSpin.addChild(rotator);

// make background white

Background background = new

Background(1.0f, 1.0f, 1.0f);

background.setApplicationBounds(bounds);

contentRoot.addChild(background);

// Let Java 3D perform optimizations on

this scene graph.

contentRoot.compile();

return contentRoot;

} // end of CreateSceneGraph method of

TwistStripApp

// Create a simple scene and attach it to the

virtual universe

public TwistStripApp() {

setLayout(new BorderLayout());

Canvas3D canvas3D = new Canvas3D(null);

add("Center", canvas3D);

BranchGroup scene = createSceneGraph();

// SimpleUniverse is a Convenience

Utility class

http://tailieuhay.com 317

Page 318: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

SimpleUniverse simpleU = new

SimpleUniverse(canvas3D);

// This will move the ViewPlatform back a

bit so the

// objects in the scene can be viewed.

simpleU.getViewingPlatform().setNominalViewingTra

nsform();

simpleU.addBranchGraph(scene);

} // end of TwistStripApp constructor

// The following method allows this to be run

as an application

public static void main(String[] args) {

System.out.println("TwistStripApp - Java

3D API version 1.1");

System.out.print("See \"Getting Started

with the Java 3D API\"");

System.out.println(" (section 2.6)");

System.out.println("This program

demonstrates back face culling.");

System.out.print("In this program two

visual objects rotate, ");

http://tailieuhay.com 318

Page 319: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

System.out.println("one wireframe and one

solid surface.");

System.out.print("The wire frame is

visible only when components");

System.out.println(" of the surface are

culled.");

Frame frame = new MainFrame(new

TwistStripApp(), 256, 256);

} // end of main method of TwistStripApp

} // end of class TwistStripApp

Trong hình 2-23 việc vô hiệu hóa chọn lọc bề mặt rõ ràng đã điền đầy

vùng bị vỡ. Bây giờ thì tất cả các đa giác đều được dựng dù hướng quay

của nó là gì chăng nữa.

http://tailieuhay.com 319

Page 320: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Phần mặt phía trước của một đa giác là mặt dùng để các đỉnh xuất

hiện theo chiều quay ngược kim đồng hồ. Điều này thường liên quan đến

“luật tay phải”. Luật này dùng để xác định phần mặt trước của một dải

hình học (chẳng hạn dải tam giác hoặc dải hình vuông thay thế cho mỗi

thành phần trong dải. Hình 2-24 chỉ ra một ví dụ sử dụng luật tay phải)

2.7 Bounds and Scope

Bound định nghĩa một không gian, một vùng cho mỗi nút. Bounds

được định nghĩa các đối tượng như BoundingSphere, BoundingBox,

BoundingPolytope. Để tiếp tục với ví dụ ánh sáng , mỗi nguồn sáng định

nghĩa một vùng ảnh hưởng gọi là vùng biên giới quét . Nếu bất kì thành

phần nào của một đối tượng quan sát giao với luồng sáng thì đối tượng sẽ

bị ảnh hưởng bởi luồng sáng

Phần về Bounds được đặt ở phần 1.9 mô tả mỗi đối tượng hành vi có

một vùng riêng. Một hành vi chỉ được kích hoạt khi biên giới của nó giao

với phần nhìn.

Scope chỉ ra một nhóm các đối tượng đồ thị khung cảnh bằng vị trí của

chúng trong đồ thị khung cảnh. Đặc biệt một Scope là một tập các đối

tượng Group (chừng hạn BranchGroup). Một node có thể chỉ ra các đối

http://tailieuhay.com 320

Page 321: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

tượng đồ thị khung cảnh khác nhau khi chúng ảnh hưởng bởi một tầm

quan sát.

Trong khi Bounds và scope cung cấp các tính năng khác nhau nhưng

chúng lai hoạt động theo những cách khác nhau. Một vùng biên giới độc

lập với vị trí của một đối tượng trong đồ thị khung cảnh. Trong khi đó

một phạm vi độc lập với đối tượng quan sát trong môi trường ảo.Chúng

được sử dụng trong nhiều ứng dụng, thêm vào đó ánh sáng và các hành vi

được sử dụng, như sương mù, âm thanh sẽ được nói phần sau của chương

này, đối với các nút AlternativeAppearance.

2.7.1 Bounds Node Components

Một đối tượng biên giới Bound được tham chiếu đến bởi các đối

tượng cần định nghĩa biên giới biên giới cho phép người lập trình đa dạng

hóa các hành động và bề mặt hoặc âm thanh trong một vung đất ảo.

Bound cũng cho phép hệ thông dựng hình của Java 3D hoạt động hiệu

quả hơn.

Các vùng biên giới được định nghĩa băng một số lớp. Bound là lớp

trừu tượng là lớp cơ sở cho các lớp biên giới. Đối tượng Bound định

nghĩa các vùng lồi kín, được sử dụng trong rất nhiều tương tác và chọn

lọc, 3 lớp mở rộng của nó là BoundingBox, BoundingPolytope, và

BoundingSphere

Khi lựa chọn một đối tượng Bound không phụ thuộc vào chi tiết của

ứng dụng, nhớ rằng những hoạt động nhỏ lẻ khác nhau trong một biên

giới sẽ được tính toán trong vùng giao nhau. BoundingSphere là dễ nhất

trong khi đó BoundingPolytope là khó nhất. Nếu bạn có rất nhiều đối

tượng Bound đang sử dụng, những hoạt động nhỏ cũng có thể thêm vào

và gây ra khác biệt rõ ràng đến toàn bộ hiệu năng của ứng dụng.

Cuối cùng phải nhớ rằng với các vùng biên giới nhỏ thì hành động càng

ít, và nên làm như vậy khi tạo các vùng biên giới.

http://tailieuhay.com 321

Page 322: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Bounds Method Summary (partial list)

Bounds là lớp trừu tượng, do đó các phương thức liệt kê dưới đây là tất

cả các phương thức trừu tượng và cụ thể của BoundingBox,

BoundingPolytope, và BoundingSphere

Bounds closestIntersection(Bounds[] boundsObjects)

Tìm đối tượng trong biên giới gần nhất mà giao với vùng biên giới này.

void combine(Bounds boundsObject)

Kết nối đối tượng bị bao này với đối tượng bao. Ta có 2 phương thức sau.

boolean equals(java.lang.Object Bounds)

Chỉ ra khi nào đối tượng bao này tương đương với đối tượng bao khác.

boolean intersect(Bounds boundsObject)

Kiểm tra sự giao nhau giữa các đối tượng bao.

boolean isEmpty()

Tests whether the Bounds is empty.

Kiểm tra khi nào các biên giới bao bị rỗng.

void set(Bounds boundsObject)

Lập giá trị cho đối tượng bao.

void transform(Transform3D trans)

Biến đổi đối tượng được bao dựa trên ma trận đưa ra.

BoundingSphere

BoundingSphere Constructor Summary (partial list)

BoundingSphere()

Tạo và định giá trị cho một BoundingSphere với bán kính bằng 1 tại 0 0 0

BoundingSphere(Point3d center, double radius)

Tạo và định giá trị cho một BoundingSphere với bán kính và tâm cho

trước

http://tailieuhay.com 322

Page 323: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

BoundingSphere(Bounds boundsObject)

Tạo và định giá trị cho một BoundingSphere từ đối tượng cho trước.

BoundingSphere(Bounds[] boundsObjects)

Tạo và định giá trị cho một BoundingSphere từ một mảng các đối tượng

bao

BoundingSphere Method Summary (partial list)

void setCenter(Point3d center)

Lập vị trí của vùng bao cầu từ một điểm

void setRadius(double r)

Lập bán kính của hình cầu bao.

BoundingBox

BoundingBox Constructor Summary

Lớp này định nghĩa một hình hộp bao thẳng trục được sử dung cho vùng

bao.

BoundingBox()

Thiết lập và khởi tạo một hình hộp bao kích thước 2 tâm ở gốc.

BoundingBox(Point3d lower, Point3d upper)

Thiết lập và khởi tạo một hình hộp bao biết trước điểm thấp điểm cao trên

x,y, z.

BoundingBox(Bounds boundsObject)

Thiết lập một hình hộp bao từ một hình sẵn có.

BoundingBox(Bounds[] Bounds)

Lập một hình hộp bao với một mảng các đối tượng bao.

http://tailieuhay.com 323

Page 324: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

BoundingBox Method Summary (partial list)

void setLower(double xmin, double ymin, double zmin)

Sets the lower corner of this bounding Box.

Lập góc dưới của hình hộp bao.

void setLower(Point3d p1)

Lập góc dưới của hình hộp bao.

void setUpper(double xmax, double ymax, double zmax)

Lập góc trên của hình hộp bao.

void setUpper(Point3d p1)

Lập góc trên của hình hộp bao.

BoundingPolytope

Một đối tượng BoundingPolytope định nghĩa một vùng đa diện sử

dụng phép giao giữa 4 hoặc hơn một nửa không gian. Một nửa không gian

là một vùng không gian bao quanh một mặt qua một mặt phẳng. Kết quả

là địng nghĩa BoundingPolytope dựa vào danh sách các mặt phẳng mà

tạo nên một vùng đóng.

BoundingPolytope Constructor Summary

BoundingPolytope()

Tạo một BoundingPolytope định nghĩa nó dựa trên tập 6 mặt phẳng

giống như hình lập phương

-1 <= x, y, z <= 1.

BoundingPolytope(Vector4d[] planes)

Tạo một BoundingPolytope sử dụng các mặt cho trước.

BoundingPolytope(Bounds boundsObject)

Tạo một BoundingPolytope ngoại tiếp một mặt bao cho trước.

BoundingPolytope(Bounds[] boundsObjects)

http://tailieuhay.com 324

Page 325: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Tạo một BoundingPolytope vây quanh một mảng các bao.

BoundingPolytope Method Summary (partial list)

int getNumPlanes()

Trả về số mặt phẳng của đối tượng BoundingPolytope.

void getPlanes(Vector4d[] planes)

Trả về giới hạn của các mặt phẳng cho bao đa diện này.

void setPlanes(Vector4d[] planes)

Lập các mặt phẳng cho bao này.

2.7.2 BoundingLeafa Node

Các biện giới bình thường sử dụng một đối tượng bao để chỉ ra một

vùng được bao quanh. Kết quả trong đồ thị khung cảnh là đối tượng

Bound di chuyển với đối tượng tham chiếu đến nó. Điều này là tố cho

nhiều ứng dụng tuy nhiên có một vài trường hợp lại cần vùng bao di

chuyển độc lập với đối tượng sử dụng vùng bao

Ví dụ như nếu một thế giớibao gồm nguồn sáng cố định chiếu sáng

vào đối tượng đang di chuyển thì vùng biên giới của ánh sáng phải bao

gồm cả đối tượng di chuyển. Một cách để nắm bắt điều này là làm cho

vùng bao rộng đủ để chứa tất cả những nơi mà đối tượng di chuyển đến.

Đây không phải là câu trả lời tốt nhất cho mọi trường hợp. Một cách giải

quyết tốt hơn là sử dụng BoundingLeafa. Đặt trên đồ thị khung cảnh với

đối tượng quan sát đối tượng BoundingLeafa di chuyển với đối tượng

quan sát và độc lập với nguồn sáng. Hình 2-25 chỉ ra một đồ thị khung

cảnh với một nguồn sáng sử dụng BoundingLeafa.

http://tailieuhay.com 325

Page 326: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Khi các ứng dụng cho BoundingLeafa bao gồm ApplicationBounds

của đối tượng Background, SchedulingBounds của Behaviors, và

InfluencingBounds của Lights, không gây cảm giác lặp lại thông tin trên

cả vùng.

Một trong những ứng dụng khá hay của đối tượng BoundingLeafa là

đặt một BoundingLeafa trên viewPlatform. BoundingLeafa này có thể

sử dụng liên tục trên một vùng bao cho các hành vi hoặc luôn luôn chấp

nhận các ứng dụng bao như nền hoặc sương mù.Ví dụ trong đoạn mã 2-11

sử dụng nguyên tắc đó.

Dòng 2,3,4 tạo đối tượng BoundingLeafa, và PlatformGeometry,

đồng thời làm cho đối tượng BoundingLeafa trở thành con của

PlatformGeometry. Đối tượng PlatformGeometry được thêm vào

nhánh hình thức của đồ thị khung cảnh ở dòng 6.

http://tailieuhay.com 326

Page 327: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

BoundingLeafa Class

Các phi tham số của hàm tạo cho BoundingLeafa tạo một đơn vị

hình cầu bao.

BoundingLeafa Constructor Summary

The BoundingLeafa node defines a bounding region object that can be

referenced by other nodes to define a region of influence, an activation

region, or a scheduling region.

Nút BoundingLeafa dùng để định nghĩa một đối tượng vùng bao có thể

được tham chiếu đến bằng các nút khác nahu để định nghĩa một vùng ảnh

hưởng, một vùng kích hoạt hoặc một vùng danh mục.

BoundingLeafa()

Tạo một nút BoundingLeafa với một đối tương đơn vị hình cầu

BoundingLeafa(Bounds region)

Tạo một nút BoundingLeafa với vùng định trước.

BoundingLeafa Method Summary

Bounds getRegion()

Nhật vùng BoundingLeafa.

void setRegion(Bounds region)

Sets this BoundingLeafa node's bounding region.

Lập vùng bao của nút BoundingLeafa.

2.7.3 Scope

Như đã giới thiệu ở phía trên, định nghĩa một scope (tầm quan sát) là

một cách để giới hạn ứng dựng hay ảnh hưởng của một nút. Nút định

nghĩa một phạm vi quan sát có thể ảnh hưởng tới đối tượng của của đồ thị

con có gốc tại đối tượng Group. Khi không có một phạm vi quan sát cho

một nút ta gọi nút đó có phạm vi quan sát toàn cầu. Điều đó có nghĩa là

http://tailieuhay.com 327

Page 328: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

nút đó có thể quan sát hoàn toàn trong môi trường ảo và chỉ bị giới hạn

bởi môi trường ảo.

Một vài nút cho phép chỉ ra cả vùng biên giới và phạm vi quan sát

nhưng việc chỉ định một phạm vi quan sát không thể thay thế cho một

vùng biên giới. Đối với một nút có một hiệu ứng trên một đối tượng đối

tượng cần phải có cả biên giới lẫn phạm vi quan sát. Một nút không có

phạm vị sẽ không ảnh hưởng được các đối tượng khác.

Một phạm vi quan sát dùng để giới hạn ứng dụng của một nút khi sử

dụng mình vùng bao sẽ rất khó khăn hoặc không thể làm. Việc gọi lại một

vùng bao để khi một thứ gì đó ứng dựng trên thế giới ảo. Có thể hiểu rằng

khi sử dụng một vùng bao để phân biệt giữa các đối tượng mà nằm gần

nhau là rất khó khăn. Thực tế, cũng có những trường hợp sử dụng được .

Nếu 2 đối tượng quan sát chạm hoặc chồng lên nhau và một đối tượng có

thể bao gồm vùng bao hoặc là đối tượng kia. Hiện tượng này không

thường xảy ra như ví dụ dưới đây.

Một khung cảnh chứa một ngọn đèn và một vài đối tượng quan sát

trên bàn. Ngọn đèn có một bóng, vì thế không phải tất cả các đối tượng sẽ

được chiếu sáng bởi chiếc đèn này. Nếu chỉ sử dụng vùng bao sẽ rất khó

để chỉ ra ứng dụng ánh sáng đúng đắn khi đèn tắt và bật giữa các đối

tượng gần nhau.

Định nghĩa phạm vi giới hạn cho nguồn sáng dễ dàng hơn điều khiển ánh

sáng trong khung cảnh. Đồ thị khung cảnh trong hình 2-26 là một giải

pháp. Đồ thị này chia ra các đối tượng được chiếu sáng và không được

chiếu sáng thành 2 nhánh của đồ thị khung cảnh. Chỉ định các nhóm được

chiếu sáng bao gồm cả đối tượng được rọi sán. Thường thì không cần

thiết phải tổ chức một đồ thị khung cảnh xung quanh vùng quan sát.

http://tailieuhay.com 328

Page 329: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

2.8 Hình học nâng cao

Java 3D API phiên bản 1.2 đưa ra 2 mở rộng lớn đối với các lớp sử

dụng các hình học. Thứ nhất cho nhiều hình học trở thành các nút thành

phần của một nút Shape3D. Tính năng này cho phép dựng hình hiệu quả

hơn.

Một tính năng khác là cho phép dữ liệu hình học có thể tham chiếu

bằng đối tượng hình học thay vì phải sao chép. Việc sao chép dữ liệu chỉ

thực hiện trong các phiên bản trước của 1.2 . Việc sao chép dữ liệu làm

mất thời gian và công sức, sử dụng việc tham chiếu trực tiếp tăng hiệu

quả nhiều chương trình.

2.8.1 Multiple Geometries in a Single Shape3D

Chương 1 giới thiệu về lớp Shape3D phần 2.2.1 giới thiệu Shape3D

với định nghĩa của đối tượng quan sát và chỉ ra cách sử dụng cơ bản của

đối tượng Shape3D. Phiên bản 1.2 thêm rất nhiều phương thức tới lớp

http://tailieuhay.com 329

Page 330: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Shape3D cho phép đối tượng Shape3D có thể tham chiếu đến nhiều đối

tượng thành phần hình học. Tính năng mới này giảm thiểu số lượng đối

tượng trong đồ thị khung cảnh.

Trong AxisApp.java giới thiệu trong phần 2.5.1 sử dụng 3 đối tượng

LineArraty để vẽ các đường đại diện cho 3 trục tọa độ trong không gian,

ngoài ra trong chương trình có 3 đối tượng Shape3D tương đương với 3

đối tượng hình học. Tuy nhiên trong ví dụ AxisApp2.java có sử dụng 1

đối tượng Shape3D, nó tham chiếu đến nhiều đối tượng thành phần hình

học khác.Xem hình 2-27

Như trong đoạn mã 2-12 có thể thấy ta chỉ tạo một đối tượng

Shape3D nhưng có thể tham chiếu đến 3 đối tượng thành phần hình học.

Shape3D Geometry Equivalence Classes

Nút là Shape3D chứa một danh sách 1 hoặc nhiều đối tượng thành phần

hình học và một đối tượng thành phần giao diện. Danh sách đối tượng

hình học có thể tương đương với các lớp và có cùng kiểu với các lớp hình

học cơ bản. Sự cân bằng thể hiện đươi đây:

Point GeometryArray: [Indexed]PointArray

Line GeometryArray: [Indexed]{LineArray, LineStripArray}

Polygon GeometryArray: [Indexed]{TriangleArray, TriangleStripArray,

TriangleFanArray,

QuadArray}

http://tailieuhay.com 330

Page 331: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

CompressedGeometry

Geometry

Text3D

Với sự hạn chế của danh sách đối tượng Shape3D tới một lớp hình học

tương đương cho thấy sự cải tiến này có vẻ không có gì là cải tiến. Một

lần nữa 3 đối tượng lineArray định nghĩa hình cho hoặc AxisApp có thể

thay thế bằng một đối tượng và một đối tượng Shape3D.

Shape3D Method Summary (partial list, see Section 2.2.1)

void addGeometry(Geometry Geometry) <new in 1.2>

Gắn đối tượng hình học tới danh sách của nút Shape3D gồm các thành

phần hình học

java.util.Enumeration getAllGeometries() <new in 1.2>

Trả về liệt kê danh sách các thành phần hình học.

Geometry getGeometry(int index) <new in 1.2>

Lấy các thành phần hình học tại vị trí index trong danh sách.

void insertGeometry(Geometry Geometry, int index) <new in 1.2>

Chèn thêm một thành phần hình học vào danh sách tại vị chí chỉ mục cho

trước.

int numGeometries() <new in 1.2>

Trả về số thành phần hình học trong danh sách.

void removeGeometry(int index) <new in 1.2>

Loại bỏ thành phần hình học tại vị trí chỉ mục cho trước trong danh sách.

void setGeometry(Geometry Geometry, int index) <new in 1.2>

Thay thế thành phần hình học tại vị trí chỉ mục cho trước trong danh sách

với một thành phần khác.

http://tailieuhay.com 331

Page 332: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

2.8.2 GeometryArray

Trong việc xây dựng hình các bước là tạo một đối tượng hình học, rồi

đăng kí giá trị cho nó để định nghĩa dữ liệu hình học (tạo độ, màu ...) .

Với phiên bản 1.2 cho phép lời gọi BY_REFERENCE thay thế cho việc

sao chép dữ liệu hình học. Việc này khi ở phiên bản cũ là đối tượng sao

chép GeometryArray được khởi tạo có một mảng private lưu giữ toàn bộ

dữ liệu này bên trong đối tượng GeometryArray. Sau đó khi dữ liệu hình

học được đăng kí với GeometryArray nó được sao chép vào mảng này.

Khi đối tượng GeometryArray BY_REFERENCE được tạo người dùng

tạo một mảng hình học và quản lí mảng này với dữ liệu hình học. Và vì

thế không có mảng bên trong đối tượng hình học.

Vậy khi nào cần sử dụng BY_REFERENCE, có 2 lí do sử dụng nó là:

1. Nếu dữ liệu hình học là động

2. Nếu dữ liệu hình học cần sử dụng nhiều bộ nhớ

Lí do lớn nhất để chọn phương pháp này là dữ liệu có thể thay đổi

thậm chí đối tượng đang sống hoặc được dịch. Cách thay đổi hình chính

là thay đối dữ liệu của nó, cách khác là phân chia mảng sử dụng bởi đối

tượng hình học.

Những gợi ý và cảnh báo khi sử dụng BY_REFERENCE

Nếu sử dụng BY_REFERENCE, sử dụng phương thức set*RefFloat là tốt

hơn cả. Ví dụ, sử dụng setCoordRefFloat()thay vì setCoordRef3f()sử

dụng mảng số thực cho phép truy cập trực tiếp hơn là sử dụng một mảng

các đối tượng. Một mảng các đối tượng trong Java 3D luôn luôn lưu trữ

các tham chiếu hơn là giá trị thực vì chỉ các mảng có kiểu dữ liệu như

thực mới lưu dữ liệu.

Nhớ rằng khi sử dụng BY_REFERENCE phương thức sử dụng khác với

khi không sử dụng nó. Người lập trình phải có trách nhiệm đảm bảo cho

kiểu dữ liệu đúng đắns.

http://tailieuhay.com 332

Page 333: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Ví dụ GeometryArray BY_REFERENCE

Sử dụng BY_REFERENCE Geometry với GeometryArray cho đối

tượng hình học tĩnh không khó hơn sao chép Geometry. Trong đoạn ma

2-13 được lấy từ chương trình TwistByRefApp.java, sử dụng tham chiếu

đến dữ liệu hình học thay vì cách cũ, trong trường hợp này tạo độ và màu

được người dùng tạo thành 2 mảng coord và color.

Việc dùng được thực hiện theo các bước sauL

• Khai báo mảng để giữ các dữ liệu hình học

• Tạo đối tượng GeometryArray mong muốn bằng tùy chọn định

dạng đỉnh BY_REFERENCE. Trong trường hợp này đối tượng

GeometryArray là một mảng TriangleStripArray.

• Điền đầy giá trị cho mảng TriangleStripArray

Tham chiếu đến dữliệu người dùng với đối tượng GeometryArray.

Thứ tự của các bước có thể thay đổi khi mảng sử dụng được khai báo

trước khi chúng được tham chiếu hoặc điền giá trị và đối tượng

GeometryArray được tạo trước khi mảng được tham chiếu.

// //////////////////////////////////////////

/////

//

// create scene graph branch group

//

public BranchGroup createSceneGraph() {

BranchGroup contentRoot = new

BranchGroup();

http://tailieuhay.com 333

Page 334: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

// Create the transform group node and

initialize it to the

// identity. Add it to the root of the

subgraph.

TransformGroup objSpin = new

TransformGroup();

objSpin.setCapability(TransformGroup.ALLOW_TRANSF

ORM_WRITE);

contentRoot.addChild(objSpin);

Shape3D twist = new Twist();

objSpin.addChild(twist);

// Duplicate the twist strip geometry and

set the

// appearance of the new Shape3D object

to line mode

// without culling.

// Add the POLYGON_FILLED and

POLYGON_LINE strips

// in the scene graph at the same point.

// This will show the triangles of the

original Mobius strip that

// are clipped. The PolygonOffset is set

to prevent stitching.

PolygonAttributes polyAttrib = new

PolygonAttributes();

http://tailieuhay.com 334

Page 335: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

polyAttrib.setCullFace(PolygonAttributes.CULL_NON

E);

polyAttrib.setPolygonMode(PolygonAttributes.POLYG

ON_LINE);

polyAttrib.setPolygonOffset(0.001f);

Appearance polyAppear = new Appearance();

polyAppear.setPolygonAttributes(polyAttrib);

objSpin.addChild(new

Shape3D(twist.getGeometry(), polyAppear));

Alpha rotationAlpha = new Alpha(-1,

16000);

RotationInterpolator rotator = new

RotationInterpolator(rotationAlpha,

objSpin);

// a bounding sphere specifies a region a

behavior is active

// create a sphere centered at the origin

with radius of 1

BoundingSphere bounds = new

BoundingSphere();

rotator.setSchedulingBounds(bounds);

objSpin.addChild(rotator);

http://tailieuhay.com 335

Page 336: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

// make background white

Background background = new

Background(1.0f, 1.0f, 1.0f);

background.setApplicationBounds(bounds);

contentRoot.addChild(background);

// Let Java 3D perform optimizations on

this scene graph.

contentRoot.compile();

return contentRoot;

} // end of CreateSceneGraph method of

TwistStripApp

GeometryArray

Lớp GeometryArray là lớp cơ sở của nhiều lớp hình học khác. Vì thế

nó định nghĩa rất nhiều phương thức cho việc quản lí dữ liệu.Để sử dụng

tham chiếu hình học,lập bit BY_REFERENCE trong trường định dạng

đỉnh trong hàm tạo của đối tượng GeometryArray.

GeometryArray Methods for Referencing Geometry Data (partial

list)

This collection of methods set the references to Geometry data in user

arrays. In each case, the method will throw an exception if the data mode

for this Geometry array object is not BY_REFERENCE. In some cases

the data mode must also be INTERLEAVED, in other cases the data

mode must not be INTERLEAVED.

Đây là các phương thức dùng để tham chiếu đến dữ liệu hình học trên

mảng sử dụng. Trong mỗi trường hợp phương thức sẽ đưa ra ngoại lệ nếu

http://tailieuhay.com 336

Page 337: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

chế độ dữ liệu không chọn là BY_REFERENCE, trong một số trường hợp

chế độ dữ liệu có thể là INTERLEAVED, trong một số trường hợp không

được phép là INTERLEAVED.

void setColorRef*(Color*[] colors) <new in 1.2>

Sets the color array reference to the specified Color* (Color3b, Color3f,

Color4b, or Color4f) array.

void setColorRefByte(byte[] colors) <new in 1.2>

Sets the byte color array reference to the specified array.

void setColorRefFloat(float[] colors) <new in 1.2>

Sets the float color array reference to the specified array.

void setCoordRef*(Point*[] coords) <new in 1.2>

Sets the coordinate array reference to the specified Point* (Point3d,

Point3f) array.

void setCoordRefDouble(double[] coords) <new in 1.2>

Sets the double coordinate array reference to the specified array.

void setCoordRefFloat(float[] coords) <new in 1.2>

Sets the float coordinate array reference to the specified array.

void setInterleavedVertices(float[] vertexData) <new in 1.2>

Sets the interleaved vertices array reference to the specified array.

void setNormalRef3f(Vector3f[] normals) <new in 1.2>

Sets the Vector3f normal array reference to the specified array.

void setNormalRefFloat(float[] normals) <new in 1.2>

Sets the float normal array reference to the specified array.

void setTexCoordRef*(int texCoordSet, TexCoord*[] texCoords)

<new in 1.2>

Sets the texture coordinate array reference for the specified texture

coordinate set to the specified

TexCoord* (TexCoord2f, TexCoord3f) array.

http://tailieuhay.com 337

Page 338: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

void setTexCoordRefFloat(int texCoordSet, float[] texCoords) <new

in 1.2>

Sets the float texture coordinate array reference for the specified texture

coordinate set to the specified array.

Một cách đơn giản để thay đổi hình học sử dụng BY_REFERENCE là

thay đối số giá trị sử dụng trong một mảng. Dưới đây là các phương thức

để thay đối giá trị dữ liệu hình học. Tất nhiên nó chỉ có tác dụng nếu chế

độ BY_REFERENCE. Các phương thức này chỉ được cho phép hoạt

động trên các đối tượng đang sống hoặc đang dịch khi khả năng

ALLOW_REF_DATA_WRITE được lập.

GeometryArray Methods for Setting Initial Location of Referenced

Geometry Data (partial list)

void setInitialColorIndex(int initialColorIndex) <new in 1.2>

Sets the initial color index for this GeometryArray object. This method

is easily confused with the

setInitialVetrexIndex method which is used when the Geometry is not

BY_REFERENCE.

void setInitialCoordIndex(int initialCoordIndex) <new in 1.2>

Sets the initial coordinate index for this GeometryArray object.

void setInitialNormalIndex(int initialNormalIndex) <new in 1.2>

Sets the initial normal index for this GeometryArray object.

void setInitialTexCoordIndex(int texCoordSet, <new in 1.2>

int initialTexCoordIndex)

Sets the initial texture coordinate index for the specified texture

coordinate set for this GeometryArray object.

http://tailieuhay.com 338

Page 339: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

GeometryArray Capabilites

BY_REFERENCE <new in 1.2>

Specifies the position, color, normal, and texture coordinate data for this

object are accessed by reference

INTERLEAVED <new in 1.2>

Specifies that the position, color, normal, and texture coordinate data for

this GeometryArray are

accessed via a single interleaved, floating-point array reference. This is

only used in by-reference

Geometry mode.

ALLOW_COUNT_READ | WRITE <new in 1.2>

allow write access to the count or initial index information for this object

ALLOW_REF_DATA_READ <new in 1.2>

allow read access to the Geometry data reference information; only used

in by-reference Geometry mode

ALLOW_REF_DATA_WRITE <new in 1.2>

allow write access to the Geometry data reference information for this

object. It also enables writing the referenced data itself, via the

GeometryUpdater interface. This is only used in by-reference Geometry

mode.

Dữ liệu hình học trong bất cứ mảng nào được tham chiếu đến bởi một

đối tượng GeometryArray sống hoặc đang được dịch có thể thay đổi

thông qua phương thức updateData của nó. Các ứng dụng đều phải quan

tâm tránh để vi phạm luật này.

http://tailieuhay.com 339

Page 340: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

updateData method of GeometryArray

public void updateData(GeometryUpdater updater) <new in 1.2>

Cập nhật mảng dữ liệu được truy cập thông qua tham chiếu. Phương thức

gọi updateData của đối tượng GeometryUpdater để đồng bộ cập nhật với

dữ liệu đỉnh được tham chiếu bởi đối tượng GeometryArray.

2.8.4 AlternateAppearance <new in 1.2>

Như đã thấy trong phần 2.6.1 đối tượng Shape3D có thể có một tham

chiếu đến nút thành phành Appearance. Gói giao diện này định nghĩa các

thuộc tính quan sát của đối tượng Shape3D. Xem hình 2-20 và 2-37.

Phần 2.6.2 mô tả làm thế nào có thể chia sẻ một gói giao diện giữa các đối

tượng Shape3D.

Một AlternateAppearance cho phép người phát triển ứng dụng có

thể phát triển các phương thức thay thế cho việc chia sẻ một gói giao diện

giữa các đối tượng Shape3D. Nó là một cách thay thế cho việc chia sẻ gói

giao diện – đưa ra cách dễ dàng hơn để tạm thời thay đổi giao diện. Có 3

cách. Thứ nhất đối tượng phải nằm trên trên vùng bao của

AlternateAppearance. Thứ 2 phải có một giới hạn quan sát trên ứng

dụng của nó. Thứ 3 chỉ những đối tượng quan sát cho phép giao diện của

nó được ghi đề đưa ra cho AlternateAppearance

Sử dụng AlternativeAppearance Node

Để sử dụng AlternateAppearance đầu tiện phải tạo gói giao diện để

sử dụng phép thay thế và tham chiếu đến gói giao diện bằng đối tượng

AlternativeAppearance. Sau đso lập vùng ảnh hưởng thông qua đối tượng

Bounds hoặc BoundingLeafa. Tạo một phạm vi quan sát cho

AlternateAppearance theo ý mình. Đừng quên thêm

AlternateAppearance vào đồ thị khung cảnh, lập cờ

appearanceOverrideEnable trên đối tượng Shape3D.

http://tailieuhay.com 340

Page 341: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Shape3D setAppearanceOverrideEnable() Method

void setAppearanceOverrideEnable(boolean flag) <new in 1.2>

Lập cờ chỉ ra khi nào một giao diện của một nút được ghi đè bằng một nút

AlternativeAppearance. Phương thức này có thể gọi khi đối tượng đang

sống hoặc dịch tùy theo khả năng nó được lập thế nào.

Shape3D Capabilities (partial list, see Section 2.2.1)

ALLOW_APPEARANCE_OVERRIDE_READ | WRITE <new in

1.2>

cho phép truy cập đọc/ghi tới cờ appearanceOverrideEnable

AlternativeAppearance Class <new in 1.2>

Các phần dưới là danh sách hàm tao cho lớp AlternateAppearance

AlternateAppearance Constructor Summary

AlternateAppearance() <new in 1.2>

Khởi tạo một nút AlternateAppearance với các tham số mặc định:

Appearance, scope,

influencingBounds, và influencingBoundingLeaf = null

AlternateAppearance(Appearance Appearance) <new in 1.2>

Tạo một nút AlternateAppearance với giao diện cho trước.

AlternateAppearance Method Summary (partial list)

void addScope(Group scope) <new in 1.2>

Gắn một nút Group cho trước tới danh sách nút AlternateAppearance

của phạm vi quan sát.

http://tailieuhay.com 341

Page 342: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

java.util.Enumeration getAllScopes() <new in 1.2>

Trả về bảng liệt kê danh sách nút AlternateAppearance của phạm vi

quan sát.

void insertScope(Group scope, int index) <new in 1.2>

Chèn vào một nút Group cho trước vào danh sách tại chỉ số cho trước.

int numScopes() <new in 1.2>

Trả về số nút trong danh sách.

void removeScope(int index) <new in 1.2>

Loại bỏ nút tại vị trí cho trước trong danh sách.

void setAppearance(Appearance Appearance) <new in 1.2>

Lập giao diện cho nút AlternateAppearance

void setInfluencingBoundingLeaf(BoundingLeafa region) <new in

1.2>

Sets the AlternateAppearance's influencing region to the specified

bounding leaf.

Lập vùng ảnh hưởng của AlternateAppearance tới lá bao cho trước.

void setInfluencingBounds(Bounds region) <new in 1.2>

Lập vùng ảnh hưởng của AlternateAppearance tới vùng bao cho trước.

void setScope(Group scope, int index) <new in 1.2>

Thay thế vị trí của nút tại vị trí chỉ mục trong danh sách với một nút

Group cho trước.

Những khả năng của lớp AlternateAppearance

AlternativeAppearance Capabilities

ALLOW_APPEARANCE_READ | WRITE allow read (write) access

to its Appearance information

ALLOW_INFLUENCING_BOUNDS_READ | WRITE allow read

(write) access to its influencing Bounds and bounding leaf information

http://tailieuhay.com 342

Page 343: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

ALLOW_SCOPE_READ | WRITE allow read (write) access to its

scope information at runtime

2.9 Clipping – Cắt xén

Chủ đề của Clipping không thực sự là việc tạo hình nhưng một trong

những nhân tố ảnh hưởng đến hình ảnh trong như thế nào. Ví dụ khi môt

hình mở rộng đến vùng biên nên nó bị cắt đi vì thế một số hình không

xem được. Cắt xén là một chủ đề phức tạp, phần này đưa ra các vấn đề cơ

bản nhất trong việc cắt hình .

2.9.1 View Defines a Frustum

Trong chương 1 giới thiệu về hệ tọa độ ảo và mô tả vị trí của mắt liên

quan đến nó. Trong một số trường hợp bạn sẽ bắt gặp hoàn cảnh mà một

đối tượng quan sát không được dựng hình. Lí do thì có rất nhiều, ngoài

đối tượng có thể nằm ngoài vùng frustum (hình cụt). Vùng này là nơi

đối tượng quan sát và các phần của đối tượng quan sát khác được hiển thị.

Hình 2-29 sẽ đưa ra cho bạn định nghĩa rõ hơn về vùng frustum.

Chú ý rằng mặt phẳng cắt phía trước(front clipping plane) nằm đằng

sau màn ảnh(image plate). Điều này là không hợp lệ nhưng nó cũng

không được khuyến khích.

http://tailieuhay.com 343

Page 344: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Phần chóp cụt này được định nghĩa thông vị trí mắt nhìn và 2 mặt

phẳng cắt trước và sau. Giá trị mặt định tương đối hợp lí tuy nhiên người

lập trình có thể thay đổi khoảng cách này.

Nên để

(back clip distance) / (front clip distance) < 3000.

Tuy nhiên thực thế tỉ lệ này thường là từ 100 đến 1000 là hợp lí nhất.

View Methods for Adjusting the Frustum (partial list)

Đối tương View trong phần đồ thị hình thức của đồ thị khung cảnh Java

3D định nghĩa rất nhiều tham số về hình ảnh. Dưới đây là một trong số

đó.

void setBackClipDistance(double distance)

Lập khoảng cách mặt cắt sau với mô hình quan sát, khoảng cách này phải

lớn hơn với khoảng cách của mặt trước.

void setFrontClipDistance(double distance)

Lập khoảng cách mặt cắt trước với mô hình quan sát, khoảng cách này

phải lớn hơn 0.0 và nhỏ hơn khoảng cách sau.

void setFieldOfView(double fieldOfView)

Lập trường ngang mô hình quan sát dạng radians.

http://tailieuhay.com 344

Page 345: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

2.9.2 Clip Node

Như đã nói ở phía trên khoảng cách của hình chóp cụt có thể thay đổi.

Nút cắt là một đối tượng thực hiện điều này. Mỗi Clip định nghĩa một

vùng ứng dụng chỉ ra một đối tượng vùng bao hoặc lá bao. Khi vùng bao

này giao với khu vực quan sát .khoảng cách mặt sau của đối tượng Clip

được sử dụng để dựng. mặt trước định nghĩa bởi đối tượng View không

ảnh hưởng.

Việc sử dụng Clip làm tăng tốc độ xử lí đặc biệt trong những khung

cảnh phức tạp.

Dưới đây là danh sách các hàm tạo và phương thức:

Clip Constructor Summary

Clip()

Tạo một Clip Node với tham số mặc định : backDistance = 100,

ApplicationBounds và applicationBoundingLeaf = null

Clip(double backDistance)

Tạo một Clip node với tham số backDistance

Clip Method Summary

void setApplicationBoundingLeaf(BoundingLeafa region)

Lập vùng ứng dụng cắt tới đối tượng bao lá.

void setApplicationBounds(Bounds region)

Lập vùng ứng dụng cắt tới đối tượng bao.

void setBackDistance(double backDistance)

Lập khoảng cách sau với giá trị cho trước.

http://tailieuhay.com 345

Page 346: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Clip Field Summary

ALLOW_APPLICATION_BOUNDS_READ | WRITE allow read

(write) access to its application Bounds and bounding leaf at runtime.

ALLOW_BACK_DISTANCE_READ | WRITE allow read (write)

access to its back distance at runtime.

Nút ModelClip có thể cắt đối tượng quan sát ra theo nhiều cách. Một

đối tượng ModelClip định nghĩa một tập 6 mặt cắt với hướng tùy ý trong

hệ tọa độ cơ bản. Mặt cắt định nghĩa một nửa không gian cho những đỉnh

được lựa chọn để dựng. Khi giữa các nửa mặt cắt có giao nhau chúng

định nghĩa một vùng mà các điểm trong đó không được dựng, dù chúng ở

trong hình chóp cụt nhìn thấy. Ảnh hưởng này của nút ModelClip được

điều khiển thông qua các vùng được mô tả trước dựa trên ảnh hưởng và

tầm quan sát.

2.9.4 ModelClip Example

Các bước sử dụng ModelClip

• Thiết lập vùng ảnh hưởng cho đối tượng ModelClip

• Chọn hoặc bỏ chọn các mặt cắt tùy theo ý mình

• Lập hướng và vị trí cho mặt phẳng để sử dụng.

• Thêm đối tượng ModelClip vào đồ thị khung cảnh

Mặc dù không thực hiện trong ví dụ này nhưng ModelClip có thể định

nghĩa một phạm vi quan sát.

http://tailieuhay.com 346

Page 347: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Nhớ rằng luôn luôn có 6 mặt phẳng trong đối tượng ModelClip. Kết

quả là mảng Vertor4d được sử dụng trong hàm tạo phải có kich thước 6.

ModelClip Constructor Summary

ModelClip() <new in 1.2>

Tạo một nút ModelClip với tham số mặc định.

ModelClip(Vector4d[] planes) <new in 1.2>

Tạo một nút ModelClip với mặt cho trước.

ModelClip(Vector4d[] planes, boolean[] enables) <new in 1.2>

Tạo một nút ModelClip với mặt cho trước và có thiết lập các cờ.

ModelClip Method Summary (partial list)

void addScope(Group scope) <new in 1.2>

Appends the specified Group node to this ModelClip node's list of scopes.

void insertScope(Group scope, int index) <new in 1.2>

Inserts the specified Group node into this ModelClip node's list of scopes

at the specified index.

int numScopes() <new in 1.2>

Returns the number of nodes in this ModelClip node's list of scopes.

void removeScope(int index) <new in 1.2>

http://tailieuhay.com 347

Page 348: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Removes the node at the specified index from this ModelClip node's list

of scopes.

void setEnable(int planeNum, boolean enable) <new in 1.2>

Sets the specified enable flag of this ModelClip node.

void setEnables(boolean[] enables) <new in 1.2>

Sets the per-plane enable flags of this ModelClip node to the specified

values.

void setInfluencingBoundingLeaf(BoundingLeafa region) <new in

1.2>

Set the ModelClip node's influencing region to the specified bounding

leaf.

void setInfluencingBounds(Bounds region) <new in 1.2>

Set the ModelClip node's influencing region to the specified Bounds.

void setPlane(int planeNum, Vector4d plane) <new in 1.2>

Sets the specified clipping plane of this ModelClip node.

void setPlanes(Vector4d[] planes) <new in 1.2>

Sets the clipping planes of this ModelClip node to the specified planes.

void setScope(Group scope, int index) <new in 1.2>

Replaces the node at the specified index in this ModelClip node's list of

scopes with the specified Group

node.

ModelClip Field Summary

ALLOW_ENABLE_READ | WRITE allow read (write) access to its

enable flags at runtime

ALLOW_INFLUENCING_BOUNDS_READ | WRITE allow read

(write) access to its influencing Bounds and bounding leaf at runtime

http://tailieuhay.com 348

Page 349: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

ALLOW_PLANE_READ | WRITE allow read (write) access to its

planes at runtime

ALLOW_SCOPE_READ | WRITE allow read (write) access to its

scope information at

runtime

http://tailieuhay.com 349

Page 350: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

CHƯƠNG 3

TẠO NỘI DUNG

3.1 Nội dung chính

Trong các chương trước chúng ta đã tìm hiểu cách tạo ra những đối

tượng trực quan bằng các phương pháp đơn giản. Bằng các phương

pháp này công việc lập trình trơ nên buốn tẻ. Trong chương này chúng

ta sẽ xem xét một phưong pháp khác để tạo ra các đối tượng trực quan.

Trong mục 3.2 sẽ giới thiệu lớp GeometryInfo, lớp tiện ích này cung

cấp khả năng tự động hóa trong việc tạo ra các đối tượng trực quan.

Lớp GeometryInfo cũng với các lớp Triangulator, Stripifier, và

NormalGeneration cho phep ta tạo ra cá đối tượng trực quan như là

các đa giác hình học. Các lớp này chuyển đổi đa giác thành tam giác,

và tinh chỉnh các đa giác này.

Mục 3.3 giới thiệu lớp Loader. Lớp này có khả năng tạo ra các dối

tượng trực quan Java3D từ các tệp được tạo bởi các phần mềm 3D. Cụ

thể lớp Loader có thể đọc các file VRML, Lightwave, AutoCad và các

định dạng file 3D khác…Một đặc điểm quan trọng là ta có thể viết các

lớp Loader riêng để phục vụ cho nhu cầu sử dụng.

http://tailieuhay.com 350

Page 351: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Các mục tiếp theo chúng ta sẽ xem xét các kỹ thuật khởi tạo nội dung.

3.1.1 GeometryInfo

Thông thường để vẽ một hình một đối tượng hình học bất kỳ, chúng ta

phải tự làm hoàn toàn và việc code sẽ rất vất vả và nhàm chán. Sử

dụng lớp GeometryInfo công việc sẽ trở nen dễ dàng và thuận tiên

hơn. Khi bắt đầu vẽ một đối tượng hình học, chúng ta sẽ xác định một

đa giác bất kỳ phù hợp với dối tượng đó. Đa giác này có thể là đa giác

lõm, không phẳng … Đối tượng GeometryInfo và các lớp khác sẽ

chuyển các đa giác này thành các tam giác nhỏ hơn, từ đó Java3D có

thể render (tô_chát) .

Để nâng cao hiệu năng của hệ thống chúng ta có thể sử dụng đối tượng

Stripifier để chai các tam giác thành các tam giác rời nhau. Nếu chúng

ta muốn tạo bóng cho đối tượng hình học, ta sử dụng NormalGenerator

để tính toán các vector bề mặt của đối tượng hình học.

3.2.1 Một ví dụ đơn giản về GeometryInfo

Trong phần này chúng ta sẽ xem xét các khởi tạo và sử dụng đối

tượng GeometryInfo. Để khởi tạo một đối tượng GeometryInfo,

chúg ta cần chỉ rõ loại geometry cần dùng: POLYGON_ARRAY,

QUAD_ARRAY, TRIANGLE_ARRAY,

http://tailieuhay.com 351

Page 352: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

TRIANGLE_FAN_ARRAY và TRAINGLE_STRIP_ARRAY. Khi

khởi tọa chúng ta phải chỉ ra coordinate và strip counts.

Chúng ta xét đoạn code dưới đây.

GeometryInfo gi = new

GeometryInfo(GeometryInfo.POLYGON_ARRAY);

gi.setCoordinates(coordinateData);

gi.setStripCounts(stripCounts);

Triangulator tr = new Triangulator();

tr.triangulate(gi);

NormalGenerator ng = new NormalGenerator();

ng.generateNormals(gi);

Stripifier st = new Stripifier();

st.stripify(gi);

Shape3D part = new Shape3D();

part.setAppearance(appearance);

part.setGeometry(gi.getGeometryArray());

- Khởi tạo đối tượng GeometryInfo và thiết lập các thông số cân

thiết (coordinate, stripcounts).

- Sau khi tạo ra đối tượng GeometryInfo, chúng ta có thể sử

dụng các lớp tiện ích khác như NormalGenerator, Triangulator

… bằng cách truyền tham số là đối tượng GeometryInfo.

-

3.2.2 Sử dụng GeometryInfo

Một số chú ý khi sử dụng đối tượng GeometryInfo. Nếu sử dụng

cả NormalGenerator và Stripifier thì ta phải sử dụng NormalGenerator

trước. Normalgenerator và Stripifier đều chỉ sự dụng với các tam giác chỉ

http://tailieuhay.com 352

Page 353: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

mục. Khi sử dụng những lớp tiện ích này, chúng ta không cần quan tâm

đến kiểu của GeometryInfo(POLYGON_ARRAY, QUAD_ARRAY,

STRIP_ARRAY… ), khi đó các dữ liệu này được chuyển đổi thành các

tam giác chỉ mục. Sau khi thực hiện các tam giác chỉ mục này được gắn

liền lại với nhau. Tuy nhiên các thành phần khác của dối tượng

GeometryInfo sẽ bị thay đổi.

3.2.3 Một số lớp thông dụng có liên quan đến GeometryInfo

Trong phần này chúng ta sẽ xem xét kỹ hơn một số lớp thông dụng

nằm trong gói

com.sun.j3d.util.geometry.

http://tailieuhay.com 353

Page 354: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Lớp GeometryInfo có một hàm tạo duy nhất, khi khởi tạo một đối

tượng cần chỉ rõ kiểu của đối tượng Gemetry và hệ trục tọa độ tương

ứng.

Hàm tạo GeometryInfo

Gói: com.sun.j3d.utils.geometry

Lớp cha: java..lang.Object

Sử dụng: Chúng ta muốn chuyển các đối tượng hình học cho đối tượng

GeometryInfo để có thể dùng các lớp tiện ích khác. Khi chúng ta chuyển

đối tượng hình học cần thể hiện cho đối tượng GeometryInfo, các lớp

tiện ích sẽ sử dụng các dữ liệu trong đối tượng GeometryInfo để thực

hiện các yêu cấu của chúng ta.

GeometryInfo(int primitive)

Giá trị của primitive:

POLYGON_ARRAY : Đa giác, các đa giác 2 chiều,3 chiều(đa

diện)

QUAD_ARRAY : Tứ diện

TRIANGLE_ARRAY : Tam giác

TRIANGLE_FAN_ARRAY : Mảng StripCounts cho biết số đỉnh

tương với mỗi tam giác rời

http://tailieuhay.com 354

Page 355: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

TRIANGLE_STRIP_ARRAY : Mảng StripCounts cho biết số đỉnh tương

với mỗi tam giác rời

Lớp GeometryInfo chứ nhiều phương thức, trong đó có các phương

thức theíet lập hay lây thông tin về hệ trục toạ độ, mầu sắc, chỉ mục,

các dữ liệu bề mặt.

Các phưong thức của lớp GeometryInfo

void recomputeIndices()

Thực hiện lại việc sắo xếo để đảm bảo các thông tin kết nối là chính xác.

Gọi hàm này khi các thông tin về hệ trục tọa dộ không chính xác

void reverse()

Đảo ngược thứ tự của tất cả các danh sách

void setColorIndices(int[] colorIndices)

void setColors(Color3f[] colors)

Đặt mảng mầu sắc

void setColors(Color4f[] colors)

Đặt mảng mầu sắc.

void setContourCounts(int[] contourCounts)

Đặt danh sách mầu viền

void setCoordinateIndices(int[] coordinateIndices)

Thiết lập mảng tỷ lệ của hệ trục tọa độ.

void setCoordinates(Point3f[] coordinates)

Thiết lập mảng của hệ trục tọa độ.

void setCoordinates(Point3d[] coordinates)

Thiết lập mảng của hệ trục tọa độ.

void setNormalIndices(int[] normalIndices)

http://tailieuhay.com 355

Page 356: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Thiết lập mảng các chú dẫn.

void setNormals(Vector3f[] normals)

void setNormals(float[] normals)

void setStripCounts(int[] stripCounts)

void setTextureCoordinateIndices(int[] texCoordIndices)

void setTextureCoordinates(Point2f[] texCoords)

Cách sử dụng các lớp tiện ích khác cũng như sử dụng với lớp

GeometryInfo. Sau đây chúg ta sẽ lần lượt xem xét hàm tạovà phương

thức của các lớp Triangulator, Stripifier và NormalGenerator. Đây

cũng chính là thứ tự khi chúng ta làm việc với POLYGON_ARRAY.

Trong đó lớp Triangulator chỉ làm việc với đối tượng hình học kiểu

POLYGON_ARRAY.

http://tailieuhay.com 356

Page 357: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Hàm tạo lớp Triangulator nhằm tạo ra đối tượng tam giác.

Triangulator Constructor Summary

Gói: com.sun.j3d.utils.geometry

Lớp cha: java.lang.Object

Triangulator()

Hàm tạo lớp Triangulator

Triangulator Method Summary

void triangulate(GeometryInfo gi)

Phươn thức chuyển đổi một đối tượng GeometryInfo tùe kiểu nguyên

thuỷ là POLYGON_ARRAY sang kiểu nguyên thuỷ kiểu

TRIANGLE_ARRY.

Hàm tạo lớp Stripifier nhằm tạo ra một đối tượng stripification

Stripifier Constructor Summary

Gói: com.sun.j3d.utils.geometry

Lớp cha: java.lang.Object

Lớp Stripfier có tiện ích đổi kiểu dũ liệu nguyên thuỷ của một đối tượng

GeometryInfo sang kiểu Triangle Strips. Để cho kết quả tốt Normal

Generation phải được thực hiệntrước khi quá trình tách nhỏ đối tượng

hình học.

Stripifier()

Hàm tạo

Pương thức của lớp Stripifier

void stripify(GeometryInfo gi)

http://tailieuhay.com 357

Page 358: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Chuyển GeometryInfo có chứa đối tượng GeometryInfo vào mảng

Triangle Strips.

Lớp NormalGenerator có hai hàm tạo. Hàm tạo thứ nhất tạo ra đối

tượng NormalGenerator với góc gấp có giá trị mặc định. Hàm tạo thứ

hai cho phép thiết lập giá trị cho crease angle.

NormalGenerator Constructor Summary

Gói: com.sun.j3d.utils.geometry

Lớp cha: java.lang.Object

NormalGenerator()

Khởi tạo một NormalGenerator với góc gập mặc định (0.76794 radians,

or 44°).

NormalGenerator(double radians)

Khởi tạo một NormalGenerator với góc gập có giá trị là tham số đầu vào.

Các Phương thức NormalGenerator

void generateNormals(GeometryInfo geom)

double getCreaseAngle()

Lấy giá trị góc gập

void setCreaseAngle(double radians)

Thiết lập góc gập

Các phương thức của lớp NormalGenerator : một phương thức thiết

lập, một phương thức lấy giá trị crease angle …

Loaders

Một lớp Leader đọc các file 3D và tạo ra cácm đối tượng của Java3D

với nội dung cảu file được đưa vào. Sau đó đối tượng 3D này có thể

http://tailieuhay.com 358

Page 359: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

được sử dụng như các đối tuwọng khác của Java3D. Gói

com.sun.j3d.leaders cung cấp các phương thức load các file 3D từ các

chuwong trình ứng dụng khác vào trong chuwong trình Java3D.

Trên thực tế ngày cáng có nhiều các định dạng file 3D từ các ứng dụng

khác nhau, công việc để load các file này không phải là công việc của

Java3D hay của gói loaders, ma chỉ có phần giao diện dùng cho kỹ

thuật loading được đưa vào.

Một ví dụ đơn giản sử dụng leader.

Để load vào nội dung một file, chúng ta không nhất thiết phải sử dụng

một lớp tiện ích để load file đó. Ta sử dụng lớp loader với các bước

như sau:

• Tìm một loader

• Import lớp loader ứng với dịnh dạng fie tương ứng

• Import những lớp cần thiết

• Định nghĩa một biến khung cảnh

• Tạo một đối tượng loader

• Load nội dung của file trong khối catch, và gán kết quả đọc được

cho biến khung cảnh

• Chèn đối tuwọng khung cảnh vào trong miền khung cảnh

Ta có thể xem xét một ứng dụng mẫu của lớp ObjectFile trong

jdk1.2/demo/java3d/ObjLoad.

Class ObjectFile

Gói: com.sun.j3d.loaders

Thực thi: Loader

http://tailieuhay.com 359

Page 360: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Lớp ObjectFile thực thi giao diện Loader với file có định dạng

WaveFront.obj, một định dạng chuẩn của file 3D đuwọc tạo ra bằng phần

mêm WaveFront Advanced Víualizer.

Chúng ta xem xét một ví dụ được thực hiện theo các bước đã nói ở

trên.

Chúng ta có thể thấy các bược 1,2..6 trong ví dụ trên đèu được hiện

theo trình tự các bước ta phân tích.

Các loader phổ biến

Trong Java3D chúng ta có thể tìm thây rất nhiều lớp Loader. Ta có

bảng danh sach cụ thể dưới đây.

File Mô tả

3DS 3D-StudioCOB Caligari trueSpaceDEM Digital Elevation Map

DXFAutoCAD Drawing Interchange

FileIOB Imagine

LWS Lightwave Scene Format

NFF WorldToolKit NFF Format

OBJ Wavefront

PDB Protein Data Bank

PLAY PLAY

SLD Solid World

VRT Superscape VRT

VTK Visual Toolkit

http://tailieuhay.com 360

Page 361: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

WRLVirtual Reality Modeling

language

3.3.3 Giao diện của gói Loader và lớp cơ sở

Để load được các file 3D trong một ứng dụng Java, chuwong trình

của chúng ta phải sử dụng đến đối tượng loader và đối tượng scene.

Đối tượng loader đọc, phân tích, và tạo ra phần thể hiện của Java 3D

cho nội dung file 3D đó. Đối tượng scene lưu lại scene graph được

tạo ra từ loader. Chúng ta có thể load được nhiều scene từ nhiều file

3D, bằng các sử dụng cùng một đối tượng loader tạo ra nhiều đối

tượng scene. Trong một chương trình Java3D chúng ta có thể load

được nhiều file định dạng khác nhau bằng các sử dụng các loader

thích hợp.

Sau đây chúng ta sẽ xem xét cụ thể các interface có trong gói

com.sun.j3d.loaders. Một lớp loader thực thi loader interface và sử

dụng một lớp thích hợp để thực thi scene interface.

com.sun.j3d.loaders Interface Summary

Loader The Loader interface is used to specify the location and elements

of a file format to load.

Scene The Scene interface is a set of methods used to extract Java 3D

scene graph information from a file

loader utility.

Trong đó gói com.sun.j3d.loaders còn cung cấp các lớp cơ sở để thực

thi những interface này.

http://tailieuhay.com 361

Page 362: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

com.sun.j3d.loaders Class Summary

LoaderBase Lớp này thực thi giao diện Loadẻ và thêm vào các hàm tạo.

Lớp đuợc thiết kế để chúng ta có thể thừ kế nếu muốn xây dựng các

loader.

SceneBase Lớp SceneBase thực thi giao diện Scene và việc thừa kế lớp

SceneBase giúp cho chúng ta dễ dàng sử dụng được các phương thức đã

xây dựng

Các phương thức được định nghĩa trong interface, còn phần thực thi

nằm trong các lớp loader mà người lập trình sử dụng.

Interface Loader Method Summary

Gói: com.sun.j3d.loaders

Giao diện Loader được sử dụng để chỉ rõ ra vị trí và các thành phần của

một định dạng file cần load. Phần giao diện này cung cấp cho lớp Loader

các định dạng file khác nhau. Giao diện Scene sẽ được thực thi để cung

cấp cho người dùng những giao diện phù hợp để lấp dữ liệu từ các file.

Scene load(java.io.Reader reader)

Phương thức lấy ra thành phần Reader và trả về một đối tượng scenecó

chứa khung cảnh.

Scene load(java.lang.String fileName)

Phương thức lấy ra nội dung của một file từ tên file, và trả về một đối

tượng scene có chứa khung cảnh

Scene load(java.net.URL url)

Phương thức lấy ra nội dung của một file từ URL, và trả về một đối tượng

scene có chứa khung cảnh

void setBasePath(java.lang.String pathName)

Phương thức này thiiết lập đường dẫn cơ sở cho các file được dùng trong

phương thức load(String)

http://tailieuhay.com 362

Page 363: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

void setBaseUrl(java.net.URL url)

Phương thức này thiiết lập đường dẫn cơ sở cho các file được dùng trong

phương thức load(URL)

void setFlags(int flags)

Phương thức thiết lập cờ load

LOAD_ALL Cho phép load toàn bộ các đối tượng vào khung cảnh.

LOAD_BACKGROUND_NODES Cờ cho phép load các đối tượng

backgrround vào khung cảnh.

LOAD_BEHAVIOR_NODES Cờ cho phép load các hành vi vào trong

khung cảnh.

LOAD_FOG_NODES Cờ cho phép load sương mù vào trong khung

cảnh.

LOAD_LIGHT_NODES Cờ cho phép load đối tượng ánh sáng vào

trong khung cảnh.

LOAD_SOUND_NODES Cờ cho phép load đối tượng âm thanh vào

trong khung cảnh..

LOAD_VIEW_GROUPS Cờ cho phép load đối tượng view (camera)

vào trong khung cảnh...

Lớp loader cơ sở cung cấp phần thực thi với mỗi phương thức load

(gồm 3 phương thức) được định nghĩa trong các loader interface.

Lớp Loader thực hiện phần thực thi 2 hàm tạo.

LoaderBase Constructor Summary

Gói: com.sun.j3d.loaders

Thực thi: Loader

Lớp Loader thực thi giao diện loader.

LoaderBase()

Khởi tạo đối tượng Loader với cá giái trị mặc định

http://tailieuhay.com 363

Page 364: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

LoaderBase(int flags)

Khởi tạo đối tượng Loader với các cờ chỉ định

Khi chúng ta viết một lớp loader mới, chúng ta có thể thừa kế lại lớp

loader cơ sở trong gói com.sun.j3d.loaders và sử dụng lớp SceneBase

trong cùng gói này.

Trong quá trình viết một loader mới chúng ta cần xem xét việc thừa

kế lớp SceneBase hoặc thực thi interface Scene một cách trục tiếp.

Lớp ScaneBase có chức năng lưu trũ và nhận dữ liệu được tạo ra bởi

lớp Loader trong quá trình đọc file. Các phương thức thực hiện việc

lưu trữ (được cung cấp bởi những người viết ra Loader) có tên dạng

add* . Các phương thức thu nhận dữ liệu (được người sử dụng lớp

loader gọi ra) có tên dạng get*.

Khi thừa kế lớp loader cơ sở, công việc chú yếu của chúng ta là viết

các phương thức để nhận ra format của file. Mỗi phương thức này

tạo ra các thành phần scene graph tương ứng và lưu các dữ liệu này

trong đối tượng scene.

SceneBase Constructor Summary

Gói: com.sun.j3d.loaders

Thực thi giao diện Scene

Lớp SceneBase thực thi giao diện Scene.

SceneBase()

Khởi tạo một đối tượng SceneBasse

SceneBase Method Summary (partial list: loader users' methods)

Background[] getBackgroundNodes()

Behavior[] getBehaviorNodes()

java.lang.String getDescription()

http://tailieuhay.com 364

Page 365: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Fog[] getFogNodes()

float[] getHorizontalFOVs()

Light[] getLightNodes()

java.util.Hashtable getNamedObjects()

BranchGroup getSceneGroup()

Sound[] getSoundNodes()

TransformGroup[] getViewGroups()

Qua những điểm trên ta có thể xây dựng được loader cho nhu cầu cảu

mình. Phần tiếp theo ta sẽ đi vào chi tiết việc viết một loader.

Viết một loader

Công việc viết một loader là một công việc phức tạp và không phải

người lập trình Java 3D nào cũng phải viết. Tuy nhiên việc nghiên cứu

cách viết, làm việc cảu một Loader sẽ giúp chúng ta hiểu rõ hơn khi

nào thì sử dụng loader, hiểu cách sử dụng GeometryInfo, hiểu được

việc thực thi của ObjectLoader.

Công việc của một loader

Ngoài nhiệm vụ chính là đọc nội dung một file đồ hoạ, tạo ra một đối

tuợng scene graph thể hiện cho nội dung của file được load, lớp loader

còn có các chức năng khác.

• Tính toán bề mặt thông thường của các đa giác.

• Thể hiện đối tượng đồ họa tại nguyên gốc

• Chỉnh tỷ lệ của đối tượng hình học một cách thích hợp, tương ứng

1-1 trên mỗi trục

• Làm mịn đối tượng hình học

http://tailieuhay.com 365

Page 366: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

• Thể hiện đối tượng hình học một cách hiệu quả bằng việc phân

nhỏ thành nhiều phần, hoặc sử dụng LOD.

Tuy nhiên không phải bất cứ loader nào cũng phải thực hiện đầy đủ

các chức năng trên. Nhiệm vụ chủ yếu của nó là tạo ra đối tướng

hình học tương ứng với nội dung file được load vào.

Hàm tạo lớp Loader

Trong phần này chúng ta sẽ xem xét việc tao ra một đối tuwọng

loader từ hàm tạo của lớp loader đã xaay dựng. Nhìn chung việc

xây dựng một lớp loader đồi hỏi những kiến thức liên quan đến

định dạng của file cần load và phần luồng stream trong Java.

Có nhiều cách tiếp caạn trong việc xây dựng một loader. Tuy nhiên

để có thể tận dụng được sự hỗ trợ của Java3D, chúng ta có thể dùng

các lớp SceneBase và LoaderBase (đã trình bày ở các chương

trước). Một loader được xây dựng trên các lớp này có khả năng

chọn được phần dữ liệu của file được sử dụng trong ứng dụng. Đó

là cách tiếp cận chuẩn cho việc xây dựng một loader.

Một khía cạnh khó khăn nữa là khi xây dựng một loader chúng ta

phải quan tâm đến format của file, có loại file đơn giản, có loại file

phức tạp, có những file còn có sự liên quan đến các file cấu hình

khác như file quy địng scene graph description.

Sử dụng khái niệm Layer, việc xây dựng lớp loader trở nên dễ dàng

hơn. Số lượng các layer lại phụ thuộc nhiều vào format của file cần

load. Sau đây chúng ta xem xét tập các layer đơn giản.

Layer/leve

l

Chức năng

Tokenizer Chuyển các ký tự thành các

http://tailieuhay.com 366

Page 367: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

token

Đối tượng Chuyển các token hình ảnh

của file thành các đối tượng

đồ hoạ (geometry, lights,

textures… )Scene Chuyển danh sách các đối

tựong scene graph vào tong

khung cảnh đồ hoạFile Liên quan đến các file hay

các URL cần mở

• Tokenizer

Đây là tầng thấp nhất của loader trong việc xử lý các file đồ hoạ.

Tần này có nhiệm vụ chia nhỏ nội dung cảu file thành phần nhỏ

hơn, gọi là các token. Lấy ví dụ một token có thể là một số, một

từ, hay một ký tự đơn.

• Đối tượng

Tầng object có nhiệm vụ tạo ra các đối tượng đồ họa từ các

token được tạo ra theo nội dung của file. Một vài đối tượng có

thể là đối tượng đỉnh, đa giác, ánh sáng, kết cấu hay bất cứ đối

tượng khung cảnh nào trong Java3D. Những object này là các

thành phàn của một khung cảnh

• Scene

Là tập hợp các đối tượng hình học.Thông thường tầng scene

trong Java3D đơn giản. Trừ truờng hợp ngoại lệ khi nó lớp

loader có nhiệm vụ load một tệp đại diện cho một khung cảnh

đồ họa. Ví dụ như file theo định dạng Open Inventor và OOGL

List.

• File

http://tailieuhay.com 367

Page 368: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

File có chứa nội dung cần được load.

Viết một File Loader đơn giản

Trong phần này chúng ta sẽ xem xét cụ thể hơn việc xây dựng một

loader đơn giản. Việc dầu tiên là chúng ta cần xác định định dạng

file mà loader của chúng ta sẽ load. Thông thường chúng ta sẽ chọn

lự một họ các file co định dạng tương đương, ví dụ như họ OOGL

(Object Oriented Graphics Library)

Định dạng QUAD

Bước đầu tiên để viết một Loader là biết được định dạng của file.

Trong phần này chúng ta sẽ xem xét qua về cấu trúc file QUAD,

các chi tiết cụ thể sẽ trình bày ở phần 4. Trong phần 4 chúng ta sẽ

xem xét những vấn đề :

Đa số các file OOGL đều có định dạng ASCII tự do- có các

khoảng trắng, trông, tab, dòng mới… giữa các phần tử (số, ký

tự…). Các phần comment được bắt đầu sau dấu # .

Định dạng QUAD thuộc loại định dạng OOGL. Định dạng QUAD

mô tả một tập hợp các bộ quad. Một file dạng QUAD là một tập

hợp 4*n đỉnh, trong đó n là số các bộ quad.

Ví dụ duới đây cho thấy noọi dung một file QUAD. File này chứa

thông tin về một hình vuông trên hệ không gian 3 chiều, với thành

phần z của hình vuông bằng 0, hình vuông này nằm trên mặt phẳng

Oxy.

http://tailieuhay.com 368

Page 369: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Cấu trúc của một ile QUAD nói chung là phứuc tạp hơn nhiều so

với ví dụ trên, tuy nhiên mục đích của chúng ta là tìm hiểu cách

viết một loader đơn giản nên ta dựa trên file QUAD đơn giản. Cấu

trúc chung của file QUAD được mô tả kỹ hơn trong phần 4.

Trong bảng dưới đâu đưa ra danh sách các lớp và mối quan hệ giữa

chúng để ta có thể xây dựng một lớp loader.

Tầng/Lớp Thực thi

tokenizer QuadFileParser

Object SimpleQuadObject chứa

QuadFileParserscene SimpleQuadScene thừa kế

lớp SimpleQuadObjectfile SimpleQuadFileLoader

thừa kế lớp

SimpleQuadScene thực thi

lớp Loaderapplication SimpleQuadLoad chứa lớp

SimpleQuadFileLoaderTrong các phần tiếp theo chúng ta sẽ xem xét kỹ hơn ácc lớp này,

thành phần và hoạt động của nó tỏng một ứng dụn loader.

Tầng Tokenizer(Quản lý các phần tử)

Bước đầu tiên để xây dựng một loader là xây dựng tokenizer. Điều

này được thực hiện bằng cách chúng ta thừa kế lớp tiện ích

StreamTokenizer. Lớp này đọc vào luồng các ký tự và chuyển đổi

nó thành tập các phần tử. Trong ví dụ này, chúng ta xây dựng lớp

QuadFileParser thừ kế lớp StreamTokenizer.

Các phương thức trong lớp QuadFileParser

http://tailieuhay.com 369

Page 370: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Phương thức Nhiệm vụ/hoạt động

Void setup() Chỉ ra các tham số cho tokenizer,

hàm này được gọi trong hàm tạoboolean getToken() Phương thức lấy ra token tiếp theo,

phương thức sử dụng hàm

nextToken()của lớp

StreamTokenizerVoid printToken() In giá trị của các token ra

System.out, dùng trng quá trình gỡ

lỗiQuadFileParser(Reade

r r)

Hàm tạo gọi phương thức setup và

liên kết các token với đối tượng

reader.

Những sự thay đổi mở rộng chủ yếu nằm trong phương thức setup.

Những sự thay đổi này bao gồm:

• Định nghĩa những ký tự đặc biệt, dấu xuống dòng, dấu

comment.

class QuadFileParser extends StreamTokenizer {

// setup

// Sets up StreamTokenizer for reading OOGL file formats.

void setup()

{

resetSyntax();

// EOL chars are insignificant in QUAD file

eolIsSignificant(false);

wordChars('A','z');

// have StreamTokenizer parse numbers (makes double-precision)

http://tailieuhay.com 370

Page 371: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

parseNumbers();

// Comments begin with # to end of line

commentChar('#');

// Whitespace characters delineate words and numbers

// blanks, tabs, and newlines are whitespace in OOGL

whitespaceChars('\t', '\r'); // ht, lf, ff, vt, cr

whitespaceChars(' ', ' '); // space

} // End of setup

/* getToken

* Gets the next token from the stream. Puts one of the four

* constants (TT_WORD, TT_NUMBER, TT_EOL, or TT_EOF) and the

token

* value into ttype token object.

* The value of this method is in the catching of exceptions in this

* central location.

*/

boolean getToken()

{

int t;

boolean done = false;

try {

t = nextToken();

}

catch (IOException e) {

System.err.println(

"IO error on line " + lineno() + ": " + e.getMessage());

return false;

}

return true;

http://tailieuhay.com 371

Page 372: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

} // End of getToken

// QuadFileParser constructor

QuadFileParser(Reader r)

{

super(r);

setup();

} // end of QuadFileParser

} // End of file QuadFileParser.java

Ta có thể thấy những thay đổi trong các phương thức getToekn(),

printToken() .. là không đáng kể. Như vậy ta đã hoàn thành việc

viết lớp QuadFileLoader, tiếp theo chung sta chuyển lên tầng trên,

tầng object.

Thực hiện tầng Object

Nhiệm vụ của tầng Object là chuyển những token được cung cấp

bởi tầng tokenizer sang các đối tượng hình học.Tỏng ví dụ của

chúng ta thì điều này là đơn giản bời vì chúng ta chỉ có một đối

tượng hình học duy nhất là tứ diện. Tuy nhiên chúng ta gặp phải

một khó khăn trong việc xác định số lượng đối tượng hình học

được cung cấp.

Các phương thức trong lớp SimpleQuadObject

Phương thức Nhiệm vụ

Boolean

readVertex(QuadFileParser st)

Đọc đỉnh, mỗi đỉnh bao gồm

tọa độ x,y,z hay các thông

tin khác về mầu sắc, bề

mặt… Boolean

readQuad(QuadFileParser st)

Đọc các tú diện bằng cách

đọc các đỉnh từ file QUAD

http://tailieuhay.com 372

Page 373: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Void

readQuadFile(QuadFileParserst)

Đọc file QUAD xác nhận

các thẻ trong file, xác định

tập các đỉnh và đọc ra cá tứ

diện(tứ giác)

Nhiệm vụ của tầng này là đọc ra các đối tượng hình học từ tập hợp

các token. Trong trường hợp này các đối tượng hình học là các

đỉnh. Tập các đỉnh này được lưu trữ trong một đối tượng ArrayList.

Sử dụng ArrayList chó phép việc thay đổi kích thước cảu mảng tạo

thời gian thực hiện. Tại tầng Scene, đối tượng kiểu ArrayList được

chuyển đổi sang một Array và sau đó là sang đối tượng hình học.

Chúng ta xem xét phần code chủ yếu trong tầng Object. Toàn bộ

phần code đầy đủ nằm trong example.jar.

import QuadFileParser;

// many other imports omitted in tutorial text

public class SimpleQuadObject

{

protected int flags;

protected int fileType = 0; // what properties vertices have

// constants for indicating file type

protected static final int COORDINATE =

GeometryArray.COORDINATES;

// lists of points are read from the .quad file into this //array. . .

protected ArrayList coordList; // Holds Point3f

/**

* readVertex reads one vertex's coordinate data

*/

boolean readVertex(QuadFileParser st)

{

http://tailieuhay.com 373

Page 374: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Point3f p = new Point3f();

st.getToken();

if(st.ttype == st.TT_EOF)

return false; // reached end of file

p.x = (float)st.nval;

st.getToken();

p.y = (float)st.nval;

st.getToken();

p.z = (float)st.nval;

// Add this vertex to the array

coordList.add(p);

return true;

} // End of readVertex

/**

* readQuad reads four vertices of the correct type (which in this

* version is always just coordinate data).

*/

boolean readQuad(QuadFileParser st)

{

int v;

boolean result = false;

for(v=0; v < 4; v++)

result = readVertex(st);

return result;

} // End of readQuad

/*

* readFile

*

* Read the model data from the file.

http://tailieuhay.com 374

Page 375: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

*/

void readQuadFile(QuadFileParser st)

{

// verify file type

st.getToken();

if(st.sval.equals("QUAD") || st.sval.equals("POLY"))

fileType = COORDINATE;

else

throw new ParsingErrorException("bad file type: "+st.sval);

// read vertices

while (readQuad(st);

} // End of readFile

} // End of class SimpleQuadObject

// End of file SimpleQuadObject.java

Nếu trong chúng ta có các thông tin đi kèm với mỗi đỉnh như mầu

săc, chữ .. các thông tin này cũng được luwu trong một ArrayList.

Những thông tin thêm vào này cũng đựoc chuyển sang mảng thích

hợp trong tầng scene.

Đây là tầng thực hiện chủ yếu công việc của một loader. Tiếp đén

là tầng Scene, tầng khung cảnh

Thực hiện tầng Scene

Tầng scene thực thi bởi lớp SimpleQuadScene.

Các phương thưc lớp SimpleQuadScene

Phương thức Nhiệm vụSceneBase makeScene() Nhận dữ liệu từ một ArrayList do

tầng dưới đưa lên, tạo ra các đối

tượng hình học tương ứng và đưa

http://tailieuhay.com 375

Page 376: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

vào khung cảnh đồ họa

Point3f[]

objectToPoint3fArray(ArrayList

in)

Chuyển đổi một ArrayList thành

một mảng Point3f, dùng phương

thức makeScene()để tạo ra các đối

tượng hình họcScene load(Reader reader) 1.Khởi tạo a một đối tượng

QuadFileParser

2.Gọi QuadFileLoad(scene)

3.Gọi makeScene()

class SimpleQuadScene extends SimpleQuadObject

2. {

3. // coordList is converted to an arrays for creating geometry

4. //

5. private Point3f coordArray[] = null;

6.

7. private Point3f[] objectToPoint3fArray(ArrayList inList)

8. {

9. Point3f outList[] = new Point3f[inList.size()];

10.

11. for (int i = 0 ; i < inList.size() ; i++) {

12. outList[i] = (Point3f)inList.get(i);

13. }

14. return outList;

15. } // End of objectToPoint3fArray

16.

http://tailieuhay.com 376

Page 377: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

17.

18. private SceneBase makeScene()

19. {

20. // Create Scene to pass back

21. SceneBase scene = new SceneBase();

22. BranchGroup group = new BranchGroup();

23. scene.setSceneGroup(group);

24.

25. // the model will be one Shape3D

26. Shape3D shape = new Shape3D();

27.

28. coordArray = objectToPoint3fArray(coordList);

29.

30. QuadArray qa = new QuadArray(coordArray.length, fileType);

31. qa.setCoordinates(0, coordArray);

32.

33. // Put geometry into Shape3d

34. shape.setGeometry(qa);

35.

36. group.addChild(shape);

37. scene.addNamedObject("no name", shape);

38.

39. return scene;

40. } // end of makeScene

41.

42. public Scene load(Reader reader) throws FileNotFoundException,

43. IncorrectFormatException,

44. ParsingErrorException

45. {

http://tailieuhay.com 377

Page 378: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

46. // QuadFileParser does lexical analysis

47. QuadFileParser st = new QuadFileParser(reader);

48.

49. coordList = new ArrayList();

50.

51. readQuadFile(st);

52.

53. return makeScene();

54. } // End of load(Reader)

55. } // End of class SimpleQuadScene

56. // End of file SimpleQuadScene.java

Thực hiện tầng File

Tầng này có nhiệm vụ thực hiện việc giao tiếp với File. Đa số phần

code của tầng này cũng tươn tự như ở tầng Object. Lớp

SimpleQuadFileLoader thừa kế lớp SimpleQuandScene và thực thi

giao diện Loader.

Xây dựng một Loader hoàn chỉnh

Trong thực tế có rất nhiều thông tin chi tiết trong file QUAD mà

loader đơn giản mà chúng ta vừa xây dựng không đáp ứng dược. Ví

dụ như những ký hiệu khoa học trong một file QUAD, các thông

tin về mầu săc… Lớp StreamTokenizer chúng ta xây dựng chưa

đáp ứng nhu cầu đó.

Một file QUAD cso thể chứa những thông tin về bề mặt, mầu sắc ..

của mỗi đỉnh, mỗi đối tượng. Để nhận được các thông tin này

chúng ta cần thay đổi tầng Object và tầng scene.

http://tailieuhay.com 378

Page 379: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Một file QUAD có thể bao gồm nội dung của một file khác. Điều

này làm tăng sự phức tạp của loader và đói hỏi việc thay đổi code

tại tất cả các tầng.

Một loader phức tập hơn có thể nhận ra và load được một họ các

định dạng file, ví dụ như LightWave loader.

Text2D

Có hai cách để thực hiện việc them chữ vào trong khung hình

Java3D. Cách thứ nhất là sử dụng lớp Text2D, cách thứ hai là sử

dụng Text3D. Sự khác nhau ở chỗ, lớp Text2D thực hiện các dòng

chữ trong không gian 2 chiều còn Text3D thực hiện trong không

gian 3 chiều.

Đối tượng Text2D là các đa giác vuông trong đó các chữ được coi

như là phần bề mặt. Đối tuwọng Text3D là những đối tượng hình

học trong không gian 3 chiều.

Là một lớp con của lớp Shpae3D, thể hiện của lớp Text2D có thể là

con của đối tượng group. Để thêm vào dòng chữ 2D trong Java3D

chúng ta cần tạo ra đói tượng Text2D sau đó thêm nó vào không

gian đồ hoạ.

Đối tượng Text2D được thực hiện sử dụng một đa giác và một

texture.

http://tailieuhay.com 379

Page 380: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

3.5.1 Ví dụ Text2D đơn giản

Trong ví dụ dưới đây chúng ta xem xét việc tạo ra một dối tượng

Text2D đơn giản. Bao gồmg bước tạo ra đối tượng Text2D và bước

tiếp hteo là thêm đối tượng này vào không gian đồ họa.

import java.applet.Applet;

import java.awt.BorderLayout;

import java.awt.Frame;

import java.awt.event.*;

import java.awt.Font;

import com.sun.j3d.utils.applet.MainFrame;

import com.sun.j3d.utils.geometry.Text2D;

import com.sun.j3d.utils.universe.*;

import javax.media.j3d.*;

import javax.vecmath.*;

// Text2DApp renders a single Text2D object.

public class Text2DApp extends Applet {

public BranchGroup createSceneGraph() {

// Create the root of the branch graph

BranchGroup objRoot = new BranchGroup();

// Create a Text2D leaf node, add it to the scene graph.

Text2D text2D = new Text2D("2D text is a textured polygon",

new Color3f(0.9f, 1.0f, 1.0f),

"Helvetica", 18, Font.ITALIC));

objRoot.addChild(text2D);

3.5.2 Lớp Text2D

Lớp Text2D là lớp tiện ích thừ kế từ lớp Shape3D.

http://tailieuhay.com 380

Page 381: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Hàm tạo lớp Text2D.

Text2D Constructor Summary

Gói: com.sun.j3d.utils.geometry

Lớp Text2D tạo ra một khung chữ nhật được ánh xạ đến phàn nội dung

text, hiẹn thị nội dung text được gửi bởi nguời dùng. Kích thước của

khung chữ nhạt được xác định phụ thuộc vào font được sử dụng(tham số

của hàm tạo). Kêt quả của đối tượng Shape3D trong suốt ngoại trừ hình

chữ nhật chứa nội dung text được đặt tại vị trí (0,0,0) kéo dài theo chiều

dương trục x, trực y

Text2D(java.lang.String text, Color3f color, java.lang.String

fontName,

int fontSize, int fontStyle)

Trong hàm tạo Text2D ta có thể thay đổi tỷ lệ kích thứoc của đối

tuwọng dòng chữ hiện ra so với kích thước điểm cố định.

Text2D Method Summary

void setRectangleScaleFactor(float newScaleFactor)

http://tailieuhay.com 381

Page 382: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Đặt giá trị tỷ lệ được sử dụng trong việc chuyển đổi chiều rộng/chiều dài

của hình ảnh sang chiểu rộng/chiều cao tương ứng trong không gian đồ

họa bắt đầu bằng thừa số 1/256

void setString(java.lang.String text) <new in 1.2>

Thiết lập giá trị dùng chữ hiện thị cho đối tượng Text2D

Text3D

Trong phần này chúng ta tìm hiểu vấn đề làm việc với lớp Text3D.

Khởi tạo một đối tượng Text3D bao gồm nhiều công việc hơn trong

đối Text2D. trước hết đối tượng Text3D được tạo ra bằng cách sử

dụng đối tượng hình học. Bước đầu tiên chúng ta phải tạo ra đối

tượng Font3D bao gồm các thuộc tính bề mặt, kích thứoc và kích

cỡ của font. Lớp Text3D là lớp con của lớp Geometry, nên đối

tuwọng text3D là một đối tượng NodeComponent được tham chiếu

bởi một hay nhiều đối tuwọng Shape3D.

Các bước tạo ra đối tượng Text3D

• Tạo mới đối tượng Font3D từ AWTFont

• Tạo mới đối tượng Text3D sử dụng đối tượng Font3D, ta có

thể chỉ định diểm tham chiếu tuỳ chọn

• Tham chiếu đói tượng Shape3D, và thêm ào không gian đồ

hoạ

Một ví dụ Text3D

Các bước tạo ra và sử dụng đối tuwọng Text3D được minh hoạ

trong ví dụ sau. Trong đó đối tuwọng Font3D tạo ra với thuộc tính

kiểu bề mặt là “Helvetica”, font chữ là 10. Sau đó chúng ta tạo ra

đối tượng Text3D tham chiếu đến một điểm trong không gian đồ

họa.

http://tailieuhay.com 382

Page 383: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

import java.applet.Applet;

import java.awt.BorderLayout;

import java.awt.Frame;

import java.awt.event.*;

import java.awt.Font;

import com.sun.j3d.utils.applet.MainFrame;

import com.sun.j3d.utils.universe.*;

import javax.media.j3d.*;

import javax.vecmath.*;

// Text3DApp renders a single Text3D object.

public class Text3DApp extends Applet {

public BranchGroup createSceneGraph() {

// Create the root of the branch graph

BranchGroup objRoot = new BranchGroup();

Font3D font3d = new Font3D(new Font("Helvetica", Font.PLAIN, 10),

new FontExtrusion());

Text3D textGeom = new Text3D(font3d, new String("3DText"),

new Point3f(-2.0f, 0.0f, 0.0f));

Shape3D textShape = new Shape3D(textGeom);

objRoot.addChild(textShape);

Chúng ta xem hình dưới đây.

http://tailieuhay.com 383

Page 384: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Để tạo ra chiều sâu (thể hiện bằng vùng mầu ghi) chúng ta sử dụng

các đối tượng Material và đối tuwọng DirectionLight.

Ta có thể “chiếu sáng” đối tượng Text3D theo nhiều hướng khác

nhau. Để có thể chiếu nhiêug hướng khác nhau chúng ta sử dụng

lớp Material.

Mỗi đối tượng Text3D có một điểm tham chiếu. Điểm tham chiếu

là sự kết hợp của path và alignment của đối tượng Text3D.

Trong bảng dưới đây cho ta minh họa về sự kết hợp này.

Những lớp liên quan để tạo ra đối tượng Text3D

Trong phần này chúng ta xem xét những lớp có liên quan để tạo ra

đối tượng Text3D.

http://tailieuhay.com 384

Page 385: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Lớp Text3D bao gồm nhiều hàm tạo. Cho phép ta tạo ra đối tuwọn

Text3D một cách linh hoạt.

Text3D Constructor Summary

A Text3D object is a text string that has been converted to 3D geometry.

The Font3D object determines the

appearance of the Text3D NodeComponent object. Each Text3D object

has a position - a reference point placing the

Text3D object. The 3D text can be placed around this position using

different alignments and paths.

Một đối tượng Text3D là một xâu ký tự được chuyển đổi sang hình học

3D. Đối tượng Font3D xác định bề ngoài của đối tượng Text3D

NodeComponent

Text3D()

Tạo ra đối tượng Text3D. Các giá trị mặc định:

appropriate, are:

font 3D null

string null

position (0,0,0)

alignment ALIGN_FIRST

path PATH_RIGHT

character spacing 0.0

http://tailieuhay.com 385

Page 386: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Text3D(Font3D font3D)

Tạo ra đối tượng Text3D với đối tượng Font3D đã xác định

Text3D(Font3D font3D, String string)

Tạo ra đối tượng Text3D với đối tượng Font3D đã xác định và nội dung

của xâu ký tự cần hiển thị

Text3D(Font3D font3D, String string, Point3f position)

Tạo ra đối tượng Text3D với cá tham số đối tượng Font3D, xâu ký tự, tọa

độ của điểm tham chiếu. Mặc định điểm tham chiếu nằm về phía bên

dưoiứ cùng bên trái của chữ cần hiển thị

Text3D(Font3D font3D, String string, Point3f position,

int alignment, int path)

ALIGN_CENTER Căn lề giữa.

ALIGN_FIRST alignment: ký tự đầu tiên của dòng chữ được đặt tịa

điểm tham chiếu.

ALIGN_LAST alignment: ký tự cuối cùng của dòng chữ được đặt tại

điểm tham chiếu..

Xem thêm ví dụ ở bảng trên.

Những phương thức của lớp Text3D, gồm những phương thức để

thiết lập các thuộc tính của đối tượng Text3D (setXXX), những

phương thức lấy giá trị các tuộc tính của đối tượng

Text3D(getXXX).

Text3D Method Summary

void setAlignment(int alignment)

Đặt canh lề cho đối tượng Text3D NodeComponent

void setCharacterSpacing(float characterSpacing)

http://tailieuhay.com 386

Page 387: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Đặt ký tự dấu cách khi tạo ra đối tượng Text3D

void setFont3D(Font3D font3d)

Thiết lậo đối tượng Font3D được sử dụng bởi đối tượng Text3D

NodeComponent

void setPath(int path)

Đặt đường dẫn của node

void setPosition(Point3f position)

Đặt điểm tham chiếu của node

void setString(java.lang.String string)

Copies the character string from the supplied parameter into the Text3D

node.

Copy xâu ký tự từ tham só đầu vào cho đối tượng Text3D node.

Các chế độ của đối tượng Text3D.

Text3D Capabilities Summary

ALLOW_ALIGNMENT_READ | WRITE Cho phép đọc ghi giá trị xâu

ký tự.

ALLOW_BOUNDING_BOX_READ

ALLOW_CHARACTER_SPACING_READ | WRITE Cho phép đọc

ghi các ký tự dấu cách.

ALLOW_FONT3D_READ | WRITE cho phép đọc ghi thông tin các

thành phần Font3D

ALLOW_PATH_READ | WRITE Cho phép đọc ghi giá trị xâu đường

dẫn.

ALLOW_POSITION_READ | WRITE Cho phép đọc ghi giá trị vị trí

của xâu

http://tailieuhay.com 387

Page 388: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

ALLOW_STRING_READ | WRITE Cho phép dọc ghi đối tượng xâu

ký tự..

Mỗi đối tượng Text3D được tạo ra từ một đối tượng Font3D. Một

đối tượng Font3D có thể được dùng để tạo ra nhiều đối tượng

Text3D khác nhau. Một đối tượng Font3D lưu các thông tin về bề

dầy hình học của đối tượng Text3D. Đối tuwonjg Font3D được thu

hồi tự động (garbage collected) mà không ảnh hưởng đến đối tượng

Text3D sử dụng chúng.

Font3D Constructor Summary

Lớp cha: java.lang.Object

Một đối tượng Font3D bao gồm Java 2D Font và chiều sâu.

Font3D(java.awt.Font font, FontExtrusion extrudePath)

Font3D(java.awt.Font font, double tessellationTolerance,

FontExtrusion extrudePath) <new in 1.2>

ALLOW_PATH_READ | WRITE Cho phép đọc ghi giá trị đường dẫn.

ALLOW_POSITION_READ | WRITE Cho phép đọc ghi giá trị vị trí.

ALLOW_STRING_READ | WRITE Cho phép đọc ghi đối tượng xau

ký tự.

Lớp Font3D không có những phương thức set* cụ thể, việc thiết

lập các thuộc tính của đối tượng Font3D được thực hiện trong hàm

tạo. Dưới đây là các phương thức get*.

Font3D Method Summary

void getBoundingBox(int glyphCode, BoundingBox bounds)

java.awt.Font getFont()

Returns the Java 2D Font used to create this Font3D object.

Trả về đối tượng Java2D Font được sử dụng để tạo ra đối tượng Font3D

http://tailieuhay.com 388

Page 389: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

void getFontExtrusion(FontExtrusion extrudePath)

Copies the FontExtrusion object used to create this Font3D object into the

specified parameter.

Thiết lập giá trị đối tượng FontExtrusion sử dụng để tạo ra đối tượng

Font3D bằng giá trị cảu tham số đầu vào. double

getTessellationTolerance() <new in 1.2>

Lớp Font được sử dụng trong việc tạ ra đối tượng Font3D. Ta mô tả

một hàm tạo lớp Font, các hàm tạo còn lại có thể xem thêm trong

javadoc.

Font Constructor Summary (partial list)

Gói: java.awt

public Font(String name, int style, int size)

Hàm tạo mới một đối tượng Font với tham số tên Font, kiểu, kích cỡ

name - the typeface name. Có thể là ten logic hoặc ten typeface. Một tên

logic cần phải là mộ trong các gía trị:

Dialog, DialogInput, Monospaced, Serif, SansSerif, or Symbol.

style -

Tham số kiểu có thể alf mộ trong các kiểu: BOLD, ITALIC …

size - Cỡ Font.

Hàm tạo lớp FontExtrusion

FontExtrusion Constructor Summary

Lớp cha: java.lang.Object

The FontExtrusion object is used to describe the extrusion path for a

Font3D object. The extrusion path is used in

conjunction with a Font2D object. The extrusion path defines the edge

contour of 3D text. This contour is

http://tailieuhay.com 389

Page 390: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

perpendicular to the face of the text. The extrusion has its origin at the

edge of the glyph with 1.0 being the height of

the tallest glyph. Contour must be monotonic in x. User is responsible for

data sanity and must make sure that

extrusionShape does not cause intersection of adjacent glyphs or within

single glyph. The output is undefined for

extrusions that cause intersections.

FontExtrusion()

Hàm tạo với giá trị mặc định

FontExtrusion(java.awt.Shape extrusionShape)

Hàm tạo đối tượng FontExtrusion với đối số shape truyền vào và

tolerance = 0.01

FontExtrusion(java.awt.Shape extrusionShape, <new in 1.2>

double tessellationTolerance)

http://tailieuhay.com 390

Page 391: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Các phương thức lớp FontExtrusion

FontExtrusion Method Summary

java.awt.Shape getExtrusionShape()

Gets the FontExtrusion's shape parameter.

void setExtrusionShape(java.awt.Shape extrusionShape)

Sets the FontExtrusion's shape parameter.

double getTessellationTolerance() <new in 1.2>

Return the tessellation tolerance with which this FontExtrusion object was

created.

Nền không gian đồ họa

Một cách mặc định, mầu nền của không gian đồ họa là mầu đen sẫm.

Tuy nhiên Java3D cung cấp cho chúng ta khả năng thay đổi nền của

không gian đồ họa, ta có thể lựa chọn mầu sắc, ảnh, các đối tượng hình

học hay kết hợp các thành phần này lại để tạo thành nền của không

gian đồ họa.

Các bước tạo ra nnè của không gian đồ họa:

• Khởi tạo một đối tượng background mới chỉ định mầu sắc hoặc

một hình ảnh nào đó.

• Thêm vào một đối tượng hình học (tùy chọn)

• Cung cấp một Application Boundary hoặc một BoundingLeaf

• Thêm đối tượng background vào không gian đồ họa

Một ví dụ background

Như ta đã trình bày ở phần trước. Một dói tuợng background có thể là

một mầu cụ thể, một hình ảnh hay thậm chí môt đối tượng hình học.

http://tailieuhay.com 391

Page 392: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

tỏng ví dụ đầu tiên chúng ta sẽ xem xét đối tượng backgrond là mầu

trắng, ví dụ thứ hai ta thêm một đối tượng hinh học vào background.

Ví dụ background là mầu nền

Background backg = new Background(1.0f, 1.0f, 1.0f);

//

backg.setApplicationBounds(BoundingSphere());

contentRoot.addChild(backg);

Ví dụ background là đối tượng hình học

Background backg = new Background(); //black background

backg.setGeometry(createBackGraph()); // add BranchGroup

of background

backg.setApplicationBounds(new BoundingSphere(new

Point3d(), 100.0));

objRoot.addChild(backg);

Phương thức createBackGraph() bao gồm việc tạo ra đối tượng hình

học làm nền. Phương thức này trả về đối tượng BranchGroup. Ta có

thể xem một ví dụ hoàn chinh BackgroundApp.java trong thư mục

examples/easyContent.

Lớp Background

Trong phần này chúng ta xem xét cụ thể thành phần và họat dộng của

lớp background

Lớp background thừa kế lớp Leaf, một thể hiện của lớp background là

thành phần con thuộc đối tượng Group

http://tailieuhay.com 392

Page 393: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Background có nhiều hàm tạo. Tham số trong hàm tọa cho biêt mầu

sắc hoặc hình ảnh cho background.

Hàm tạo của lớp Background

Background Constructor Summary

The Background leaf node defines either a solid background color or a

background image that is used to fill the

window at the beginning of each new frame. It optionally allows

background geometry to be referenced.

Background geometry must be pre-tessellated onto a unit sphere and is

drawn at infinity. It also specifies an

application region in which this background is active.

Background()

Constructs a Background node with a default color (black).

Background(Color3f color)

Constructs a Background node with the specified color.

Background(float r, float g, float b)

Constructs a Background node with the specified color.

Background(ImageComponent2D image)

Constructs a Background node with the specified image.

Các phương thức trong lớp background

http://tailieuhay.com 393

Page 394: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Background Method Summary

void setApplicationBoundingLeaf(BoundingLeaf region)

Set the Background's application region to the specified bounding leaf.

void setApplicationBounds(Bounds region)

Set the Background's application region to the specified bounds.

void setColor(Color3f color)

Sets the background color to the specified color.

void setColor(float r, float g, float b)

Sets the background color to the specified color.

void setGeometry(BranchGroup branch)

Sets the background geometry to the specified BranchGroup node.

void setImage(ImageComponent2D image)

Sets the background image to the specified image.

Các tham số cáu hình khác của đối tượng Background

Background Capabilities Summary

ALLOW_APPLICATION_BOUNDS_READ | WRITE allow read

(write) access to its application bounds

ALLOW_COLOR_READ | WRITE allow read (write) access to its

color

ALLOW_GEOMETRY_READ | WRITE allow read (write) access to

its background geometry

ALLOW_IMAGE_READ | WRITE allow read (write) access to its

image

3.8 Dữ liệu người dùng:

Các đối tượng SceneGraphObject có thể tham chiếu đến bất cứ đối

tượng nào như là các dữ liệu người dùng. Danh sách lớp con của lớp

http://tailieuhay.com 394

Page 395: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

SceneGraphObject gòm có: Appearance, Background, Behaviour,

BranchGroup, Geometry, Lights, Shape3D và TransformGroup.

Lấy ví dụ, một ứng dụng có thể có nhiều đối tượng có khả năng tương

tác, di chuyển. Mỗi đối tượng có thể có thể chứa những dữ liệu dạng

text trong đối tượng dữ liệu người dùng.

Các phương thức lớp SceneGraphObject

SceneGraphObject Methods (Partial List - User Data Methods)

SceneGraphObject is a common superclass for all scene graph component

objects. This includes Node, Geometry,

Appearance, etc.

java.lang.Object getUserData()

Retrieves the userData field from this scene graph object.

void setUserData(java.lang.Object userData)

Sets the userData field associated with this scene graph object.

http://tailieuhay.com 395

Page 396: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

CHƯƠNG 4

TƯƠNG TÁC

Trong chúng ta sẽ tìm hiểu về các vấn đề sau:

• Tìm hiểu lớp Behaviour, lớp cơ sở cho việc thực hiện tương tác và

xây dựng hoạt hình

• Xây dựng một lớp Behaviour

• Phối hợp các đối tượng Behaviour vào trong thế giới ảo để thực

hiện tưong tác

• Sử dụng lớp tiện ích xử lý bàn phím

• Sử dụng lớp tiến ích xử lý chuột

• Sử lớp lớp tiệc ích picking

Trong các chương trước chúng ta đa xem xét việc lập trình Java3D mọt

cách hoàn toàn tĩnh. Tuy nhiên điều thú vị cảu Java3D còn nằm ở vịec lập

trình tương tác và hoạt hình.

Tương tác là khi các hình ảnh thay đổi phản ứng lại hành động cảu người

dùng. Hoạt hình là những thay đổi của hình ảnh mà không cần sự tương

tác trực tiếp của con người. Trong Java3D, cả tương tác và hoạt hình đều

sử dụng lớp Behaviour. Chúng ta sẽ xem xét lớp này chi tiét hơn trong

các mục chủa chuwong này.

http://tailieuhay.com 396

Page 397: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

4.1 Hành vi: Cơ sở của tương tác và hoạt hình

Cả tưong tác và hạot hình đều sử dụng đối tượng Behaviour. Lớp

Behaviour là một lớp cơ sở trừu tượng, cung cấp các kỹ thuật để thay đổi

đồ thị khung cảnh. Lớp Behaviour và các lớp dẫn xuất, liên kết với phần

mã của người phát triển cung cấp nhằm làm thay đổi hình ảnh, âm thanh

trong không gian ảo. Đối tượng Behaviour trong một đồ thị khung cảnh

có nhiệm vụ thây đổi đồ thị khung cảnh, hay phản ứng lại các kích thích.

Một kích thích, hay tác động có thể là việc ấn một phím, di chuyển chuột,

sự va chạm giữa các đối tượng… Những tác động này có thẻ thêm vào

các đối tượng trong đồ thị khung cảnh hay loại bỏ cá đối tượng trong đồ

thị khung cảnh, thay đổi thuộc tính của đối tượng, sắp lại lại các đối

tượng …

4.1.1 Ứng dụng của hành vi

Trong bảng dưới đây chúng ta sẽ liệt kê những khả năng có thể của

lớp Behaviour, liệt kê nhưng tác nhân từ cột bên trái xuống phỉa dưới, và

những thay đổi nằm trên dòng đầu. Chúng ta chỉ liệt ke những khả năng

đơn giản cảu Behaviour chứ không liệt kê đầy đủ tất cả các khả năng có

thể của Behaviour. Một vài sự kết hợp giữ các tác nhân và các thay đổi

chỉ có ý nghĩa trong những trường hợp đặc biệ, chúng ta gọi là ứng dụng

cụ thể.

Tác nhân TransformGroup Geometry SceneGraph Vie w

Người

dùng

Tương tác Ứng dụng cụ

thể

Ứng dụng

cụ thể

Di

chuyển

Sự va

chạm

Đối tượng trực

quan thay đổi

Đối tượng

trực quan

Đối tượng

xuất hiện

Thể

hiện

http://tailieuhay.com 397

Page 398: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

hướng hay vị trí thay đổi bề

noài trong

các va chạm

trong các va

chạm

những

thay đổi

trong va

chạm

Thời

gian

Hoạt hình Hoạt hình Hoạt hình Hoạt

hìnhKhung

nhìn

Bảng Tần các chi

tiết

(LOD)

Ứng dụng

cụ thể

Ứng

dụng cụ

thể

Bảmg trên chúng ta chỉ liệt kê những truờn hợp đơn giản những khả

năng của lớp Behaviour. Picking được thực thi sử dụng các hành vi

nhưng không được liệ kê ở trên.

Nhưng sự vật ngoài tự nhiên, như một cái cây, bao gồm một số lượng

rất lơn các đối tượng hình học được thể hiện một cách chính xác như la,

cành .Một phương pháp khác được sử dụng là sử dụng kết cấu đa giác

thay cho các đối tượng hình học.

Kỹ thuật trên (texture polygon) thương được gọi là billboard

approach. Điều này là hợp lý và đúng đắn khi một hành vi được sử dụng

tự động định hướng textured polygon trực giao với khung nhìn, trong đó

chỉ có bè mặt cảu kết cấu đa diện được nhìn thấy. Hành vi định hướnggọi

là billboard behavior.

Hướng tiếp cận billboard thực sự hiệu quả khi đối tượng được biểu

diễn bởi texture có khoảng cách xa vì vậy các phần độc lập khác của đối

tượng trực quan được biểu diễn bởi texture sẽ khó khăn. Lấy ví dụ biểu

diễn một cái cây, nếu khung nhìn là rất xa không đủ khả năng nhìn một

cách rõ ràng và nổi bật cành cây, khi đó sẽ là rất vô lý và phí phạm khi

tốn bộ nhớ và công việc xử lý để biể diên tưng chiếc lá. Kỹ thuật này

http://tailieuhay.com 398

Page 399: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

được khuyến khích sử dụng trong các ứng dụng yêu cầu thể hiện các đối

tượng trực quan ở khoảng cách xa.

Hành vi LOD (level of detail) c ó nh ững ứng dụng liên quan. Với

LOD, các đối tượng trực quan được biểu diễn bởi rất nhiều đối tượng trực

quan khác nhỏ hơn, chi tiết hơn. Khi khung nhìn (viewer) càng gần các

chi tiết được thể hiẹn càng rõ và khi khung nhìn ở xa, các đối tượng trực

quan được biểu diễn ít chi tiết hơn. Behaviour LOD tự động chuyển đổi

các chế độ trình diễn dựa vào khoảng cách giữa đối tượng với viewer.

Cả billboard và LOD đều tương ứng với các lớp dẫn xuất từ lớp

Behaviour

4.1.2 Tổng quan lớp Behaviour

Trong bảng 4-1, chỉ rõ sự chuyên môn hoá của Behaviour trong

Java3D API và các gói tiện ích. Trong phần này chúng ta sẽ lân lượt xem

xét từng lớp trong bảng 4-1.

4.2 Cơ bản về hành vi

Như đã đề cập trong các phần trước, lớp Behaviour được sủ dụng

nhiều trong các ứng dụng Java3D theo nhiều cách khác nhau.Việc tìm

hiểu hoạt đọng và lập trình với lớp Behaviour là điều rất quan trọng.

Trong mục này chúng ta sẽ tìm hiểu lớp Behaviour, đưa ra cách thức để

tạo ra một lớp Behaviour của riêng mình và một ví sử dụng lớp

Behaviour.

http://tailieuhay.com 399

Page 400: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Sơ đồ các lớp con của lớp Behaviour

4.2.1 Viết một lớp Behaviour

Trong phần này chúng ta sẽ tìm hiểu cách viết một lớp

Behaviour.Mechanics của Behaviours

Một lớp Behaviour thực thi quá trình khởi tạo và phương thức

processStimulus của lớp cơ sở trừu tượng Behaviour. Ngoài ra một lớp

Behaviour tự xây dựng cũng có ít nhất một àhm tạo và có các phương

thức khác của riêng nó.

Các Behaviour thông qua các đối tượng đồ hoạ, sẽ hành động trong

một đồ thị khung cảnh nhằm tác động đến hành vi. Đối tượng Behaviour

cần một tham chiếu đến đối tượng có sự thay đổi, để nó có khả năng tạo

ra những hành vi thay đổi.

Trong hàm tạo, có thể thiết lập tham chiếu đến đối tượng trong sự

thay đổi. Nếu không, tỏng một phương thức khác cảu lớp Behaviour tự

xây dựng phải chứa những thông tin này, quá trình tham chiếu phải được

thực hiện tại thời điểm đồ thị khung cảnh được tạo ra.

http://tailieuhay.com 400

Page 401: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Quá trình khởi tạo được gọi đến khi đồ thị khung cảnh chứa lớp

Behaviour được tạo ra.

Phương thức khởi tạo có trách nhiêm cài đặt những trigger ban đầu để

bắt các sự kiện của Behaviour và cái đặt những điều kiện ban đầu cho

các dữ liệu tĩnh của đối tượng Behaviour.

Các triggger thực chất là các đối tượng WakeupCondition (các điệu

kiến thức dậy), hay là sự kết hợp của các WakeupCondition . Phương

thức processStimulus được gọi khi các trigger được kích hoạt. Phương

thức processStimulus có trach nhiệm bắt và xử lý các sự kiện xảy ra.

Nhiều sự kiện có thể có thể được mã hoá trong một đối tượng

WakeupCondition (nhiều loại kích hoạt của bàn phím có thể được mã

hoá trong WakeupOnAWTEvent), nó bao gồm cả việc giải mã các sự

kiện.

Phương thức processStimulus phản xạ lại các tác nhân, thường là sự

thay đổi của các đối tượng, trong những điều kiện thích hợp, thiết lập lại

các trigger.

Tiếp theo chúng ta xem xét các bước để viết một lớp Behaviour cho

riêng mình.

Viết hàm tạo, chứa tham chiếu đến đối tượng trong sự thay đổi

Viết đè hàm khởi tạo public void initialization(),chỉ định các tiêu

chuẩn kích hoạt ban đầu (trigger)

Viết đè hàm public void processStimulus(), giải mã điều kiện xảy ra

hành động của trigger, reset lại trigger nếu cần thiết.

Các bước trên là các thức chúng ta tạo ra các lớp Behaviour đơn gaỉn,

những Behaviour phức tạp đòi hỏi phải lập trình xử lý nhiều bước hơn.

Chúng ta xem xét ví dụ dưới đây, được thực hiện theo các bước đã

nêu ở trên

Ví dụ xây dựng lớp Behaviour : SimpleBehaviour

http://tailieuhay.com 401

Page 402: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Trong ví dụ dưới đây chúng ta xây dựng một lớp Behaviour thực hiện

một hành vi đơn giản, làm quay một số thứ dưới sự điều khiển banừg bàn

phím. Để xây dựng một lớp Behaviour như vậy, chúng ta cần một tham

chiếu đến một TransformGroup (đối tượng chứa, chịu sự thay đổi) và

một biến góc nghiêng. Dưới sự kích hoạt của bàn phím, goc nghiêng sẽ

thay đổi và góc nghiêng của TransformGroup được thiết lập bằng với

giá trị mới của góc nghiêng này. Khi đó việc quay đối tượng

TransformGroup không còn là vấn đề khó khăn nữa.

Để tạo ra lớp Behaviour này, chúng ta chỉ cần lập trình theo các

buwóc đã nêu ở trên. Hàm tạo sẽ chứa tham chiếu đến đối tượng

TransformGroup của sự thay đổi. Phương thức initialization thiết lập cá

thông số trigger ban đầu theo sự kiện WakeOnAWTEvent sự kiện, và

thiết lập góc nghiêng bằng 0. Như đã đề cập ở phần trên, tác nhân của một

Behaviour được coi như một đối tượng WakeupCondition . Trong phần

4.3 chngs ta sẽ xem xét lớp WakeupCondition . Phương thức

processStimulus sẽ giải mã phím bấm đẻ có thể xác định được phím hay

tổ hợp phím nào được ấn. Phương thức processStimulus thuwòng xuyên

tăng biến góc nghiêng lên, từ đó ta có thể điều chỉnh sự thay đổi cảu đối

tượng TransformGroup một cách thích hợp. Công việc cuối cùng của

phương thức processStimulus là thiết lập lại các trigger.

Trong ví dụ này, trigger luôn luôn được thiết lập lại dưới tác động của

phím bấm. Behaviour có thể thay đổi các trigger của mình thạm chí trong

suốt thời gian hoạt đọng cảu Behaviour để thay đổi các hành vi.

Trong ví dụ dưới đây gói java.awt.event dùng để xử lý tương tác với

bàn phím. Gói java.util.enumeration cần thiết để giải mã đối tượng

WakeuponCondition

http://tailieuhay.com 402

Page 403: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

// SimpleBehaviorApp renders a single, rotated

cube.

public class SimpleBehaviorApp extends Applet {

public class SimpleBehavior extends Behavior

{

private TransformGroup targetTG;

private Transform3D rotation = new

Transform3D();

private double angle = 0.0;

// create SimpleBehavior - set TG object

of change

SimpleBehavior(TransformGroup targetTG) {

this.targetTG = targetTG;

}

// initialize the Behavior

// set initial wakeup condition

// called when behavior becomes live

public void initialize() {

// set initial wakeup condition

this.wakeupOn(new

WakeupOnAWTEvent(KeyEvent.KEY_PRESSED));

}

// called by Java 3D when appropriate

stimulus occurs

http://tailieuhay.com 403

Page 404: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

public void processStimulus(Enumeration

criteria) {

// do what is necessary in response

to stimulus

angle += 0.1;

rotation.rotY(angle);

targetTG.setTransform(rotation);

this.wakeupOn(new

WakeupOnAWTEvent(KeyEvent.KEY_PRESSED));

}

}

}// end of class SimpleBehavior

Lớp SimpleBehaviourApp chỉ thực hiẹn những chức năng chính cần

thiết của một Behaviour đơn giản. Chungs ta có thể phát triển thêm các

chức năng phong phú hơn, ví dụ ta có thể xet góc quay của trục quay có

thể được thay đổi bởi các phương thức của lớp.

Một điểm để phát triển nâng cấp là khắc phục hiẹn tượng tràn của góc

nghiêng.

Những sai lầm trong việc viết một lớp Behaviour

• Quên việc thiết lập và reset lại Behaviour trigger

• Không trả về từ phương thức của lớp Behaviour

Một điều hiển nhiên là nếu không thiết lạp trigger thì hành vi sẽ không thể

thực hiện được. Ngoài ra trigger cũng càn phải được reset trước khi hành

động tiếp theo lặp lại.

Khi cả hai phương thức initilization và processStimulus được gọi bởi

hệ thống Java3D, các hàm này phải trả về để cho phép việc tô trát được

tiếp tục. Lấy ví dụ, khi hành vi quay tròn được gọi, góc quay và đối tượng

TransformGroup cần được cập nhật một cách định kỳ.

http://tailieuhay.com 404

Page 405: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

4.2.2 Sử dụng một lớp Behaviour

Trong phần này chúng ta sẽ tìm hiểu việc thêm vào hành vi cảu đối

tượng trong chương trình.

Bước dầu tiên để thêm vào hành vi bao gồm việc chắc chắn đồ thị

khung cảnh có sự dự trũ cho hành vi. Ví dụ, để sử dụng được lớp

SimpleBehaviourApp trong phần trên , trong đồ thị khung cảnh phải có

chứa đối tượng TransformGroup được chuẩn bị để quay. Rất nhiều

Behaviour chỉ cần một đối tượng TransformGroup, trong khi đó đồ thị

khung cảnh đòi hỏi một Behaviour là ứng dụng và Behaviour phụ thuộc.

Thiết lập sự hỗ trợ cảu một Behaviour, một thể hiện của lớp

Behaviour phải được thêm vào đồ thị khung cảnh.Trong thực tế một đối

tượng Behaviour không phải là một phần của đồ thị khung cảnh và sẽ trở

thành “rác” và được dọn dẹp bởi garbage collection.

Bước cuối cùng để thêm vào một Behaviour là cung cấp một khung

lịch cho Behaviour. Để nâng cấp làm việc hiệu quả hơn, Java3D sử dụng

khung lịch để thực hiện execution culling.Bhv ch ỉ tr ở n ên active khi

khung lịch của nó giao với sự hoạt động của ViewPlatform. Chỉ có những

Behaviour đã active mới có kảh năng nhạn được các tác nhân kích thích.

Trong trường hợp đó, các tác nhân có thể bị một số Behaviour bỏ

qua.Người lập trình cần quản lý sự chọn lọc trong suốt quá trình chọn lựa

lịch của các Behaviour.

Các bước sử dụng một Behaviour

1.Chuẩn bị đồ thị khung cảnh

2.Them Behaviour vào đồ thị khung cảnh, tham chiếu dến đối

tượng cần chuyển động, thay đổi

3.Xác định một khung lịch (SchedulingBoundingLeaf)

4.Đọc và ghi các khả năng cho đối tượng đích

http://tailieuhay.com 405

Page 406: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Ví dụ dưới đây mô tả các bước sử dụng một Behaviour như đã trình

bày ở trên

public BranchGroup createSceneGraph() {

// Create the root of the branch graph

BranchGroup objRoot = new BranchGroup();

TransformGroup objRotate = new

TransformGroup();

objRotate.setCapability(TransformGroup.ALLOW_TRAN

SFORM_WRITE);

objRoot.addChild(objRotate);

objRotate.addChild(new ColorCube(0.4));

SimpleBehavior myRotationBehavior = new

SimpleBehavior(objRotate);

myRotationBehavior.setSchedulingBounds(new

BoundingSphere());

objRoot.addChild(myRotationBehavior);

// Let Java 3D perform optimizations on

this scene graph.

objRoot.compile();

return objRoot;

}

http://tailieuhay.com 406

Page 407: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Hình trên mô tả mối quan hệ giữa đối tượng Behaviour và đối tượng

chịu sự thay đổi. đối tượng TransformGroup. Ví dụ của chúng ta nhằm

thực hiện quay một ColorCube, nhưng lớp Behaviour không chỉ giưoi

hạn như vậy , ta có thẻ quay bất kỳ đối tượng nào là con của đối tượng

TransformGroup. Ví dụ trên chỉ có ý dịnh là điểm khởi đầu cho quá tnhf

làm việc vói Behaviour, chứ không có ý định thực hiện những khả năng

có thể của Behaviour.

Những sai lầm trong việc sử dụng đối tượng Behaviour

Trong ba bước sử dụng lớp Behaviour , hai bước thuwòng gây nhàm

lẫn sai sót:

• Không chỉ định khung lịch

• Không thêm đối tượng Behaviour vào trong đồ thị khung cảnh

Một điều chú ý là chúng ta nên chú ý hạn chế việc tạo lịch cho mỗi đối

tượng Behaviour càng ít càng tốt để đảm bảo cho hiệu năng của toàn hệ

thống.

Đặt đối tượng Behaviour vào đồ thị khung cảnh

Behaviour có thể được thêm vào bất cứ đau trong đồ thị khung cảnh.

Tiêu chí lựa chọn vị trí thêm đối tượng Behaviour vào đồ thị khung cảnh

phụ thuộc vào các yếu tố: hiệu quả của vịec đặt lịch, bảo trì code.

Trong đồ thị khung cảnh tạo bởi SimpleBehaviourApp, đối tượng

SimpleBehaviour và đối tượng ColorCube khong nằm trong cùng một hệ

tọa độ địa phương.

http://tailieuhay.com 407

Page 408: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Đối tượng TransformGroup chí có tác dụng quay đối tượng

ColorCube vì vậy khung lịch của di myRotationBehaviour luôn đính kèm

đối tượng ColorCube cho phép việc tương tác với đối tượng ColorCube

khi nó visible. Dù sao, nều đối tượng TransformGroup được dùng để

biêc dịch đối tượng ColorCube, khi dó đối tượng ColorCube có thể bị

dịch chuyển ra ngoài của khung nhìn. Khi đối tượng bound nằm trong đồ

thị khung cảnh cùng với đối tượng Behaviour, người dùng có thể có khả

năng tiếp tục biên dịch đối tượng đó.

Miễn là sự kích hoạt quả view vẫn giao với kung lịch của đối tượng

Behaviour, lúc đó đối tượng Behaviour vẫn còn active.

Chúng ta có thể tương tác với đối tượng trực quan không nằm trong

view.Vấn đề là nếu như lúc đo view thay đổi và không còn giao với

khung kế hoạch của của đối tượng Behaviour , khi đó đối tượng

Behaviour là không active. Như vậy khi đó đối tượng chúng ta muốn

tương tác có thể vẫn anừm trng view nhưng không active. Có hai giải

pháp cho vấn đề này. Một là chúng ta thay đổi đồ thị khung cảnh để vẫn

giữ được khung lịch của đối tượng Behaviour với đối tượng trực quan.

Điều này có thẻ thực hiện được trọn vẹn theo hình dưới đây. Phương

pháp thứ hai là sử dụng đối tượng BoundingLeaf cho khung lịch. Chúng

ta sẽ xem xét lớp BoundingLeaf này trong phần 3.7

http://tailieuhay.com 408

Page 409: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Những chú ý khi xây dựng lớp Behaviour

Điều cần chú ý khi viết một Behaviour là hiệu năng của hệ thống.

Một Behaviour không tốt sẽ làm giảm hiẹu năng của quá trình tô

trát.chức năng. Một điều cần chú ý khi viết mọt Behaviour là: memory

burnvà những trigger điều kiện không cần thiết.

‘Memory burn’ là thuật ngữ dùng để chỉ việc tạo ra những đối tượng

không cần thiết tỏng Java. Việc sử dụng bộ nhớ quá mức ,sẽ ảnh huwòng

đến quá trình garbage collection và quá trình ô trát sẽ bị dưng lại. Các

phương thức của lớp Behaviour thuwòng gây ra vấn đề ‘memmory burn’.

Ví dụ như đoạn mã tỏng 4-1, phương thức processStimulus sử dụng toán

tử new trong qu á tr ình g ọi wakeupOn. i ều n ày khi ến cho m ột đối

tượng mới được tạo ra mỗi khi phương thức này được gọi, đối tượng này

trở thành ‘rác’ mỗi lần Behaviour được kích hoạt.

Tuy nhiên việc xác định và tránh xảy ra ‘memmory burn’ thường khá

dễ dàng.

Ví dụ trong đoạn code 4-3, thay bằng việc khởi tạo một đối tượng mới,

chúng ta sẽ sử dụng lại đối tượng cũ. Trong phần này chúng ta xem xét

kảh năng để thiết lập các điều kiện trigger nhằm kích hoạc các Behaviour

trong mỗi khung của quá trình tô trát. Nếu như không có tác nhân gì kích

hoạt Behaviour, sẽ là không cần thiết nếu chúng ta gọi đến phương thức

processStimulus.

4.2.3 Các hàm API trong lớp Behaviour

Trong phần này chúng ta sẽ tìm hiểu chi tiết về các hàm API của lớp

Behaviour.

Là một lớp cơ sở trừu tượng, lớp Behaviour càn được thừa kế trước khi

khởi tạo một đối tượng Behaviour.

http://tailieuhay.com 409

Page 410: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Trong gói tiện ích của Java3D có sằn rất nhiều các lớp Behaviour. Đó

là các lớp con của Leaf, thể hiện của một lớp thừa kế lớp Behaviour là

con của một nhóm trong đồ thị khung cảnh.

Các phương thức processStimulus và initialization cung cấp một gao

diện để chúng Java3D có thể hợp tác các Behaviours trong không gian

ảo. Các phương thức khác của lớp Behaviour đọc trình bày trong bảng

dưới đây. Phương thức wakeOn được dùng trong hai phương thức

initialization và processStimulus để thiết lập trigger cho Behaviour.Tham

số đầu vào của phương thức này là đối tượng WakeupCondition . Lớp

WakeupCondition và các lớp liên quan sẽ được trình bày trong phần

4.3.

Phương thức postId cho phép một Behaviour có thể giao tiếp với các

phương thức khác. Mộ trong những điều kiện wakeup là

WakeupOnBehaviorPost. Đối tượng Behaviour có thể sử dụng phương

thức postId để tạo ra sự cộng tác với điều kiện WakeupOnBehaviorPost

thích hợp. Chúng ta xem xem xét lớp akeupOnBehaviorPost chi tiết hơn

trong mục 4-16.

http://tailieuhay.com 410

Page 411: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Phương thức setEnable chung cấp một cách thức để vô hiệu hoá một

Behaviour thậm chí ngay cả khi bounds làm cho nó active. Giá trị mặc

định là true (đối tượng Behaviour được enable)

Một đối tượng Behaviour chỉ active khi khung đặt lịch của nó giao

với quá tình họat động của view.Tỏng một không gian ảo, chúng ta có thẻ

có nhiều view, một Behaviour có thể được active bởi nhiều view.

Phương thức getView rất hiệu quả với Behaviour dựa trên thông tin

của mỗi View (BillBoard, LOD..) và đối với những Behaviour nói chung

chung. Phương thức này trả về tham chiếu tới đối tượng View chính hiện

đang được kết hợp với Behaviour đó. Chúng ta không có phương thức

setView.

Đối tượng View chính được định nghĩa là đối tượng View đầu tiên

đọc gắn kèm với ViewPlatform, nếu chúng ta có nhiều View active.

Vì vậy một hành vi Billboard pahỉ hướng tới view chính, trong trường

hợp có nhiều view trong cùng một đồ thị khung cảnh.

Các hàm API của ViewPlatform

Các Behaviour chỉ active (có khả năng kích hoạt được) chỉ khi khung

lịch của nó giao với quá trình hoạt động của ViewPlatform .

Behavior Method Summary

Behavior is an abstract class that contains the framework for all

behavioral components in Java 3D.

View getView()

Returns the primary view associated with this behavior.

void initialize()

Initialize this behavior.

void postId(int postId)

Post the specified Id.

void processStimulus(java.util.Enumeration criteria)

http://tailieuhay.com 411

Page 412: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Process a stimulus meant for this behavior.

void setEnable(boolean state)

Enables or disables this Behavior.

void setSchedulingBoundingLeaf(BoundingLeaf region)

Set the Behavior's scheduling region to the specified bounding leaf.

void setSchedulingBounds(Bounds region)

Set the Behavior's scheduling region to the specified bounds.

void wakeupOn(WakeupCondition criteria)

ViewPlatform Method Summary (partial list)

These methods of the ViewPlatform class get and set the activation

volume (sphere) radius. Default activation radius

= 62.

float getActivationRadius()

Get the ViewPlatform's activation radius.

void setActivationRadius(float activationRadius)

Set the ViewPlatform's activation radius which defines an activation

volume around the view platform.

4.3 Điều kiện kích hoạt: Cách kích hoạt các hành vi

Những active Behaviour được kích hoạt bởi sự kiện của một hay

nhiều tác nhân kích hoạt. tác nhân kích hoạt. Tác nhân wakeup cho một

Behaviour được xác định sử dụng lớp con của lớp WakeupCondition .

Lớp cơ sở trừu tượng, là cơ sở của tất cả các lớp wakeup trong

Java3D. Có 5 lớp thừa kế lớp WakeupCondition , một trong số dó là lớp

cơ sở trừu tượng WakeupCriterion, các lớp còn lại kết hợp nhiềU điều

kiện wakeup trong một điều kiện wakeup duy nhất.

http://tailieuhay.com 412

Page 413: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Một điều kiện wakeup của một đối tượng Behaviour được xác định

như là sự kết hợp của các điều khiện khác sử dụng lớp kết hợp wakeup

thích hợp. Phần tiếp theo chúng ta mô tả lớp WakeupCondition và các

lớp con của nó.

4.3.1 Điều kiện kích hoạt

Lớp WakeupCondition cung cấp hai phương thức.Phương thức đầu

tiên, allElements, trả về danh sách liệt kê các tác nhân wakeup của đối

tượng WakeupCondition . Phương thức còn lại, triggeredElements, li ệt

k ê nh ững t ác nh ân wakeup có thể kích hoạt Behaviour. Phương thức

này có thể rất hữu hiệu trong phương thức processStimulus.

WakeupCondition Method Summary

The WakeupCondition abstract class is the base for all wakeup classes.

It provides the following two methods.

Enumeration allElements()

http://tailieuhay.com 413

Page 414: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Returns an enumeration of all WakeupCriterion objects in this

Condition.

Enumeration triggeredElements()

Returns an enumeration of all triggered WakeupCriterion objects in this

Condition.

4.3.2 WakeupCriterion

WakeupCriterion là phương thức trừu tượng cho phép 14 quy định

lớp tác nhân wakeup. WakeupCondition chỉ cung cấp một phương thức

duy nhất: hasTriggered. Chúng ta không cần thiết phải sử dụng phương

thức này, vì phương thức triggeredElements của lớp WakeupCondition

thực hiện điều này hộ chúng ta.

WakeupCriterion Method Summary

boolean hasTriggered()

Returns true if this criterion triggered the wakeup.

4.3.3 Quy định lớp WakeupCriterion

Trong bảng 4-2 đưa ra quy định 14 lớp WakeupCriterion. Những

lớp này được sự dụng để xác định những điều kiện wakup cho đối tượng

Behaviour. Thể hiện của những lớp này được sử dụng một cách độc lập

hay trong việc sử dụng kết hợp các điều kiện wakeup trong các lớp đã

nói trong mục trước.

Chúng ta sẽ xem xét chi tiết các lớp này trong ngay sau đây. CÓ

những lớp chỉ gồm những hàm API đơn giản, lớp WakeupOnActivation

chỉ có một hàm tạo duy nhất. Tham số khung lịch của các điều kiện

wakeup được chỉ định trong đối tượng Behaviour tương ứng.

http://tailieuhay.com 414

Page 415: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Những chú ý xung quanh WakeupCriterion

Một số lớp WakeupCriterion được kích hoạt ngay trong “first

detection” của một sự kiện. Đều này có nghĩa là tác nhân sẽ chỉ một lần

kích hoạt bởi sự kiện. Ví dụ đối tượng WakeupOnActivation sẽ kích hoạt

sự giao nhau giữa quá trình vận động của ViewPlatform và vùng kung

lịch của đối tượng Behaviour. Khi sự giao nhau này vần còn,

WakeupCondition sẽ không kích hoạt thêm một nào nữa. ĐIều tương tự

cũng đúng với một dãy các frame sau đó cho đến khi Java3D nhận biết

được sự thay đổi quá trình giao nhau, thì WakeupCondition mới có thể

kích hoạt lần tiếp theo.

Ta có những lớp WakeupCriterion theo từn cặp (Entry/Exit hay

Activation/ Deactivation). Những nhân tố này chỉ kích hoạt một cách xen

kẽ giữa tunừg cặp Entry hoặc Activation.

WakeupOnActivation

Nếu khung lịch giao với quá trình active của ViewPlatform trong một

thời gian đủ ngắn thì rất có thể là nó không được nhận ra. Khi đó cả

Acivation và Deactivation đều khong được kích hoạt. trong những trường

hợp như vậy, Behaviour sẽ không trở nên active.

WakeupOnActivation Constructor Summary

extends: WakeupCriterion

Class specifying a wakeup on first detection of a ViewPlatform's

activation volume intersection with this object's

scheduling region. WakeupOnActivation is paired with

WakeupOnDeactivation which appears on page 4-21.

WakeupOnActivation()

Constructs a new WakeupOnActivation criterion.

WakeupOnAWTEvent

http://tailieuhay.com 415

Page 416: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Nhiều lớp WakeupCriterion thực hiện kích hoạt trong những hàm

tạo và các phương thức một cách phụ thuộc.

Ví dụ WakeupOnAWTEvent có 2 hàm tạo và một phương thức. Hàm

tạo cho phép xác định các sự kiện AWT nhất định bằng cách sử dụng các

hằn của lớp AWT. Phương thức còn lại trả về mảng các sự kiện AWT liên

tục nhau được kích hoạt bởi trigger/

WakeupOnAWTEvent Constructor Summary

Thừa kế: WakeupCriterion

Lớp xác định một Behaviour được kích hoạt bởi một sự kiên AWT

WakeupOnAWTEvent(int AWTId)

Khởi tạo một đối tượng WakeupOnAWTEvent mới, trong đó AWTId là

một trong các hằng số

KeyEvent.KEY_TYPED,

KeyEvent.KEY_PRESSED, KeyEvent.KEY_RELEASED,

MouseEvent.MOUSE_CLICKED,

MouseEvent.MOUSE_PRESSED, MouseEvent.MOUSE_RELEASED,

MouseEvent.MOUSE_MOVED,

MouseEvent.MOUSE_DRAGGED, or one of many other event values.

WakeupOnAWTEvent(long eventMask)

Khởi tạo một đối tượng WakeupOnAWTEvent sử dụng ORed

EVENT_MASK,và AWT EVENT_MASK với các giá trị:

: KEY_EVENT_MASK, MOUSE_EVENT_MASK,

MOUSE_MOTION_EVENT_MASK, hoặc các giá trị khác.

WakeupOnAWTEvent Method Summary

AWTEvent[] getAWTEvent()

http://tailieuhay.com 416

Page 417: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Trả vể một mảng các sự kiên AWT liên tiếp, những sự kiện kích hoạt lớp

WakeupOnAWTEvent .

WakeupOnBehaviorPost

Lớp WakeupOnBehaviorPost cùng với phương thức the postID của

lớp Behavior cung cấp một kỹ thuật qua đó một hành vi có thể được thực

hiện.Một đối tượng Behavior có thể post đưa ra một giá tri ID (kiểu số

nguyên). Các Behaviour khác có thể xác định được điều kiện kích hoạt

của nó, sử dụng ID của một Behaviour xác định. Điều này cho phép

chúng ta có thể tạo ra một Behaviour mở cửa ra vào, và một Behaviour

khác đóng cửa. Với cách thức như vậy ngay cả những Behaviour phức

tạp chúng ta có thể xây dựng một cách tương tự như vây, kết hợp

Behaviour với post ID.

WakeupOnBehaviorPost Constructor Summary

Thừa kế: WakeupCriterion

Lớp xác định một Behaviour được kích hoạt khi một đối tượng

Behaviour khác đưa ra một sự kiện

WakeupOnBehaviorPost(Behavior behavior, int postId)

Khởi tạo một đối tượng WakeupOnBehaviorPost

Do WakeupCondition có thể chứa nhiều đối tượng

WakeupCriterion, bao gồm nhiều hơn 1 WakeupOnBehaviorPost,

phương thức để xác định rõ các triggering post caàn thiết cho sự kiện

trigger.

http://tailieuhay.com 417

Page 418: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

WakeupOnBehaviorPost Method Summary

Behavior getBehavior()

Trả về Behaviour xác định được thiết lập trong hàm tạo của đối tượng

int getPostId()

Nhận postId xác định của WakeupCriterion

Behavior getTriggeringBehavior()

Trả về behavior được kích hoạt bằng tác nhân.

int getTriggeringPostId()

Trả về thông tin postId kích hoạt Behaviour

Đoạn code dưới đây của một chuwong trình đơn giản sử dụng

Behaviour posting để hợp tác các Behaviour. Ví dụ mở và đóng cửa ra

vào. Ứng dụng bao gồm một lớp: OpenBehaviour, và đaọn code tạo ra

hai đối tượng Behaviour. Đối tượng thứ hai là thể hiện của

CloseBehaviour, hoàn toàn giốnh hệt OpenBehaviour. Trong lớp

CloseBehaviour, điều kiện tráo đổi trong phương thức initialization (và

Behaviour ngược lại được thực hiện)

public class OpenBehavior extends Behavior {

private TransformGroup targetTG;

private WakeupCriterion

pairPostCondition;

private WakeupCriterion wakeupNextFrame;

private WakeupCriterion

AWTEventCondition;

http://tailieuhay.com 418

Page 419: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

private Transform3D t3D = new

Transform3D();

private Matrix3d rotMat = new Matrix3d();

private double doorAngle;

OpenBehavior(TransformGroup targetTG) {

this.targetTG = targetTG;

AWTEventCondition = new

WakeupOnAWTEvent(KeyEvent.KEY_PRESSED);

wakeupNextFrame = new

WakeupOnElapsedFrames(0);

}

public void

setBehaviorObjectPartner(Behavior behaviorObject)

{

pairPostCondition = new

WakeupOnBehaviorPost(behaviorObject, 1);

}

public void initialize() {

this.wakeupOn(AWTEventCondition);

doorAngle = 0.0;

}

http://tailieuhay.com 419

Page 420: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

public void processStimulus(Enumeration

criteria) {

if

(criteria.nextElement().equals(pairPostCondition)

) {

System.out.println("ready to

open door");

this.wakeupOn(AWTEventCondition);

doorAngle = 0.0f;

} else { // could be KeyPress or

nextFrame, in either case: open

if (doorAngle < 1.6) {

doorAngle += 0.1;

if (doorAngle > 1.6)

doorAngle = 1.6;

// get rotation and scale

portion of transform

targetTG.getTransform(t3D);

t3D.getRotationScale(rotMat);

// set y-axis rotation to

doorAngle

// (clobber any previous y-

rotation, x and z scale)

rotMat.m00 =

Math.cos(doorAngle);

rotMat.m22 = rotMat.m00;

http://tailieuhay.com 420

Page 421: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

rotMat.m02 =

Math.sin(doorAngle);

rotMat.m20 = -rotMat.m02;

t3D.setRotation(rotMat);

targetTG.setTransform(t3D);

this.wakeupOn(wakeupNextFrame);

} else { // finished opening

door, signal other behavior

System.out.println("door is

open");

this.wakeupOn(pairPostCondition);

postId(1);

}

}

}

} // end of class OpenBehavior

Code 4-4: Sử dụng lớp OpenBehaviour và CloseBehaviour

Đối tượng của hai lớp này sẽ thay phiên nhau phản hồi với tác nhân

phím bấm.Đối tượng open behavior sẽ trả lời lại kích hoạt phím bấm đầu

tiên đồng thời nó đánh dấu cho đối tượng close Behaviour biết và thiết

lập điều kiện trigger của nó để có thể đựoc đối tượng close Behaviour

nhân biêt.Đối tượng open behavior mở cửa để trả lời lại tác nhân phím

bấm.Đối tượng close behavior thiết lập trigger của nó như là một phím

bấm để trả lời lại tín hiệu từ đối tượng open Behaviour

http://tailieuhay.com 421

Page 422: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Phím bấm tiếp theo kích hoạt đối tượng close. Đối tượng close lúc đo

sẽ thực hiện chức năng tương tự đối tượng open : gửi đến một tín hiệu và

thiết lập lại điều kiện kích hoạt của chính nó.

Đối tượng close đóng cửa để trả lời sự kiện bấm phím. Tiếp đó phím

bấm tiếp theo cũng được thực hiện tương tự. WakeupOnCollisionEntry

Java3D có khả năng tự động nhận ra sự va chạm giữa các đối tượng trong

không gian ảo. Java3D cung cấp 3 lớp WakeupCondition để xử lý sự va

chạm của các đối tượng:

• WakeupOnCollisionEntry,

• WakeupOnCollisionMovement,

• WakeupOnCollisionExit.

Một WakeupOnCollisionEntry sẽ đựoc kích hoạt khi một đối tượng

lần đầu va chạm. Sau đó WakeupOnCollisionMovement sẽ được kích

hoạt trong khi hai đối tượng trong va chạm

Cuối cùng một đối tượng WakeupOnCollisionExit sẽ kích hoạt khi va

chạm kết thúc Java3D chỉ có thẻ quản lý được một va chạm của một đối

tượng tại một thời điểm. Những va chạm diễn ra trong khoảng thời gian

rất ngắn cũng không được nhận biêt. Một cách hợp lý, CollisionEntry và

CollisionExit đều không đựoc kích hoạt. Quá trình nhạn biết va chạm

Collision detectiontrong thực tế diễn ra rất phức tạp.Dù sao tron tài liệu

này chúng ta không đi sâu vào collision detection, có thể tham kahỏ thêm

trong Java3D API specification.

Hàm tạo WakeupOnCollisionEntry

Thừa kế: WakeupCriterion

Lớp xác định va chạm đầu tiên của một đối tượng xác định với một đối

tượng khác trong đồ thị khung cảnh.

WakeupOnCollisionEntry(Bounds armingBounds)

http://tailieuhay.com 422

Page 423: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Tạo một đối tượng WakeupOnCollisionEntry mới.

WakeupOnCollisionEntry(Node armingNode)

Tạo một đối tượng WakeupOnCollisionEntry mới.

WakeupOnCollisionEntry(Node armingNode, int speedHint)

Tạo một đối tượng WakeupOnCollisionEntry mới trong đó speedHint

nhận một trong các giá trị: USE_BOUNDSvà USE_GEOMETRY

WakeupOnCollisionEntry(SceneGraphPath armingPath)

Tạo một đối tượng WakeupOnCollisionEntry mới với giá trị speed hint là

USE_BOUNDS WakeupOnCollisionEntry(SceneGraphPath

armingPath, int speedHint)

Tạo một đối tượng WakeupOnCollisionEntry mới với giá trị speed hint là

USE_BOUNDS hoặc USE_GEOMETRY.

WakeupOnCollisionExit

WakeupOnCollisionExit Constructor Summary

Thừa kế WakeupCriterion

Lớp xác định khi một đối tượng xác định kết thúc va chạm với các đối

tượng khác trong đồ thị khung cảnh

WakeupOnCollisionExit(Bounds armingBounds)

Hàm tạo với tham số Bound

WakeupOnCollisionExit(Node armingNode)

Hàm tạo với tham số armingNode

WakeupOnCollisionExit(Node armingNode, int speedHint)

Hàm tạo với tham số armingNode,speedHine

WakeupOnCollisionExit(SceneGraphPath armingPath)

Hàm tạo với tham sốarmingPath

http://tailieuhay.com 423

Page 424: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

WakeupOnCollisionExit(SceneGraphPath armingPath, int

speedHint)

Hàm tạo với tham số armingPath, speedHint

WakeupOnCollisionExit Method Summary

Bounds getArmingBounds()

Trả về đối tượng Bound được sử dụng trong việc xác địng va chạm

SceneGraphPath getArmingPath()

Trả về đường dẫn dùng trong va chạm xác định

Bounds getTriggeringBounds()

Trả về đối tượng Bounds gây ra va chạm

SceneGraphPath getTriggeringPath()

Trả về đường dẫn mô tả đối tượng gây ra va chạm

WakeupOnCollisionMovement

WakeupOnCollisionMovement Constructor Summary

Thừ kế: WakeupCriterion

Lớp xác định khi đối tượng xác định di chuyển trong va chạm với một đối

tượng khác trong không gian ảo

WakeupOnCollisionMovement(Bounds armingBounds)

Hàm tạo WakeupOnCollisionMovement

WakeupOnCollisionMovement(Node armingNode)

Hàm tạo WakeupOnCollisionMovement

WakeupOnCollisionMovement(Node armingNode, int speedHint)

Hàm tạo WakeupOnCollisionMovement trong đó speedHint nhận giá trị:

http://tailieuhay.com 424

Page 425: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

USE_BOUNDS hoặc USE_GEOMETRY

WakeupOnCollisionMovement(SceneGraphPath armingPath)

Hàm tạo WakeupOnCollisionMovement.

WakeupOnCollisionMovement(SceneGraphPath armingPath, int

speedHint)

Hàm tạo WakeupOnCollisionMovement, trong đó speedHint nhận một

trong hai giá trị: USE_BOUNDS hoặc USE_GEOMETRY

WakeupOnCollisionMovement Method Summary

Bounds getArmingBounds()

Trả về đối tượng bounds đựợc sử dụng trong collision condition.

SceneGraphPath getArmingPath()

Trả về đương dẫn đựoc sủ dụng trong collision condition.

Bounds getTriggeringBounds()

Trả về đối tượng Bounds gây ra va chạm

SceneGraphPath getTriggeringPath()

Trả về đường dẫn gây ra va chạm.

WakeupOnDeactivation

WakeupOnDeactivation Constructor Summary

Thừa kế: WakeupCriterion

Lớp xác định va chạm đầu tiên khi quá trình hoạt động củ ViewPlatform

không còn giao với khung lịch của đối tượng

WakeupOnDeactivation()

Hàm tạo đối tượng WakeupOnDeactivation

http://tailieuhay.com 425

Page 426: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

WakeupOnElapsedFrames

Đối tượng WakeupOnElapsedFrames được sử dụng để kích hoạt một

đối tượng active sau một số lượng frame nhất đinh trôi qua.

WakeupOnElapsedFrames Constructor Summary

Thừa kế: WakeupCriterion

Lớp xác định một kích hoạt sau một ố lượng frame nhất định

WakeupOnElapsedFrames(int frameCount)

Hàm tạo WakeupOnElapsedFrames.

frameCount - Số luwọng các frames mà Java 3D vẽ ra trước khi kích hoạt

một đối tượng Behaviour; giá trị n cho biết sao n frame Behaviour sẽ

đuợc kích hoạt. giá trị 0 cho biết Behaviour sẽ đựoc kích hoạt ngay sau

frame hiện thời.

WakeupOnElapsedFrames(int frameCount, boolean passive) <new in

1.2>

Hàm tạo WakeupOnElapsedFrames với tham số frameCount và tham số

passive

passive - cờ chỉ dẫn cho biết khi nào Behaviour trở nên bị động, một

Behaviour chủ động sẽ làm cho hệ thống phải chạy một cách liêc tục khi

một Behaviour bị động nó cho phép các sự kiện khác gây ra frame đuợc

chạy.

WakeupOnElapsedFrames Method Summary

int getElapsedFrameCount()

Trả về số lương các frameCount

boolean isPassive() <new in 1.2>

Trả về trạng thái của cờ bị động.

http://tailieuhay.com 426

Page 427: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

WakeupOnElapsedTime

Java 3D không thể bảo đảm thời gian chính xác của trigger cho một tiêu

chuẩn WakeupOnElapsedTime.

WakeupOnElapsedTime Constructor Summary

Thừa kế: WakeupCriterion

Lớp xác định một wakeup sau một khoang thời gian (ms) trôi qua.

WakeupOnElapsedTime(long milliseconds)

Hàm tạo đối tượng WakeupOnElapsedTime

WakeupOnElapsedTime Method Summary

long getElapsedFrameTime()

Trả về thời gian trôi qua của WakeupCriterion

WakeupOnSensorEntry

Trong Java 3D, bất kỹ thiết bị input nào (ngoại trừ chuột và bàn phím)

đều là một sensor Mỗi sensor có một hotspot được xác định trong hệ

thốnh của sensor. Sự giao nhau giữa hotspt cảu môt sensor với một region

có thể được nhận biết bởi lớp WakeupOnSensorEntry và

WakeupOnSensorExit.

WakeupOnSensorEntry Constructor Summary

Thừ kế: WakeupCriterion

Lớp xác định một wakeup trong giai đaọn đầu tiên nhận biết sự giao nhau

giưa một sensor nào đó với một boundary xác định

WakeupOnSensorEntry(Bounds region)

http://tailieuhay.com 427

Page 428: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Hàm tạo đối tượng WakeupOnEntry.

WakeupOnSensorEntry Method Summary

Bounds getBounds()

Trả về bound của đối tượng xác định.

Sensor getTriggeringSensor() <new in 1.2>

Trả về đối tượng sensor gây ra wakeup.

WakeupOnSensorExit

WakeupOnSensorExit Constructor Summary

Thừa kế: WakeupCriterion

Lớp xác định một wakeup trong giai đoạn nhận biết đầu tiên khi không

còn sự giao nhau giữa một đối tượng sensor trước đó với một boundary

xác định.

WakeupOnSensorExit(Bounds region)

Hàm tạo đối tượng WakeupOnExit .

WakeupOnSensorExit Method Summary

Bounds getBounds()

Trả về bound của đối tượng xác định.

Sensor getTriggeringSensor() <new in 1.2>

Trả về đối tượng Sensor gây ra wakeup.

WakeupOnTransformChange

http://tailieuhay.com 428

Page 429: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

WakeupOnTransformChange rất hiệu quả trong việc nhận biết thay

đổi vị trí hay hướng của các đối tượng trực quan trong đồ thị khung cảnh.

Lớp này sử dụng phương thức postId để tạo ra các Behaviour hợp tác.

Điều này đặc biệt hiệu quả khi chúng ta muốn hợp tác với một Behaviour

đã được xây dựng trước đó.

WakeupOnTransformChange Constructor Summary

Thừa kế: WakeupCriterion

Lớp xác định một wakeup khi một đối tượng transform trong một nhóm

TransformGroup xác định thay đổi.

WakeupOnTransformChange(TransformGroup node)

Hàm tạo đối tượng WakeupOnTransformChange.

WakeupOnTransformChange Method Summary

TransformGroup getTransformGroup()

Trả về node TransformGroup sử dụng trong WakeupCriterion

WakeupOnViewPlatformEntry

Quá trình nhận biết sự giao nhau của ViewPlatform với một region xác

định có thể được thực hiện bởi lớp WakeupOnViewPlatfomEntry và lớp

WakeupOnViewPlatformExit.

WakeupOnViewPlatformEntry Constructor Summary

Thừa kế: WakeupCriterion

Lớp xác định một wakeup trong lần đầu tiên giao nhau của ViewPlatform

với một boundary xác định.

WakeupOnViewPlatformEntry(Bounds region)

Hàm tạo đối tượng WakeupOnEntry.

http://tailieuhay.com 429

Page 430: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

WakeupOnViewPlatformEntry Method Summary

Bounds getBounds()

Trả về bound của đối tượng xác định

WakeupOnViewPlatformExit

WakeupOnViewPlatformExit Constructor Summary

Thừa kế : WakeupCriterion

Lớp xác định một wakeup trong lần đầu tiên khi ViewPlatform không còn

giao nhau với đối tượng boundary xác định

WakeupOnViewPlatformExit(Bounds region)

Hàm tạo đối tượng WakeupOnExit

WakeupOnViewPlatformExit Method Summary

Bounds getBounds()

Trả về bound của đối tượng xác định

4.3.4 Thành phần của WakeupCondition

Nhiều đối tượng WakeupCriterion có thể được kết hợp gắn với một

WakeupCondition sử dụng 4 lớp được giới thiệu trong phần sau. Hai

lớp đầu tiên được gắn liền vào một WakeupCondition từ một tập

WakeupCriterion mọt cách vật lý.Lớp thứ ba và lớp thư tư cho phép kết

http://tailieuhay.com 430

Page 431: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

hợp các thể hiện của hai lớp đầu tiên thành một đối tượng

WakeupCondition phức tạp.

WakeupAnd Constructor Summary

extends: WakeupCondition

Class specifying any number of wakeup criterion logically ANDed

together.

WakeupAnd(WakeupCriterion[] conditions)

Constructs a new WakeupAnd condition.

WakeupOr Constructor Summary

extends: WakeupCondition

Class specifying any number of wakeup criterion logically ORed

together.

WakeupAnd(WakeupCriterion[] conditions)

Constructs a new WakeupOr condition.

WakeupAndOfOrs Constructor Summary

extends: WakeupCondition

Class specifying any number of WakeupOr condition logically ANDed

together.

WakeupAndOfOrs(WakeupOr[] conditions)

Constructs a new WakeupAndOfOrs condition..

WakeupOrOfAnds Constructor Summary

http://tailieuhay.com 431

Page 432: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

extends: WakeupCondition

Class specifying any number of WakeupAnd condition logically ORed

together.

WakeupOrsOfAnds(WakeupAnd[] conditions)

Constructs a new WakeupOrOfAnds condition.

4.4 Lớp Behaviour tiện ích xử lý bàn phím

Chúng ta đã xem xét viewer với vị trí và góc không đổi. Thay đổi

viewer là một khả năng quan trọng trong rất nhiều ứng dụng 3D. Java3D

cung cấp khả năng thay đổi vị trí, hướng của viewer. Trong hình dưới đây

chúng ta có thể thấy nền transform. Nếu như transform thay đổi, ảnh

huwỏng tới dịch chuyển hoặc định hướng lại hoặc của viewer. Từ quan

điểm này chúng ta có thể thấy thiết kế cơ bản của tương tác bàn phím: ta

có một đối tượng Behaviour thay đổi nền view để đáp lại tác động của

phím bấm.

Đây chính cách mà là lớp tiện ích Java3D làm việc. trong phần còn lại

chúng ta xem xét việc sử dụng lớp tương tác với bàn phím.

http://tailieuhay.com 432

Page 433: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Cách dịch chuyển trong SimpleUniverse

Lớp SimpleUniverse và các lớp liên quan cung cấp một sự kết hợp để

nhận được đối tượng ViewPlatformTransform object. Từ đó chúng ta

có thể di chuyển SimpleUniverse. Đặcbiệt đaọn cod dưới đây nhận được

ViewPlatformTransform từ một đối tượng SimpleUniverse

TransformGroup vpt =

su.getViewingPlatform().getViewPlatformTransform ();

4.4.1 Một ví dụ đơn giản

Ví dụ KeyNavigatorApp sau đây nằm trong thư mục

examples/Interaction

Trong chương trình này chúng ta có thể thấy được các bước thực hiện bao

gồm cả việc sử dụng lớp KeyNavigatorBehavior giống như việc sử dụng

các lớp Behaviour khác.

1. Tạo ra đối tượng KeyNavigatorBehaviour ,thiết lập transform

group

2. Thêm đối tượng KeyNavigatorBehavior vào đồ thị khung cảnh

3. Cung cấp một gới hạn (hoặc BoundingLeaf) cho đối tượng

KeyNavigatorBehavior

public BranchGroup

createSceneGraph(SimpleUniverse su) {

// Create the root of the branch graph

TransformGroup vpTrans = null;

BranchGroup objRoot = new BranchGroup();

objRoot.addChild(createLand());

// create other scene graph content

http://tailieuhay.com 433

Page 434: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

vpTrans =

su.getViewingPlatform().getViewPlatformTransform

();

translate.set( 0.0f, 0.3f, 0.0f); // 3

meter elevation

T3D.setTranslation(translate); // set as

translation

vpTrans.setTransform(T3D); // used for

initial position

KeyNavigatorBehavior keyNavBeh = new

KeyNavigatorBehavior(vpTrans);

keyNavBeh.setSchedulingBounds(new

BoundingSphere(new Point3d(),1000.0));

objRoot.addChild(keyNavBeh);

// Let Java 3D perform optimizations on

this scene graph.

objRoot.compile();

return objRoot;

}

Theo công thức các bước đã trình bày ở trên, trong phương thức

createSceneGraph đòi hỏi việc truy cập vào nhóm ViewPlatform

transform.Quá trình thực thi này truyền đối tượng SimpleUniverse vào

phương thức createSceneGraph làm cho nó trở nên active để có thể truy

cập vào các nhành view khác của SimpleUniverse, như

PlatformGeometry, ViewerAvatar, hoặc thêm một đối tượng

BoundingLeaf vào nhánh view.

Dòng 13-15 khởi tạo vị trí ban đầu của viewer. Trong trường hợp

này , đối tượng viewer được chuyển tới vị trí 0.3 meters nằm trên vị trí

http://tailieuhay.com 434

Page 435: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

ban đầu của thế giới ảo. Đầy chỉ là vị trí ban đầu và chúng ta có thẻ thay

đổi vị trí và góc của viewer sau này.

// The following allows this to be run as an

application

// as well as an applet

public KeyNavigatorApp() {

setLayout(new BorderLayout());

Canvas3D canvas3D = new Canvas3D(null);

add("Center", canvas3D);

// SimpleUniverse is a Convenience

Utility class

SimpleUniverse simpleU = new

SimpleUniverse(canvas3D);

BranchGroup scene =

createSceneGraph(simpleU);

simpleU.addBranchGraph(scene);

} // end of KeyNavigatorApp (constructor)

Cách xây dựng ứng dụng chung của một Behavior

Như bất kỳ đối tượng Behaviour khác, KeyNavigatorBehaviour

chỉ active khi khung lịch của nó giao nhau với giai đoạn active của một

ViewPlatform.

4.4.2 Lớp KeyNavigatorBehaviour và KeyNavigator

http://tailieuhay.com 435

Page 436: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Lớp tiệc ích tương tác bàn phím thực thi hai lớp. Trong thời gian chạy

chương trình có hai đối tượng. Đối tượng đầu tiên là đối tượng

KeyNavigatorBehavior, đối tượng thứ hai là KeyNavigator. Lớp thứ hai

không cần thiết phải trình bày trong tài liẹu này. Đối tượng

KeyNavigatorBehavior thực hiện hầu hết tất cả các hàm chức năng

truyền thống của mọt lớp Behaviour, ngoài việc nó gọi đến đối tượng

KeyNavigator để thực hiện phương thức perform the

processStimulus.Lớp KeyNavigator nhận sự kiện AWTEvent và chuyển

các sự kiện thành từng các phím bấm riêng biệt.Bảng dưới đây 4-3 chỉ ra

tác dụng của từng phím bấm riêng biệt. Lớp KeyNavigator thực thi sự

vận động nhanh chóng.

KeyNavigatorBehavior Constructor Summary

Gói: com.sun.j3d.utils.behaviors.keyboard

Thừa kế : Behavior

Lớp là một behavior đơn giản that gọi đến KeyNavigator để thay đổi bề

ngoài view platform

KeyNavigatorBehavior(TransformGroup targetTG)

Hàm tạo một node key navigator behavior mới có tác dụng trên nhóm

transform xác định

KeyNavigatorBehavior Method Summary

void initialize()

Hàm đè phương thức khởi tạo của lớp Behavior để thiết lập thông số

wakeupvoid processStmulus(java.util.Enumeration criteria)

Hàm đè phương thức processStimulus của lớp Behavior để quản lý sự

kiện

http://tailieuhay.com 436

Page 437: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

4.5 Lớp tiện ích tương tác với chuột

Gói tiện ích Behaviour (com.sun.j3d.utils.behaviors.mouse) chứa

những lớp Behaviour tỏng đó quản lý việc tương tác với chuột. Bao gồm

các lớp để chuyển dịch, phóng to/nhỏ và điều khiển quay các đối tượng

trực quan theo sự di chuyển của chuột.

Bảng 4-4 tổng hợp lại 3 Behaviour xác định của trong việc tương tác

với chuột the. Trong gói còn có chứa lớp cơ sở trừu tượng

MouseBehavior class và giao diện MouseCallback . Lớp cơ sở trừu

tượng và giao diện được sử dụng để tạo ra các Behaviour xác định của

con chuột.

4.5.1 Sử dụng lớp MouseBehaviour

Sử dụng lớp mouse Behaviour cũng tương tự như ki sử dụng ácc

lứop Behaviour khác.

Các bước khi sử dụng lớp mouse Behaviour

1.Cung cấp khả năng đọc và ghi cho đối tượng đích transform group

2. Khởi toạ một đối tượng MouseBehavior

3. Thiết lập đối tượng đích đến transform group

4. Cung cấp một giứoi hạn (or BoundingLeaf) cho đối tượng

MouseBehavior

5. Thêm đối tượng MouseBehavior vào đồ thị khung cảnh

Figure 4-10 Recipe for Using Mouse Behavior Classes

Tuy nhiên các bước trên là kô bắt buộc phải thực hiện đầy đủ. Bước 2

và bước 3 có thể cung thực hiện trong một hàm tạo. ví dụ dưới đây giới

http://tailieuhay.com 437

Page 438: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

thiệu phương thức createSceneGraph từ ví dụ MouseRotateApp. Đồ thị

khung cảnh chứa đối tượng ColorCube. Người dùng có thể quay đối

tượng ColorCube sử dụng chuột và cả đối tượng MouseRotate trong đồ

thị khung cảnh

// MouseRotateApp renders a single,

interactively rotatable cube.

public class MouseRotateApp extends Applet {

public BranchGroup createSceneGraph() {

// Create the root of the branch graph

BranchGroup objRoot = new BranchGroup();

TransformGroup objRotate = new

TransformGroup();

objRotate.setCapability(TransformGroup.ALLOW_TRAN

SFORM_WRITE);

objRotate.setCapability(TransformGroup.ALLOW_TRAN

SFORM_READ);

objRoot.addChild(objRotate);

objRotate.addChild(new ColorCube(0.4));

objRoot.addChild(new Axis());

http://tailieuhay.com 438

Page 439: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

MouseRotate myMouseRotate = new

MouseRotate();

myMouseRotate.setTransformGroup(objRotate);

myMouseRotate.setSchedulingBounds(new

BoundingSphere());

objRoot.addChild(myMouseRotate);

// Let Java 3D perform optimizations on

this scene graph.

objRoot.compile();

return objRoot;

} // end of CreateSceneGraph method of

MouseRotateApp

// Create a simple scene and attach it to the

virtual universe

public MouseRotateApp() {

setLayout(new BorderLayout());

Canvas3D canvas3D = new Canvas3D(null);

add("Center", canvas3D);

BranchGroup scene = createSceneGraph();

// SimpleUniverse is a Convenience

Utility class

http://tailieuhay.com 439

Page 440: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

SimpleUniverse simpleU = new

SimpleUniverse(canvas3D);

// This will move the ViewPlatform back a

bit so the

// objects in the scene can be viewed.

simpleU.getViewingPlatform().setNominalViewingTra

nsform();

simpleU.addBranchGraph(scene);

} // end of MouseRotateApp (constructor)

// The following allows this to be run as an

application

// as well as an applet

public static void main(String[] args) {

System.out

.print("MouseRotateApp.java \n-

a demonstration of using the MouseRotate ");

System.out

.println("utility behavior class

to provide interaction in a Java 3D scene.");

System.out

.println("Hold the mouse button

while moving the mouse to make the cube

rotate.");

http://tailieuhay.com 440

Page 441: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

System.out

.println("This is a simple

example progam from The Java 3D API Tutorial.");

System.out.println("The Java 3D Tutorial

is available on the web at:");

System.out

.println("http://java.sun.com/pr

oducts/java-media/3D/collateral");

Frame frame = new MainFrame(new

MouseRotateApp(), 256, 256);

} // end of main (method of MouseRotateApp)

} // end of class MouseRotateApp

Code Fragment 4-7 Using the MouseRotate Utility Class

Chương trình cho kết qủa:

http://tailieuhay.com 441

Page 442: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Một cách tương tự chúng ta có thể làm việc với hai lớp mouse

Behaviour còn lại. Trong thực técả ba lớp này đều có thể dùng chung

trong một ứng dụng tác động cùn vào một đối tượng trực quan Chúng ta

cũng chỉ cần một đối tượng TransformGroup chung có cả 3 đối tượng

mouse behaviors. Trong ví dụ tiếp theo chúng ta xem xét các thức hai

mouse Behaviour cùng hành động trong một thế giới ảo. Ví dụ

MouseRotate2App tạo ra một đồ thị khung cảnh với hai đối tượng

ColorCube nằm gần nhau.Mỗi đối tượng ColorCubes gắn liền với một đối

tượng MouseRotate.

Khi cả hai đối tượng mouse behavior cùng active, lúc đo người dùng

click và di chuyển chuột, cả hai đối tượng ColorCubes cùng quay.

Nếu chúng ta không muốn cả hai đối tượng cùng quay, ta có hai giải

pháp

• Thay đổi vị trí viewer hay thay đổi khung lịch của Behaviour sao

cho chỉ có một Behaviour đuwọc active

• Sử dụng kỹ thuật picking cách ly Behaviour. Ký thuật picking

được xem xét trong phần 4.6

Trong phần 4.6 chúng sẽ sử dụng các lớp thích hợp để có thể kết hợp

các mouse Behaviour với picking cho phép người dùng tương tác với

từng đối tượng trực quan tại một thời điểm.

4.5.2 Mouse Behaviour Foundation

Các phương thức mouse Behaviour xác định (MouseRotate,

MouseTranslate, và MouseZoom) là mở rộng của lớp cơ sỏ trưừ tượng

MouseBehavior và thực thi giao diện MouseCallback .

Lớp cơ sở trừu tượng Mouse Behavior

http://tailieuhay.com 442

Page 443: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Lớp cơ sở trừu tượng được giới thiệu sau đây khi chúng ta muốn thừa

kế nó đê viết các lớp mouse Behaviour của rieng mình.

MouseBehavior Method Summary

Lớp cơ sở cho tất cả các thao tác chuột mouse

void initialize()

Khởi tạo behavior.

void processMouseEvent(java.awt.event.MouseEvent evt)

kiểm soat các sự kiện chuột.

void processStimulus(java.util.Enumeration criteria)

Tất cả các thao tác chuột phải thực thi phương thức này của lớp

Behaviour void setTransformGroup(TransformGroup

TransformGroup)

Thiết lập TransformGroup đích cho Behaviour

void wakeup()

Gọi đến phương thức wakeup.

MouseCallback Interface

Một lớp thực thi giao diện này cung cấp phương thức

transformChanged, phương thức này sẽ được gọi khi đối tượng đich

transform thay đổi theo một cách thức xác định. cả 3 lớp mouse

Behaviour đều phải thực thi giao diện này. Chúng ta cũng có thể viết đè

phương thức transformChanged của một trong số các lớp kia để xác định

phương thức được gọi khi đối tượng transform thay đổi

Các phương thức Interface MouseBehaviorCallback

Gói: com.sun.j3d.utils.behaviors.mouse

void transformChanged(int type, Transform3D transform)

http://tailieuhay.com 443

Page 444: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Lớp thực thi giao diện này đựơc dăng ký với một trong số các

MouseBehaviors sẽ được gọi mỗi khi Behaviour cập nhật transform.

Giá trị của type: MouseCallback.ROTATE,

MouseCallback.TRANSLATE, hoặc MouseCallback.ZOOM.

4.5.3 Các lớp MouseBehaviour

Mouse Rotate

Một đồ thị khung cảnh có chưa một đối tượng MouseRotate cho phép

nguời dùng quay đối tượng truqj quan. Chúng ta sẽ xem chi tiết trong các

ví dụ MouseRotateApp,

MouseRotate2App, và MouseBehaviorApp.

Hàm tạo MouseRotate Constructor

Gói: com.sun.j3d.utils.behaviors.mouse

Thừa kế : MouseBehavior

MouseRotate là một Behaviour cho phép người dùng điều khiẻn việc

quay đối tượng thông qua chuột. Để sử dụng lớp này, trước hết tạo ra một

transform group mà hành động quay này tác động vào. người dùng có thẻ

quay bất cứ đối tượng con nào của nhóm TransformGroup.

MouseRotate()

Hàm tạo một mouse rotate behavior mặc định.

MouseRotate(TransformGroup TransformGroup)

Hàm tạo một mouse rotate behavior gắn với TransformGroup

MouseRotate(int flags)

Khởi tạo một mouse behavior với cờ, giái trị của cờ:

MouseBehavior.INVERT_INPUT Cho phép đảo ngược đầu vào.

http://tailieuhay.com 444

Page 445: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

MouseBehavior.MANUAL_WAKEUP Cho phép gọi Behaviour một

cách chủ động

Tổng hợp phương thức MouseRotate

void setFactor(double factor)

void setFactor(double xFactor, double yFactor)

void setupCallback(MouseBehaviorCallback callback)

Phương thức transformChanged trong lớp callback sẽ đựoc gọi tự động

mỗi khi transform được cập nhật

void transformChanged(Transform3D transform)

Chúng ta có thẻ chông hàm, khi đó hàm mới sẽ được gọi mỗi khi

Behaviour cập nhật transform

MouseTranslate

Cho phép người dùng di chuyển đối tượng trực quan trong một mặt

phẳng song song với mặt phẳng xác định trong không gian ảo. Xem ví dụ

MouseBehaviorApp.

MouseTranslate Constructor Summary

Gói : com.sun.j3d.utils.behaviors.mouse

Thừa kế : MouseBehavior

MouseTranslate là một đối tượng Behaviour cho phép người dùng điều

khiển sự chuyển động theo (X/Y) của một đối tượng bằn các sự dụng

chuột phải

MouseTranslate()

Khởi tạo một Behaviour dịch chuyển mặc định

MouseTranslate(TransformGroup TransformGroup)

Khởi tạo một Behaviour dịch chuyển với tham số TransformGroup

http://tailieuhay.com 445

Page 446: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

MouseTranslate(int flags)

Khởi tạo một Behaviour dịch chuyển với tham số cờ. Cờ nhận một trong

các giá trị:

MouseBehavior.INVERT_INPUT Cho phép đảo ngược đầu vào.

MouseBehavior.MANUAL_WAKEUP Cho phép gọi Behaviour một

cách chủ động

MouseTranslate Method Summary

void setFactor(double factor)

void setFactor(double xFactor, double yFactor)

void setupCallback(MouseBehaviorCallback callback)

Phương thức transformChanged trong lớp callback sẽ đựoc gọi tự động

mỗi khi transform được cập nhật

void transformChanged(Transform3D transform)

Chúng ta có thẻ chông hàm, khi đó hàm mới sẽ được gọi mỗi khi

Behaviour cập nhật transform

MouseZoom

Cho phép người dùng di chuyển đối tượng trực quan trong một mặt

phẳng trực giao với .Xem them ví dụ MouseBehaviorApp.

Hàm tạo MouseZoom

Gói: com.sun.j3d.utils.behaviors.mouse

Thừa kế : MouseBehavior

MouseZoom là một đối tượng behavior cho phép người dùng thay đổi vị

trí của đối tượng truqjc uan theo trục Z bằn nút giữ của chuột.

MouseZoom()

Tạo ra đối tượng mouse zoom behavior mặc định.

http://tailieuhay.com 446

Page 447: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

MouseZoom(TransformGroup TransformGroup)

Tạo ra đối tượng mouse zoom behavior với tham số transform group.

MouseZoom(int flags)

Khởi tạo một zoom Behaviour với tham số cờ. Cờ nhận một trong các giá

trị:

MouseBehavior.INVERT_INPUT Cho phép đảo ngược đầu vào.

MouseBehavior.MANUAL_WAKEUP Cho phép gọi Behaviour một

cách chủ động

MouseZoom Method Summary

void setFactor(double factor)

void setupCallback(MouseBehaviorCallback callback)

void transformChanged(Transform3D transform)

Chúng ta có thẻ chông hàm, khi đó hàm mới sẽ được gọi mỗi khi

Behaviour cập nhật transform

4.5.4 Mouse Navigation

Trong số các hàm tạo của ba lớp mouse Behaviour đều có tham số

flag.Khi cờ có giá trị MouseBehavior.INVERT_INPUTS đối tượng

mouse Behaviour đảo ngược lại thứ tự của input. Nhờ vậy ta các lớp

mouse Behaviour có thể dùng để điều khiển chuyển hướng.Xem ví dụ

MouseNavigatorApp.

Đoạn code trong 4-8 trình bày phương thức createSceneGraph. Đối tượng

TransformGroup đích của mỗi đối tượng the mouse behavior objects là

ViewPlatform transform. Đối tượng SimpleUniverse là tham số truyền

http://tailieuhay.com 447

Page 448: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

cho phương thức createSceneGraph vì vậy đối tượng ViewPlatform có thể

được truy cập.

public BranchGroup

createSceneGraph(SimpleUniverse su) {

// Create the root of the branch graph

BranchGroup objRoot = new BranchGroup();

TransformGroup vpTrans = null;

BoundingSphere mouseBounds = null;

vpTrans =

su.getViewingPlatform().getViewPlatformTransform(

);

objRoot.addChild(new ColorCube(0.4));

objRoot.addChild(new Axis());

mouseBounds = new BoundingSphere(new

Point3d(), 1000.0);

MouseRotate myMouseRotate = new

MouseRotate(MouseBehavior.INVERT_INPUT);

myMouseRotate.setTransformGroup(vpTrans);

myMouseRotate.setSchedulingBounds(mouseBo

unds);

objRoot.addChild(myMouseRotate);

http://tailieuhay.com 448

Page 449: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

MouseTranslate myMouseTranslate = new

MouseTranslate(MouseBehavior.INVERT_INPUT);

myMouseTranslate.setTransformGroup(vpTran

s);

myMouseTranslate.setSchedulingBounds(mous

eBounds);

objRoot.addChild(myMouseTranslate);

MouseZoom myMouseZoom = new

MouseZoom(MouseBehavior.INVERT_INPUT);

myMouseZoom.setTransformGroup(vpTrans);

myMouseZoom.setSchedulingBounds(mouseBoun

ds);

objRoot.addChild(myMouseZoom);

// Let Java 3D perform optimizations on this

scene graph.

objRoot.compile();

return objRoot;

} // end of CreateSceneGraph method of

MouseNavigatorApp

Kết quả cho ta là:

http://tailieuhay.com 449

Page 450: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

4.6 Picking Object

Trong ví dụ MouseRotate2App, cả hai đối tượng ColorCube đều quay

khi gặp tác động của guời dùng. Trong ví dụ đó cả hai đối tượng đều chưa

có thể quay một cách đọc lập.Kỹ thuật picking cho phép chúng ta tương

tác với từng đối tượng trực quan trong đồ thị khung cảnh .

Picking được thực thi bởi một Behaviour, dưới sự kích hoạt của sự kiện

click chuột. Để picking một đối tượng, người dùng di chuyển chuột vào

đối tượng trực quan và click chuột. Đối tượng behavior được kích hoạt

bởi sự kiện click chuột và thực hiện picking. Một ray là một tia đựoc

chiếu từ vị trí con trỏ chuột song song với projected.

Sự giao nhau của ray với đối tượng trong không gian ảo được tính toán .

Đối tượng trực quan giao cắt với mặt phẳng khung hình gần nhất được

clựa chọn để giao cắt.

http://tailieuhay.com 450

Page 451: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Một pick ray trong không gian ảo

Một cách tổng thể, quá trình giao cắt không thực hiện trực tiếp trên

đối tượng được lựa chọn, mà làm việc với đối tượng chuyển hướng đồ thị

khung cảnh đến đối tượng. Lấy ví dụ để picking một đối tượng

ColorCube object để điều khiển quay , đối tượng ColorCube không bị

trực tiếp điều khiển mà thay vào đó là đối tượng TransformGroup nằm

trên đối tượng ColorCube trong cùng path đến đối tượng ColorCube. Nói

một cách khác nếu công việc picking kựa chọn đối tượng trực quan nhằm

thay đổi mầu sắc của đối tượng,khi đó đối tượng trực quan phải được tác

động một cách trực tiếp.

Việc xác định chính xác đối tượng được xử lý không phải là một công

việc đơn giản. Nếu chúng ta cần quay một đối tượng hìn lập phương 6

mặt , mỗi mặt là một đối tượng Shape3D đọc lập được sapư xếp bởi 6 đối

tượng TransformGroup , khi đó đối tượng hình lập phương sẽ cần phải

giao cắt trực tiếp chứ không phải là đối tượng TransformGroup

Việc quay đối tượng hình lập phương bằng việc tương tác đến đối

tượng TransformGroup, là con của đối tượng BranchGroup trong đồ thị

khung cảnh .

http://tailieuhay.com 451

Page 452: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Việc tính toán quá trình giao cắt là rất “tốn kém”. Vì vậy, picking đòi

hỏi khả năng tính toán cao và làm tăng độ phức tạp của đồ thị khung

cảnh. trong Java3D cung cấp cho chúng ta những cách khác nhau để giới

hạn số lượng tính toán phải thực hiẹn trong picking. Một cách quan trọng

là sử dụng khẳ năng và thuộc tính các node của đồ thị khung cảnh.

Một node trong đồ thị khung cảnh có phương thức setPickable()đặt là

false khi đó đối tượng node này và tất cả các đối tượng con của nó đều

không thể picking Bởi vậy, những node không được xem xét đến khi tính

toán giao cắt.

Một đặc điểm khác của lớp Node là khả năng

ENABLE_PICK_REPORTING. Khả năng này chỉ áp dụng với một nhóm

node.

Node Method (partial list)

Thừa kế : SceneGraphObject

Lớp con: Group, Leaf

Lớp Node là một lớp cơ sở trừu tượng cho tất cả các Group và Leaf

Nodes.Nó cung cấp một khung thông dụng trong việc xây dựng một

http://tailieuhay.com 452

Page 453: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Java3D đồ thị khung cảnh., như specifically bounding volumes, picking

và khả năng nhận biết collision

void setBounds(Bounds bounds)

Thiết lập một đối tượng hình học bao quanh một node.

void setBoundsAutoCompute(boolean autoCompute)

Bật tắt chế độ tự động tính toán tự động đối tượng hình học bao quanh mộ

setPickable(boolean pickable)

Đặt chế độ pick, nếu là true đối tượng Node này có thẻ pick, ngựoc lại đối

tượng Node và các con của nó đều không thể pick được

Node Capabilities Summary (partial list)

ENABLE_PICK_REPORTING

Chỉ định Node có thể được thông báo trong SceneGraphPath nếu như quá

trìh pick được thực hiện. Khả năng này chỉ có thẻ đuwọc định rõ cho các

Group node, nó không áp dụng cho các node lá.Giá trị mặc định là false.

ALLOW_BOUNDS_READ | WRITE

Chỉ định Node được đọc/ghi đẻ truy cập các thông tin vào khung của nó.

ALLOW_PICKABLE_READ | WRITE

Một cách khác để người lập trình có thể giảm thiểu việc tính toán

trong qú trình picking là sử dụng thử nghiệm giao cắt của khung bao

quanh thay vì việc sử dụng giao cắt của các đối tượng hình học. Rất nhìeu

lớp có các hàm tạo và phương thức nhận tham số đầu vào

USE_BOUNDS hoặc USE_GEOMETRY. Quyết định sử dụng khung

baop quanh rõ ràng đã đem lại hiệu quả hơn nhiều (trong việc tính toán)

đối với hầu hết vì vậy hiệu năng của chương trình tăng rõ rệt. Tuy nhiên

http://tailieuhay.com 453

Page 454: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

phương án này thực tế không phải lúc nào cũng tỏ ra hiệu quả và thực

hiện đuợc.

Một kỹ thuật thứ 3 để giảm những tính toán phức tạp trong quá trình

picking la giới hạn phạm vi picking với những phần có liên quan trong đồ

thị khung cảnh.

4.6.1 Using Picking Utility Classes

Có hai cách tiếp cận trong quá tình sử dụng picking của java3D: sử

dụng đối tượng của lớp picking, hoặc tạo ra lớp picking mới và sử dụng

thể hiện của nó . Gói picking bao gồm các lớp để pick/rotate,

pick/translate, và pick/zoom . Mỗi lớp picking sử dụng một phím chuột

khác nhau để thực hiện quá trình điều khiển đối tượng với đầy đủ khả

năng của các lớp picking trong cùng một ứng dụng.

Trong phần này chúng ta giới thiệu các lớp tiện ích

PickRotateBehavior, PickTranslateBehavior, và PickZoomBehavior.

Trong phần tiếp theo 4.6.2 chúng ta giới thiệu các lớp hay sử dụng trong

việc tạo ra các lớp picking mới.

Do mỗi đối tượng picking behavior object có khả năng thực hiện với

bất kỳ đối tượng đồ thị khung cảnh, vì vậy chỉ cần một đối tượng picking

behavior đẻ cung cấp khả năng picking Đoạn code dưới đây mô tả công

việc cần thiết đẻ sử dụng các lớp picking behavior trong một chương trình

Java 3D

PickRotateBehavior behavior = new PickRotateBehavior(root,

canvas, bounds);

root.addChild(behavior);

http://tailieuhay.com 454

Page 455: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Đối tượng behavior sẽ quản lí bất cứ sưk kiện picking nào diễn ra

trong đồ thị khung cảnh (nằm dưới root) và xử lí các thao tác kéo thả

chuột.

Các bứoc sử dụng lớp picking

1. Khởi tạo đồ thị khung cảnh

2. Khởi tạo đối tượng picking behavior với root, canvas, và bounds

xác định.

3. Thêm đối tượng behavior vào đồ thị khung cảnh.

4. Bật chức năng thích hợp cho đối tượng đồ thị khung cảnh

Những sai sót hặygp phải khi sử dụng đối tượng Picking

Sử dụng lớp picking behavior có thể dẫn đến các sai lầm hay gặp phải

như khi lập trình với lớp behavior. Vấn đề thường gặp là: quên không bao

gồm các đối tượng behavior trong đồ thị khung cảnh, và không thiết lập

khung thích hợp cho đối tượng behavior

Chương trình ví dụ MousePickApp.

Đoạn code dưới đây trình bầy phương thức createSceneGraph của lớp

MousePickApp. Chương trình sử dụng đối tượng PickRotate object để

cung cấp quá trình tuơng tác. Đoạn code dưới đây tuân thủ các bước đã

trình bày ở trên.

public BranchGroup createSceneGraph(Canvas3D

canvas) {

// Create the root of the branch graph

BranchGroup objRoot = new BranchGroup();

TransformGroup objRotate = null;

http://tailieuhay.com 455

Page 456: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

PickRotateBehavior pickRotate = null;

Transform3D transform = new

Transform3D();

BoundingSphere behaveBounds = new

BoundingSphere();

// create ColorCube and

PickRotateBehavior objects

transform.setTranslation(new Vector3f(-

0.6f, 0.0f, -0.6f));

objRotate = new

TransformGroup(transform);

objRotate.setCapability(TransformGroup.AL

LOW_TRANSFORM_WRITE);

objRotate.setCapability(TransformGroup.AL

LOW_TRANSFORM_READ);

objRotate.setCapability(TransformGroup.EN

ABLE_PICK_REPORTING);

objRoot.addChild(objRotate);

objRotate.addChild(new ColorCube(0.4));

pickRotate = new

PickRotateBehavior(objRoot, canvas,

behaveBounds);

objRoot.addChild(pickRotate);

// add a second ColorCube object to the

scene graph

http://tailieuhay.com 456

Page 457: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

transform.setTranslation(new

Vector3f( 0.6f, 0.0f, -0.6f));

objRotate = new

TransformGroup(transform);

objRotate.setCapability(TransformGroup.AL

LOW_TRANSFORM_WRITE);

objRotate.setCapability(TransformGroup.AL

LOW_TRANSFORM_READ);

objRotate.setCapability(TransformGroup.EN

ABLE_PICK_REPORTING);

objRoot.addChild(objRotate);

objRotate.addChild(new ColorCube(0.4));

// Let Java 3D perform optimizations on this

scene graph.

objRoot.compile();

return objRoot;

} // end of CreateSceneGraph method of

MousePickApp

http://tailieuhay.com 457

Page 458: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Đoạn code trên cũng tuơng tự với ví dụ MouseRotate2App, tuy nhiên

vẫn khác nhua trong một số trường hợp. Điều khác biệt chủ yếu là ứng

dụng trên chỉ sử dụng một đối tượng behavior trong khi ứng dụng

MouseRotate2App sử dụng h2 đối tượng behavior – cho mỗi đối tượng

trực quan.

Ngoài ra chức năng của các behavior cũng rất khác nhau. Ứng dụng của

chúng ta chô phép người dùng pick một đối tượng để tương tác, trong khi

ứng dụng MouseRotate2App làm quay cả hai đối tượng.

4.6.2 Các hàm API cơ bản trong các lớp Picking

Về cơ bản có 3 'levels' picking classes được cung cấp trong Java 3D.

Các hàm Java 3D API cơ bản cung cấp các hàm chức năng ở tầng dưới

cùng. Gói tiện ích picking cung cấp nhưng lớp picking behavior chung,

phù hợp và dễ dàng thay đổi. Gói tiệc ích picking cũng cung cấp các lớp

behavior có thể sử dụng trực tiếp trong chuwong trình Java3D.

Những lớp nhân cơ bản bao gồm lớp PickShape và lớp

SceneGraphPath, và các phương thức của BranchGroup và Locale.Những

http://tailieuhay.com 458

Page 459: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

lớp này cung cấp những kỹ thuật để xác định hưng hình đựoc sử dụng

trong việc tương tác với các đối tượng trừu tượng. trong phần này chúng

ta giứoi thiệu các hàm API của các lớp : PickShape and SceneGraphPath.

Những lớp tiệc ích picking xác định sủ dụng các lớp chung để thực

thi một picking behavior xác định.

PickShape classes

Lớp cơ sở trừu tượng chỉ cung cấp một cách trừu tượng 5 lớp con:

PickBounds, PickRay, PickSegment, PickPoint, và PickCone.

Thông thường , đối tượng hình học, là đích của picking, sẽ xác định

sử dụng đối tượng pick shapes nào.Đối với các hình có dạng đa giác bất

cứ pick shape nào cũng thỏa mãn được nhiệm vụ này. Tuy nhiên có sự

khác nhau về hiêu năng sử dung giữa các lớp này.

Sơ đồ phả hệ PickShape

PickShape

Lớp con: PickBounds, PickRay, PickSegment, PickPoint, and PickCone

PickBounds

Đối tượng PickBounds thể hiện mọt khung cho pick testing.

http://tailieuhay.com 459

Page 460: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

PickBounds Constructor Summary

Thừa kế: PickShape

Một khung để cung cấp cho phương thức BranchGroup Locale pick.

PickBounds()

Hàm tạo Pickbounds

PickBounds(Bounds boundsObject)

Hàm tạo với tham số bound.

PickBounds Method Summary

Bounds get()

Trả về đối tượng bound từ đối tượng PickBounds.

void set(Bounds boundsObject)

Thiết lập boundsObject trong đối tượng PickBounds.

PickPoint

Đối tượng PickPoint thể hiẹn cho điểm picking. Là lớp con của lớp

PickShape, đối tượng PickPoint có thể được sử dụng với BranchGroup

and Locale pick testing

PickPoint Constructor Summary

Thừa kế : PickShape

Một điểm cung câp cho phương thức pick của BranchGroup và Locale

PickPoint()

Hàm tọa đối tượng PickPoint tại (0, 0, 0).

PickPoint(Point3d location)

Hàm tọa PickPoint với tham số location.

http://tailieuhay.com 460

Page 461: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

PickPoint Method Summary

void set(Point3d location)

Thiết lập giá trị vị trí của PickPoint.

PickRay

Đối tượng PickRay thể hiện một ray trong picking.

PickRay Constructor Summary

Thừa kế : PickShape

Đối tượng PickRay là một gói gọn các ray để truyền vào cho phương thức

picking trong lớp BranchGroup và Locale

PickRay()

Hàm tạo với giá trị mặc định (0, 0, 0).

PickRay(Point3d origin, Vector3d direction)

Hàm tạo với tham số hướng.

PickRay Method Summary

void set(Point3d origin, Vector3d direction)

Thiết lập một tia đến một điểm từ vị trí với tham số tọa đọ và hướng.

PickSegment

Đối tượng PickSegment biểu diễn một đoạn thẳng (defined by two

points) để picking.

Lớp con lớp PickShape, đối tượng PickSegment được sử dụng với

phương thức pick testing của BranchGroup và Locale

http://tailieuhay.com 461

Page 462: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

PickSegment Constructor Summary

Thừa kế : PickShape

PickSegment()

Hàm tạo PickSegment.

PickSegment(Point3d start, Point3d end)

Hàm tạo PickSegment tham số điểm đầu điểm cuối.

PickSegment Method Summary

void set(Point3d start, Point3d end)

Thiết lạp một PickSegment tham số điểm đầu điẻm cuối.

PickCone

PickCone lớp mới trong API phiên bản 1.2. Lớp PickCone là lớp cơ

sở trừu tượng với tất cả các khung hình nón. Khung hình nón sử dụng

hiệu quả khi picking giữa các đối tượng hình học.

Gồ hai lớp con: PickConeRay và PickConeSegment. Điểm khác biệt

giữa chúng là độ dài. PickConeRay là một hình nón với độ dài is a cone

of vô tận length trong khi PickConeSegment có độ dài giới hạn.

Đối tượng PickConeRay đựoc xác định ởi một điểm ban đầu và

hướng. Đối tượng PickConeSegment được định nghĩa hai điểm xác định

cả độ dài và huwosng của hình nón.

PickCone Method Summary

void getDirection(Vector3d direction) <new in 1.2>

http://tailieuhay.com 462

Page 463: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Trả về hướng của đối tượng PickCone

void getOrigin(Point3d origin) <new in 1.2>

double getSpreadAngle() <new in 1.2>

Trả về góc rộng của đối tượng PickCone.PickConeRay <new in 1.2>

PickConeRay Constructor Summary

Thừa kế PickCone

PickConeRay() <new in 1.2>

Hàm tạo PickConeRay.

PickConeRay(Point3d origin, Vector3d direction, <new in 1.2>

double spreadAngle)

Hàm tạo PickConeRay.

PickConeRay Method Summary

void set(Point3d origin, Vector3d direction, double spreadAngle)

Phương thức thiết lập các tham số của đối tượng PickCone

PickConeSegment <new in 1.2>

PickConeSegment Constructor Summary

Thừa kế : PickCone

PickConeSegment() <new in 1.2>

PickConeSegment(Point3d origin, Point3d end, double spreadAngle)

<new in 1.2>

PickConeSegment Method Summary

void getEnd(Point3d end) <new in 1.2>

http://tailieuhay.com 463

Page 464: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Trả về điểm cuối của đối tượng PickConeSegment. Điểm đầu đuwojc

nhận từ phương thức của lớp cha.

void set(Point3d origin, Point3d end, double spreadAngle) <new in

1.2>

PickCylinder <new in 1.2>

Lớp PickCylinder và lớp con của nó cũng tưong tự như lớp PickCone

và các lớp con của PickCone. Lớp PickCone là lớp cơ sở trừu tượng của

hai lớp: PickCylinderRay và PickCylinderSegment.

PickCylinder Method Summary

void getDirection(Vector3d direction) <new in 1.2>

Trả về hướng của đối tượng PickCylinder.

void getOrigin(Point3d origin) <new in 1.2>

Trả về điểm khởi đầu của đối tượng cylinder.

double getRadius() <new in 1.2>

Trả về goc ban đầu của đối tượng cylinder

PickCylinderRay <new in 1.2>

PickCylinderRay Constructor Summary

Thừa kế : PickCylinder

PickCylinderRay() <new in 1.2>

http://tailieuhay.com 464

Page 465: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Hàm tạo PickCylinderRay. Sử dụng phương thức set(Point3d, Vector3d

double) đẻ thiết lập các giá trị của htuộc tính

PickCylinderRay(Point3d origin, Vector3d direction, <new in 1.2>

double radius)

Hàm tạo với tham số điểm ban đầu và hứong.

PickCylinderRay Method Summary

void set(Point3d origin, Vector3d direction, double radius) <new in

1.2>

Phương thức thiết lập giá trị cho các thuộc tính của đối tượng

PickCylinderRay.

PickCylinderSegment <new in 1.2>

PickCylinderSegment Constructor Summary

Thừa kế : PickCylinder

PickCylinderSegment() <new in 1.2>

Hàm tạo PickCylinderSegment.

PickCylinderSegment(Point3d origin, Point3d end, double radius)

<new in 1.2>

PickCylinderRay Method Summary

void getEnd(Point3d end) <new in 1.2>

Trả về điểm cuối đối tượng PickCylinderSegment.

void set(Point3d origin, Point3d end, double radius) <new in 1.2>

SceneGraphPath

http://tailieuhay.com 465

Page 466: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Lớp SceneGraphPath được sử dụng trong hầu hết các ứng dụng

picking.Điều này là do quá trình picking thuwongf xuyên bao gồm quá

trình tìm đừong đi trong đồ thị khung cảnh có chứa đối tượng cần tương

tác. Một đối tượng SceneGraphPath thể hiện một đường đi trong đồ thị

khung cảnh.

SceneGraphPath Method Summary (partial list)

boolean equals(java.lang.Object o1)

Trả về true nếu đối tượng o1 có kiêu SceneGraphPath và các dữ liệu

thành phần của đối tượng o1 tương ứng bằng với các thành phần dữ liệu

của đối tượng SceneGraphPath và néu giá trị của transforms cũng bằng

nhau

Transform3D getTransform()

Trả về bản copy của transform gắn liền với đối tượng SceneGraphPath;

trả về null nếu không có transform.

int hashCode()

boolean isSamePath(SceneGraphPath testPath)

Xác định hai đối tượng đại diện cho cùng một đường đi hay không.

int nodeCount()

Trả về số node của đừong đi.

void set(SceneGraphPath newPath)

void setLocale(Locale newLocale)

Thiết lập đường đi là đường đi từ đối tượng Locale đến một đối tượng

Locale.xác định

void setNode(int index, Node newNode)

void setNodes(Node[] nodes)

void setObject(Node object)

http://tailieuhay.com 466

Page 467: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

void setTransform(Transform3D trans)

java.lang.String toString()

Các phương thức picking của BranchGroup và Local Picking

Đây là tầng thấp nhất trong việc tính toán picking được cung cấp

trong Java 3D API.

BranchGroup and Locale picking methods for use with PickShape

SceneGraphPath[] pickAll(PickShape pickShape)

Trả về mảng tham chiếu các node nằm duới BranchGroup,có thể pick và

có giao cắt với đối tượng PickShape.

SceneGraphPath[] pickAllSorted(PickShape pickShape)

Trả về một mảng các có thứ tự tham chiếu đến các thành phần có thể pick

đựoc và có giao cắt với đối tượng pickShape. Phần tử [0] tham chiếu đến

thành phần nằm gần đối tượng PickShape nhất

SceneGraphPath pickClosest(PickShape pickShape)

SceneGraphPath pickAny(PickShape pickShape)

4.6.3 Các lớp picking

Những lớp picking nói chung được dùng hiệu quả trong việc tạo ra

các picking behavior . Các lớp : PickMouseBehavior, PickObject,và

PickCallback.

PickMouseBehavior Class

Lớp cơ sở cung cấp các phương thức picking behavior.Lớp này còn

rất hiệu quả trong việc xây dựung các picking class sau này bằng việc

thừa kế nó.

PickMouseBehavior Method Summary

http://tailieuhay.com 467

Page 468: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Gói : com.sun.j3d.utils.behaviors.picking

Thừa kế : Behavior

void initialize()

Phương thức này cần được viết đè để cung cấp các trạng thái ban đầu và

các đièu kiện trigger ban đầu.

void processStimulus(java.util.Enumeration criteria)

void updateScene(int xpos, int ypos)

PickObject Class

Lớp PickObject cung cấp các phương thức xác định đối tượng nào

đựoc chọn bởi hành động pick của người dùng.

PickObject Constructor Summary

Gói: com.sun.j3d.utils.behaviors.picking

Thừa kế : java.lang.Object

PickObject(Canvas3D c, BranchGroup root)

Hàm tạo PickObject.

PickObject Method Summary (partial list)

Lớp PickObject có nhiều phương thức đẻ tính toán sự giao cắt của một

đối tượng pickRay với đối tượng đồ thị khung cảnh..

PickShape generatePickRay(int xpos, int ypos)

Khởi tạo một đối tượng PickRay bắt đầu từ vị trí của viewer và trỏ tới

điểm xác địnhtheo huwonsg xác định.

PickObject Method Summary (partial list - continued)

http://tailieuhay.com 468

Page 469: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

SceneGraphPath[] pickAll(int xpos, int ypos)

Trả về một mảng tham chiếu tất cả các thành phần nằm dưới

BranchGroup có giao cắt với một ray bắt đầu từ vị trí viewer và trỏ tới

khung hình theo hướng và đỉem tới xác định

SceneGraphPath[] pickAllSorted(int xpos, int ypos)

Tương tự phương thức trên nhưng mảng trả vè được sắp xếp theo thứ tự.

SceneGraphPath pickAny(int xpos, int ypos)

Trả về tham chiếu đến một đối tượng nằm dưới BranchGroup có giao cắt

với một ray bắt đầu từ vị trí viewer và trỏ tới khung hình theo hướng và

đỉem tới xác định

SceneGraphPath pickClosest(int xpos, int ypos)

Node pickNode(SceneGraphPath sgPath, int node_types)

Trả về một đối tượng Node có kiểu xác định và có chưa đối tượng

SceneGraphPath xác định giá trị của kiểu node:

PickObject.BRANCH_GROUP,

PickObject.GROUP, PickObject.LINK, PickObject.MORPH,

PickObject.PRIMITIVE,

PickObject.SHAPE3D, PickObject.SWITCH,

PickObject.TRANSFORM_GROUP.

Node pickNode(SceneGraphPath sgPath, int node_types, int

occurrence)

PickingCallback Interface

Giao diện PickingCallback cung cấp một khng làm việc để thừa kế

một lớp picking đã có trước.

Interface PickingCallback Method Summary

http://tailieuhay.com 469

Page 470: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Gói: com.sun.j3d.utils.behaviors.picking

void transformChanged(int type, TransformGroup tg)

Lớp Intersect

Lớp cung cấp các phương thức để kiểm tra việc qiao cắt của một đối

tượng PickShape (core class) với một đối tượng geometry primitives.

Intersect Constructor Summary

Gói: com.sun.j3d.utils.behaviors.picking

Thừa kế : java.lang.Object

Intersect()

Hàm tạo Intersect.

Intersect Method Summary (partial list)

boolean pointAndLine(PickPoint point, Point3d[] coordinates, int

index)

Trả về true nếu như đối tượng PickPoint và đối tượng Line giao nhau.

Lien đuợc xác định bởi tham số đầu vào.

boolean pointAndPoint(PickPoint point, Point3d pnt)

Tra về true néu đối tượng PickPoint và đối tượng Point3d giao cắt nhau.

boolean rayAndLine(PickRay ray, Point3d[] coordinates, int index,

double[] dist)

boolean rayAndPoint(PickRay ray, Point3d pnt, double[] dist)

boolean rayAndQuad(PickRay ray, Point3d[] coordinates, int index,

double[] dist)

boolean rayAndTriangle(PickRay ray, Point3d[] coordinates, int

index,

http://tailieuhay.com 470

Page 471: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

double[] dist)

boolean segmentAndLine(PickSegment segment, Point3d[]

coordinates, int index,

double[] dist)

Intersect Method Summary (partial list - continued)

boolean segmentAndPoint(PickSegment segment, Point3d pnt,

double[] dist)

boolean segmentAndQuad(PickSegment segment, Point3d[]

coordinates, int index,

double[] dist)

boolean segmentAndTriangle(PickSegment segment, Point3d[]

coordinates,

int index, double[] dist)

4.6.4 Các lớp Picking Behavior

Gói com.sun.j3d.utils.behaviors.picking cung cấp các lớp

PickRotateBehavior

Lớp PickRotateBehavior cho phép người dùng tưong tác pick và

rotate đối tượng trực quan.

PickRotateBehavior Constructor Summary

Gói: com.sun.j3d.utils.behaviors.picking

Thừa kế : PickMouseBehavior

Thực this: PickingCallback

PickRotateBehavior(BranchGroup root, Canvas3D canvas, Bounds

bounds)

http://tailieuhay.com 471

Page 472: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

PickRotateBehavior(BranchGroup root, Canvas3D canvas, Bounds

bounds,

int pickMode)

Giáptrị PickMode : PickObject.USE_BOUNDS hay

PickObject.USE_GEOMETRY. Note: If pickMode is set

to PickObject.USE_GEOMETRY, all geometry objects in the scene

graph intended to be available for picking

must have their ALLOW_INTERSECT bit set.

PickRotateBehavior Method Summary

void setPickMode(int pickMode)

Thiết lập giá trị pickMode: nhạn một trong các giá trị

PickObject.USE_BOUNDS hay

PickObject.USE_GEOMETRY.

void setupCallback(PickingCallback callback)

void transformChanged(int type, Transform3D transform)

void updateScene(int xpos, int ypos)

PickTranslateBehavior

Lớp PickTranslateBehavior cho phép người dung tương tác pick và

translate đối tượng trực quan. Một thể hiện của lớp

PickTranslateBehavior có thể đuợc sử dụng kết hợp với các đối tượng

tcủa các lớp picking khác.

PickTranslateBehavior Constructor Summary

Gói : com.sun.j3d.utils.behaviors.picking

Thừa kế : PickMouseBehavior

http://tailieuhay.com 472

Page 473: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Thực thi: PickingCallback

PickTranslateBehavior(BranchGroup root, Canvas3D canvas,

Bounds bounds)

Khởi tạo hành vi pick/translate chờ sự kiện từ chuột trong đồ thị khung

cảnh

PickTranslateBehavior(BranchGroup root, Canvas3D canvas,

Bounds bounds,

int pickMode)

PickTranslateBehavior Method Summary

void setPickMode(int pickMode)

Thiết lạp giá trị thành phần pickMode

void setupCallback(PickingCallback callback)

Đăng kí lớp callback được gọi mỗi khi đối tượng được kích họat.

void transformChanged(int type, Transform3D transform)

void updateScene(int xpos, int ypos)

PickZoomBehavior

Lớp PickZoomBehavior cho phép người dung tương tác pick và zoom

đối tượng trực quan. Một thể hiện của lớp PickZoomBehavior có thể đuợc

sử dụng kết hợp với các đối tượng tcủa các lớp picking khác.

PickZoomBehavior Constructor Summary

Gói: com.sun.j3d.utils.behaviors.picking

Thừa kế : PickMouseBehavior

Thực thi: PickingCallback

http://tailieuhay.com 473

Page 474: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

PickZoomBehavior(BranchGroup root, Canvas3D canvas, Bounds

bounds)

Khởi tạo hành vi pick/zoom chờ sự kiện từ chuột trong đồ thị khung cảnh

PickZoomBehavior(BranchGroup root, Canvas3D canvas, Bounds

bounds,

int pickMode)

PickZoomBehavior Method Summary

void setPickMode(int pickMode)

Thiết lạp giá trị thành phần pickMode .

void setupCallback(PickingCallback callback)

Đăng kí lớp callback được gọi mỗi khi đối tượng được kích họat.

void transformChanged(int type, Transform3D transform)

Phương thức Callback từ lớp MouseZoom.

void updateScene(int xpos, int ypos)

Cập nhật khung cảnh .

CHƯƠNG 5

Hoạt Hình

http://tailieuhay.com 474

Page 475: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Trong chương này, chúng tôi sẽ trình bày các vấn đề cơ bản sau:

• Sử dụng các lớp Alpha và Interpolator để thêm các hoạt ảnh

đơn giản

• Sử dụng các lớp LOD và Billboard để giảm khối lượng tính

toán khi tạo các hoạt ảnh

• Sử dụng đối tượng Morph với các đối tượng hành vi tùy chỉnh

để tạo hoạt ảnh từ các khung hình chính

• Tạo đối tượng hình học động để tạo Behavior hiệu chỉnh dữ liệu

BY_REFERENCE.

Trong thế giới ảo, có rất nhiều đối tượng trực quan thay đổi độc lập với

hành động của con người. Ví như một chiếc đồng hồ ảo chẳng hạn, nó có

thể hoạt động mà không cần tương tác của người dùng. Chiếc đồng hồ

chính là một ví dụ về hoạt ảnh. Vậy hoạt ảnh là những thay đổi xảy ra

trong vũ trụ ảo mà không có tương tác trực tiếp của con người. Ngược lại,

những thay đổi xảy ra trong vũ trụ ảo mà là kết quả trực tiếp của hành

động người dùng thì được gọi là tương tác (chúng ta đã xét trong chương

4).

http://tailieuhay.com 475

Page 476: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Animation - Hoạt hình:

Tương tự như phần tương tác, hoạt ảnh trong Java 3D cũng được cài

đặt nhờ sử dụng đối tượng Behavior (hành vi). Bất cứ hoạt ảnh nào cũng

có thể tạo ra được với các đối tượng hành vi. Tuy nhiên, Java 3D API

cung cấp một tập các lớp cho phép tạo hoạt ảnh mà không phải tạo một

lớp mới. Các lớp này đều kế thừa lớp Behavior.

Java 3D cung cấp một tập các lớp hoạt ảnh có vai trò như những bộ

nội suy (Interpolator ). Đối tượng Interpolator cùng với một đối tượng

Alpha điều khiển một vài thông số của đối tượng đồ thị khung cảnh để

tạo ra hoạt ảnh dựa thời gian. Đối tượng Alpha cung cấp cơ chế định thời

gian. Chi tiết về hai lớp đối tượng này sẽ được bàn đến trong mục 5.2.

Một tập các lớp hoạt ảnh khác trong Java 3D tạo hoạt ảnh cho các đối

tượng trực quan nhờ đáp ứng sự thay đổi về khung nhìn. Tập các lớp này

(bao gồm: lớp OrientedShape3D, các lớp hành vi Billboard và Level Of

Detail (LOD )) không được điều khiển bởi các khoảng thời gian mà bởi

vị trí và hướng của khung nhìn. Hai lớp hành vi sẽ được xét kĩ hơn trong

các mục 5.3 và 5.5

Một vài lớp hoạt ảnh không kế thừa từ lớp Behavior như:

OrientedShape3D và Morph . Mục 5.4 sẽ trình bày về OrientedShape3D,

lớp hoạt ảnh được đưa vào Java 3D API từ phiên bản v1.2 như một sự

thay thế cho hành vi Billboard trong các phiên bản trước đó. Mục 5.6

trình bày về Morph , lớp hoạt ảnh được sử dụng cả trong các ứng dụng

hoạt ảnh và nội suy.

http://tailieuhay.com 476

Page 477: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Hình 5-1. Sơ đồ phân cấp các lớp hoạt ảnh kế thừa Behavior

Đối tượng Interpolator và Alpha với hoạt ảnh dựa thời gian

Đối tượng Alpha sinh ra một giá trị nằm trong khoảng từ 0 đến 1 tùy

thuộc vào thời gian và các tham số của đối tượng Alpha. Thực thể nội suy

(Interpolator ) là các đối tượng hành vi tùy chỉnh sử dụng một đối tượng

Alpha để sinh hoạt ảnh cho các đối tượng trực quan. Nội suy bao gồm sự

thay đổi vị trí, hướng, độ lớn, màu sắc hoặc độ trong suốt của đối tượng.

Các hành vi nội suy có thể được cài đặt bằng cách tạo ra một lớp hành vi

tùy chỉnh, tuy nhiên, sử dụng lớp nội suy cho phép tạo hoạt ảnh dễ dàng

hơn nhiều. Trong phần 5.2.3, chúng ta sẽ xét một ví dụ sử dụng lớp nội

suy RotationInterpolator.

Alpha

Đối tượng Alpha sinh ra một giá trị, được gọi là giá trị Alpha, nằm

trong khoảng từ 0.0 và 1.0, kể cả hai đầu mút. Giá trị Alpha thay đổi theo

thời gian như đã định sẵn bởi các tham số của đối tượng Alpha. Với các

bộ giá trị tham số nhất định, tại thời điểm cụ thể, đối tượng Alpha chỉ

sinh ra một giá trị Alpha duy nhất. Biểu diễn bằng đồ thị giá trị Alpha so

với thời gian, chúng ta sẽ được một dạng sóng mà đối tượng Alpha sinh

ra.

Đồ thị dạng sóng của đối tượng Alpha có bốn đoạn: Alpha tăng,

Alpha bằng 1, Alpha giảm và Alpha bằng 0. Bốn đoạn này tạo thành một

http://tailieuhay.com 477

Page 478: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

chu kì của dạng sóng Alpha và tương ứng với bốn tham số của đối tượng

Alpha. Thời gian của một chu kì được xác định bằng một số nguyên, đơn

vị tính là mili giây. Hình 5-2 biểu diễn bốn đoạn của dạng sóng Alpha.

Việc định thời gian của các đối tượng Alpha có liên hệ với thời điểm

khởi động chúng. Thời điểm khởi động của tất cả các đối tượng Alpha

đều được lấy từ thời điểm khởi động hệ thống. Vì thế tuy các đối tượng

Alpha được tạo ra ở các thời điểm khác nhau, nhưng chúng đều có chung

một thời điểm khởi động. Kết quả là, tất cả các đối tượng nội suy mặc dù

dựa trên các đối tượng Alpha khác nhau nhưng đều được đồng bộ hóa.

Dạng sóng của các đối tượng Alpha có thể bắt đầu ở những thời điểm

khác nhau. Chu kì dạng sóng đầu tiên của một đối tượng Alpha có thể bị

trễ do việc sử dụng một trong hai hoặc cả hai tham số: TriggerTime (thời

điểm kích hoạt) và PhaseDelayDuration (thời gian trễ). TriggerTime xác

định khoảng thời gian từ lúc đối tượng Alpha khởi động cho đến khi bắt

đầu hoạt động. Sau khoảng thời gian xác định bởi tham số

PhaseDelayDuration tính từ thời điểm kích hoạt TriggerTime, chu kì của

dạng sóng đầu tiên bắt đầu. Các tham số này được thể hiện trong hình 5-

2.

Dạng sóng của đối tượng Alpha có thể quay vòng một chu kì, tiếp tục

quay vòng với số lần xác định hoặc sẽ quay vòng không dừng. Số chu kì

của sóng xác định bởi tham số loopCount. loopCount dương qui định số

chu kì, loopCount bằng –1 xác định vòng lặp không dừng. Nếu dạng sóng

Alpha quay vòng hơn 1 chu kì, tất cả các giai đoạn trên đều được lặp lại,

ngoại trừ giai đoạn trễ.

http://tailieuhay.com 478

Page 479: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Hình 5-2. Các giai đoạn của dạng sóng Alpha

Dạng sóng Alpha có thể không sử dụng tất cả bốn giai đoạn trên mà

có thể được tạo thành từ một, hai, ba hoặc bốn giai đoạn. Hình 5-3 biểu

diễn một số dạng sóng tạo bởi một, hai hoặc ba giai đoạn.

Đối tượng Alpha có hai kiểu chỉ định các tập con giai đoạn được sử

dụng. Kiểu INCREASING_ENABLE chỉ định sử dụng các giai đoạn

Alpha tăng và giai đoạn Alpha bằng 1. Kiểu DECREASING_ENABLE

chỉ định sử dụng giai đoạn Alpha giảm và Alpha bằng 0. Kiểu thứ ba là

kết hợp của cả hai kiểu trên, chỉ định sử dụng cả bốn giai đoạn.

Hình 5-3. Một vài dạng sóng cơ sở được tạo với đối tượng Alpha

http://tailieuhay.com 479

Page 480: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Các đặc tả về kiểu của đối tượng Alpha sẽ vô hiệu các thiết lập tham

số khoảng thời gian. Ví dụ, khi kiểu là INCREASING_INABLE, thì các

tham số DecreasingAlphaDuration, DecreasingAlphaRampDuration và

AlphaAtZeroDuration sẽ bị bỏ qua. Mặc dù bất kì một dạng sóng nào

cũng có thể xây dựng được bằng cách cho khoảng thời gian tồn tại của

các giai đoạn không cần thiết bằng 0, tuy nhiên, việc đặc tả chính xác kiểu

sẽ làm tăng hiệu quả của đối tượng Alpha.

Sử dụng các đối tượng Interpolator và Alpha:

Cách thức sử dụng các đối tượng Interpolator và Alpha rất giống

với cách thức sử dụng đối tượng hành vi. Điểm khác biệt lớn nhất so với

cách sử dụng đối tượng hành vi chính là việc gộp cùng với đối tượng

Alpha.

Công thức sử dụng các đối tượng Interpolator và Alpha có thể tóm

tắt như sau:

1. tạo đối tượng đích với các khả năng thích hợp

2. tạo đối tượng Alpha

3. tạo đối tượng Interpolator tham chiếu đến đến đối tượng

Alpha và đối tượng đích

4. thêm các giới hạn cho đối tượng Interpolator

5. thêm đối tượng Interpolator vào đồ thị khung cảnh

Hình 5-4. Công thức sử dụng các đối tượng Interpolator và Alpha

để tạo hoạt ảnh

Ví dụ sử dụng lớp Alpha và RotationInterpolator:

ClockApp.java là một ví dụ sử dụng lớp RotationInterpolator. Khung

cảnh là mặt một chiếc đồng hồ. Chiếc đồng hồ này được điều khiển quay

http://tailieuhay.com 480

Page 481: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

mỗi phút một lần bởi hai đối tượng RotationInterpolator và Alpha.

Chương trình đầy đủ xin xem phần phụ lục, ở đây chúng tôi chỉ trích rút

một phần để tập trung vào vấn đề chính.

Trong chương trình này, đối tượng đích là một đối tượng

TransformGroup. Yêu cầu đối tượng này phải được thiết lập khả năng

ALLOW_TRANSFORM_WRITE. Các đối tượng Interpolator khác

nhau sẽ hoạt động trên các đối tượng đích khác nhau. Ví dụ, đích của đối

tượng ColorInterpolator là một đối tượng Material. Đối tượng

Interpolator thiết lập giá trị của đối tượng đích dựa vào các giá trị của

đối tượng Alpha và các giá trị do chính nó lưu giữ.

Đối tượng Interpolator định nghĩa điểm kết thúc của hoạt ảnh.

Trong trường hợp của RotationInterpolator, đối tượng này xác định góc

quay bắt đầu và kết thúc. Đối tượng Alpha điều khiển hoạt ảnh tương ứng

với thời gian và cách mà Interpolator dịch chuyển từ điểm này đến một

điểm khác bằng đặc tả các giai đoạn của dạng sóng Alpha.

Ứng dụng này sử dụng thiết lập mặc định cho đối tượng

RotationInterpolator với góc bắt đầu là 0 và góc kết thúc là 2Π (một vòng

quay hoàn chỉnh). Trục quay mặc định là trục y. Đối tượng Alpha được

thiết lập ở chế độ quay không dừng (loopCount = -1) với quãng thời gian

là 1 phút (60.000 mili giây). Hai đối tượng này kết hợp với nhau sẽ làm

cho đối tượng trực quan (đối tượng đích) quay một vòng hoàn chỉnh trong

1 phút. Chu trình này được tiếp diễn và lặp lại ngay lập tức. Kết quả là

chiếc đồng hồ dường như quay không ngừng chứ không phải là quay một

vòng rồi bắt đầu lại một vòng khác.

Đoạn mã sau định nghĩa phương thức createSceneGraph trong chương

trình ClockApp.java. Đoạn mã này được đánh dấu các bước tương ứng

với công thức đưa ra trong hình 5-4.

public BranchGroup createSceneGraph() {

http://tailieuhay.com 481

Page 482: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

// Create the root of the branch graph

BranchGroup objRoot = new BranchGroup();

// create target TransformGroup with

Capabilities

TransformGroup objSpin = new

TransformGroup();

objSpin.setCapability(TransformGroup.ALLO

W_TRANSFORM_WRITE);

// create Alpha that continuously rotates

with a period of 1 minute

Alpha alpha = new Alpha (-1, 60000);

// create rotation about y-axis

RotationInterpolator rotInt = new

RotationInterpolator (alpha, objSpin);

rotInt.setSchedulingBounds(new

BoundingSphere());

objRoot.addChild(objSpin);

objSpin.addChild(new Clock());

objRoot.addChild(rotInt);

Background background = new Background();

background.setColor(1.0f, 1.0f, 1.0f);

background.setApplicationBounds(new

BoundingSphere());

objRoot.addChild(background);

http://tailieuhay.com 482

Page 483: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

// Let Java 3D perform optimizations on this

scene graph.

objRoot.compile();

return objRoot;

} // end of CreateSceneGraph method of

ClockApp

Hình 5-5 là một cảnh được tạo ra bằng chương trình ClockApp tại 4:30.

Mặt đồng hồ trông bị nghiêng đi là do cả mặt đấy quay theo trục thẳng

đứng.

Làm trơn dạng sóng Alpha

Ngoài khoảng thời gian của 4 giai đoạn như đã trình bày, người lập

trình còn có thể xác định các sườn thoải cho giai đoạn Alpha tăng và

Alpha giảm. Trong đoạn thoải này, giá trị Alpha thay đổi dần dần. Trong

trường hợp lập trình cho vật thể chuyển động, thì cách này cho phép vật

thể chuyển động chậm dần hoặc nhanh dần trông giống thật hơn.

Vì giá trị của đoạn dốc thoải tác động đến cả phần bắt đầu và kết thúc

của giai đoạn, nên đoạn này lớn nhất chỉ bằng một nửa của cả giai đoạn.

http://tailieuhay.com 483

Page 484: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Hình 5-5. Một cảnh sinh bởi chương trình ClockApp tại 4:30

Hình 5-6 biểu diễn một dạng sóng Alpha được thiết lập cả

Hình 5-6. Làm trơn dạng sóng Alpha

AlphaApp.java (xem phụ lục) là một chương trình ví dụ về tác động

của việc thiết lập IncreasingAlphaRampDuration trên một dạng sóng

Alpha. Sự khác biệt về giá trị sẽ được đánh giá trực quan qua việc quan

sát chuyển động của 3 chiếc ô tô. Cả 3 chiếc này xuất phát tại cùng một

tọa độ x và di chuyển song song với nhau. Chiếc xe trên cùng không có

đoạn giá trị Alpha thoải, chiếc dưới cùng có đoạn thoải với giá trị lớn

nhất (bằng một nửa của giai đoạn Alpha tăng hoặc giảm), còn chiếc ở

http://tailieuhay.com 484

Page 485: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

giữa có đoạn thoải với giá trị bằng một nửa giá trị lớn nhất (tức là bằng ¼

giai đoạn Alpha tăng hoặc giảm). Mỗi xe cần 2 giây để chuyển động qua

khung nhìn.

Time ~ 0.4s Time ~ 0.8s

Time ~ 1.2s Time ~ 1.6s

Hình 5-7. Tác dụng của IncreasingAlphaRampDuration trên một dạng

sóng Alpha

Hình 5-7 biểu diễn 4 cảnh sinh ra từ chương trình AlphaApp. Quan

sát chương trình, chúng ta có thể nhận thấy rằng: ban đầu chiếc xe trên

cùng (không có đoạn thoải) chuyển động nhanh hơn và giữ nguyên tốc

http://tailieuhay.com 485

Page 486: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

độ, hai chiếc phía dưới chuyển động chậm hơn nhưng nhanh dần. Đến

thời điểm 1 giây sau khi khởi động, cả 3 chiếc đều đi được quãng đường

giống nhau. Trong một nửa quãng đường còn lại, vị trí của 3 chiếc xe bị

đảo ngược với chiếc dưới cùng chạy nhanh nhất nhưng chậm dần. Cuối

cùng, khi hết 2 giây, 3 chiếc xe lại bắt kịp nhau.

Alpha API:

Lớp Alpha có vai trò chuyển đổi một giá trị thời gian về một giá trị

Alpha (giá trị nằm trong khoảng từ 0 đến 1, kể cả hai đầu mút). Vì vậy,

có thể nói đối tượng Alpha là một hàm của thời gian, trả về một giá trị

nằm trong đoạn [0, 1]. Ứng dụng thông thường của Alpha là cung cấp giá

trị Alpha cho các hành vi Interpolator .

Các phương thức API của lớp Alpha có thể tùy biến một cách dễ

dàng để sử dụng trong các ứng dụng bằng cách tác động vào các tham số

của chúng. 4 phương thức khởi tạo chủ yếu sau xuất hiện trong hầu hết

các ứng dụng Alpha:

Alpha()

Khởi tạo đối tượng Alpha với mode = INCREASING_ENABLE,

loopCount = -1, increasingAlphaDuration = 1000, tất cả các tham số khác

= 0, ngoại trừ thời gian khởi động: StartTime. StartTime được thiết lập

bằng thời gian khởi động của chương trình.

Alpha(int loopCount, long increasingAlphaDuration)

Khởi tạo đối tượng Alpha với hai tham số loopCount và

increasingAlphaDuration là tùy biến của người dùng, thiết lập chế độ

INCREASING_ENABLE và gán giá trị 0 cho tất cả các tham số còn lại

(ngoại trừ StartTime).

Alpha(int loopCount, long triggerTime,

long phaseDelayDuration, long increasingAlphaDuration,

long increasingAlphaRampDuration,

http://tailieuhay.com 486

Page 487: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

long alphaAtOneDuration)

Khởi tạo đối tượng Alpha ở chế độ INCREASING_ENABLE

Alpha(int loopCount, int mode, long triggerTime,

long phaseDelayDuration, long increasingAlphaDuration, long

increasingAlphaRampDuration,

long alphaAtOneDuration, long decreasingAlphaDuration, long

alphaAtZeroDuration)

Khởi tạo đối tượng Alpha theo các tham số định nghĩa của người dùng.

Lớp Alpha cung cấp rất nhiều các phương thức hữu ích, cho phép

người dùng tuỳ biến các đặc tính của đối tượng Alpha. Chúng tôi liệt kê ở

đây một vài phương thức phổ dụng nhất. Chú ý rằng mỗi phương thức set

(phương thức thiết lập) đều có một phương thức get (không tham số) trả

về một giá trị cùng kiểu với kiểu của tham số có mặt trong phương thức

set tương ứng.

boolean finished()

Kiểm tra xem đối tượng Alpha hiện thời đã kết thúc mọi hoạt động

của nó hay chưa.

void setAlphaAtOneDuration(long alphaAtOneDuration)

Thiết lập thuộc tính alphaAtOneDuration của đối tượng Alpha hiện

thời đến giá trị xác định.

void setAlphaAtZeroDuration(long alphaAtZeroDuration)

Thiết lập giá trị xác định cho thuộc tính alphaAtZeroDuration của đối

tượng Alpha hiện thời.

void setDecreasingAlphaDuration(long decreasingAlphaDuration)

Thiết lập giá trị xác định cho thuộc tính decreasingAlphaDuration của

đối tượng Alpha hiện thời.

void setDecreasingAlphaRampDuration(long

decreasingAlphaRampDuration)

Thiết lập giá trị xác định cho thuộc tính

http://tailieuhay.com 487

Page 488: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

decreasingAlphaRampDuration của đối Alpha tượng hiện thời.

void setIncreasingAlphaDuration(long increasingAlphaDuration)

Thiết lập giá trị xác định cho thuộc tính increasingAlphaDuration của

đối tượng Alpha hiện thời.

void setIncreasingAlphaRampDuration(long

decreasingAlphaRampDuration)

Thiết lập giá trị xác định cho thuộc tính

increasingAlphaRampDuration của đối tượng Alpha hiện thời.

void setLoopCount(int loopCount)

Thiết lập giá trị xác định cho thuộc tính loopCount của đối tượng

Alpha hiện thời.

void setMode(int mode)

Thiết lập chế độ xác định bởi đối số mode cho đối tượng Alpha hiện

thời. mode có thể là INCREASING_ENABLE hoặc

DECREASING_ENABLE, hay là hoặc của hai giá trị.

INCREASING_ENABLE - chỉ định sử dụng giai đoạn 3 và 4

DECREASING_ENABLE - chỉ định sử dụng giai đoạn 1 và 2

void setPhaseDelayDuration(long phaseDelayDuration)

Thiết lập giá trị phaseDelayDuration của đối tượng Alpha hiện thời

bằng giá trị cho trong đối số.

void setStartTime(long startTime)

Thiết lập giá trị startTime của đối tượng Alpha hiện thời bằng giá trị

cho trong đối số. startTime quy định mốc cho mọi tính toán thời gian

tương đối. Giá trị mặc định của startTime là thời điểm khởi động hệ

thống.

void setTriggerTime(long triggerTime)

Thiết lập giá trị triggerTime của đối tượng Alpha hiện thời bằng giá

trị cho trong đối số.

http://tailieuhay.com 488

Page 489: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

float value()

Trả về một giá trị nằm trong đoạn [0, 1] dựa trên thời gian hiện thời và

đối số time-to-Alpha được thiết lập cho đối tượng Alpha đang xét.

float value(long atTime)

Trả về một giá trị nằm trong đoạn [0, 1] dựa trên giá trị atTime và đối

số time-to-Alpha được thiết lập cho đối tượng Alpha đang xét.

Các lớp hành vi Interpolator :

Interpolator là một lớp trừu tượng, kế thừa lớp hành vi Behavior để

cung cấp các phương thức chung cho các lớp con nội suy. Có khoảng hơn

10 lớp con Interpolator cơ bản. Hình 5-8 biểu diễn mối quan hệ của các

lớp Interpolator cơ sở (ô sáng màu) trong Java 3D cùng các gói tiện ích

(ô sẫm màu).

Hình 5-8. Biểu đồ phân cấp lớp đối tượng Interpolator cơ sở trong Java

3D và các tiện ích

Mỗi đối tượng nội suy Interpolator là một đối tượng hành vi

Behavior tùy biến có cơ chế kích hoạt để “đánh thức” mỗi khung ảnh.

Trong phương thức processStimulus, đối tượng Interpolator kiểm tra

giá trị của đối tượng Alpha liên hợp với nó, hiệu chỉnh đối tượng đích

dựa trên các giá trị này rồi xác lập lại cơ chế kích hoạt để “đánh thức”

khung ảnh tiếp theo (trừ phi đối tượng Alpha kết thúc hoạt động). Một

http://tailieuhay.com 489

Page 490: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

vài phương thức này được cung cấp bởi lớp trừu tượng Interpolator , còn

hầu hết các hành vi còn lại được cài đặt trong mỗi lớp Interpolator đơn

lẻ.

Mỗi đối tượng Interpolator chứa 2 giá trị được sử dụng như các

điểm giới hạn cho các hành động được nội suy. Ví dụ, đối tượng nội suy

RotationInterpolator lưu trữ hai góc là giới hạn quay do nó điều khiển.

Với mỗi khung ảnh, đối tượng Interpolator kiểm tra giá trị Alpha của

đối tượng Alpha liên hợp với nó rồi tạo ra các hiệu chỉnh quay thích hợp

cho đối tượng đích TransformGroup của nó. Nếu giá trị Alpha là 0 thì

một trong hai giá trị sẽ được sử dụng; nếu giá trị Alpha là 1, thì giá trị kia

sẽ được sử dụng. Nếu giá trị Alpha nằm trong khoảng từ 0 đến 1, đối

tượng Interpolator sẽ nội suy tuyến tính giữa hai giá trị, dựa trên giá trị

Alpha rồi sử dụng kết quả để điều chỉnh đối tượng đích.

Mô tả chung chung về các đối tượng Interpolator như vậy không

đúng lắm với các lớp SwitchValueInterpolator và PathInterpolator. Đối

tượng SwitchValueInterpolator lựa chọn một nút con trong nhóm các nút

đích Switch, nên trong lớp này, không hề có quá trình nội suy.

Tuy rằng các lớp Interpolator rất giống nhau, chúng cũng mang một

vài chi tiết khác nhau dễ nhận ra. Bảng sau so sánh các đặc điểm khác

nhau của 7 lớp Interpolator cơ bản. Trong các phần sau, chúng ta lần

lượt sẽ đi sâu hơn về 7 lớp này.

lớp Interpolator chức năng kiểu đối tượng đích TrangColorInterpolator thay đổi màu

khuyếch tán của

một đối tượng

Material 5-12

PathInterpolator lớp trừu tượng TransformGroup 5-20PositionInterpolator thay đổi vị trí

của đối tượng

TransformGroup 5-14

RotationInterpolator thay đổi chuyển TransformGroup 5-15

http://tailieuhay.com 490

Page 491: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

động quay

(hướng) của đối

tượngScaleInterpolator thay đổi kích cỡ

của đối tượng

TransformGroup 5-16

SwitchValueInterpolator lựa chọn một

thay đổi (switch)

trong một bộ các

đối tượng

Switch 5-17

TransparencyInterpolator thay đổi mức độ

trong suốt của

đối tượng

TransparencyAttributes 5-19

Bảng 5-1. Tóm tắt các lớp Interpolator cơ bản

Chú ý: PathInterpolator là một lớp trừu tượng, nên không có đối

tượng đích. Tuy nhiên, bất cứ lớp nào thừa kế lớp này đều có đối tượng

đích thuộc kiểu Transformation.

Để hiểu thêm hiệu ứng của các Interpolator này, hãy xem ví dụ

InterpolatorApp.java (chi tiết ở phần phụ lục). Trong chương trình này,

mỗi đối tượng Interpolator được điều khiển bởi một đối tượng Alpha

đơn. Các thay đổi về vị trí, quay, độ lớn, màu sắc, độ trong suốt, và đối

tượng trực quan được tạo ra bởi các đối tượng PositionInterpolator,

RotationInterpolator, ScaleInterpolator, ColorInterpolator,

TransparencyInterpolator, và SwitchValueInterpolator tương ứng.

http://tailieuhay.com 491

Page 492: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Hình 5-9. InterpolatorApp.java

Mã của chương trình Interpolator.java

package Animation;

import java.applet.Applet;

import java.awt.BorderLayout;

import java.awt.Frame;

import com.sun.j3d.utils.applet.MainFrame;

import com.sun.j3d.utils.universe.*;

import com.sun.j3d.utils.geometry.ColorCube;

import javax.media.j3d.*;

http://tailieuhay.com 492

Page 493: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

import javax.vecmath.*;

// InterpolatorApp renders an

public class InterpolatorApp extends Applet {

Shape3D createCar(float xScale, float yScale,

boolean createNormals,

boolean assignColoring) {

Shape3D car = new Shape3D();

QuadArray carGeom = null;

if (createNormals)

carGeom = new QuadArray(16,

GeometryArray.COORDINATES

|

GeometryArray.NORMALS);

else

carGeom = new QuadArray(16,

GeometryArray.COORDINATES);

carGeom.setCoordinate( 0, new

Point3f(xScale*-0.25f, yScale*0.22f, 0.0f));

carGeom.setCoordinate( 1, new

Point3f(xScale* 0.20f, yScale*0.22f, 0.0f));

carGeom.setCoordinate( 2, new

Point3f(xScale* 0.10f, yScale*0.35f, 0.0f));

http://tailieuhay.com 493

Page 494: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

carGeom.setCoordinate( 3, new

Point3f(xScale*-0.20f, yScale*0.35f, 0.0f));

carGeom.setCoordinate( 4, new

Point3f(xScale*-0.50f, yScale*0.10f, 0.0f));

carGeom.setCoordinate( 5, new

Point3f(xScale* 0.50f, yScale*0.10f, 0.0f));

carGeom.setCoordinate( 6, new

Point3f(xScale* 0.45f, yScale*0.20f, 0.0f));

carGeom.setCoordinate( 7, new

Point3f(xScale*-0.48f, yScale*0.20f, 0.0f));

carGeom.setCoordinate( 8, new

Point3f(xScale*-0.26f, yScale*0.00f, 0.0f));

carGeom.setCoordinate( 9, new

Point3f(xScale*-0.18f, yScale*0.00f, 0.0f));

carGeom.setCoordinate(10, new

Point3f(xScale*-0.16f, yScale*0.12f, 0.0f));

carGeom.setCoordinate(11, new

Point3f(xScale*-0.28f, yScale*0.12f, 0.0f));

carGeom.setCoordinate(12, new

Point3f(xScale* 0.25f, yScale*0.00f, 0.0f));

carGeom.setCoordinate(13, new

Point3f(xScale* 0.33f, yScale*0.00f, 0.0f));

carGeom.setCoordinate(14, new

Point3f(xScale* 0.35f, yScale*0.12f, 0.0f));

carGeom.setCoordinate(15, new

Point3f(xScale* 0.23f, yScale*0.12f, 0.0f));

if (createNormals){

int i;

http://tailieuhay.com 494

Page 495: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Vector3f normal = new Vector3f(0.6f,

0.6f, 0.8f);

for(i = 0; i < 8; i++)

carGeom.setNormal(i, normal);

normal.set(new Vector3f(0.5f, 0.5f,

0.5f));

for(i = 8; i <16; i++)

carGeom.setNormal(i, normal);

}

if (assignColoring){

ColoringAttributes colorAttrib =

new ColoringAttributes(0.0f,

0.0f, 1.0f, ColoringAttributes.NICEST);

Appearance carAppear = new

Appearance();

carAppear.setColoringAttributes(color

Attrib);

car.setAppearance(carAppear);

}

car.setGeometry(carGeom);

return car;

}

public BranchGroup createSceneGraph() {

// Create the root of the branch graph

BranchGroup objRoot = new BranchGroup();

Transform3D t3d = new Transform3D();

http://tailieuhay.com 495

Page 496: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

BoundingSphere bounds = new

BoundingSphere();

// create target TransformGroup with

Capabilities

TransformGroup objMove = new

TransformGroup();

objMove.setCapability(TransformGroup.ALLO

W_TRANSFORM_WRITE);

// create target TransformGroup with

Capabilities

TransformGroup objRotate = new

TransformGroup();

objRotate.setCapability(TransformGroup.AL

LOW_TRANSFORM_WRITE);

// create target TransformGroup with

Capabilities

TransformGroup objScale = new

TransformGroup();

objScale.setCapability(TransformGroup.ALL

OW_TRANSFORM_WRITE);

// create target Material with

Capabilities

Material objColor = new Material();

objColor.setCapability(Material.ALLOW_COM

PONENT_WRITE);

http://tailieuhay.com 496

Page 497: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

// create target Transparency with

Capabilities

TransparencyAttributes objTransp = new

TransparencyAttributes();

objTransp.setCapability(TransparencyAttri

butes.ALLOW_VALUE_WRITE);

objTransp.setTransparencyMode(Transparenc

yAttributes.BLENDED);

// create target Switch with Capabilities

Switch objSwitch = new Switch();

objSwitch.setCapability(Switch.ALLOW_SWIT

CH_WRITE);

// create Alpha

Alpha alpha = new Alpha (-1,

Alpha.INCREASING

_ENABLE + Alpha.DECREASING_ENABLE,

0, 0, 2000, 0,

1000, 2000, 0, 1000);

// create position interpolator

PositionInterpolator posInt = new

PositionInterpolator (alpha, objMove);

posInt.setSchedulingBounds(bounds);

posInt.setStartPosition(-1.0f);

// create rotation interpolator

http://tailieuhay.com 497

Page 498: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

RotationInterpolator rotInt = new

RotationInterpolator (alpha, objRotate);

rotInt.setSchedulingBounds(bounds);

// create scale interpolator

ScaleInterpolator scaInt = new

ScaleInterpolator (alpha, objScale);

scaInt.setSchedulingBounds(bounds);

// create color interpolator

ColorInterpolator colInt = new

ColorInterpolator (alpha, objColor);

colInt.setStartColor(new Color3f(1.0f,

0.0f, 0.0f));

colInt.setEndColor(new Color3f(0.0f,

0.0f, 1.0f));

colInt.setSchedulingBounds(bounds);

// create transparency interpolator

TransparencyInterpolator traInt = new

TransparencyInterpolator (alpha, objTransp);

traInt.setSchedulingBounds(bounds);

// create switch value interpolator

SwitchValueInterpolator swiInt = new

SwitchValueInterpolator (alpha, objSwitch);

swiInt.setSchedulingBounds(bounds);

http://tailieuhay.com 498

Page 499: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

t3d.setTranslation(new Vector3f(0.0f,

0.8f, 0.0f));

TransformGroup objMovePos = new

TransformGroup(t3d);

objRoot.addChild(objMovePos);

objMovePos.addChild(objMove);

objMove.addChild(createCar(0.4f, 0.4f,

false, true));

objRoot.addChild(posInt);

t3d.setTranslation(new Vector3f(0.0f,

0.5f, 0.0f));

TransformGroup objRotPos = new

TransformGroup(t3d);

objRoot.addChild(objRotPos);

objRotPos.addChild(objRotate);

objRotate.addChild(createCar(0.4f, 0.4f,

false, true));

objRoot.addChild(rotInt);

t3d.setTranslation(new Vector3f(0.0f,

0.2f, 0.0f));

TransformGroup objScalePos = new

TransformGroup(t3d);

objRoot.addChild(objScalePos);

objScalePos.addChild(objScale);

objScale.addChild(createCar(0.4f, 0.4f,

false, true));

objRoot.addChild(scaInt);

http://tailieuhay.com 499

Page 500: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

t3d.setTranslation(new Vector3f(0.0f,

-0.2f, 0.0f));

TransformGroup objColorPos = new

TransformGroup(t3d);

objRoot.addChild(objColorPos);

Shape3D colorCar = createCar(0.4f, 0.4f,

true, false);

Appearance materialAppear = new

Appearance();

materialAppear.setMaterial(objColor);

colorCar.setAppearance(materialAppear);

objColorPos.addChild(colorCar);

objRoot.addChild(colInt);

t3d.setTranslation(new Vector3f(0.0f,

-0.5f, 0.0f));

TransformGroup objTranspPos = new

TransformGroup(t3d);

objRoot.addChild(objTranspPos);

Shape3D transpCar = createCar(0.4f, 0.4f,

false, true);

Appearance transpAppear =

transpCar.getAppearance();

transpAppear.setTransparencyAttributes(ob

jTransp);

objTranspPos.addChild(transpCar);

objRoot.addChild(traInt);

http://tailieuhay.com 500

Page 501: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

t3d.setTranslation(new Vector3f(0.0f,

-0.8f, 0.0f));

TransformGroup objSwitchPos = new

TransformGroup(t3d);

objRoot.addChild(objSwitchPos);

objSwitch.addChild(createCar(0.4f, 0.4f,

false, true));;

objSwitch.addChild(new ColorCube(0.1f));

objSwitchPos.addChild(objSwitch);

objRoot.addChild(swiInt);

swiInt.setLastChildIndex(2);// since

switch made after interpolator

DirectionalLight lightD1 = new

DirectionalLight();

// lightD1.setDirection(new Vector3f(-0.7f,-

0.7f,0.0f));

lightD1.setInfluencingBounds(bounds);

objRoot.addChild(lightD1);

Background background = new Background();

background.setColor(1.0f, 1.0f, 1.0f);

background.setApplicationBounds(new

BoundingSphere());

objRoot.addChild(background);

// Let Java 3D perform optimizations on this

scene graph.

objRoot.compile();

http://tailieuhay.com 501

Page 502: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

return objRoot;

} // end of CreateSceneGraph method of

InterpolatorApp

// Create a simple scene and attach it to the

virtual universe

public InterpolatorApp() {

setLayout(new BorderLayout());

Canvas3D canvas3D = new Canvas3D(null);

add("Center", canvas3D);

BranchGroup scene = createSceneGraph();

// SimpleUniverse is a Convenience

Utility class

SimpleUniverse simpleU = new

SimpleUniverse(canvas3D);

// This will move the ViewPlatform back a bit

so the

// objects in the scene can be viewed.

simpleU.getViewingPlatform().setNominalVi

ewingTransform();

simpleU.addBranchGraph(scene);

} // end of InterpolatorApp (constructor)

http://tailieuhay.com 502

Page 503: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

// The following allows this to be run as an

application

// as well as an applet

public static void main(String[] args) {

System.out.print("InterpolatorApp.java

\n- a demonstration of using Interpolator ");

System.out.println("objects to provide

animation in a Java 3D scene.");

System.out.println("This is a simple

example progam from The Java 3D API Tutorial.");

System.out.println("The Java 3D Tutorial

is available on the web at:");

System.out.println("http://java.sun.com/p

roducts/java-media/3D/collateral");

Frame frame = new MainFrame(new

InterpolatorApp(), 256, 256);

} // end of main (method of InterpolatorApp)

} // end of class InterpolatorApp

Những nhầm lẫn thường gặp khi lập trình với Interpolator

Các đối tượng Interpolator là dẫn suất có quan hệ rất gần gũi với

các đối tượng hành vi. Vì vậy, việc sử dụng các đối tượng Interpolator

cũng sẽ phải đối mặt với các lỗi thường gặp như khi sử dụng các đối

tượng hành vi. Thêm vào đó, cũng có các bẫy lỗi khác, chung cho các

Interpolator và các bẫy lỗi riêng cho mỗi Interpolator .

Một nhầm lẫn thường gặp gây ra bởi việc không nhận thấy rằng các

đối tượng Interpolator thay đổi thường xuyên giá trị các đối tượng đích

http://tailieuhay.com 503

Page 504: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

của chúng. Người lập trình có thể nghĩ rằng đối tượng đích

TransformGroup của đối tượng RotationInterpolator có thể được sử dụng

để tịnh tiến đối tượng đó ngoài hoạt động quay mà đối tượng

RotationInterpolator cung cấp. Điều này là hoàn toàn sai. Tập các biến

đổi của đối tượng đích TransformGroup được ghi lại mỗi lần tại khung

ảnh mà đối tượng Alpha hoạt động. Điều này cũng có nghĩa rằng: hai đối

tượng Interpolator không thể có cùng một đối tượng đích.

Một lỗi khác cũng hay xảy ra khi người lập trình quên không thiết lập

các khả năng thích hợp cho đối tượng đích. Kết quả là gây ra lỗi runtime

error.

Core Interpolator API:

Interpolator là một lớp trừu tượng, nó chỉ được sử dụng khi cần tạo

một lớp con mới. Lớp Interpolator chỉ cung cấp duy nhất một hàm cho

người sử dụng các lớp con của nó:

void setAlpha(Alpha Alpha)

Thiết lập đối tượng Alpha cho đối tượng Interpolator hiện hành .

ColorInterpolator

Đối tượng ColorInterpolator có đối tượng đích thuộc kiểu Material.

Interpolator này cho phép thay đổi thành phần màu khuyếch tán của vật

liệu đích. Khả năng này vừa là điểm mạnh lại cũng là điểm hạn chế của

ColorInterpolator. Điểm mạnh thể hiện ở khả năng cho phép nhiều hơn

một đối tượng trực quan dùng chung một đối tượng vật liệu Material. Vì

vậy, một đối tượng ColorInterpolator cùng với một đối tượng đích

Material có thể tác động tới nhiều đối tượng trực quan khác nhau. Hạn

chế ở chỗ các đối tượng trực quan với chất liệu Material NodeComponent

chỉ có thể nhìn thấy khi được chiếu sáng.

Sự nhầm lẫn thường xảy ra ở đây chính là do sự phức tạp trong việc

tạo độ bóng cho hình ảnh. Việc sử dụng ánh sáng trong đồ họa là khá rắc

http://tailieuhay.com 504

Page 505: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

rối, vì vậy nó được trình bày chi tiết trong một chương riêng, chương 6.

Màu sắc của thực thể trực quan là sự kết hợp của 3 thành phần: phản xạ,

khuyếch tán và màu xung quanh. ColorInterpolator chỉ thay đổi một trong

3 thành phần, đó chính là thành phần khuyếch tán.

Một lỗi khác cũng hay xảy ra khi gắn đối tượng đích Material cho đối

tượng Shape3D. Hình 5-10 biểu diễn một phần biểu đồ đồ thị khung cảnh

của đối tượng ColorInterpolator với đối tượng đích Material

NodeComponent.

Hình 5-10. Một phần biểu đồ đồ thị khung cảnh của đối tượng

ColorInterpolator với đối tượng đích Material NodeComponent

Lớp ColorInterpolator có dạng của phương thức get khác với các

Interpolator khác. Phương thức get của ColorInterpolator không phải là

phương thức không tham số.

ColorInterpolator là một hành vi hiệu chỉnh màu khuyếch tán của đối

tượng material đích bằng cách nội suy tuyến tính giữa một cặp màu cho

trước, sử dụng giá trị sinh ra bởi đối tượng Alpha xác định.

Lớp ColorInterpolator có các phương thức khởi tạo sau:

ColorInterpolator(Alpha Alpha, Material target)

Khởi tạo đối tượng Interpolator màu thường với đối tượng đích cho

trước. Giá trị màu nội suy nằm trong khoảng từ màu đen tới màu trắng.

http://tailieuhay.com 505

Page 506: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

ColorInterpolator(Alpha Alpha, Material target,

Color3f startColor, Color3f endColor)

Khởi tạo đối tượng Interpolator màu với đối tượng đích, màu bắt

đầu, màu kết thúc cho trước.

Các phương thức thường dùng khác:

void setEndColor(Color3f color)

Thiết lập thuộc tính endColor cho đối tượng Interpolator hiện thời.

Phương thức get tương ứng: void getEndColor(Color3f color)

void setStartColor(Color3f color)

Thiết lập thuộc tính startColor cho đối tượng Interpolator hiện thời.

Phương thức get tương ứng: void getStartColor(Color3f color)

void setTarget(Material target)

Thiết lập đối tượng thành phần chất liệu (material) đích cho

Interpolator hiện thời

Phương thức get tương ứng: Material getTarget()

PositionInterpolator

Đối tượng PositionInterpolator thay đổi vị trí của đối tượng trực quan

theo một trục tọa độ. Hai điểm dừng sử dụng cho phép nội suy được cho

dưới dạng hai giá trị thực dấu phảy động cùng trục tọa độ tịnh tiến. Trục

tịnh tiến mặc định là trục x.

Các phương thức khởi tạo:

PositionInterpolator(Alpha Alpha, TransformGroup target)

Khởi tạo đối tượng nội suy vị trí Interpolator thường với đối tượng

đích cho trước, trục tịnh tiến mặc định là x, vị trí bắt đầu startPosition là

0.0f, vị trí kết thúc endPosition là 1.0f.

PositionInterpolator(Alpha Alpha, TransformGroup target,

http://tailieuhay.com 506

Page 507: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Transform3D axisOfTranslation,

float startPosion, float endPosition)

Khởi tạo đối tượng Interpolator vị trí biến đổi thành phần tịnh tiến

của đối tượng TransformGroup đích theo một trục tịnh tiến nhất định.

Các phương thức khác:

void setAxisOfTranslation(Transform3D axisOfTranslation)

Thiết lập trục tịnh tiến cho đối tượng Interpolator hiện thời.

void setEndPosition(float position)

Thiết lập vị trí kết thúc endPosition cho đối tượng Interpolator hiện

thời.

void setStartPosition(float position)

Thiết lập vị trí bắt đầu startPosition cho đối tượng Interpolator hiện

thời.

RotationInterpolator

Đối tượng RotationInterpolator biến đổi hướng quay của đối tượng

trực quan xung quanh một trục. Hai điểm sử dụng trong phép nội suy

được cho dưới dạng hai giá trị góc dấu phảy động và trục quay. Giá trị nội

suy sẽ được sử dụng để sinh chuyển động quay quanh trục quay. Trục

quay mặc định là trục y dương.

Các phương thức khởi tạo:

RotationInterpolator(Alpha Alpha, TransformGroup target)

Khởi tạo đối tượng nội suy quay Interpolator thường với đối tượng

đích cho trước, sử dụng trục quay mặc định (+Y), góc nhỏ nhất là 0.0f,

góc lớn nhất là 2*pi radian.

RotationInterpolator(Alpha Alpha, TransformGroup target,

Transform3D axisOfRotation,

float minimumAngle, float maximumAngle)

Khởi tạo đối tượng Interpolator biến đổi thành phần quay của một

đối tượng transform đích.

http://tailieuhay.com 507

Page 508: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Các phương thức khác:

void setAxisOfRotation(Transform3D axisOfRotation)

Thiết lập trục quay cho đối tượng Interpolator hiện thời.

void setMaximumAngle(float angle)

Thiết lập giá trị góc lớn nhất maximumAngle theo radian cho đối

tượng Interpolator hiện thời.

void setMinimumAngle(float angle)

Thiết lập giá trị góc nhỏ nhất minimumAngle theo radian cho đối

tượng Interpolator hiện thời.

void setTarget(TransformGroup target)

Thiết lập nút TransformGroup đích cho đối tượng Interpolator hiện

thời.

ScaleInterpolator

Lớp ScaleInterpolator định nghĩa một hành vi biến đổi thành phần tỉ

lệ kích thước (giữ nguyên các tính chất khác) của đối tượng

TransformGroup đích bằng cách nội suy tuyến tính giữa một cặp giá trị tỉ

lệ cho trước (sử dụng giá trị của đối tượng Alpha xác định). Giá trị tỉ lệ

nội suy được sử dụng để sinh ra biến đổi tỉ lệ trong hệ tọa độ địa phương

của đối tượng Interpolator hiện thời.

Các phương thức khởi tạo:

ScaleInterpolator(Alpha Alpha, TransformGroup target)

Khởi tạo đối tượng nội suy tỉ lệ biến đổi nút TransformGroup đích

giữa hai giá trị Alpha xác định, sử dụng đối tượng Alpha và một ma trận

đồng nhất cho trước, với tỉ lệ phóng bé nhất minimum scale = 0.1f và tỉ lệ

phóng lớn nhất maximum scale = 1.0f.

ScaleInterpolator(Alpha Alpha, TransformGroup target,

Transform3D axisOfScale,

float minimumScale, float maximumScale)

http://tailieuhay.com 508

Page 509: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Khởi tạo đối tượng scaleInterpolator biến đổi thành phần tỉ lệ nút

TransformGroup đích giữa hai giá trị tỉ lệ (minimumScale và

MaximumScale).

Các phương thức khác:

void setAxisOfScale(Transform3D axisOfScale)

Thiết lập biến đổi AxisOfScale cho đối tượng nội suy Interpolator

hiện thời.

void setMaximumScale(float scale)

Thiết lập tỉ lệ phóng lớn nhất maximumScale cho đối tượng

Interpolator hiện thời.

void setMinimumScale(float scale)

Thiết lập tỉ lệ phóng nhỏ nhất minimumScale cho đối tượng

Interpolator hiện thời.

void setTarget(TransformGroup target)

Thiết lập đối tượng TransformGroup cho đối tượng Interpolator

hiện thời.

SwitchValueInterpolator

Đối tượng SwitchValueInterpolator không nội suy giữa các giá trị như

các đối tượng Interpolator khác. Nó chỉ lựa chọn một trong các con của

đối tượng Switch. Giá trị ngưỡng để chuyển tới một con khác được xác

định bằng cách chia đoạn [0.0, 1.0] cho số con mà đối tượng Switch có.

Chú ý rằng, đối tượng Interpolator không tự động cập nhật khi số

con của đối tượng Switch thay đổi. Các giá trị chuyển đổi (switching

value) được xác định ngay khi tạo đối tượng SwitchValueInterpolator.

Nên nếu ban đầu đối tượng Switch không có con, hoặc khi số con của nó

thay đổi sau khi đối tượng Interpolator đã được tạo thì số các con trong

đối tượng Interpolator phải được cập nhật. Điểm thuận lợi khi sử dụng

đối tượng này là người lập trình có thể xác định một tập con các chỉ mục

http://tailieuhay.com 509

Page 510: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

để đối tượng Interpolator sử dụng. Tập con này bị giới hạn bởi tập các

chỉ mục tuần tự.

Các phương thức khởi tạo:

SwitchValueInterpolator(Alpha Alpha, Switch target)

Khởi tạo đối tượng hành vi SwitchValueInterpolator biến đổi chỉ mục

con của nút Switch đích trong khoảng từ 0 đến n-1, trong đó, n là số con

của nút Switch đích.

SwitchValueInterpolator(Alpha Alpha, Switch target,

int firstChildIndex, int lastChildIndex)

Khởi tạo đối tượng hành vi SwitchValueInterpolator biến đổi chỉ mục

con của nút Switch đích giữa hai giá trị firstChildIndex và lastChildIndex

cho trước.

Các phương thức khác:

void setFirstChildIndex(int firstIndex)

Thiết lập chỉ mục con đầu tiên firstChildIndex của đối tượng

Interpolator hiện thời.

void setLastChildIndex(int lastIndex)

Thiết lập chỉ mục con cuối lastChildIndex của đối tượng Interpolator

hiện thời.

void setTarget(Switch target)

Thiết lập đối tượng Switch đích cho đối tượng Interpolator hiện

thời.

Trong các tham số của phương thức khởi tạo SwitchValueInterpolator

có đối tượng Switch. Vậy Switch là gì?

Switch

Lớp Switch kế thừa từ lớp Group và là cha của 0 hay nhiều nhánh con

đồ thị khung cảnh. Đối tượng Switch lựa chọn một trong các con của nó

để biểu diễn. Nó định nghĩa một giá trị lựa chọn (switch value) có thể

http://tailieuhay.com 510

Page 511: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

chọn 1 hoặc chọn 0 hay nhiều con của nó và nhờ sử dụng một mặt nạ để

xác định xem con nào được biểu diễn. Đối tượng Switch có thể sử dụng

độc lập không cần đối tượng Interpolator hay LOD .

Các phương thức khởi tạo:

Switch()

Khởi tạo một nút Switch với các tham số mặc định.

Switch(int whichChild)

Khởi tạo và gán giá trị ban đầu cho một nút Switch sử dụng chỉ mục

lựa chọn con thích hợp.

CHILD_ALL - chỉ thị tất cả các con được biểu diễn

CHILD_MASK - sử dụng mặt nạ childMask (kiểu BitSet) để lựa

chọn con thích hợp

CHILD_NONE - không có con nào được biểu diễn

Switch(int whichChild, java.util.BitSet childMask)

Khởi tạo và gán giá trị đầu cho một nút Switch sử dụng chỉ mục lựa

chọn và mặt nạ cho trước.

Các phương thức khác:

void setChildMask(java.util.BitSet childMask)

Thiết lập mặt nạ lựa chọn con.

void setWhichChild(int child)

Thiết lập chỉ mục lựa chọn con xác định con nào được biểu diễn.

Khả năng có thể thiết lập cho Switch:

ALLOW_SWITCH_READ | WRITE

Chỉ định rằng nút Switch này cho phép đọc lựa chọn nút con, các giá

trị mặt nạ và các con hiện thời của nó.

TransparencyInterpolator

Lớp TransparencyInterpolator định nghĩa đối tượng hành vi biến đổi

mức độ trong suốt của đối tượng đích thuộc lớp TransparencyAttributes

http://tailieuhay.com 511

Page 512: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

bằng cách nội suy tuyến tính giữa một cặp giá trị độ trong suốt cho trước

(sử dụng giá trị sinh bởi đối tượng Alpha cho trước). Nhiều hơn một đối

tượng trực quan có thể chia sẻ một đối tượng TransparencyAttributes, vì

vậy một đối tượng TransparencyAttributes có khả năng tác động cùng lúc

đến nhiều đối tượng trực quan khác nhau. Chú ý rằng các chế độ trong

suốt khác nhau có thể ảnh hưởng đến chất lượng biểu diễn và sự hiện diện

của các đối tượng trực quan.

Các phương thức khởi tạo:

TransparencyInterpolator(Alpha Alpha,

TransparencyAttributes target)

Khởi tạo đối tượng nội suy độ trong suốt với đối tượng đích cho

trước, độ trong suốt tối thiểu là 0.0f và tối đa là 1.0f.

TransparencyInterpolator(Alpha Alpha,

TransparencyAttributes target,

float minimumTransparency,

float maximumTransparency)

Khởi tạo đối tượng nội suy độ trong suốt biến đổi độ trong suốt chất

liệu của đối tượng đích giữa hai giá trị minimumTransparency và

maximumTransparency.

Các phương thức khác:

void setMaximumTransparency(float transparency)

Thiết lập giá trị maximumTransparency cho đối tượng Interpolator

hiện thời.

void setMinimumTransparency(float transparency)

Thiết lập giá trị minimumTransparency cho đối tượng Interpolator

hiện thời.

void setTarget(TransparencyAttributes target)

Thiết lập đối tượng đích TransparencyAttributes cho đối tượng

Interpolator hiện thời.

http://tailieuhay.com 512

Page 513: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Các lớp đối tượng nội suy đường:

Path Interpolator (nội suy đường) khác với các lớp nội suy khác ở

chỗ, nó có thể chứa hai hay nhiều hơn hai giá trị để nội suy. Path

Interpolator cung cấp các khả năng nội suy vị trí (Position

Interpolation), nội suy quay (Rotation Interpolation); vừa nội suy vị trí,

vừa nội suy quay; hoặc vừa nội suy vị trí, nội suy quay và nội suy tỉ lệ

(Scale Interpolation). Đích của đối tượng nội suy là một đối tượng

TransformGroup, đối tượng này thay đổi vị trí, hướng, và tỉ lệ thích hợp

cho các đối tượng con của nó.

Một đối tượng Path Interpolator chứa một tập các giá trị, hay các

điểm mút, được sử dụng theo từng cặp để nội suy. Giá trị Alpha có vai

trò xác định giá trị hai điểm nào sẽ được sử dụng. Giá trị các điểm này

nằm trong khoảng từ 0.0 tới 1.0, bao gồm cả hai đầu mút, tương ứng với

khoảng giá trị của đối tượng Alpha. Điểm mút đầu tiên phải có giá trị là

0.0, còn điểm mút cuối cùng phải có giá trị là 1.0. Các mút còn lại được

lưu trữ theo trật tự giá trị tăng dần trong đối tượng nội suy đường.

Các giá trị của một điểm mút là tương ứng với các giá trị tham số biến

(ví dụ như vị trí hay góc quay) được sử dụng trong phép nội suy.Với mỗi

điểm mút thì có một giá trị tham số xác định làm đại diện. Điểm mút có

giá trị lớn nhất bằng hoặc nhỏ hơn giá trị Alpha và giá trị của điểm mút

tiếp theo sẽ được sử dụng. Các điểm mút được xác định theo một trật tự,

theo đó, khi giá trị Alpha thay đổi, các điểm mút sẽ được sử dụng theo

từng cặp kề nhau.

Phía bên trái của hình 5-11 biểu diễn các giá trị điểm mút cho một đối

tượng Path Interpolator nội suy vị trí. Với mục đích minh họa, chúng tôi

chỉ xét vị trí trong không gian 2 chiều. Phần giữa của hình ánh xạ vị trí

của đối tượng trực quan với các giá trị Alpha từ 0.0 tới 1.0. Phía bên phải

là các giá trị điểm mút được sử dụng tương ứng với các giá trị Alpha khác

http://tailieuhay.com 513

Page 514: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

nhau của ví dụ này. Kết hợp các giá trị điểm mút và tham số Alpha sẽ xác

định hoạt ảnh.

Hình 5-11. Quan hệ giữa giá trị các điểm mút và giá trị Alpha cho vị

trí trong không gian 2 chiều

Ví dụ sử dụng PathInterpolator

Sử dụng đối tượng nội suy đường tuân theo công thức sử dụng các đối

tượng nội suy khác. Sự khác biệt là ở số lượng biến được sử dụng để khởi

tạo đối tượng nội suy đường. Công thức sử dụng có thể tóm tắt trong hình

sau:

1. tạo đối tượng đích với khả năng thích hợp

2. tạo đối tượng Alpha

3. tạo các mảng điểm mút và các giá trị khác

4. tạo đối tượng nội suy đường tham chiếu đến đối tượng Alpha, đối

tượng đích, và mảng của các giá trị thiết lập

5. thêm danh giới cho đối tượng nội suy

6. thêm đối tượng nội suy đường vào đồ thị khung cảnh

Hình 5-12. Công thức sử dụng đối tượng nội suy đường

Chương trình RotPosPathApp.java sử dụng đối tượng

RotPosPathInterpolator để tạo hoạt ảnh cho một khối hộp ColorCube qua

một tập các giá trị vị trí và quay. Đối tượng RotPosPathInterpolator chứa

tập các giá trị quay (mảng Quat4f), vị trí (mảng Point3f), và các giá trị

điểm mút (mảng giá trị thực). Chi tiết của ví dụ này xin xem thêm phần

phụ lục.

http://tailieuhay.com 514

Page 515: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

public BranchGroup createSceneGraph() {

// Create the root of the branch graph

BranchGroup objRoot = new BranchGroup();

Alpha alpha = new Alpha(-1, 10000);

TransformGroup target = new

TransformGroup();

Transform3D axisOfRotPos = new

Transform3D();

float[] knots = {0.0f, 0.1f, 0.2f, 0.3f,

0.4f, 0.6f, 0.8f, 0.9f, 1.0f};

Quat4f[] quats = new Quat4f[9];

Point3f[] positions = new Point3f[9];

target.setCapability(TransformGroup.ALLOW

_TRANSFORM_WRITE);

AxisAngle4f axis = new

AxisAngle4f(1.0f,0.0f,0.0f,0.0f);

axisOfRotPos.set(axis);

quats[0] = new Quat4f(0.0f, 1.0f, 1.0f,

0.0f);

quats[1] = new Quat4f(1.0f, 0.0f, 0.0f,

0.0f);

quats[2] = new Quat4f(0.0f, 1.0f, 0.0f,

0.0f);

http://tailieuhay.com 515

Page 516: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

quats[3] = new Quat4f(0.0f, 1.0f, 1.0f,

0.0f);

quats[4] = new Quat4f(0.0f, 0.0f, 1.0f,

0.0f);

quats[5] = new Quat4f(0.0f, 1.0f, 1.0f,

0.0f);

quats[6] = new Quat4f(1.0f, 1.0f, 0.0f,

0.0f);

quats[7] = new Quat4f(1.0f, 0.0f, 0.0f,

0.0f);

quats[8] = quats[0];

positions[0]= new Point3f( 0.0f, 0.0f,

-1.0f);

positions[1]= new Point3f( 1.0f, -1.0f,

-2.0f);

positions[2]= new Point3f( -1.0f, 1.0f,

-3.0f);

positions[3]= new Point3f( 2.0f, 0.0f,

-4.0f);

positions[4]= new Point3f( -2.0f, -1.0f,

-5.0f);

positions[5]= new Point3f( 3.0f, 1.0f,

-6.0f);

positions[6]= new Point3f( -3.0f, 0.0f,

-7.0f);

positions[7]= new Point3f( 2.0f, -1.0f,

-4.0f);

positions[8]= positions[0];

http://tailieuhay.com 516

Page 517: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

RotPosPathInterpolator rotPosPath = new

RotPosPathInterpolator(

alpha, target, axisOfRotPos,

knots, quats, positions);

rotPosPath.setSchedulingBounds(new

BoundingSphere());

objRoot.addChild(target);

objRoot.addChild(rotPosPath);

target.addChild(new ColorCube(0.4));

Background background = new Background();

background.setColor(1.0f, 1.0f, 1.0f);

background.setApplicationBounds(new

BoundingSphere());

objRoot.addChild(background);

PointArray point_geom = new PointArray(9,

GeometryArray.COORDINATES);

point_geom.setCoordinates(0, positions);

Appearance points_appear = new

Appearance();

ColoringAttributes points_coloring = new

ColoringAttributes();

points_coloring.setColor(1.0f, 0.0f,

0.0f);

http://tailieuhay.com 517

Page 518: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

points_appear.setColoringAttributes(point

s_coloring);

PointAttributes points_points = new

PointAttributes(4.0f, true);

points_appear.setPointAttributes(points_p

oints);

Shape3D points = new Shape3D(point_geom,

points_appear);

objRoot.addChild(points);

objRoot.compile();

return objRoot;

} // end of CreateSceneGraph method of

RotPosPathApp

Đoạn mã trên được trích không toàn vẹn từ phương thức

createSceneGraph trong chương trình RotPosPathApp.java để bạn đọc có

hình dung sơ qua về cách sử dụng một đối tượng nội suy đường:

RotPosPathInterpolator. Các bước thực hiện đã được đánh số từ 1-6 tương

ứng với các bước trong công thức.

Hình 5-13 là một cảnh trong chương trình RotPosPathApp, với các

điểm màu đỏ biểu diễn vị trí của 9 điểm mút. Điểm đầu tiên được dùng 2

lần, nên trong hình, chúng ta chỉ thấy có 8 điểm.

http://tailieuhay.com 518

Page 519: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Hình 5-13. Một cảnh trong chương trình RotPosPathApp

Khi chương trình RotPosPathApp được thực hiện, khối hộp

ColorCube di chuyển từ vị trí điểm mút này đến vị trí của điểm mút khác,

đồng thời tự quay để đến được các điểm mút khác nhau. Giống như tất cả

các đối tượng nội suy khác, hoạt ảnh kết quả phụ thuộc vào sự kết hợp

giữa các giá trị đối tượng nội suy với các tham số Alpha được sử dụng.

Như đã nói bên trên, lớp PathInterpolator có rất nhiều các lớp con

khác nhau. Ngoài các lớp con trong hạt nhân của Java 3D, còn có một cặp

các lớp liên quan trong gói tiện ích. Lớp TCBPathSplineInterpolator là

một lớp tương tự với lớp PathInterpolator. Lớp này có một lớp con nằm

trong gói tiện ích (tham khảo hình 5-8 để hình dung được quan hệ giữa

các lớp nội suy).

Trong chương trình RotPosPathApp, hoạt ảnh xuất hiện không tự

nhiên chủ yếu là do sự kết hợp vị trí các điểm mút được chọn. Khi khối

hộp ColorCube di chuyển đến mỗi vị trí điểm mút xác định, thì ngay lập

tức chuyển động của nó thay đổi để đến được điểm mút tiếp theo. Di

chuyển như vậy không tự nhiên do trong thế giới thực, chuyển động của

tất cả các vật đều có tính ì nhất định.

http://tailieuhay.com 519

Page 520: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

TCBPathSplineInterpolator là một tiện ích cung cấp các hành vi và

chức năng tương tự lớp PathInterpolator, nhưng làm trơn đường đi của

đối tượng thành một đường cong dựa trên vị trí các điểm mút. Đường

cong này bắt chước chuyển động của đối tượng trong thế giới thực. Trong

chuyển động này, đối tượng trực quan có thể không đi qua toàn bộ hoặc

không hề đi qua bất cứ điểm mút nào. Chương trình ví dụ,

SplineAnim.java, bạn đọc có thể tìm trong đĩa chương trình kèm theo.

PathInterpolator

PathInterpolator là một lớp trừu tượng cung cấp giao diện và chức

năng cơ bản cho các lớp con của nó. Các đối tượng PathInterpolator lưu

trữ các giá trị điểm mút và tính toán chỉ mục của các giá trị này để sử

dụng dựa trên giá trị Alpha và thời gian hiện thời

(currentInterpolationValue). Tham số currentInterpolationValue được tính

toán bằng cách nội suy tuyến tính trong chuỗi các điểm mút đã được định

nghĩa trước (sử dụng giá trị sinh bởi đối tượng Alpha xác định). Điểm

mút đầu tiên phải có giá trị là 0.0 và điểm mút cuối cùng phải có giá trị là

1.0. Điểm mút trung gian với chỉ mục k phải có giá trị lớn hơn giá trị của

bất cứ điểm mút nào có chỉ mục nhỏ hơn k.

Một số phương thức cung cấp bởi lớp PathInterpolator:

int getArrayLengths()

Trả về độ dài của mảng các điểm mút

void setKnot(int index, float knot)

Thiết lập điểm mút tại chỉ mục xác định bởi index cho đối tượng

Interpolator hiện thời.

void setKnots(float [] knots)

Thiết lập (thay thế) tất cả các điểm mút cho đối tượng Interpolator

hiện thời.

http://tailieuhay.com 520

Page 521: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

RotPosPathInterpolator

RotPosPathInterpolator là một lớp đối tượng hành vi, biến đổi thành

phần quay và tịnh tiến của đối tượng đích thuộc lớp TransformGroup

bằng cách nội suy tuyến tính giữa chuỗi các cặp điểm mút/vị trí và điểm

mút/hướng, sử dụng giá trị sinh bởi đối tượng Alpha xác định. Vị trí và

hướng nội suy được sử dụng để sinh một dịch chuyển trong hệ tọa độ địa

phương của đối tượng Interpolator này. Xét về mặt giao diện lập trình

ứng dụng thì phương thức khởi tạo là quan trọng nhất đối với lớp đối

tượng này. Trong phương thức khởi tạo, tất cả các giá trị và đối tượng liên

quan đều phải được xác định. Chú ý rằng mỗi mảng tham số phải có cùng

độ dài trong đối tượng khởi tạo hiện tại và các đối tượng PathInterpolator

khác trong chương trình.

RotPosPathInterpolator(Alpha Alpha, TransformGroup target,

Transform3D axisOfRotPos, float[] knots, Quat4f[] quats,

Point3f[] positions)

Khởi tạo đối tượng Interpolator mới biến đổi chuyển động quay và

tịnh tiến của đối tượng đích TransformGroup.

Một số phương thức cung cấp bởi lớp RotPosPathInterpolator:

void getPositions(Point3f[] positions)

Sao chép các giá trị vị trí của đối tượng Interpolator hiện thời vào

mảng positions. Mảng positions phải đủ lớn để chứa dữ liệu.

void getQuats(Quat4f[] quats)

Sao chép giá trị các quantenion của đối tượng Interpolator hiện thời

vào mảng quats. Mảng quats phải đủ lớn để chứa dữ liệu.

void setAxisOfRotPos(Transform3D axisOfRotPos)

Thiết lập trục của giát trị RotPos cho đối tượng Interpolator hiện

thời.

void setPosition(int index, Point3f position)

http://tailieuhay.com 521

Page 522: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Thiết lập vị trí tại chỉ mục xác định cho đối tượng Interpolator hiện

thời.

void setQuat(int index, Quat4f quat)

Thiết lập quantenion tại chỉ mục xác định cho đối tượng Interpolator

hiện thời.

void setTarget(TransformGroup target)

Thiết lập đối tượng đích TransformGroup cho đối tượng Interpolator

hiện thời.

Lớp Billboard :

Thuật ngữ “Billboard ” được sử dụng trong đồ họa máy tính để ám

chỉ công nghệ quay tự động một đối tượng trực quan 2 chiều sao cho nó

luôn đối mặt với người quan sát. Sự phát sinh lớp hành vi Billboard xuất

phát từ ý tưởng sử dụng các bề mặt đơn giản thay thế cho cho các hình

khối phức tạp. Hành vi Billboard thông thường được dùng cho mục đích

này, ngoài ra, nó còn được dùng cho các mục đích khác, ví dụ như làm

cho dòng văn bản có thể được nhìn thấy từ mọi góc độ trong môi trường

ảo. Trong Java 3D, công nghệ Billboard được cài đặt bởi một lớp con

của lớp hành vi Behavior, vì vậy, người ta vẫn hay dùng thuật ngữ “hành

vi Billboard ” để chỉ công nghệ này.

Một ví dụ kinh điển sử dụng hành vi behavior là ứng dụng biểu diễn

cây cối dưới dạng hình 2 chiều. Tất nhiên, nếu cái cây chỉ giữ một hướng

cố định thì khi góc nhìn thay đổi, người quan sát sẽ phát hiện ra hình dạng

2 chiều của cây. Nhưng nếu cái cây đó tự định hướng lại sao cho luôn đối

mặt với người quan sát thì nó dường như có dạng 3 chiều. Hiệu quả của

hiệu ứng này càng cao nếu cái cây đó nằm ở hình nền của khung cảnh

hoặc là nằm ở phía đằng xa so với vị trí quan sát.

Billboard làm việc được với hình ảnh cây cối bởi cây cối có dạng

gần giống nhau khi nhìn từ đằng trước, đằng sau hay từ bất cứ góc nhìn

http://tailieuhay.com 522

Page 523: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

nào. Billboard làm cho đối tượng trực quan xuất hiện hoàn toàn giống

nhau từ bất cứ góc nhìn nào, nên nó rất thích hợp sử dụng cùng với ảnh 2

chiều để tạo đối tượng 3 chiều có dạng hình học đối xứng qua trục y như

các tòa nhà hình trụ, tháp nước, hay bất kì đối tượng hình trụ nào. Đối

tượng Billboard còn có thể sử dụng cho các đối tượng 3 chiều không có

dạng đối xứng khi chúng được quan sát từ một khoảng cách đủ lớn để che

dấu dạng 2 chiều.

Hình 5-14 biểu diễn một phần của đồ thị khung cảnh được xây dựng

để sử dụng nút Billboard . Thông thường hai nút TransformGroup được

sử dụng. Nút TransformGroup phía trên được dùng để định vị trí đối

tượng trực quan và có thể là tĩnh. Nút TransformGroup phía dưới được

dùng để định hướng đối tượng và được thao tác bởi đối tượng Billboard .

Chi tiết việc lập trình sẽ được trình bày trong phần dưới đây.

Sử dụng đối tượng Billboard

Việc sử dụng đối tượng Billboard tương tự việc sử dụng đối tượng

Interpolator , ngoại trừ rằng không cần dùng đối tượng Alpha để điều

khiển hoạt ảnh. Hoạt ảnh của đối tượng Billboard được điều khiển bởi vị

trí tương đối của người quan sát trong thế giới ảo. Hình 5-15 biểu diễn

các bước sử dụng Billboard .

Hình 5-14. Biểu đồ đồ thị khung cảnh sử dụng đối tượng Billboard

http://tailieuhay.com 523

Page 524: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

1. tạo đối tượng đích với khả năng ALLOW_TRANSFORM_WRITE

2. tạo đối tượng Billboard tham chiếu đến đối tượng đích

TransformGroup

3. thêm danh giới làm việc cho đối tượng Billboard

4. lắp ghép đồ thị

Hình 5-15. Công thức sử dụng đối tượng Billboard tạo hoạt ảnh

Các lỗi thường gặp khi sử dụng Billboard

Mặc dù việc sử dụng đối tượng Billboard không hề phức tạp, nhưng

cũng có hai lỗi lập trình thường gặp sau. Lỗi thứ nhất xảy ra do đối tượng

đích TransformGroup thiết lập lại hoàn toàn giá trị của nó mỗi khi được

cập nhật. Do đó, đối tượng TransformGroup này không thể sử dụng để

định vị đối tượng trực quan. Nếu dùng đối tượng đích để định vị, hiệu ứng

Billboard vẫn hoạt động, tuy nhiên, trong lần cập nhật quay đầu tiên,

thông tin vị trí của đối tượng đích sẽ bị mất và đối tượng trực quan sẽ

được hiển thị tại vị trí ban đầu.

Nếu đối tượng đích không được thiết lập thuộc tính

ALLOW_TRANSFORM_WRITE khi chương trình được thực thi sẽ phát

sinh lỗi runtime. Nếu danh giới làm việc không được thiết lập hay thiết

lập không chính xác thì đối tượng Billboard sẽ không điều khiển được

đối tượng trực quan. Danh giới làm việc thông thường được xác định bởi

đối tượng BoundingSphere với phạm vi làm việc đủ lớn để bao gồm đối

tượng trực quan.

Có một giới hạn khi sử dụng lớp Billboard : trong các ứng dụng với

nhiều hơn một quan sát, mỗi đối tượng Billboard chỉ điều khiển hoạt ảnh

chính xác cho chỉ một quan sát. Với một vài ứng dụng thì khả năng cung

cấp của Billboard là đảm bảo, còn với các ứng dụng khác, đặc điểm này

là một giới hạn lớn. Java3D API phiên bản 1.2 giới thiệu lớp

OrientedShape3D để vượt qua giới hạn này. Đối tượng OrientedShape3D

cung cấp các chức năng giống với chức năng của đối tượng Billboard

http://tailieuhay.com 524

Page 525: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

nhưng có thêm khả năng xử lý nhiều quan sát cùng một lúc. Billboard

quay quanh một trục hoặc một điểm. Trong trường hợp sử dụng khác, đối

tượng Billboard điều khiển một đối tượng TransformGroup sao cho trục

z dương của đối tượng TransformGroup và các con của nó luôn đối diện

với người quan sát. Do Billboard hướng trục z+ của đối tượng đích về

phía người quan sát nên nó không thể dùng để quay vật thể quanh trục z.

Vì lý do này, nếu một trục quay của đối tượng được xác định là (0, 0, z)

thì đơn giản Billboard không làm gì cả.

Chương trình ví dụ sử dụng Billboard

Chương trình ví dụ BillboardApp tạo một thế giới ảo với cây cối sử

dụng kĩ thuật Billboard . Mặc dù cây cối trong chương trình này được tạo

bởi các hình thô (hình tam giác phẳng) nhưng chúng không hề hiển thị

như các đối tượng 2 chiều.

Hai đối tượng TransformGroup được sử dụng cho mỗi cây trong ví dụ

này. Một đối tượng TransformGroup, TGT, đơn giản chỉ dịch các cây

thành tọa độ vị trí trong ứng dụng. Giá trị của TGT không bị thay đổi

trong thời gian thực thi của ứng dụng. Đối tượng TransformGroup thứ

hai, TGR, điều khiển hoạt động quay của cây. TGR là đối tượng đích của

Billboard .

public BranchGroup

createSceneGraph(SimpleUniverse su) {

// Create the root of the branch graph

TransformGroup vpTrans = null;

BranchGroup objRoot = new BranchGroup();

Vector3f translate = new Vector3f();

http://tailieuhay.com 525

Page 526: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Transform3D T3D = new Transform3D();

TransformGroup TGT = null;

TransformGroup TGR = null;

Billboard billboard = null;

BoundingSphere bSphere = new

BoundingSphere();

objRoot.addChild(createLand());

SharedGroup share = new SharedGroup();

share.addChild(createTree());

float[][] position = { { 0.0f, 0.0f,

-3.0f }, { 6.0f, 0.0f, 0.0f },

{ 6.0f, 0.0f, 6.0f }, { 3.0f,

0.0f, -10.0f },

{ 13.0f, 0.0f, -30.0f }, {

-13.0f, 0.0f, 30.0f },

{ -13.0f, 0.0f, 23.0f },

{ 13.0f, 0.0f, 3.0f } };

for (int i = 0; i < position.length; i++)

{

translate.set(position[i]);

T3D.setTranslation(translate);

TGT = new TransformGroup(T3D);

TGR = new TransformGroup();

http://tailieuhay.com 526

Page 527: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

TGR.setCapability(TransformGroup.ALLOW_TRANSFORM_

WRITE);

billboard = new Billboard(TGR);

billboard.setSchedulingBounds(bSphere);

//

billboard.setAlignmentMode(Billboard.ROTATE_ABOUT

_POINT);

objRoot.addChild(TGT);

objRoot.addChild(billboard);

TGT.addChild(TGR);

TGR.addChild(new Link(share));

}

vpTrans =

su.getViewingPlatform().getViewPlatformTransform(

);

translate.set(0.0f, 0.3f, 0.0f);

T3D.setTranslation(translate);

vpTrans.setTransform(T3D);

KeyNavigatorBehavior keyNavBeh = new

KeyNavigatorBehavior(vpTrans);

keyNavBeh

.setSchedulingBounds(new

BoundingSphere(new Point3d(), 1000.0));

objRoot.addChild(keyNavBeh);

Background background = new Background();

background.setColor(0.3f, 0.3f, 1.0f);

http://tailieuhay.com 527

Page 528: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

background.setApplicationBounds(new

BoundingSphere());

objRoot.addChild(background);

// Let Java 3D perform optimizations on

this scene graph.

objRoot.compile();

return objRoot;

} // end of CreateSceneGraph method of

BillboardAppĐoạn mã trên được trích từ phương thức

createSenceGraph của chương trình BillboardApp.java với các kí hiệu

đánh dấu tương ứng với các bước thực hiện được liệt kê trong hình 5-15.

Hình 5-16. Biểu đồ đồ thị sử dụng đối tượng Billboard trong

BillboardApp.java

Hình 5-17 hiển thị một cảnh sinh bởi chương trình ví dụ BillboardApp.

http://tailieuhay.com 528

Page 529: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Hình 5-17. Một ảnh của BillboardApp với tất cả “cây” 2 chiều đều

hướng về phía người quan sát BillboardApp.java cung cấp

KeyNavigatorBehavior cho phép người dùng di chuyển xung quanh và

quan sát các cây từ các vị trí và hướng nhìn khác nhau. Xin xem lại phần

4.4.2 của chương 4 để biết thêm chi tiết về lớp đối tượng này.

Giao diện lập trình ứng dụng của Billboard (Billboard

API)

Trong ví dụ BillboardApp phía trên, đối tượng Billboard hoạt động

với chế độ mặc định là quay đối tượng trực quan xung quanh trục y. Nên,

nếu các cây trong ví dụ này được quan sát từ phía trên hay từ phía dưới,

dạng 2 chiều của nó sẽ bị lộ.

Một chế độ thay thế là quay đối tượng trực quan quanh một điểm.

Trong chế độ này, hình ảnh 2 chiều được điều khiển quay quanh 1 điểm,

do đó, đối tượng trực quan luôn được quan sát trực diện từ bất cứ vị trí

quan sát nào. Một ứng dụng dễ thấy là biểu diễn mặt trăng hay các vật thể

hình cầu ở khoảng cách xa dưới dạng một hình tròn.

http://tailieuhay.com 529

Page 530: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Các phương thức khởi tạo của Billboard

Billboard ()

Khởi tạo một Billboard với tham số mặc định: mode =

ROTATE_ABOUT_AXIS, axis = (0, 1, 0).

Billboard (TransformGroup tg)

Khởi tạo một đối tượng Billboard với các tham số mặc định hoạt

động trên đối tượng TransformGroup xác định.

Billboard (TransformGroup tg, int mode, Vector3f axis)

Khởi tạo đối tượng Billboard với trục quay và chế độ hoạt động xác

định điều khiển đối tượng TransformGroup xác định.

Billboard (TransformGroup tg, int mode, Point3f point)

Khởi tạo đối tượng Billboard với tâm quay và chế độ xác định, hoạt

động trên đối tượng đích TransformGroup xác định.

Một vài phương thức khác cung cấp bởi lớp Billboard :

void setAlignmentAxis(Vector3f axis)

Thiết lập trục canh chỉnh.

void setAlignmentAxis(float x, float y, float z)

Thiết lập trục canh chỉnh.

void setAlignmentMode(int mode)

Thiết lập chế độ canh chỉnh, trong đó mode có thể là

ROTATE_ABOUT_AXIS - Chỉ định quay xung quanh một

trục xác định

ROTATE_ABOUT_POINT - Chỉ định quay xung quanh một điểm

xác định và chỉ định rằng trục Y của đối tượng con phải phù hợp với trục

Y của đối tượng được quan sát

void setRotationPoint(Point3f point)

Thiết lập tâm quay

void setRotationPoint(float x, float y, float z)

Thiết lập tâm quay

http://tailieuhay.com 530

Page 531: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

void setTarget(TransformGroup tg)

Thiết lập đối tượng đích TransformGroup cho đối tượng Billboard

hiện thời.

OrientedShape3D

Đối tượng OrientedShape3D được sử dụng để thực hiện các chức

năng giống như đối tượng Billboard trong mục trước. Điểm khác biệt

chủ yếu giữa hai lớp đối tượng như đã được nhắc đến ở phần trên là ở chỗ

OrientedShape3D có khả năng làm việc với nhiều hơn một quan sát còn

Billboard thì không, cũng như khả năng chia sẻ sử dụng chỉ có ở

OrientedShape3D.

Đối tượng OrientedShape3D cũng yêu cầu sử dụng ít mã hơn.

OrientedShape3D không hiệu chỉnh đối tượng đích TransformGroup, mà

để mở khả năng này cho mã chương trình thực hiện. OrientedShape3D

không phải là một đối tượng hành vi do đó, người lập trình cũng không

cần quan tâm đến giới hạn hoạt động.

Với so sánh trên thì dễ thấy OrientedShape3D là sự lựa chọn hiển

nhiên cho các ứng dụng dùng hiệu ứng Billboard . Nguyên nhân duy nhất

để không loại bỏ lớp Billboard khỏi Java3D API chính là khả năng

tương thích ngược với các ứng dụng đang tồn tại.

Đối tượng OrientedShape3D quay xung quanh một trục hoặc một tâm.

Trong cả hai trường hợp, đối tượng OrientedShape3D tự định hướng bản

thân nó sao cho trục z+ của các con của nó luôn đối diện với người quan

sát. Do OrientedShape3D hướng trục z+ của các vật thể về phía người

quan sát, nên không có ý nghĩa gì nếu quay vật thể quanh trục z. Vì lí do

này nên trục quay không được song song với trục z, có nghĩa là, trục quay

không được định nghĩa là (0, 0, z) với bất cứ giá trị nào của z. Nếu một

trục song song với z được chỉ định, OrientedShape3D đơn giản sẽ không

http://tailieuhay.com 531

Page 532: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

làm gì cả. Lúc đó coi như là đối tượng TransformGroup được thiết lập ma

trận đồng nhất.

Không có giới hạn cho giá trị được sử dụng để làm tâm quay. Nếu chế

độ biểu diễn được thiết lập là ROTATE_ABOUT_POINT thì vật thể sẽ

quay xung quanh một điểm xác định.

Giao diện lập trình ứng dụng của OrientedShape3D

Giao diện lập trình ứng dụng của OrientedShape3D là tương tự với

giao diện lập trình của lớp Billboard , ngoài ra, cũng có vài điểm khác

biệt. Sự khác biệt phát sinh chủ yếu do sự khác nhau về cấu trúc phân cấp

lớp đối tượng. OrientedShape3D kế thừa từ lớp Shape3D, trong khi đó,

Billboard lại kế thừa từ Behavior.

Danh sách các phương thức khởi tạo của OrientedShape3D không

nhiều như của lớp Shape. Ví dụ như không có phương thức khởi tạo với

chỉ một tham số Geometry. Trong trường hợp này, các phương thức khởi

tạo không kế thừa lớp cơ sở. Một ứng dụng có thể sử dụng phương thức

khởi tạo không tham số và một vài phương thức khác để tạo ra đối tượng

OrientedShape3D cần thiết.

Các phương thức khởi tạo:

OrientedShape3D()

Khởi tạo đối tượng OrientedShape3D với các tham số mặc định

OrientedShape3D(Geometry geometry, Appearance appearance,

int mode, Point3f point)

Khởi tạo đối tượng OrientedShape3D với thành phần hình học, thành

phần xuất hiện, chế độ và tâm quay xác định.

OrientedShape3D(Geometry geometry, Appearance appearance,

int mode, Vector3f axis)

Khởi tạo đối tượng OrientedShape3D với thành phần hình học, thành

phần xuất hiện, chế độ và trục quay xác định.

http://tailieuhay.com 532

Page 533: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Một số phương thức khác cung cấp bởi OrientedShape3D:

void setAlignmentAxis(float x, float y, float z)

void setAlignmentAxis(Vector3f axis)

void setAlignmentMode(int mode)

void setRotationPoint(float x, float y, float z)

void setRotationPoint(Point3f point)

Các phương thức này có các tham số và chức năng giống với các phương

thức cùng tên của Billboard . Xem chi tiết ở phần “Giao diện lập trình

ứng dụng của Billboard ”.

Các khả năng có thể thiết lập cho OrientedShape3D:

ALLOW_AXIS_READ | WRITE

Cho phép đọc (ghi) thông tin trục canh chỉnh.

ALLOW_MODE_READ | WRITE

Cho phép đọc (ghi) thông tin chế độ canh chỉnh.

ALLOW_POINT_READ | WRITE

Cho phép đọc (ghi) thông tin tâm quay.

Ví dụ sử dụng OrientedShape3D

Việc sử dụng OrientedShape3D rất dễ dàng, bất cứ chỗ nào sử dụng

đối tượng Shape3D đều có thể thay thế đơn giản bằng đối tượng

OrientedShape3D.

Xét chương trình ví dụ OrientedShape3DApp.java. Ứng dụng này tạo

một phong cảnh ảo với các cây Billboard 2 chiều. Mỗi cây là một con

của một đối tượng OrientedShape3D, đối tượng này tạo hiệu ứng

Billboard cho cây.

1. public BranchGroup createSceneGraph(SimpleUniverse su) {

2. // Create the root of the branch graph

3. BranchGroup objRoot = new BranchGroup();

http://tailieuhay.com 533

Page 534: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

4.

5. Vector3f translate = new Vector3f();

6. Transform3D T3D = new Transform3D();

7. TransformGroup positionTG = null;

8. OrientedShape3D orientedShape3D = null;

9.

10. Geometry treeGeom = createTree();

11.

12. //specify the position of the trees

13. float[][] position = {{ 0.0f, 0.0f, -2.0f},

14. {-13.0f, 0.0f, 23.0f},

15. { 1.0f, 0.0f, -3.5f}};

16.

17. // for the positions in the array create a OS3D

18. for (int i = 0; i < position.length; i++){

19. translate.set(position[i]);

20. T3D.setTranslation(translate);

21. positionTG = new TransformGroup(T3D);

22.

23. orientedShape3D = new OrientedShape3D();

24. orientedShape3D.addGeometry(treeGeom);

25.

26. objRoot.addChild(positionTG);

27. positionTG.addChild(orientedShape3D);

28. }

Đoạn mã trên được trích từ phương thức createSceneGraph của

chương trình OrientedShape3DApp.java. Có thể nhận thấy tính dễ dùng

của OrientedShape3D so với Billboard .

http://tailieuhay.com 534

Page 535: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Hoạt ảnh mức chi tiết (Level Of Detail Animations)

Mức chi tiết (Level Of Detail – LOD ) là một thuật ngữ chỉ kĩ thuật

biến đổi lượng chi tiết trong một đối tượng trực quan dựa trên một vài giá

trị của thế giới ảo. Ứng dụng thường gặp của kĩ thuật này là thay đổi mức

chi tiết của đối tượng dựa trên khoảng cách đối với người quan sát. Khi

khoảng cách tới đối tượng trực quan càng tăng thì càng ít chi tiết của đối

tượng đó được hiển thị. Do vậy, việc giảm độ phức tạp của đối tượng có

thể không ảnh hưởng đến kết quả hiển thị. Việc giảm bớt lượng chi tiết

của đối tượng khi chúng ở khoảng cách xa so với người quan sát sẽ làm

giảm khối lượng tính toán để tô trát. Nếu kĩ thuật này được áp dụng tốt sẽ

có thể tiết kiệm được đáng kể số lượng công thức tính toán mà vẫn không

làm mất đi nội dung của vật thể.

Lớp DistanceLOD cung cấp đối tượng hành vi LOD dựa trên khoảng

cách của vật thể đối với người quan sát. Một ứng dụng khác của LOD có

thể là thay đổi lượng chi tiết dựa trên tốc độ tô trát (hay tốc độ hiển thị,

được tính bằng số khung hình / giây) để giữ tỉ lệ khung hình là thấp nhất;

tốc độ của vật thể, hay mức độ chi tiết có thể được điều khiển với các

thiết lập của người dùng.

Mỗi đối tượng LOD có một hoặc nhiều hơn các đối tượng Switch

đóng vai trò đối tượng đích. Đối tượng Switch là một nhóm đặc biệt bao

gồm không, một hoặc nhiều hơn các con của chúng trong đồ thị khung

cảnh được dùng để hiển thị. Trong trường hợp sử dụng DistanceLOD,

việc lựa chọn con của đối tượng đích Switch được điều khiển bởi khoảng

cách của đối tượng DistanceLOD đối với người quan sát, dựa trên một tập

các ngưỡng khoảng cách.

Ngưỡng khoảng cách được xác định trong một mảng bắt đầu với

khoảng cách xa nhất, khi đó, con đầu tiên của đối tượng đích sẽ được sử

dụng. Con đầu tiên của đối tượng đích thông thường là đối tượng trực

quan chi tiết nhất. Khi khoảng cách của đối tượng DistanceLOD đối với

http://tailieuhay.com 535

Page 536: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

người quan sát lớn hơn ngưỡng thứ nhất, con thứ hai của đối tượng switch

sẽ được sử dụng. Các ngưỡng khoảng cách sau phải lớn hơn ngưỡng

khoảng cách trước và xác định khoảng cách mà con tiếp theo của đối

tượng đích được sử dụng. Do đó, số lượng con của đối tượng đích là

nhiều hơn số ngưỡng khoảng cách.

Nếu có nhiều hơn một đối tượng Switch được thêm vào với tư cách là

đích của đối tượng LOD , các đối tượng đích Switch sẽ được sử dụng

song song. Có nghĩa là các con của các đối tượng đích Switch có cùng chỉ

mục sẽ được lựa chọn đồng thời. Theo cách làm này, đối tượng trực quan

phức tạp có thể được biểu diễn bởi nhiều đối tượng hình học là con của

các đối tượng Switch khác nhau.

Sử dụng đối tượng DistanceLOD

Việc sử dụng đối tượng DistanceLOD tương tự việc sử dụng đối

tượng nội suy Interpolator , ngoại trừ việc không có đối tượng Alpha

nào cần sử dụng để điều khiển hoạt ảnh. Hoạt ảnh của đối tượng LOD

được điều khiển bởi khoảng cách tương đối của nó đối với người quan sát

trong thế giới ảo, theo cách này, việc sử dụng đối tượng DistanceLOD

giống với việc sử dụng đối tượng Billboard . Sử dụng đối tượng

DistanceLOD cũng cần phải thiết lập các ngưỡng khoảng cách. Hình 5-18

biểu diễn các bước để sử dụng DistanceLOD.

1. tạo các đối tượng Switch đích với khả năng

ALLOW_SWITCH_WRITE

2. tạo danh sách mảng các ngưỡng khoảng cách cho đối tượng

DistanceLOD

3. tạo đối tượng DistanceLOD sử dụng mảng các ngưỡng khoảng

cách

4. thiết lập đối tượng Switch đích cho đối tượng DistanceLOD

http://tailieuhay.com 536

Page 537: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

5. thiết lập giới hạn hoạt động cho đối tượng DistanceLOD

6. “lắp ghép” đồ thị khung cảnh, bao gồm cả việc thêm các con cho

các đối tượng Switch

Hình 5-18. Công thức sử dụng DistanceLOD để tạo hoạt ảnh

Các lỗi thường gặp khi sử dụng LOD

Mặc dù việc sử dụng đối tượng LOD không phải là phức tạp, nhưng

cũng có hai lỗi lập trình thường gặp sau. Lỗi thường xảy ra nhất là không

gộp đối tượng Switch đích vào đồ thị khung cảnh. Thiết lập đối tượng

Switch là đích của đối tượng DistanceLOD không tự động gộp nó vào đồ

thị khung cảnh.

Nếu khả năng ALLOW_SWITCH_WRITE không được thiết lập cho

đối tượng Switch đích thì khi chương trình được thực thi sẽ phát sinh lỗi

runtime. Còn nữa, nếu giới hạn hoạt động không được thiết lập, hoặc thiết

lập không chính xác thì LOD không điều khiển được đối tượng trực

quan. Giới hạn hoạt động thông thường được quy định bởi một đối tượng

BoundingSphere với bán kính đủ lớn để điều khiển được đối tượng trực

quan. Tương tự như các đối tượng hành vi khác, nếu không gộp LOD

vào đồ thị khung cảnh thì chương trình cũng sẽ không báo lỗi.

Có một giới hạn mà lớp LOD không vượt qua được chính là số lượng

quan sát mà chương trình có thể làm việc được. Nếu chương trình có

nhiều hơn một quan sát, LOD chỉ có thể điều khiển hoạt ảnh chính xác

cho chỉ một trong số các quan sát đó.

Ví dụ sử dụng DistanceLOD

Đoạn mã sau được trích từ phương thức createSceneGraph trong

chương trình DistanceLODApp. Chi tiết về chương trình này, xin xem

http://tailieuhay.com 537

Page 538: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

thêm phần phụ lục và đĩa chương trình kèm theo. Đoạn mã này đã được

đánh số tương ứng với các bước trong công thức sử dụng ở hình 5-18.

public BranchGroup createSceneGraph() {

BranchGroup objRoot = new BranchGroup();

BoundingSphere bounds = new

BoundingSphere();

// create target TransformGroup with

Capabilities

TransformGroup objMove = new

TransformGroup();

objMove.setCapability(TransformGroup.ALLO

W_TRANSFORM_WRITE);

// create Alpha

Alpha alpha = new Alpha (-1,

Alpha.INCREASING_ENABLE

+ Alpha.DECREASING_ENABLE,

0, 0, 5000, 1000, 1000,

5000, 1000, 1000);

// specify the axis of translation

AxisAngle4f axisOfTra = new

AxisAngle4f(0.0f,1.0f,0.0f,(float)Math.PI/-2.0f);

Transform3D axisT3D = new Transform3D();

axisT3D.set(axisOfTra);

// create position interpolator

http://tailieuhay.com 538

Page 539: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

PositionInterpolator posInt

= new PositionInterpolator (alpha,

objMove, axisT3D, 0.0f, -35.0f);

posInt.setSchedulingBounds(bounds);

// create DistanceLOD target object

Switch targetSwitch = new Switch();

targetSwitch.setCapability(Switch.ALLOW_S

WITCH_WRITE);

// add visual objects of various levels

of detail to the target switch

Appearance sphereAppearA = new

Appearance();

ColoringAttributes sphereCAa = new

ColoringAttributes();

sphereCAa.setColor(0.1f, 0.8f, 0.1f);

sphereAppearA.setColoringAttributes(spher

eCAa);

Appearance sphereAppearB = new

Appearance();

ColoringAttributes sphereCAb = new

ColoringAttributes();

sphereCAb.setColor(0.8f, 0.1f, 0.1f);

sphereAppearB.setColoringAttributes(spher

eCAb);

http://tailieuhay.com 539

Page 540: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

targetSwitch.addChild(new Sphere(.40f, 0,

25, sphereAppearA));

targetSwitch.addChild(new Sphere(.40f, 0,

15, sphereAppearB));

targetSwitch.addChild(new Sphere(.40f, 0,

10, sphereAppearA));

targetSwitch.addChild(new Sphere(.40f, 0,

4, sphereAppearB));

// create DistanceLOD object

float[] distances = { 5.0f, 10.0f,

20.0f};

DistanceLOD dLOD = new

DistanceLOD(distances, new Point3f());

dLOD.addSwitch(targetSwitch);

dLOD.setSchedulingBounds(bounds);

if((targetSwitch.numChildren()-1) !=

dLOD.numDistances()){

System.out.println("DistanceLOD

not initialized properly");

System.out.println(targetSwitch.n

umChildren());

System.out.println(dLOD.numDistan

ces());

}

// assemble scene graph

http://tailieuhay.com 540

Page 541: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

objRoot.addChild(objMove); // target

TG of position interp to move vo

objRoot.addChild(posInt); // add

position interpolator

objMove.addChild(dLOD); // make

the bounds move with visual object

objMove.addChild(targetSwitch);// must

add target switch to scene graph too

// show a level 3 object up close for

comparison

Transform3D t3d = new Transform3D();

t3d.set(new Vector3f(0.6f, 0.0f, 0.0f));

TransformGroup tga = new

TransformGroup(t3d);

objRoot.addChild(tga);

tga.addChild(new Sphere(.40f, 0, 4,

sphereAppearB));

// show a level 0 object at a distance

for comparison

t3d.set(new Vector3f(-5.0f, 0.0f,

-35.0f));

TransformGroup tgb = new

TransformGroup(t3d);

objRoot.addChild(tgb);

tgb.addChild(new Sphere(.40f, 0, 25,

sphereAppearA));

http://tailieuhay.com 541

Page 542: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

// a white background is better for

printing images in tutorial

Background background = new Background();

background.setColor(1.0f, 1.0f, 1.0f);

background.setApplicationBounds(new

BoundingSphere());

objRoot.addChild(background);

// Let Java 3D perform optimizations on this

scene graph.

objRoot.compile();

return objRoot;

} // end of CreateSceneGraph method of

DistanceLODApp

Hình 5-19 biểu diễn biểu đồ đồ thị khung cảnh được tạo ra trong ví dụ

trên. Chú ý rằng, đối tượng Switch đích vừa là con của đối tượng

TransformGroup vừa được tham chiếu đến bởi đối tượng DistanceLOD.

Cả hai quan hệ này đều cần được xác lập.

http://tailieuhay.com 542

Page 543: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Hình 5-19. Một phần biểu đồ đồ thị khung cảnh cho chương trình

DistanceLODApp

Hình 5-20 là hai cảnh được sinh từ chương trình DistanceLODApp.

Mỗi ảnh này có 2 khối cầu tĩnh và một khối cầu dịch chuyển (trong hình

bên phải, khối cầu bên trái nhất đã bị che khuất). Khối cầu dịch chuyển

được biểu diễn bằng một đối tượng DistanceLOD với 4 khối cầu có độ

phức tạp hình học khác nhau. Khối cầu nhỏ màu xanh là khối cầu chi tiết

nhất được sử dụng bởi đối tượng DistanceLOD ở khoảng cách cực đại.

Khối cầu lớn màu đỏ là khối cầu kém chi tiết nhất của đối tượng

DistanceLOD và ở khoảng cách cực tiểu. Hai khối cầu này được hiển thị

để làm mốc so sánh.

Trong chương trình này, đối tượng DistanceLOD được biểu diễn bởi các

khối cầu có màu sắc khác nhau để minh họa quá trình chuyển đổi.

Một đối tượng nội suy vị trí PositionInterpolator được sử dụng để

dịch chuyển đối tượng DistanceLOD theo hướng vuông góc với màn

hình. Khi đối tượng DistanceLOD dịch chuyển ra xa người quan sát, nó

sẽ chuyển đối tượng trực quan để hiển thị. Nếu không sử dụng các khối

http://tailieuhay.com 543

Page 544: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

cầu có màu sắc khác nhau sẽ rất khó khăn để nhận biết khi nào thì đối

tượng trực quan được chuyển.

Hình 5-20. Hai cảnh được sinh ra từ DistanceLODApp.

Giao diện lập trình ứng dụng DistanceLOD API

DistanceLOD định nghĩa một nút đối tượng hành vi LOD dựa

khoảng cách, hoạt động trên một nút nhóm Switch để lựa chọn một trong

số các con của nút Switch đó dựa vào khoảng cách của nút đối tượng

LOD so với người quan sát. Một mảng n giá trị khoảng cách đơn điệu

tăng, được xác định sao cho thành phần đầu tiên distances[0] tương ứng

với mức chi tiết cao nhất và thành phần cuối cùng distances[n-1] tương

ứng với mức chi tiết thấp nhất. Dựa vào khoảng cách thực từ người quan

sát đến nút DistanceLOD, n giá trị khoảng cách [0, n-1] lựa chọn n+1

mức chi tiết [0, n]. Nếu gọi khoảng cách từ người quan sát đến nút LOD

thì phương trình để xác định mức chi tiết (con của nút Switch) được lựa

chọn là:

0 nếu d <= distances[0]

1. i nếu distances[i-1] < d <= distances[i]

2. n nếu d > distances[n-1]

http://tailieuhay.com 544

Page 545: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Chú ý rằng cả vị trí và mảng các giá trị khoảng cách đều được xác

định trong hệ tọa độ địa phương của nút hiện thời.

Các phương thức khởi tạo:

DistanceLOD()

Khởi tạo và khởi gán cho nút DistanceLOD giá trị mặc định.

DistanceLOD(float[] distances)

Khởi tạo và gán giá trị ban đầu cho nút DistanceLOD với mảng các

giá trị khoảng cách xác định và vị trí mặc định (0, 0, 0).

DistanceLOD(float[] distances, Point3f position)

Khởi tạo và khởi gán cho nút DistanceLOD với mảng các giá trị

khoảng cách và vị trí xác định.

Một số phương thức cung cấp bởi DistanceLOD:

int numDistances()

Trả về số lượng các ngưỡng khoảng cách.

void setDistance(int whichDistance, double distance)

Thiết lập ngưỡng khoảng cách LOD xác định.

void setPosition(Point3f position)

Thiết lập vị trí của nút LOD .

Morph

Các lớp nội suy thay đổi các thuộc tính trực quan khác nhau trong thế

giới ảo. Tuy nhiên, không có lớp nội suy nào cung cấp các khả năng thay

đổi hình dạng hình học của các đối tượng trực quan. Khả năng này do lớp

Morph cung cấp. Đối tượng Morph tạo hình dạng cho một đối tượng

trực quan thông qua việc nội suy từ một tập các đối tượng

GeometryArray. Theo đặc điểm này, lớp Morph giống với các lớp nội

suy. Tuy nhiên, Morph không phải là lớp nội suy, thậm chí, nó còn

không kế thừa lớp hành vi Behavior. Lớp Morph mở rộng từ lớp Node.

http://tailieuhay.com 545

Page 546: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Trong chương 4, chúng ta đã làm quen với phương thức

processStimulus của đối tượng Behavior để thực hiện các thay đổi đối với

đồ thị khung cảnh thực hay đối với các đối tượng trong đồ thị khung cảnh

thực. Do không có lớp hành vi chuyên biệt sử dụng với đối tượng Morph

, các ứng dụng Morph phải tự xây dựng lớp hành vi riêng. Lớp Morph

được coi như một lớp hoạt ảnh hay lớp tương tác phụ thuộc vào sự mô

phỏng hành vi tương tác với đối tượng Morph .

Đối tượng Morph có thể được sử dụng để biến kim tự tháp thành

hình khối hộp, mèo thành chó, hoặc biến đổi bất kì hình dạng hình học

nào thành một dạng hình học khác. Hạn chế duy nhất là các đối tượng

hình học sử dụng cho việc nội suy phải cùng thuộc một lớp và là lớp con

của lớp GeometryArray, với cùng số lượng các đỉnh. Hạn chế về số lượng

đỉnh không phải là hạn chế lớn của Morph , trong đĩa chương trình kèm

theo, bạn đọc có thể thấy chương trình Pyramid2Cube.java, biến một kìm

tự tháp thành hình hộp.

Đối tượng Morph cũng có thể được sử dụng để tạo hoạt ảnh cho các

đối tượng trực quan (ví dụ: làm cho một người đi lại được, hay làm cho

bàn tay có thể cầm nắm được vật dụng…). Chương trình ví dụ tạo hoạt

ảnh cho bàn tay, Morphing.java cũng có thể tìm thấy trong đĩa chương

trình kèm theo. Chương trình ví dụ thứ 3, làm cho một dạng hình que đi

lại được sẽ được trình bày chi tiết trong phần sau.

Sử dụng đối tượng Morph

Để hiểu được cách sử dụng đối tượng Morph , trước hết, cần phải

biết các thức đối tượng Morph làm việc. Morph không quá phức tạp.

Đối tượng Morph lưu trữ một mảng các đối tượng GeometryArray với

mỗi đối tượng định nghĩa đặc tả hình học hoàn chỉnh cho một đối tượng

trực quan. Các đối tượng GeometryArray có thể được coi như là các

http://tailieuhay.com 546

Page 547: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

khung ảnh chính trong hoạt ảnh, hay chính xác hơn, là các hằng số trong

phương trình tính toán để tạo ra một đối tượng GeometryArray mới.

Ngoài mảng các đối tượng GeometryArray, một đối tượng Morph

còn có một mảng các trọng số, đây chính là các biến số trong phương

trình. Sử dụng các đối tượng GeometryArray cùng với các trọng số, đối

tượng Morph khởi tạo một đối tượng mảng hình học sử dụng giá trị

trọng số trung bình của tọa độ, màu sắc, …cung cấp bởi đối tượng

GeometryArray. Thay đổi các trọng số sẽ làm thay đổi hình dạng hình

học.

1. tạo một mảng các đối tượng GeometryArray

2. tạo một đối tượng Morph với khả năng

ALLOW_WEIGHTS_WRITE

3. lắp ghép đồ thị khung cảnh, bao gồm cả việc thêm các con cho đối

tượng đích Switch

Hình 5-21. Công thức sử dụng đối tượng Morph

Như đã trình bày, sử dụng đối tượng Morph không khó, tuy nhiên,

các bước này đúng cho cả hoạt ảnh và tương tác. Hoạt ảnh và tương tác

được cung cấp thông qua một đối tượng hành vi. Do đó, sử dụng đối

tượng Morph thường có nghĩa là viết một lớp hành vi. Cách viết lớp

hành vi đã được trình bày trong phần 4.2.1, nên ở đây không nói chi tiết.

Tất nhiên, Morph hoàn toàn có thể sử dụng mà không cần đối tượng

hành vi, nhưng nó sẽ không thể tạo ra được hoạt ảnh.

Ví dụ sử dụng Morph

Chương trình Morph này sử dụng một đối tượng hành vi tùy chỉnh

để sinh hoạt ảnh. Bước đầu tiên trong quá trình phát triển sẽ là xây dựng

lớp hành vi này.

http://tailieuhay.com 547

Page 548: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Trong đối tượng hành vi được sử dụng để tạo hoạt ảnh cho đối tượng

Morph , phương thức processStimlus thay đổi trọng số của đối tượng

Morph . Trong ví dụ này processStimulus thiết lập các giá trị trọng số

dựa vào giá trị Alpha của một đối tượng Alpha. Hoạt động này xảy ra tại

mỗi khung ảnh được tô trát khi điều kiện kích hoạt đã được thỏa mãn.

Đoạn mã sau là đoạn mã xây dựng đối tượng hành vi tùy biến trong

chương trình MorphApp.

public class MorphBehavior extends Behavior{

private Morph targetMorph;

private Alpha alpha;

// the following two members are here for

effciency (no memory burn)

private double[] weights = {0, 0, 0, 0};

private WakeupCondition trigger = new

WakeupOnElapsedFrames(0);

// create MorphBehavior

MorphBehavior(Morph targetMorph, Alpha

alpha){

this.targetMorph = targetMorph;

this.alpha = alpha;

}

public void initialize(){

// set initial wakeup condition

this.wakeupOn(trigger);

}

http://tailieuhay.com 548

Page 549: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

public void processStimulus(Enumeration

criteria){

// don't need to decode event since

there is only one trigger

// do what is necessary

weights[0] = 0;

weights[1] = 0;

weights[2] = 0;

weights[3] = 0;

float alphaValue = 4f * alpha.value()

- 0.00001f;

int alphaIndex = (int) alphaValue;

weights[alphaIndex] = (double)

alphaValue - (double)alphaIndex;

if(alphaIndex < 3)

weights[alphaIndex + 1] = 1.0 -

weights[alphaIndex];

else

weights[0] = 1.0 -

weights[alphaIndex];

targetMorph.setWeights(weights);

// set next wakeup condition

this.wakeupOn(trigger);

}

} // end of class MorphBehavior

http://tailieuhay.com 549

Page 550: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Lớp MorphBehavior tạo khung hoạt ảnh chính bằng cách sử dụng các

đối tượng GeometryArray hai lần tại một thời điểm theo một quá trình có

tính tuần hoàn. Lớp này thích hợp cho tất cả các hoạt ảnh sử dụng 4

khung ảnh chính và có thể thay đổi dễ dàng để khớp với số lượng khung

ảnh chính khác nhau.

Với lớp hành vi tùy chỉnh vừa viết, mọi việc còn lại chỉ là tạo khung

ảnh chính sử dụng cho hoạt ảnh. Hình 5-22 biểu diễn các hình vẽ tay

được sử dụng làm khung ảnh chính cho chương trình ví dụ. Muốn xây

dựng các khung ảnh đẹp hơn, có thể sử dụng các gói 3D.

Các hình có màu đen trông giống như là hai khung hình chính, mỗi

cái được lặp lại một lần, nhưng thực tế, chúng là bốn khung hình chính

riêng biệt. Sự khác nhau là ở thứ tự các đỉnh được xác định.

Đoạn mã sau được trích từ phương thức createSceneGraph của

chương trình MorphApp.java với các số đánh dấu các bước được chỉ ra

trong hình 5-21. Trong phương thức này, một đối tượng MorphBehavior,

một đối tượng Alpha và một đối tượng Morph được tạo ra, rồi được gộp

vào đồ thị khung cảnh. Các đối tượng khung ảnh chính GeometryArray

được tạo ra bởi một số phương thức khác. Toàn bộ chương trình có thể

tìm thấy trong đĩa chương trình kèm theo.

Hình 5-22. Các hình khung ảnh chính của MorphApp với đường quỹ đạo

của một đỉnh (đường mờ)

public BranchGroup createSceneGraph() {

http://tailieuhay.com 550

Page 551: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

// Create the root of the branch graph

BranchGroup objRoot = new BranchGroup();

Transform3D t3d = new Transform3D();

t3d.set(new Vector3f(0f, -0.5f, 0f));

TransformGroup translate = new

TransformGroup(t3d);

// create GeometryArray[] (array of

GeometryArray objects)

GeometryArray[] geomArray = new

GeometryArray[4];

geomArray[0] = createGeomArray0();

geomArray[1] = createGeomArray1();

geomArray[2] = createGeomArray2();

geomArray[3] = createGeomArray3();

// create morph object

Morph morphObj = new Morph(geomArray);

morphObj.setCapability(Morph.ALLOW_WEIGHT

S_WRITE);

// create alpha object

Alpha alpha = new Alpha(-1, 1, 0, 0,

2000, 100, 0, 0, 0, 0);

// create morph driving behavior

MorphBehavior morphBehav = new

MorphBehavior(morphObj, alpha);

http://tailieuhay.com 551

Page 552: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

morphBehav.setSchedulingBounds(new

BoundingSphere());

//assemble scene graph

objRoot.addChild(translate);

translate.addChild(morphObj);

objRoot.addChild(morphBehav);

Background background = new Background();

background.setColor(1f, 1f, 1f);

background.setApplicationBounds(new

BoundingSphere());

objRoot.addChild(background);

// Let Java 3D perform optimizations on this

scene graph.

objRoot.compile();

return objRoot;

} // end of CreateSceneGraph method of

MorphApp

Một chú ý thú vị rút ra từ ví dụ trên là nhiều hoạt ảnh khác nhau có

thể được tạo ra, sử dụng chính các khung hình chính được xây dựng ở

trên, với các lớp hành vi khác nhau. Hình 5-23 biểu diễn một cảnh sinh ra

bởi Morph3DApp. Trong chương trình này, 3 lớp hành vi khác nhau tạo

hoạt ảnh dựa trên một số hoặc tất cả đối tượng GeometryArray của

MorphApp. Chúng được gọi lần lượt (từ trái qua phải) là “In Place”,

“Tango”, và “Broken”.

http://tailieuhay.com 552

Page 553: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Hình 5-23. Một cảnh trong chương trình Morph3App

Giao diện lập trình ứng dụng Morph API

Các phương thức khởi tạo:

Morph (GeometryArray[] geometryArrays)

Khởi tạo và khởi gán giá trị cho đối tượng Morph với một mảng đối

tượng GeometryArray xác định và một đối tượng null thuộc kiểu

Appearance.

Morph (GeometryArray[] geometryArrays, Appearance appearance)

Khởi tạo và khởi gán giá trị cho đối tượng Morph với một mảng đối

tượng GeometryArray và một đối tượng Appearance xác định.

Một số phương thức khác cung cấp bởi Morph :

void setAppearance(Appearance appearance)

Thiết lập thành phần hiển thị bề ngoài cho nút Morph .

void setGeometryArrays(GeometryArray[] geometryArrays)

Thiết lập thành phần geometryArrays cho nút Morph .

void setAppearanceOverrideEnable(boolean flag)

Thiết lập cờ để có nút lá AlternateAppearance làm bề ngoài hiển thị

cho nút Morph .

http://tailieuhay.com 553

Page 554: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

void setWeights(double[] weights)

Thiết lập vector trọng số Morph cho nút Morph hiện thời.

Các khả năng có thể thiết lập cho Morph :

ALLOW_APPEARANCE_READ | WRITE

Xác định rằng nút hiện thời cho phép đọc (ghi) thông tin

appearance của nó.

ALLOW_GEOMETRY_ARRAY_READ | WRITE

Xác định rằng nút hiện thời cho phép đọc (ghi) thông tin dạng hình

học của nó.

ALLOW_WEIGHTS_READ | WRITE

Xác định rằng nút hiện thời cho phép đọc (ghi) vector trọng số

Morph của nó.

Giao diện GeometryUpdater

Trong các phần trên, hoạt ảnh được tạo ra chủ yếu bằng cách di

chuyển các khối hình hình học, chứ không thay đổi hay tạo ra hình mới.

Ngoại trừ Morph tạo ra hình nội suy từ các hình cho trước. Java 3D API

giới thiệu giao diện GeometryUpdater, giao diện này cùng với

BY_REFERENCE geometry (chương 2) cho phép thay đổi hình dạng

hình học trong thời gian thực thi chương trình.

Với giao diện GeometryUpdater, người lập trình ứng dụng có thể tạo

ra bất cứ loại hoạt ảnh nào phụ thuộc vào việc thay đổi thông tin về dạng

hình học, kể cả các hoạt ảnh sử dụng kĩ thuật Billboard , level of detail

và Morph . Giao diện GeometryUpdater có tính mềm dẻo cao, cho phép

người lập trình tạo được nhiều hiệu ứng hơn so với các kĩ thuật trên.

Các ứng dụng có thể sử dụng GeometryUpdater bao gồm các kĩ thuật

hoạt ảnh chuẩn như kiến tạo các hệ động, các hệ phân tử; sinh bóng mờ tự

động hay các hiệu ứng đặc biệt như chớp… Do GeometryUpdater cho

http://tailieuhay.com 554

Page 555: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

phép truy cập đến dữ liệu từng đỉnh của đối tượng hình học nên khả năng

tạo hoạt ảnh là không có giới hạn.

Mặc dù có thể hiệu chỉnh dữ liệu đối tượng hình học BY_REFERENCE

mà không cần sử dụng đối tượng GeometryUpdater, nhưng cách làm này

cho kết quả hoặc là không thể dự đoán được hoặc là không ổn định.

Sử dụng GeometryUpdater

Để sử dụng được đối tượng GeometryUpdater cho các ứng dụng hình

học động, trước hết cần tạo đối tượng hình học BY_REFERENCE với các

khả năng thích hợp, tạo một lớp GeometryUpdater và lấy ra một đối

tượng thuộc lớp đó, rồi tạo một lớp hành vi tùy biến và cũng lấy ra một

đối tượng thuộc lớp đó. Công việc này không quá phức tạp như nhìn nhận

ban đầu.

Công việc tạo đối tượng hình học BY_REFERENCE không làm gì

nhiều hơn ngoài việc tạo ra một đối tượng hình học khác. Đối tượng

GeometryUpdater có nhiệm vụ hiệu chỉnh đối tượng hình học khi được

gọi. Đối tượng hành vi lập lịch gọi đối tượng GeometryUpdater trong ứng

dụng.

Chúng ta xem xét qua hai phương thức quan trọng của giao diện

GeometryUpdater. Hai phương thức này có cùng tên là updateData().

Phương thức updateData() thứ nhất phải được cài đặt chi tiết trong lớp

định nghĩa GeometryUpdater trong ứng dụng. Phương thức updateData()

thứ hai là phương thức của GeometryArray, phương thức này sẽ gọi

phương thức được cài đặt trong lớp GeometryUpdater.

void updateData(Geometry geometry)

Cập nhật dữ liệu hình học có thể truy cập bởi tham chiếu.

void updateData(GeometryUpdater updater)

http://tailieuhay.com 555

Page 556: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Phương thức này gọi phương thức updateData của đối tượng

GeometryUpdater xác định để đồng bộ hóa cập nhật dữ liệu đối tượng

hình học được tham chiếu bởi đối tượng GeometryArray hiện thời.

Chương trình ví dụ hệ thống phân tử đài phun nước sử

dụng GeometryUpdater

Các hệ thống phân tử thông thường được sử dụng để mô hình nước,

khói, pháo hoa và các hiện tượng giống dạng lỏng khác. Trong một hệ

thống phân tử, có hai tham số thiết kế cơ bản: các phân tử sẽ có dạng như

thế nào, vị trí và hướng của nó sẽ được cập nhật ra sao. Các phân tử thông

thường được biểu diễn dưới dạng điểm hoặc đường, tuy nhiên, các dạng

hình học khác cũng có thể được sử dụng. Việc cập nhật chuyển động có

thể mô phỏng được hành vi tự nhiên của các đối tượng (cụ thể hơn là mô

phỏng các định luật vật lý) hay các chuyển động mong muốn khác. Thông

thường, một vài phần của mã chương trình sẽ có thành phần ngẫu nhiên

để tránh cho các phân tử hoạt động hoàn toàn giống nhau.

Trong chương trình ví dụ, các hạt nước được biểu diễn dưới dạng các

đoạn thẳng nhỏ với chuyển động tuân theo các quy luật vật lý (cụ thể là

chúng được gia tốc bởi trọng trường). Mỗi đoạn thẳng được xác định bởi

2 điểm.

Hình 5-24 là một chuỗi các ảnh thu được từ chương trình ví dụ

ParticleApp. Ảnh phía bên trái là đài nước trước khi các phân tử nước

được khởi tạo. Ảnh ở giữa là khi cột “nước” được khởi tạo trong đài

phun. Trong ảnh này, có tất cả khoảng 300 phần tử hoạt động. Hình ngoài

cùng bên phải là ảnh đài phun khi đã hoạt động một khoảng thời gian.

Trong hình này có khoảng 500 phần tử nước hoạt động.

http://tailieuhay.com 556

Page 557: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Hình 5-24. Chuỗi hình ảnh thu từ chương trình ParticleApp

Trong chương trình ParticleApp.java, cả đài phun được quay quanh

trục để thể hiện tính 3 chiều tự nhiên của hoạt ảnh. Lớp hành vi tuỳ biến

Behavior và lớp GeometryUpdater là các lớp trong của lớp Fountain. Có

thể dùng một vài cách khác để thiết kế hoạt ảnh như trên. Tuy nhiên, sử

dụng các lớp này như là lớp trong sẽ biến Fountain trở thành một đối

tượng đồ hoạ hoạt ảnh hoàn chỉnh. Hơn nữa, do cả hai lớp Behavior và

Geometry đều chỉ được sử dụng cho riêng ứng dụng này, nên chẳng có lí

do gì để cho phép chúng được sử dụng bởi các lớp khác bên ngoài

Fountain.

Các đoạn mã sau tương ứng định nghĩa các đối tượng hình học, hành

vi và geometryUpdater cho ứng dụng ParticleApp. Ba đoạn mã này là

thành phần chính tạo nên hoạt ảnh trong ParticleApp.

Đoạn mã đầu tiên đưa ra định nghĩa cho lớp Fountain. Cụ thể, nó định

nghĩa một vài trường và tạo ra đối tượng hình học được dùng để biểu diễn

nước.

Ba trường (hay 3 thuộc tính) được định nghĩa gần thẻ . Trường

waterLines và baseElevation được sử dụng trong một vài phương thức

khác nhau nên chúng được khai báo là các thuộc tính của lớp Fountain.

waterLines là một tham chiếu đến đối tượng hình học LineArray, đối

tượng hình học của phần tử nước. baseElevation là giá trị toạ độ y của

http://tailieuhay.com 557

Page 558: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

chân đài phun. Trường thuộc tính thứ 3 giữ một tham chiếu đến đối tượng

WaterUpdater được tạo ra tại đây với mục đích là không làm tràn bộ nhớ.

Phương thức thứ nhất của lớp Fountain là createWaterGeometry().

Phương thức này có định nghĩa một biến nguyên N , N là số lượng các

phần tử nước (số các đoạn thẳng của LineArray) được dùng để biểu diễn

nước. Giá trị 1400 được gán cho N trong đoạn mã không có gì đặc biệt

ngoại trừ việc nó làm cho hoạt ảnh trông có vẻ hợp lý hơn. Gần như bất

cứ giá trị nào cũng có thể gán cho N. Càng nhiều phần tử được sử dụng để

tạo hoạt ảnh thì thời gian để xây dựng một khung hình hiển thị càng lớn.

Trong phương thức createWaterGeometry(), đối tượng LineArray

được tạo ra trên dòng mã gán nhãn . Số lượng các đỉnh là N*2, bởi mỗi

phần tử (mỗi đoạn thẳng) cần một đỉnh bắt đầu và một đỉnh kết thúc. Chú

ý rằng định dạng đỉnh bao gồm cả BY_REFERENCE.

Các phần tử nước được tạo hoạt ảnh bằng cách thay đổi giá trị toạ độ

đỉnh cho các đoạn thẳng tương ứng. Việc này chỉ có thể thực hiện được

nếu khả năng thích hợp được thiết lập. Dòng mã dán nhãn đầu tiên thiết

lập khả năng cho phép ghi dữ liệu đỉnh. Khả năng này cần phải được thiết

lập cho bất cứ ứng dụng nào sử dụng GeometryUpdater. Trong hầu hết

các ứng dụng sử dụng GeometryUpdater, khả năng đọc cũng cần phải

được thiết lập. Ứng dụng này đòi hỏi như vậy. Dòng mã dán nhãn thứ 2

có nhiệm vụ thiết lập khả năng đọc dữ liệu giá trị đỉnh.

Phụ thuộc ứng dụng và cách đối tượng GeometryUpdater được thiết

kế, thông tin dạng hình học nhất định ngoài dữ liệu đỉnh có thể cần để

thiết lập đối tượng Geometry. Ví dụ, nếu đối tượng GeometryUpdater

không “biết” được số đỉnh được sử dụng thì giá trị này phải được đọc từ

đối tượng Geometry đã được truyền cho nó. Tất nhiên, thông tin này chỉ

có thể đọc được nếu khả năng thích hợp được thiết lập. Dòng mã tiếp sau

hai dòng mã gán nhãn chịu trách nhiệm thiết lập khả năng đọc số lượng

đỉnh.

http://tailieuhay.com 558

Page 559: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Các dòng mã còn lại trong đoạn mã sau khởi tạo toạ độ cho N đỉnh. Mỗi

đỉnh được khởi tạo toạ độ (0, baseElevation, 0), do đó ban đầu, không có

phần tử nào được nhìn thấy.

public class Fountain extends BranchGroup {

protected LineArray waterLines = null;

protected float baseElevation = -0.45f;

protected GeometryUpdater geometryUpdater =

new WaterUpdater();

Geometry createWaterGeometry() {

int N = 1400; // number of 'drops'

waterLines = new LineArray(N * 2,

LineArray.COORDINATES

| LineArray.BY_REFERENCE);

waterLines.setCapability(GeometryArray.ALLOW_REF_

DATA_WRITE);

waterLines.setCapability(GeometryArray.ALLOW_REF_

DATA_READ);

http://tailieuhay.com 559

Page 560: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

waterLines.setCapability(GeometryArray.ALLOW_COUN

T_READ);

float[] coordinates = new float[N * 3 *

2];

int p;

for (p = 0; p < N; p += 2) { // for each

particle

coordinates[p * 3 + 0] = 0.0f;

coordinates[p * 3 + 1] =

baseElevation;

coordinates[p * 3 + 2] = 0.0f;

coordinates[p * 3 + 3] = 0.0f;

coordinates[p * 3 + 4] =

baseElevation;

coordinates[p * 3 + 5] = 0.0f;

}

waterLines.setCoordRefFloat(coordinates);

// the following statements would be

redundant

// waterLines.setInitialCoordIndex(0);

// waterLines.setValidVertexCount(N*2);

return waterLines;

}

http://tailieuhay.com 560

Page 561: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

abstract class UpdateWaterBehavior extends

Behavior {

WakeupOnElapsedFrames w = null;

public UpdateWaterBehavior() {

w = new WakeupOnElapsedFrames(0);

}

public void initialize() {

wakeupOn(w);

}

public void processStimulus(Enumeration

critiria) {

waterLines.updateData(geometryUpdater);

wakeupOn(w);

} // end processStimulus

} // end class UpdateWaterBehavior

public class WaterUpdater implements

GeometryUpdater {

Random random;

public WaterUpdater() {

random = new Random();

http://tailieuhay.com 561

Page 562: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

}

public void updateData(Geometry geometry)

{

GeometryArray geometryArray =

(GeometryArray) geometry;

float[] coords =

geometryArray.getCoordRefFloat();

int N =

geometryArray.getValidVertexCount();

int i;

for (i = 0; i < N; i += 2) { // for

each particle

if (coords[i * 3 + 1] >

baseElevation) { // update active

// particles

coords[i * 3 + 0] +=

coords[i * 3 + 0] - coords[i * 3 + 3]; // x1

coords[i * 3 + 1] +=

coords[i * 3 + 1] - coords[i * 3 + 4]

- 0.01f; // y1

coords[i * 3 + 2] +=

coords[i * 3 + 2] - coords[i * 3 + 5]; // z1

coords[i * 3 + 3] =

(coords[i * 3 + 0] + coords[i * 3 + 3]) / 2; //

x2

http://tailieuhay.com 562

Page 563: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

coords[i * 3 + 4] =

(coords[i * 3 + 1] + coords[i * 3 + 4] + 0.01f) /

2;// y2

coords[i * 3 + 5] =

(coords[i * 3 + 2] + coords[i * 3 + 5]) / 2; //

z2

if (coords[i * 3 + 1] <

baseElevation) { // if particle

// below base

coords[i * 3 + 0] =

0.0f; // x1

coords[i * 3 + 1] =

baseElevation; // y1

coords[i * 3 + 2] =

0.0f; // z1

coords[i * 3 + 3] =

0.0f; // x2

coords[i * 3 + 4] =

baseElevation; // y2

coords[i * 3 + 5] =

0.0f; // z2

}

} else { // an inactive particle

if (random.nextFloat() >

0.8) { // randomly start a drop

coords[i * 3 + 0] =

0.03f * (random.nextFloat() - 0.5f); // x1

http://tailieuhay.com 563

Page 564: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

coords[i * 3 + 1] =

0.14f * random.nextFloat()

+

baseElevation; // y1

coords[i * 3 + 2] =

0.03f * (random.nextFloat() - 0.5f); // z1

} // end if

} // end if-else

} // end for loop

}

}

}

Đoạn mã sau định nghĩa lớp UpdateWaterBehavior, một lớp mở rộng

từ lớp Behavior. Đây là đoạn mã dễ nhất trong ứng dụng

GeometryUpdater. Lớp Behavior điều khiển hoạt ảnh bằng cách gọi

phương thức updateGeometry của đối tượng hình học được tạo hoạt ảnh

khi phương thức processStimulus của nó được gọi.

Định nghĩa lớp UpdateWaterBehavior bao gồm trường w – một tham

chiếu đến đối tượng WakeupOnElasedFrames - được sử dụng để kích

hoạt đối tượng hành vi. Đối tượng WakeupOnElasedFrames được tạo

trong phương thức khởi tạo của UpdateWaterBehavior bắt đầu từ dòng

mã được dán nhãn . Phương thức initialize() của lớp

UpdateWaterBehavior, bắt đầu từ dòng mã , thiết lập điều kiện đánh

thức ban đầu cho đối tượng hành vi.

Phương thức processStimulus(), bắt đầu từ dòng mã gán nhãn , định

nghĩa các hành động của đối tượng hành vi đáp ứng lại các sự kiện đánh

thức nó. Trong trường hợp này, phương thức updateData() được gọi và

truyền tham số geometryUpdater cho waterLines.

http://tailieuhay.com 564

Page 565: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

abstract class UpdateWaterBehavior extends

Behavior {

WakeupOnElapsedFrames w = null;

public UpdateWaterBehavior() {

w = new WakeupOnElapsedFrames(0);

}

public void initialize() {

wakeupOn(w);

}

public void processStimulus(Enumeration

critiria) {

waterLines.updateData(geometryUpdater);

wakeupOn(w);

} // end processStimulus

} // end class UpdateWaterBehavior

Đoạn mã sau định nghĩa lớp GeometryUpdater. GeometryUpdater

dịch chuyển các phần tử nước bằng cách thay đổi dữ liệu tọa độ của

chúng.

Lớp GeometryUpdater trong ứng dụng này có một hàm khởi tạo và

một phương thức. Trong hàm khởi tạo, nhãn , một đối tượng Random

được tạo ra để sử dụng trong phương thức thường duy nhất của lớp,

phương thức updateData().

http://tailieuhay.com 565

Page 566: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Phương thức updateData(), nhãn , tạo hoạt ảnh cho các phần tử

nước. Thông thường, không phải tất cả các phần tử đều hoạt động tại

cùng một thời điểm. Phần tử nào không hoạt động sẽ có tọa độ y trùng với

tọa độ y của chân đài phun (baseElevation). Nếu một phần tử có tọa độ y

bằng với baseElevation, nó được coi là không hoạt động và vì thế, phần tử

này không di chuyển. Ban đầu, tất cả các phần tử nước đều không hoạt

động.

Xét hệ phần tử này một thời gian ngắn sau khi khởi động, khi này, đã

có một vài phần tử hoạt động, số còn lại thì chưa. Mỗi lần updateData()

được gọi, tiến trình hoạt ảnh sẽ thu thập thông tin liên quan về đối tượng

hình học để cập nhật. Trên dòng mã , tham số Geometry được ép kiểu

thành GeometryArray. Trên dòng mã , một tham chiếu đến dữ liệu tọa

độ đỉnh được lấy ra. Dòng thu thập số lượng đỉnh.

Chú ý rằng, ứng dụng này có thể chạy hiệu quả hơn bằng cách tính

toán các thông tin này một lần rồi lưu trữ nó trong các trường của đối

tượng. Tuy nhiên, hiệu quả đạt được cũng chỉ hạn chế và làm cho đoạn

mã không sử dụng lại được. Lớp Geometry này có thể được sử dụng cho

đài phun với các kích thước khác nhau.

Khi đã có những bước chuẩn bị thích hợp, phương thức updateData() xét

mỗi phần tử tại một thời điểm nào đó trong vòng lặp . Với mỗi phần tử

hoạt động (xác định bằng cách so sánh tọa độ y của nó với

baseElevation), chương trình sẽ tính toán chuyển động cong dạng parabol

của nó. Tọa độ đỉnh đầu tiên của một phần tử được gán các giá trị thích

hợp để mô hình chuyển động, sau đó, tọa độ cũ của đỉnh thứ nhất sẽ được

gán cho đỉnh thứ hai.

Câu lệnh if trên dòng kiểm tra xem phần tử đã vượt qua

baseElevation hay chưa. Nếu điều kiện này thỏa mãn, phần tử đó sẽ

ngừng hoạt động bởi chương trình cập nhật giá trị tọa độ cả hai đỉnh của

nó về giá trị ban đầu, giá trị xác định phần tử không hoạt động.

http://tailieuhay.com 566

Page 567: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Một phần các phần tử không hoạt động, phần else của điều kiện trên dòng

, được ngẫu nhiên khởi tạo bởi điều kiện trên dòng . Trong ví dụ này,

một lượng trung bình khoảng 20% các phần tử không hoạt động sẽ được

khởi tạo.

public class WaterUpdater implements

GeometryUpdater {

Random random;

public WaterUpdater() {

random = new Random();

}

public void updateData(Geometry geometry)

{

GeometryArray geometryArray =

(GeometryArray) geometry;

float[] coords =

geometryArray.getCoordRefFloat();

int N =

geometryArray.getValidVertexCount();

int i;

for (i = 0; i < N; i += 2) { // for

each particle

if (coords[i * 3 + 1] >

baseElevation) { // update active

http://tailieuhay.com 567

Page 568: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

// particles

coords[i * 3 + 0] +=

coords[i * 3 + 0] - coords[i * 3 + 3]; // x1

coords[i * 3 + 1] +=

coords[i * 3 + 1] - coords[i * 3 + 4]

- 0.01f; // y1

coords[i * 3 + 2] +=

coords[i * 3 + 2] - coords[i * 3 + 5]; // z1

coords[i * 3 + 3] =

(coords[i * 3 + 0] + coords[i * 3 + 3]) / 2; //

x2

coords[i * 3 + 4] =

(coords[i * 3 + 1] + coords[i * 3 + 4] + 0.01f) /

2;// y2

coords[i * 3 + 5] =

(coords[i * 3 + 2] + coords[i * 3 + 5]) / 2; //

z2

if (coords[i * 3 + 1] <

baseElevation) { // if particle

// below base

coords[i * 3 + 0] =

0.0f; // x1

coords[i * 3 + 1] =

baseElevation; // y1

coords[i * 3 + 2] =

0.0f; // z1

http://tailieuhay.com 568

Page 569: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

coords[i * 3 + 3] =

0.0f; // x2

coords[i * 3 + 4] =

baseElevation; // y2

coords[i * 3 + 5] =

0.0f; // z2

}

} else { // an inactive particle

if (random.nextFloat() >

0.8) { // randomly start a drop

coords[i * 3 + 0] =

0.03f * (random.nextFloat() - 0.5f); // x1

coords[i * 3 + 1] =

0.14f * random.nextFloat()

+

baseElevation; // y1

coords[i * 3 + 2] =

0.03f * (random.nextFloat() - 0.5f); // z1

} // end if

} // end if-else

} // end for loop

}

}

Cột nước trong hoạt ảnh trông sẽ đẹp hơn nếu các đoạn thẳng biểu

diễn mỗi phần tử loại bỏ được răng cưa. Việc này có thể thực hiện được

bằng cách thêm đối tượng LineAttributes với

setLineAntialiasedEnable(true) vào thành phần Appearance của phần tử

nước. Tuy nhiên, lưu ý rằng, việc làm này có thể phải trả giá bởi tốc độ

xử lý hoạt ảnh.

http://tailieuhay.com 569

Page 570: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

http://tailieuhay.com 570

Page 571: Lap Trinh Java2D and 3D

Lập trình đồ họa trên Java 2D và 3D

Tài liệu tham khảo

Trong quá trình làm cuốn tutorial về lập trình đồ họa trong Java 2D

& 3D chúng em có tham khảo các tài liệu sau:

1. Slide bài giảng Kĩ thuật đồ họa và hiện thực ảo của ThS.Lê Tấn

Hùng.

2. The Java Tutorial, 2nd Volume. Available online at:

http://java.sun.com/docs/books/tutorial/2d/index.html

3. The 2D Text Tutorial. Available online from the Java Developer

Connection:

http://developer.java.sun.com/developer/onlineTraining/Graphics/2

DText/

3. The Java 2D Sample Programs. Available online at:

http://java.sun.com/products/java-media/2D/samples/index.html

4. The Java 2D Demo. Available from the Java 2D website:

http://java.sun.com/products/java-media/2D/index.html

5. The Java 3D document at:

http://java.sun.com/developer/onlineTraining/java3d/

http://tailieuhay.com 571