[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: [pygame] Collision Detection with Pygame/OpenGL Surfaces



"Ian Mallett" <geometrian@xxxxxxxxx> wrote:
> Hi,
> I'm making a program for visualizing molecules.  Each atom will be
> selected
> by the mouse.  Since I know the color of each atom, my idea for detecting
> if
> a mouse is over one is as follows:
>
> 1: get the color of the pixel the mouse is over
> 2: if the color is __ select the atom with that color.
>
> The problem is, pygame has issues with OpenGL surfaces and the call to
> Surface.get_at() declares I can't call an OpenGL surface.  Is there any
> way
> to get around this?

I wouldn't go this route for a couple of reasons:

- it's tying the view and the controller together in a brittle fashion
(see recent threads about MVC in this mailing list)

- (related to above) it places serious constraints on visual decisions -
each color needs to map to exactly one atom. This means that you can't use
the same color for all hydrogen atoms, for instance. Also, if you draw the
atoms with lighting, there will be a large range of colors that map to an
individual atom.

- hardware display surfaces (whether OpenGL or Direct3D) tend to be much
faster to write to than to read from.


You can work around all of these things, but instead, I've used a
different approach in my PyGame/OpenGL projects:

- use gluUnproject
[http://pyopengl.sourceforge.net/documentation/manual/gluUnProject.3G.html]
to take the position of the mouse in screenspace and project it back into
worldspace.

- use this to cast a "view ray" into my world

- intersect my view ray with my (possibly simplified) model geometry,
collecting collision records that each contain a reference to the object
collided with and the distance from the eyepoint for the collision.

- sort the collision records from nearest to farthest


For the intersection logic, a ray/sphere intersection function is pretty
easy to find out there (indeed, given the large number of ray tracers that
support spheres, that ought to be pretty well optimized these days).


For my code, I started out doing this every frame, and it got to be a
little bit more of a CPU hit than I wanted, so I cached the screen
position of the cursor - if that didn't change (and if the camera didn't
move), the world object being hovered over wasn't changing, either, so I
didn't have to redo my selection query. If you're only doing this in
response to a mouse click, and not every frame, you're already ahead.

Another optimization is to structure your collision data - there are a lot
of spacial partitions out there, including BSP trees, k-d trees, loose
octtrees, and so on. For molecular models, I'd look for something with
hierarchical bounding boxes. With a good spacial partition scheme, you can
discard large numbers of potential collision objects with very little
work.


-Dave LeCompte