How to create a spinnable image for iPhone/iPad? - iphone

I am really at a loss for starting this project. I have an object that I want the user to be able to flick their finger and spin on an iPhone/iPad app that I am creating, but don't really know how to do it. As an example of what I am talking about, the Elements app allows you to "spin" the element. Any thoughts?

The Elements uses OpenGL to present a 3D model. I suggest you look into OpenGL if you want a similar effect.
http://maniacdev.com/2009/04/8-great-resources-for-learning-iphone-opengl-es/
In the case of The Elements, it's not an image you're spinning, it's a 3D model.

This will spin something in a circle. However, you'll have to handle your touch events for the flick
Where angle is a CGFloat and theView is a UIView
-(void)spinViewABit
{
angle += 0.01;
if (angle > 6.283) {
angle = 0;
}
CGAffineTransform transform=CGAffineTransformMakeRotation(angle);
theView.transform = transform;
}

Related

How to do panning in Unity?

I am a beginner in Unity and I created a 3D app in Unity.
For rotate, I'm rotating the camera around the 3d model.
For pan, if I move the 3d model, I've to keep a track of the coordinates (x,y,z). But if I move the camera, since LookAt() is implemented in the rotate function, it doesn't look like the pan gesture is executed (while shifting from rotating and panning).
Can someone please suggest a solution for this problem?
If you want to pan with the object, you can do so using vector mathematics.
Example:
new Vector3 lookAt = ...;
new Vector3 offset = ...;
cameraTransform.LookAt(lookAt + offset);
if you want to change between the motions of panning and rotation, you can use a statemachine for that.
switch (state)
{
case CHANGEPAN:
// do something
break;
case CHANGEROT:
// do something
break;
}
whilst panning, if you don't want to rotate the camera at all, you'll need to do an equivalent translation to the cameras position. You can do that also with vector mathematics, since position in the transform is just a Vector3.

AVCaptureSession front camera orientation

I'm using AVCaptureSession to record video, using AVAssetWriterInput I'm writing the video to a file.
My problem is with the video orientation, using apple RosyWriter example, I can transform the AVAssetWriterInput so the video will be at the right orientation.
- (CGFloat)angleOffsetFromPortraitOrientationToOrientation:(AVCaptureVideoOrientation)orientation
{
CGFloat angle = 0.0;
switch (orientation) {
case AVCaptureVideoOrientationPortrait:
angle = 0.0;
break;
case AVCaptureVideoOrientationPortraitUpsideDown:
angle = M_PI;
break;
case AVCaptureVideoOrientationLandscapeRight:
angle = -M_PI_2;
break;
case AVCaptureVideoOrientationLandscapeLeft:
angle = M_PI_2;
break;
default:
break;
}
return angle;
}
- (CGAffineTransform)transformFromCurrentVideoOrientationToOrientation:(AVCaptureVideoOrientation)orientation
{
CGAffineTransform transform = CGAffineTransformIdentity;
// Calculate offsets from an arbitrary reference orientation (portrait)
CGFloat orientationAngleOffset = [self angleOffsetFromPortraitOrientationToOrientation:orientation];
CGFloat videoOrientationAngleOffset = [self angleOffsetFromPortraitOrientationToOrientation:self.videoOrientation];
// Find the difference in angle between the passed in orientation and the current video orientation
CGFloat angleOffset = orientationAngleOffset - videoOrientationAngleOffset;
transform = CGAffineTransformMakeRotation(angleOffset);
return transform;
}
The problem is with the front camera orientation, using this code wont work after the user change to front camera.
It seems like what cause the problem is when I'm changing the cam to front, the AVCaptureConnection changes and I get different orientation for the front cam and for the back cam.
So maybe I need to adjust to the differences between the initial orientation for back and front cam.
I dont really want to change the connection's orientation every time the user switch cams, because as Apple say it hurts performance (and indeed it looks bad when im doing it),
so instead Apple suggest to use the AVAssetWriterInput transform property to change the output orientation, but I'm not sure I can use the transform, because I want to let the user toggle the camera while recording but I cant change the transform after I start writing (it crashes)...
Any ideas how to solve this?
Since the image from front camera is mirrored you will need to mirror the transformation as well. The function to do this is simply scaling one of the dimensions with -1. Try playing around with this:
transform = CGAffineTransformConcat(CGAffineTransformMakeRotation(angle), CGAffineTransformMakeScale(1.0, -1.0));
Note possible permutations are (beside angle) X scale factor is -1 and or swapping the order of concat
EDIT: explanation
AVCaptureSession will return you the image data that do not rotate as your device does, naturally I believe that would be landscape left or right. If you need your video to have a correct orientation depending on how you are holding the device you need to apply some transform to it, in most cases it is enough to just apply some rotation. However, a front camera is a specific case because it simulates the mirror while you are still receiving non-mirrored frames. As the result to this your video seems to be up-side-down or left-side-right or all the other combinations depending on what rotation you are applying, thus as you said "I tried a lot of angles but I just cant get it right...". Again, to simulate the mirror effect you should scale one of the axis by -1.
EDIT: swapping orientation (from comments)
This is just an idea and I think it is a good one.. Do not use the asset transformation at all, do your own. Create a view with size you want your video to be, then create an image view subview to it with all the transforms, clippings and content modes you need. From the samples you get create images, set them to the image view and get layer snapshot from the view. Then send the snapshot to the asset writer.
I know what you are thinking here is "overhead". Well, I don't think so. As the views and image views do transformation on CPU same does the asset writer, so all you did is you canceled its internal transformation and used your own system. If you will try this I would very much like to hear about your results.
To get the layer image:
- (UIImage *)imageFromLayer:(CALayer *)layer {
UIGraphicsBeginImageContext([layer frame].size);
[layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return outputImage;
}
Not the easiest way, but I think it will definitely work if you intercept the frame and perform your own transforms. You don't need any UIView for that - AVFoundation allows direct access and manipulation of its frame (you can replace with your own buffer when writing to the file, if needed). The only drawback I see is performance. Even just flipping an image might be very slow on old devices and at high resolution.
If this does hurt performance, you can save the video as it is and maintain a separate array of orientations for each frame. After the video is saved, reopen it, perform transformations for each frame, and save it to a new file. I have done something similar and it does work.
On a side note, AVAssetWriterInput's transform property works only on iPhone. If, say, you record a video with AVFoundation and upload it somewhere and watch it in browser, it will have the wrong orientation. So if you're after a thorough solution, your own transformation is the way to go.
If you often do video/image processing (e.g. in this case, flipping / rotating), consider the OpenCV library. It takes some time to learn, but it's worth it.

Radial Dial in Xcode

I am trying to make an app that uses a radial dial. As an example the radial dial features as availabel in this app
http://itunes.apple.com/us/app/kitchen-dial/id448558628?mt=8&ign-mpt=uo%3D4
What I wanted to ask is what method should I use to accomplish this? Guys, I am not asking you to write the code for me what I am asking is how is this done conceptually? I mean when a user swipses left/right on the screen how does it know which radial dial to move and in which direction. I am sure there are multiple buttons and there is some image transition going on here. I need to understand the concept of making such a thing. If anyone know or has done something similar please do share your thoughts. Does apple has a sample code for this? Thank you.
The central concepts are:
Ability to rotate an image around a center point.
Ability to calculate an angle relative to the center point given an x,y coordinate.
So, to move the wheel:
On touch began:
Calculate starting angle based on x,y
On touch moved:
Calculate new angle based on x,y and subtract starting angle. This is the angle delta (or how much more to rotate the image by).
To register button taps on the wheel:
On tap:
Calculate angle based on x,y, add existing rotation, divide by the angle size of each segment to get an index.
You asked for a high-level explanation of the concepts - and that's pretty much it.
This is a complicated question. The simple answer is: use a pan gesture recognizer, with:
- (void)panBegan:(UIPanGestureRecognizer *)pan {
CGRect frame = [self frame];
_central = CGPointMake(frame.origin.x+frame.size.width/2, frame.origin.y+frame.size.height/2);
CGPoint p = [pan locationInView:[self superview]];
p.x -= _central.x;
p.y -= _central.y;
_angle = atan2(p.x, p.y);
}
- (void)panMoved:(UIPanGestureRecognizer *)pan {
CGPoint p = [pan locationInView:[self superview]]];
p.x -= _central.x;
p.y -= _central.y;
CGFloat deltaAngle = _angle - atan2(p.x, p.y);
self.transform = CGAffineTransformMakeRotation(deltaAngle + _finalAngle);
}
where _angle is angle of the initial touch of the pan, and _finalAngle is saved angle at the end of the previous pan.
But: the UIPanGestureRecognizer has a velocity property, and you should be using it at the end of the pan to continue the rotation, as if the dial had inertia. And, if the dial has a fixed integer set of legal stopping positions, then you must adjust the slowdown curve so it stops on a legal stop. And, if you animate the deceleration, and the user starts a new pan before the previous one is finished, then you have to adjust _finalAngle based on the perceived position, not the stored position.
Here is a list of rotary knobs that are open source, so you can look at the code and see whats involved:
http://maniacdev.com/2011/12/open-source-libraries-for-easily-adding-rotary-knob-controls-in-your-ios-apps/

Image stretching

I want Stretch a image. For that i use sprite. I want stretch sprite & this stretching is may be Circular or curve animation. I don't understand what methode used for that. Can anyone help me?
Since you tagged your question with cocos2d I guess you'll be using that. It's really basic to strech an image
Sprite *mySprite = [Sprite spriteWithFile:#"mysprite.png"];
mySprite.position = ccp(100, 100);
mySprite.scale = 2.0;
[self addChild:mySprite];
If you want to animate it you can use the cocos2d actions or just create your own animation. The example below does a linear animation to 3x original sprite size in 1 second:
id action1 = [ScaleTo actionWithDuration:1.0 scale:3.0];
[mySprite runAction: action1];
For manipulating views and images in general in ways such as streching you can read up on transforms provided by the sdk, you can learn about 2D transforms here http://developer.apple.com/iphone/library/documentation/GraphicsImaging/Conceptual/drawingwithquartz2d/dq_affine/dq_affine.html and you can extend that further to 3D by manipulating the layers transforms instead of the views transforms. Youll be able to do things such as scaling and rotating and you can define your own transforms as well. This example project http://developer.apple.com/iphone/library/samplecode/MoveMe/ is a good reference to get started with transforms and animating them.

Upside-down interface for iPhone

I want to have a completely upside down interface. I don't mean it should change according to the orientation of the phone. I mean it should be upside down ( UIInterfaceOrientationPortraitUpsideDown ) the whole time. A button should be able to 'right' it again. The same button should return everything to upside down.
What's the best way of achieving this?
Set the transform attribute on the root view's layer. Something like:
bool upsideDown = ...
float degrees = upsideDown ? 180.0f : 0.0f;
NSNumber* radians = [NSNumber numberWithFloat:degrees * M_PI / 180.0f];
[rootView.layer setValue:radians forKeyPath:#"transform.rotation.z"];
(Of course, you could easily optimize out the little formula converting from degrees to radians since you only use 0.0 and pi. Included it just for clarity.)
If you want an upside-down interface, orientation does not matter. In essence, apply a rotated affine transform to the view you use, such as:
window.transform = CGAffineTransformRotate(window.transform, M_PI);
Some offset will be required there if you have a status bar up there. Apply that again and you "rotate" it back.
I would look into two options:
Rotating the Canvas 180 degrees
Inverting the accelerometer
Not sure how to accomplish either task, but a quick Google search displayed some results.
http://www.tuaw.com/2007/09/10/iphone-coding-using-the-accelerometer/
iPhone dev - Manually rotate view
http://iphonedevelopmentbits.com/how-to-make-your-iphone-application-accelerometer-rotation-aware/
How can I rotate an image in response to the iPhone's accelerometer?