Skip to main content
GameDev.net gamedev.net
🔒 Locked

Help me to understand Clipping & Z-Buffer

Started by PdG Jul 11, 2008 at 3:29 AM 12 replies 2.1k views
Original Post
PdG
PdG
Hi, i'm fighting against the proj matrix :) Objective: display a planet with a ring using a realistic coordinate system. For example Saturn. I create the projection matrix and, to increase the precision, i set the near clip and far clip just above and behind the planet.


D3DXMatrixPerspectiveFovLH(&mProj, D3DX_PI * 0.25f, 1020.0f/738.0f,distance-radius, distance+radius);
HR(pD3dDevice->SetTransform(D3DTS_PROJECTION, &mProj)); 


where distance is the distance of the center of the planet to the origin (0,0,0) (where is setted the camera), and radius is the planet radius, including the ring. Putting near and far planet to distance-radius and distance+radius i should see all the planet whitout clipping. But the result is: ring is cutted How you can see, the ring is cutted. Now, i try to put the planet far away- also the planet now is cutted Now also the planet is cutted. I suspect a precision issue: in the first case the distance is = 3755313 (the u.m. is kilometers), in the second case is distance = 10088947. I've tried also an hack like:


D3DXMatrixPerspectiveFovLH(&mProj, D3DX_PI * 0.25f, 1020.0f/738.0f,distance-radius*2, distance+radius*2);
HR(pD3dDevice->SetTransform(D3DTS_PROJECTION, &mProj)); 


but it doesn't works... Some suggestions?
CProgrammer
CProgrammer
The near clipping plane is a plane, not a sphere. Therefore your code will only work if the planet is placed in the center of the cameras view, i.e at position [0, 0, z]. Otherwise the distance you are calculating to the planet is a diagonal distance and thus longer than it should be.
So to solve your problem, calclate the distance value as though the planet was at [0, 0, z].

PdG
PdG
So let me understand..

Suppose the planet has coordinates x,y,z
Fortunally, the camera has coordinate 0,0,0

now the distance that i compute is sqrt(x*x+y*y+z*z).
Have i to calculate as sqrt(0*0+0*0+z*z) = z?

No, there's something wrong.. if the planet is at (10000,0,0), and the camera is rotated to track it, i'll see at the center of the screen, but the distance is 10000, not 0!


[Edited by - PdG on July 11, 2008 6:47:23 AM]
Squallc
Squallc
Perhaps you should transform the planet's coordonate with the view matrix and apply the distance only with z.
PdG
PdG
Quote:
Original post by Squallc
Perhaps you should transform the planet's coordonate with the view matrix and apply the distance only with z.


Unfortunally it doesn't works..

distance = abs(mView._31*coords.d3dCoords.x+mView._32*coords.d3dCoords.y+mView._33*coords.d3dCoords.z);D3DXMatrixPerspectiveFovLH(&mProj, D3DX_PI * 0.25f, 1020.0f/738.0f,distance-radius, distance+radius);HR(pD3dDevice->SetTransform(D3DTS_PROJECTION, &mProj)); 


(i need only to transform the z coordinate).
coords.d3dCoords is the directx coordinates of the planet.

And the result is:

still clipped

Rotating the camera, the clips effect vary again: (if the planet is at the center of the screen, it's well rendered, if it's near the corner, i obtain this issue.)

:(
Squallc
Squallc
The world matrix of the planet is the identity ?
PdG
PdG
Quote:
Original post by Squallc
The world matrix of the planet is the identity ?


No.. if the planet has coordinate x,y,z, the world should be x00,0y0,00z, right?


Squallc
Squallc
Quote:
Original post by PdG
No.. if the planet has coordinate x,y,z, the world should be x00,0y0,00z, right?


No a translation the matrix is
100X
010Y
001Z
0001

Quote:
Original post by PdG
coords.d3dCoords is the directx coordinates of the planet.

Did you mean that these coordantes has been transformed by the world matrix of this planete ?
PdG
PdG
Quote:
Original post by Squallc
Quote:
Original post by PdG
No.. if the planet has coordinate x,y,z, the world should be x00,0y0,00z, right?


No a translation the matrix is
100X
010Y
001Z
0001

Quote:
Original post by PdG
coords.d3dCoords is the directx coordinates of the planet.

Did you mean that these coordantes has been transformed by the world matrix of this planete ?


(sorry, i've made a mistake)

I mean that, for the planet, the world matrix is:

D3DXMatrixTranslation(&matWorld, coords.d3dCoords.x, coords.d3dCoords.y, coords.d3dCoords.z);

Buckeye
Buckeye
You might give this a try:

Assuming you know the camera's direction -

cdir = normalize(camera_direction_vector); // if camera direction is not normalized

pdir = normalize(planet_direction); // if camera is at (0,0,0), planet_direction = planet_position

nearZ = (distance_to_planet-radius) * cos( asin( cdir dot pdir ) );

EDIT: that will only be appox., now that I think about it. It doesn't take into account the vertical angle above/below centerline.

Is your camera upvector always (0,1,0)?
Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly. You don't forget how to play when you grow old; you grow old when you forget how to play.
MJP
MJP
This is really really simple:

D3DXVECTOR3 vPlanetPosViewSpace;D3DXVec3TransformCoord(&vPlanetPosViewSpace, &vPlanetPos, &mView);D3DXMatrixPerspectiveFovLH(... ,vPlanetPosViewSpace.z - radius, vPlanetPosViewSpace.z + radius);
PdG
PdG
Quote:
Original post by MJP
This is really really simple:

D3DXVECTOR3 vPlanetPosViewSpace;D3DXVec3TransformCoord(&vPlanetPosViewSpace, &vPlanetPos, &mView);D3DXMatrixPerspectiveFovLH(... ,vPlanetPosViewSpace.z - radius, vPlanetPosViewSpace.z + radius);


God bless the united states! :)
It works!

Thank you!
PdG
PdG
Quote:
Original post by Buckeye

EDIT: that will only be appox., now that I think about it. It doesn't take into account the vertical angle above/below centerline.

Is your camera upvector always (0,1,0)?


No, you're in space and you can rotate on all three axis.

Anyway the solution of mjp seems to works.
I've to do a little adjustment with constant value (pheraps some precision problem with big number), but now it works.

Thank you anyway!
MJP
MJP
Just a little explanation of what I did there...

The zNear and zFar parameters you pass to D3DXMatrixPerspectiveFovLH specify distance to two planes, which are perpendicular to the camera. Like this:



Since these planes are perpendicular, every point on one of these planes has the same z-coordinate with respect to the camera (the coordinate space relative to the camera is view-space). However while they have the same view-space z value, they don't have the same distance (as you've already noticed). So when we're trying to find good values for those two planes, we're looking for view-space z values rather than distance. Fortunately, it's very easy to calculate hits (as you saw in the code I posted).

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.