Ich arbeite an einem 3D-Szeneneditor und möchte die Szene in orthographischer Projektion zeigen. Mein aktuelles Problem ist, dass ich nicht sicher bin, wie ich die orthografische Projektionsmatrix so berechnen soll, dass die Objekte nicht in einer völlig anderen Größe auf dem Bildschirm angezeigt werden.
Ich habe derzeit die folgenden 2 Funktionen zur Berechnung der Kameraprojektionsmatrix.
Matrix4.createPerspective = function(fov, aspect, near, far, result) {
if (typeof result === 'undefined') {
result = new Matrix4();
}
var ymax = near * Math.tan(fov * Math.PI / 360);
var ymin = - ymax;
var xmin = ymin * aspect;
var xmax = ymax * aspect;
Matrix4.createFrustum(xmin, xmax, ymin, ymax, near, far, /*out*/ result);
return result;
};
Matrix4.createOrthographic = function(left, right, top, bottom, near, far, result) {
if (typeof result === 'undefined') {
result = new Matrix4();
}
var re = result.elements;
var w = right - left;
var h = top - bottom;
var p = far - near;
var x = ( right + left ) / w;
var y = ( top + bottom ) / h;
var z = ( far + near ) / p;
re[0] =2/w; re[4] = 0; re[8] = 0; re[12] =-x;
re[1] = 0; re[5] =2/h; re[9] = 0; re[13] =-y;
re[2] = 0; re[6] = 0; re[10] =-2/p; re[14] =-z;
re[3] = 0; re[7] = 0; re[11] = 0; re[15] = 1;
return result;
};
Und so werden sie eingesetzt:
updateProjectionMatrix: function(entity) {
var camera = entity.getComponent('Camera');
if (camera.isDirty()) {
camera.aspect = camera.width / camera.height;
if (camera.isOrthographic()){
Matrix4.createOrthographic(
0,
camera.width,
0,
camera.height,
camera.near,
camera.far,
/*out*/ camera._projectionMatrix);
} else {
Matrix4.createPerspective(
camera.fov,
camera.aspect,
camera.near,
camera.far,
/*out*/ camera._projectionMatrix);
}
}
},
Hier ist ein Beispiel dafür, was ich in Blender erreichen möchte (F5 wechselt zwischen Ortho und Perspektive). Beachten Sie, dass beide Cubes in den Ansichtsfenstern ungefähr gleich groß zu sein scheinen:
camera
projection
viewport
CheerioBacon
quelle
quelle
Antworten:
Erstens
createPerspective
sieht Ihre Funktion nicht ganz richtig aus - vergleichen Sie die verwendeten FormelngluPerspective
.Wenn Sie für beide Kameras dieselbe Ansichtsmatrix verwenden möchten, müssen Sie beim Einrichten der orthografischen Matrix
0, camera.width, 0, camera.height
wahrscheinlich nicht verwenden-0.5*camera.width, 0.5*camera.width, -0.5*camera.height, 0.5*camera.height
. Dadurch bleibt die Ansicht um die Kameraposition zentriert, anstatt die untere linke Ecke der Ansicht an der Kameraposition zu platzieren.Möglicherweise müssen Sie auch unterschiedliche Nah- / Fernwerte für die Orthokamera verwenden, je nachdem, ob in der Orthoansicht die Geometrie hinter der Kamera angezeigt werden soll (was einen negativen Wert in der Nähe der Ebene erfordern würde).
Als Nächstes müssen Sie dann berechnen
camera.width
undcamera.height
basierend auf dem aktuell ausgewählten / fokussierten Objekt, wenn Sie in den orthografischen Modus wechseln. Sie möchten, dass diese Werte die Breite und Höhe des Kegelstumpfs in der Tiefe (Abstand entlang der Z-Achse des Kameraraums) des ausgewählten Objekts darstellen.Wenn Sie eine
gluPerspective
perspektivische Matrix im Stil verwenden, repräsentieren die Komponenten [0, 0] und [1, 1] der Matrix 2 / Breite bzw. 2 / Höhe in einer Tiefe von 1,0 Einheiten von der Kamera. Die Breite und Höhe des Kegelstumpfes skalieren linear mit der Tiefe. Sie müssen sie also nur mit der Tiefe des fokussierten Objekts multiplizieren:Natürlich können Sie die perspektivischen Matrixkomponenten bei Bedarf auch anhand des Sichtfelds und des Seitenverhältnisses neu berechnen.
quelle
var ymax = Math.tan(camera.fov * Math.PI / 360);
var xmax = ymax * camera.aspect;
var width = objectDepth * xmax;
var height = objectDepth * ymax;