adb uninstall com.oculus.sdk.xrface cd XrSamples/XrFace/Projects/Android ../../../../gradlew installDebug
Visual означает, что движения лица оцениваются на основе данных с камер, направленных внутрь, и дополнительных данных с микрофона. Audio означает, что движения лица оцениваются только на основе данных с микрофона.
XR_FB_face_tracking2 представляет расширение для предоставления выходных данных лица. Оно отбирает изображения с пользовательских датчиков и выдает веса блендшейпа, соответствующие действию в различных областях лица. Мы настоятельно рекомендуем выбирать XR_FB_face_tracking2, а не устаревшее расширение XR_FB_face_tracking, поскольку расширение XR_FB_face_tracking не поддерживает отслеживание языка и отслеживание мимики с помощью звука. Информацию о старом расширении XR_FB_face_tracking см. на сайте Khronos OpenXR Registry.RECORD_AUDIO, если вы хотите, чтобы движения мимики оценивались по звуку с микрофона.<manifest xmlns:android="http://schemas.android.com/apk/res/android" ><!-- Tell the system this app can handle face tracking --><uses-feature android:name="oculus.software.face_tracking" android:required="true" /><uses-permission android:name="com.oculus.permission.FACE_TRACKING" /><!-- Tell the system this app can use audio for face tracking --><uses-permission android:name="android.permission.RECORD_AUDIO" /><!-- Tell the system this app can handle eye tracking --><uses-feature android:name="oculus.software.eye_tracking" android:required="true" /><uses-permission android:name="com.oculus.permission.EYE_TRACKING" /> .... </manifest>
com.oculus.permission.EYE_TRACKING, com.oculus.permission.FACE_TRACKING и android.permission.RECORD_AUDIO — это разрешения среды выполнения, поэтому приложение должно явно запросить у пользователя предоставление разрешения. Подробнее о разрешениях см. в разделе Разрешения среды выполнения. В следующем примере показано, как это можно сделать. private static final String PERMISSION_FACE_TRACKING = "com.oculus.permission.FACE_TRACKING";
private static final String PERMISSION_EYE_TRACKING = "com.oculus.permission.EYE_TRACKING";
private static final String PERMISSION_RECORD_AUDIO = "android.permission.RECORD_AUDIO";
private static final int REQUEST_CODE_PERMISSION_FACE_AND_EYE_TRACKING = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestFaceAndEyeTrackingPermissionIfNeeded();
}
private void requestFaceAndEyeTrackingPermissionIfNeeded() {
List<String> permissionsToRequest = new ArrayList<>();
if (checkSelfPermission(PERMISSION_EYE_TRACKING) != PackageManager.PERMISSION_GRANTED) {
permissionsToRequest.add(PERMISSION_EYE_TRACKING);
}
if (checkSelfPermission(PERMISSION_FACE_TRACKING) != PackageManager.PERMISSION_GRANTED) {
permissionsToRequest.add(PERMISSION_FACE_TRACKING);
}
if (checkSelfPermission(PERMISSION_RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
permissionsToRequest.add(PERMISSION_RECORD_AUDIO);
}
if (!permissionsToRequest.isEmpty()) {
String[] permissionsAsArray =
permissionsToRequest.toArray(new String[permissionsToRequest.size()]);
requestPermissions(permissionsAsArray, REQUEST_CODE_PERMISSION_FACE_AND_EYE_TRACKING);
}
}
XrInstance instance; XrSystemId system; XrSession session; XrSpace sceneSpace;
SampleXrFramework/Src/XrApp.h.SampleXrFramework/Src/XrApp.cpp.XrInstance:std::vector<const char*> extensions;
XrInstance instance = XR_NULL_HANDLE;
XrInstanceCreateInfo instanceCreateInfo = {XR_TYPE_INSTANCE_CREATE_INFO};
....
instanceCreateInfo.enabledExtensionCount = extensions.size();
instanceCreateInfo.enabledExtensionNames = extensions.data();
....
OXR(initResult = xrCreateInstance(&instanceCreateInfo, &instance));
SampleXrFramework/Src/XrApp.cpp.#include <openxr/openxr.h>
XrSession Session;
XrSpace StageSpace;
SampleXrFramework\Src\XrApp.h.XR_FB_FACE_TRACKING2_EXTENSION_NAME в качестве имени расширения.XR_FB_EYE_TRACKING_SOCIAL_EXTENSION_NAME вместе с XR_FB_FACE_TRACKING2_EXTENSION_NAME, иначе блендшейпы для глаз EYES_LOOK_* не будут предоставлены.XrInstance необходимо получить системные свойства, вызвав функцию xrGetSystemProperties, чтобы это проверить.XrSystemFaceTrackingProperties2FB, которая описывает, поддерживает ли система отслеживание движений глаз. Ниже приводится определение.typedef struct XrSystemFaceTrackingProperties2FB {
XrStructureType type;
void* XR_MAY_ALIAS next;
XrBool32 supportsVisualFaceTracking;
XrBool32 supportsAudioFaceTracking;
} XrSystemFaceTrackingProperties2FB;
XrSystemFaceTrackingProperties2FB. XrSystemFaceTrackingProperties2FB faceTrackingSystemProperties{
XR_TYPE_SYSTEM_FACE_TRACKING_PROPERTIES2_FB};
XrSystemProperties systemProperties{
XR_TYPE_SYSTEM_PROPERTIES, &faceTrackingSystemProperties};
OXR(xrGetSystemProperties(GetInstance(), GetSystemId(), &systemProperties));
if (faceTrackingSystemProperties.supportsAudioFaceTracking ||
faceTrackingSystemProperties.supportsVisualFaceTracking) {
// face tracking is supported!
}
supportsAudioFaceTracking структуры XrSystemFaceTrackingProperties2FB возвращает true, поддерживается отслеживание лица с помощью звука. Если поле supportsVisualFaceTracking возвращает true, устройство поддерживает отслеживание лица с помощью камер, направленных внутрь.xrGetInstanceProcAddr в спецификации OpenXR. Следующий пример демонстрирует, как это сделать. PFN_xrCreateFaceTracker2FB xrCreateFaceTrackerFB_ = nullptr;
PFN_xrDestroyFaceTracker2FB xrDestroyFaceTrackerFB_ = nullptr;
PFN_xrGetFaceExpressionWeights2FB xrGetFaceExpressionWeightsFB_ = nullptr;
OXR(xrGetInstanceProcAddr(
GetInstance(),
"xrCreateFaceTracker2FB",
(PFN_xrVoidFunction*)(&xrCreateFaceTrackerFB_)));
OXR(xrGetInstanceProcAddr(
GetInstance(),
"xrDestroyFaceTracker2FB",
(PFN_xrVoidFunction*)(&xrDestroyFaceTrackerFB_)));
OXR(xrGetInstanceProcAddr(
GetInstance(),
"xrGetFaceExpressionWeights2FB",
(PFN_xrVoidFunction*)(&xrGetFaceExpressionWeightsFB_)));
XrFaceTracker2FB для трекера отслеживания лиц. Чтобы создать и получить дескриптор XrFaceTracker2FB для трекера движения лица, необходимо вызвать функцию xrCreateFaceTracker2FB, определенную как:XrResult xrCreateFaceTracker2FB( XrSession session, const XrFaceTrackerCreateInfo2FB* createInfo, XrFaceTracker2FB* faceTracker);
xrCreateFaceTracker2FB. Следующий пример демонстрирует, как это использовать. XrFaceTracker2FB faceTracker_ = XR_NULL_HANDLE;
XrFaceTrackerCreateInfo2FB createInfo{XR_TYPE_FACE_TRACKER_CREATE_INFO2_FB};
createInfo.faceExpressionSet = XR_FACE_EXPRESSION_SET2_DEFAULT_FB;
createInfo.requestedDataSourceCount = 2;
XrFaceTrackingDataSource2FB dataSources[2] = {
XR_FACE_TRACKING_DATA_SOURCE2_VISUAL_FB,
XR_FACE_TRACKING_DATA_SOURCE2_AUDIO_FB};
createInfo.requestedDataSources = dataSources;
OXR(xrCreateFaceTracker2FB_(GetSession(), &createInfo, &faceTracker_));
com.oculus.permission.FACE_TRACKING в своем манифесте, а пользователь должен предоставить это разрешение.xrGetFaceExpressionWeights2FB сразу после возврата этого вызова, как показано в следующем разделе.XR_FACE_EXPRESSION2_COUNT_FB и XR_FACE_CONFIDENCE2_COUNT_FB. float weights_[XR_FACE_EXPRESSION2_COUNT_FB] = {};
float confidence_[XR_FACE_CONFIDENCE2_COUNT_FB] = {};
xrGetFaceExpressionWeights2FB. Эта функция получает веса и достоверности для 70 смешанных форм, которые отслеживаются трекером лица в заданный момент времени. Его определение следующее:XrResult XRAPI_CALL xrGetFaceExpressionWeights2FB( XrFaceTracker2FB faceTracker, const XrFaceExpressionInfo2FB* expressionInfo, XrFaceExpressionWeights2FB* expressionWeights);
xrGetFaceExpressionWeights2FB.XrFaceExpressionInfo2FB представляет собой параметр функции xrGetFaceExpressionWeights2FB, который описывает время, в которое запрашиваются выражения лица. Вызывающие элементы должны запрашивать время, равное прогнозируемому времени отображения кадра, для которого выполнен рендеринг. Система вернет значение с максимально близкой к запрошенной временной меткой. Всегда указывается приблизительна метка времени, чтобы вызывающий абонент мог определить, в какой степени система смогла выполнить запрос. Система применит соответствующее моделирование для предоставления выражений в это время. Определение структуры XrFaceExpressionInfo2FB представлено ниже.typedef struct XrFaceExpressionInfo2FB {
XrStructureType type;
const void* XR_MAY_ALIAS next;
XrTime time;
} XrFaceExpressionInfo2FB;
XrFaceExpressionInfo2FB.XrFaceExpressionWeights2FB представляет собой параметр функции xrGetFaceExpressionWeights2FB, содержащий массивы, описывающие веса и достоверности блендшейпа отслеживания лица. Ниже приводится определение.typedef struct XrFaceExpressionWeights2FB {
XrStructureType type;
void* XR_MAY_ALIAS next;
uint32_t weightCount;
float* weights;
uint32_t confidenceCount;
float* confidences;
XrBool32 isValid;
XrBool32 isEyeFollowingBlendshapesValid;
XrFaceTrackingDataSource2FB dataSource;
XrTime time;
} XrFaceExpressionWeights2FB;
XrFaceExpressionWeights2FB.xrGetFaceExpressionWeights2FB. XrFaceExpressionWeights2FB expressionWeights{XR_TYPE_FACE_EXPRESSION_WEIGHTS2_FB};
expressionWeights.next = nullptr;
expressionWeights.weights = weights_;
expressionWeights.confidences = confidence_;
expressionWeights.weightCount = XR_FACE_EXPRESSION2_COUNT_FB;
expressionWeights.confidenceCount = XR_FACE_CONFIDENCE2_COUNT_FB;
XrFaceExpressionInfo2FB expressionInfo{XR_TYPE_FACE_EXPRESSION_INFO2_FB};
expressionInfo.time = GetPredictedDisplayTime();
OXR(xrGetFaceExpressionWeights2FB_(faceTracker_, &expressionInfo, &expressionWeights));
for (uint32_t i = 0; i < XR_FACE_EXPRESSION2_COUNT_FB; ++i) {
// weights_[i] contains one specific weight
....
}
xrDestroyFaceTracker2FB.OXR(xrDestroyFaceTracker2FB_(faceTracker_));
XR_META_face_tracking_visemes, когда вам нужны виземы в качестве временного решения, прежде чем ваша установка начнет поддерживать блендшейпы.XrInstance необходимо получить системные свойства, вызвав функцию xrGetSystemProperties, чтобы это проверить.XrSystemFaceTrackingVisemesPropertiesMETA, которая описывает, поддерживаются ли виземы системой. Ниже приводится определение.typedef struct XrSystemFaceTrackingVisemesPropertiesMETA {
XrStructureType type;
void* next;
XrBool32 supportsVisemes;
} XrSystemFaceTrackingVisemesPropertiesMETA;
XrSystemFaceTrackingVisemesPropertiesMETA faceTrackingVisemesSystemProperties{
XR_TYPE_SYSTEM_FACE_TRACKING_VISEMES_PROPERTIES_META};
XrSystemProperties systemProperties{XR_TYPE_SYSTEM_PROPERTIES,
&faceTrackingVisemesSystemProperties};
OXR(xrGetSystemProperties(instance, systemId, &systemProperties));
if (faceTrackingVisemesSystemProperties.supportsVisemes) {
// visemes are supported!
}
xrGetFaceExpressionWeights2FB, добавив XrFaceTrackingVisemesMETA к следующей цепочке структуры XrFaceExpressionWeights2FB. Определение структуры XrFaceTrackingVisemesMETA представлено ниже. Обязательно проверьте достоверность возвращаемых данных, проверив флаг isValid после вызова xrGetFaceExpressionWeights2FB.typedef struct XrFaceTrackingVisemesMETA {
XrStructureType type;
const void* next;
XrBool32 isValid;
float visemes[XR_FACE_TRACKING_VISEME_COUNT_META];
} XrFaceTrackingVisemesMETA;
xrGetFaceExpressionWeights2FB, чтобы получить виземы, а не блендшейпы. XrFaceExpressionWeights2FB expressionWeights{XR_TYPE_FACE_EXPRESSION_WEIGHTS2_FB};
expressionWeights.weightCount = 0;
expressionWeights.confidenceCount = 0;
XrFaceTrackingVisemesMETA visemeInfo{XR_TYPE_FACE_TRACKING_VISEMES_META};
expressionWeights.next = &visemeInfo;
XrFaceExpressionInfo2FB expressionInfo{XR_TYPE_FACE_EXPRESSION_INFO2_FB};
expressionInfo.time = GetPredictedDisplayTime();
OXR(xrGetFaceExpressionWeights2FB_(faceTracker_, &expressionInfo, &expressionWeights));
if (visemeInfo.isValid) {
for (uint32_t i = 0; i < XR_FACE_TRACKING_VISEME_COUNT_META; ++i) {
// visemeInfo.visemes[i] contains a weight of specific visemes
}
}
weightCount и confidenceCount допустимые значения weightCount, weights, confidenceCount и confidences, а не 0, то функция xrGetFaceExpressionWeights2FB вернет и блендшейпы, и виземы.| Визема | Фонемы | Примеры | Умеренная | Выраженная | Вращающаяся |
|---|---|---|---|---|---|
SIL | Нейтральная | ![]() | Нет | ![]() | |
PP | p, b, m | put, bat, mat | ![]() | ![]() | ![]() |
FF | f, v | fat, vat | ![]() | ![]() | ![]() |
TH | th | think, that | ![]() | ![]() | ![]() |
DD | t, d | tip, doll | ![]() | ![]() | ![]() |
KK | k, g | call, gas | ![]() | ![]() | ![]() |
CH | tS, dZ, S | chair, join, she | ![]() | ![]() | ![]() |
SS | s, z | sir, zeal | ![]() | ![]() | ![]() |
NN | n, l | lot, not | ![]() | ![]() | ![]() |
RR | r | red | ![]() | ![]() | ![]() |
AA | A: | car | ![]() | ![]() | ![]() |
E | e | bed | ![]() | ![]() | ![]() |
IH | ih | tip | ![]() | ![]() | ![]() |
OH | oh | toe | ![]() | ![]() | ![]() |
OU | ou | book | ![]() | ![]() | ![]() |