2017-03-09 1 views
-1

J'ai un environnement de terrain 3D comme ceci:Comment viser la caméra au z-index de la cellule devant mon personnage?

J'essaie d'obtenir le caractère (caméra) pour rechercher les montées, et regarder vers le bas en descendant, comme l'escalade en temps réel la vie.

C'est ce qu'il fait actuellement:

En ce moment, la caméra se déplace vers le haut et en bas des collines très bien, mais je ne peux pas obtenir l'angle de la caméra fonctionne correctement. La seule façon de penser à viser vers le haut ou vers le bas selon le terrain est d'obtenir l'index z de la cellule que mon personnage est actuellement en train d'affronter, mais je ne sais vraiment pas comment faire. Ceci est vrai pour une mission, et nous n'utilisons pas intentionnellement d'objets, donc les choses sont organisées un peu étrangement.

Voici comment je suis en train de faire les choses:

const int M = 100; // width 
const int N = 100; // height 
double zHeights[M+1][N+1]; // 2D array containing the z-indexes of terrain cells 
double gRX = 1.5; // x position of character 
double gRY = 2.5; // y position of character 
double gDirection = 45; // direction of character 
double gRSpeed = 0.05; // move speed of character 


double getZ(double x, double y) // returns the height of the current cell 
{ 
    double z = .5*sin(x*.25) + .4*sin(y*.15-.43); 
    z += sin(x*.45-.7) * cos(y*.315-.31)+.5; 
    z += sin(x*.15-.97) * sin(y*.35-8.31); 

    double amplitute = 5; 
    z *= amplitute; 
    return z; 
} 

void generateTerrain() 
{ 
    glBegin(GL_QUADS); 

    for (int i = 0; i <= M; i++) 
    { 
     for (int j = 0; j <= N; j++) 
     { 
      zHeights[i][j] = getZ(i,j); 
     } 
    } 
} 

void drawTerrain() 
{ 
    for (int i = 0; i < M; i++) 
    { 
     for (int j = 0; j < N; j++) 
     { 
      glColor3ub((i*34525+j*5245)%256, (i*3456345+j*6757)%256, (i*98776+j*6554544)%256); 
      glVertex3d(i, j, getZ(i,j)); 
      glVertex3d(i, j+1, getZ(i,j+1)); 
      glVertex3d(i+1, j+1, getZ(i+1,j+1)); 
      glVertex3d(i+1, j, getZ(i+1,j)); 
     } 
    } 
} 

void display() // callback to glutDisplayFunc 
{ 
    glEnable(GL_DEPTH_TEST); 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
    glLoadIdentity(); 

    double radians = gDirection /180.*3.141592654; // converts direction to radians 
    double z = getZ((int)gRX, (int)gRY); // casts as int to find z-index in zHeights[][] 
    double dx = cos(radians)*gRSpeed; 
    double dy = sin(radians)*gRSpeed; 
    double at_x = gRX + dx; 
    double at_y = gRY + dy; 
    double at_z = z; // source of problem, no idea what to do 

    gluLookAt(gRX, gRY, z + 2, // eye position 
       at_x, at_y, at_z + 2, // point to look at, also wrong 
       0, 0, 1); // up vector 

    drawTerrain(); 
    glEnd(); 
} 

void init() 
{ 
    generateTerrain(); 
} 
+0

Le produit croisé de votre vecteur avant et en haut vecteur vous donne un vecteur latéral. Le produit croisé de votre vecteur latéral et le vecteur normal de la cellule actuelle vous donneront la direction que vous voulez regarder pour "suivre la pente". Vous pouvez calculer les vecteurs normaux en normalisant le produit croisé des vecteurs de pente de la cellule. Puisque votre fonction de hauteur est dérivable, vous pouvez utiliser la dérivée pour trouver vos vecteurs de pentes à tout moment. De vos images cependant, suivre la courbe doucement ne semble pas être une préoccupation. Dans ce cas, vous pouvez simplement comparer les hauteurs voisines pour trouver vos pentes. –

+0

Addendum: De toute façon, vous aurez besoin de calculer des vecteurs normaux si vous voulez faire un ombrage. –

Répondre

0

Tout d'abord, je ne vois aucune raison de jeter à int ici:

double z = getZ((int)gRX, (int)gRY); 

Il suffit d'utiliser les valeurs double pour obtenir un comportement lisse.

Votre approche de base est déjà plutôt bonne. Vous prenez la position actuelle (gRX, gRY), marchez un peu dans la direction de visualisation (dx, dy) et utilisez-le comme point à regarder. Il y a juste deux petites choses qui ont besoin d'adaptation:

double dx = cos(radians)*gRSpeed; 
double dy = sin(radians)*gRSpeed; 

Bien que la multiplication par gRSpeed pourrait être une bonne idée, à mon avis, ce facteur ne devrait pas être lié à la cinématique du personnage. Au lieu de cela, cela représente la fluidité de la direction de votre vue. Les petites valeurs font que la direction collent très étroitement à la géométrie du terrain, des valeurs plus grandes l'aplanissent.

Et enfin, vous avez besoin d'évaluer la hauteur à votre look au point:

double at_z = getZ(at_x, at_y);