D3DXIntersect() not succeeding

Started by
7 comments, last by george7378 11 years, 2 months ago

Hi everyone,

I'm trying to sort out some basic system which allows my camera to follow the height of a mesh (the mesh pointer itself is a public member of a class, of which meshTorus is an instance) a bit like terrain, using the D3DXIntersect() function. I'm defining a ray to start at the location of my camera (held in &campos) and point directly downwards (effectively allowing me to detect my vertical height above the chosen mesh). This is sent to a float called terrainHeight:

D3DXIntersect(meshTorus.meshPointer, &campos, &D3DXVECTOR3(0, -1, 0), NULL, NULL, NULL, NULL, &terrainHeight, NULL, NULL);

The only problem is that when I use it, the function doesn't succeed (when I run a check, it doesn't return D3D_OK). I can't think why this is - the mesh certainly exists because I render just before the function is called, and it's there.

I suspect that this is something pretty simple that I just don't know about! I should also say that I am running D3DXIntersect() in the render loop, just after rendering the mesh to be tested.

Thanks!

Advertisement

george7378, on 28 Jan 2013 - 02:03, said:
The only problem is that when I use it, the function doesn't succeed (when I run a check, it doesn't return D3D_OK).

Okay, what does it return then?

I don't think the 4th parameter is optional, but I'm not sure. Another note taken from the MDSN comment section: This function will return E_INVALIDCALL if mesh flags have D3DXMESH_IB_WRITEONLY or D3DXMESH_VB_WRITEONLY.

Also, you don't want determine the camera's position in or after the render stage. You'll want to do this before you render anything, otherwise you'll be rendering from incorrect camera positions.

I changed my code to this:

HRESULT hr = D3DXIntersect(meshTorus.meshPointer, &campos, &D3DXVECTOR3(0, -1, 0), NULL, NULL, NULL, NULL, &terrainHeight, NULL, NULL);
    _com_error err(hr); LPCTSTR errMsg = err.ErrorMessage();
    MessageBox(NULL, errMsg, "error", MB_OK);

...and when I run the program, I get this in my message box:

[attachment=13388:errintersect.jpg]

...however, when I add a pointer for the 4th parameter, I get the message 'this function completed successfully' in my messagebox. I guess that's solved it!

Also, I always update my camera position before the actual BeginScene() is called. I guess this is OK?

Thanks for your help!

When you use some DX api function, or from any other library that you might include into your project, first what should you do is to look for documentation about that function (if any) and see if some of its paramters can be NULL, if it doesn't say then it is more likely that it will fail if you pass NULL.

Also, I always update my camera position before the actual BeginScene() is called. I guess this is OK?

In between Begin and EndScene you must put code that is related to drawing, usually DrawXXX calls, setting shaders, render targets... Everything else you put where you think that is making sense.

_com_error err(hr); LPCTSTR errMsg = err.ErrorMessage();
MessageBox(NULL, errMsg, "error", MB_OK);

I don't think that can give proper info about DX error, its better to put breakpoint just after D3DXIntersect function and copy value of hr and paste it in "DXErr.exe" utility from DX SDK.

OK, I'm picking up some useful stuff here, thanks. I am having another slight problem with my D3DXIntersect function though - I have applied a translation matrix to the mesh I'm interested in so that it appears lower down, however, the function still seems to think the mesh is in the same place as it was before I applied the translation (i.e. when I loaded it in). Is there a simple way to make D3DXIntersect take transformations in the world matrix into account?

Thanks!

Try this: http://stackoverflow.com/questions/11274336/d3dxintersect-ray-in-wrong-coords

Ah, it looks like that's what I'm doing wrong. While I'm trying to sort out the workings of this function, I translated my floor up so that the mesh sits on it without having any transformations applied (my floor was at -4 before, so it is probably better to put it at 0 anyway), and I think I've got it working.

At the moment, this is my code:

if (D3DXIntersect(meshTorus.meshPointer, &campos, &D3DXVECTOR3(0, -1, 0), &meshHit, NULL, NULL, NULL, &terrainHeight, NULL, NULL)==D3D_OK);
{if (meshHit){campos.y += (0.5 - terrainHeight);} //0.5 is the height of my camera above the flat ground
else {campos.y = 0.5; terrainHeight = 0;}}

This works fine in that my camera follows the height of the object beautifully. However, I was wondering if anyone can think of a better way of elevating the camera than the one I have now? My current method for determining the height of the camera just seems a bit 'ugly' for some reason, but I can't think of a different way of doing it (given that I only know the distance to the ray's intersection with the mesh).

Also, my mesh has an underside too, so should I be worrying that there will be more than one intersection of the ray with the mesh?

Now I'm going to go and figure out the best way to transform the ray for the translated mesh...

You could translate your world matrix down by 0.5, but I'm not sure if that's better.


Also, my mesh has an underside too, so should I be worrying that there will be more than one intersection of the ray with the mesh?

D3DXIntersect returns the shortest distance. Assuming that's what you're interested in, you don't have to worry about that.

OK - I've been testing this method some more and it seems to work for more complicated island meshes too. It's also good because it only follows the height of the terrain below you (i.e. you can't suddenly mount this platform by walking under it - you have to walk up the ramp):

[attachment=13414:Direct3D first person camera 2013-01-29 23-30-20-68.png]

[attachment=13415:Direct3D first person camera 2013-01-29 23-30-55-32.png]

This topic is closed to new replies.

Advertisement