Comment trouvez-vous la plus grande sphère que vous pouvez dessiner en perspective?
Vu du haut, ce serait ceci:
Ajouté: sur le tronc de droite, j'ai marqué quatre points dont je pense que nous savons quelque chose. Nous pouvons dé-projeter les huit coins du frusum et les centres des extrémités proches et lointaines. Nous connaissons donc les points 1, 3 et 4. Nous savons également que le point 2 est à la même distance de 3 que 4 de 3. Ainsi, nous pouvons calculer le point le plus proche sur la ligne 1 à 4 jusqu'au point 2 afin d'obtenir la centre? Mais les mathématiques et le code réels m'échappent.
Je veux dessiner des modèles (qui sont approximativement sphériques et pour lesquels j'ai une sphère englobante de mini-boule) aussi grands que possible.
Mise à jour: j'ai essayé de mettre en œuvre l'approche incircle sur deux plans comme suggéré par bobobobo et Nathan Reed :
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;
}
J'avoue que je l'aile; J'essaie d'adapter le code 2D en l'étendant en 3 dimensions. Il ne calcule pas l'inspiration correctement; le point central de la sphère semble être à chaque fois sur la ligne entre la caméra et le coin supérieur gauche, et c'est trop grand (ou trop proche). Y a-t-il des erreurs évidentes dans mon code? L'approche, si elle est fixe, fonctionne-t-elle?
Réponses:
Je suppose que votre tronc est symétrique, car votre dessin semble le suggérer. Il y a trois contraintes (deux si votre tronc est 2D):
A. la sphère ne peut pas être plus grande que la distance entre les plans proche et lointain
Si
D
est la distance proche-lointaine, la première contrainte est simplement:B. la sphère ne peut pas s'élargir plus que les plans latéraux
Maintenant, pour l'autre contrainte, disons que
α
c'est le demi-angle du tronc etL
la demi-largeur du plan éloigné, comme le montre ce dessin:La première formule est donnée par trigonométrie dans le triangle. Le second provient de la somme des angles d'un triangle. Ce qui nous donne la deuxième contrainte:
Si votre 3D est frustum, vous aurez une troisième contrainte avec les nouvelles
L
et lesα
valeurs.Résultat final
La
R
valeur que vous recherchez est lamin
des trois bornes.Comment obtenir les paramètres
Si vous pouvez dé-projeter le tronc dans la vue ou l'espace du monde, vous pouvez calculer L, D et α de la manière suivante, où les
P
points sont du plan proche et lesQ
points du plan éloigné:Les flèches signifient des vecteurs, "." est le produit scalaire, et || indique la longueur d'un vecteur. Remplacez
Q2
parQ3
etP2
parP3
pour obtenir L et α dans la dimension verticale.la source
En 2D: considérez le tronc comme un triangle (2D)
Vous voulez ensuite trouver le cercle du triangle.
En tant que problème 3D, vous devez trouver l' inspiration d'une pyramide carrée.
Si j'avais la formule, je l'imprimerais ici, mais hélas, je ne connais pas la formule.
la source
La plus grande sphère possible devrait toucher le plan éloigné (en utilisant les termes pour voir les frustrations ici) en plein centre. Il toucherait également les plans supérieur / inférieur ou gauche / droit, selon l'angle FoV le plus petit. Je dois dire que je n'ai pas de preuve mathématique réelle pour ces hypothèses, mais elles devraient être exactes. Peut-être que quelqu'un a une idée sur la façon de le prouver.
Une sphère peut être définie par son point central et un rayon. Cx et Cy sont les mêmes que le centre du plan éloigné.
Cz et le rayon peuvent être obtenus en résolvant un système d'équation basé sur les hypothèses énumérées ci-dessus.
T est l'un des plans inférieur / supérieur ou gauche / droit (voir ci-dessus) avec t1, t2 et t3 comme vecteur normal normalisé et t4 comme distance depuis l'origine. f est le centre du plan éloigné.
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 est ensuite calculé en insérant cz dans ceci: -fz + cz = r
Vous pouvez obtenir tous les plans à partir de la matrice de projection que vous utilisez. (Pas ViewProjection dans ce cas)
ensuite vous devez déplacer la sphère vers le bon espace: C '= inverse (Voir) * C
la source
J'essaie de faire quelque chose de similaire, et dans mon cas, la vitesse est plus cruciale que la précision tant que la sphère n'existe pas en dehors des limites du tronc.
Si vous calculez la distance la plus courte entre les linéaires (ou faces en 3D), la distance la plus courte trouvée pourrait être utilisée comme le diamètre d'un cercle / sphère qui se trouve entièrement à l'intérieur du tronc. L'origine de l'incircle / insphere pourrait simplement être la moyenne de tous les sommets (somme et division). Ce serait assez rapide et fonctionnerait également pour tous les types de polyèdres convexes.
Le seul inconvénient est que le cercle ou la sphère ne sera pas nécessairement le plus grand cercle ou sphère possible. Pour un tronc avec beaucoup de volume et un bord très court, le cercle / sphère partagerait beaucoup moins d'espace de tronc que possible.
Une autre idée
Si vous voulez l'inspiration d'un tronc de vue 3D et que vous avez la matrice de perspective utilisée pour construire ce tronc, alors vous pouvez simplement utiliser cette matrice sur l'insphère d'un cube unitaire, et cela devrait être une inspiration parfaite pour le tronc. (Le diamètre de l'inspiration d'un cube est la longueur de l'un des bords du cube, le centre est le milieu du cube qui est la moyenne des sommets du cube)
la source