Wie finden Sie die größte Kugel, die Sie perspektivisch zeichnen können?
Von oben gesehen wäre das:
Hinzugefügt: Auf dem Kegelstumpf rechts habe ich vier Punkte markiert, von denen ich glaube, dass wir etwas wissen. Wir können alle acht Ecken des Frusums und die Zentren des nahen und des fernen Endes entfernen. Wir kennen also Punkt 1, 3 und 4. Wir wissen auch, dass Punkt 2 dieselbe Entfernung von 3 wie 4 von 3 hat. Dann können wir den nächsten Punkt auf der Linie 1 bis 4 zu Punkt 2 berechnen, um die zu erhalten Center? Aber die eigentliche Mathematik und der eigentliche Code entgehen mir.
Ich möchte möglichst große Modelle zeichnen (die ungefähr kugelförmig sind und für die ich eine Miniball-Begrenzungskugel habe).
Update: Ich habe versucht, den von Bobobobo und Nathan Reed vorgeschlagenen Incircle -on-Two-Planes-Ansatz zu implementieren :
function getFrustumsInsphere(viewport,invMvpMatrix) {
var midX = viewport[0]+viewport[2]/2,
midY = viewport[1]+viewport[3]/2,
centre = unproject(midX,midY,null,null,viewport,invMvpMatrix),
incircle = function(a,b) {
var c = ray_ray_closest_point_3(a,b);
a = a[1]; // far clip plane
b = b[1]; // far clip plane
c = c[1]; // camera
var A = vec3_length(vec3_sub(b,c)),
B = vec3_length(vec3_sub(a,c)),
C = vec3_length(vec3_sub(a,b)),
P = 1/(A+B+C),
x = ((A*a[0])+(B*a[1])+(C*a[2]))*P,
y = ((A*b[0])+(B*b[1])+(C*b[2]))*P,
z = ((A*c[0])+(B*c[1])+(C*c[2]))*P;
c = [x,y,z]; // now the centre of the incircle
c.push(vec3_length(vec3_sub(centre[1],c))); // add its radius
return c;
},
left = unproject(viewport[0],midY,null,null,viewport,invMvpMatrix),
right = unproject(viewport[2],midY,null,null,viewport,invMvpMatrix),
horiz = incircle(left,right),
top = unproject(midX,viewport[1],null,null,viewport,invMvpMatrix),
bottom = unproject(midX,viewport[3],null,null,viewport,invMvpMatrix),
vert = incircle(top,bottom);
return horiz[3]<vert[3]? horiz: vert;
}
Ich gebe zu, dass ich es fliege; Ich versuche, 2D-Code anzupassen , indem ich ihn auf drei Dimensionen ausdehne. Die insphere wird nicht korrekt berechnet. Der Mittelpunkt der Kugel scheint jedes Mal auf der Linie zwischen der Kamera und der linken oberen Ecke zu liegen und zu groß (oder zu nah) zu sein. Gibt es offensichtliche Fehler in meinem Code? Funktioniert der Ansatz, wenn er fixiert ist?
Antworten:
Ich gehe davon aus, dass Ihr Kegelstumpf symmetrisch ist, da Ihre Zeichnung dies zu suggerieren scheint. Es gibt drei Einschränkungen (zwei, wenn Ihr Kegelstumpf 2D ist):
A. Die Kugel kann nicht größer sein als der Abstand zwischen der nahen und der fernen Ebene
Wenn
D
der Nah-Fern-Abstand ist, ist die erste Einschränkung einfach:B. die Kugel nicht breiter werden kann als die Seitenebenen
Angenommen, die andere Einschränkung
α
ist der halbe Winkel des Kegelstumpfs undL
die halbe Breite der fernen Ebene, wie in dieser Zeichnung gezeigt:Die erste Formel wird durch Trigonometrie im Dreieck angegeben. Die zweite ergibt sich aus der Summe der Winkel eines Dreiecks. Was uns die zweite Einschränkung gibt:
Wenn Ihr Kegelstumpf 3D ist, haben Sie eine dritte Einschränkung mit neuen
L
undα
Werten.Endergebnis
Der
R
Wert, den Sie suchen, ist dermin
der drei Grenzen.Wie bekomme ich die Parameter?
Wenn Sie das Kegelstumpf im Blickfeld oder im Weltraum entfernen können, können Sie L, D und α folgendermaßen berechnen, wobei die
P
Punkte von der nahen Ebene und dieQ
Punkte von der fernen Ebene stammen:Pfeile bedeuten Vektoren, "." Ist das Skalarprodukt und || gibt die Länge eines Vektors an. Ersetzen Sie
Q2
mitQ3
undP2
mitP3
, um L und α in der vertikalen Dimension zu erhalten.quelle
In 2D: Betrachten Sie den Kegelstumpf als Dreieck (2D)
Sie wollen dann die finden incircle des Dreiecks.
Als 3D-Problem müssen Sie die Kugel einer quadratischen Pyramide finden.
Wenn ich die Formel hätte, würde ich sie hier ausdrucken, aber leider kenne ich die Formel nicht.
quelle
Die größtmögliche Kugel sollte die entfernte Ebene (mit den Begriffen für Sichtstörungen hier) genau in der Mitte berühren. Es würde auch die obere / untere oder die linke / rechte Ebene berühren, abhängig davon, welcher FoV-Winkel kleiner ist. Ich muss sagen, dass ich keinen tatsächlichen mathematischen Beweis für diese Annahmen habe, aber sie sollten stimmen. Vielleicht hat jemand eine Idee, wie man das beweisen kann.
Eine Kugel kann durch ihren Mittelpunkt und einen Radius definiert werden. Cx und Cy ist dasselbe wie die Mitte des Flugzeugs.
Cz und der Radius können durch Lösen eines Gleichungssystems basierend auf den oben aufgeführten Annahmen erhalten werden.
T ist entweder die untere / obere Ebene oder die linke / rechte Ebene (siehe oben) mit t1, t2 und t3 als normalisiertem Normalenvektor und t4 als Abstand vom Ursprung. f ist die Mitte des Flugzeugs.
t1 * cx + t2 * cy + t3 * cz - t4 = r
-fz + cz = r
t1 * cx + t2 * cy + t3 * cz - t4 = -fz + cz
t1 * cx + t2 * cy + fz - t2 = + cz - t3 * cz
t1 * cx + t2 * cy - fz - t2 = cz * (1 - t3)
cz = (t1 · cx + t2 · cy - fz - t2) / (1 - t3)
r wird dann durch Einfügen von cz berechnet: -fz + cz = r
Sie können alle Flugzeuge mit der Projektionsmatrix abrufen. (In diesem Fall nicht ViewProjection)
danach müssen Sie die Kugel an die richtige Stelle verschieben: C '= invers (Ansicht) * C
quelle
Ich versuche, etwas Ähnliches zu tun, und in meinem Fall ist Geschwindigkeit wichtiger als Genauigkeit, solange die Kugel nicht außerhalb der Grenzen des Kegelstumpfs existiert.
Wenn Sie den kürzesten Abstand zwischen Liniensegeln (oder Flächen in 3d) berechnen, kann der kürzeste gefundene Abstand als Durchmesser eines Kreises / einer Kugel verwendet werden, der / die vollständig im Kegelstumpf liegt. Der Ursprung des Kreises / der Kugel könnte einfach der Durchschnitt aller Eckpunkte (Summe & Division) sein. Es wäre ziemlich schnell und würde auch für alle Arten von konvexen Polyedern funktionieren.
Der einzige Nachteil ist, dass der Kreis oder die Kugel nicht unbedingt der größtmögliche Kreis oder die größtmögliche Fläche sein muss. Bei einem Kegelstumpf mit viel Volumen und einer sehr kurzen Kante würde sich der Kreis / die Kugel viel weniger als möglich den Kegelstumpfraum teilen.
Eine andere Idee
Wenn Sie die Inspiration eines 3D-Betrachtungsstumpfs wünschen und die Perspektivmatrix haben, die zum Konstruieren dieses Stumpfs verwendet wird, können Sie diese Matrix einfach auf der Inspiration eines Einheitswürfels verwenden, und dies sollte eine perfekte Inspiration für den Stumpf sein. (Der Durchmesser der Insphäre eines Würfels ist die Länge einer der Würfelkanten, der Mittelpunkt ist die Mitte des Würfels, die den Durchschnitt der Scheitelpunkte des Würfels darstellt.)
quelle