for fun i am trying to make a pure C library for modeling surface-based objects. as a first simple test i am trying to define a cube, and i am doing it algorithmically so the faces are described in an inner loop rather than literally one-by-one like one often sees. i'm experiencing a lot of inhibition imagining how to plot and index which neighboring surfaces are adjacent to which edges of which face. so, i'm spamming it here cause the inhibition increase was pretty sharp. bloopa-blrgh! so first for the cube i define 3 axes, a vector pointing in the direction of each face. for each face, 1 axis (or its negation) defines where the face is located relative to the cube center, and the other 2 axes (or their negation optionally) define the local coordinates of that face, basically. i have a nested loop, for (int axis = 0; axis < 3; ++axis) for (int sign = -1, sign < 2; sign += 2) that defines 6 unique faces. so, say the axes are simply <1,0,0>,<0,1,0>,<0,0,1>. in the first iteration, that means we're doing the -X face, then the +X face. I could alternatively swap the for loops. let's make it more intuitive. i'll restructure the loops like so: for (int sign = 1; sign > -2; sign -= 2) for (int axis = 0; axis < 3; ++axis) now the loop starts on +X, then does +Y, then +Z, then -X, then -Y, then -Z. ok, so on the first +X face, the two coordinates for the face will be +Y and +Z. when i define neighbors of a piecewise object surface, i was thinking of doing it using a 2x2 multidimensional array ... this was intended to aid intuition but i've forgotten the meaning of it a bit. each surface is modeled as having rectangular uv coordinates in the range [<0,0>,<1,1>]. there are up to 4 neighbors, fewer if a side has 0 length. so there is a neighbor along <0,0>, <0,1> and one along <1,0>, <1,1> these are the two neighbors where U is held constant. then there is a neighbor along <0,0>,<1,0> and one along <0,1>, <1,1> these are the two neighbors where V is held constant in other words, there is a neighbor in the direction of -V where V=0 and U ranges, then a neighbor in the direction of +V where V=1 and U ranges, and a neighbor in the direction of -U where U=0 and V ranges, and a neighbor in the direction of +U where U=1 and V ranges. So we could think of the indices in neighbors[2][2] as representing, is U positive? in the first dimension, and is V positive? in the second dimension, so a point at the midpoint of an edge with uv coordinates could select a neighbor like neighbors[u > 0.5 ? 1 : 0][v > 0.5 ? 1 : 0]. arrighty ?? now with these square faces, the two other axes would represent the directions of U and V. So, with the first square face, the face is centered on X, and U will be Y, and V will be Z (because the formula is (axis+n)%3). So in the +U direction, the neighbor will actually _be_ Y. because going in the direction of Y on any face moves you to the Y face. we're 1/3rd there!! for the X face, neighbors[1][0] .. wait V has no sign when U is +/- so this doesn't work: does not work oops: neighbors[u > 0.5 ? 1 : 0][v > 0.5 ? 1 : 0]. instead we need something like this: neighbors[dim > U_DIM ? 1 : 0][pt[dim] > 0.5 ? 1 : 0] one of the indices selects whether we are considering a U or a V neighbor and the other index selects where it is the positive or the negative neighbor. so, if we are considering the +U and +Y neighbor of the +X face,+sign then we would set neighbors[0/*for U axis*/][1/*for positive direction*/] = &faces[Y_face_idx]; now the way i am calculating Y_face_idx right now is axis + sign * 3 so the idx for the +Y face would be 1 + 1*3 but i gotta fix a bug there because i'm assuming sign ranges [0,1] and instead it's {-1,1} uhh i guess that would be (axis*2+(sign+1)*3)/2 or such but that's kind of complicated, basically i'll be calculating 5/6 of all the face idcs for every face i want it more clear to fix bugs while confused ok so basically i've simplified the problem down to these indices hmm and it looks like i'm trying to make it succcinct rather than clear or something... so what kind of axis changes are there? - the axis increases by 1 or 2 (mod 3) to find the adjacent faces - both signs are engaged to find adjacent faces so basically a sign shifts it by either 3 or 1 depending on storage axis majority and the opposite (1 or 3) is true of the axis that's reasonable. i could have local constants for AXIS_STRIDE and SIGN_STRIDE and use those :) super clear ! i've started implementing that. i'll write hte time (1940). i also want to make helper functions for the surface to set norms for how the neighbor indexing works. i've got: int idx = axis*FACE_AXIS_STRIDE+(sign+1)*SIGN_AXIS_STRIDE/2; i'm thinking i can make a double nested loop to iterate the surface neighbors, just like the storage norm. i'll make the helper functions first i guess. unsure what to call them. 1942 1944 here's my helper to set the norm: surface** surface_neighbor(surface* sface, int dim_0_or_1, int edge_0_or_1) { return &sface->neighbors[dim_0_or_1][edge_0_or_1]; } hmm i think i'll invert the order of those indices so that memory locality relates to spacial locality more 1945 hrmmm but then i want to make the implementation order different from the helper order which could trip me up later. i'll leave the ordering as-is. 1946 omigod i'm using vim at the same time as gmail and i keep hitting escape when i am done typing which closes the draft window o_o 1946 good for practicing contextual habit selection 1946 1947 1948 ok i'm calculating the neighbor index based on axis and direction and i'm confused about it again ummm thought i figured this out we care about what the axis is of the actual neighbor. so, given what the _uv_ neighbor axis is, we can calculate the _xyz_ axis by inverting the existing mapping. the u axis is specifically set to face axis + 1, and the v axis to face axis + 2, so we can add the uv dimension index to the face axis index to get the neighbor axis index. 1949 1950 ok now the sign of the neighbor axis ... the u or v can be multiplied by the sign of the face direction or not, it is up to what makes sense right here. right now it is indeed multiplied: surfaces[idx] = square3_new( add3(position, mul31(axes[axis], sign)), axes[mul31((axis+1)%3, sign)], axes[mul31((axis+2)%3, sign)] ); mul31 is my C functoin for scaling a 3-vector. looks like i have some bugs there, the axes[] list index should go inside the mul call, not outside ok i'll try to fix it maybe this looks better: surfaces[idx] = square3_new( add3(position, mul31(axes[axis], sign)), mul31(axes[(axis+1)%3], sign), mul31(axes[(axis+2)%3], sign) ); ok so i am trying to figure out if the neighbor is on the positive or negative (locally transformed) XYZ axis, if it is at the positive or negative UV axis. if we consider +X as the first face here, we can see that positive U relates to the positive Y axis. so the sign i think would be the U sign multiplied by the face sign it would clearly be simpler if it didn't scale it: then the U sign would exactly match the axis sign. i guess i'll remove the mul31s for now and let the internal links represent the continuity of the surface oh and it's 1954 1955 here's what i have now: surfaces[idx] = square3_new( add3(position, mul31(axes[axis], sign)), axes[(axis+1)%3], axes[(axis+2)%3] ); for (int neighbor_axis = 0; neighbor_axis < 2; ++ neighbor_axis) { for (int neighbor_dir = 0; neighbor_dir < 2; ++ neighbor_dir) { int neighbor_idx = ( ((axis+neighbor_axis)%3) * FACE_AXIS_STRIDE + nieghbor_dir * SIGN_AXIS_STRDE ); implement more here } } 1956 i fixed the spelling in nieghbor. ok so now we have the idx, gotta assign the neighbor pointer to point to the neighboring surface 1956 1957 whew! that was so hard to try :s here it is as now, i'm sure there are more bugs to fix that will emerge: surface ** surface_list = malloc(sizeof(surface*)*6); pt3 axes[3]; transformationationaxesinto(&axes, orientation_and_size); // iterate over 6 faces with idcs // each face has a sign pair, and a direction. const int FACE_AXIS_STRIDE = 1; const int FACE_SIGN_STRIDE = 3; for (int sign = 1; sign > -2; sign -= 2) { for (int axis = 0; axis < 3; ++ axis) { int idx = axis*FACE_AXIS_STRIDE+(sign+1)*SIGN_AXIS_STRIDE/2; surface_list[idx] = &surfaces[idx]; surfaces[idx] = square3_new( add3(position, mul31(axes[axis], sign)), axes[(axis+1)%3], axes[(axis+2)%3] ); for (int neighbor_axis = 0; neighbor_axis < 2; ++ neighbor_axis) { for (int neighbor_dir = 0; neighbor_dir < 2; ++ neighbor_dir) { int neighbor_idx = ( ((axis+neighbor_axis)%3) * FACE_AXIS_STRIDE + neighbor_dir * SIGN_AXIS_STRDE ); *surface_neighbor(surfaces[idx], neighbor_axis, neighbor_dir) = surfaces[neighbor_idx]; } } // find neighbors maybe ! // 3 axes. opposing axis is not a neighbor. // all other axes are neighbors, in each direction // [wow this is hard to think-intend! } }