I've been trying to figure this out for six months now, and have a workable solution, but I just can't figure out how to get my model to behave exactly how I want. I'm rendering a 3D model with an arcball rotation implementation and zoom/pan functionality for the iPad, although the transformation code will be identical to that of desktop OpenGL. Currently, the user has the ability to change the center of rotation of the model by clicking on the model. The center of rotation changes, but the origin stays stationary which causes the model to move away from where the user touched the screen. What I would like it to do is allow the user to touch the model and have the model stay stationary, but have it move the origin to where the user touched. I'm not sure what transformations or the order of transformations needed to do this. The current order of transformations is:
glPushMatrix();
glTranslatef(pan.x, pan.y, 0);
glMultMatrixf(mat); //this is my rotation/scale matrix I get from my arcball class
glTranslatef(-origin.x, -origin.y, -origin.z);
//draw model
glPopMatrix();
Any idea what changes need to be made to make it so the origin moves instead of the model?
At first blush, I'd say you should shift the scene's origin to the desired rotation point before applying the rotation matrix, so that the shift happens along the global axes. then apply the rotation matrix, draw the item, and shift the origin back to the original origin for the rest of the display function (which should be taken care of in the glPopMatrix).
glPushMatrix();
glTranslatef(pan.x, pan.y, 0);
glTranslatef(-origin.x, -origin.y, -origin.z);
glMultMatrixf(mat); //this is my rotation/scale matrix I get from my arcball class
//draw model
glPopMatrix();
Related
Using SceneKit
I want to make the gray transparent box to disappear and only show the colored boxes when the user zooms in.
So I want to detect when that box's edges are starting to fall off the screen as I zoom, so I can hide the gray box accordingly.
First thoughts, but there may be better solutions:
You could do an unprojectPoint on the node and check against screen coordinates, do the +/- math on object size and skip Z. I "think" that would work
You can do some physics based collision detection against an invisible box or plane geometries that acts as your screen edges, has some complexity if your view is changing, but testing would be easy - just leave visible until you get what you want, then isVisible=false
isNode(insideFrustomof: ) - returns boolean on whether it "might" be visible. I'm assuming "might" means obscured by other geometry which in your case, shouldn't matter (edit) on second thought, that doesn't solve your problem but I'll leave it in here for reference.
I'm working on developing iOS AR application using ARKit + Core location. And the points which are displayed on the map using coordinates move from place to place when I go. But I need they are displayed on the same place.
Here you can see the example of what I mean:
https://drive.google.com/file/d/1DQkTJFc9aChtGrgPJSziZVMgJYXyH9Da/view?usp=sharing
Could you help to handle with this issue? How can I have fixed places for points using coordinates? Any ideas?
Thanks.
Looks like you attach objects to planes. However, when you move the ARKit extends the existing planes. As a result if you put points, for example, at the center of the plane, then the center is always updated. You need to recalculate the coordinates of the point and place objects correctly.
The alternative is not to add objects to planes (or in relation to them). If you need to "put" object on a plane, then the best way is to wait, until the plane will be directed enough (it will not change his direction significantly if you will move), then select a point on the plane where you want to put your object, then convert this point coordinate to global coordinates (as a result if plane will change his size the coordinate you have will not be changed at all), and finally put object in root (or another object that it's not related to the plane).
I currently have a scene which contains a central node at the root of the scene with earth-like geometry and a node representing a flying vehicle.
However I cannot find the right approach to control the movement of the vehicle. I need the ability to turn left and right while orbiting at a static altitude and speed.
I have tried many combinations of animations and physics body forces all leading to undesirable results.
The closest I've come is:
Setting the pivot property of the vehicle to the centre of the scene
Then setting an Action like below to control moving forward
[_vehicleNode runAction:[SCNAction repeatActionForever:[SCNAction rotateByX:-1 y:0 z:0 duration:10.0]]];
Then finally applying forces for turning left and right with
[_vehicleNode.physicsBody applyTorque:SCNVector4Make(0, 1, 0, 1) impulse:YES];
However I cannot seem to set the pivot and/or position to the right value to get the desired result.
Edit: It appears as the above method would be the solution I'm looking for, however for some reason when I add geometry to the vehicle node, it's position in the scene graph gets changed dramatically. When I add hardcoded buttons to change it's position to where it belongs it appears correct for only that single frame then straight back to being in the middle of nowhere.
Edit 2: After replacing all geometry with a primitive sphere for testing the node is now rotating as intended but is now unaffected by physics forces appearing to ignore it's declaration as a dynamicBody.
If I understand what you are trying to achieve correctly, you can try this:
add a first node to your scene, positioned at (0,0,0) and make it rotate forever along the Y axis using an SCNAction
add your ship node as a child of the first node. Position it at (X,0,0) so that it orbits around the earth
rotate your ship node along the X axis with an action or an animation
I'm trying to make a circular UIView animate in a particular direction until it collides with the borders of the view (which is full screen, so basically the borders of the device), at which point it will reflect off it and continue on its way infinitely. However, I'm not really sure how to pose my question, so I'm having trouble finding any information on it. I already have the view, the direction it will move in, and its velocity. I'm just not sure how to handle an animation like that.
Any advice is much appreciated! Thanks!
Use a CADisplayLink to continuously update the position of the view, synced with the refresh rate of the screen. The update method that that display link triggers will take into account the current x and y velocity of the view and update the frame based on it. If at ever point the x- or y-coordinate goes under or over a limit (0 or screen width/height), reverse the appropriate velocity value and recalculate the position.
for days now I am trying to solve this, apparently I just can't get affine transforms.
Basically, I would like to rotate a movie multiple times by 90 degrees. There is a good example here:
Rotating Video w/ AVMutableVideoCompositionLayerInstruction
but this works only for the first rotation, while I would like to rotate it from portrait to landscape, back to portrait, back to landscape.
Whatever I tried, I get absolutely weird results. Unfortunately, even after much reading, my understanding of affine transforms obviously did not improve either.
So I am basically asking for a layout of an algorithm which will
rotate the layer of an AVMutableVideoComposition by 90 degrees,
regardless of its current orientation.
Apply a translation to move the layer into the center.
This should be called each time I click on a button.
But whatever I try, the layer is rotating correctly, but the translation is moving the layer out of the center. What is the right way to do this?
But whatever I try, the layer is rotating correctly, but the translation is moving the layer out of the center. What is the right way to do this?
The right way to do this is with 2 transforms: one to rotate, and one to translate. At the beginning of the processing, make sure that your current position is set - by assigning the current transform at the start of processing. Then, create two independent transforms - one for rotate, and the other for translation. You can 'concat' these two transforms to create a new one which does both operations - but if you expect the translation to function 'in place', be sure to re-set the original transform before you apply the new one.