A great game hit a bottomless pit

Yeah I’ve been working on my space RTS game for a few months now. It’s been going very well.
But recently I hit a major obstacle which I find is a waste of time to hack at. It’s not worth the time.

Problem: selecting ships on the screen in 3d with a 2d mouse pointer, clicking and dragging.

I’ve already done tons of work on the engine. The engine works great and other aspects of the engine, moving ships in 3d, were shaping up well. But if I can’t knock selection down, I give up. I must have that.

If anyone is interesting in doing this part of the system I’m willing to give tons of credit to them.

I even have a half workable demo right now.

I don’t know what you use for occlusion culling, but using an octree could help you for that.

Just subdivide your space and make the smallest cube the size of your smallest ship.

When you set your view, you know exactly in what box is the view, so you could find the set of other boxes that are in front of you. If somebody clicks on the screen, you should easely be able to map to the first cube it is touching and trace a ray parallel to the view point and check every boxes until you find a ship at wich point you select it.

If the user drag, you just create a volume from the rays emiting from the 4 corner and select all the ship in the volume.

It’s a bit rough, I just though about it in like 5 minutes, but I think it is a good direction.

OpenGL has a function with does what you want (selects an object on which you cliked with the mouse). I don’t know it but my friend does.
Regarding writing your code I am trying to make an 3D RTS (kind of War3). We made the terrain, the skeletal animation and now we need an engine and the 3DStudio models (we have a designer also). Maybe we can exchange some code…

NewROmancer

Hi,

is your problem the speed of picking, the picking itself as OpenGl problem or something like “How do I drag the ship that it’s always under my mouse and doesn’t move faster than the mouse”.

Kilam.

Schlogenburg, I have some working code on how to rotate an object by dragging the mouse. It was written for Direct3DRM but the only thing you have to do to translate the code is change a call to IDirect3DRMFrame::AddRotation to a glRotate call. However, this code requires that you know which object you want to rotate, which is usually done by picking the object at the mouse cursor.

I can help you with the rotation but I need some help with picking also. I would like to rewrite a 3D modeler I made from Direct3DRM to OpenGL because OpenGL seems to be faster and more reliable.

One of Schlogenburg’s first questions is how to select his ship. I would be interested in the selection code also.

Thanks in advance!

i don’t know if this is goind to help…
but here is an ideia

you have the 3d objects coords like x,y,z

eliminate the z value…
so now you have on the screen imagine… 5 ou 6 3d models… only with 2d coords -> x and y

you compare the value to your mouse pointer and voila

in case one ship is in the back of the other, grab the z value… a see what is near you.

now… selecting the 2d coord for the ships
try first… creating a function that gets only a vertice of the ship… and test it.
i think you can draw a dot in the screen… and test if the mouse pointer is in the range of a few more dots in X and Y…

imagine a complete black screen only with a few dots… these dots are your model… if you remove the z value… so… draw the models to your mouse in 2d, so the mouse can see them

i know this kind of help stinks… but hope you have an ideia of it…

efx

Well I can’t say that helped me much but just to let you know what I have done so far.

I have had a working selection system in an old version of the engine, which used software rendering.
My problem: Rendering a 3d point on the screen, but then finding the 2d screen coordinate for it.

The thing is that GL is a graphics library and has it’s own functions and everything you do must use one of it’s graphics functions.

As far as I know, I can’t render a 3d vertex onscreen and find the 2d screen coordinate for it. If I could, then all I’d have to do is draw the ships, flush them to the screen, draw vertexes where the ships are located in 3d, convert those to 2d screen coords, and voila I find the mouse pointer in relation to this and problem solved.

I read a cool idea for selection in the OpenGL redbook; if you can assign an integer id number for each object in your scene, do this:

  • when a pick occurs, get the mouse x-y point
  • render your scene again in an offscreen buffer as usual but instead of using the normal texture/vertex colors, render all objects with a single color value which is the integer id number for the object
  • once you have rendered your scene this way, get the pixel color at the x-y coordinate that was picked with the mouse; the color value of the pixel is the id number for that object; you now know what was picked!

I thought that was a pretty cool idea

[This message has been edited by DJ Tricky S (edited 08-23-2000).]

Well I can’t say that helped me much but just to let you know what I have done so far.

I have had a working selection system in an old version of the engine, which used software rendering.
My problem: Rendering a 3d point on the screen, but then finding the 2d screen coordinate for it.

The thing is that GL is a graphics library and has it’s own functions and everything you do must use one of it’s graphics functions.

As far as I know, I can’t render a 3d vertex onscreen and find the 2d screen coordinate for it. If I could, then all I’d have to do is draw the ships, flush them to the screen, draw vertexes where the ships are located in 3d, convert those to 2d screen coords, and voila I find the mouse pointer in relation to this and problem solved.

Yeah I’ve tried that too. It works when your just clicking on a ship, but when you click and drag a box, are you supposed to read like 500 pixels?
Inefficient and would be probably error full.

3d vertex->2d screen coord would be much more efficient

How about the glFeedbackBuffer?

void glFeedbackBuffer(
GLsizei size,
GLenum type,
GLfloat * buffer
);

You call glFeedbackBuffer with type set to GL_2D and then 2d window coordinates are returned to the buffer!

And then you call glRenderMode with GL_FEEDBACK.

[This message has been edited by Blaze (edited 08-23-2000).]

I have also looked into feedback, but I’m not all that fluent with C++, so I was thinking that it would take me forever to debug it.

It would be REALLY helpfull if someone could post some feedback code?

I understand rendermode, but I have no idea of the usage of the feedback routine.

yes I have looked at the red book and blue book, but I still don’t know how to apply their code to my game.

Yes I’d be happy to exchange code, I emailed you at your yahoo email address. Please check it soon

Here is the best mode to make your selection. I did it at an MFC program. To each ship that is an object you attach 2 variables: the x and y which represent the position on the screen in 2D. Then you cycle on the list of the ships to see what ships are into ther coordonates defined with the mouse. It won’t take you more than 5000 computer cycle to select them.
To do this you are supposed that each ship is an instance of an object (derived from a parent class ship let’s say) and each object has his own painiting procedure.

NewROmancer

Originally posted by Schlogenburg:
[b]Well I can’t say that helped me much but just to let you know what I have done so far.

I have had a working selection system in an old version of the engine, which used software rendering.
My problem: Rendering a 3d point on the screen, but then finding the 2d screen coordinate for it.

The thing is that GL is a graphics library and has it’s own functions and everything you do must use one of it’s graphics functions.

As far as I know, I can’t render a 3d vertex onscreen and find the 2d screen coordinate for it. If I could, then all I’d have to do is draw the ships, flush them to the screen, draw vertexes where the ships are located in 3d, convert those to 2d screen coords, and voila I find the mouse pointer in relation to this and problem solved.

[/b]

This could be done with the gluProject function. Give it the 3d point and the current matrices and you will get the 2d screen coordinates.

Kilam.

The Source for gluProject:

gluProject(x, y, z, modelMatrix, projMatrix, viewport, &wx, &wy, &wz);

Don’t mind about the z-coordinate returned. It seems to be the z-buffer value (never
used it so…).

You obtain the matrices with:

glGetDoublev(GL_MODELVIEW_MATRIX,modelMatrix);
glGetDoublev(GL_PROJECTION_MATRIX,projMatrix);
glGetIntegerv(GL_VIEWPORT,viewport);

Do this directly after drawing, before any changes to the model- or projection matrix could happen!

By the way… the other method to do the picking would be to use the

gluUnProject()

method. This gives you the 3D coordinates for a 2D screen point. Then you could
search for your ship you picked in 3D. But you must pick the ship (means: a polygon
of the ship must be hit) and not the bounding box. This picking is more accurate then the
other way, but if you want to pick the bounding box you should use the other way.

Kilam.

NewRomancer:

But this could slow down your performance when you determine the x-y position in every frame. You should do it when the user picks something.

To Kilam Malik:
You’re correct. But if he created the objects as I described the performance hit is less than 1%. Because I’ll have the same problem in my game I looked a little over the problem. There is a function:
glSelectBuffer
that makes (I think that I understood well) what we want. We have to specify 6 planes that form an finite space and for every object from the space increases an counter. Dig about it and send some feedback here. You should make the rendering mode GL_SELECT.
Anyway look in the help from MSDN.

NewROmancer

When I understand the glSelectBuffer, you render everything you want to select again with GL_SELECT as render mode. Nothing graphically is rendered there, but every polygon of your scene is checked for intersection with the clipping planes. Hope I’m right so far.

Wouldn’t it be faster to:

  • Get the picking 2D coordinates.
  • Read the z-buffer value at this coordinate.
  • Do an gluUnProject to get the 3D coordinates of your picking.
  • Compare this 3D point if its lying inside a bounding box of your objects.

Or second possibility:

  • Project all boundingboxes of your objects into 2D (with gluProject).
  • Compare your 2D pickpoint if its inside one of these boxes.

You could use some structures like octrees to sort all your bounding boxes of your objects to do a faster search.

One thing to remind: The first option only lets you pick the object itself, nothing around it (because of the z-value in the z-buffer when you pick it. It will be 1.0 when you pick in empty space).
The second option lets you compare the bounding box of the ship.

It seems to me, that the glSelectBuffer-Method must be by far slower as it has to compare every polygon.
Even if you have only boxes, the algorithm in the openGL implementation must the general enough to handle all shapes of polygons and that makes it slower than a specialiced routine.

Kilam.

i like the idea of checking the projected x and y coord. but here are a few more

Why not use you collision detection system (i suppose you have one to check if a ship has been hit). so pretend that you are firing at the middle of the viewport and do a normal collision detection to see which object was hit. As for dragging just record the movement of the mouse around the screen and translate that to a rotation ,
for example:
suppose that the middle of the screen is at point (0,0) and the mouse does a movement from (100,0) to (150,0) then translate the 50 pxl movement into a rotation
how? well suppose the ships move in a circle or a sphere. and the middle of the sphere is 100 points in the Z direction (away from you)
then the rotation angle would be:
arc tangent(the movement across x-axis/distance to middle of sphere) = atan (50,100) //in this example//
do the same for movement across the y-axis, of course you can improve on this example, but if you are good in Math you’ll get the just of it.

Good Luck, post a link to the demo when it is available

cleverdesign@hotmail.com