Archived

This topic is now archived and is closed to further replies.

Dominik_78

3D View and orientation of other player's

Recommended Posts

Hi, i got my networkcode working now - but I am stuck to what to transfer to the server. I got the Position in Space and my qauntion (Angle and 3 Values). but I got a wiered effect in the rotation. what i transfer: cameraQuat.GetAxisAngle(axis, angle); angle = (float) RADTODEG(angle); float ax, ay, az; axis.GetValues(ax, ay, az); I transfer angle, ax, ay, az. (this represents the functioning view rotation info of a clients view) this is what i do to render the client on the server: for (int ei = 0; ei < enemycount; ei++) { if (enemies[ei].isConnected() == TRUE && enemies[ei].isAlive() == TRUE) { glLoadIdentity(); glRotatef(angle, ax, ay, az); glTranslatef(x_tra,y_tra,z_tra); glTranslatef(enemies[ei].x_pos,enemies[ei].y_pos,enemies[ei].z_pos); glRotatef(enemies[ei].angle, enemies[ei].dx, enemies[ei].dy, enemies[ei].dz); res = res + enemies[ei].drawEnemy(); } } *_pos = position d* = direction (quantion) what have I done wrong? thank you Dominik

Share this post


Link to post
Share on other sites
Hi again,

as i play around with this I notice it feels like gimbal lock. but how can this be? I use quantions? Is this because I have to multiply my 2 Rotations into one in a different way? and if this is so, how to do this? (link to a more in deep quantion tutorial would be best if this is the way to do it).

But this way of rotate translate camera view + translate rotate client position and direction is giving the right position but the orientation of the client is in some ways wrong (sometimes it is ok, if i only rotate on one axis). just like my old problem which was due to the gimbal lock.

did somebody else experiensed this?

thanks

Dominik

Share this post


Link to post
Share on other sites
First of all, it''s quaternion, not quantion (the term quantion actually exists, btw, but it is used in the field of particle physics... )

About your problem, well, I have to admit that I don''t really understand what you mean. There is something ''wrong'' with your rotations. OK. But what exactly ? We need more information to be able to help you.

Generally, if your camera computation are solely based on quaternions, and no Euler angles come into play at any moment (and that includes things like roll, pitch and yaw), then the gimbal lock should not occur. A conversion from quaternion to angle/axis should not be a problem either.

Now, you apply two different glRotate() commands on two different angle/axis pairs. This can lead to a gimbal lock. You can actually visualize the two distinct angle/axis pairs as two (from 3) vectors forming an Euler coordinate triple: your are rotating your coordinate frame twice, around different axes. Given the (in-)appropriate values for such an axis/angle pair, the last rotation can possibly lock.

The trick to avoid gimbal lock-like situations, is to do *all* the rotation in quaternion space. Only the final rotation can then be safely transfered to a rotation matrix (perhaps through an intermediate angle/axis conversion). Any subsequent coordsys rotation you apply to this system can produce a gimbal lock.

But your problem can very well be somewhere else. There is not enough information. For further help, you''ll need to describe your problem in greater detail, and provide some more insight in what you are trying to achieve with those rotations.

/ Yann

Share this post


Link to post
Share on other sites
Thank's Yann L,

it is probably due to my lack of abitlity to express my problem in 3D in english that good.

I got my Camera Rotation's and I use quaternion to represent them.

EDIT: The view on the client is perfect but the representation of the client rotation on the server is the problem.

If I move and turn in space my quaternion is affected and just before I render to the screen I read out the euler angle out of the Camera - quaternion.
this:


          
CSSVector3D axis;
cameraQuat.GetAxisAngle(axis, angle);
angle = (float) RADTODEG(angle);
float ax, ay, az;
axis.GetValues(ax, ay, az);


Now this happens:

I transfer this extracted values to the server (problably wrong if I understand your post right).

Now to display the client on the server I first extract the euler angle from the quaternion like on the client (camera orientation of the server). and then I apply the translation of the client and the rotation of the client to OpenGL and render a client object. Position then is OK but the rotation not.

Now the effect is:

if i turn around only on one the x-ax on the client (pull the stick back to make a looping) everything is ok but as soon as a 2nd axis come into play the problem starts just like my gimbal lock problem I had the time before I started to changes all my rotations to quaternions.

now what can I do?

Am I right to think that I need 2 rotations because of the translate between them and sticking the 2 together will mess my client position up a lot. Because it is a difference to rotate and translate or translate and rotate right?



[edited by - Dominik_78 on December 28, 2002 11:19:45 AM]

Share this post


Link to post
Share on other sites
So Yann L, is it now easier to understand my problem?

I need that 2 Rotations and between that I need a translate. to make 1. My Enemy rotate around me and second rotate about it own center to make the enemy point to the right direction.


thanks

Dominik

Share this post


Link to post
Share on other sites
quote:

So Yann L, is it now easier to understand my problem?


Honestly, I''m still not quite sure what you want I guess you''re writing a multiplayer game, where each player has his local camera position. And you want the player character''s mesh objects to be oriented in the right direction, when viewed from another player. Is that right ? If not, kannst Du dein Problem auch kurz auf Deutsch erklären, um weiteren Mißverständnissen vorzubeugen

So let''s assume that this is what you want. The standard way of doing that is as follows: Player A moves around in a 3D scene. His camera matrix gets transfered to Player B. B''s system applies A''s transfered camera matrix as local transformation matrix onto A''s character mesh object. That''s pretty much it. The local camera view of B should, and will not interfere with the local object matrix of A''s character.

In pseudocode, that would look like this:


  

glLoadIdentity();
glLoadMatrixf( This_Players_Camera_Matrix );

for( p = each connected enemy player ) {
m = Network.GetEnemyObjectMatrix(p); // get the local character object matrix of enemy[p]

glPushMatrix(); // push current view matrix onto the stack

glMultMatrixf(m); // multiply the local transform matrix of the current enemy with the view matrix

RenderObject(p); // draw it

glPopMatrix(); // get back view matrix from the stack

}

There won''t be any gimbal lock problems. The local object transform matrix is just normally concatenated with the view matrix, pretty much standard. You should also directly extract the camera matrix from the quaternion you use for your camera model. Not using Euler angles at any point is the best way to avoid gimbal locks of any sort.

/ Yann

Share this post


Link to post
Share on other sites
Puh, now that is what I want.

I thank you Yann L.

Danke

I did not mentioned the multiplayer aspect. That was my 1. fault.

I will test this in the evening - now I have to work a bit for the last days of the year.

thank you

Share this post


Link to post
Share on other sites
quote:

Or what else can I do now?


Not much, without further info. The code above is absolutely standard, and widely used in hierarchical animation, so this can't be the problem. I suspect that you don't actually have a gimbal lock problem, but that something is wrong with the matrix you transfer from the other player.

OK, let's see, if there is a fundamental problem with your engine, or not. Try this:

    

// fill an array with 4 random translations. I assume that your engine

// use x,y as the ground plane, and z goes upwards. If not, adjust the glTranslate and glRotate axes below.

// replace MY_SCALE with something meaningful for your world scale.

float temp[4*2];
for( int a=0; a<4; a++ ) {
temp[a*2+0] = ((float)rand() / (float)RAND_MAX) * MY_SCALE;
temp[a*2+1] = ((float)rand() / (float)RAND_MAX) * MY_SCALE;
}

// Load camera matrix

glLoadMatrixf( This_Players_Camera_Matrix );

float angle = 0.0;

// test code

for( p = each connected enemy player ) {
glPushMatrix(); // push current view matrix onto the stack

glTranslatef(temp[p*2], temp[p*2+1], 0); // translate to random position of this enemy

glRotatef(angle, 0, 0, 1); // rotate around up axis

RenderObject(p); // draw it

glPopMatrix(); // get back view matrix from the stack

angle += 0.5f;
}


What happens, if you run this ?


[edited by - Yann L on December 30, 2002 10:26:20 AM]

Share this post


Link to post
Share on other sites
So here is the result:

4 Ship's are at a random place spinning around there center on the z-axis.

A screenshot for a good example:



the white diamonds are the seperator of the area.

below the radar shows the connected player that is out of view.
the testobject is right infront of the view.

the object spinns around it's origin.

Das Object dreht sich entlang der Achse, die sich vom Cockpit zum Antrieb erstreckt.

The Matrix of the client is posted in the upper left corner.

the other digits are for network checking.

Dominik

[edited by - Dominik_78 on December 30, 2002 1:07:07 PM]

Share this post


Link to post
Share on other sites
Ok, that is correct behaviour. So the error must be in the way you compute your enemy's object matrices. I suspect that you didn't compensate for the different reference coordinate systems.

Try this (I'll explain it in German, so it's perhaps easier to understand, the process is somewhat tricky):

Wenn Spieler A mit seinem Schiff durch den Raum navigiert, ist sein Referenz-Koordinatensystem das Schiff. Der äußere Raum wird um sein Schiff herum gedreht. Wenn er also beispielsweise nach rechts sieht, dreht sich der Raum um ihn herum nach links. Gleiches gilt für die anderen beiden Achsen.

Angenommen, Spieler B sieht Spieler A's (feindliches) Schiff von außen. Nun ist das Referenz Koordinatensystem nicht mehr Spieler A's Schiff, sondern der (fixe) Raum. Das bedeutet, daß Spieler A's Kamera Matrix nicht für das neue Referenzsystem gültig ist, und entsprechend angepasst werden muss. Das geschieht durch Invertieren des Rotationsteiles der Kamaramatrix, der obere 3x3 Teil. Für den Spezialfall einer reinen Rotationsmatrix, wird die Invertierung durch ein einfaches Transponieren des oberen 3x3 Bereiches der Kameramatrix erreicht. Aber Achtung: der Translationsteil ist in diesem Fall nicht mehr gültig. Also: Einheitsmatrix laden, erst mit Translationsmatrix (ohne Rotation), und schließlich mit der transponierten 3x3 Kameramatrix multiplizieren.

Diese so angepasste Matrix kann nun über das Netzwerk versendet, und direkt von einem glMultMatrixf() Befehl verarbeitet werden.

OK, that should work


[edited by - Yann L on December 30, 2002 1:46:25 PM]

Share this post


Link to post
Share on other sites
Transpose ist der englishe Begriff dafür?

Dann hab ich glaube ich eine Funktion in meiner Matrix-klasse dafür. Das Ergebnis sollte ich schnell haben.

ich poste gleich nochmal.


sorry that this is getting to german...

[edited by - Dominik_78 on December 30, 2002 1:56:26 PM]

Share this post


Link to post
Share on other sites
Thank''s Yann,

you are surly a real crack!

This solved the Problem.

I will for now tranfer the hole matrix from the client to the Server. Wouldn''t it be enough to send only the Orientation Quaternion and my Position and do the recalulation on the receiving PC?

Anyway - this helped me a lot. And for the next time I hope I will keep transpose in mind.

I am accually a Database C / Java Programmer and in my sparetime I am trying to develope this multiplayer spaceshooter. I surly let you know as soon as I am finished with the programming and my friends are done with the 3D-Models and sound effects / music.

I hope to have 8-16 players online in the game at once. This is why I want to keep an eye on my bandwidth.

thank you
and I hope this post is understandable to anybody

Dominik

Share this post


Link to post
Share on other sites
quote:

Transpose ist der englishe Begriff dafür?


Yep. Aber nur den oberen 3x3 Bereich ! Viele Matrix Klassen transponieren die volle 4x4 Matrix, das funktioniert in diesem Fall nicht !

Nochmal kurzer Pseudocode:

glLoadIdentity()
glTranslatef( ... ship position ... )
glMultMatrixf( Camera view matrix with transposed 3x3 rotation part, and no translation)

Das Ergebnis ist die Matrix, die Du beim Client benutzen kannst (durch ein glMultMatrixf). Im Prinzip drehst Du das Schiff in der entgegengesetzten Richtung, in der die Kamera des Gegners steht, und schiebst es dann an die richtige Stelle im Raum.

Edit: Oh OK, you got it working

quote:

I will for now tranfer the hole matrix from the client to the Server. Wouldn't it be enough to send only the Orientation Quaternion and my Position and do the recalulation on the receiving PC?


Sure, would also work. Do not forget to transpose, though.


[edited by - Yann L on December 30, 2002 2:14:20 PM]

Share this post


Link to post
Share on other sites
quote:
Original post by Yann L
Yep. Aber nur den oberen 3x3 Bereich ! Viele Matrix Klassen transponieren die volle 4x4 Matrix, das funktioniert in diesem Fall nicht !

Nochmal kurzer Pseudocode:

glLoadIdentity()
glTranslatef( ... ship position ... )
glMultMatrixf( Camera view matrix with transposed 3x3 rotation part, and no translation)

Das Ergebnis ist die Matrix, die Du beim Client benutzen kannst (durch ein glMultMatrixf). Im Prinzip drehst Du das Schiff in der entgegengesetzten Richtung, in der die Kamera des Gegners steht, und schiebst es dann an die richtige Stelle im Raum.




Danke

Ich hab in meiner Matrix Klasse nichts geändert. Ich hab mir die aktuelle Matrix in einen Zwischenspeicher abgesichert.

Dann über die komplette Matrix (4x4) ein "Transpose" ausgeführt und die Indizes 3,7,11,12,13,14,15 in meiner transposed Matrix mit der der gespeicherten überschrieben und dies dann gesendet.


[edited by - Dominik_78 on December 30, 2002 2:34:32 PM]

Share this post


Link to post
Share on other sites
quote:

Dann über die komplette Matrix (4x4) ein "Transpose" ausgeführt und die Indizes 3,7,11,12,13,14,15 in meiner transposed Matrix mit der der gespeicherten überschrieben und dies dann gesendet.


Ach so, so herum geht''s natürlich auch. Ich dachte an eine gezieltes Transpose in der Zielmatrix, ist etwas effizienter. Naja, wird aber wohl kaum einen großen Unterschied machen

Share this post


Link to post
Share on other sites
Kann ich mir Transpose so vorstellen:


vorher:

0 1 2 3
4 5 6 7
8 9 10 11
12 13 14 15

nachher:

0 4 8 12
1 5 9 13
2 6 10 14
3 7 11 15

Die Identity Indizes (0,5,10,15) werden ja nicht berührt.

Hmm ich bau mir in der Klasse einen 3x3Transpose ein. dann geht es ggf. schneller, wie Du gesagt hast. Optimieren wird denk ich mal später eh ein großer Teil sein, den ich verschwende an einigen Stellen noch Bandbreite vom AGP und Speicher und auch CPU-Cycles.


[edited by - Dominik_78 on December 31, 2002 3:11:56 AM]

Share this post


Link to post
Share on other sites
Heh For those interested, this was his problem: He had a multiplayer space shooter, and wanted to map the camera view matrix of each player on the appropriate opponent ship models as viewed from the other players over the network. Turned out that he forgot to take the different coordinate frames into account. A transpose of the camera rotation part solved the problem.

quote:

Kann ich mir Transpose so vorstellen:
[...]


Yes, that''s the definition of it. Basically swapping 6 components.

quote:

Hmm ich bau mit in der Klasse einen 3x3Transpose ein. dann geht es ggf. schneller, wie Du gesagt hast. Optimieren wird denk ich mal später eh ein großer Teil sein, den ich verschwende an einigen Stellen noch Bandbreite vom AGP und Speicher und auch CPU-Cycles


Well, don''t expect a tremdendeous speedup, unless you have lots of players connected to the game. You should definitely treat all other (much more important) bottlenecks first, esp. in the rendering system.

Share this post


Link to post
Share on other sites
Exactly as I thought - the rendering system is the first to optimize - I would like to render triangle strips instead of single triangles, but that would require a recalulation of my 3D models to optimize the order of my vertexes.

So I could've never explained my problem like that. Man, my english is inadequate .

What playeramounts can be achived online?

How do those MMO - Spacecombatgames handle that much information? The Server surly is 1. dedicated and 2. only send clipped data to the client. This would help increasing the playeramount.

with clipped I mean sending only data that is relevant for the client. Sending positions of players miles away in the gameworld would not make much sense.


[edited by - Dominik_78 on December 31, 2002 4:03:09 AM]

Share this post


Link to post
Share on other sites