Bao Cao Tuan 8
Bao Cao Tuan 8
Bao Cao Tuan 8
Điều này là mặc định cho một khối trong Blender (cũng như trong
Three.js). Hãy thay đổi UV bằng cách chỉ chọn hai phần ba texture.
Nếu bây giờ chúng ta hiển thị điều này trong Three.js, bạn có thể thấy rằng
texture được áp dụng khác nhau.
Tùy chỉnh ánh xạ UV thường được thực hiện từ các chương trình như
Blender, đặc biệt là khi các mô hình trở nên phức tạp hơn. Phần quan trọng nhất
cần nhớ ở đây là ánh xạ UV chạy theo hai chiều, u và v, từ 0 đến 1. Để tùy chỉnh
ánh xạ UV, cần xác định đối với mỗi mặt, phần nào của texture sẽ được hiển thị.
Chúng ta làm điều này bằng cách xác định tọa độ u và v cho mỗi đỉnh tạo nên
khuôn mặt. Bạn có thể sử dụng đoạn mã sau để đặt giá trị u và v:
geom.faceVertexUvs[0][0][0].x = 0.5;
geom.faceVertexUvs[0][0][0].y = 0.7;
geom.faceVertexUvs[0][0][1].x = 0.4;
geom.faceVertexUvs[0][0][1].y = 0.1;
geom.faceVertexUvs[0][0][2].x = 0.4;
geom.faceVertexUvs[0][0][2].y = 0.5;
Đoạn mã này sẽ đặt các thuộc tính uv của mặt đầu tiên thành giá trị
được chỉ định. Hãy nhớ rằng mỗi mặt được xác định bởi ba đỉnh, vì vậy để
đặt tất cả các giá trị uv cho một mặt, chúng ta cần đặt sáu thuộc tính. Nếu bạn
mở 07-uv-maps-Manual.html, ví dụ bạn có thể thấy điều gì xảy ra khi bạn
thay đổi ánh xạ uv theo cách thủ công.
Tiếp theo, chúng ta sẽ xem xét cách texture có thể được lặp lại,cách
được thực hiện bằng một số thủ thuật ánh xạ UV bên trong.
cube.material.map.wrapT = THREE.RepeatWrapping;
Thuộc tính WrapS xác định cách bạn muốn texture hoạt động dọc theo trục
x của nó và thuộc tính WrapT xác định cách texture sẽ hoạt động dọc theo trục y.
Three.js cung cấp hai tùy chọn cho việc này, như sau:
THREE.RepeatWrapping cho phép texture tự lặp lại.
THREE.ClampToEdgeWrapping là cài đặt mặc định. Với THREE.
ClampToEdgeWrapping, texture không lặp lại toàn bộ, nhưng chỉ
các pixel ở cạnh được lặp lại.
Nếu bạn tắt tùy chọn menu repeatWrapping, tùy chọn
THREE.ClampToEdgeWrapping được sử dụng, như sau:
Nếu chúng ta sử dụng THREE.RepeatWrapping, chúng ta có thể đặt
thuộc tính lặp lại như trong đoạn mã sau:
cube.material.map.repeat.set(controls.repeatX, controls.repeatY);
Biến repeatX xác định tần suất texture được lặp lại dọc theo trục x của nó
và biến repeatY xác định tương tự cho trục y. Nếu các giá trị này được đặt thành 1,
texture sẽ không lặp lại. Nếu chúng được đặt thành giá trị cao hơn, bạn sẽ thấy
texture sẽ bắt đầu lặp lại. Bạn cũng có thể sử dụng các giá trị nhỏ hơn 1. Trong
trường hợp đó, có thể thấy rằng bạn sẽ phóng to texture. Nếu bạn đặt giá trị lặp lại
thành giá trị âm, texture sẽ được nhân đôi.
Khi bạn thay đổi thuộc tính lặp lại, Three.js sẽ tự động cập nhật texture và
render với cài đặt mới này. Nếu bạn thay đổi từ THREE.RepeatWrapping thành
THREE.ClampToEdgeWrapping, bạn cần cập nhật rõ ràng kết cấu:
cube.material.map.needsUpdate = true;
Cho đến bây giờ, chúng ta chỉ sử dụng hình ảnh tĩnh cho texture. Tuy
nhiên, Three.js cũng có tùy chọn sử dụng canvas HTML5 làm texture.
2.3. Render với canvas và sử dụng như là một texture
2.3.1. Sử dụng canvas làm texture
2.3.2. Sử dụng canvas làm bump map
2.4. Sử dụng đầu ra từ video làm texture
Nội dung báo cáo tuần 8
- Tìm hiểu về animation cơ bản và cách tạo ra animations bằng model.
3. Tìm hiểu animation cơ bản
3.1. Morphing and skeletal animations
Khi tạo animations trong các external programs (ví dụ: Blender), bạn thường có
hai tùy chọn chính để xác định animations:
• Morph targets: Với morph targets, cần xác định một phiên bản biến đổi,
nghĩa là vị trí chính của lưới. Đối với mục tiêu bị biến đổi này, tất cả các vị trí
đỉnh được lưu trữ lại. Tất cả những gì bạn cần để làm chuyển động hình dạng là di
chuyển tất cả các đỉnh từ vị trí này sang vị trí quan trọng khác và lặp lại quá trình
đó. Ảnh chụp màn hình sau đây cho thấy các mục tiêu hình thái khác nhau được
sử dụng để hiển thị biểu cảm khuôn mặt (được cung cấp bởi nền tảng Blender):
Three.js hỗ trợ cả hai chế độ, nhưng nhìn chung có thể bạn sẽ nhận được kết quả tốt hơn
với các mục tiêu biến đổi. Vấn đề chính với skeletal animation là nhận được export tốt từ
một chương trình 3D như Blender có thể được tạo chuyển động trong Three.js. Dễ dàng
có được một mô hình hoạt động tốt với các mục tiêu hình thái hơn là với xương và da.
Trong phần này, chúng ta sẽ xem xét cả hai tùy chọn và cũng xem xét một vài định dạng
bên ngoài được Three.js hỗ trợ trong đó có thể xác định animations.
3.1.1. Animation with morph targets
Morph targets là cách đơn giản nhất để xác định một animation. Bạn xác
định tất cả các đỉnh cho từng vị trí quan trọng (còn được gọi là khung
chính) và báo lại cho Three.js để di chuyển các đỉnh từ vị trí này sang vị trí
khác. Tuy nhiên, nhược điểm của phương pháp này là đối với các lưới lớn
và hình động lớn, các tập tin mô hình sẽ trở nên rất lớn. Lý do là đối với
mỗi vị trí quan trọng, tất cả các vị trí đỉnh được lặp lại.
Chúng ta sẽ tìm ra cách làm việc với morph targets bằng hai ví dụ. Trong ví
dụ đầu tiên, chúng ta sẽ để Three.js xử lý quá trình chuyển đổi giữa các
khung chính khác nhau (hoặc các mục tiêu hình thái như chúng ta sẽ gọi
chúng từ bây giờ) và trong phần thứ hai, chúng ta sẽ thực hiện việc này một
cách thủ công.
3.1.1.1. Animation with MorphAnimMesh
Lấy ví dụ đàu tiên về first morphing, chúng ta sẽ sử dụng một mô
hình cũng có sẵn từ bản phân phối Three.js – ngựa. Cách duy nhất để
hiểu cách morph-targets là dựa trên sự làm việc của animation bằng
việc mở ví du 10-morph-targets. html lên.
Trong ví dụ này, con ngựa ở phía bên phải là animation và đang chạy, và con ngựa ở phía
bên trái đang đứng yên. Con ngựa thứ hai này (bên trái) được kết xuất từ mô hình cơ bản,
nghĩa là bộ đỉnh ban đầu. Với menu ở góc trên bên phải, bạn có thể duyệt qua tất cả các
mục tiêu hình thái có sẵn và xem các vị trí khác nhau mà ngựa bên trái có thể đảm nhận..
Three.js cung cấp một cách để di chuyển từ vị trí này sang vị trí tiếp theo, nhưng điều
này có nghĩa là chúng ta phải theo dõi thủ công vị trí hiện tại chúng ta đang ở và mục tiêu
chúng ta muốn hướng đến, và khi chúng ta đã đạt được mục tiêu vị trí, lặp lại điều này
cho các vị trí khác. May mắn là Three.js cũng cung cấp một lưới cụ thể, đó là THREE.
MorphAnimMesh, nó lưu lại các thông tin chi tiết cho chúng ta. Trước khi chúng ta tiếp
tục, đây là một ghi chú nhanh về một lưới liên quan đến hoạt hình khác được cung cấp
bởi Three.js có tên là THREE. MorphBlendMesh. Nếu bạn xem qua các đối tượng
được cung cấp bởi Three.js, bạn có thể nhận thấy đối tượng này. Với lưới cụ thể này, bạn
có thể thực hiện khá nhiều điều tương tự bạn có thể làm với
THREE.MorphAnimMesh, và khi bạn nhìn vào mã nguồn, bạn thậm chí có thể thấy
rằng phần lớn nó được sao chép giữa hai đối tượng này. THREE. MorphBlendMesh.
Tuy nhiên,nó dường như không được dùng nữa và không được sử dụng trong bất kỳ ví
dụ chính thức nào của Three.js. Tất cả mọi thứ bạn có thể làm với
THREE.MorhpBlendMesh thì có thể làm đươc với THREE.MorphAnimMesh, vì
vậy, hãy sử dụng THREE.MorphAnimMesh cho loại chức năng này. Đoạn mã sau đây
cho bạn thấy cách tải mô hình và tạo THREE.MorphAnimMesh từ nó:
var loader = new THREE.JSONLoader();
loader.load('../assets/models/horse.js', function (geometry, mat) {
var mat = new THREE.MeshLambertMaterial(
{
morphTargets: true,
vertexColors: THREE.FaceColors
});
var mat2 = new THREE.MeshLambertMaterial(
{color: 0xffffff, vertexColors: THREE.FaceColors});
mesh = new THREE.Mesh(geometry, mat);
mesh.position.x = -100;
frames.push(mesh);
currentMesh = mesh;
morphColorsToFaceColors(geometry);
mesh.geometry.morphTargets.forEach(function (e) {
var geom = new THREE.Geometry();
geom.vertices = e.vertices;
geom.faces = geometry.faces;
var morpMesh = new THREE.Mesh(geom, mat2);
frames.push(morpMesh);
morpMesh.position.x = -100;
});
geometry.computeVertexNormals();
geometry.computeFaceNormals();
geometry.computeMorphNormals();
meshAnim = new THREE.MorphAnimMesh(geometry, mat);
meshAnim.duration = 1000;
meshAnim.position.x = 200;
meshAnim.position.z = 0;
scene.add(meshAnim);
showFrame(0);
}, '../assets/models');
function showFrame(e) {
scene.remove(currentMesh);
scene.add(frames[e]);
currentMesh = frames[e];
console.log(currentMesh);
}
function morphColorsToFaceColors(geometry) {
if (geometry.morphColors && geometry.morphColors.length) {
var colorMap = geometry.morphColors[0];
for (var i = 0; i < colorMap.colors.length; i++) {
geometry.faces[i].color = colorMap.colors[i];
geometry.faces[i].color.offsetHSL(0, 0.3, 0);
}
}
}
Đây là cách tiếp cận tương tự mà chúng ta đã thấy khi tải các mô hình khác. Lần này, mô
hình bên ngoài cũng chứa các mục tiêu hình thái. Thay vì tạo một đối tượng
THREE.Mesh bình thường, chúng ta tạo THREE.MorphAnimMesh. Có một vài điều
bạn cần tính đến khi tải hình ảnh động::
• Đảm bảo rằng vật liệu bạn sử dụng có THREE.morphTargets được đặt thành
true. Nếu nó không được đặt, lưới của bạn sẽ không chuyển động.
• Trước khi tạo THREE.MorphAnimMesh, đảm bảo rằng đã call
computeMorphNormals trên geometry để tất cả the normal vectors cho các mục
tiêu hình thái được tính toán. Điều này là cần thiết cho hiệu ứng ánh sáng và bóng
chính xác..
• Cũng có thể xác định màu sắc cho các khuôn mặt của một mục tiêu hình thái cụ
thể. Đây là tài nguyên có sẵn từ morphColors. Bạn có thể sử dụng điều này để
biến đổi không chỉ hình dạng của hình học, mà cả màu sắc của từng khuôn mặt.
Với phương thức trợ giúp morphColorsToFaceColors, chúng ta chỉ sửa màu của
các mặt thành tập màu đầu tiên trong mảng morphColors.
• Cài đặt mặc định là phát toàn bộ hình động trong một lần. Nếu có nhiều hình động
được xác định cho cùng một hình dạng, bạn có thể sử dụng hàm
parseAnimations() cùng với playAnimation(name,fps) để phát một trong các
hình động được xác định. Chúng ta sẽ sử dụng phương pháp này trong phần cuối
của chương này, nơi chúng ta tải hình ảnh động từ một mô hình MD2..
Tất cả những gì còn lại phải làm là cập nhật hình ảnh động trong vòng lặp render. Đối
với điều này, một lần nữa chúng ta sử dụng THREE.Clock để tính toán delta và sử
dụng nó để cập nhật hình ảnh động, như sau::
function render() {
stats.update();
this.update = function () {
cube.morphTargetInfluences[0] = controls.influence1;
cube.morphTargetInfluences[1] = controls.influence2;
};
};
Lưu ý rằng hình học ban đầu có thể bị ảnh hưởng bởi nhiều mục tiêu
hình thái cùng một lúc. Hai ví dụ này cho thấy các khái niệm quan
trọng nhất đằng sau hoạt hình mục tiêu hình thái. Trong phần tiếp
theo, chúng ta sẽ có một cái nhìn nhanh về hoạt hình bằng cách sử
dụng xương và da.
3.1.2. Animation using bones and skinning
Morph animations thì rất đơn giản. Three.js biết tất cả các vị trí đỉnh đích
và chỉ cần chuyển từng đỉnh từ vị trí này sang vị trí tiếp theo. Đối với
xương và da, nó trở nên phức tạp hơn một chút. Khi bạn sử dụng xương
cho hoạt hình, bạn di chuyển xương và Three.js phải xác định cách dịch
chuyển da theo (một tập hợp các đỉnh) cho phù hợp. Trong ví dụ này,
chúng ta sử dụng một mô hình được xuất từ Blender sang định dạng
Three.js (hand-1.js in the models folder). Đây là mô hình của một bàn
tay, hoàn chỉnh với một bộ xương. Bằng cách di chuyển xương xung
quanh, chúng ta có thể làm động mô hình. Trước tiên hãy xem cách chúng
ta tải mô hình:
console.log(mesh.skeleton);
Three.js cung cấp một trình trợ giúp đơn giản mà bạn có thể sử
dụng để hiển thị
xương của mô hình.
helper = new THREE.SkeletonHelper( mesh );
helper.material.linewidth = 2;
helper.visible = false; scene.add( helper );
The bones are highlighted. You can see an example of this by
enabling the
Trong Chapter 8, Creating and Loading Advanced Meshes and Geometries, chúng ta đã
xem xét một số định dạng 3D được Three.js hỗ trợ. Một vài trong số các định dạng cũng
hỗ trợ hình ảnh động. Trong chương này, chúng ta sẽ xem xét các ví dụ sau:
• Blender with the JSON exporter: Chúng ta sẽ bắt đầu với một hình ảnh động
được tạo trong Blender và xuất sang định dạng JSON của Three.js.
• Collada model: Định dạng Collada có hỗ trợ cho hình ảnh động. Trong ví dụ này,
chúng ta sẽ tải một hình ảnh động từ tệp Collada và render nó với Three.js.
• MD2 model: Mô hình MD2 là một định dạng đơn giản được sử dụng trong các
công cụ Quake cũ. Mặc dù định dạng này có lỗi thời 1 tí, nhưng nó vẫn là một
định dạng tốt để lưu trữ hình ảnh động nhân vật.
Chúng ta sẽ bắt đầu với Blender model.
Ngoài định dạng riêng của Three.js, chúng ta có thể sử dụng một vài định dạng khác để
xác định hình động. Cái đầu tiên chúng ta sẽ xem là tải mô hình Collada.
Kế hoạch tuần sau: Tìm hiểu về cách làm việc với Textures
5. Tìm hiểu về animation cơ bản
Ôn lại về render loop, để tạo ra animation chúng ta sẽ render khung hình. Three.js hỗ trợ
việc này bằng hàm requestAnimationFrame.
Với code này ta chỉ cần gọi hàm render() sau khi đã khởi tạo xong một scene. Bên trong
hàm render ta dùng hàm requestAnimationFrame để xác định thời gian render lại scene
đó, thường là 60 lần một giây. Với cách này chúng ta không cần phải quan tâm đến việc
canh thời gian khi nào cần render, và nếu animation không cần phải hiển thị thì CPU hay
GPU cũng sẽ không cần phải xử lý để render ảnh.
1. Animation đơn giản
Đối với cách tiếp cận này, ta sẽ tạo ra animation bằng cách thay đổi độ xoay, thu
phóng, vị trí, material, các đỉnh, ….
Animation trong hình này được tạo với đoạn code sau đặt trước hàm
requestAnimationFrame và chứa trong hàm render
Ở đây chúng ta chỉ thay đổi các thuộc tính của các object trong mỗi render
loop.
2. Tạo Animatio bằng Tween.js
Tween.js là một thư viện javascript hỗ trợ việc xác định thay đổi các thuộc tính
nằm trong khoảng hai giá trị. Tất cả các điểm nằm giữa điểm start và end sẽ được
thư viện này tự động tính toán. Quá trình này gọi là tweening.
Link: https://github.com/sole/tween.js/
Đoạn code trên tạo một tween, tween này thay đổi vị trí của một mesh từ vị trí
hiện tại đến (100, 100, 100) trong vòng 10 giây.
Ta có thể thêm một tween khác xảy ra ngay sau một tween bằng hàm chain().
VD: tween1.chain(tween2);
Bên trong render loop ta thêm vào TWEEN.update();
Sau khi tạo một tween ta sẽ bắt đầu tween này bằng cách gọi hàm start() và có thể
ngừng bằng cách gọi hàm stop().
6. Camera trong three.js
Three.js hỗ trợ nhiều loại control camera, hữu ích và thường được dùng nhất là các
loại FirstPersonControls, FlyControls, RollControls, TrackballControls và
OrbitControls. Ngoài ra còn một số loại control khác ít được sử dụng hơn như:
EditorControls Control này tạo ra để dùng cho three.js
online editor, nằm ở link
https://threejs.org/editor/
OculusControls Control này hỗ trợ việc nhìn xung quanh
khi sử dụng thiết bị Oculus Rift
OrthographicTrackballControls Control này giống với TrackballControls
nhưng dành riêng cho
OrthographicCamera
PointerLockControls Control này cố định con trỏ chuột tại một
vị trí, thường được dùng với một số game
3D đơn giản.
VRControls Control này dùng
PositionSensorVRDevice API để điều
khiển scene. Tìm hiểu thêm tại
https://developer.mozilla.org/en-
US/docs/Web/API/Navigator/getVRDisplays
Ngoài ra thay vì dùng control camera ta cũng có thể tự di chuyển camera bằng cách dùng
hàm lookAt
VD. Camera.lookAt(new Vector3(100, 100, 100));
1. TrackBallControls
Trước khi dùng TrackBallControls cần phải thêm tập tin javascript
<script type="text/javascript" src="../libs/TrackballControls.js"></script>
Để cập nhật vị trí camera ta cần phải cung cấp thời gian giữa mỗi lần render.
Các cử chỉ có thể sử dụng
Nhấn chuột trái và di chuyển Xoay màn hình
Cuộn chuột Phóng to thu nhỏ
Nhấn chuột phải và di chuyển Di chuyển camera
Ta có thể chỉnh các thuộc tính của control như panSpeed (tốc độ di chuyển
camera), rotateSpeed (tốc độ xoay camera), zoomSpeed (tốc độ thu phóng).
Thuộc tính kiểu boolean noZoom xác định có thể thu phóng camera hay không.
Demo: https://threejs.org/examples/misc_controls_trackball.html
2. FlyControls
Với FlyControls ta có thể điều khiển camera giống như bay qua scene.
Trước khi dùng TrackBallControls cần phải thêm tập tin javascript
<script type="text/javascript" src="../libs/FlyControls.js"> </script>
Sau đó ta thêm control vào camera như sau
3. FirstPersonControls
Điều khiển camera theo góc nhìn thứ nhất, các phím WASD dùng để di chuyển và chuột
dùng để nhìn xung quanh.
Để khởi tạo FirstPersonControls cũng giống với các control khác, chúng ta chỉ đi vào hai
thuộc tính là lon và lat (tọa độ mà camera lúc mới render)
4. OrbitControls
Control cho phép người dùng xoay quanh quanh quỹ đạo của mục tiêu được chọn.
Khởi tạo OrbitControls
1. Sprite
Để biểu diễn một hạt trong three.js cách đầu tiên là dùng Sprite. Trong three.js sprite
là một mặt phẳng hai chiều luôn hướng mặt về phía camera.
THREE.SpriteMaterial( parameters : Object )
.color : Color
Màu của material, mặc định là màu trắng.
.fog : boolean
Thuộc tính xác định material có bị ảnh hưởng bởi sương mù hay không
.lights : boolean
Thuộc tính xác định material có ảnh hưởng bởi ảnh sáng hay không
.map : texture
Thuộc tính xác định texture được ánh xạ
.sizeAttenuation : boolean
Thuộc tính xác định độ lớn của sprite có bị ảnh hưởng bởi khoảng cách so với
camera hay không.
Ảnh bên trái là Sprite với SpriteMaterial mặc định, chúng ta có thể truyển ảnh vào Sprite
bằng cách map SpriteMaterial với một texture.
2. PointCloud
Với THREE.Sprite ta có thể dễ dàng tạo các đối tượng và di chuyển chúng trong scene.
Nhưng ta sẻ gặp vấn đề liên quan đến hiệu năng với số lượng sprite lớn. Vì thế nên
three.js còn cung cấp lớp THREE.PointCloud để quản lý tập hợp các particle.
- Trong ví dụ này, bạn có thể sử dụng menu để di chuyển hình cầu và khối lập
phương xung quanh. Nếu kiểm tra tùy chọn xoay, bạn sẽ thấy hai mắt lưới này
xoay quanh tâm của chúng. Tuy nhiên, hai đối tượng này chưa được thêm vào
scene trực tiếp, nhưng đã được thêm vào như một nhóm.
sphere = createMesh(new THREE.SphereGeometry(5, 10, 10));
cube = createMesh(new THREE.BoxGeometry(6, 6, 6));
group = new THREE.Object3D();
group.add(sphere);
group.add(cube);
scene.add(group);
- Trong đoạn code này, chúng ta đã tạo THREE.Object3D. Đây là cơ sở lớp của
THREE.Mesh và THREE.Scene, nhưng bản thân nó không chứa bất cứ thứ gì
hoặc gây ra bất cứ điều gì được đưa ra. Lưu ý rằng trong phiên bản mới nhất của
Three.js, một đối tượng mới gọi là THREE.Group được giới thiệu để hỗ trợ nhóm.
Đối tượng này chính xác là giống như một đối tượng THREE.Object3D và bạn có
thể thay thế THREE.Object3D () trong mã trước đó với THREE.group () cho cùng
hiệu ứng. Trong ví dụ này, sử dụng hàm add để thêm hình cầu và khối lập phương
vào đối tượng này và sau đó chúng ta thêm nó vào scene. Nếu bạn nhìn vào ví dụ,
bạn vẫn có thể di chuyển khối lập phương và khối cầu xung quanh và chia tỉ lệ và
xoay hai đối tượng này. Bạn cũng có thể làm những điều này trong nhóm. Nếu bạn
nhìn vào menu nhóm, bạn sẽ thấy các tùy chọn vị trí và tỷ lệ. Bạn có thể sử dụng
chúng để mở rộng tỉ lệ và di chuyển toàn bộ nhóm xung quanh. Tỉ lệ và vị trí của
các đối tượng trong nhóm này có liên quan đến tỉ lệ và vị trí của chính nhóm đó.
- Tỉ lệ và vị trí rất đơn giản. Chungs ta cần nhớ, mặc dù khi bạn xoay một nhóm, nó
không xoay các đối tượng bên trong nó một cách riêng biệt; nó xoay toàn bộ nhóm
quanh trung tâm của nó (trong ví dụ, bạn xoay toàn bộ nhóm xung quanh trung
tâm của đối tượng nhóm). Trong ví dụ này, chúng tôi đã đặt một mũi tên sử dụng
đối tượng THREE.ArrowHelper ở trung tâm của nhóm để chỉ ra điểm quay:
var arrow = new THREE.ArrowHelper(new THREE.Vector3(0, 1, 0),
group.position, 10, 0x0000ff);
scene.add(arrow);
- Nếu bạn kiểm tra cả hai hộp grouping and rotate , group sẽ xoay. Bạn sẽ nhìn
thấy hình cầu và khối lập phương xoay quanh tâm của nhóm (được biểu thị bằng
mũi tên), như sau:
- Khi sử dụng group, bạn vẫn có thể tham khảo, sửa đổi và định vị trí individual
geometries. Điều duy nhất bạn cần nhớ là tất cả các vị trí, góc quay, và bản dịch
được thực hiện liên quan đến đối tượng cha. Trong phần tiếp theo, chúng ta sẽ xem
xét khi hợp nhất, nơi bạn sẽ kết hợp nhiều geometries riêng biệt và kết thúc bằng
một THREE.Geometry object.
Nhập nhiều mesh thành một mesh
Trong hầu hết các trường hợp, sử dụng groups cho phép bạn dễ dàng thao tác và
quản lý số lượng lớn meshes. Khi bạn xử lý số lượng lớn objects, hiệu suất sẽ trở
thành một vấn đề. Với groups, bạn vẫn làm việc với các đối tượng riêng lẻ mà mỗi đối
tượng cần được xử lý và hiển thị riêng biệt. Với THREE.Geometry.merge (), bạn có
thể merge geometries với nhau và tạo ra một kết hợp. Trong ví dụ sau, bạn có thể thấy
cách thức này hoạt động và hiệu suất cuả nó. Nếu bạn mở ví dụ 02-merging.html, bạn
sẽ thấy một scene với một tập hợp các khối bán trong suốt được phân phối ngẫu
nhiên. Với thanh trượt trong menu, bạn có thể đặt số lượng hình khối bạn muốn trong
scene và vẽ lại scene bằng cách nhấp vào nút vẽ lại. Tùy thuộc vào phần cứng bạn
đang chạy, bạn sẽ thấy sự suy giảm hiệu suất khi số lượng hình khối tăng lên. Trong
trường hợp của chúng ta, như bạn có thể thấy trong ảnh chụp màn hình sau, điều này
xảy ra ở khoảng 4.000 đối tượng, trong đó tốc độ làm mới giảm xuống khoảng 40fps
thay vì 60fps thông thường:
- Như bạn có thể thấy, có một giới hạn nhất định đối với số lượng lưới bạn có thể
thêm vào scene. Thông thường, bạn có thể sẽ không cần nhiều lưới, nhưng khi tạo
các trò chơi cụ thể (ví dụ: một cái gì đó như Minecraft) hoặc nâng cao Trực quan
hóa, bạn có thể cần phải quản lý một số lượng lớn các lưới riêng lẻ. Với
THREE.Geometry.merge(),bạn có thể giải quyết vấn đề này. Trước khi chúng ta
xem code, Hãy chạy ví dụ tương tự, nhưng lần này, với combine box checked.
Với option flagged, chúng ta hợp nhất tất cả các hình khối thành một
THREE.Geometry và thêm vào đó một hình khối để thay thế, như màn hình sau:
- Như bạn có thể thấy, chúng ta có thể dễ dàng render 20.000 khối mà không làm
giảm hiệu suất. Để làm điều này, chúng ta sử dụng một vài dòng mã sau đây:
var geometry = new THREE.Geometry();
for (var i = 0; i < controls.numberOfObjects; i++) {
var cubeMesh = addcube();
cubeMesh.updateMatrix();
geometry.merge(cubeMesh.geometry,cubeMesh.matrix);
}
scene.add(new THREE.Mesh(geometry, cubeMaterial));
- Trong đoạn mã này, hàm addCube () trả về THREE.Mesh. Ở các phiên bản cũ hơn
trong Three.js, chúng ta có thể sử dụng hàm THREE.GeometryUtils.merge để hợp
nhất objects THREE.Mesh vào THREE.Geometry function. Với phiên bản mới
nhất, function này đã bị phản đối vì function THREE.Geometry.merge. Để đảm
bảo merged-in THREE.Geometry object được định vị và xoay một cách chính xác,
chúng ta không chỉ cung cấp THREE.Geometry cho merge function, mà còn vì ma
trận biến đổi. Khi chúng ta thêm ma trận này vào hàm hợp nhất, khối lập phương
chúng ta hợp nhất sẽ được định vị chính xác.
- Chúng tôi làm điều này 20.000 lần và chỉ còn lại một geometries mà chúng tôi
thêm vào scene. Nếu nhìn vào mã code, có lẽ bạn sẽ thấy một vài nhược điểm của
phương pháp này. Vì còn lại một geometries duy nhất, bạn không thể áp dụng một
tài liệu cho từng khối lập phương. Điều này, có thể được giải quyết phần nào bằng
cách sử dụng THREE.MeshFaceMaterial. Tuy nhiên, nhược điểm lớn nhất là bạn
mất kiểm soát đối với các hình khối riêng lẻ. Nếu bạn muốn di chuyển, xoay hoặc
chia tỷ lệ một khối thì bạn không thể (trừ khi bạn tìm kiếm mặt chính xác, đỉnh và
định vị chúng riêng lẻ).
- Với cách tiếp cận nhóm và hợp nhất, bạn có thể tạo ra geometries lớn và phức tạp
bằng cách sử dụng các geometries cơ bản được cung cấp bởi Three.js. Nếu bạn
muốn tạo geometries tiên tiến hơn, sau đó sử dụng phương pháp lập trình được
cung cấp bởi Three.js không phải lúc nào cũng là lựa chọn tốt nhất và dễ nhất.
Three.js, may mắn là nó cung cấp một vài các tùy chọn khác để tạo geometries.
Trong phần tiếp theo, chúng ta sẽ xem cách có thể load geometries và lưới từ các
nguồn bên ngoài.
2. Load geometry từ resource ngoài
Three.js có thể đọc một số file định dạng 3D và import geometries and meshes
trong những files đó. Bảng sau đây cho thấy các định dạng fle được hỗ trợ
bởi Three.js:
Lưu và load Three.js với format JSON
Bạn có thể sử dụng định dạng JSON của Three.js cho hai kịch bản khác nhau
trong Three.js. Có thể sử dụng nó để lưu và load một THREE.Mesh hoặc sử dụng
nó để lưu và load complete scene.
a. Lưu và load THREE.Mesh
Kịch bản Để thể hiện việc lưu và load, một ví dụ đơn giản dựa trên
THREE.TorusKnotGeometry. Với ví dụ này, bạn có thể tạo một nút hình
xuyến, giống như chúng ta đã làm trong Chapter 5, Learning to Work with
Geometries và sử dụng nút save từ Menu Save & Load, bạn có thể lưu hình
học hiện tại. Ví dụ này, chúng ta lưu sử dụng API lưu trữ cục bộ HTML5. API
này cho phép chúng ta dễ dàng lưu trữ liên tục thông tin trong trình duyệt của
khách hàng và truy xuất nó sau đó (ngay cả sau khi trình duyệt đã bị tắt và khởi
động lại).
Chúng ta xem ví dụ 03-load-save-json-object.html.
Exporting JSON từ Three.js rất dễ dàng và không yêu cầu phải có bất kỳ thư
viện bổ sung nào. Điều duy nhất bạn cần làm để xuất THREE.Mesh Ở dạng
JSON là như sau:
var result = knot.toJSON();
localStorage.setItem("json", JSON.stringify(result));
Trước khi lưu, chúng ta sẽ chuyển đổi kết quả từ hàm toJSON, JavaScript
object, đến một chuỗi bằng cách sử dụng hàm JSON.opesify. Điều này dẫn đến
một chuỗi JSON trông giống như thế này (hầu hết các đỉnh và mặt đều bị bỏ
lại):
{
"metadata": {
"version": 4.3,
"type": "Object",
"generator": "ObjectExporter"
},
"geometries": [{
"uuid": "53E1B290-3EF3-4574-BD68-E65DFC618BA7",
"type": "TorusKnotGeometry",
"radius": 10,
"tube": 1,
"radialSegments": 64,
"tubularSegments": 8,
"p": 2,
"q": 3,
"heightScale": 1
}],
...
}
Như bạn có thể thấy, Three.js lưu tất cả thông tin về THREE.Mesh. Để lưu
thông tin này sử dụng HTML5 local storage API, tất cả những gì chúng ta phải
làm là gọi hàm localStorage.setItem. Đối số đầu tiên là key value (json) mà sau
này chúng ta có thể sử dụng để lấy thông tin đã truyền vào làm đối số thứ hai.
Load THREE.Mesh back into Three.js cũng chỉ cần một vài dòng mã, như sau:
var json = localStorage.getItem("json");
if (json) {
var loadedGeometry = JSON.parse(json);
var loader = new THREE.ObjectLoader();
loadedMesh = loader.parse(loadedGeometry);
loadedMesh.position.x -= 50;
scene.add(loadedMesh);
}
Ở đây, chúng ta sẽ nhận JSON từ bộ nhớ cục bộ bằng cách sử dụng tên mà
chúng ta đã lưu(json trong trường hợp này). Đối với điều này, chúng ta sử
dụng hàm localStorage.getItem được cung cấp bởi API lưu trữ cục bộ HTML5.
Tiếp theo, chúng ta cần chuyển đổi chuỗi trở lại thành JavaScript object
(JSON.parse) và chuyển đổi JSON object trở lại THREE.Mesh. Three.js cung
cấp helper object có tên THREE.ObjectLoader, mà bạn có thể sử dụng để
chuyển đổi JSON đến THREE.Mesh. Trong ví dụ này, chúng ta sử dụng parse
method trên trình load để phân tích trực tiếp một chuỗi JSON. Trình load về
cũng cung cấp một hàm load, trong đó bạn có thể chuyển URL sang một tệp có
chứa định nghĩa JSON.
Như bạn có thể thấy, chúng ta chỉ lưu THREE.Mesh. Nếu bạn muốn lưu scene
hoàn chỉnh, bao gồm đèn và máy ảnh, bạn có thể sử dụng
THREE.SceneExporter
b. Lưu và load một scene
Nếu bạn muốn lưu complete scene, bạn sử dụng cách tiếp cận giống như chúng
ta đã thấy trong phần trước cho geometry.
Trong ví dụ này, bạn có ba tùy chọn: exportScene, clearScene và importscene.
Với exportScene, trạng thái hiện tại của scene sẽ được lưu trong bộ nhớ cục bộ
của trình duyệt. Để kiểm tra import function, bạn có thể xóa scene bằng cách
nhấp vào nút ClearScene và load nó từ bộ nhớ cục bộ với nút importscene.
Code làm tất cả điều này rất đơn giản, nhưng trước khi bạn có thể sử dụng nó,
bạn phải import trình xuất và trình load yêu cầu từ bản phân phối Three.js
(look at the examples/js/exporters and examples/js/loaders directories):
<script type="text/javascript" src="../libs/SceneLoader.js">
</script>
<script type="text/javascript" src="../libs/SceneExporter.js">
</script>
Với các cách import JavaScript trong trang, bạn có thể xuất scene với mã sau:
var exporter = new THREE.SceneExporter();
var sceneJson = JSON.stringify(exporter.parse(scene));
localStorage.setItem('scene', sceneJson);
Cách tiếp cận này hoàn toàn giống như cách chúng ta đã sử dụng trong phần
trước, chỉ có lần này, chúng ta sử dụng THREE.SceneExporter () để export
scene hoàn chỉnh. kết quả JSON trông như thế này:
{
"metadata": {
"formatVersion": 3.2,
"type": "scene",
"generatedBy": "SceneExporter",
"objects": 5,
"geometries": 3,
"materials": 3,
"textures": 0
},
"urlBaseType": "relativeToScene", "objects": {
"Object_78B22F27-C5D8-46BF-A539-A42207DDDCA8": {
"geometry": "Geometry_5",
"material": "Material_1",
"position": [15, 0, 0],
"rotation": [-1.5707963267948966, 0, 0],
"scale": [1, 1, 1],
"visible": true
}
... // removed all the other objects for legibility
},
"geometries": {
"Geometry_8235FC68-64F0-45E9-917F-5981B082D5BC": {
"type": "cube",
"width": 4,
"height": 4,
"depth": 4,
"widthSegments": 1,
"heightSegments": 1,
"depthSegments": 1
}
... // removed all the other objects for legibility
}
... other scene information like textures
Khi bạn load lại JSON này, Three.js chỉ tạo lại các đối tượng chính xác như chúng
đã được export. Loading a scene được thực hiện như thế này:
var json = (localStorage.getItem('scene'));
var sceneLoader = new THREE.SceneLoader();
sceneLoader.parse(JSON.parse(json), function(e) {
scene = e.scene;
}, '.');
Đối số cuối cùng được truyền vào trình load ('.') làm sai URL tương đối. Ví dụ,
nếu bạn có materials sử dụng textures(ví dụ: ảnh bên ngoài), chúng sẽ lấy ra bằng
URL tương đối này. Trong ví dụ này, chúng ta không sử dụng textures, Chỉ cần
pass tới thư mục hiện tại. Giống như với THREE.ObjectLoader, bạn cũng có thể
load một JSON chạy từ một URL bằng cách sử dụng chức năng load.
Có nhiều chương trình 3D khác nhau mà bạn có thể sử dụng để tạo các lưới phức
tạp. Một mã nguồn mở phổ biến là Blender (www.blender.org). Three.js có thể
export cho Blender (và cho Maya và 3D Studio Max) xuất trực tiếp sang định dạng
JSON của Three.js. Trong phần tiếp theo, sẽ hướng dẫn bạn cách để Blender được
giới thiệu sử dụng trình xuất này và chỉ cho bạn cách bạn có thể xuất một model
phức tạp trong Blender và hiển thị nó trong Three.js.
Làm việc với Blender
Trước khi bắt đầu với configuration, chúng ta sẽ hiển thị kết quả rằng chúng tôi sẽ
hướng tới mục đích. Trong ảnh chụp màn hình sau, bạn có thể thấy một model
Blender đơn giản được export với plugin Three.js và được import trong Three.js với
THREE.JSONLoader:
\
a. Cài đặt the Three.js exporter trong Blender
Để có được Blender để xuất các model Three.js, trước tiên chúng ta cần thêm
trình xuất Three.js to Blender. Các bước sau đây dành cho Mac OS X nhưng
khá giống nhau trên Windows và Linux. Bạn có thể load xuống Blender từ
www.blender.org và làm theo các hướng dẫn cài đặt flatform-specifc. Sau khi
cài đặt, bạn có thể thêm Plugin Three.js. Đầu tiên, định vị thư mục addons từ
bản cài đặt Blender của bạn sử dụng cửa sổ terminal:
Tiếp theo, bạn cần lấy bản distribution Three.js và giải nén nó. Trong bản này,
bạn có thể tìm tới thư mục sau: utils / export / blender / 2.65 / scripts / addons /.
Trong thư mục này, có một thư mục con duy nhất có tên io_ mesh_threejs. Sao
chép thư mục này vào thư mục addons của bản cài đặt Blender.
Bây giờ, tất cả những gì chúng ta cần làm là khởi động Blender và kích hoạt
trình xuất. Trong Blender, mở Blender User Preferences (File | User
Preferences). Trong cửa sổ mở, chọn tab Addons và trong hộp tìm kiếm, nhập
three. Màn hình sẽ xuất hiện:
Ở đây, plugin Three.js được tìm thấy, nhưng nó vẫn bị vô hiệu hóa. Kiểm tra
small checkbox bên phải và Three.js exporter sẽ được bật. Kiểm tra cuối cùng
để xem mọi thứ có hoạt động chính xác không, mở File | Export menu option,
sẽ thấy Three.js được liệt kê dưới dạng tùy chọn xuất.
Với plugin được cài đặt, chúng ta có thể load model đầu tiên.
b. Load và xuất một model từ Blender
Như ví dụ, chúng ta đã thêm một model Blender đơn giản có tên
misc_ouch01.blend trong thư mục assets/models , bạn có thể tìm thấy trong các
nguồn cho cuốn sách này. Trong Phần này, chúng ta sẽ load xuống model này
và hiển thị các bước tối thiểu cần thiết để xuất model này thành Three.js.
Đầu tiên, chúng ta cần load model này trong Blender. Sử dụng File | Open và
điều hướng đến thư mục chứa misc_ouch01.blend file. Chọn file này và click
Open. Một màn hình trông giống như thế này:
Việc xuất model này sang định dạng Three.js JSON khá đơn giản. Từ File
menu, open Export | Three.js, nhập tên của file export và chọn Export Three.js.
Điều này sẽ tạo ra một file JSON được hiểu theo định dạng Three.js. Một phần
nội dung của contents này được hiển thị:
{
"metadata" :
{
"formatVersion" : 3.1,
"generatedBy" : "Blender 2.7 Exporter",
"vertices" : 208,
"faces" : 124,
"normals" : 115,
"colors" : 0, "uvs" : [270,151],
"materials" : 1,
"morphTargets" : 0,
"bones" : 0
},
...
Material này xác định texture, misc_ouch01_col.jpg, for mapDiffuse property.
Vì vậy, bên cạnh việc xuất model , chúng ta cũng cần đảm bảo texture file
cũng có sẵn cho Three.js. May mắn thay, chúng ta có thể lưu texture này trực
tiếp từ Blender.
Trong Blender, mở chế độ xem UV / Image Editor. Bạn có thể chọn chế độ
xem này từ menu the dropdown.
Đảm bảo texture bạn muốn xuất được chọn, misc_ouch_01_col.jpg (bạn có thể
chọn một trường hợp khác bằng biểu tượng hình ảnh nhỏ). Tiếp theo, nhấp vào
Menu Image và sử dụng tùy chọn menu Save as Image để lưu hình ảnh. Lưu nó
trong cùng thư mục nơi bạn đã lưu model bằng cách sử dụng tên được chỉ định
trong JSON export file. Chúng ta sẽ load model vào Three.js.
Đoạn code để load model này vào Three.js:
var loader = new THREE.JSONLoader();
loader.load('../assets/models/misc_chair01.js', function (geometry,
mat) {
mesh = new THREE.Mesh(geometry, mat[0]);
mesh.scale.x = 15;
mesh.scale.y = 15;
mesh.scale.z = 15;
scene.add(mesh);
}, '../assets/models/');
Chúng ta đã thấy JSONLoader trước đây, nhưng lần này, chúng ta sử dụng
hàm load thay vì hàm parse. Trong chức năng này,chúng ta chỉ định URL
muốn load (trỏ đến tệp JSON đã xuất), mọt cáo callback được gọi khi đối
tượng được load, và location, ../assets/models/, nơi có thể tìm thấy texture (liên
quan đến trang). Callback này có hai tham số: geometry và mat. Tham số
geometry chứa model và tham số mat chứa một mảng vật liệu các đối tượng.
Chúng ta biết rằng chỉ có một material, vì vậy khi tạo ra THREE.MESH.
chúng trực tiếp tham khảo material đó.
Sử dụng Three.js exporter không phải là cách duy nhất để load các model từ
Blender vào Three.js. Three.js hiểu một số định dạng file 3D và Blender có thể
xuất trong một vài định dạng Tuy nhiên, sử dụng định dạng Three.js rất dễ
dàng và nếu mọi thứ đi sai, chúng thường được tìm thấy nhanh chóng.
Trong phần sau, chúng ta sẽ xem xét một vài định dạng mà Three.js hỗ trợ và
cũng hiển thị một ví dụ dựa trên Blender cho các định dạng OBJ và MTL.
Ở đầu chương này, chúng ta đã liệt kê một số định dạng được hỗ trợ
bởi Three.js. Trong phần này, chúng ta sẽ nhanh chóng đi qua một vài ví dụ cho
những định dạng đó. Lưu ý rằng đối với tất cả các định dạng này, cần phải có một
JavaScript bổ sung. Bạn có thể find tất cả các files này trong bản phân phối
Three.js trong các example/js/thư mục loaders.
a. The OBJ and MTL formats
OBJ và MTL là các định dạng đồng hành và thường được sử dụng cùng nhau.
File OBJ định nghĩa geometry và file MTL định nghĩa cho material được sử
dụng. Cả OBJ và MTL là các định dạng dựa trên văn bản. Một phần của OBJ
file trông như thế này:
v -0.032442 0.010796 0.025935
v -0.028519 0.013697 0.026201
v -0.029086 0.014533 0.021409
usemtl Material
s1
f 2731 2735 2736 2732
f 2732 2736 3043 3044
MTL file định nghĩa materials:
newmtl Material
Ns 56.862745
Ka 0.000000 0.000000 0.000000
Kd 0.360725 0.227524 0.127497
Ks 0.010000 0.010000 0.010000
Ni 1.000000
d 1.000000
illum 2
Các định dạng OBJ và MTL của Three.js được hiểu rõ và cũng được hỗ trợ
bằng Blender. Vì vậy, để thay thế, bạn có thể chọn xuất các model từ Blender
trong định dạng OBJ / MTL thay vì định dạng Three.js JSON. Three.js có hai
bộ load khác nhau bạn có thể sử dụng. Nếu bạn chỉ muốn load geometry, bạn
có thể sử dụng OBJLoader. Chúng ta đã sử dụng trình load này cho ví dụ của
mình.
Để import cái này vào Three.js, bạn phải thêm JavaScript OBJLoader:
<script type="text/javascript" src="../libs/OBJLoader.js">
</script>
Import model:
var loader = new THREE.OBJLoader();
loader.load('../assets/models/pinecone.obj', function (loadedMesh) {
var material = new THREE.MeshLambertMaterial({color: 0x5C3A21});
// loadedMesh is a group of meshes. For
// each mesh set the material, and compute the information
// three.js needs for rendering.
loadedMesh.children.forEach(function (child) {
child.material = material;
child.geometry.computeFaceNormals();
child.geometry.computeVertexNormals();
});
mesh = loadedMesh;
loadedMesh.scale.set(100, 100, 100);
loadedMesh.rotation.x = -0.3;
scene.add(loadedMesh);
});
Trong đoạn code này, chúng ta sử dụng OBJLoader để tải mô hình từ một
URL. Một khi mô hình là đã tải, callback mà chúng ta cung cấp được gọi và
thêm mô hình vào scene.
Ví dụ tiếp theo (07-load-obj-mtl.html) sử dụng OBJMTLLoader để tải một mô
hình và trực tiếp assign material.
var mesh;
loader.load("../assets/models/dae/Truck_dae.dae", function
(result) {
mesh = result.scene.children[0].children[0].clone();
mesh.scale.set(4, 4, 4);
scene.add(mesh);
});
Sự khác biệt chính ở đây là kết quả của đối tượng được trả về
callback . Kết quả object có cấu trúc sau:
var result = {
scene: scene,
morphs: morphs,
skins: skins,
animations: animData,
dae: {
...
}
};
Như bạn có thể thấy, đối với hầu hết các mô hình phức tạp, bao gồm
cả material, bạn thường phải thực hiện một số bước bổ sung để có
được kết quả mong muốn. Bằng cách nhìn kỹ vào các tài liệu được
xác nhận (sử dụng console.log ()) hoặc thay thế chúng bằng test
material, vấn đề thường dễ dàng nhận ra.
c. Load STL, CTM, VTK, AWD, Assimp, VRML và Babylon models
Chúng ta sẽ nhanh chóng lướt qua các định dạng này vì tất cả chúng
đều theo cùng một Nguyên tắc:
1. including [NameOfFormat] Loader.js trong trang web của bạn.
2. use [NameOfFormat] Loader.load () để tải URL.
3. Kiểm tra định dạng phản hồi cho callback trông như thế nào và
render kết quả.
Chúng ta đã include một ví dụ cho tất cả các định dạng này:
Nếu bạn xem mã nguồn cho các ví dụ này, bạn có thể thấy rằng đối
với một số, chúng ta cần thay đổi một số thuộc tính material hoặc
thực hiện một số tỷ lệ trước khi model được hiển thị chính xác. Lý
do chúng ta cần làm điều này là vì cách mô hình được tạo ra trong
ứng dụng bên ngoài của nó, mang lại cho nó các kích thước khác
nhau và grouping hơn chúng ta thường sử dụng trong Three.js.
THREE.CircleGeometry
Dùng để tạo mặt phẳng có hình tròn, hình này được tạo bởi nhiều hình tam giác cùng
hướng về tâm.
THREE.CircleGeometry(radius : Float, segments : Integer, thetaStart : Float,
thetaLength : Float)
radius - bán kính của hình tròn
segments - Số mặt phẳng tam giác dùng để tạo hình tròn.
thetaStart - Góc bắt đầu để vẻ hình tròn
thetaLength – Giá trị xác định bao nhiêu phần của hình tròn có thể được nhìn thấy.
(giá trị từ 0 – 2PI)
THREE.RingGeometry
Dùng để tạo một hình vòng.
RingGeometry có các thuộc tính khá giống với Circle geometry
THREE.RingGeometry(innerRadius : Float, outerRadius : Float,
thetaSegments : Integer, phiSegments : Integer, thetaStart : Float, thetaLength : Float)
innerRadius – Xác định bán kính của hình tròn bên trong vòng được tạo.
outerRadius – Xác định khoảng cách từ tâm vòng đến phía ngoài.
thetaSegments – xác định số phần tạo thành phía ngoài vòng tròn, chỉ số này càng
lớn vòng tròn sẽ càng tròn.
phiSegments – xác định số mặt tạo thành bề mặt của vòng.
thetaStart – góc bắt đầu của vòng tròn.
thetaLength – chỉ số xác định độ mở của vòng tròn.
THREE.ShapeGeometry
Dùng để tạo hình dạng tùy chỉnh dựa trên tập hợp các hình được truyền vào.
THREE.ShapeGeometry(shapes : Array, curveSegments : Integer)
shapes – chuỗi các hình ảnh kiểu THREE.Shape.
curveSegments – số lượng segment mỗi hình.
Trước khi tạo một ShapeGeometry chúng ta phải có các Shape. Ví dụ với hình trên ta tạo
như sau.
2. Three-dimensional geometries
THREE.BoxGeometry
Dùng để tạo một hình hộp đơn giản dựa vào chiều rộng, chiều dài, chiều sâu.
THRRE.BoxGeometry(width : Float, height : Float, depth : Float,
widthSegments : Integer, heightSegments : Integer, depthSegments : Integer)
width – rộng, song song với trục x.
height – chiều dài, song song với trục y.
depth – chiều sâu, song song với trục z.
widthSegments/heightSegments/depthSegments – số segment để tạo thành các mặt
phẳng tương ứng.
THREE.SphereGeometry
Dùng để tạo geometry có dạng hình cầu.
THREE.SphereGeometry(radius : Float, widthSegments : Integer,
heightSegments : Integer, phiStart : Float, phiLength : Float, thetaStart : Float,
thetaLength : Float)
Radius – bán kính của hình cầu.
widthSegments – số lượng segment theo chiều ngang.
heightSegments – số lượng segment theo chiều dọc.
phiStart – xác định góc bắt đầu theo chiều ngang của hình cầu.
phiLength – xác định góc độ mở theo chiều ngang của hình cầu.
thetaStart – xác định góc bắt đầu theo chiều dọc của hình cầu.
thetaLength – xác định góc độ mở theo chiều dọc của hình cầu.
THREE.TorusGeometry
Dùng để tạo hình có dạng torus.
THREE.TorusGeometry(radius : Float, tube : Float, radialSegments : Integer,
tubularSegments : Integer, arc : Float)
radius – khoảng cách tính từ tâm tròn ở giữa đến giữa các ống của torus.
tube – bán kính của các ống.
radialSegments – xác định số segment được dùng dọc theo chiều dài các ống.
tubularSegments – xác định số segment theo chiều rộng của các ống.
arc – xác định mức được vẻ của torus (giống thetalength).
THREE.TorusKnotGeometry
Dùng để tạo ra hình có dạng các torus bị thắt nút.
THREE.TorusKnotGeometry(radius : Float, tube : Float, tubularSegments : Integer,
radialSegments : Integer, p : Integer, q : Integer)
radius – bán kinh của các torus.
tube - bán kính của các ống.
tubularSegments/ radialSegments: tương tự như TorusGeometry.
p — Xác định số vòng các torus cuốn quanh trục tọa độ.
q — Xác định số vòng các torus tự cuốn quanh nó.
Chú ý: nếu p = q, hình ảnh sẽ có dạng một torus bình thường.
THREE.PolyhedronGeometry
Dùng để tạo các khối đa diện đều
vertices — Tập hợp các điểm dưới dạng [1,1,1, -1,-1,-1, ... ]
indices — Tập hợp các chỉ số tạo thành bề mặt của khối đa diện có dạng [0,1,2,
2,3,0, ... ]
radius — Bán kính của hình đa diện.
detail — Độ chi tiết của các mặt, nếu tăng chỉ số này sẽ có thêm nhiều mặt.
Dưới đây là các đa diện có sẵn của three.js, chúng ta có thể dùng chúng thay vì tạo
một PolyhedronGeometry tùy chỉnh. Các đa diện có sẵn không có vertices và indices.
VD: Nếu muốn tạo một hình chóp tam giác ta tạo một đối tượng kiểu
THREE.Tetrahedron.
10.Geometries nâng cao và Binary Operation
THREE.ConvexGeometry
Với THREE.ConvexGeometry, chúng ta có thể tạo một convex hull (bao lồi) bao quanh
tập hợp các điểm được truyền vào.
Hình trên là một ConvexGeometry được tạo từ 20 điểm.
Do THREE.ConvexGeometry không chứa trong thư viện three.js chuẩn nên chúng ta sẽ
thêm file js để dùng được geometry này.
<script src="../libs/ConvexGeometry.js"></script>
THREE.LatheGeometry
Dùng để tạo hình có dạng giống chiếc lọ.
THREE.LatheGeometry(points : Array, segments : Integer, phiStart : Float,
phiLength : Float)
points – các điểm cơ bản để tạo thành một LatheGeometry.
segments – số lượng segment dùng để tạo hình, các nhiều segment hình càng tròn
hơn.
phiStart – Góc độ bắt đầu vẻ của hình. (Hình được vẻ từ các điểm cơ bản)
phiLength – Xác định độ mở của hình.
THREE.TubeGeometry
Dùng để tạo hình có dạng ống.
THREE.TubeGeometry(path : Curve, tubularSegments : Integer, radius : Float,
radialSegments : Integer, closed : Boolean)
path — thuộc tính có kiểu THREE.SplineCurve3 dùng để xác định hình dạng.
tubularSegments – số lượng segment tạo nên ống
radius – bán kính của ống.
radialSegments – số segment bao quanh ống.
closed – thuộc tính kiểu boolean, xác định các điểm đầu và các điểm cuối của ống
có nối với nhau không.
THREE.TextGeometry
Lớp này dùng để tạo chữ 2D và chữ 3D.
THREE.TextGeometry(text : String, options : Object)
text - văn bản sẽ được hiển thị.
options — Object that can contains the following parameters.
TextGeometry có các thuộc tính giống với ExtrudeGeometry nhưng có thêm font và
size.
font — an instance of THREE.Font.
size — Float. Size of the text. Default is 100.
Tạo có thể kết hợp các geometry để tạo thành một geometry mới. Để làm được điều này
ta sẽ sử dụng thư viện có tên là ThreeBSP. Thư viện này có thể được download tại
https://github.com/skalnik/ThreeBSP.
Thư viên này được viết bằng CoffeeScript, vì vậy chúng ta phải cài đặt coffeescript trước
khi sử dụng bằng lệnh: “npm install -global coffeescript”
Sau đó thêm thư viện ThreeBSP vào file HTML.
<script type="text/coffeescript" src="../libs/ThreeBSP.coffee"></script>
II. CAMERA
Perspective camera:
Định nghĩa: Loại camera này mô phỏng cách mắt con người nhìn.
Góc nhìn của Perspective camera
Float .fov: field of view, đây là thuộc tính xác định góc độ giữa 2 mặt trái và phải.
Float .near: Xác định khoảng cách gần nhất mà camera có thể render.
Float .far: Xác định khoảng cách xa nhất mà camera có thể render.
Orthographic Camera
Định nghĩa: Kích thước của các object qua camera này sẽ không bị ảnh hưởng bởi
khoảng cách
Bốn tham số đầu tiên là các thuộc tính left, right, top, bot xác định 4 biên của
orthographic camera. Tiếp theo là near và far tương tự perspective camera.
Thuộc tính và hàm chung thường dùng của camera
LookAt
PointLight
Định nghĩa: Ánh sáng soi từ một điểm đến mọi phía xung quanh
Các thuộc tính thường dùng
Integer .color: Màu sắc của ánh sáng.
Float .intensity: Cường của độ ánh sáng.
Number .distance: Tầm tối đa của PointLight, càng xa tâm, cường độ ánh sáng tại vị
trí đó càng giảm.
SpotLight
Định nghĩa: Ánh sáng soi hình nón từ một điểm va hướng đến một hướng theo
một góc độ xác định.
Các thuộc tính thường dùng
Integer .color: Màu sắc của ánh sáng.
Float .intensity: Cường của độ ánh sáng.
number .distance: Tầm tối đa của ánh sáng, càng xa tâm, cường độ ánh sáng tại vị trí
đó càng giảm.
Radians .angle: Góc độ chiếu của Spotlight, tối đa là π/2
Float .penumbra: Tỉ lệ cường độ của phần penumbra so với ánh sáng, giá trị từ
khoảng 0-1
DirectionalLight
Định nghĩa: Là ánh sáng dưới dạng các tia sáng song song soi về một hướng,
DirectionalLight không thể rotate.
Các thuộc tính thường dùng
Integer .color: Màu sắc của ánh sáng.
Float .intensity: Cường của độ ánh sáng.
Boolean .castShadow: Cho phép ánh sáng này có thể tạo bóng.
DirectionalLightShadow .shadow: Dùng để tùy chỉnh bóng cho ánh sáng.
HemisphereLight
Định nghĩa: Ánh sáng từ phía trên của scene, giảm dần khi chiếu xuống. Ánh
sáng này không thể tạo bóng.
Các thuộc tính thường dùng
Float .color: Màu sắc ánh sáng từ bầu trời.
Float .groundColor: Màu sắc ánh sáng dưới mặt đất.
Float .intensity: Cường của độ ánh sáng.
RectAreaLight
Định nghĩa: Ánh sáng chiếu thông qua một mặt phẳng chữ nhật.
Các thuộc tính thường dùng
Integer .color: Màu sắc của ánh sáng.
Float .intensity: Cường của độ ánh sáng.
Float .width: Chiều rộng của ánh sáng.
Float .height: Chiều dài của ánh sáng.
12.MATERIAL
Mesh được tạo thành từ material và geometry. Geometry có thể được xem là khung
của object còn material là lớp bao của khung đó.
Các loại material có các thuộc tính chung, ta có thể chia các thuộc tính này thành ba
loại
• Basic properties: Các thuộc tính này thường được dùng nhất.
VD: ID, Name, opacity, visible, …
• Blending properties: Các thuộc tính này xác định cách material phối màu với
background.
• Advanced properties: Một vài thuộc tính quyết định cách WebGL render object.
Hầu hết trước hợp ta sẽ không dùng các thuộc tính này.
Basic properties
name String Dùng để gán tên cho material và gọi ở nơi khác
MeshNormalMaterial
Material ánh xạ vector với màu RGB.
MeshLambertMaterial
Material không có có độ bóng
MeshLambertMaterial
Material với bề mặt có độ bóng
Các thuộc tính liên quan
Màu sắc ánh sáng do material này phát ra, mặc định
emissive Color
là màu đen
c. Tạo scene
- Để có thể hiển thị bất kỳ thứ gì với thư viện three.js. Cần có 3 thứ: Scene,
Camera và Renderer.
- Tiếp theo chúng ta sẽ tạo mesh, cụ thể là một khối lập phương
● Đầu tiên chúng ta sẽ tạo một BoxGeometry. Đây là một đối tượng chứa tất cả
các điểm (đỉnh) và các mặt của khối.
● Tạo material cho geometry đã tạo.
● Kết hợp material và geometry tạo thành mesh. Sau đó thêm mesh này vào
scene.
d. Làm cho khối lập phương chuyển động
- Tạo một vòng lặp animate và viết code xử lý sự thay đổi của các đối tượng trên
một frame.