2010-11-07 3 views
5

J'ai un programme OpenGL (écrit en Delphi) qui permet à l'utilisateur de dessiner un polygone. Je veux le faire pivoter automatiquement autour d'un axe (disons Y asix) et obtenir une forme 3D.OpenGL: Comment transformer une forme 2D en 3D?

Comment est-ce que je peux faire ceci?

Répondre

4

Pour simplifier, vous pouvez forcer au moins un point sur l'axe de rotation. Vous pouvez le faire facilement en ajoutant/soustrayant la même valeur à toutes les valeurs x, et la même valeur à toutes les valeurs y, des points dans le polygone. Il conservera la forme originale.

Le reste n'est pas si difficile. Choisissez un angle qui est assez petit, disons un ou deux degrés, et calculez les coordonnées des sommets du polygone qui tournent autour de l'axe. Ensuite, il suffit de joindre les points avec des fans de triangle et des bandes de triangle.

Pour faire pivoter un point autour d'un axe, il suffit de baser Pythagore. À 0 degré de rotation, vous avez les points à leurs coordonnées 2-d avec une valeur de 0 dans la troisième dimension. Supposons que les points sont en X et Y et que nous tournons autour de Y. La coordonnée X d'origine représente l'hypoténuse. A 1 degré de rotation, on a:

sin(1) = z/hypotenuse 
cos(1) = x/hypotenuse 

(en supposant que les fonctions trigonométriques sur la base diplômes)

pour faire tourner un point (x, y) par angle T autour de l'axe Y afin de produire un point 3D (x «y », z '):

y' = y 
x' = x * cos(T) 
z' = x * sin(T) 

Ainsi, pour chaque point sur le bord du polygone vous produire un cercle de 360 ​​points centrés sur l'axe de rotation.

maintenant faire une forme 3D comme ceci:

  1. créer un «ventilateur de triangle GL en utilisant votre point central et la première matrice de points ayant subi une rotation
  2. pour chaque rangée successive, créer une bande de triangle en utilisant les points de la matrice et les points contenus dans le tableau précédent
  3. finition en créant un autre ventilateur de triangle centré sur le point central et en utilisant les points dans la dernière rangée

One Il est important de noter que les types de fonctions trigonométriques que j'ai utilisés mesurent des angles en radians, et OpenGL utilise des degrés. Pour convertir les degrés en radians, la formule est:

degrees = radians/pi * 180 
+0

Merci pour la réponse! C'était simple et bien expliqué. – Mahm00d

+0

Mon plaisir, @Flom – sje397

0

Si vous voulez juste de tourner, puis:

glRotatef(angle,0,1,0); 

tournera autour de l'axe Y. Si vous voulez un tour, c'est beaucoup plus complexe.

+0

Mon erreur. Par révolution, je voulais dire tour. Je vais éditer la question. – Mahm00d

1

Essentiellement, la stratégie consiste à balayer le profil donné par l'utilisateur autour de l'axe donné et de générer une série de bandes de triangles reliant les tranches adjacentes.

Supposons que l'utilisateur a dessiné le polygone dans le plan XZ. En outre, supposons que l'utilisateur a l'intention de balayer autour de l'axe Z (ie la ligne X = 0) pour générer le solide de révolution, et qu'un des bords du polygone repose sur cet axe (vous pouvez généraliser plus tard). travail).Pour une géométrie assez simple, vous pouvez traiter le périmètre du polygone comme une fonction x = f (z), c'est-à-dire supposer qu'il existe une valeur X unique pour chaque valeur Z. Quand nous allons en 3D, cette fonction devient r = f (z), c'est-à-dire que le rayon est unique sur la longueur de l'objet. Maintenant, supposons que nous voulions approximer le solide avec M "tranches" couvrant chacune 2 * Pi/M radians. Nous utiliserons également N "piles" (échantillons dans la dimension Z). Pour chacune de ces tranches, nous pouvons construire une bande triangulaire reliant les points sur une tranche (i) avec les points sur la tranche (i + 1). Voici un code pseudo-ish décrivant le processus:

double dTheta = 2.0 * pi/M; 
double dZ = (zMax - zMin)/N; 

// Iterate over "slices" 
for (int i = 0; i < M; ++i) { 
    double theta = i * dTheta; 
    double theta_next = (i+1) * dTheta; 

    // Iterate over "stacks": 
    for (int j = 0; j <= N; ++j) { 
    double z = zMin + i * dZ; 

    // Get cross-sectional radius at this Z location from your 2D model (was the 
    // X coordinate in the 2D polygon): 
    double r = f(z); // See above definition 

    // Convert 2D to 3D by sweeping by angle represented by this slice: 
    double x = r * cos(theta); 
    double y = r * sin(theta); 

    // Get coordinates of next slice over so we can join them with a triangle strip: 
    double xNext = r * cos(theta_next); 
    double yNext = r * sin(theta_next); 

    // Add these two points to your triangle strip (heavy pseudocode): 
    strip.AddPoint(x, y, z); 
    strip.AddPoint(xNext, yNext, z); 
    } 
} 

C'est l'idée de base. Comme l'a dit sje697, vous aurez peut-être besoin d'ajouter des embouts pour garder la géométrie fermée (c'est-à-dire un objet solide, plutôt qu'un shell). Mais cela devrait vous donner assez pour vous lancer. Ceci peut facilement être généralisé aux formes toroïdales (bien que vous n'ayez pas de fonction r = f (z) en tête-à-tête dans ce cas).