PDA

View Full Version : A great game hit a bottomless pit



Schlogenburg
08-22-2000, 06:19 PM
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.

Gorg
08-22-2000, 07:29 PM
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.

NewROmancer
08-22-2000, 09:11 PM
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

Kilam Malik
08-22-2000, 09:35 PM
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.

skippyj777
08-23-2000, 02:24 AM
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!

efx
08-23-2000, 11:57 AM
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.. http://www.opengl.org/discussion_boards/ubb/frown.gif draw the models to your mouse in 2d, so the mouse can see them http://www.opengl.org/discussion_boards/ubb/smile.gif

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

efx

Schlogenburg
08-23-2000, 12:10 PM
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.

DJ Tricky S
08-23-2000, 12:13 PM
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 http://www.opengl.org/discussion_boards/ubb/smile.gif

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

Schlogenburg
08-23-2000, 12:18 PM
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.

Schlogenburg
08-23-2000, 12:28 PM
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

Blaze
08-23-2000, 12:44 PM
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).]

Schlogenburg
08-23-2000, 12:55 PM
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.

Schlogenburg
08-23-2000, 06:45 PM
Yes I'd be happy to exchange code, I emailed you at your yahoo email address. Please check it soon

NewROmancer
08-23-2000, 09:04 PM
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

Kilam Malik
08-23-2000, 09:05 PM
Originally posted by Schlogenburg:
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.



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.

Kilam Malik
08-23-2000, 09:27 PM
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.

Kilam Malik
08-23-2000, 09:36 PM
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.

NewROmancer
08-24-2000, 03:02 AM
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

Kilam Malik
08-24-2000, 04:38 AM
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.

The Wolf
08-24-2000, 01:05 PM
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

Pauly
08-24-2000, 01:57 PM
I like the idea of projecting bounding boxes into screen space.

Kilam's suggestion sounds good.

- Click the mouse

- Use gluUnProject to project all the bounding boxes for objects in the frustrum into 2d space

- Compare values.

Quick and easy!

Schlogenburg
08-24-2000, 02:42 PM
. . No I don't really totally understand that.

Here's my interpretation and its problem:

I got my 2d points onscreen to compare to mouse pointer. Nice.
Problem is how big are the bounding boxes(fields that the ships occupy on 2d screen) so say I can tell if user's clicking on fighter close or very very far away?

I need the Z coordinates-distance from viewer to these ships . . .

heh just solved my own problem, never mind me
use distance formulae to find distance between user and ship, also using ship
size value(say 1 for fighter, 10 for capital ship) to affect the size of bounding box . .


also remember I AM using gluUnProject and NeRomancer is going to help me with this

zed
08-24-2000, 06:21 PM
http://members.xoom.com/myBollux world builder press p then press h and drag the mouse over the screen is this what u want?. i just use the selection buffer

NewROmancer
08-24-2000, 09:01 PM
If the z value matters them I think that the best way to do this is with glRenderMode(GL_SELECT). In MSDN is explained pretty well all this. Next week I'll try to find a solution and as soon as I'll solve the problem I'll post the code...
HAve a nice week-end because I have a friend that has just became a slave (he got married - and I have to go to his wedding).

NewROmancer

Kilam Malik
08-24-2000, 11:07 PM
Originally posted by Schlogenburg:

I need the Z coordinates-distance from viewer to these ships . . .


Yeah, thats the first possibility I posted. You use gluUnProject on the x and y screencoordinates and the z-buffer value on this screen position (use glReadPixels). Then you get the x-y-z coordinates in your coordinate space.

Kilam.

Bob
08-25-2000, 12:53 AM
As far as I understand, the selection buffer can solve some problems that might occur when using manual bouding box selection.

Imagine a scene, where you have a flying torus (doughnut) infront of you. Behind that torus, there is another object that you want to select. This object is visible through the hole of the torus. Now, if you are using bouding boxes, won't you select the torus when clicking on the other object? If using selection buffer, this problem is solved, because you are clicking ON the other object, not WITHIN the bouding box of the torus.

skippyj777
08-25-2000, 02:17 PM
Schlogenburg asked for the code, so here it is. Sorry guys, its DirectX (I know you all hate DirecX http://www.opengl.org/discussion_boards/ubb/biggrin.gif), but I haven't ported my modeler to OpenGL yet because I am also stuck on the selection problem.


THE CODE
========

type
TfrmMain = class(TForm)
protected
DraggingSelection: Boolean; // True if user is using mouse to drag or rotate selected object
DragCount: DWORD; // Number of times mouse has moved since drag started
LastMouseX, LastMouseY: Integer;

procedure DragModelStart;
procedure DragModelEnd;

end;

// D3DVALUE is a single-precision floating point
// D3DVECTOR is a record/structure of 3 D3DVALUES, one for each x, y, and z

procedure TfrmMain.DragModelStart;
begin
DraggingSelection := True;
DragCount := 0;
end;

procedure TfrmMain.DragModelEnd;
begin
DraggingSelection := False;
end;

// MouseDown code picks/selects model and if a model was picked it calls DragModelStart()

procedure TfrmMain.adxctlMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
var
// For drag
DeltaX, DeltaY, DeltaR: Double;
Denom: Double;

Rotation: D3DVECTOR;
RotationTheta: D3DVALUE;
begin
if Dragging then begin
Inc(DragCount);

DeltaX := x - LastMouseX;
DeltaY := y - LastMouseY;
LastMouseX := x;
LastMouseY := y;

DeltaR := Sqrt(DeltaX * DeltaX + DeltaY * DeltaY);
Denom := Sqrt(Radius * Radius + DeltaR * DeltaR);

if (DeltaR = 0) or (Denom = 0) then Exit;

Rotation.x := -DeltaY / DeltaR; // Notice the reverse of x and y - this is intentional
Rotation.y := -DeltaX / DeltaR;
Rotation.z := 0;
RotationTheta := DeltaR / Denom;

if DragCount < 2 then begin
// First couple of drag movements cause wierd model rotation
RotationTheta := 0;
end;

ADXHRESULT(Model.Frame.AddRotation(D3DRMCOMBINE_AF TER, Rotation.x, Rotation.y, Rotation.z, RotationTheta));

RenderUpdate;
end;
end;

// MouseUp event calls DragModelEnd

// RenderUpdate re-renders entire scene

skippyj777
08-25-2000, 02:22 PM
NOTE: The Model.Frame variable is an IDirect3DRMFrame3, which is a child frame of the scene frame, so its position is in world coordinates. Likewise with the camera frame (but the camera position should not affect the above code).

I imagine that the call to AddRotation() would be replaced by a call to glRotate(), or maybe you would postmultiply a new rotation matrix onto a position/orientation matrix associated with your model?

skippyj777
08-25-2000, 02:24 PM
Do you have a beta version of your game somewhere on the net?

Schlogenburg
08-25-2000, 06:31 PM
Thanks for posting all that. It'll take a while to digest, and no I don't hate DirectX. It is another tool that may come in handy if GL fails me.

First I'll try this though, if it doesn't work I'll take a close look at the DX code:

-Use angles from the viewers position to the ships, first of all to find which ships are within viewing window(a 45 degree window), getting the angles RELATIVE to the viewer and relating that to the angle of the mouse position, converted. Say mouse position is at far right, y-axis would be 45 degrees. In the middle it would be zero, but always additioning the actual angle of the viewer.

ps. about the demo, it's not very playable as you cannot select ships to give them orders. However the camera system works very well, as does many other aspects of the engine eg. Moving ships around realistically.

I'll definetly let people know when the early 0.01 beta is available. Screenshots will be posted soon also, as of course I can at least get those.

NewROmancer
08-27-2000, 08:44 PM
I looked at the code of skippyj777 and I don't get where is the selection code. You see you have to make the connection between the objects from the scene with the objects into the memory (in other words if I detect that at one position from the screen is an object i must know what object from my object list it is...). And that code I don't see in the program. And if you don't use the lists from Ogl or you don't code the position of the ship in your object you have to make some pattern recognition and then...
The solution is to attach to each object in the world a propriety named coordinates
(an array of 3 floats or doubles) and keep them in the memory all the time. This problem is that the function of transformations from the objects into the memory to screen isn't bijective.
If you want to use the tools OpenGl has you have to create all the objects from lists and them you can select with the gl PopName().

NewROmancer

skippyj777
08-28-2000, 04:55 AM
This code does not select a model because there is only one model. The selection code the program does have (which I removed from the sample) selects a face on the model.

Crowdpleazr
08-28-2000, 04:16 PM
Since you are making a space based 3dRTS, I suggest you look at Homeworld and how they handled this problem. I thought it worked quite well and I was never frustrated with it:

1) A single click is a selection on the firstmost object in your view with coords(x,y, z) where you raytrace z into infinity (or the boundries of your view) until it hits an object

2) A click and drag selects all objects within that 2d plane, traced back into infinity (or the boundries of your view). If there are two objects on top of each other, they are still both selected.

That way, the user then must control the camera properly to get the ships he wants selected, and you don't have to worry about exactly what he needs. This has the added benefit of being a similar thought process to how most other RTS games work. I've seen enough suggestions here to help you implement this in code.

08-30-2000, 04:46 PM
It seems like you guys are going through a lot of trouble to find out what you are trying to select. I think that the redbook idea is probably the most simple, though it does have problems if one object totally occludes another object. Even there, though, I think that it would be rather unlikely in a space RTS that one object would totally occlude another during selection. Generally, people want to pick what they can see.

I haven't checked, but is GLReadPixels that slow? Even for a large number of pixels I can't imagine it being that bad. Even if it is slow I doubt that it is as bad as doing all sorts of sorting, projection, and intersection testing.

Schlogenburg
08-30-2000, 06:54 PM
You can't drag using any of those methods. Is draggin REALLY needed in an RTS game I ask you? It's tons of work to implement it.

the methods you suggest are much simpler

Schlogenburg
08-31-2000, 01:18 PM
Well I've been experimenting and cleaning up my camera system so that it's bug free and all I have to do is implement my angular selection.
This may seem like a simple question, it is a simple question, it's finding the angle between two points in 2d space. If I can do that it's easy to do in 3d space.
Easy to do on paper and calculator, but doing it in a decent way in the C++ language is different, could somebody post a snippet of code to do this?

what I need to do is pass it two points, the cameras location in 2d x and z and another location in 2d and find the angle from the camera to the location like so:

float FindAngle(float x1 z1 x2 z2)
{
find angle from point 1 to point 2
return angle(float)
}

Space Toaster
09-01-2000, 02:56 AM
Humm, I don't really understand where is the problem exactly, if you want to know the angle between 2 vectors:

From Inet (I'm very lazy) :

theta=acos((v1 DOT v2)/(|v1|*|v2|))

v1,v2: vector
DOT : dot product
|v1| : length of v1

If you preblem is to determine which model your mouse is on...

You need to make a bounding square (implicitly) for each model, you scale it by the distance, and then you go through all your visible object and determine in x and y if you mouse pointer is in one of those square. If there is more then one, choose the nearest.

To move you model in 3d, I propose you have a look at homeworld, it is quite user friendly.

If I do not answer your question, or if you need more detail explanation, feel free to ask.

Good luck!

09-01-2000, 10:30 AM
See the source to the smooth.c demo in the GLUT distribution for an example of doing this using gluProject and gluUnproject (in the mouse and move methods).

Schlogenburg
09-01-2000, 01:48 PM
And where can I find that GLUT source?
Also my angular selection system seems to be working in my experiments so far, if it turns out that it works, and it is pretty accurate, I will post the code for everybody to see what is probably the easiest way to do it.

Schlogenburg
09-02-2000, 04:38 PM
The viewer is supposed to rotate around the ship with the camera pointing at the ship
to get any angle they want. The new feature is that they can change their angle, so it's
not fixed to stare at the ship all the time. The camera will stay, the fixed angle to look
at the camera will still exist, but the viewer will look freely.

I've had nothing but problems with the coding of this. It always rotates or translates the
wrong way and I can't quite seem to figure out the order of operations and coding it
in my head. The logic evades me.

Here's what needs to be done, the orders of operation but not in the right order
and probably missing an order or two.

-Move the world so that the ship of our attention is at origin, 0,0,0
-Zoom out, this is our zoom distance from the ship
-Rotate, this is the angle that we're looking at the ship if we're under the ship, in front
etc.
-THEN rotate other than the fixed angle towards the ship. User presses observer button
to look. This is the confusing part(coding that is). The camera stays in the
same place but it's looking angle changes.

Now I hope this makes sense, I've explained it as clearly as I could. I hope you know
my problem and what I hope to accomplish.

I'm pretty sure this is an easy concept too.

NOTE: please post pseudo code and document it as you see fit.

Ickno
09-02-2000, 05:13 PM
Originally posted by Doug:
See the source to the smooth.c demo in the GLUT distribution for an example of doing this using gluProject and gluUnproject (in the mouse and move methods).

I tried this code, but the 2d point never rendered to anything near my selection in 3D. ... I'm pretty frustrated with the whole thing...

Schlogenburg
09-02-2000, 07:43 PM
Your telling me. Try using a system of angles.

Carlos
09-07-2000, 08:19 PM
The best way to select objects is:
draw all your objets in the back buffer,
each one with a different color, then
you have only to compare the color of
the pixel where the mouse is with the
color of your objects. If you are working
at 32-lebel depth, as usuall, a single
scan of your image lets you choose between
65,000 objects, if you need more you need
to scan again. Of course you do this in the back buffer so the user doesn't see nothing.This method is very simple, very elegant and very powerfull, it will work always as long as you draw the scene EXACTLY in the same way, when you are showing it and when you are picking objects. It is mentioned in the advanced methods, in the last chapter of the oficial red book. I implemented this
method in my GNU/Linux application, where the number of objects can easily be several thousands, and where I have 17 different classes of objects, which makes things even more complex, so I really know what I am talking about ;-)

Schlogenburg
09-08-2000, 12:02 PM
I don't mean to be offensive or anything, but I've already explained many times that the problem is not the picking so much as the click & drag which is essential.

Dragging using your technique would be far from efficient.

Blaze
09-09-2000, 07:06 AM
Carlos:

I don't think that is a very efficient way of doing it.

I still think the feedback buffer is the best bet.

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

Schlogenburg
09-09-2000, 12:05 PM
What's wrong with this code? This is part of my camera positioning code for the freelook.
It translates the camera to the ship's coordinate that the camera's orbiting, and if they want to look around freely then it goes to oberver mode 1.
Here I project out the zoom line so I end up with the camera's 3d coordinate and can feely look around.

There's something wrong with my trig here.

void RenderCamera()
{
if (Mcamera.zoom<10)
Mcamera.zoom=10;

if (Mcamera.zoom>80)
Mcamera.zoom=80;

if (Mcamera.xangle>90)
Mcamera.xangle=90;

MoveShips();
// if Camera has new target and hasn't acquired approp. position
if (Mcamera.ctargetstep<10)
{
Mcamera.x+=Mcamera.cx;
Mcamera.y+=Mcamera.cy;
Mcamera.z+=Mcamera.cz;
Mcamera.ctargetstep+=1;
}
else
{
Mcamera.x=ship[Mcamera.target].x;
Mcamera.y=ship[Mcamera.target].y;
Mcamera.z=ship[Mcamera.target].z;
}

float tx,ty,tz;

tx=Mcamera.x;
ty=Mcamera.y;
tz=Mcamera.z;

Mcamera.vx=((float)cos(Mcamera.yangle) * Mcamera.zoom)+ship[Mcamera.target].x;
//Mcamera.vz=((float)sin(Mcamera.yangle*piover180) * Mcamera.zoom)+ship[Mcamera.target].z;
Mcamera.vz=((float)sin(Mcamera.yangle) * Mcamera.zoom)+ship[Mcamera.target].z;
float ux=Mcamera.xangle;
if (ux>360)
ux-=360;
if (ux<0)
ux+=360;

float t=(cos (ux)*180);

Mcamera.vy=((float)t * Mcamera.zoom)+ship[Mcamera.target].y;


if (!Observer)
{
glTranslatef(-tx,-ty,-tz);
glTranslatef(0,0,-Mcamera.zoom);
// Camera Looking Around

glRotatef(Mcamera.xangle,1.0f,0.0f,0.0f);
glRotatef(Mcamera.yangle,0.0f,1.0f,0.0f);
//sprintf(str, "Orbit x: %f y: %f",Mcamera.xangle,Mcamera.vy);

}

if (Observer)
{
glRotatef(Mcamera.vxangle,1,0,0);
glRotatef(Mcamera.vyangle,0,1,0);
//glTranslatef(Mcamera.vx,-Mcamera.vy,-Mcamera.vz);
//glTranslatef(-tx,-ty,-(tz-Mcamera.zoom));
glTranslatef(Mcamera.vx,-Mcamera.vy,-Mcamera.vz);

}

}

Schlogenburg
09-09-2000, 01:08 PM
Sorry NEVER MIND THAT CODE PEOPLE
don't reply to that one.

That code was all wrong from a different version. Here's the real stuff:

void RenderCamera()
{
if (Mcamera.zoom<10)
Mcamera.zoom=10;

if (Mcamera.zoom>80)
Mcamera.zoom=80;

if (Mcamera.xangle>90)
Mcamera.xangle=90;

MoveShips();
// if Camera has new target and hasn't acquired approp. position
if (Mcamera.ctargetstep<10)
{
Mcamera.x+=Mcamera.cx;
Mcamera.y+=Mcamera.cy;
Mcamera.z+=Mcamera.cz;
Mcamera.ctargetstep+=1;
}
else
{
Mcamera.x=ship[Mcamera.target].x;
Mcamera.y=ship[Mcamera.target].y;
Mcamera.z=ship[Mcamera.target].z;
}

float tx,ty,tz;

tx=Mcamera.x;
ty=Mcamera.y;
tz=Mcamera.z;

Mcamera.vx=((float)sin(Mcamera.yangle*piover180) * Mcamera.zoom)+ship[Mcamera.target].x;
//Mcamera.vz=((float)sin(Mcamera.yangle*piover180) * Mcamera.zoom)+ship[Mcamera.target].z;
Mcamera.vz=((float)cos(Mcamera.yangle*piover180) * Mcamera.zoom)+ship[Mcamera.target].z;
float ux=Mcamera.xangle;
if (ux>360)
ux-=360;
if (ux<0)
ux+=360;

float t=(sin (ux)*piover180);

Mcamera.vy=((float)sin(Mcamera.xangle*piover180)*M camera.zoom)+ship[Mcamera.target].y;
sprintf(str,"%f",sin(Mcamera.xangle*piover180));

if (!Observer)
{
glTranslatef(-tx,-ty,-tz);
glTranslatef(0,0,-Mcamera.zoom);
// Camera Looking Around

glRotatef(Mcamera.xangle,1.0f,0.0f,0.0f);
glRotatef(Mcamera.yangle,0.0f,1.0f,0.0f);
//sprintf(str, "Orbit x: %f y: %f",Mcamera.xangle,Mcamera.vy);

}

if (Observer)
{
glRotatef(Mcamera.vxangle,1,0,0);
glRotatef(Mcamera.vyangle,0,1,0);
//glTranslatef(Mcamera.vx,-Mcamera.vy,-Mcamera.vz);
//glTranslatef(-tx,-ty,-(tz-Mcamera.zoom));
glTranslatef(Mcamera.vx,-Mcamera.vy,-Mcamera.vz);

}

}

Carlos
09-09-2000, 01:35 PM
Dragging is an entirely different matter than picking. I do use dragging to move, rotate and scale my objects, but unless you use OpenGL alone, this tends to be done using some sort of Toolkit like Motif/Lesstif, GTK,
Tcl/Tk, QT. I am sure in Windows things are not all that different. If you use a drawing area widget this is the way to do that. Of course then you have to build your own engine, in dynamic memory, etc...


About the efficiency of the picking method I described above, I am not sure that people understood what I said: In picking mode, all
objects are drawn at the same time, but each one with a different color, so you can distinguish them. If your scene draws at
say 20fps, then you pick your object in about 1/20 sec. Note that for example depth problems are automatically solved because objects which are underneath will be hidden and cannot be picked. You can have (I do) complex lightning, you can have any texture mapping, etc... Of course you need to
disable them (dithering also, for obvious reasons) in picking mode, which makes things even faster.

If your program is simple, feedback
or standard selection techniques can
be used, but if you have something more
complex, with many different objects and matrix transformations, this is really the simplest 100% reliable way to select objects!
See Red Book, pg 389.

Schlogenburg
09-09-2000, 07:37 PM
I'd be glad to use that picking method. OpenGL's selection buffer works well for simple selecting. But honestly, for a game that appears something like homeworld, do you actually think you'll be able to play the game without dragging?
100+ships on the screen?

I'm using selection like so:
Instead of using mouse pointer, the viewer moves the whole camera with the selection cursor in the middle of the screen.
Then the engine compares the angle of the camera to a ship to see if it's the same angle that the viewer clicked at. It's a very very simple concept.
I have a very simple trig problem here it seems. I'm using both COS and SIN and they are mixed up. When I rotate the camera up, then go to observer mode like so, the camera's location changes and that's not supposed to happen.

Please somebody take a look at the code and tell me what's not right.