Comment puis-je trouver la plus grande sphère qui s'insère à l'intérieur d'un tronc?

12

Comment trouvez-vous la plus grande sphère que vous pouvez dessiner en perspective?

Vu du haut, ce serait ceci:

entrez la description de l'image ici

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?

Volonté
la source
La sphère doit-elle être entièrement de l'autre côté du plan lointain comme dans l'image?
Mikael Högström
@ MikaelHögström J'imagine qu'ils auraient dû l'être pour être le plus grand possible?
Will
Hmm je suppose que cela dépend de votre objectif ... Si vous dessinez une sphère avec une moitié au-delà du plan lointain, ce serait plus grand, mais peut-être que cela va à l'encontre de votre objectif?
Mikael Högström
@ MikaelHögström aha Je comprends votre question; oui je veux que tout le modèle soit dessiné, pas de plan lointain qui le traverse.
Will

Réponses:

12

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 Dest la distance proche-lointaine, la première contrainte est simplement:

R  D / 2

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 et Lla demi-largeur du plan éloigné, comme le montre ce dessin:

tronc

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:

R  L tan((π - 2α) / 4)

Si votre 3D est frustum, vous aurez une troisième contrainte avec les nouvelles Let les αvaleurs.

Résultat final

La Rvaleur que vous recherchez est la mindes 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 Ppoints sont du plan proche et les Qpoints du plan éloigné:

formule2

Les flèches signifient des vecteurs, "." est le produit scalaire, et || indique la longueur d'un vecteur. Remplacez Q2par Q3et P2par P3pour obtenir L et α dans la dimension verticale.

sam hocevar
la source
Comment, à partir du tronc (calculé en dé-projetant les points de vue pour vous rapprocher et vous éloigner), déterminez-vous le champ de vision? Et en 3D, il n'y a que deux choix, pas trois, non? Mes tentatives pour mettre votre algorithme en code me donnent toujours un très gros R.
Will
@Vais-je ajouter un deuxième dessin avec des formules qui, je l'espère, vous aideront.
sam hocevar
2

En 2D: considérez le tronc comme un triangle (2D)

entrez la description de l'image ici

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.

bobobobo
la source
2
Il suffit probablement de trouver le cercle incurvé du tronc vertical ou horizontal en 2D, selon celui qui a le plus petit champ de vision, au moins pour les troncs "standard" (non cisaillés ou quoi que ce soit).
Nathan Reed
1

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

Luis W
la source
1

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)

zeroth
la source