Sprunghafte drehungen und verschiebungen...

Started by Elrohir, May 17, 2009, 05:59:47 PM

Previous topic - Next topic

Elrohir

Guten Abend...
Mein ziel ist es derzeit, eine Kamera nach dem klicken der rechten Maustaste um einen charakter herumdrehen zu können, und nur, wenn man den charakter bewegt,soll dieser mitgedreht werden...
Und falls er sich nicht bewegt, wird der dreh-wert gespeichert und danach auf den charakter angewendet...

So, allerdings habe ich noch kleinere Probleme.... undzwar zuckt die darstellung teilweise, aber das ließe sich hoffentlich noch beheben, und das größere problem, dass du bewegungsrichtung irgentwie scheinbar wahllos ist, obwohl ich mir immer die achsen der Rotationsmatrix hole...
Desweiteren verschiebt sich der charakter von der mitte des Bildschirms aus.... was nicht unbedingt der erwünschte effekt ist^^
Hier einmal der code:
der character ist ein object3D und die camera halt das Camera-objekt... sollte wohl alles durch die namensgebung ersichtlich sein, hoffe ich...

character.setTranslationMatrix(new Matrix());

    SimpleVector pos = new SimpleVector(0,0,0);
    pos.add(new SimpleVector(0, ellipsoid.y, 0));
            SimpleVector dir = world.checkCollisionEllipsoid(pos, grav, ellipsoid, 1);
            pos.add(new SimpleVector(0, -ellipsoid.y, 0));
            dir.x = 0;
            dir.z = 0;
            pos.add(dir);
            pos.add(new SimpleVector(0, ellipsoid.y, 0));
           
if(publickeys.up){
SimpleVector temp = character.getRotationMatrix().getZAxis();
                temp.scalarMul(-moveSpeed);
                temp = world.checkCollisionEllipsoid(pos, temp, ellipsoid, 8);
                pos.add(temp);
                temp.add(dir);
}
if(publickeys.down){
SimpleVector temp = character.getRotationMatrix().getZAxis();
                temp.scalarMul(moveSpeed);
                temp = world.checkCollisionEllipsoid(pos, temp, ellipsoid, 8);
                pos.add(temp);
                temp.add(dir);
}
if(publickeys.right){
SimpleVector temp = character.getRotationMatrix().getXAxis();
                temp.scalarMul(-moveSpeed);
                temp = world.checkCollisionEllipsoid(pos, temp, ellipsoid, 8);
                pos.add(temp);
                temp.add(dir);
}
if(publickeys.left){
SimpleVector temp = character.getRotationMatrix().getXAxis();
                temp.scalarMul(moveSpeed);
                temp = world.checkCollisionEllipsoid(pos, temp, ellipsoid, 8);
                pos.add(temp);
                temp.add(dir);
}
if(publickeys.lookUp){
//camera.moveCamera(Camera.CAMERA_MOVEUP, 10);
}
if(publickeys.lookDown){
//camera.moveCamera(Camera.CAMERA_MOVEDOWN, 10);
}
            pos.add(new SimpleVector(0, -ellipsoid.y, 0));
            synchronized(character){

                character.getTranslation().set(0,0,0);
                character.translate(pos);
                character.translateMesh();
                pos.add(character.getBackPosition());
                character.setBackPosition(pos);
                character.setCenter(pos);
                synchronized(camera){
                camera.moveCamera(Camera.CAMERA_MOVEIN, 300);

                    //camera.setPositionToCenter(character);
        if(publickeys.rotatex){
        float rotynew = 0;
        float mousexnew = mousemapper.getMouseX();
        float difference = -(mousexnew - mousex);
        if(difference>0)
        rotated=true;
        rotynew = difference/210;
        if(rotynew!=0)
        mousex = mousexnew;
        float mouseynew = mousemapper.getMouseY();
        difference = -(mouseynew - mousey);
        if(difference>0)
        rotated=true;
        float rotxnew = difference/210;
        if(rotxnew!=0)
        mousey = mouseynew;
        //camera.rotateCameraY(-roty);
        camera.rotateCameraX(-rotx);
        camera.rotateCameraY(rotynew);
        camera.rotateCameraX(rotx + rotxnew);
        //camera.rotateCameraY(roty + rotynew);
        rotx += rotxnew;
        roty += rotynew;
        rotycharnew += rotynew;
        rotxcharnew += rotxnew;   
        }
       
                    if(publickeys.up || publickeys.down || publickeys.left || publickeys.right){
                    if(rotated){
            character.getRotationMatrix().setIdentity();
            character.rotateY(-rotychar);
            character.rotateX(rotxcharnew);
            character.rotateY(rotychar + rotycharnew);
            rotxchar += rotxcharnew;
            rotychar += rotycharnew;
            rotxcharnew = 0;
            rotycharnew = 0;
            character.rotateMesh();
                    rotated=false;
                    }
                    }
                    camera.moveCamera(Camera.CAMERA_MOVEOUT, 300);

                }
            }

EgonOlsen

Hmm, also so ad hoc fällt mir auf, dass


character.getTranslation().set(0,0,0);


nicht den Zweck erfüllen wird, für den es vermutlich gedacht war. Der Rückgabewert von getTranslation() ist immer ein neuer Simplevector, keine Referenz auf die Translation des Objekts an sich. Besser wäre:


character.getTranslationMatrix().setIdentity();


Weiterhin macht


character.translateMesh();


die Translation permanent im Mesh...ich denke nicht, dass es das ist, was du machen willst.

Ohne jetzt jede Zeile einzeln durchgegangen zu sein, denke ich, dass es vielleicht schon helfen könnte, wenn du beide Zeilen ersatzlos streichst.

Elrohir

#2
Quote from: EgonOlsen on May 18, 2009, 08:07:40 PM
Hmm, also so ad hoc fällt mir auf, dass


character.getTranslation().set(0,0,0);


nicht den Zweck erfüllen wird, für den es vermutlich gedacht war. Der Rückgabewert von getTranslation() ist immer ein neuer Simplevector, keine Referenz auf die Translation des Objekts an sich. Besser wäre:


character.getTranslationMatrix().setIdentity();


Weiterhin macht


character.translateMesh();


die Translation permanent im Mesh...ich denke nicht, dass es das ist, was du machen willst.

Ohne jetzt jede Zeile einzeln durchgegangen zu sein, denke ich, dass es vielleicht schon helfen könnte, wenn du beide Zeilen ersatzlos streichst.


Nunja, nur habe ich dann das problem, dass der charakter sich gar nicht mehr bewegt, wenn ich diese beiden zeilen ersatzlos streiche....
Also, um genau zu sein isses so, dass sich die kamera beim bewegen halt bewegt... der char nicht... und wenn ich rotiert habe, dann bewegt sich die kamera aber immer noch in die axialrichtung des vorigen koordinatensystems.... also das muss iwi schon da hin...

ok, das ist jetzt komisch.... wenn ich das translatemesh drinlasse, dann dreht bewegt sich der char mit... aber nach der drehung trotzdem noch in die gleiche richtung...
allerdings habe ich das gefühlt, dass sich der charakter gar nicht so weit bewegt, dass dessen zentrum dann auch an der position liegt...
denn wenn ich dann die kamera drehe, dreht sie sich scheinbar um einen punkt irgentwo VOR dem charakter.... undzwar weiter vorne, je länger ich ihn bewege...
Desweiteren fällt mir noch auf, dass das bild dann halt immer flackert, weil die cam ja kurzzeitig in dem charakter ist, und wieder rauszoomt... wie kann man ein neuzeichnen währrenddessen umgehen? :o

EDIT: hm, ok, das mit dem neuzeichnen lässt sich ja mit einer boolean-variable einfach steuern.. aber das andre is mir bissher schleierhaft, wieso das nicht funktioniert :o

EgonOlsen

Aber zumindest

character.getTranslation().set(0,0,0);

ist eine Null-Operation. Das macht nichts sinnvolles. Und translateMesh() willst du nicht bei jedem Aufruf machen, weil du damit das gesamte Object im Objectspace verschiebst. Was macht denn setBackPosition() eigentlich?

Ich verstehe auch immer noch nicht wirklich, was genau du erreichen willst...die Kamera dreht sich um die Figur und wenn sich diese ihrerseits bewegt, soll sich diese mitdrehen? Und die Bewegungsrichtung der Figur stimmt dabei nicht? Also, wenn du ein compilierbares Beispiel hättest, wäre das bestimmt sehr hilfreich.

Elrohir

#4
ok, nach einigen weiteren tests habe ich glaube ich das hauptproblem, auf dem das alles basiert ausfindig gemacht...
undzwar dreht sich der charakter nicht in seinem zentrum, sondern er dreht sich um den startpunkt...
Allerdings habe ich noch keine lösung gefunden, um das koordinatensystem für die drehung in den charaktermittelpunkt zu transferieren...
habe schon drüber nachgedacht, den charakter einfach zurückzubewegen.. sah dann  so aus:

if(publickeys.up || publickeys.down || publickeys.left || publickeys.right){
            Matrix mat = character.getTranslationMatrix().cloneMatrix();
            character.setTranslationMatrix(mat.invert());
            character.translateMesh();
                    character.getRotationMatrix().setIdentity();
            character.rotateY(-rotychar);
            character.rotateX(rotxcharnew);
            character.rotateY(rotychar + rotycharnew);
            rotxchar += rotxcharnew;
            rotychar += rotycharnew;
            rotxcharnew = 0;
            rotycharnew = 0;
            character.rotateMesh();
            character.setTranslationMatrix(mat);
            character.translateMesh();
}


jedoch funktionierte es auch damit nicht..
nja, aber auf jeden fall löst das das verschieben problem, da der charakter dann ja von der gedrehten stelle aus sich weiterbewegte, beim zurückdrehen um nicht nicht bewegten drehpunkt, war der abstand zu der kamera, die sich korrekt verhielt natürlich verändert..


ja, diese zeile konnte ich auch streichen....
Nun, was ich erreichen will ist, dass man bei aktiviertem rechtsklick die kamera um den charakter drehen kann...
wenn man sich bewegt, soll der charakter die drehung mitvollziehn... also auch nach drehung der kamera und späterem beginn der bewegung diese drehung "nachholen".... ist mit der steuerung in spielen wie guild wars gut zu vergleichen denke ich ;)

ein kompilierbares beispiel habe ich jetzt leider nicht zu hand, werde die tage aber zusehn, dassich eins zusammenstelle, wenn es bis dahin nicht gelöst ist ;)

EDIT: das backposition speicher einfach den simplevector der momentanen position ab ;)

EgonOlsen

Den Drehpunkt kannst du mit setRotationPivot(...) setzen. Ansonsten kann ich wirklich nur schwer folgen gerade... ??? Du setzt die Translation mittels character.setTranslationMatrix(new Matrix()); immer zurück, ermittelts eine neue in Richtung der Achsen der Rotationsmatrix und rechnest die permanent in das Mesh rein mittels translateMesh()...also erstmal solltest du wirklich diese translateMesh()-Aufrufe loswerden. Die brauchst du nicht und die sind schrecklich langsam und das Resultat ist schwer zu handhaben, weil das Objekt dann eben nicht mehr da im Objectspace steht, wo es mal war, sondern irgendwie bei (-1000, 1981,88232)...das versteht kein Mensch mehr hinterher.
Wenn du character.setTranslationMatrix(new Matrix()); und translateMesh(); rauslässt, sollte das Resultat eigentlich sehr ähnlich dem jetzigen sein.

Die Steuerung in GuildWars kenne ich nicht, deswegen verstehe ich das hier wohl auch nicht...also du drehst du Kamera um die Figur...ok...also sagen wir mal, die sehe die Figur danach so, dass ich auf ihre rechte Seite schaue. Jetzt bewege ich die Figur nach vorne und...da verlässt es mich...wer "holt" hier jetzt welche Bewegung von wem nach?

Elrohir

Quote from: EgonOlsen on May 18, 2009, 09:14:23 PM
Den Drehpunkt kannst du mit setRotationPivot(...) setzen. Ansonsten kann ich wirklich nur schwer folgen gerade... ??? Du setzt die Translation mittels character.setTranslationMatrix(new Matrix()); immer zurück, ermittelts eine neue in Richtung der Achsen der Rotationsmatrix und rechnest die permanent in das Mesh rein mittels translateMesh()...also erstmal solltest du wirklich diese translateMesh()-Aufrufe loswerden. Die brauchst du nicht und die sind schrecklich langsam und das Resultat ist schwer zu handhaben, weil das Objekt dann eben nicht mehr da im Objectspace steht, wo es mal war, sondern irgendwie bei (-1000, 1981,88232)...das versteht kein Mensch mehr hinterher.
Wenn du character.setTranslationMatrix(new Matrix()); und translateMesh(); rauslässt, sollte das Resultat eigentlich sehr ähnlich dem jetzigen sein.

Die Steuerung in GuildWars kenne ich nicht, deswegen verstehe ich das hier wohl auch nicht...also du drehst du Kamera um die Figur...ok...also sagen wir mal, die sehe die Figur danach so, dass ich auf ihre rechte Seite schaue. Jetzt bewege ich die Figur nach vorne und...da verlässt es mich...wer "holt" hier jetzt welche Bewegung von wem nach?

Nungut, das mit der translationsmatrix und dem translatemesh konnte ich wieder entfernen... ich kannte das mit dem rotationpivot leider nicht, und dachte, dass dabei dann das rotationskoordinatensystem verschoben würde...

nja, also das rotieren klappt jetzt fast... nur irgentwie verschiebt sich die position des charakters immer noch teilweise, was aber vermutlich durch die fehlerhafte bewegung ausgelöst wird...
ich werde morgen mal versuchen, das zu beheben, indem ich von dem up-und side-vector der Camera den orthogonal dazu liegenden Vector berechne, und dann den und den Side-vector bei der bewegung benutze statt wie bisher die axen, da diese ja immer in die gleiche richtung zeigen...

zu der letzten frage: an diesem punkt dreht sich die figur dann erst so, dass die kamera nicht mehr von der seite draufguckt, sondern eben wieder von hinten.... deswegen speichere ich halt, wie weit sich die kamera um das objekt gedreht hat, und drehe das objekt dann soweit nach, dass die kamera bei einer bewegung immer genau von hinten draufguckt...

Elrohir

hm, irgentwie will es immer noch nicht so ganz...

Habe jetzt einmal alle nötigen dateien in nem ordner zusammengestellt... ich hoffe mal, du kannst was damit anfangen...
Den quellcode von der bewegung etc. findest du in dem src-ordner..
Die ausführbare datei ist dementsprechend die 3D testview.jar

Ich hoffe sehr, dass eine lösung für das problem gefunden werden kann... (beziehe mich hierbei auf die interessanterweise immer noch vorhandene rotaten NICHT um den mittelpunkt des charakters, und die inzwischen auch leider nicht mehr ganz passende rotation....)

http://upload.worldofplayers.de/files3/VRY503DTestview.rar

EgonOlsen

Kann das irgendwie gerade nicht runterladen...die Sanduhr erscheint und nichts passiert, wenn ich auf deinen Link klicke...ist der Server unten?

Elrohir

#9
Quote from: EgonOlsen on May 22, 2009, 02:18:24 PM
Kann das irgendwie gerade nicht runterladen...die Sanduhr erscheint und nichts passiert, wenn ich auf deinen Link klicke...ist der Server unten?

hm, probiers am besten nochmal, also, ich habs grad nochmal versucht, und es hat ohne probleme funktioniert :o

Aber falls nicht, habe es nochmal auf nem andern server hochgeladen:
http://download.lima-city.de/schattenmagier/3DTestview.rar

EgonOlsen

Ja, jetzt geht's. Ich muss mal sehen, wann ich einen Blick drauf werfen kann...

EgonOlsen

Ok, ich habe eine angepasste Version hochgeladen nach: http://www.jpct.net/download/tmp/Testview.java

Ich habe einige Sachen entfernt, die offenbar nicht verwendet wurden. Z.B. den ganzen Gravitationskram. Wenn der wieder nötig sein sollte, musst du ihn selber reinbauen, aber ich dachte es wäre sinnvoller, schrittweise vorzugehen. Den backPosition-Kram habe ich auch entfernt...wurde ja eh nicht wirklich benutzt.

Noch ein paar Anmerkungen: Rotationen im Gradmaß rotieren zwar irgendwie, aber wirklich sinnvoll nutzbar sind sie in jPCT nicht. jPCT erwartet die Werte im Bogenmaß (statt rotateX(90) dann eben rotateX((float)Math.PI/2f)).
Wenn du Bewegungen und Animationen u.ä. in einem zweiten Thread laufen lässt, musst du das mit dem Rendering synchronisieren. Ansonsten bekommst du alle möglichen Arten von Seiteneffekten. Ich habe das im Quelltext über ein SYNC-Objekt gelöst. Besser wäre es aber, beides in einem Thread zu erledigen.
Dein Kollisionsellipsoid war gigantisch groß. Der jetzige mag nicht wirklich passen, aber wenn du irgendwo Werte wie 200, 400, 200 dafür siehst, dann ist was im Argen.
Was mich auch eine ganze Weile an der Nase herum geführt hat: Du hattest die Figur als Kollisionspartner definiert. Wenn du dann World.checkCollision... nutzt, kollidiert sie quasi mit sich selber. Besser du benutzt für sowas die Methoden in Object3D. Die sorgen bereits dafür, dass ein Objekt nicht gegen sich selber rennt.

Ich hoffe, das hilft dir weiter...

Elrohir

Allerherzlichsten Dank! :)

Die Gravitation hatte ich erst genommen, weil es ein charakter werden sollte, der auf dem boden läuft, doch zu vorführungszwecken erschien ein fliegender Charakter als erstes Modell passender ;)

Zu den Rotationen: ich dachte leider, die Rotationen würden das Gradmaß verlangen... aber in der tat habe ich mich selber schon stark gewundert, warum die Ergebnisse nicht den erwarteten entsprachen^^

zum world.checkCollision: ich hatte gedacht, dass man immer die Welt nehmen muss, weil diese ja alle Objekte in sich "vereint"... danke für die Aufklärung :)


Zusammengefasst: hilft mir sehr weiter! :)^^

Elrohir

So, ich denke mal, das passt noch in dieses Thema, da es immer noch relevant ist...
undzwar geht es jetzt darum, dass nach einigem rumprobieren festgestellt wurde, dass bei den drehungen immer noch eine rotation um die y-achse vorhanden ist, obwohl bei der Methode ja lediglich die x- und z-achse verwendet wurden.
Ein speichern der bereits gedrehten werte dürfte allerdings nichts ändern, denn wenn man die maus nur in Y- oder X-richtung verschiebt, dann dreht sich der character auch wie gewollt um die jeweilige Achse. Nur in Kombination dieser beiden drehungen wird der character auch anders gedreht, sodass die Welt quasi auf dem kopf stehen kann, nachdem man die camera eigentlich vertikal um den character gedreht hat...
vermutlich dafür zu ändernder code-abschnitt:
float differenceX = mousemapper.getDeltaX();
float differenceY = mousemapper.getDeltaY();
SimpleVector line = new SimpleVector(differenceX, 0,
differenceY);
Matrix m = line.normalize().getRotationMatrix();
m.rotateAxis(m.getXAxis(), (float) -Math.PI / 2f);
camera.rotateAxis(m.invert3x3().getXAxis(), line.length() / 200f);[/coe]

EgonOlsen

#14
Hmmm, ja...wenn man quasi "rührt", dann kippt die Kamera langsam...ich bin nicht sicher an was das liegt und ob es überhaupt ein Fehler und nicht auf merkwürdige Art richtig ist (auf den Boden gucken, nach links kippen, nach oben gucken ergibt nämlich z.B. den Blick auf eine schiefe Ebene)... Ich habe mehrere Berechnungswege ausprobiert und alle hatten dieses "Problem". Letztendlich ist diese Art der Bewegung aber vielleicht auch gar nicht das, was man will, sondern eher eine FPS-artige Bewegung (d.h. der Horizont bleibt immer gerade)!?
Abgesehen davon, dass ich mich ungefähr 35 Stunden lang mit der Tatsache vera****t habe, dass du die Rotationsmatrix der Plane nach dem rotateMesh() nicht zurücksetzt, habe ich den entsprechenden Codeteil mal durch eine fps-artige Steuerung ersetzt und die verlinkte Java-Datei mit dieser neuen Version ersetzt. Taugt das für eure Zwecke so?