Billboard sprite hit testing: help wanted...

Started by
4 comments, last by ManagedJack 17 years, 5 months ago
Hi, I'm using a billboard sprite in my MDX application to represent small markers in 3D-space. The application is based on the sample framework of the DirectX SDK. I'd like to implement hit-testing for mouse clicks on these sprites (actually, it is only one at different positions), but I don't really know if I am on the right track. At first some code that I use for the sprite:
// excerpt from DrawSprite function
// set the sprite's worldView matrix, needed for billboarding
markerSprite.SetWorldViewLH(Matrix.Translation(this.basePoint), viewMatrix);

markerSprite.Begin(SpriteFlags.Billboard | SpriteFlags.AlphaBlend);

markerSprite.Draw(texture,
              textureRect, // rectangle used from texture in pixels
              new Vector3(textureRect.Width / 2, textureRect.Height, 0), // center of sprite defined on whole texture in pixels used when billboarding
              new Vector3(0, 0, 0), // offset position of sprite in world defined on whole texture in pixels, 
              Color.White.ToArgb());
markerSprite.End();
At first I concentrated on implementing hit-testing by projecting the relevant part of the sprite texture to screen coordinates. But this does not fit into my other hit-testing code where I unproject a ray into object space. So how do I do the hit-testing in object space? Is it a good idea to create a plane and use plane.IntersectLine(...)? How do I get the depth information to compare it with other objects that are also hit by the ray? Any help is welcome, Jack P.S. I use managed DirectX, but I think it's not relevant for the problem.
Advertisement
This might be a good one for the Math & Physics messageboard considering the problem. Try posting it there.
you could try rendering to another texture but use specific colours for each object with no texturing, lighting or anti-aliasing.. just basic flat colours for each object. Then lock the texture and test the pixel at the mouse location. Each colour could represent an object on the screen.


This could be slow though as you shouldnt really lock textures every frame. Your also limited to how many objects you can have on the screen.

P.S - I dont use managed directx so dont know if this helps.
Hi again,

@Galaximo: You might be right. But I still think this must be quite a common problem. I'd have assumed that there is a special trick to do it with DirectX (a Sprite.GetIntersection(.) method?). But meanwhile I'll search the Math forum for planes and rays...

Thanks, jrmcv, it seems the proposal you made is a bit costly in regard to performance, but I'll have to give it a try if there is no other choice.

Jack
This code below will give you the position and ray when clicked on a certain location on the screen. You could then do ray test with the individual objects. As your using a lot of sprites with few polygons, this may not be too expensive to test everything in view.

x, y are screen coordinates (0 -> 1) m_proj, m_view are camera projection and view matrix. You may need to change y to 1-y

	float px, py;	MATRIX iMatrix;        // get direction from camera based on screen coordinates and proj matrix	px = (x  - 1.0f) / m_proj(0, 0);	py = (y  - 1.0f) / m_proj(1, 1);	D3DXMatrixInverse(&iMatrix, 0, m_view); // invert view matrix        // get camera position (0, 0, 0) through inverse view matrix 	pos->x =0;	pos->y =0;	pos->z =0;	D3DXVec3TransformCoord(pos, pos, &iMatrix);       // transform direction through inverse view	dir->x =px;	dir->y =py;	dir->z =1.0f;	D3DXVec3TransformNormal(dir, dir, &iMatrix);

pos is ray start location, dir is the ray direction (all in world space)
Thanks, jrmcv,

meanwhile I found a suitable way:


  • Get 3D coordinates of billboard sprite edges (glad to be using only rectangles!)

  • Create plane according to a discussion at Google.

  • Find the intersection point of the current ray with this plane.

  • Determine if the intersection point resides within the rectangle.



I wonder if it is my fault or if the given hints on of Google discussion are incomplete. I think you need at least 4 dot products to determine if the intersection point is within a rectangular area.

Thanks,

Jack

This topic is closed to new replies.

Advertisement