Sign in to follow this  
QuadMV

Need some C coding help with matrix math

Recommended Posts

Hi all, I’m looking for some help, and hope to actually find someone willing to write a somewhat small function for me in C to perform some math that is necessary for a new technique I want to integrate into my engine. I think someone who is good with billboard math will probably find this problem easy: I’ll try and keep it as simple as I can: I have two 3D object in directX (consider them .X models, but it doesn’t really matter for the math) Each object is at a certain location and orientation designated by a 4x4 matrix. This is a DirectX matrix, and if I recall an OpenGL matrix is a little different and would result in slightly different math so I want to be clear that I’m using DirectX. Each object has a poly/triangle somewhere on it that is used as a marker What I need is a function that will rotate and move object2 so the triangle marker of object2 perfectly overlays the triangle marker of object 1. I do not want to move object 1 at all, I just want to move and rotate object 2 to align it with object 1 This sounds a lot like a variation on a billboard to me but math isn’t my thing. I’m assuming the function will take 4 parameters: D3DXMATRIX obj1mat; D3DXMATRIX obj2mat; D3DXVECTOR3 obj1tri; D3DXVECTOR3 obj2tri; Returning D3DXMATRIX I believe the return value is the adjusted MATRIX for object2, with a new position and orientation so the two objects align on the triangles. Is there anyone out there that understands this requests, knows the math, and would be willing to whip up a C function to do it for me? I’d be extremely grateful to anyone who would be willing to contribute. Thanks

Share this post


Link to post
Share on other sites
There may be a different, standard solution to this common problem, but I've tested the following and it appears to work.

The function doesn't require that the 'tag' faces be the same size or shape, but if they are, they will match exactly. The first thing you need then is a function to construct a local coordinate system for a face. Pseudocode:
vector3 u = normalize(verts[1] - verts[0]);
vector3 w = faceNormal;
vector3 v = cross(w, u);
matrix4 m;
identity(m);
loadTranslation(m, GetFaceCenter(i));
loadBasisVectors(m, u, v, w);
GetFaceCenter() just returns the average of the vertices of the face. Also, remember that in DX the basis vectors go in the first three rows of the matrix.

We now have two meshes, mesh1 and mesh2, under the images of matrix transforms M1 and M2, respectively. We wish to adjust the matrix M2 such that face2 from mesh2 aligns with face1 from mesh1. Pseudocode:
void AlignMeshes(
const Mesh& mesh1,
const Mesh& mesh2,
const matrix4& M1,
matrix4& M2,
size_t face1,
size_t face2)
{
matrix4_t L1, L2;
mesh1.GetFaceCoordinateSystem(face1, L1);
mesh2.GetFaceCoordinateSystem(face2, L2);
rotateAboutLocalY(L1, 180.0f);
matrix4 M = GetInverse(L2*M2)*L1*M1;
M2 = M2*M;
}
I had to flip things around from my column-vector version, and could conceivably have messed something up in the process. But I have tested it, and it seems to work perfectly.

I realize this isn't exactly what you asked for (straight C function using DirectX syntax), so let me know if you have any questions or problems converting the code.

Share this post


Link to post
Share on other sites
Quote:
Original post by JohnBolton
You really should write the code yourself. You might learn something.
Well, now I'm chagrined for having given a more or less complete answer :-) But c'est la vie...

Share this post


Link to post
Share on other sites
JYK,

You Rock, thank you very much. I’ll try this right away. I really appreciate the quick response. This shows real community spirit and a tribute to Gamedev and its members.

JohnBolton, you don’t even deserve a response so all I’ll say is I hope maybe you learn something from JYK and remember what goes around comes around. We all have our areas of expertise. Maturity comes from knowing your weaknesses and not trying to pretend you’re something that you’re not!




Share this post


Link to post
Share on other sites
Quote:
Original post by QuadMV
JohnBolton, you don’t even deserve a response so all I’ll say is I hope maybe you learn something from JYK and remember what goes around comes around. We all have our areas of expertise. Maturity comes from knowing your weaknesses and not trying to pretend you’re something that you’re not!


I think that people asking other people to write their code for them are lame. It's like asking someone to do your homework for you. You didn't even try to solve your problem. You just thought, "I don't want to do this, maybe I can get someone to do it for me".

jyk and I are both major contributors in these forums. He choose to be helpful by writing your code for you. I don't consider writing your code to be contributing. It benefits nobody but you, so I chose to be even more helpful (IMHO) by urging you to do it yourself.

Share this post


Link to post
Share on other sites
Quote:
Original post by JohnBolton
He choose to be helpful by writing your code for you. I don't consider writing your code to be contributing. It benefits nobody but you, so I chose to be even more helpful (IMHO) by urging you to do it yourself.
In my defense I answered the question as I did because I was interested, and saw it as a chance to add that particular function to my code base; furthermore, the lack of a supporting explanation was mostly due to lack of time.

So let me try to make up for it with a brief explanation. In the local space of a mesh, each face lies in a plane. There is still an infinite number of local coordinate systems that can be associated with the face, but we can choose one such that the origin is the center (average of vertices) of the face and one of the basis vectors is parallel to an edge. This is somewhat arbitrary, but is also convenient and appropriate for this algorithm.

We have two meshes, mesh1 and mesh2, and a face from each, face1 and face2; we then use the above method to construct local systems for these faces; the resultant 4x4 matrices are L1 and L2.

Our eventual goal is to align L1 and L2 in world space. Since the faces will be facing in opposite directions, we want to 'flip' L1 to reflect this. In my example I did this by rotating about its local up axis.

The meshes are under the image of the transformation matrices M1 and M2, therefore so are L1 and L2. In world space, we then have L1*M1 and L2*M2. We want to apply a transform to the latter such that it becomes equal to the former; this breaks down to a straightforward linear algebra problem and can be solved as follows:
L1*M1 = L2*M2*M
(L2*M2)^-1*(L1*M1) = (L2*M2)^-1*(L2*M2)*M
(L2*M2)^-1*(L1*M1) = I*M
M = (L2*M2)^-1*(L1*M1)
M2*M will then transform mesh2 such that the two faces are coincident (or aligned, if they are different sizes or shapes). Again, I may have made an error in the row-vector version, but that's the basic idea.

Anyway, I hope that will address the shortcomings of my previous post and resolve any remaining issues :-)

Share this post


Link to post
Share on other sites
JYK, Thank you for your posts supporting my question.

JohnBolton, I don’t want to get into a pissing contest/war with you. I disagree and don’t believe your comments are justified. I’m not in the habit of asking people to write code for me, and have provided my share of help to developers over the last 25 years of my programming career. Your comments that I didn’t even try are wrong and unjustified. Why assume the worst in people? I have tried, and I’ve not been able to get it right. You’d waste a lot of time trying to explain it to me because most of the math guys I’ve dealt with speak another language most of the time. I can learn more by looking at the code than I can having a mathematician explain it to me over the span of 50 posts. I wasn’t requesting hundreds of lines of code or someone to develop an entire class. I know enough that 99% of the code would be the math formula itself, and as such, I was asking for the math to be put into laymen’s terms (which for me is C code). I think you were too quick to jump down my throat and wanted to let you know IMHO it was inappropriate.


Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this