I. Gớới thiệu về VRML
5. The Browser object
Đối tợng Browser là một đối tợng ECMAScript nằm bên trong trình dịch
ECMAScript đợc cung cấp bởi trình duyệt VRML. Tất cả các trình duyệt cần đợc cung cấp đối tợng này. Không may, các script hỗ trợ trong VRML thờng khá mâu thuẫn nhau và nói chung là thờng hỗ trợ không tốt. Điều này là rất đáng tiếc khi các script hỗ trợ đóng vai trò rất quan trọng. Dù vậy, nh tôi đã nói, đối tợng Browser vẫn đợc gắn liền trong bộ dịch ECMAScript của trình duyệt. Đó là đối tợng tĩnh, nghĩa là bạn không phải tạo ra các biến kiểu đối tợng này trớc khi bạn có thể sử dụng các phơng thức của nó. Để sử dụng phơng thức bên trong đối tợng Browser, chỉ cần sử dụng cú pháp sau :
Browser.functionName().
Nó sẽ thực thi các phơng thức tĩnh bên trong đối tợng Browser. Đối tợng Browser đối tợng sử dung rất nhiều. Nó là tài nguyên thông tin của cũng cung cấp một số cách thay đổi thế giới quan của bạn. Trớc hết, chúng ta sẽ xem việc lấy thông tin từ trình duyệt. Bạn hãy nhớ lại ở Script node có 2 trờng đợc gọi là directOutput và mustEvaluate. Chúng khá là quan trọng khi sử dụng Browser, nên tôi sẽ nhắc lại cho các bạn biết chúng có vai trò thế nào.
mustEvaluate – Nếu nó có giá trị là true, thì script sẽ đợc định lợng ngay tức khắc.
Trình duyệt đợc phép ngăn lại quá trình xử lý script nếu có quá trình quan trọng hơn cần thực hiện trớc. MustEvaluate nếu bằng true thì trình duyệt sẽ không có khả năng làm điều này nữa mà phải thực thi script ngay tức khắc.
directOutput – nếu có giá trị true, script có thể ghi trực tiếp tới eventIns và đọc
trực tiếp từ eventOuts của nút mà nó truy cập tới. Bình thờng, script có thể chỉ làm nh vậy khi gửi hoặc nhận sự kiện trong tập các sự kiện bình thờng.
Information Technology
Tập các phơng thức đầu tiên mà chúng ta sẽ xem trong đối tợng Brower là các ph- ơng thức lấy thông tin. Tôi sẽ sắp xếp chúng lại, kèm theo các mô tả ngắn gọn các ph ơng thức :
Browser.getName()
Đây là phơng thức chỉ trả lại một chuỗi chứa tên của trình duyệt, ví dụ nh
"Cosmo Player". Nó trả về một chuỗi rỗng nếu không có thông tin.It returns
Browser.getVersion()
Phơng thức trả lại chuỗi chứa thông tin về phiên bản của trình duyệt. Nó cũng là chuỗi rỗng nếu không có thông tin gì.
Browser.getWorldURL()
Phơng thức trả lại chuỗi URL hiện tại đang đợc load.
Browser.getCurrentFrameRate()
Trả lại một giá trị tơng đơng với tốc độ load các frame hiện hành (số các hình ảnh trình duyệt thể hiện đợc trên một giây).
Browser.getCurrentSpeed()
Đây cũng là phơng thức trả về một giá trị số, là thời gian bằng tốc độ chuyển động của ngời dùng, liên quan đến hệ thống toạ độ Viewpoint's.
Browser.setDescription(string description) – cần mustEvaluate có giá trị TRUE . đây
là phơng thức thay đổi mô tả hiện tại của trang Web bằng một chuỗi, tơng đơng một tham số.
Browser.loadURL(MFString url, MFString parameter)-cần mustEvaluate có giá
bằng TRUE . Nó load các thông tin mới về từ các file khác. Đối số đầu tiên là danh sách MFString để thử. The chuẩn của VRML, các phần tử của danh sách đợc thử cho đến khi thành công. Đối số thứ 2, parameter, cung cấp thêm các thông số, chẳng hạn cửa sổ TARGET vv..Những tham số bạn hoàn toàn có thể sử dụng cho node Anchor. Thực tế có nhiều công việc làm giống nh Anchor. Nếu trang Web mới đợc load xuống cùng lúc thì
trang hiện tại sẽ bị đóng xuống và đợc thay thế bằng nội dung mới.
Browser.replaceWorld(MFNode nodes) - cần mustEvaluate có giá trị bằng
TRUE
Nó thay thế toàn bộ các trang đang load hiện tại bằng các node trong đối tợng MFNode. Phơng thức này sẽ không bào giờ quay lui lại đợc, cũng giống nh các script đang vận hành cũng sẽ đợc thay thế.
Có 2 phơng thức cho phép bạn tạo ra các phần mới của VRML , chúng đợc biết tới nh các phơng thức createVrmlFromX. Chúng là :
Browser.createVrmlFromString(String string)
Browser.createVrmlFromURL(MFString url, SFNode node, String eventIn)
Các phơng thức cho phép ta tạo ra các phần mới của VRML từ các chuỗi hoặc các file. Cả 2 phơng thức tạo ra đối tợng MFNode mới, do đó bạn có thể sử dụng để thêm vào nhóm các node thông qua addChildren eventIn.Tất cả các node đều có sự kiện eventIn này, vì thế bạn có thể thêm các node con tại bất kỳ nơi nào bạn muốn.
Hai phơng thức làm việc theo các cách không khác nhau là mấy, nh bạn có thể thấy ở định nghĩa của các phơng thức. Tại sao có điều này thì tôi không rõ. Bạn cũng có thể nghĩ chúng làm việc nh nhau, nhng thực tế không phải thế.
createVrmlFromString lấy chuỗi làm tham số và trả lại đối tợng MFNode chứa
VRML từ chuỗi. Chuỗi phải là VRML có giá trị và phải độc lập hoàn toàn. Có nghĩa là nó không thể sử dụng DEFed ngoài chuỗi và cũng nh vậy cho định nghĩa PROTO. Bạn cũng có thể tính đến cả ROUTEs trong chuỗi. Về cơ bản, chuỗi cũng giống nh file VRML và có thể sử dụng các quy định về file cho chuỗi. Ví dụ, nếu chúng ta bên trong một script mà có sự kiện eventOut của MFNode gọi là newChildren, nó sẽ dẫn đến sự kiện
addChildren ở một nhóm các node, chúng ta có thể làm một số việc nh sau
newVRML = 'Shape {';
newVRML += ' appearance Appearance {'; newVRML += ' material Material {'; newVRML += ' diffuseColor 1 0 0'; newVRML += ' }';
newVRML += ' }';
newVRML += ' geometry Box {'; newVRML += ' }';
newVRML += '}';
newChildren = Browser.createVrmlFromString(newVRML);
Chúng sẽ kết hợp thành một chuỗi mà chúng ta cần và sau đó tạo thành MFNode mới từ chuỗi đó. MFNode này ngay lập tức đợc gán cho sự kiện eventOut newChildren, và nó đợc gửi tới nhóm các node. Nút con hiện thời của nhóm đợc thay thế, chỉ một node mới đợc thêm vào.
Còn một phơng thức khác ít phức tạp hơn. createVrmlFromString() làm việc rất đơn giản và linh hoạt. Ngợc lại, , createVrmlFromURL() phức tạp hơn và không linh hoạt bằng. Với phơng thức này, bạn phải cung cấp MFString chứa danh sách các URL để thử thay thế vào tham số đầu tiên trong phơng thức. Các file hoàn toàn phải có giá trị VRML và tuân theo các luật bình thờng. Các node bên trong file sẽ đợc đọc và biến đổi sang node mới cho bạn sử dụng. Sự lúng túng sẽ đến khi bạn thử và gửi MFNode mới tới nhóm các node ở bên ngoài. Phơng thức createVrmlFromString cho bạn đối tợng MFNode đơn giản mà bạn có thể vận dụng một cách linh hoạt và làm những gì bạn muốn. Phơng thức createVrmlFromURL không trả lại bất cứ giá trị nào. Thay vào đó, nó gửi MFNode bằng
chính nó, từ bên trong phơng thức. Đó là vai trò của các tham số. Đầu tiên là tham chiếu đến nút bạn muốn thêm các phần mới và thứ hai là tên của MFNode eventIn mà sẽ nhận nút mới. Tôi nghĩ ví dụ sau sẽ nói rõ hơn
DEF GROUP Group { }
Script {
field SFNode group USE GROUP url "javascript:
function initialize() {
urlString = new MFString('cone.wrl');
Browser.createVrmlFromURL(urlString,group,'addChildren'); }
" }
Nh bạn thấy, các tham số là tên các file đợc dùng, SFNode tham chiếu, tên của các sự kiện eventIn. Phơng thức quản lý mọi thứ khác cho bạn, gửi nút mới vào addChildren eventIn của nhóm. Tôi không chắc chắn tại sao nó lại làm nh vậy, nhng biết chắc có lý do nào đó. Tôi sẽ nói cho các bạn khi nào tôi biết lý do này. Khi lựa chọn bạn có thể bỏ qua phơng thức createVrmlFromURL() và sử dụng phơng thức createVrmlFromString() với nút Inline chứa tên các file bạn muốn thay thế, nh :
newVRML = 'Inline { url "cone.wrl" }';
newChildren = Browser.createVrmlFromString(newVRML);
Nó đa ra chức năng giống nh phơng thức createVrmlFromURL() với việc sử dụng cách của createVrmlFromString(). Cám ơn Eyal Teler cho đề xuất này.
Trở lại công việc hay xem ví dụ sau : #VRML V2.0 utf8
WorldInfo {
title "Floppy's VRML97 Tutorial Example 4.5b" info ["(C) Copyright 2000 Vapour Technology Ltd." "guide@vapourtech.com"] } NavigationInfo { type ["NONE"] } Viewpoint {
description "Default View" position 0 0.5 2
}
Transform {
translation -0.25 -0.15 0 children [
DEF CUBESENSOR TouchSensor { } Shape { appearance Appearance { material Material { diffuseColor 1 0 0 } } geometry Box { size 0.1 0.1 0.17 } } ] } Transform { translation 0 -0.15 0 children [
DEF SPHERESENSOR TouchSensor { } Shape { appearance Appearance { material Material { diffuseColor 0 1 0 } } geometry Sphere { radius 0.05 } } ] }
Transform {
translation 0.25 -0.15 0 children [
DEF CONESENSOR TouchSensor { } Shape { appearance Appearance { material Material { diffuseColor 0 0 1 } } geometry Cone { bottomRadius 0.05 height 0.1 } } ] }
DEF TOP Transform { translation 0 0.5 0 children [ Transform { rotation 1 0 0 1.57 children [ Shape { appearance Appearance { material Material { diffuseColor 0.4 0.4 0.4 } } geometry Box { size 1 1e-8 1 } } ] } ] }
DEF CREATOR Script {
eventIn SFTime cube_touchTime eventIn SFTime sphere_touchTime eventIn SFTime cone_touchTime field SFNode parentNode USE TOP eventOut MFNode newChildren mustEvaluate TRUE
url "javascript:
function cube_touchTime(value,time) { newVRML = 'Group {';
newVRML += ' children [';
newVRML += ' DEF SENSOR PlaneSensor {'; newVRML += ' maxPosition 0.45 0.45'; newVRML += ' minPosition -0.45 -0.45'; newVRML += ' }';
newVRML += ' DEF OBJECT Transform {'; newVRML += ' children [';
newVRML += ' Shape {';
newVRML += ' appearance Appearance {'; newVRML += ' material Material {'; newVRML += ' diffuseColor 1 0 0'; newVRML += ' }';
newVRML += ' }';
newVRML += ' geometry Box {'; newVRML += ' size 0.1 0.1 0.1'; newVRML += ' }'; newVRML += ' }'; newVRML += ' ]'; newVRML += ' }'; newVRML += ' ]'; newVRML += '}';
newVRML += 'ROUTE SENSOR.translation_changed TO OBJECT.set_translation'; newChildren = Browser.createVrmlFromString(newVRML); } function sphere_touchTime(value,time) { newVRML = 'Group {'; newVRML += ' children [';
newVRML += ' DEF SENSOR PlaneSensor {'; newVRML += ' maxPosition 0.45 0.45';
newVRML += ' minPosition -0.45 -0.45'; newVRML += ' }';
newVRML += ' DEF OBJECT Transform {'; newVRML += ' children [';
newVRML += ' Shape {';
newVRML += ' appearance Appearance {'; newVRML += ' material Material {'; newVRML += ' diffuseColor 0 1 0'; newVRML += ' }';
newVRML += ' }';
newVRML += ' geometry Sphere {'; newVRML += ' radius 0.05'; newVRML += ' }'; newVRML += ' }'; newVRML += ' ]'; newVRML += ' }'; newVRML += ' ]'; newVRML += '}';
newVRML += 'ROUTE SENSOR.translation_changed TO OBJECT.set_translation';
newChildren = Browser.createVrmlFromString(newVRML); }
function cone_touchTime(value,time) { urlString = new MFString('cone.wrl');
Browser.createVrmlFromURL(urlString, parentNode, 'addChildren'); }
" }
ROUTE CUBESENSOR.touchTime TO CREATOR.cube_touchTime ROUTE SPHERESENSOR.touchTime TO CREATOR.sphere_touchTime ROUTE CONESENSOR.touchTime TO CREATOR.cone_touchTime ROUTE CREATOR.newChildren TO TOP.addChildren
Tất cả các phơng thức đều đơn giản, tôi sẽ đa ra đây một ví dụ, qua đó bạn có thể thấy hoạt động của chúng. Trong đó sẽ không có cái gì là bạn không hiểu vì tất cả mọi
thứ bây giờ đều đã khá quen thuộc. TimeSensor trong ví dụ có vai trò cập nhật bình th- ờng các văn bản hiện ra màn hình.
#VRML V2.0 utf8 WorldInfo {
title "Floppy's VRML97 Tutorial Example 4.5a" info ["(C) Copyright 2000 Vapour Technology Ltd." "guide@vapourtech.com"]
}
NavigationInfo { }
Viewpoint {
description "Default View" } Shape { appearance Appearance { material Material { diffuseColor 1 1 1 } }
geometry DEF TEXT Text { fontStyle FontStyle { size 0.5 justify "MIDDLE" } } }
DEF TIMER TimeSensor { loop TRUE
startTime 0 stopTime -1 cycleInterval 0.1 }
eventIn SFTime ping eventOut MFString string url "javascript:
function ping(value,time) {
browserString = 'Browser: ' + Browser.getName(); versionString = 'Version: ' + Browser.getVersion(); urlString = 'URL: ' + Browser.getWorldURL(); speedString = 'Speed: ' + Browser.getCurrentSpeed();
frameString = 'Frame Rate: ' + Browser.getCurrentFrameRate() + ' fps'; string = new MFString(browserString, versionString, urlString, speedString, frameString);
} " }
ROUTE TIMER.cycleTime TO TEXTCREATOR.ping ROUTE TEXTCREATOR.string TO TEXT.string