3D Rotationspunkt

NicoHatProbleme2

Bekanntes Mitglied
Ich versuche im Moment eine 3D Figur um einen Punkt (0, 0) zu drehen, indem ich die Rotationsmatrix benutze. Ich dachte eigentlich, dass diese dann immer um 0, 0 dreht, da die Figur sich um 0, 0 dreht, wenn ich die einzelnen Punkte von so -100 bis 100 habe und dann erst die richtigen Koordinaten addiere, statt diese direkt zu addieren. Bei so 500 scheint es fast zu funktionieren, doch wenn ich 300er Koordinaten benutze, dreht sich die Figur im Raum um einen bestimmten Punkt. Wieso das?
 

Neumi5694

Top Contributor
Um welche Achse rotierst du? Z? Dann verhält sich das genau so wie unter 2D

Vorgangsweise, um Werte oder Vektoren mit einem Offset zu drehen, aber das Offset nicht zu verändern.
1. Offset abziehen
2. Drehen um eine Achse, die durch (0,0,0) verläuft mit der entsprechenden Matrix
3. Offset hinzuaddieren
 

NicoHatProbleme2

Bekanntes Mitglied
Habs wohl etwas schlecht formuliert... Also, ich versuche, um die y Achse zu drehen, um so eine komplette Kameradrehung zu simulieren (seit mir aufgefallen ist, dass dies dann um einen Punkt dreht), indem ich den offset da lasse. Doch nun dreht sich die Figur nicht wie gedacht um 0,0 , sondern um irgendeinen Punkt
 

Neumi5694

Top Contributor
Mir ist auch aufgefallen, dass die y-Achse, da ich den Standard J-Frame nehme, von oben nach unten geht... Das muss ich dann auch irgendwie umändern
Das nennt sich in Java AffineTransform, das kannst du deinem Graphics-Objekt zuweisen.
Alternativ geht'S natürlich auch, wenn du für die Ausgabe auf den Bildschirm einfach alle Y-Werte entsprechend manuell umrechnest.
Das hab ich in meinem ISO-Renderer so gemacht.

Eine Drehung um die Y-Achse lässt sich letzten Endes auch in 2D realisieren. Nur wenn du eine freie Achse verwendest, ändern sich alle absoluten Koordinaten.

Aber ohne Code lässt sich nicht wirklich sagen, warum sich deine Transformation anders verhält, wenn die Koordinaten größer werden. Sinn ergibt das keinen.
Post den Code mal inklusive dem Code, der die Matrix erstellt. und auch eine daraus berechnete Beispielmatrix.

Wenn es wirklich um irgend was anderes dreht, dann hast du keine reine 3x3 Matrix, sondern eine 3x4 mit einem Offset.
Entweder das, oder die Koordinaten deines Objekts beziehen sich nicht auf den absoluten Nullpunkt, sondern haben ein eigenes Koordinatensystem(und dann müssten sie erst mal nach absolut konvertiert werden).

Wenn du als Objekt z.B. einen Würfel hast, der an einer Koordinate mit 3 Drehwinkeln positioniert ist und die Eckpunktkoordinaten von diesem Mittelpunkt abhängen, dann müsste man das Koordinatensystem in Position verschieben und/oder drehen und nicht die Eckpunkte.
 
Zuletzt bearbeitet:

NicoHatProbleme2

Bekanntes Mitglied
Das hier ist ein Ausschnitt aus der Vektor Klasse:

Code:
public double[] getRotationOnXAxis(Camera camera, double y, double z) {
        Matrix yAndZ = getRotationOnAxis(y, z);
        yAndZ = yAndZ.multiply(getRotationMatrix(camera.xRotation));
        return yAndZ.numbers[0];
    }
    public double[] getRotationOnYAxis(Camera camera, double x, double z) {
        Matrix xAndZ = getRotationOnAxis(x, z);
        xAndZ = xAndZ.multiply(getRotationMatrix(camera.yRotation));
        return xAndZ.numbers[0];
    }
    public double[] getRotationOnZAxis(Camera camera, double x, double y) {
        Matrix xAndY = getRotationOnAxis(x, y);
        xAndY = xAndY.multiply(getRotationMatrix(camera.zRotation));
        return xAndY.numbers[0];
    }
    private Matrix getRotationOnAxis(double firstPos, double secondPos) {
        Matrix rotationOnAxisMatrix = new Matrix(new double[1][2]);
        rotationOnAxisMatrix.numbers[0][0] = firstPos;
        rotationOnAxisMatrix.numbers[0][1] = secondPos;
        
        return rotationOnAxisMatrix;
    }
    private Matrix getRotationMatrix(double theta) {
        Matrix rotationMatrix = new Matrix(new double[2][2]);
        rotationMatrix.numbers[0][0] = Math.cos(theta);
        rotationMatrix.numbers[0][1] = -Math.sin(theta);
        rotationMatrix.numbers[1][0] = Math.sin(theta);
        rotationMatrix.numbers[1][1] = Math.cos(theta);
        return rotationMatrix;
    }
    public double getProjectedX(Camera camera) {
        double x = position.numbers[0][0] + middle.numbers[0][0] - camera.x;
        double y = position.numbers[0][1] + middle.numbers[0][1] - camera.y;
        double z = position.numbers[0][2] + middle.numbers[0][2] - camera.z;
        System.out.println(x + "," + y + "," + z);
        //rotate
        double[] newPos = new double[2];
        newPos = getRotationOnXAxis(camera, y, z);
        y = newPos[0];
        z = newPos[1];
        newPos = getRotationOnYAxis(camera, x, z);
        x = newPos[0];
        z = newPos[1];
        newPos = getRotationOnZAxis(camera, x, y);
        x = newPos[0];
        y = newPos[1];
        return translate(x, z, camera.focalLength);
    }
    public double getProjectedY(Camera camera) {
        double x = position.numbers[0][0] + middle.numbers[0][0] - camera.x;
        double y = position.numbers[0][1] + middle.numbers[0][1] - camera.y;
        double z = position.numbers[0][2] + middle.numbers[0][2] - camera.z;
        //rotate
        double[] newPos = new double[2];
        newPos = getRotationOnXAxis(camera, y, z);
        y = newPos[0];
        z = newPos[1];
        newPos = getRotationOnYAxis(camera, x, z);
        x = newPos[0];
        z = newPos[1];
        newPos = getRotationOnZAxis(camera, x, y);
        x = newPos[0];
        y = newPos[1];
        return translate(y, z, camera.focalLength);
    }
    @SuppressWarnings("deprecation")
    private double translate(double xOrY, double z, double focalLength) {
        //System.out.println(focalLength + "*" + xOrY + "  " + (focalLength + "+" + position.numbers[0][2] + "+" + middle.numbers[0][2]  + "-" + camera.z));
        return new BigDecimal(focalLength*xOrY).divide(
            new BigDecimal(focalLength+z), BigDecimal.ROUND_HALF_DOWN).doubleValue();
    }
 

Neumi5694

Top Contributor
Ich geb's zu, ich werde da nicht besonders schlau draus.
Aber ich sehe hier keinen Grund dafür, warum sich ein Punkt mit einer Koordinate um die 500 anders verhalten sollte als einer bei 300, es sei denn, das kommt von der Kamera, deren Werte du in getProjected abziehst.
 

Neumi5694

Top Contributor
Andere Möglichkeiten gibt's viele. Das hängt ganz vom Datenmodell ab.
In Java3D macht man die Sachen gar nicht manuell, da wird ein Orbitbehaviour zum Rotieren gesetzt. Ich hab mich jetzt nicht ewig lang mit 3D Apis beschäftigt, aber im Normalfall ändert man eben nicht die Objekte, sondern eben die Kamera selbst.
Deshalb sind Rundungsfehler im Normalfall auch kein Thema, da die Koordinaten sich nicht verändern, sondern nur in Bildschirmkoordinaten umgerechnet werden. die meisten Engines arbeiten mit Float. BigDecimal ist dafür kompletter Overkill.

Für die Parallelprojektion meines ISO-Drahtgittermodell-Renderers ändere ich z.B. die Position und Drehung der Teile und deren Sub-Komponenten gar nicht, sondern stelle dann für die Ansicht ein Koordinatensystem zur Verfügung, in welches die Punkte konvertiert werden.
Ich hatte zwar auch schon mit Java3D experimentiert, aber der Aufwand, das vorhandene System zu ersetzen, überstieg den Nutzen.
 

Neue Themen


Oben