ARKit add snap Picture but it causes rotation - ios

I create a project of AR app, then add on one tap gesture in view. But the picture is rotation. I found the self.sceneView.session.currentFrame.camera.transform causes the rotation, how to solve this?
- (void)handleTapGesture:(UITapGestureRecognizer *)tap {
SCNPlane * plane = [SCNPlane planeWithWidth:self.sceneView.bounds.size.width / 6000 height:self.sceneView.bounds.size.height / 6000];
UIImage * image = self.sceneView.snapshot;
plane.firstMaterial.diffuse.contents = image;
SCNNode * node = [SCNNode nodeWithGeometry:plane];
[self.sceneView.scene.rootNode addChildNode:node];
simd_float4x4 translation = matrix_identity_float4x4;
translation.columns[3][2] = -0.3;
translation = matrix_multiply(self.sceneView.session.currentFrame.camera.transform,translation);
node.simdTransform = translation;
}

I has not fond why camera transform has rotaion,but I multiply one tranform to fix it ,and it work well.
SCNMatrix4 stranslation = SCNMatrix4Translate(SCNMatrix4Identity, 0, 0, -0.3);
stranslation = SCNMatrix4Rotate(stranslation, M_PI_2, 0, 0, 1);
simd_float4x4 translation = SCNMatrix4ToMat4(stranslation);
translation = matrix_multiply(scameraTranstion,translation);

Related

Setting SCNNode's rotation with valid values, but it's always 0,0,0,0

I'm trying to set my camera node's rotation, and the value's are there, but it never changes from 0,0,0,0...
initialize the player node (left out other settings, the node has no geometry, but its physics body does have geometry)
playerNode = [SCNNode node];
and I set it's position and add it to the scene's root node...
- (void)viewDidLoad
{
[super viewDidLoad];
// create a new scene
SCNScene *scene = [SCNScene scene];
scene.physicsWorld.gravity = SCNVector3Make(0, -9, 0);
scene.physicsWorld.timeStep = 1.0/360;
// add world node
worldNode = [SCNNode node];
worldNode.name = #"world";
[scene.rootNode addChildNode:worldNode];
// add terrain
.../* terrain stuff */
// add player node
playerNode = [SCNNode node];
playerNode.name = #"player";
playerNode.position = SCNVector3Make(0, 0, 0);
playerNode.physicsBody = [SCNPhysicsBody bodyWithType:SCNPhysicsBodyTypeDynamic shape:[SCNPhysicsShape shapeWithGeometry:[SCNCylinder cylinderWithRadius:0.2 height:1] options:nil]];
playerNode.physicsBody.angularDamping = 0.9999;
playerNode.physicsBody.damping = 0.9999;
playerNode.physicsBody.rollingFriction = 0;
playerNode.physicsBody.friction = 0;
playerNode.physicsBody.restitution = 0;
playerNode.physicsBody.velocityFactor = SCNVector3Make(1, 0, 1);
playerNode.physicsBody.categoryBitMask = playerCategory;
[scene.rootNode addChildNode:playerNode];
// create and add a camera to the scene
SCNNode *cameraNode = [SCNNode node];
[playerNode addChildNode:cameraNode];
cameraNode.camera = [SCNCamera camera];
cameraNode.camera.xFov = 53;
cameraNode.camera.zNear = 0.01;
cameraNode.camera.zFar = 5000;
// place the camera
cameraNode.position = SCNVector3Make(0, 0, 0);
.../* rest of view did load */
}
and then trying to set the rotation:
-(void)lookGestureRecognized:(UIPanGestureRecognizer *)gesture {
SCNView *scnView = (SCNView *)self.view;
CGPoint translation = [gesture translationInView:self.view];
NSLog(#"lookGestureRecognized: translation x %g y %g", translation.x, translation.y);
CGFloat hAngle = acos(((float)translation.x / 200) - (float)M_PI_2);
CGFloat vAngle = acos(((float)translation.y / 200) - (float)M_PI_2);
// rotate hero
[playerNode.physicsBody applyTorque:SCNVector4Make(0, 1, 0, hAngle) impulse:YES];
// tilt camera
[SCNTransaction setAnimationDuration:0.0];
elevation = MAX((float)-M_PI_4, MIN((float)M_PI_4, elevation + vAngle));
NSLog(#"elevation: %g", elevation);
SCNVector4 cameraRotation = SCNVector4Make(1, 0, 0, elevation);
cameraNode.rotation = cameraRotation;
// cameraNode.transform = SCNMatrix4Rotate(cameraNode.transform, 1, 0, 0, elevation); // tried this, didn't work either
NSLog(#"cameraNode.rotation = x %g y %g z %g, w %g", cameraNode.rotation.x, cameraNode.rotation.y, cameraNode.rotation.z, cameraNode.rotation.w);
// reset translation
[gesture setTranslation:CGPointZero inView:self.view];
}
the elevation is being calculated correctly, but trying to set it to the node's rotation fails... the log always says 0,0,0,0...
NSLog sample output:
2015-02-17 14:37:11.732 usingGestureRecognizer.01[96111:289778] lookGestureRecognized: translation x 0 y 0.5
2015-02-17 14:37:11.733 usingGestureRecognizer.01[96111:289778] elevation: -0.785398
2015-02-17 14:37:11.733 usingGestureRecognizer.01[96111:289778] cameraNode.rotation = x 0 y 0 z 0, w 0
Any ideas?
(Side note, mimic'ing the code I found from an example, translated it from swift to obj-c, and the sample code works perfectly)
The simple answer? I'm a newb.
The actual answer? Be very careful when copying code from a tutorial... I had declared a private variable SCCNode cameraNode, and was trying to change this node's rotation, however, the actual camera node doing the camera work was declared as a private method variable in viewDidLoad...
So, again, thank you very much for your help guys, this site is invaluable to me, I have learned so much, but I'm personally 0 for 2 asking questions, both of mine have just been MY oversights. Thanks again, sincerely

figuring out the conversions from UIKit coordinates to SKScene coordinates

I am new to SpriteKit but not to iOS. I'm having a great deal of difficulty figuring out the conversions from UIKit coordinates to SKScene coordinates. In addition, their relations to the units used for the SpriteKit physics engine evades me.
Here's what I'm trying to do: I am launching a sprite with an initial velocity in both x and y directions. The sprite should start near the screen's bottom left corner (portrait mode) and leave near the bottom right corner. Another sprite should appear somewhere on the previous sprite's trajectory. This sprite is static.
The blue frame is the screen boundary, the black curve is the first sprite's trajectory and the red circle is the static sprite.
Now using the screen as 640 x 960. In my SKScene's didMoveToView: method I set the gravity as such:
self.physicsWorld.gravity = CGVectorMake(0.0f, -2.0f);
Then I make the necessary calculations for velocity and position:
"t" is time from left corner to right;
"y" is the maximum height of the trajectory;
"a" is the acceleration;
"vx" is velocity in the x direction;
"vy" is velocity in the y direction;
and
"Tstatic" is the time at which the dynamic sprite will be at the static sprite's position;
"Xstatic" is the static sprite's x-position;
"Ystatic" is the static sprite's y-position;
-(void)addSpritePair {
float vx, vy, t, Tstatic, a, Xstatic, Ystatic, y;
a = -2.0;
t = 5.0;
y = 800.0;
vx = 640.0/t;
vy = (y/t) - (1/8)*a*t;
Tstatic = 1.0;
Xstatic = vx*Tstatic;
Ystatic = vy*Tmark + 0.5*a*Tstatic*Tstatic;
[self spriteWithVel:CGVectorMake(vx, vy) andPoint:CGPointMake(xmark, ymark)];
}
-(void)spriteWithVel:(CGVector)velocity andPoint:(CGPoint)point{
SKSpriteNode *staticSprite = [SKSpriteNode spriteNodeWithImageNamed:#"ball1"];
staticSprite.anchorPoint = CGPointMake(.5, .5);
staticSprite.position = point;
staticSprite.name = #"markerNode";
staticSprite.zPosition = 1.0;
SKSpriteNode *dynamicSprite = [SKSpriteNode spriteNodeWithImageNamed:#"ball2"];
dynamicSprite.anchorPoint = CGPointMake(.5, .5);
dynamicSprite.position = CGPointMake(1 ,1);
dynamicSprite.zPosition = 2.0;
dynamicSprite.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:hoop.size.width/2];
dynamicSprite.physicsBody.allowsRotation = NO;
dynamicSprite.physicsBody.velocity = velocity;
dynamicSprite.physicsBody.affectedByGravity = YES;
dynamicSprite.physicsBody.dynamic = YES;
dynamicSprite.physicsBody.mass = 1.0f;
dynamicSprite.markerPoint = point;
dynamicSprite.physicsBody.restitution = 1.0f;
dynamicSprite.physicsBody.friction = 0.0f;
dynamicSprite.physicsBody.angularDamping = 0.0f;
dynamicSprite.physicsBody.linearDamping = 0.0f;
[self addChild:hoop];
[self addChild:marker];
}
When I execute the code, the following happens:
Can someone please help me out?

How to change anchor point?

I'm working with SceneKit. The object SCNNode is rotated relative to the center. How to change anchor point of the SCNNode?
SCNScene *scene = [SCNScene new];
SCNBox *boxGeometry = [SCNBox boxWithWidth:384.f height:512.f length:20.f chamferRadius:0];
SCNMaterial *material = [SCNMaterial new];
material.diffuse.contents = [UIImage imageNamed:#"material"];
SCNNode *boxNode = [SCNNode nodeWithGeometry:boxGeometry];
boxNode.geometry.firstMaterial = material;
boxNode.pivot = SCNMatrix4MakeTranslation(0.5f, 0.5f, 0.5f);
[scene.rootNode addChildNode:boxNode];
self.sceneView.scene = scene;
self.sceneView.allowsCameraControl = YES;
Your pivot transform translation is very small compared to the size of your box. It's not normalized.
If you want to translate around one of the corners you should translate half of the side in all directions.
boxNode.pivot = SCNMatrix4MakeTranslation(384.0/2.0, 512.0/2.0, 20.0/2.0);
As a simple example :
yourSceneNode.pivot = SCNMatrix4MakeTranslation(0.5, 0.5, 0.5),
where you change the node's position, rotation and scale properties.
SCNNode class reference explains this nicely

How to rotate a CGVector by a right angle?

I want to store direction of my sprite as CGVector,
I have only 4 possible vectors:
CGVector up = CGVectorMake(0, 100);
CGVector down = CGVectorMake(0, -100);
CGVector left = CGVectorMake(-100, 0);
CGVector right = CGVectorMake(100, 0);
and I have 2 events:
-(void) turnLeft;
-(void) turnRight;
in case that now (my_sprite.direction == CGVector(0,100)) and event turnRight happened how can I get CGVector(100, 0)???
P.S. I don't want to many if or switch statements, because in the future should be much more vectors.
Since you want the ability to use more directions in the future, It would be better to just store angle and speed.
- (void)applyDirectionChange{
CGFloat x = sinf(self.angle)*self.speed;
CGFloat y = cosf(self.angle)*self.speed;
self.direction = CGVectorMake(x,y);
}
- (void)turnRight{
self.angle += 90*M_PI/180;
[self applyDirectionChange];
}
- (void)turnLeft{
self.angle -= 90*M_PI/180;
[self applyDirectionChange];
}
if you still want to keep your constant vectors, put them in an array in the right order and have an current direction index pointing to the right vector:
//declarations
NSUInteger currentDirectionIndex;
NSUInteger numDirections;
CGVector[4] directions;
//initialize them somewhere
currentDirectionIndex = 0;
numDirections = 4;
directions[0] = up;
directions[1] = right;
directions[2] = down;
directions[3] = left;
//in your methods
- (void)turnRight{
currentDirectionIndex++;
if(currentDirectionIndex>=numDirections)
currentDirectionIndex = 0;
self.direction = directions[currentDirectionIndex];
}
- (void)turnLeft{
currentDirectionIndex--;
if(currentDirectionIndex<0)
currentDirectionIndex = numDirections-1;
self.direction = directions[currentDirectionIndex];
}
Let's rearrange your vectors into this order:
CGVector up = CGVectorMake( 0, 100);
CGVector right = CGVectorMake( 100, 0);
CGVector down = CGVectorMake( 0, -100);
CGVector left = CGVectorMake(-100, 0);
Now we can see that rotating a vector 90 degrees clockwise is the same as swapping the coordinates and then negating the Y coordinate:
CGVector vectorByRotatingVectorClockwise(CGVector in) {
CGVector out;
out.dx = in.dy;
out.dy = -in.dx;
return out;
}

while performing dual operation on UIImageView

This time I am facing problem while performing dual operation on UIImageView means
1) Zoom+Flip the Image
2)Zoom + Reverse the Image
3)Zoom + Flip or Reverse + Rotate(+- 90)deg
so please help to find out the solution of this problem. In thiscase for Zoom I use the GuestureRecognizer for fliping+Revesing+Rotating UIImageView I Use the the UIButton for these operation so how I can handle these operations wiith combination on UIImage
what exact the problem When I Zoom In or Zoom Out the image the at the same time I want to rotate (+-90 deg) or Flip or Reverse the Image at exact zoom In or Zoom Out Position but that time Image get reset then perform the respective operation such rotate, flip ,reverse I wanted to do it simultaneously on UIImage
my code as
if (btnNames == "Rotate R")
{
Angle = deg + 90;
imgview.Transform = CGAffineTransform.MakeRotation (Angle * (float)Math.PI / 180);
return Angle;
} else
{
Angle = deg - 90;
imgview.Transform = CGAffineTransform.MakeRotation (Angle * (float)Math.PI / 180);
return Angle;
}
For Reverse
CGAffineTransform transform = CGAffineTransform.MakeScale (-1, 1);
imgView.Transform = transform;
return true;
============
For Flip
if (flips == false)
{
CGAffineTransform transform = CGAffineTransform.MakeScale (1, -1);
imgView.Transform = transform;
return true;
}
this code i implemented it works fine individually perform to operation. But I want to work simultaneously on UIImage
I would recommend:
Place the UIImage in a UIScrollView with zooming setup
Modify your UIImage's Transform for reverse, rotate, etc.
To setup zooming:
yourScroller.MaximumZoomScale = 5;
yourScroller.MinimumZoomScale = 1;
yourScroller.ViewForZoomingInScrollView = _ => yourImage;
An example for rotation would be:
yourImage.Transform.Rotate (Math.PI / 2)
Play around with it, the UIScrollView should modify the same Transform on the image, so everything should work in tandem.
I'm not sure I really understand what you mean, but it sounds like your trying to do more the one transformations for an image by setting the UIView's transform property like this (example):
myView.transform = scale;
myView.transform = flip;
myView.transform = rotate;
What happens then is, that only the last one of these "is active: on the view.
What you should do is "keeping/saving" the current transformation and appending the new one with CGAffineTransformConcat like:
myView.transform = scale;
myView.transform = CGAffineTransformConcat(myView.transform, flip);
myView.transform = CGAffineTransformConcat(myView.transform,rotate);
Keep in mind that for some transformations order of concatenation matters!
Transformations can be combined by applying them to an existing transformation:
CGAffineTransform transform = CGAffineTransformIdentity;
// Rotate
if (btnNames == "Rotate R") {
Angle = deg + 90;
transform = CGAffineTransformRotate(transform, Angle * (CGFloat)Math.PI / 180);
} else {
Angle = deg - 90;
transform = CGAffineTransformRotate(transform, Angle * (CGFloat)Math.PI / 180);
}
// Reverse
transform = CGAffineTransformScale(transform, -1, 1);
// Flip
if (!flips) {
transform = CGAffineTransformScale(transform, 1, -1);
}
// Apply combined transformation
imgView.transform = transform;

Resources