On QCAR iOS 1.5 with the UIView attached to the target and autorotated:
We're going to demonstrate drawing a view at each of the corner points of a target, and a scaled view central to the target, all of which will stay oriented correctly.
Create a subclass of ARParentViewController (CornerTrackingVC) to insert a new layer between the ARView and the popup Overlay View:
#import <UIKit/UIKit.h>
#import "ARParentViewController.h"
@interface CornerTrackingVC : ARParentViewController
{
UIView *s0V;
UIView *s1V;
UIView *s2V;
UIView *s3V;
UIView *centreV;
}
@property (nonatomic, assign) UIView *s0V;
@property (nonatomic, assign) UIView *s1V;
@property (nonatomic, assign) UIView *s2V;
@property (nonatomic, assign) UIView *s3V;
@property (nonatomic, assign) UIView *centreV;
@end
And:
#import <QuartzCore/QuartzCore.h>
#import "CornerTrackingVC.h"
#import "ARViewController.h"
#import "OverlayViewController.h"
@implementation CornerTrackingVC
@synthesize s0V;
@synthesize s1V;
@synthesize s2V;
@synthesize s3V;
@synthesize centreV;
- (void) loadView
{
NSLog(@"ARParentVC: creating");
parentView = [[UIView alloc] initWithFrame:arViewRect];
parentView.autoresizesSubviews = YES;
// Add the EAGLView and the overlay view to the window
arViewController = [[ARViewController alloc] init];
// need to set size here to setup camera image size for AR
arViewController.arViewSize = arViewRect.size;
[parentView addSubview:arViewController.view];
// These are the four corner points
CGRect frame = {0,0,4,4};
s0V = [[UIView alloc] initWithFrame:frame];
s1V = [[UIView alloc] initWithFrame:frame];
s2V = [[UIView alloc] initWithFrame:frame];
s3V = [[UIView alloc] initWithFrame:frame];
s0V.backgroundColor = [UIColor redColor];
s1V.backgroundColor = [UIColor greenColor];
s2V.backgroundColor = [UIColor blueColor];
s3V.backgroundColor = [UIColor yellowColor];
// And this is the centre-piece
centreV = [[UIView alloc] initWithFrame:CGRectMake(20, 50, 4, 4)];
centreV.backgroundColor = [UIColor orangeColor];
[parentView addSubview:centreV];
// Create a container that is correctly resized and rotated
frame = CGRectMake(0, 0, arViewRect.size.width, arViewRect.size.height);
UIView *cornerTrackingV = [[UIView alloc] initWithFrame:frame];
[cornerTrackingV addSubview:s0V];
[cornerTrackingV addSubview:s1V];
[cornerTrackingV addSubview:s2V];
[cornerTrackingV addSubview:s3V];
cornerTrackingV.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[parentView addSubview:cornerTrackingV];
// Create an auto-rotating overlay view and its view controller (used for
// displaying UI objects, such as the camera control menu)
overlayViewController = [[OverlayViewController alloc] init];
[parentView addSubview: overlayViewController.view];
self.view = parentView;
}
- (void)dealloc
{
self.s0V = nil;
self.s1V = nil;
self.s2V = nil;
self.s3V = nil;
self.centreV = nil;
[super dealloc];
}
In the app delegate, hold the coordinates and ref the subclass:
#import <UIKit/UIKit.h>
@class CornerTrackingVC;
@interface ImageTargetsAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow* window;
CornerTrackingVC* cornerTrackingVC;
UIImageView *splashV;
@public
CGPoint s0;
CGPoint s1;
CGPoint s2;
CGPoint s3;
CGPoint centre;
}
@property (nonatomic) CGPoint s0;
@property (nonatomic) CGPoint s1;
@property (nonatomic) CGPoint s2;
@property (nonatomic) CGPoint s3;
@property (nonatomic) CGPoint centre;
@end
Set up the subclass in place of ARParentViewController, and add a timer for the animation:
// Add the EAGLView and the overlay view to the window
cornerTrackingVC = [[CornerTrackingVC alloc] init];
cornerTrackingVC.arViewRect = screenBounds;
[window insertSubview:cornerTrackingVC.view atIndex:0];
[window makeKeyAndVisible];
[NSTimer scheduledTimerWithTimeInterval:0.04 target:self selector:@selector(moveCorners:) userInfo:NULL repeats:YES];
And add the method to manipulate the views per time period, using the target coordinates:
- (void)moveCorners:(NSTimer*)theTimer
{
// move each of the corner 'tags'
CGRect frame = CGRectMake(s0.x, s0.y, 4, 4);
cornerTrackingVC.s0V.frame = frame;
frame = CGRectMake(s1.x, s1.y, 4, 4);
cornerTrackingVC.s1V.frame = frame;
frame = CGRectMake(s2.x, s2.y, 4, 4);
cornerTrackingVC.s2V.frame = frame;
frame = CGRectMake(s3.x, s3.y, 4, 4);
cornerTrackingVC.s3V.frame = frame;
// simplistically make the scale the average of the two diagonals
// we could extract the scale from the pose
CGFloat diag1 = sqrtf(powf(s0.x-s2.x,2.0) + powf(s0.y-s2.y,2.0));
CGFloat diag2 = sqrtf(powf(s1.x-s3.x,2.0) + powf(s1.y-s3.y,2.0));
// draw a 4:3 rectangle scaled to the target
frame.size.width = (diag1 + diag2)/2 / 2.0;
frame.size.height = frame.size.width * 3.0/4.0;
frame.origin.x = centre.x - frame.size.width/2;
frame.origin.y = centre.y - frame.size.height/2;
cornerTrackingVC.centreV.frame = frame;
}
In the EAGLView add methods that calculate the correct positions of target points, accounting for the screen orientation:
- (CGPoint) projectCoord:(CGPoint)coord inView:(const QCAR::CameraCalibration&)cameraCalibration andPose:(QCAR::Matrix34F)pose withOffset:(CGPoint)offset andScale:(CGFloat)scale
{
CGPoint converted;
QCAR::Vec3F vec(coord.x,coord.y,0);
QCAR::Vec2F sc = QCAR::Tool::projectPoint(cameraCalibration, pose, vec);
converted.x = sc.data[0]*scale - offset.x;
converted.y = sc.data[1]*scale - offset.y;
return converted;
}
- (CGPoint) toPortrait:(CGPoint) coord
{
CGPoint newCoord;
newCoord.x = self.frame.size.width - coord.y;
newCoord.y = coord.x;
return newCoord;
}
- (CGPoint) toPortraitUD:(CGPoint) coord
{
CGPoint newCoord;
newCoord.x = coord.y;
newCoord.y = self.frame.size.height - coord.x;
return newCoord;
}
- (CGPoint) toLandscapeLeft:(CGPoint) coord
{
CGPoint newCoord;
newCoord.x = self.frame.size.width - coord.x;
newCoord.y = self.frame.size.height - coord.y;
return newCoord;
}
- (void) calcScreenCoordsOf:(CGSize)target inView:(CGFloat *)matrix inPose:(QCAR::Matrix34F)pose
{
// 0,0 is at centre of target so extremities are at w/2,h/2
CGFloat w = target.width/2;
CGFloat h = target.height/2;
// need to account for the orientation on view size
CGFloat viewWidth = self.frame.size.height; // Portrait
CGFloat viewHeight = self.frame.size.width; // Portrait
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
if (UIInterfaceOrientationIsLandscape(orientation))
{
viewWidth = self.frame.size.width;
viewHeight = self.frame.size.height;
}
// calculate any mismatch of screen to video size
QCAR::CameraDevice& cameraDevice = QCAR::CameraDevice::getInstance();
const QCAR::CameraCalibration& cameraCalibration = cameraDevice.getCameraCalibration();
QCAR::VideoMode videoMode = cameraDevice.getVideoMode(QCAR::CameraDevice::MODE_DEFAULT);
CGFloat scale = viewWidth/videoMode.mWidth;
if (videoMode.mHeight * scale < viewHeight)
scale = viewHeight/videoMode.mHeight;
CGFloat scaledWidth = videoMode.mWidth * scale;
CGFloat scaledHeight = videoMode.mHeight * scale;
CGPoint margin = {(scaledWidth - viewWidth)/2, (scaledHeight - viewHeight)/2};
// now project the 4 corners of the target
ImageTargetsAppDelegate *delegate = [[UIApplication sharedApplication] delegate];
delegate.s0 = [self projectCoord:CGPointMake(-w,h) inView:cameraCalibration andPose:pose withOffset:margin andScale:scale];
... ditto for s1-s3 and centre using (-w,-h), (w,-h), (w,h) and (0,0) ...
// correct the coordinates for screen orientation
switch (orientation) {
case UIInterfaceOrientationPortrait:
delegate.s0 = [self toPortrait:delegate.s0];
delegate.s1 = [self toPortrait:delegate.s1];
delegate.s2 = [self toPortrait:delegate.s2];
delegate.s3 = [self toPortrait:delegate.s3];
delegate.centre = [self toPortrait:delegate.centre];
break;
case UIInterfaceOrientationPortraitUpsideDown:
delegate.s0 = [self toPortraitUD:delegate.s0];
delegate.s1 = [self toPortraitUD:delegate.s1];
delegate.s2 = [self toPortraitUD:delegate.s2];
delegate.s3 = [self toPortraitUD:delegate.s3];
delegate.centre = [self toPortraitUD:delegate.centre];
break;
case UIInterfaceOrientationLandscapeLeft:
delegate.s0 = [self toLandscapeLeft:delegate.s0];
delegate.s1 = [self toLandscapeLeft:delegate.s1];
delegate.s2 = [self toLandscapeLeft:delegate.s2];
delegate.s3 = [self toLandscapeLeft:delegate.s3];
delegate.centre = [self toLandscapeLeft:delegate.centre];
break;
default:
break;
}
}
And in renderFrameQCAR add the code to the loop over detected trackables:
CGSize target = {247,173};
[self calcScreenCoordsOf:target inView:&modelViewProjection.data[0] inPose:trackable->getPose()];
Download vuforia-videoplayback-is-1-0-2.zip and try it......thats the thing u r searching....