我正在将Vuforia与Metal一起用于iOS(本机)。
我将“自动旋转”添加到了金属样本,并将configureVideoBackgroundWithCameraMode:
从默认“样本”添加到了“金属样本”应用程序。
但是,视频背景无法正确旋转。从初始方向旋转到其他方向时,视频背景会被分割,拉伸和镜像。
这是我的代码,只有新的片段而不是原始的金属样本中的片段:ImagetargetsMetalViewController.mm
-(void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
[self handleRotation:[[UIApplication sharedApplication] statusBarOrientation]];
}
- (void) handleRotation:(UIInterfaceOrientation)interfaceOrientation
{
dispatch_async(dispatch_get_main_queue(),^{
// ensure overlay size and AR orientation is correct for screen orientation
[self handleARViewRotation:[[UIApplication sharedApplication] statusBarOrientation]];
[self->vapp changeOrientation:[[UIApplication sharedApplication] statusBarOrientation]];
[self->metalView updateRenderingPrimitives];
});
}
- (void) handleARViewRotation:(UIInterfaceOrientation)interfaceOrientation
{
// Retrieve up-to-date view frame.
// Note that,while on iOS 7 and below,the frame size does not change
// with rotation events,// on the contray,on iOS 8 the frame size is orientation-dependent,// i.e. width and height get swapped when switching from
// landscape to portrait and vice versa.
// This requires that the latest (current) view frame is retrieved.
CGRect viewBounds = [[UIScreen mainScreen] bounds];
int smallerSize = MIN(viewBounds.size.width,viewBounds.size.height);
int largerSize = MAX(viewBounds.size.width,viewBounds.size.height);
if (interfaceOrientation == UIInterfaceOrientationPortrait ||
interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown)
{
NSLog(@"AR View: Rotating to Portrait");
CGRect viewBounds;
viewBounds.origin.x = 0;
viewBounds.origin.y = 0;
viewBounds.size.width = smallerSize;
viewBounds.size.height = largerSize;
[metalView setframe:viewBounds];
}
else if (interfaceOrientation == UIInterfaceOrientationLandscapeleft ||
interfaceOrientation == UIInterfaceOrientationLandscapeRight)
{
NSLog(@"AR View: Rotating to Landscape");
CGRect viewBounds;
viewBounds.origin.x = 0;
viewBounds.origin.y = 0;
viewBounds.size.width = largerSize;
viewBounds.size.height = smallerSize;
[metalView setframe:viewBounds];
}
}
-(void)configureVideoBackgroundWithCameraMode:(Vuforia::CameraDevice::MODE)cameraMode viewWidth:(float)viewWidthConfig andHeight:(float)viewHeightConfig {
[[self vapp]configureVideoBackgroundWithCameraMode:cameraMode viewWidth:viewWidthConfig viewHeight:viewHeightConfig];
}
SampleApplicationSession.mm
- (void) changeOrientation:(UIInterfaceOrientation) ARViewOrientation {
self.mARViewOrientation = ARViewOrientation;
CGSize arViewBoundsSize = [self getcurrentARViewBoundsSize];
int smallerSize = MIN(arViewBoundsSize.width,arViewBoundsSize.height);
int largerSize = MAX(arViewBoundsSize.width,arViewBoundsSize.height);
if (self.mARViewOrientation == UIInterfaceOrientationPortrait)
{
Vuforia::onSurfaceChanged(smallerSize,largerSize);
Vuforia::setRotation(Vuforia::ROTATE_IOS_90);
}
else if (self.mARViewOrientation == UIInterfaceOrientationPortraitUpsideDown)
{
Vuforia::onSurfaceChanged(smallerSize,largerSize);
Vuforia::setRotation(Vuforia::ROTATE_IOS_270);
}
else if (self.mARViewOrientation == UIInterfaceOrientationLandscapeleft)
{
Vuforia::onSurfaceChanged(largerSize,smallerSize);
Vuforia::setRotation(Vuforia::ROTATE_IOS_180);
}
else if (self.mARViewOrientation == UIInterfaceOrientationLandscapeRight)
{
Vuforia::onSurfaceChanged(largerSize,smallerSize);
Vuforia::setRotation(Vuforia::ROTATE_IOS_0);
}
[self.delegate configureVideoBackgroundWithCameraMode:self.cameraMode
viewWidth:arViewBoundsSize.width
andHeight:arViewBoundsSize.height];
}
- (void) configureVideoBackgroundWithCameraMode:(Vuforia::CameraDevice::MODE)cameraMode viewWidth:(float)viewWidthConfig viewHeight:(float)viewHeightConfig
{
float viewWidth = viewWidthConfig;
float viewHeight = viewHeightConfig;
// Get the default video mode
Vuforia::CameraDevice& cameraDevice = Vuforia::CameraDevice::getInstance();
Vuforia::VideoMode videoMode = cameraDevice.getVideoMode(cameraMode);
// Configure the video background
Vuforia::VideoBackgroundConfig config;
config.mPosition.data[0] = 0.0f;
config.mPosition.data[1] = 0.0f;
[self performSelectorOnmainThread:@selector(updateOrientation) withObject:self waitUntilDone:YES];
if (self.mIsactivityInPortraitMode) {
float aspectRatioVideo = (float)videoMode.mWidth / (float)videoMode.mHeight;
float aspectRatioView = viewHeight / viewWidth;
if (aspectRatioVideo < aspectRatioView) {
config.mSize.data[0] = (int)videoMode.mHeight * (viewHeight / (float)videoMode.mWidth);
config.mSize.data[1] = (int)viewHeight;
}
else {
config.mSize.data[0] = (int)viewWidth;
config.mSize.data[1] = (int)videoMode.mWidth * (viewWidth / (float)videoMode.mHeight);
}
}
else {
// --- View is landscape ---
if (viewWidth < viewHeight) {
// Swap width/height: this is neded on iOS7 and below
// as the view width is always reported as if in portrait.
// On IOS 8,the swap is not needed,because the size is
// orientation-dependent; so,this swap code in practice
// will only be executed on iOS 7 and below.
float temp = viewWidth;
viewWidth = viewHeight;
viewHeight = temp;
}
// Compare aspect ratios of video and screen. If they are different we
// use the full screen size while maintaining the video's aspect ratio,// which naturally entails some cropping of the video
float aspectRatioVideo = (float)videoMode.mWidth / (float)videoMode.mHeight;
float aspectRatioView = viewWidth / viewHeight;
if (aspectRatioVideo < aspectRatioView) {
config.mSize.data[0] = (int)viewWidth;
config.mSize.data[1] = (int)videoMode.mHeight * (viewWidth / (float)videoMode.mWidth);
}
else {
config.mSize.data[0] = (int)videoMode.mWidth * (viewHeight / (float)videoMode.mHeight);
config.mSize.data[1] = (int)viewHeight;
}
}
// Calculate the viewport for the app to use when rendering
#ifdef DEBUG_SAMPLE_APP
NSLog(@"VideoBackgroundConfig: size: %d,%d",config.mSize.data[0],config.mSize.data[1]);
NSLog(@"VideoMode:w=%d h=%d",videoMode.mWidth,videoMode.mHeight);
NSLog(@"width=%7.3f height=%7.3f",viewWidth,viewHeight);
//NSLog(@"ViewPort: X,Y: %d,%d Size X,Y:%d,viewport.posX,viewport.posY,viewport.sizeX,viewport.sizeY);
#endif
// Set the config
Vuforia::Renderer::getInstance().setVideoBackgroundConfig(config);
}
- (void)updateOrientation
{
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
if (orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown)
{
self.mIsactivityInPortraitMode = YES;
}
else if (orientation == UIInterfaceOrientationLandscapeleft || orientation == UIInterfaceOrientationLandscapeRight)
{
self.mIsactivityInPortraitMode = NO;
}
}
这是一个示范: https://streamable.com/w0ock
由于我调用Vuforia :: onSurfaceChanged并更新了VideoBackground,所以我不确定该怎么做