Trang này chứa các mẹo phổ biến để xây dựng Scene
và tương tác với trang đó.
Kết xuất cảnh không có thực tế tăng cường
Lớp SceneView
cho phép bạn hiển thị cảnh 3D mà không cần sử dụng máy ảnh của thiết bị hoặc phiên thực tế tăng cường (AR). Điều này sẽ hữu ích khi xem trước đối tượng 3D trong ứng dụng của bạn mà không có AR hoặc cung cấp chức năng thay thế trên những thiết bị không hỗ trợ AR.
Theo mặc định, SceneView
không hiển thị hình ảnh từ máy ảnh thực tế tăng cường (AR) và sử dụng nền đen. Để thay đổi màu nền, bạn có thể gọi view.setBackgroundColor()
hoặc xác định màu nền trong bố cục như dưới đây:
<com.google.ar.sceneform.SceneView
android:id="@+id/scene_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/deep_teal"/>
Nút Camera
của cảnh được đặt ở điểm gốc (vị trí 0,0,0) và hướng về phía trước (hướng 0,0,-1). Vì vị trí và chế độ xoay của máy ảnh không gắn với tính năng theo dõi chuyển động thực tế tăng cường (AR), nên bạn có thể đặt lại vị trí hoặc tạo ảnh động cho bất kỳ nút nào khác.
Camera camera = sceneView.getScene().getCamera();
camera.setLocalRotation(Quaternion.axisAngle(Vector3.right(), -30.0f));
Lượt tương tác
Xử lý thao tác chạm của người dùng
Khi người dùng chạm vào màn hình, Sceneform sẽ truyền sự kiện chạm đến các trình xử lý và trình nghe sự kiện được đính kèm vào các nút và cảnh. Hành vi này tương tự như cách sự kiện nhấn truyền đến các thành phần hiển thị và nhóm thành phần hiển thị trong Android. Sau đây là thứ tự truyền bá:
Sự kiện này được gửi tới mọi trình nghe được thêm vào
scene.addOnPeekTouchListener()
.Điều này tương tự như
viewGroup.intercept()
, ngoại trừ việc trình nghe chạm chạm không thể xử lý sự kiện.Sự kiện được chuyển đến nút đầu tiên mà tia giao nhau với.
- Nút này có thể sử dụng sự kiện bằng cách xác định một phương thức
onTouchEvent()
trả vềtrue
. - Nếu phương thức
onTouchEvent()
trả vềfalse
hoặc không có trình nghe nào được xác định, thì sự kiện sẽ được truyền đến cấp độ gốc của nút. Quá trình này sẽ tiếp tục cho đến khi sự kiện được xử lý hoặc đạt đến cảnh.
- Nút này có thể sử dụng sự kiện bằng cách xác định một phương thức
Cuối cùng, nếu không có trình nghe nào sử dụng sự kiện này, thì sự kiện sẽ được chuyển cho
scene.onTouchListener()
.
Phát hiện cử chỉ
ArFragment
đã tích hợp sẵn tính năng hỗ trợ các cử chỉ nhấn (lựa chọn), kéo (di chuyển), chụm (mở rộng) và xoay (xoay).
Ví dụ: xem HelloSceneformActivity.java
trong ứng dụng mẫu HelloSceneform.
Tạo các nút tùy chỉnh
Tương tự như việc tạo thành phần hiển thị Android tuỳ chỉnh, bạn có thể tạo các nút tuỳ chỉnh bằng cách phân lớp con Node
. Dưới đây là một số tình huống mà bạn nên tạo nút tuỳ chỉnh:
- Bạn muốn truy cập vào các sự kiện trong vòng đời của nút, chẳng hạn như
onUpdate()
,onActivate
vàonDeactivate()
. - Bạn muốn tạo một nút bao gồm một nhóm các nút.
- Bạn đang sao chép nhiều mã và có thể đưa mã đó vào một lớp con.
Để biết ví dụ, hãy xem Planet.java
trong ứng dụng mẫu Hệ thống năng lượng mặt trời.
Tạo ảnh động cho các nút
Có hai cách để tạo ảnh động cho nút:
- Sử dụng
ObjectAnimator
qua API Ảnh động Android tiêu chuẩn. - Tạo một lớp nút tuỳ chỉnh và ghi đè
onUpdate()
Tạo ảnh động bằng ObjectAnimator
Dưới đây là ví dụ tạo ảnh động đến cường độ của tiêu điểm:
final int durationInMilliseconds = 1000;
final float minimumIntensity = 1000.0f;
final float maximumIntensity = 3000.0f;
ValueAnimator intensityAnimator =
ObjectAnimator.ofFloat(
spotlightNode.getLight(), "intensity", minimumIntensity, maximumIntensity);
intensityAnimator.setDuration(durationInMilliseconds);
intensityAnimator.setRepeatCount(ValueAnimator.INFINITE);
intensityAnimator.setRepeatMode(ValueAnimator.REVERSE);
intensityAnimator.start();
Để biết thêm thông tin, hãy xem phần Tạo ảnh động bằng ObjectAnimator.
Tạo ảnh động trong onUpdate
Ghi đè onUpdate()
của nút để tạo hiệu ứng chuyển khung hình thành khung. Ví dụ sau đây, từ Planet.java
trong ứng dụng mẫu Hệ thống năng lượng mặt trời, điều chỉnh thẻ thông tin mỗi khung hình để hiển thị với người dùng, ngay cả khi hành tinh này xoay.
@Override
public void onUpdate(FrameTime frameTime) {
Vector3 cameraPosition = getScene().getCamera().getWorldPosition();
Vector3 cardPosition = infoCard.getWorldPosition();
Vector3 direction = Vector3.subtract(cameraPosition, cardPosition);
Quaternion lookRotation = Quaternion.lookRotation(direction, Vector3.up());
infoCard.setWorldRotation(lookRotation);
}
Thêm đèn
Bạn có thể đính kèm Lights
vào bất kỳ nút nào trong cảnh. Theo mặc định, mọi cảnh Cảnh đều bao gồm một nút Sun
, được gắn đèn định hướng.
Bạn có thể chỉnh sửa mặt trời hoặc thêm đèn của riêng mình vào một cảnh. Ví dụ sau đây sẽ giúp bạn thêm tiêu điểm:
Light spotLightYellow =
Light.builder(this, Light.Type.FOCUSED_SPOTLIGHT)
.setColor(new Color(android.graphics.Color.YELLOW))
.setShadowCastingEnabled(true)
.build();
Sau đó, hãy gọi setLight()
để đính kèm tệp đó vào nút.
Tùy chỉnh hình ảnh mặt phẳng
Theo mặc định, cảnh có PlaneRenderer
làm nổi bật Planes
khi được phát hiện bằng ARCore. Thông báo sẽ có dạng như sau:
Bạn có thể sửa đổi chất liệu và hoạ tiết mặc định dùng để kết xuất các mặt phẳng được phát hiện. Sau đây là cách thay đổi hoạ tiết:
Texture.Sampler sampler =
Texture.Sampler.builder()
.setMinFilter(Texture.Sampler.MinFilter.LINEAR)
.setWrapMode(Texture.Sampler.WrapMode.REPEAT)
.build();
// R.drawable.custom_texture is a .png file in src/main/res/drawable
Texture.builder()
.setSource(this, R.drawable.custom_texture)
.setSampler(sampler)
.build()
.thenAccept(texture -> {
arSceneView.getPlaneRenderer()
.getMaterial().thenAccept(material ->
material.setTexture(PlaneRenderer.MATERIAL_TEXTURE, texture));
});
Bóng
Bóng đổ khiến kết xuất đồ hoạ xuất hiện trên mặt đất trên thế giới và giúp người dùng cảm nhận được chiều sâu và không gian.
Trong Cảnh, có những đối tượng có thể truyền bóng và các đối tượng có thể nhận được bóng.
Lights
vàRenderables
có thể truyền bóngTheo mặc định, tính năng truyền bóng được bật trên mặt trời nhưng không bật được cho đèn. Hãy gọi
setShadowCastingEnabled()
để bật tính năng này.Renderables
vàPlaneRenderer
có thể nhận được bóng.Theo mặc định, tính năng nhận bóng đã được bật. Hãy gọi cho
setShadowReceiver()
để tắt.
Nếu một trình kết xuất có thể truyền và nhận bóng, thì quá trình này có thể tự truyền bóng.