Flipping a node horizontally - swift

I tried to play with scale values but it was too unreliable. Maybe I was doing something wrong. Is there a way to flip SCNNode horizontally with code?

A scale of x: -1.0, y: 1, z: 1 will mirror the node about the X Axis. This is they way that you should do it. Note that if the X Axis is not int he middle of the node, then this is going to change its position. You can translate it so that the x axis is in the middle then scale it and then translate it back if thats a problem. Its of course easier just to line up the artwork to begin with so the X axis lies on the plane where you want the mirroring to occur.

Related

Unity Rotate Sphere To Point Directly Upwards Based On Child Point

I've got a 3d sphere which I've been able to plot a point on using longitude and latitude thanks to some work of another developer I've found online. I think I understand what its doing.
What I need to do now is rotate my planet so the point is always at the top most point (ie the north pole) but I'm not sure how to do this. I'm probably missing some important fundamentals here so I'm hoping the answer can assist in my future learning.
Here's an image showing what I have - The blue line is a line coming from the longitude and latitude I have plotted and I need to rotate the planet so that line is basically pointing directly upwards.
https://ibb.co/2y24FxS
If anyone is able to advise it'd be very much appreciated.
If I'm not mistaken, Unity uses a coordinate system where the y-axis points up.
If the point on your sphere was in the xy-plane, you'd just have to determine the angle between the radius-vector (starts in the center of the sphere, ends on the point in question) and the y-axis, and than rotate by that amount around the z-axis, so that the radius vector becomes vertical. But your point is at an arbitrary location in 3D space - see the image below. So one way to go about it is to first bring the point to the xy-plane, then continue from there.
Calculate the radius vector, which is just r = x-sphereCenter. Make a copy of it, set y to zero, so that you have (x, 0, z) - which is just the projection of the vector r on the horizontal xz-plane - let's call the copy rXZ.
Determine the signed angle between the x-axis and rXZ (use Vector3.SignedAngle(xAxis, rXZ, yAxis), see docs), and create a rotation matrix M1 that rotates the sphere in the opposite direction around the vertical (negate the angle). This should place your point in the xy-plane.
Now determine the angle between r and the y-axis (Vector3.SignedAngle(r, yAxis, zAxis)), and create a new rotation matrix M2 that rotates by that angle around the zAxis. (I think for this second one, the simpler Vector3.Angle will work as well.)
So, what you want now is to combine the two matrices (by multiplying them) into a single transform (I'm assuming this is a transformation in the local coordinate system of the sphere, where (0, 0, 0) is the sphere's center). If I'm not mistaken, Unity uses column-major matrices, so the multiplication order should be M = M2 * M1 (the rightmost matrix is applied first).
Reorient your globe using M as a local transform, and it should bring your point to the top. You can also create M3 = M1.inverse, and then do M = M3 * M2 * M1, to preserve the original angular offset from the xy-plane.
Check for edge cases, such as r already being vertical (pointing straight up, or straight down).

Want to find intersecting angle (3D position) of two 3D points or Y distance

I have point A (x,y,z) and point B (x, y, z) in ARWorld. I want to keep point A horizontally parallel to B or let's say both should be on the surface.
See the image to get a better idea.
I am planning to get Y direction height or vertical height from A to B and then I will push down A by height. But how to find the height.
I want to keep A's x and z the same as it is.
Not sure how to articulate the issue, But aY - By does not work.
NOTE: A and B both are different Anchor in ARKit. Box/Mesh is on the anchor. Seems like I need global absolute world positions.
Is there any other way to get a rounded position in the image?
You say you want to get the positionA mapped down to the same "height" (Y axis) level as positionB
positionA.y = positionB.y;
it is simple as that.
Be aware that I am talking about absolute world space positions ... the values will of course be different in the Inspector since there you see only the local positions relative to the parent.
So when we are talking about GameObjects what you want to do is
var positionA = objectA.transform.position;
var positionB = objectB.transform.position;
positionA.y = positionB.y;
objectA.transform.position = positionA;
I would make an horizontal plane in B find the closest point in that plane to A and move A to that point.
Create horizontal plane:
Taking the constructor into account Plane(Vector3 inNormal, Vector3 inPoint);.
Plane myPlane = new Plane(Vector3.up, <Bpositon>)
Then with Plane.ClosestPointOnPlane you can find the closest point to A in your horizontal plane.
Vector3 closestPoint = myPlane.ClosestPointOnPlane(<APosition>);
Then you can move A to that point.
APosition = closesPoint;
Conviniently the closest point in the plane to one point is the one perpendicular to the plane, so the one "horizontally parallel" I believe you are after.

How to position and scale a triangular model by knowing its vertices in Unity3d

I want to position different equilateral triangular models, in a 3d space in unity. The problem is that the 3 known vertices aren't equilateral triangular, some of them aren't even isosceles so I need to wrap my model to match it's corners to the given vertices.
I would like to model those triangles different from each other that's why want to use pre-created models.
Currently I do the following calculation to position and scale the triangles onto a isosceles triangle:
Middle-point of the given 3 vertices
Vector3 middlepoint = (points[0]+points[1]+points[2])/3;
Distance from Middle-point
pointdistance[i] = Vector3.Distance(points[i],middlepoint);
The closest point is the one I will rotate the triangle to, so I know the triangles height (y-Axis), let's say the corner point is points[0] so float height = Vector3.Distance(points[0],middlepoint);
(I'm certain this step is wrong for a non isosceles triangle) I calculate it's width by determining the circumscribed circle radius, with the help of the remaining points
float width = (float)(Vector3.Distance(points[1] , points[2])*Math.Sqrt(3)/3);
Apply the scale to the model
float scale = new Vector3(height,width,1);
I calculate the normal normalVec of those 3 points to get the x and y orientation right, this works well so i think I don't need to change it
Instantiate the triangle
this.Triangle = (GameObject)Instantiate(standardTriangleModel,middlepoint, Quaternion.LookRotation(normalVec,points[0]));
The result looks pretty good until the triangles are not isosceles anymore
(Blue line = middlepoint to closest point, Green lines = connection between the given vertices)
So does anyone have a clue how i could position and resize my triangular models to match those points?
No code as I don't have unity handy at the moment. This answer is based on how to shear using unity gameobject transforms by trejkaz on the Unity Q&A site.
Start with gameobjects that are a right triangle of height and width 1:
Then for Triangle ABC, Set the X scale of the right triangle gameobject (which we can call mainObject) to be the length of AB, and set the Y scale to be the shortest distance between C and the line that travels through AB (the height of the triangle measured from the base AB).
Consider the angle CAB = θ.
Then, put mainObject inside of a parent gameobject called Outer1. Scale Outer1 with Y=sqrt(2)/sin(90-θ), X=sqrt(2).
Then, put Outer1 inside of a parent gameobject called Outer2. Rotate Outer2 around mainObject.forward by (θ-90) (which should be a clockwise rotation of 90-θ).
Then, put Outer2 inside of a parent gameobject called Outer3. Scale Outer3 with Y=sin((90-θ)/2), X=cos((90-θ)/2).
At this point, mainObject should be sheared and scaled into the correct shape. You will just need to position and rotate Outer3 so that the (pre-shearing) right angle corner of mainObject is at A,mainObject.right points from A to B, and mainObject.forward points normal to the triangle.

DirectX and Negative Scale

I am starting to experiment with some DirectX type stuff, and I had a question about the scaling matrices. If I set my view matrix to:
XMMatrixTranspose(XMMatrixIdentity() * XMMatrixScaling(1.0f,2.0f,1.0f))
Then everything (a centered square) on the y-axis appears twice as big, which is what I expect. If I set it to a negative number, ala:
XMMatrixScaling(1.0f,-2.0f,1.0f)
Then everything disappears. In fact, if I set any value of the scale matrix to < 0 then nothing shows up. I was expecting that the image would just be 'flipped' along the corresponding axis, but it just doesn't show up at all. Is it possible to use negative values when scaling, or am I just doing something completely wrong ??
This is caused by back-face culling and clipping. Assuming you have culling enabled (on by default), when you set the scale of the x or y axis to negative, it flips the winding order of all the triangles. This causes all the triangles to be considered "backwards" and the GPU doesn't draw them. Assuming you have no other transformation matrices applied, and the square is in the x-y plane, flipping the z sign doesn't cause the triangles to be back-facing, but rather just causes the square to be outside the viewport (e.g. moving from z = 0.5, halfway inside the veiwport depth range, to z = -0.5, outside the viewport depth range).
Back-face culling is a performance optimization since most 3D scenes have closed geometry (or at least, they don't let you see the open parts). This means that every backward facing triangle should have a front facing triangle that covers it, so there's no point in drawing the backward ones. This sometimes isn't always true though, if you've ever played a game and gotten too close to a rock or wall, and been able to see through the whole object, that's because you've clipped through the front, and since the other side is back-facing, it doesn't get drawn.

UIImage rotation axis

I want to rotate an image (UIImage) but can only do it from a default axis which is dead centre of the image ! as in Fig A. I want to move the axis to the centre of the x axis at the foot of the image as in Fig B. Can someone help me with this? I can only think of work arounds such as placing the image on an imaginary circle around the origin where the centre of the image would be where I position, then rotate the objects. This is too complicated and hopefully unneccessary. Imagine i want to place a number of images around a clock face with the origin in the centre where the clock hands originate, that's what I want to achieve. (The maths for doing this would also be appreciated).
(mid x axis and mid y axis).
Try using the view's underlying CALayer's anchorPoint property.
http://developer.apple.com/library/mac/documentation/GraphicsImaging/Reference/CALayer_class/Introduction/Introduction.html#//apple_ref/doc/uid/TP40004500-CH1-SW36
I think you can do it by first rotating using CGContextRotateCTM and then shifting that center point to the point you want it to be by using CGContextTranslateCTM
Like rotate 90 degree first to right
then shift center(x,y) to newPoint((x- width/2), (y - height/2)) here width and height are of rotated image.
I hope this helps.