terrain following

Started by
16 comments, last by Motorherp 17 years, 7 months ago
okay thanks
Advertisement
alright its returning the normal (i think) now how do i rotate the character?
Quote:Original post by treeway
alright its returning the normal (i think) now how do i rotate the character?


Hi again. There's not really any need to calculate angles and rotation axes to rotate the character, you could just construct the new orientation matrix manualy like so:

vec3 norm = BlendNormals(tri.verts, tri.vertNormals, character.pos);character.yAxis = norm;character.xAxis = (norm.cross(character.zAxis)).normalise();character.zAxis = (norm.cross(character.xAxis)).normalise(); 
[size="1"] [size="4"]:: SHMUP-DEV ::
Okay ive calculated the roatation matrix but I would like to be able to get the actual angle of the ground below the player as a single 3d vector - how do I find this?

Thanks

[Edited by - treeway on August 20, 2006 9:29:18 AM]
This is how im trying to do it:

D3DXVECTOR3 faceRotation;
faceRotation = scene->terrain->BlendNormals(faceId,playerPosition);
D3DXVECTOR3 xAxis;
D3DXVECTOR3 yAxis;
D3DXVECTOR3 zAxis;
D3DXVec3Normalize(&yAxis,&faceRotation);
D3DXVec3Cross(&xAxis,&faceRotation,playerLeftAxis);
D3DXVec3Normalize(&xAxis,&xAxis);
D3DXVec3Cross(&zAxis,&faceRotation,playerforwardHandAxis);
D3DXVec3Normalize(&zAxis,&zAxis);

Xrotation = atanf(D3DXVec3Dot(playerLeftAxis,&xAxis));
Zrotation = atanf(D3DXVec3Dot(playerforwardHandAxis,&zAxis));
playerYRotation = atanf(D3DXVec3Dot(playerUpAxis,&yAxis));

playerObject->setRotation(Xrotation,playerYRotation,Zrotation);

and the rotation seems right on a flat surface (0,90,0) but on hills its fluctuates between 0 and -0.000041 both of which are wrong.
For a start which implimentation of BlendNormals() are you using. I've realised the second one I posted is completely bogus now that I've studied it. Use the last one instead which should be correct forgiving any typos or minor mistakes I might have made since I just made it up on the spot. The idea is right though so if you step through it with a debugger you should be able to fix any minor problems.

Secondly, which way round do you take the z and x axes? I usualy use z for heading and x for left (or right depending on handedness). If you're using the same then you're constructing the character orientation matrix incorrectly since you should be crossing the up vector with the left vector to get the z axis.

lastly the way to calculate the angle between two vectors in 3d is like this:

angle = atan2(Length(v1.Cross(v2)), v1.Dot(v2));

Note that the angle will come out in radians not degrees.
[size="1"] [size="4"]:: SHMUP-DEV ::
Hi

I used the last method you posted and i was converting the angles to degrees in my output because i find them easier to visualise but im setting the rotation using radians. My Z axis is into the screen and left is left on the screen - I see the problem from before but when i fiexed it its still not right :( .

D3DXVECTOR3 faceRotation;
D3DXVECTOR3 xAxis;
D3DXVECTOR3 yAxis;
D3DXVECTOR3 zAxis;

faceRotation = scene->terrain->BlendNormals(faceId,playerPosition);
yAxis = faceRotation;
D3DXVec3Cross(&xAxis,&faceRotation,playerforwardHandAxis);
D3DXVec3Normalize(&xAxis,&xAxis);
D3DXVec3Cross(&zAxis,&faceRotation,playerLeftAxis);
D3DXVec3Normalize(&zAxis,&zAxis);

Xrotation = atan2f(D3DXVec3Length(D3DXVec3Cross(&xAxis,&xAxis,&zAxis)),D3DXVec3Dot(&xAxis,&zAxis));


playerObject->setXRotation(Xrotation);

//////////////// BLEND NOTMALS /////////////////

D3DXVECTOR3 PhysicsTerrain::BlendNormals(DWORD faceIndex, D3DXVECTOR3* point)
{
D3DXVECTOR3* verts;
verts = new D3DXVECTOR3[3];
verts[0] = verticies[faceIndex];
verts[1] = verticies[faceIndex +1];
verts[2] = verticies[faceIndex +2];

D3DXVECTOR3* norms;
norms = new D3DXVECTOR3[3];
norms[0] = normals[faceIndex];
norms[1] = normals[faceIndex +1];
norms[2] = normals[faceIndex +2];

return BlendNormals(verts,norms,point);
}

D3DXVECTOR3 PhysicsTerrain::BlendNormals(D3DXVECTOR3* pVerts, D3DXVECTOR3* pVertNormals, D3DXVECTOR3* point)
{
D3DXVECTOR3 edges[2];
D3DXVec3Subtract(&edges[0],&pVerts[1],&pVerts[0]);
D3DXVec3Subtract(&edges[1],&pVerts[2],&pVerts[0]);

float blends[2];

blends[0] = D3DXVec3Dot(&(*point - pVerts[0]),&edges[0]) / D3DXVec3Length(&edges[0]);

D3DXVECTOR3 triNorm;
D3DXVec3Cross(&triNorm,&edges[0],&edges[1]); // no need to normalise
D3DXVECTOR3 tangent;
D3DXVec3Cross(&tangent,&triNorm,&edges[0]);
D3DXVec3Normalize(&tangent,&tangent);

float vert0Proj = D3DXVec3Dot(&tangent,&pVerts[0]);
float vert2Proj = D3DXVec3Dot(&tangent,&pVerts[2]);

blends[1] = (D3DXVec3Dot(point,&tangent) - vert0Proj) / (&vert2Proj - &vert0Proj);

D3DXVECTOR3 norm = pVertNormals[0] + blends[0]*(pVertNormals[1] - pVertNormals[0]);
norm = norm + blends[1]*(pVertNormals[2] - norm);

return norm;
}


Couple of problems I can spot from the off there which I'll highlight in bold:

blends[0] = D3DXVec3Dot(&(*point - pVerts[0]),&edges[0]) / D3DXVec3Length(&edges[0]);

I'm not actualy sure if this is valid or not, it might complile to something which doesn't do what you expect. Not totaly sure on this one but I'd create the vector seperately before you point to it just to be sure. Also I think for the maths to come out right the first reference to edges has to be normalised. Try something like this:

D3DXVECTOR3 temp = *point - pVerts[0];D3DXVECTOR3 normEdge;D3DXVec3Normalize(&normEdge,&edges[0]);blends[0] = D3DXVec3Dot(&temp,&normEdge) / D3DXVec3Length(&edges[0]);


Whats really messing you up is this line here though:

blends[1] = (D3DXVec3Dot(point,&tangent) - vert0Proj) / (&vert2Proj - &vert0Proj);

What you're doing here is taking the difference in memory locations rather than the difference in values. Change this to:

blends[1] = (D3DXVec3Dot(point,&tangent) - vert0Proj) / (vert2Proj - vert0Proj);


You probably want to normalise the return of BlendNormals inside the actual fundtion rather than after so it makes more sense too. Its good practice to step through any maths intensive or complex code line by line at least once checking you're getting the expected values at each stage. If you make a habit of this you'll spot these kind of problems easily.


PS: Just spotted another mistake here:

Xrotation = atan2f(D3DXVec3Length(D3DXVec3Cross(&xAxis,&xAxis,&zAxis)),D3DXVec3Dot(&xAxis,&zAxis));

You're storing the result of the cross product in the xAxis which also gets used in the dot product. You'll need to stor the cross product result in a seperate vector to make sure the xAxis is preserved for the dot product. Also there's no point in calculating the angle between x and z axes since you just orthonormalised the matrix in the previous step. This angle will always come out as 90 degrees.

[Edited by - Motorherp on August 20, 2006 4:07:50 PM]
[size="1"] [size="4"]:: SHMUP-DEV ::

This topic is closed to new replies.

Advertisement