Эта страница содержит общие советы по созданию Scene
и взаимодействию с ней.
Рендеринг сцены без дополненной реальности
Класс SceneView
позволяет визуализировать 3D-сцену, не требуя использования камеры устройства или сеанса дополненной реальности. Это полезно для предварительного просмотра 3D-объектов в приложении без дополненной реальности или предоставления альтернативных функций на устройствах, не поддерживающих дополненную реальность.
По умолчанию SceneView
не отображает изображение с камеры дополненной реальности и использует черный фон. Чтобы изменить цвет фона, вы можете либо вызвать view.setBackgroundColor()
, либо определить цвет фона в макете, как показано ниже:
<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"/>
Узел Camera
сцены размещается в начале координат (позиция 0,0,0) и направлен вперед (направление 0,0,-1). Поскольку положение и вращение камеры не привязаны к отслеживанию движения AR, вы можете изменить положение или анимировать ее, как и любой другой узел.
Camera camera = sceneView.getScene().getCamera();
camera.setLocalRotation(Quaternion.axisAngle(Vector3.right(), -30.0f));
Взаимодействия
Обработка касаний пользователя
Когда пользователь касается экрана, Sceneform передает событие касания обработчикам событий и слушателям, прикрепленным к узлам и сцене. Это поведение похоже на то, как события касания распространяются на представления и группы представлений в Android. Вот порядок распространения:
Событие отправляется любому слушателю, добавленному в
scene.addOnPeekTouchListener()
.Это похоже на
viewGroup.intercept()
, за исключением того, что слушатель касания сцены не может использовать событие.Событие передается первому узлу, с которым пересекается луч.
- Узел может использовать событие, определив набор методов
onTouchEvent()
, который возвращаетtrue
. - Если метод
onTouchEvent()
возвращаетfalse
или прослушиватель не определен, событие распространяется на родительский узел. Этот процесс продолжается до тех пор, пока событие не будет потреблено или не будет достигнута сцена.
- Узел может использовать событие, определив набор методов
Наконец, если ни один слушатель не воспользовался событием, оно передается в
scene.onTouchListener()
.
Обнаружение жестов
ArFragment
встроена поддержка жестов касания (выбора), перетаскивания (перемещения), сжатия (масштабирования) и скручивания (поворота).
Например, см. HelloSceneformActivity.java
в примере приложения HelloSceneform .
Создание пользовательских узлов
Подобно созданию пользовательских представлений Android, вы можете создавать пользовательские узлы, создавая подклассы Node
. Вот несколько ситуаций, когда вы можете захотеть создать пользовательский узел:
- Вы хотите получить доступ к событиям жизненного цикла узла, таким как
onUpdate()
,onActivate
иonDeactivate()
. - Вы хотите создать узел, состоящий из группы узлов.
- Вы дублируете много кода и можете выделить его в подкласс.
Например, см. Planet.java
в примере приложения Solar System .
Анимация узлов
Существует два способа анимации узлов:
- Используйте
ObjectAnimator
из стандартного Android Animation API. - Создайте собственный класс узла и переопределите
onUpdate()
Анимация с помощью ObjectAnimator
Вот пример, который анимирует интенсивность прожектора:
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();
Дополнительные сведения см. в разделе Анимация с помощью ObjectAnimator .
Анимация в onUpdate
Переопределите onUpdate()
узла, чтобы анимировать его от кадра к кадру. В следующем примере из Planet.java
в примерном приложении Солнечной системы информационная карточка настраивается в каждом кадре так, чтобы она смотрела на пользователя, даже когда планета вращается.
@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);
}
Добавить свет
Lights
можно прикрепить к любому узлу сцены. По умолчанию каждая сцена Sceneform включает узел Sun
, к которому подключен направленный свет.
Вы можете изменить солнце или добавить в сцену свои собственные источники света. В следующем примере добавляется прожектор:
Light spotLightYellow =
Light.builder(this, Light.Type.FOCUSED_SPOTLIGHT)
.setColor(new Color(android.graphics.Color.YELLOW))
.setShadowCastingEnabled(true)
.build();
Затем вызовите setLight()
, чтобы прикрепить его к узлу.
Настроить визуализацию плоскости
По умолчанию у сцены есть PlaneRenderer
, который выделяет Planes
, когда они были обнаружены ARCore. Это выглядит так:
Вы можете изменить материал и текстуру по умолчанию, используемые для визуализации обнаруженных плоскостей. Вот как изменить текстуру:
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));
});
Тени
Тени заставляют объекты рендеринга казаться привязанными к миру и дают пользователям ощущение глубины и пространства.
В Sceneform есть объекты, которые могут отбрасывать тени , и объекты, которые могут получать тени .
Lights
иRenderables
могут отбрасывать тениПо умолчанию отбрасывание теней включено для солнца, но не для источников света. Вызовите
setShadowCastingEnabled()
, чтобы включить его.Renderables
иPlaneRenderer
могут получать тени.По умолчанию прием теней включен. Вызовите
setShadowReceiver()
, чтобы отключить его.
Если визуализируемый объект одновременно отбрасывает и получает тени, он может отбрасывать тени на себя.