So I have a 3D Plane described by 2 Vectors:
P : a point which lies on the Plane
N : the surface normal for the Plane
And i ha
Not sure what method you are using to render, but borrowing from OpenSceneGraph's matrix:
void Matrix_implementation::makeLookAt(const Vec3d& eye,const Vec3d& center,const Vec3d& up)
{
Vec3d f(center-eye);
f.normalize();
Vec3d s(f^up);
s.normalize();
Vec3d u(s^f);
u.normalize();
set(
s[0], u[0], -f[0], 0.0,
s[1], u[1], -f[1], 0.0,
s[2], u[2], -f[2], 0.0,
0.0, 0.0, 0.0, 1.0);
preMultTranslate(-eye);
}
inline void Matrixd::preMultTranslate( const Vec3d& v )
{
for (unsigned i = 0; i < 3; ++i)
{
double tmp = v[i];
if (tmp == 0)
continue;
_mat[3][0] += tmp*_mat[i][0];
_mat[3][1] += tmp*_mat[i][1];
_mat[3][2] += tmp*_mat[i][2];
_mat[3][3] += tmp*_mat[i][3];
}
}
Hopefully this will give you an idea for your implementation. I'm not very good with quaternions which might have a simpler solution, but this method works well for me.
Some useful things about rotations:
So, the problem is to find any set of three orthonormal vectors and arrange them as
| x1 x2 x3 0 |
| y1 y2 y3 0 |
| z1 z2 z3 0 |
| 0 0 0 1 |
this is exactly what the method you described tries to do, if it doesn't work then there is a problem with your implementation.
We can obviously use your normal as (x1,y1,z1), but the problem is the system has infinitely many solutions for the remaining two vectors (although knowing one of them gives you the other, as the cross product). The following code ought to give a stable vector perpendicular to (x1,y1,z1):
float normal[3] = { ... };
int imin = 0;
for(int i=0; i<3; ++i)
if(std::abs(normal[i]) < std::abs(normal[imin]))
imin = i;
float v2[3] = {0,0,0};
float dt = normal[imin];
v2[imin] = 1;
for(int i=0;i<3;i++)
v2[i] -= dt*normal[i];
This basically uses Gram-Schmidt orthogonalisation with the dimension that is already most orthogonal to the normal vector. v3 can then be obtained by taking the cross product of normal
and v2
.
You may need to take some care setting up the rotation, it's about the origin so you need to apply the translation after the rotation and it's for column vectors rather than row vectors. If you're using OpenGL watch that OpenGL takes arrays in column major order (rather than C's row major order) so you may need to transpose.
I'm afraid I haven't tested the above, I've merely nabbed it from some code I wrote a while ago and adapted it to your problem! Hopefully I haven't forgotten any details.
Edit: I did forget something :)
The matrix above assumes your normal to the polygon is along the x-axis, and I have a sneaking suspicion it won't be, all you need to do is put the "normal" vector in the correct column of the rotation matrix, and v2/v3 in the other two columns. So if the normal to your polygon is along the z axis, then the normal goes in the 3rd column and v2/v3 go in the first two columns.
Sorry if that causes any confusion.