- Home /
Position and rotate 3 sprites perpendicular to the edges of a triangle
Hello everyone been stuck on this for a few days now and would like some help.
What I have so far (image below) is sort of the position part of my question working just its not 100% correct plus the rotations are not quite there.
What's on the image is 3 Vertices of a triangle white spheres, 3 Red lines are centre to edge of the triangle, White line is from 0,0,0 to triangle centre, plus grey triangle grid in the shape of a sphere.
What I would like is for the 3 sprites to be rotated and positioned so its in-line with the edges so that those 3 sprites form the triangle.
Feel free to ask if you need more information.
Note: I can add my current code but its messy with different tests etc etc and probably the complete wrong way of doing things anyway, I have mainly done 2D stuff in Unity in my short time using Unity and C#. This is my first 3D project without following step by step tutorials so its a big step/milestone for me.
Perhaps I'm misunderstanding the problem, but couldn't you simply use Quaternion.LookRotation to make your sprites face the correct direction?
What I would like is for the 3 sprites to be rotated and positioned so its in-line with the edges so that those 3 sprites form the triangle.
After I saw your drawing, I was not sure of how your sprites align with the sides...how you face the normals of the sprites. Below is my original answer. i converting it to a comment since I'm not sure what you want.
Based just on the description and given a triangle defined by three points, a, b, and c, you can do:
var ab = b - a;
var bc = c - b;
var ca = a - c;
var up = Vector3.Cross(ab, bc);
var forward1 = Vector3.Cross(ab, up);
var forward2 = Vector3.Cross(bc, up);
var forward3 = Vector3.Cross(ca, up);
The three forwards can then be use with Quaternion.LookRotation() to rotate the sprites correctly. Note that I may have the parameters in the Vector3.Cross(backwards).
Thank you for the reply's VesuvianPrime and robertbu
doesn't seem to work this is the result
Looks like the x axis is pointing up I think that needs to be y, also tried various combinations so see if they were backwards or would use the y axis but no luck. $$anonymous$$ight have to change my idea so something more simplistic.
Answer by robertbu · Sep 12, 2014 at 08:20 AM
With questions like this 80% of the problem is figuring out what the person wants. Note with the code I gave you that the sprites are inline with the edges of the triangle. So let me assume that the sprites are to be parallel with the face of the triangle and that the pivot point is in the center of the sprite, and that you want the pivot point centered on each side. a, b, and c are the Vector3 positions of the triangle. sprite1, sprite2, and sprite3 are the transforms of the three sprites. The sprites will be aligned vertically...the up and down of the sprite will be aligned along the edges.
var ab = b - a;
var bc = c - b;
var ca = a - c;
var up = Vector3.Cross(ab, bc);
sprite1.position = a + 0.5 * ab;
sprite1.rotation = Quaternion.FromToRotation(Vector3.up, ab);
sprite1.rotation = Quaternion.LookRotation(-up, transform.up);
sprite2.position = b + 0.5 * bc;
sprite2.rotation = Quaternion.FromToRotation(Vector3.up, bc);
sprite2.rotation = Quaternion.LookRotation(-up, sprite2.up);
sprite3.position = c + 0.5 * ca;
sprite3.rotation = Quaternion.FromToRotation(Vector3.up, ca);
sprite3.rotation = Quaternion.LookRotation(-up, sprite3.up);
Note that if the triangles are always facing negative 'z', then the LookRotation() is not necessary.
Almost again!
I have tidied up my/your SelectATile function a bit to show you.
void SelectATile() {
Ray ray = Camera.main.ScreenPointToRay( Input.mousePosition );
Layer$$anonymous$$ask $$anonymous$$ask = 1 << 8;
if ( Physics.Raycast( ray, out hit, $$anonymous$$ask ) ) {
if ( hit.collider.tag == "Tile" ) {
Verts = hit.collider.GetComponent<$$anonymous$$eshFilter>().shared$$anonymous$$esh.vertices;
v1 = hit.collider.transform.TransformPoint( Verts[ 0 ] );
v2 = hit.collider.transform.TransformPoint( Verts[ 1 ] );
v3 = hit.collider.transform.TransformPoint( Verts[ 2 ] );
var ab = v2 - v1;
var bc = v3 - v2;
var ca = v1 - v3;
var up = Vector3.Cross( ab, bc );
TileSide1.position = v1 + 0.5f * ab;
TileSide1.rotation = Quaternion.FromToRotation( Vector3.up, ab );
TileSide1.rotation = Quaternion.LookRotation( -up, TileSide1.up );
TileSide2.position = v2 + 0.5f * bc;
TileSide2.rotation = Quaternion.FromToRotation( Vector3.up, bc );
TileSide2.rotation = Quaternion.LookRotation( -up, TileSide2.up );
TileSide3.position = v3 + 0.5f * ca;
TileSide3.rotation = Quaternion.FromToRotation( Vector3.up, ca );
TileSide3.rotation = Quaternion.LookRotation( -up, TileSide3.up );
}
}
}
If I manually edit the rotation in the scene view I can get a result like this which is.
Using rotation steps while holding down the Ctrl key, 6 on x (red) axis then 6 again on the y (green) axis. Don't know if that helps in any way with modifications to the code.
Thanks for your help on this.
If the last image represents what you are trying to achieve, then you need a combination of the logic of my first answer (comment) and this one. But before doing that, something is wrong with the second solution (answer). That is, with an anchor set to the center of the sprite, the sprites should be positioned so that the center of the sprite is at the middle of each line. $$anonymous$$y guess is that the anchor for the sprite is not middle center. If it is, we need to dig a bit deeper.
Combining the two will look something like this:
TileSide1.position = v1 + 0.5f * ab;
TileSide1.rotation = Quaternion.FromToRotation( Vector3.up, ab );
var forward1 = Vector3.Cross(ab, up);
TileSide1.rotation = Quaternion.LookRotation(forward1, TileSide1.up );
To get it to look like your picture, the anchor would need to be middle left or middle right. And as mentioned, the Cross() may be backwards (though given that sprites are two sided, you may not be able to tell). At my desktop, it would only take a few $$anonymous$$utes for me to give you an exact answer, but I'm away from my desktop for a few days.
Done it!! :D Using the same code from my comment, then reading yours about pivots and thinking about the adding of the rotation in scene view. I put the sprites as child's of Game Object's which I then gave a starting rotation value of x = 0, y = 270, z = 90 in the inspector. Resulting in this when clicking a tile.
I can not thank you enough for helping me on this.
Your answer
Follow this Question
Related Questions
transform.forward doesn't work in my code 3 Answers
An Efficient Way To Follow Transform's Position? 3 Answers
How to make Camera position Independent of its Rotation? 1 Answer
Flip over an object (smooth transition) 3 Answers
How can I have 2 transforms have the same position and rotation 0 Answers