Ball is Kaputt

Status
Nicht offen für weitere Antworten.

suelman

Mitglied
Hi,
Kleines Rotationsproblem:


Bewegung in 2 Richtungen:
X und Z.
Geschwindigkeit speedX/speedZ

Ball rollt im begrenzten Spielfeld.
Sprich:
Wenn posZ>zMax speedZ*=-1;
...

Für die Rotation des Balls im 3dRaum in etwa:

speed = Math.sqrt(speedX*speedX+speedZ*speedZ);

angle = Math.atan2(speedZ, speedX)

//rotation:
gl.gl_Rotatef(gesRotation+=speed, Math.cos(angle),0,-Math.sin(angle));

So, der ganze Schmu haut auch soweit hin. Der Ball rollt wunderbar übers Spielfeld.
ABER:
jedesmal wenn er an der Spielbegrenzung abprallt, sprich
speedZ*=-1;
oder
speedX*=-1;

haut das für einen Frame mit der Rotation nicht mehr hin. Ist ganz logisch, weil sich die Drehrichtung hart ändert.
Bsp: nehmen wir an
speedX sei 0;
speedZ = 1;
gesRotaion ist 90;

nun ändert speedZ sein Vorzeichen.

Damit die Rotation noch passt muss

gl.gl_RotateF(90,0,0,1)

nach dem Vorzeichenwechsel zu

gl.gl_RotateF(270,0,0,-1)

werden.


Überseh ich da irgendwas oder muss ich das Problem anders angehen ?
 

Marco13

Top Contributor
???:L Beschreib' mal etwas genauer, wie dieser ... ... ... Zusammenhang zwischen Geschwindigkeit und Rotation .... ... ... zustande kommt....
 

suelman

Mitglied
Marco13 hat gesagt.:
???:L Beschreib' mal etwas genauer, wie dieser ... ... ... Zusammenhang zwischen Geschwindigkeit und Rotation .... ... ... zustande kommt....

also der Rotationswinkel (Gesmatwinkel) wird durch gesRotation+=speed gegeben

vlg( gl.gl_Rotatef(gesRotation+=speed, Math.cos(angle),0,-Math.sin(angle)); )

die nächsten drei Parameter geben die Rotation in x,y,z richtung (bei mir ist x und z ausreichend).
Diese liegen immer zwischen -1 und 1.

Und wie gesagt. das rollen funktioniert. Nur bei einem Richtungswechsel n.B. z wird zu -z springt er ja quasie um
gesRotation in die entgegengesetzte richtung. Und genau da hauts nicht hin. Sprich bei einem Vorzeichenwechsel von z müsste er auch -gesRotation machen. aber So einfach ists ja nicht, weil ich ja anteilig auch noch in x richtung drehe.
Das rollen selber in die entgegengesetzte richtung ist auch richtig.

axo. und die Rotation geht fortlaufen. Sprich wenn 360 grad überschritten ists so als fängt gl.gl_Rotatef wieder bei 0 an ...
 
S

Spacerat

Gast
Hmm...

Das mus kein Rechenfehler sein. Das liegt glaube ich an GL. Transformations-Befehle wirken additiv auf die aktuelle Matrix. Möglicherweise fehlt hier, da und dort nur ein gl_loadIdentity(). Im Zweifelsfalle sollte man dann auch mit gl_pushMatrix() und gl_popMatrix() arbeiten. Hat lange gedauert, bis ich das auf der Reihe hatte.

Allerdings, wenn daran gedacht wurde, bräuchte ich mal einblick in etwas vorhandenen Code.

mfg Spacerat
 

Marco13

Top Contributor
So ganz hab' ichs immernoch nicht kapiert: Du hast eine Rollrichtung auf einer Ebene. Der Ball rollt über die Ebene und dreht sich dabei, wobei die Drehachse senkrecht auf der Rollrichtung (und parallel zur Rollebene) liegt. Wenn der Ball abprallen soll, muss man sich genau überlegen (oder darüber philosophieren) wie die Drehachse danach sein soll - im Zweifelsfall wieder senkrecht zur (neuen) Rollrichtung - das komplizierte ist vmtl. der richtige (stetige) Übergang zwischen diesen Richtungen - meintest du das?
 

suelman

Mitglied
Marco13 hat gesagt.:
...- im Zweifelsfall wieder senkrecht zur (neuen) Rollrichtung - das komplizierte ist vmtl. der richtige (stetige) Übergang zwischen diesen Richtungen - meintest du das?

Marco, du formulierst immer so dass man es versteht. Das ist genau was ich meine. Nur ebend nicht senkrecht, das braucht nicht umbedingt, da es für mich reicht, wenn der ball normal rollt. Die drehrichtung ist anteilig aufgeteilt in x und z richtung (y richtung ist quasi vertikal, x und z horizontal und ebend in die ebene hinein). Definiert durch >>Math.cos(angle),0,-Math.sin(angle)
Das Problem liegt genau in den Übergängen der Drehrichtung.

dreht man z.B. nur in z richtung könnte man das einfach lösen indem man mit
gl.gl_Rotatef(-gesRotation+=speed, Math.cos(angle),0,-Math.sin(angle));
statt
>>gl.gl_Rotatef(gesRotation+=speed, Math.cos(angle),0,-Math.sin(angle)); rotieren würde, aber da schlägt die anteilige drehung der x achse sofern nicht gilt: z=1 und x=0 bzw z=-1 und x= 0, böse mit.

@Spacerat
Also die schilderung des Problems mit meinem pseudocode sollte eigentlich reichen um das Problem zu diskutieren. Das mit dem Load Identity / Push und Pop hab ich mitlerweile eigentlich ganz gut verstanden meine ich, aber wenns dir(und damit ev auch mir) hilft ...

Code:
gl.glLoadIdentity();
//...
gl.glPushMatrix();

//translate to x,y,z position
gl.glTranslatef(pos.x, pos.y, pos.z);
//Rotate ball (tan b = Ankatete / Gegenkatete)
if(rotX==0){
	angle = 0;
}else{
	angle = (float)Math.atan2(rotZ, rotX);
}
rotationSpeed = (float) Math.sqrt((rotX*rotX)+(rotZ*rotZ));
rotationX-=rotationSpeed*Globals.BALL_SPEED_MULTIPLICATOR;
gl.glRotatef(rotationX, -(float)Math.sin(angle), 0, (float)Math.cos(angle));
//set Material
gl.glMaterialfv(GL.GL_FRONT, GL.GL_AMBIENT, Materials.Ball_ambient,0);
gl.glMaterialfv(GL.GL_FRONT, GL.GL_DIFFUSE, Materials.Ball_diffuse,0);
gl.glMaterialfv(GL.GL_FRONT, GL.GL_SPECULAR, Materials.Ball_specular,0);
gl.glMaterialfv(GL.GL_FRONT, GL.GL_EMISSION, Materials.Ball_emissiv,0);
gl.glMaterialf(GL.GL_FRONT, GL.GL_SHININESS, Materials.Ball_shininess);
//enable and set textures
gl.glEnable(GL.GL_NORMALIZE);
gl.glActiveTexture(GL.GL_TEXTURE0);
gl.glEnable(GL.GL_TEXTURE_2D);
gl.glBindTexture(GL.GL_TEXTURE_2D,texture0);
gl.glUniform1iARB(gl.glGetUniformLocationARB(prog.m_programObject, "texture0"), 0);
gl.glActiveTexture(GL.GL_TEXTURE1);
gl.glBindTexture(GL.GL_TEXTURE_2D, bumpMap);
gl.glUniform1iARB(gl.glGetUniformLocationARB(prog.m_programObject, "texture1"), 1);

gl.glCallList(list);
gl.glPopMatrix();
gl.glActiveTexture(GL.GL_TEXTURE0);
gl.glDisable(GL.GL_TEXTURE_2D);
gl.glActiveTexture(GL.GL_TEXTURE1);
gl.glDisable(GL.GL_TEXTURE_2D);
[!code]
 

Marco13

Top Contributor
Hm... das könnte ein bißchen fummelig werden - zumindest fällt mir spontan keine schöne "Fingerschnipp-Zauberlösung" ein... ein erster Ansatz wäre, die Rotation des Balles nicht nur als einen float-Wert zu speichern, sondern ... hm ???:L (ja, ganz brutal erstmal, um den Ansatz zu verdeutlichen: ) als komplette Matrix. Die Matrix wird dann bei jedem Dreh-Schritt (also überall da, wo du im Moment
rotationX-=rotationSpeed*Globals.BALL_SPEED_MULTIPLICATOR;
machst) mit einer Matrix multipliziert, die nur das Delta beschreibt - also sowas wie
Code:
float angleDelta = rotationSpeed*Globals.BALL_SPEED_MULTIPLICATOR;
Vector currentAxis = new Vector(-(float)Math.sin(angle), 0, (float)Math.cos(angle));
Matrix rotationDelta = new Matrix(currentVector, angleDelta);
currentRotation.multiplyWith(rotationDelta);
gl.glMultMatrix(currentRotation);
Das ist natürlich in gewisser Hinsicht die Holzhammer-Methode, aber müßte zum Testen relativ leicht zu implementieren sein, und wenn's dann hübsch aussieht, kann man überlegen, ob man's noch schöner, "sauberer" und effizienter hinkriegt...
 

suelman

Mitglied
Ah, das sieht allerdings recht gut aus. das könnte klappen. Werds leider erst Sonntag/spätestestens Montag versuchen können. Aber auf den ersten Blick würd ich sagen der Ansatz sieht sehr gut aus. Wobei ich mal schnell dazwischen schieben möchte, so auf den ersten Blick und als Verständnisfrage:

mit
Code:
Matrix rotationDelta = new Matrix(currentVector, angleDelta);


meinst du doch bestimmt
Code:
Matrix rotationDelta = new Matrix(currentAxis, angleDelta);
oder wo kommt der currentVector auf mal her ?

MFG und danke !!! (vorerst :) ich werd auf jeden noch posten obs dann geklappt hat)
 
S

Spacerat

Gast
Möglicherweise hilft dann das ja...
Code:
gl.glRotatef(rotationX, -(float) Math.sin(angle), 0, 0);
gl.glRotatef(rotationZ, 0, 0, (float)Math.cos(angle));
Natürlich muß "rotationZ" dafür noch berechnet werden (ggf. "=-rotationX"). Zumindest werden die Achsen damit unabhängig voneinander rotiert. Bevor du aber mit diesen Matrix und Vector-Klassen losrennst (immer diese Overheads frisst Speicher und Performance), schau dir noch mal an welche Möglichkeiten JOGL (ist doch JOGL oder? ...sieht jedenfalls danach aus) dafür bietet. Ich rede da gerade von "LoadMatrix" und GetMatrix. Damit kann man diese Berechnungen auf Basis von Primitivtypen durchführen.

mfg Spacerat
 

Marco13

Top Contributor
Das wäre natürlich eine einfachere Lösung. Meistens ist es so: Für jedes Problem gibt es eine Lösung, die einfach, elegant... und falsch ist. Ich müßte mich da jetzt auch erstmal mit Bleistift und Papier hinsetzen, um mit Sicherheit sagen zu können, dass das so nicht funktioniert, aber ich "glaube", dass es nicht funktioniert: Die Drehachsen ändern sich ja, und im Moment des Abprallens befindet sich der Ball in einer bestimmten "Konfiguration", die man mit zwei Euler-Winkeln nicht unbedingt beschreiben kann, und die als "Ausgangslage" für alle weiteren Drehungen dienen muss. Aber der TO kann es natürlich auch auf die einfache Variante versuchen :)
 
G

Guest

Gast
Spacerat hat gesagt.:
Möglicherweise hilft dann das ja...
Code:
gl.glRotatef(rotationX, -(float) Math.sin(angle), 0, 0);
gl.glRotatef(rotationZ, 0, 0, (float)Math.cos(angle));
Natürlich muß "rotationZ" dafür noch berechnet werden (ggf. "=-rotationX"). Zumindest werden die Achsen damit unabhängig voneinander rotiert. Bevor du aber mit diesen Matrix und Vector-Klassen losrennst (immer diese Overheads frisst Speicher und Performance), schau dir noch mal an welche Möglichkeiten JOGL (ist doch JOGL oder? ...sieht jedenfalls danach aus) dafür bietet. Ich rede da gerade von "LoadMatrix" und GetMatrix. Damit kann man diese Berechnungen auf Basis von Primitivtypen durchführen.

mfg Spacerat

Also das hab ich schon probiert gehabt.

und wegen

Spacerat hat gesagt.:
...Natürlich muß "rotationZ" dafür noch berechnet werden
ja das muss anders berechnet werden. es spielt da ja sogar eine rolle in welcher reihenfolge rotiert wird. Zudem ist 'mein' Problem damit ja noch nicht aus der Welt. Zudem muss bei dem 'Spacerat' Ansatz auch noch um die Y-Achse rotiert werden, weil nach der Rotation um die X-Achse sich die Z-Achse Verschoben hat.

Ich werd mir da lieber erstmal ersteren Ansatz zur Brust nehmen, der hat mehr Perspektive. Dazu muss ich ja lediglich die Positionstransformation immer relativ abhängig zu der Vorherigen Position berechnen, ansonsten hab ich kaum Änderungen an der Formel. Und das bischen Performance was verlohren geht ist nebensächlich. (Jedenfalls für mein kleines Spielchen). ...
 

suelman

Mitglied
Also, jetzt wo ich es implementiert und das verhalten gesehen hab, erscheint es offensichtlicht.
Marco13, der Ansatz ist ursprünglich gut, aber:
Das kann natürlich auch nicht gehen. Quasie das selbe fenomen was ich darüber bei spacerat beschreiben hab. Sobald ich die alte Matrix nehme, (also nach der letzten teildrehung) haben sich die Drehachsen schon ein stück verändert. Die Anschließende Drehung muss dann natürlich auch relativ dazu mit angepassten drehachsen sein. Womit sich der ball mit einem einfachen
Code:
gl.glRotatef(-rotationSpeed*Globals.BALL_SPEED_MULTIPLICATOR, (float)Math.cos(angle), 0, (float)Math.sin(angle));
natürlich wild in alle richtungen dreht.
Ich wette man kann mein problem viel einfacher lösen als die Verschiebung der Drehachsen zu bestimmen. Wir kommen nur nicht drauf.

(Lautes Verdammtgerufe)
 

Marco13

Top Contributor
Ich tippe mal darauf, dass es auch mit der Reihenfolge der Multiplikationen zu tun hat. Kannst du ein FERTIG COMPILIERBARES!!! Beispielprogramm posten?
 

Ebenius

Top Contributor
suelman hat gesagt.:
Marco13 hat gesagt.:
Ich tippe mal darauf, dass es auch mit der Reihenfolge der Multiplikationen zu tun hat.
ich eher weniger, weil das eigentliche rollen auf der ebene Funktioniert

Marco13 hat gesagt.:
Kannst du ein FERTIG COMPILIERBARES!!! Beispielprogramm posten?

Ich wüsste nicht wie/hab kein onlinespeicher zur Verfügung
Du hast doch Eigene Dateien... Als ZIP packen, hochladen, rechtsklick auf den Link, Link posten. :cool:
 

suelman

Mitglied
Jaaaa, das problem ist aber dass da was von max 512 kB steht. Das reicht nicht annähernd und das so abzuspecken dass ich das ich das auf 512kb bekomme ist mehr arbeit als das neu zu schreiben, und bevor ich mich daran setze kann ich mich besser an die lösung des problems machen ...
 

suelman

Mitglied
Marco, du hattest recht, war doch "mehr oder weniger" n reihenfolgefehler drin nachdem ich mich an deinen Ansatz gemacht hab. aber nu läufts
hier der code (falls es noch interessiert)

Code:
		gl.glPushMatrix();
		//translate to x,y,z position
		gl.glTranslatef(pos.x, pos.y, pos.z);
		gl.glGetFloatv(GL.GL_MODELVIEW_MATRIX, transform_matrix, 0);
		//Rotate ball (tan b = Ankatete / Gegenkatete)
		angle = (float)Math.atan2(rotZ, rotX);
		rotation = (float) Math.sqrt((rotX*rotX)+(rotZ*rotZ))*Globals.BALL_SPEED_MULTIPLICATOR;
		// no Transformation bevor rotation so start from the identity
		gl.glLoadIdentity();
		gl.glRotatef(-rotation, -(float)Math.sin(angle), 0, (float)Math.cos(angle));
		gl.glGetFloatv(GL.GL_MODELVIEW_MATRIX, matrix, 0);
		//multiply last new Rotation with last rotation
		gl.glLoadMatrixf(matrix, 0);
		gl.glMultMatrixf(old_matrix, 0);
		//multiply transformation and rotation
		gl.glGetFloatv(GL.GL_MODELVIEW_MATRIX, old_matrix, 0);
		gl.glLoadMatrixf(transform_matrix, 0);
		gl.glMultMatrixf(old_matrix, 0);
		//set materials and paint...

Nochmals danke für eure bemühungen !!
 
Status
Nicht offen für weitere Antworten.

Ähnliche Java Themen

Neue Themen


Oben