Swift CGVector Inconsistencies - ios

I am working on a SpriteKit game in which a sprite is thrown from the upper right portion of the screen and lands in about the middle. In order to propel the sprite, I am using the applyForce method. Currently, I am explicitly setting the values of the dx and dy of the vector.
Frequently, the sprite lands where I expect it to based on set dx and dy values. However, sometimes the sprite travels farther than intended.
Essentially the issue is that the sprite travels inconsistent distances when applied the same force vector. I am wondering if there is any way to counter this issue and maintain consistent results with the same applied vector.

Related

ARKit - positioning a node in the world relative to world origin

At the moment, my code loads in a 3D model, creates a node using that model, and displays the node in the scene. Setting the scale/rotation (euler angles) of the node works fine. However, I'm trying to set the position of the node relative to the world origin, and I don't want the node to be attached to a plane.
I've tried setting node.position and node.worldPosition to no avail; although the position of the node changes, when the camera moves, the node doesn't stay static, but moves about with the camera. I'm new to using ARKit, so I'm probably doing something stupid, but I can't figure out what it is that I need to do, so any help would be much appreciated.
Edit:
The weird thing is that if I set the coordinates to say SCNVector3(0, 3, 0) it's fine, but if I go over a certain number of meters away it seems to fail. Is this expected
Firstly, poor world tracking can be caused by these common issues.
Poor ligthing. Causes low number of feature points available for tracking
Lack of texture Causes low number of feature points available for tracking
Fast Movement Causes blurry images which causes tracking to fail
However, what I believe is happening in your case (which is a little more tricky to debug)... is you are most likely placing the loaded model underneath the detected horizontal plane in the scene.
In other words, you may have positioned the SCNNode using a negative Y coordinate which places the node below the horizontal detected plane and causes the model to drift around as you change the cameraView
try setting the Y position of the node to either 0 or a small positive value like 0.1 metres
node.position = SCNVector3(0, 0, -1) // SceneKit/AR coordinates are in meters
sceneView.scene.rootNode.addChildNode(node)
z = -1 places the SCNNode 1 metre in front of your cameraView.
Note: I verified this issue myself using a playground I use for testing purposes.

finding the depth in arkit with SCNVector3Make

the goal of the project is to create a drawing app. i want it so that when i touch the screen and move my finger it will follow the finger and leave a cyan color paint. i did created it BUT there is one problem. the paint DEPTH is always randomly placed.
here is the code, just need to connect the sceneView with the storyboard.
https://github.com/javaplanet17/test/blob/master/drawingar
my question is how do i make the program so that the depth will always be consistent, by consistent i mean there is always distance between the paint and the camera.
if you run the code above you will see that i have printed out all the SCNMatrix4, but i none of them is the DEPTH.
i have tried to change hitTransform.m43 but it only messes up the x and y.
If you want to get a point some consistent distance in front of the camera, you don’t want a hit test. A hit test finds the real world surface in front of the camera — unless your camera is pointed at a wall that’s perfectly parallel to the device screen, you’re always going to get a range of different distances.
If you want a point some distance in front of the camera, you need to get the camera’s position/orientation and apply a translation (your preferred distance) to that. Then to place SceneKit content there, use the resulting matrix to set the transform of a SceneKit node.
The easiest way to do this is to stick to SIMD vector/matrix types throughout rather than converting between those and SCN types. SceneKit adds a bunch of new accessors in iOS 11 so you can use SIMD types directly.
There’s at least a couple of ways to go about this, depending on what result you want.
Option 1
// set up z translation for 20 cm in front of whatever
// last column of a 4x4 transform matrix is translation vector
var translation = matrix_identity_float4x4
translation.columns.3.z = -0.2
// get camera transform the ARKit way
let cameraTransform = view.session.currentFrame.camera.transform
// if we wanted, we could go the SceneKit way instead; result is the same
// let cameraTransform = view.pointOfView.simdTransform
// set node transform by multiplying matrices
node.simdTransform = cameraTransform * translation
This option, using a whole transform matrix, not only puts the node a consistent distance in front of your camera, it also orients it to point the same direction as your camera.
Option 2
// distance vector for 20 cm in front of whatever
let translation = float3(x: 0, y: 0, z: -0.2)
// treat distance vector as in camera space, convert to world space
let worldTranslation = view.pointOfView.simdConvertPosition(translation, to: nil)
// set node position (not whole transform)
node.simdPosition = worldTranslation
This option sets only the position of the node, leaving its orientation unchanged. For example, if you place a bunch of cubes this way while moving the camera, they’ll all be lined up facing the same direction, whereas with option 1 they’d all be in different directions.
Going beyond
Both of the options above are based only on the 3D transform of the camera — they don’t take the position of a 2D touch on the screen into account.
If you want to do that, too, you’ve got more work cut out for you — essentially what you’re doing is hit testing touches not against the world, but against a virtual plane that’s always parallel to the camera and a certain distance away. That plane is a cross section of the camera projection frustum, so its size depends on what fixed distance from the camera you place it at. A point on the screen projects to a point on that virtual plane, with its position on the plane scaling proportional to the distance from the camera (like in the below sketch):
So, to map touches onto that virtual plane, there are a couple of approaches to consider. (Not giving code for these because it’s not code I can write without testing, and I’m in an Xcode-free environment right now.)
Make an invisible SCNPlane that’s a child of the view’s pointOfView node, parallel to the local xy-plane and some fixed z distance in front. Use SceneKit hitTest (not ARKit hit test!) to map touches to that plane, and use the worldCoordinates of the hit test result to position the SceneKit nodes you drop into your scene.
Use Option 1 or Option 2 above to find a point some fixed distance in front of the camera (or a whole translation matrix oriented to match the camera, translated some distance in front). Use SceneKit’s projectPoint method to find the normalized depth value Z for that point, then call unprojectPoint with your 2D touch location and that same Z value to get the 3D position of the touch location with your camera distance. (For extra code/pointers, see my similar technique in this answer.)

Move along uneven physics body with Sprite Kit

I have a physics body that is uneven but not dynamic (the terrain) and a physics body (character) that is dynamic and is on top of the terrain, and I want this character to move along the terrain simulating kind of a "walking" action where it will keep going up the terrain but it won't fall back (or move back) like a ball because of gravity, and to set a maximum tilt so that it does not tip over.
My attempt was to add a force in the direction I want the character to move but this is causing the character to fall back due to gravity, and I don't want to disable gravity because then character won't fall down when going down the terrain.
Thank you very much
this is why using a physics engine for a platforming game is very difficult and not always a great approach..
you can try sprite.physicsBody.allowsRotation = false
might help
Create SKAction to move your character to destination point or dx and dy. Run that SKAction from your character node with the runAction. Like
SKAction.moveByX(...
When the action is finished, gravity will bring the character down.
If the movement is slow, play with the character's physicsBody friction and/or mass.
You can also change the the character's physicsBody.velocity = CGVectorMake(
And your terrain will be better with edgeLoop physicsBody which won't be dynamic.
And with uneven you mean inclined but smooth? If not smooth and with edges, your character may get held up at an edge depending on center of gravity of character and if you are allowing rotation.

Dynamic physics bodies will not remain stationary

for a test, i have created two SCNBox objects, and one SCNFLoor.
I now set scene.physicsWorld.gravity = SCNVector3Make(0,-9.8,0);
I have placed one cube on the floor, and one cube on the top of the other.
All three nodes have zero rotation, and physicsBody.friction values set to 1.0.
I measure the node velocity at 3 points, : didBeginContact, didUpdateContact, and didEndContact. If the linear or angular velocity is not zero i set it to zero, along with the velocityFactor, and AngularVelocityFactor properties of each dynamic node.
Regardless of any of these points, the objects continue to move, (albeit slowly) but the problem is there.
Can someone point me in the right direction, what am i missing ? the documentation states a friction value of 1 will prevent sliding. This is clearly not the case.
I am looking for some coding help where i can either zero the node velocity before its position is updated during each cycle, or prevent the sliding from occurring.
Solution was to ensure objects were not moving in the SCNSceneRendererDelegate method :
-(void)renderer:(id)aRenderer updateAtTime:(NSTimeInterval)time
This is pre-physics simulation and you can ensure stationary objects remain stationary this way. Its not ideal but no physics simulator is.

What is this rotation behavior in XNA?

I am just starting out in XNA and have a question about rotation. When you multiply a vector by a rotation matrix in XNA, it goes counter-clockwise. This I understand.
However, let me give you an example of what I don't get. Let's say I load a random art asset into the pipeline. I then create some variable to increment every frame by 2 radians when the update method runs(testRot += 0.034906585f). The main thing of my confusion is, the asset rotates clockwise in this screen space. This confuses me as a rotation matrix will rotate a vector counter-clockwise.
One other thing, when I specify where my position vector is, as well as my origin, I understand that I am rotating about the origin. Am I to assume that there are perpendicular axis passing through this asset's origin as well? If so, where does rotation start from? In other words, am I starting rotation from the top of the Y-axis or the x-axis?
The XNA SpriteBatch works in Client Space. Where "up" is Y-, not Y+ (as in Cartesian space, projection space, and what most people usually select for their world space). This makes the rotation appear as clockwise (not counter-clockwise as it would in Cartesian space). The actual coordinates the rotation is producing are the same.
Rotations are relative, so they don't really "start" from any specified position.
If you are using maths functions like sin or cos or atan2, then absolute angles always start from the X+ axis as zero radians, and the positive rotation direction rotates towards Y+.
The order of operations of SpriteBatch looks something like this:
Sprite starts as a quad with the top-left corner at (0,0), its size being the same as its texture size (or SourceRectangle).
Translate the sprite back by its origin (thus placing its origin at (0,0)).
Scale the sprite
Rotate the sprite
Translate the sprite by its position
Apply the matrix from SpriteBatch.Begin
This places the sprite in Client Space.
Finally a matrix is applied to each batch to transform that Client Space into the Projection Space used by the GPU. (Projection space is from (-1,-1) at the bottom left of the viewport, to (1,1) in the top right.)
Since you are new to XNA, allow me to introduce a library that will greatly help you out while you learn. It is called XNA Debug Terminal and is an open source project that allows you to run arbitrary code during runtime. So you can see if your variables have the value you expect. All this happens in a terminal display on top of your game and without pausing your game. It can be downloaded at http://www.protohacks.net/xna_debug_terminal
It is free and very easy to setup so you really have nothing to lose.

Resources