Nested For Loop Confusion
Hello,
I would appreciate anyones help on this nested for loop problem I'm having - I can't seem to get my head around it, and I need a fresh pair of eyes to take a look for me.
Explanation
I have a simple float array that is actually a broken down image data that has a total Length of 217,088 (pixels essentially). The original image rect is 512 x 424 before it's externally broken down into this single float array.
I also have 4 Meshes, each mesh is 128 x 424 along the X axis, which give a total mesh coverage of 512 x 424. (each mesh has a vertex count of 54,272. [4 * 54,272 = 217,088] : Same length as my array/pixels).
Each vertex in my Mesh represents a Pixel in the image array. However, the Image array is 1D, and the Mesh Array is 2D
Problem
I'm trying to match the ImageArray (well the data) with the Mesh. A Pixel for a Vertex But because there are a mesh in 4 columns, it's confusing me :/
The entire ImageArray is fed into each Mesh Object, which has its own script attached to it that tries to 'convert' the 1D into 2D, with respect to the Mesh Object. But my for loops appears to be wrong, as I don't get the correct outcome.
This script is attached to all 4 of the MeshObjects, and is called every frame with the entire ImageArray being fed into it:
public void UpdateMesh(double[] _data){
int i = 0;
for(int _y = 0; _y < height; _y++){
for(int _x = 0; _x < width; _x++){
//int index = (_y * width) + _x;
int point_index = (_y ) + (x + _x);
double point = _data[point_index];
points[i] = new Vector3(_x, _y, (float)point);
i++;
}
}
_Mesh.vertices = points;
}
Where 'y' always equals zero, and 'x' equals 0 on the Mesh 0. 128 on the Mesh 1. 256 on the Mesh 2. And 384 on the Mesh 3. (It just progresses in 128 each time as the mesh is moving along the X axis). I think its more my '_Y' loop that is causing the issue. I'm not sure?!
Answer by oliver-jones · May 12, 2016 at 11:26 PM
I solved it.
First of all - instead of having columns of mesh, I made rows instead - as that seems like a more easier way.
As mentioned before, each of my rows of mesh has a Script attached to it, with a function called 'UpdateMesh' which is called every frame, and has the entire ImageArray passed to it.
public void UpdateMesh(double[] _data){
for(int _y = 0; _y < height; _y++){
for(int _x = 0; _x < width; _x++){
int index = (_y * width) + _x;
int point_index = (height * width) * chunkIndex;
double point = _data[ index + point_index ];
points[index] = new Vector3(points[index].x, points[index].y, (float)point);
}
}
_Mesh.vertices = points;
}
Where 'width' is the width of the mesh, where in this case it's now the entire width of the image too which is 512 (as the mesh is now Row by Row, not Col by Col).
And 'height' is the height of the mesh which is 106 (424 / 4 of the entire image).
And 'chuckIndex' is the index given to each mesh in order (0 to 3);
Answer by Bunny83 · May 12, 2016 at 10:00 PM
Well, your code is missing conceptionally those 4 meshes. Your point_index calculation seems strange. First because we don't know what "x" actually is and second image data is usually layed out row by row in a flattened array, so your commented "index" is the right way to calculate the index into the image data array.
How you manage your 4 meshes is up to you. You don't necessarily need to process the image row by row. You can process it column by column as well. That way you would work on one mesh at a time, however if you store all 4 vertices arrays anyways it doesn't matter how you process the image.
Vector3[][] verts = new Vector3[4][];
for(int i = 0; i < verts.Length; i++)
{
verts[i] = new Vector3[128*height];
}
for(int _y = 0; _y < height; _y++)
{
for(int _x = 0; _x < width; _x++)
{
int index = (_y * width) + _x;
float point = (float)_data[index];
verts[_x / 128][(_x%128) + _y*width] = new Vector3(_x, _y, point);
}
}
for(int i = 0; i < verts.Length; i++)
{
Mesh m = _Meshes[i];
m.vertices = verts[i];
// calculate / assign triangles here
}
Another way would be to iterate the pixels column by column. That way you can process one mesh at a time:
for (int i = 0; i < 4; i++)
{
Vector3[] verts = new Vector3[128*height ];
for(int _x = 0; _x < 128; _x++)
{
for(int _y = 0; _y < height; _y++)
{
int index = (_y * width) + _x + 128*i;
float point = (float)_data[index];
verts[_x + _y*width] = new Vector3(_x + 128*i, _y, point);
}
}
_Meshes[i].vertices = verts;
// assign triangles for the mesh here
}
Since you use the absolute _x and _y coordinates all your 4 $$anonymous$$esh GameObjects finally need to be placed at the same position. Just attaching them as a child to another GameObject would make the most sense. In the second approach you could remove the +128*i
from line 10 so each mesh has the same local coordinates (0-128). In that case you want to offset the 4 mesh objects from each other by 128 on the x axis. That way the pivot of every "stripe" is at the stripes lower corner. It makes no visual difference but they may be easier to manage in the editor.
It's not clear what all this is actually good for. I guess it should be some kind of height map. Using Unity's Terrain system could save you alot of trouble in this case. At the moment you don't take into acount that each stripe should end where the next begins. So to have a seamless surface you have to duplicate the vertices at the connecting edges since you can't define triangles between vertices that belong to different meshes. So the first 3 stripes would need 129 vertices and the last 128 since there are 3 connecting edges between those 4 stripes.
Again, it's a lot easier to use Unity's Terrain system if you plan something like that.
Thanks. The code I showed above is what's attached to all 4 for my $$anonymous$$eshes ($$anonymous$$eshObjects). And X = 128 * $$anonymous$$eshIndex. The image is row by row. But my mesh is column by column, which is way its more confusing for me :/
Well, but what values do you have in width and height? Does width equals 512 or 128? Your point_index still doesn't make sense since you treat _y and_x the same way. You would need to multiply _y by 512 (the full width) so the index into the image data correctly jump into the next row. If "x" is the "stripe-offset" your "_x" loop has to go from 0 to 128