Grid Increment by Rotation

Working on generating a 3D GameObject Array of cubes grid-locked and angled to match the initial rotation. Although all of my objects spawn in the correct rotation, the grid itself is world-aligned.

alt text

The grid is populated by the bottom-left most grid piece and then placed accordingly.

Noteworthy Global Variables:

public float GridLength = 3.5f;
GameObject[,,] Grid;
Vector3 Rotation = Vector3.zero;
Vector3 PointA = Vector3.zero;
Vector3 PointB = Vector3.zero;

Important Snippet (in Update)

// Gridlock scale to point B
                                int a = Mathf.RoundToInt((PointB.x-PointA.x)/GridLength),               // difference in X length
                                        b = Mathf.RoundToInt((PointB.y-PointA.y)/GridLength)+1, // difference in Y length
                                        c = Mathf.RoundToInt((PointB.z-PointA.z)/GridLength);           // difference in Z length
                                if (Grid.Length != a*b*c && (Mathf.Abs(a*b*c) > 0)) {
                                        Debug.Log("Size Changed. Grid["+a+","+b+","+c+"]");
                                        // clear grid
                                        foreach(GameObject o in Grid) {
                                                Destroy (o);
                                        }
                                        // repopulate grid
                                        Grid = new GameObject[Mathf.Abs(a),Mathf.Abs(b),Mathf.Abs(c)];
                                        for (int k = Mathf.Min(0, c+1); k < Mathf.Max(c, 0); k ++) {
                                                for (int j = Mathf.Min(0, b+1); j < Mathf.Max(b, 0); j ++) {
                                                        for (int i = Mathf.Min(0, a+1); i < Mathf.Max(a, 0); i ++) {
                                                                try {
                                                                        Grid[Mathf.Abs(i),Mathf.Abs(j),Mathf.Abs(k)] = GameObject.Instantiate(Prefab, PointA+new Vector3(i*GridLength, j*GridLength, k*GridLength), Quaternion.Euler(Rotation)) as GameObject;
                                                                        Grid[Mathf.Abs(i),Mathf.Abs(j),Mathf.Abs(k)].transform.GetComponent<BoxCollider>().enabled = false;
                                                                } catch {
                                                                        Debug.LogError("Error creating Grid["+Mathf.Abs(i)+","+Mathf.Abs(j)+","+Mathf.Abs(k)+"]");
                                                                }
                                                        }
                                                }
                                        }

I need to align this based on the Rotation vector (EulerAngles).

You can handle this in a couple of different ways. Given a pivot point for all of your quads called ‘pivotPoint’, you can change the position this way:

Vector3 newPos = Quaternion.Euler(-Rotation) * (oldPos - pivotPoint) + pivotPoint;

You can either do this to the transform.position of each object after you instantiate the object, or you can do it to the position you calculate before the Instantiate() call. I’m using ‘-Rotation’ because you want the whole group to be rotated in the opposite direction you are using for the individual quads. For example using your code above, you could do:

Vector3 pos = PointA+new Vector3(i*GridLength, j*GridLength, k*GridLength);
pos = Quaternion.Euler(-Rotation) * (pos - pivotPoint) + pivotPoint;
Grid[Mathf.Abs(i),Mathf.Abs(j),Mathf.Abs(k)] = GameObject.Instantiate(Prefab, pos, Quaternion.Euler(Rotation)) as GameObject;

Another solution would be to place an empty game object at the pivot point, then make all the objects children of the empty game object. By rotating the empty game object, all the children will be rotated.

There were actually 2 problems aligned with this question, but your solution would surely work for one. First, the Grid jumps are world locked, not local. Next, the gameobjects were being placed on world jumps, not local.

The first solution was given on #Unity3D:

Grid[Mathf.Abs(i),Mathf.Abs(j),Mathf.Abs(k)] = GameObject.Instantiate(Prefab, PointA+new Vector3(i*GridLength, j*GridLength, k*GridLength), Quaternion.Euler(Vector3.zero)) as GameObject;
Grid[Mathf.Abs(i),Mathf.Abs(j),Mathf.Abs(k)].transform.RotateAround(PointA, Vector3.up, Rotation.y);

This generates the item at world grid coordinates, and then pivots off of the start point. Your option would certainly work in this scenario as well. The next problem was with A,B,C. I have to walk North in jumps to increase Z count, East for X, and vertical for Y. Well, there’s no rotation on Y, so that was fine there. What I got so far was something like this:

float dist = Vector3.Distance(PointB, PointA);
float angle = Mathf.Atan2(PointB.z - PointA.z, PointB.x-PointA.x);
	//angle += Rotation.y;
Vector3 diff = new Vector3(
	(Mathf.Cos(angle)*dist),
	PointB.y-PointA.y,
	(Mathf.Sin(angle)*dist));
// Gridlock scale to point B
int a = (int)Mathf.Round(diff.x / GridLength),		// difference in X length
	b = (int)Mathf.Round(diff.y / GridLength),	// difference in Y length
	c = (int)Mathf.Round(diff.z / GridLength);		// difference in Z length
if (Mathf.Abs(a) < 1) a = 1; if (Mathf.Abs(b) < 1) b = 1; if (Mathf.Abs(c) < 1) c = 1;

First, grab the distance from start to end. Next, reverse check for the angle. Use trig, using distance as the Hypotenuse, to find the X/Y offset on those coordinates. This swaps North/East to Forward/Right. Still some minor tweaks to perform before I can move forward.