tags:

views:

94

answers:

1

Hi guys,

Here is my end-objective: I have a very large terrain array of Vector3s (~2 million) and what I want to do is find the transformation matrix that would result in the smallest total lengths of all of these vectors relative to the origin (aka distance from vector to the origin). Yup, simply adding them all together.

I can perform this in a brute-force way in C#. but it takes minutes! What I do here is take each element of the matrix that represents translation (no rotation allowed in this application) and slowly increment them from, say, -5.0 to 5.0 individually (with some delta like 0.01) so that all combinations have been tested and I store the total lengths of the vertices after transforming them by this matrix.

The pseudo-code approach looks something like this:

float total = 0
float delta = 0.01
for(matrix_translate_x -5.0 -> 5.0)
for(matrix_translate_y -5.0 -> 5.0)
for(matrix_translate_z -5.0 -> 5.0)
     for each vector
          transform vector by matrix
          add length to total

I'm wondering if there is a way to perform this lightning fast using HLSL. I understand how to do calculations with float3s and float4x4s in the language, but what I don't know how to do store the results of each iteration so a final solution can be determined after the GPU process all of the vertices. So far I have these vertices in a heightmap which I render to a rendertarget to analyze the results.

Is using HLSL for this application feasible? Ideally this would take one render since -5 to 5 on 3 axis is 100,000 combinations using 0.01 as a delta! I'm also open to other suggestions not using HLSL.

Thanks!


EDIT: I didn't anticipate there would be an easy math answer so I kind of simplified my question for brevity! See reply #1.

This "terrain" I spoke of exists as a cloud of 3D points scattered in a tube fashion along the X axis. I can independently move both ends of this tube (like holding onto both ends of a broomhandle and moving your arms) in the Y and Z direction to try to find the smallest total length as I wrote above. So there would actually be two vectors, one at X=0 and one at X=max_x. All points in between 0 and max_x will be interpolated between the two solution vectors. So in truth we kind of can "rotate" here. Does that make sense at all?

I assumed if I could figure out the principles in HLSL I could apply it to my problem completely. Sorry to confuse.


[By the way, I also posted this question (copy/paste) on the XNA community forums. Is that bad forum etiquette? I'm new to this sort of thing...]

+1  A: 

That seems like a very brute-force approach to finding your desired solution. I think you should be able to compute the solution directly, without trying out all possibilities.

If I understand correctly, you have n 3-vectors x_1,...,x_n, and you're trying to find a translation (i.e. another 3-vector) d such that

sum(i=1,...n) || (x_i+d) ||

is minimal (where || denotes the 2-norm, or length, of a vector).

Correct?

I believe you should be able to make this sum minimal (without being able to prove it, though) by setting d so that it brings the centroid of the data set to the origin. In other words

d = -(1/n) * sum(i=1,...n) x_i

Try this solution out -- is it equivalent to the solution computed by brute force using your algorithm above?

Edited because I believe I misunderstood the problem initially.

Edited again to ask for clarification because the comment format doesn't allow me to format formulas.

I'm not quite sure I understand -- could you try and express mathematically the operations you can carry out on the dataset?

To clarify:

  • Can you translate along all axes? Or are translations along the x axis "forbidden"?

  • You say you can "move both ends of the dataset independently in y and z" (if I'm paraphrasing you correctly). This sounds as if you're allowing at least rotation in the y-z-plane. Do you also allow scaling along y and z? What about shearing?

Does this matrix express what you're trying to do:

        | 1 0 0 | 
x_new = | 0 a b |*x_orig + d
        | 0 c d |

where the 3-vector x_orig is the original data point, the matrix performs arbitrary operations in the y-z-plane, and the 3-vector d expresses a translation that is applied after the matrix.

Martin B
Thanks Martin, I edited my post because your solution was correct, however I over-simplified my problem. Your solution vector D had x = max_x/2 so I know it's working. But since I can solve for each end of the cloud (see above edit) independently we can include a rotation. Can we modify this equation? I'm not sure how you derived it but I think we're on the right track.
bufferz
Because I can't insert mathematical formulas in the comment, I edited my answer above -- see the questions there.
Martin B
I cannot translate in the x direction nor do I really need to. I can rotate in the y-z-plane because of the way I move each end independently. No scaling/shearing allowed. I think you have a good understanding of what I'm trying to do in 3D space.One solution to this problem is a 3D line-fitting approach, which works pretty well for me using the Least-Squares algorithm. However, this isn't exact enough for me - I really want to get the absolute perfect positioning of this cloud. Least Squares gives me an YZ intercept at 0,0, and a YZ slope for the rest of the points along the X axis.
bufferz
Using the tangents of these intercepts, I can create a rotation matrix to represent the solution. However, as I pointed out, Least Squares (and similar) are still approximations ... brute force is the only way I could figure out how to guarantee an optimal solution.
bufferz
Still not sure I understand what you're trying to achieve. If you say a least-squares line fitting is close to what you're trying to do, then it sounds to me as if you're trying to transform your 3D "tube" of points so that it is oriented along the x-axis, with its middle at the origin. Is this what you're trying to do? In that case, your measure of "sum of lengths of vectors" won't really do what you want (if I understand you correctly), because if you oriented the "tube" along the y-axis (say), the sum of vector lengths would be the same as if you oriented it along the x-axis...
Martin B