Digamos que tengo una estructura de datos como la siguiente:

Camera {
   double x, y, z

   /** ideally the camera angle is positioned to aim at the 0,0,0 point */
   double angleX, angleY, angleZ;
}

SomePointIn3DSpace {
   double x, y, z
}

ScreenData {
   /** Convert from some point 3d space to 2d space, end up with x, y */
   int x_screenPositionOfPt, y_screenPositionOfPt

   double zFar = 100;

   int width=640, height=480
}

Sin recorte de pantalla o mucho de nada, ¿cómo iba yo a calcular la pantalla de posición x,y de algún punto dado algunos puntos 3d en el espacio. Quiero proyecto que punto 3d en la pantalla 2d.

Camera.x = 0
Camera.y = 10;
Camera.z = -10;


/** ideally, I want the camera to point at the ground at 3d space 0,0,0 */
Camera.angleX = ???;
Camera.angleY = ????
Camera.angleZ = ????;

SomePointIn3DSpace.x = 5;
SomePointIn3DSpace.y = 5;
SomePointIn3DSpace.z = 5;

ScreenData.x e y es la pantalla de la posición x del punto 3d en el espacio. ¿Cómo puedo calcular esos valores?

Podría utilizar las ecuaciones que se encuentran aquí, pero no entiendo cómo la anchura/altura de pantalla entra en juego. También, no entiendo en la entrada de la wiki ¿qué es el visor de posición del vers la posición de la cámara.

http://en.wikipedia.org/wiki/3D_projection

InformationsquelleAutor Berlin Brown | 2011-12-26

8 Comentarios

  1. 48

    El ‘cómo se hace’ es el uso homogéneo de las transformaciones de coordenadas. Usted toma un punto en el espacio y:

    • La posición relativa de la cámara utilizando el modelo de la matriz.
    • Proyecto sea orthographically o en perspectiva el uso de la matriz de proyección.
    • Aplicar la ventanilla trnasformation para colocarlo en la pantalla.

    Esto se pone muy vago, pero voy a tratar de cubrir el importante bits y dejar algo de él para usted. Supongo que usted entienda los conceptos básicos de la matriz de matemáticas :).

    Homogénea Vectores, Puntos, Transformaciones

    En 3D, un homogénea punto sería una columna de la matriz de la forma [x, y, z, 1]. El componente final es la ‘w’, un factor de escala, que para los vectores es 0: esto tiene el efecto de que no se puede traducir en vectores, que es matemáticamente correcta. No vamos a ir allí, estamos hablando de puntos.

    Homogénea transformaciones son matrices de 4×4, utilizar debido a que permite la traducción para ser representada como una multiplicación de la matriz, en lugar de una adición, que es agradable y rápido para su tarjeta de video. También es conveniente porque se puede representar sucesivas transformaciones mediante la multiplicación de ellos juntos. Nos aplicar transformaciones a los puntos por la realización de la transformación * punto.

    Hay 3 principales transformaciones homogéneas:

    Hay otras, especialmente en la ‘mira’ de transformación, que vale la pena explorar. Sin embargo, yo sólo quería dar una breve lista y un par de enlaces. Aplicación sucesiva de mover, escalar y rotar aplicado a los puntos colectiva es el modelo de la matriz de transformación, y los coloca en la escena, en relación a la cámara. Es importante darse cuenta de lo que estamos haciendo es muy similar a los objetos en movimiento alrededor de la cámara, no la otra manera alrededor.

    Ortográficas y de Perspectiva

    A la transformación de coordenadas universales a coordenadas de pantalla, primero se debe usar una matriz de proyección, que, normalmente, vienen en dos sabores:

    • Ortográficas, comúnmente utilizados para 2D y CAD.
    • Perspectiva, buena para juegos y entornos 3D.

    Una proyección ortográfica de la matriz se construye como sigue:

    Básicos de render 3D de proyección de perspectiva en 2D de la pantalla con la cámara (sin opengl)

    Donde los parámetros son:

    • Superior: La coordenada Y del borde superior del espacio visible.
    • Inferior: La coordenada Y del borde inferior del espacio visible.
    • Izquierda: La coordenada X de la esquina izquierda del espacio visible.
    • Derecho: La coordenada X del borde derecho del espacio visible.

    Creo que es bastante simple. Lo que establece es una zona del espacio que va a aparecer en la pantalla, que se puede cortar la contra. Es muy sencillo aquí, porque el área de espacio visible es un rectángulo. El recorte en perspectiva es más complicado debido a que el área que aparece en la pantalla o la visualización de volumen, es un frustrum.

    Si usted está teniendo un momento difícil con la wikipedia en la proyección en perspectiva, Aquí está el código para construir una matriz adecuada, cortesía de geeks3D

    void BuildPerspProjMat(float *m, float fov, float aspect,
    float znear, float zfar)
    {
      float xymax = znear * tan(fov * PI_OVER_360);
      float ymin = -xymax;
      float xmin = -xymax;
    
      float width = xymax - xmin;
      float height = xymax - ymin;
    
      float depth = zfar - znear;
      float q = -(zfar + znear) / depth;
      float qn = -2 * (zfar * znear) / depth;
    
      float w = 2 * znear / width;
      w = w / aspect;
      float h = 2 * znear / height;
    
      m[0]  = w;
      m[1]  = 0;
      m[2]  = 0;
      m[3]  = 0;
    
      m[4]  = 0;
      m[5]  = h;
      m[6]  = 0;
      m[7]  = 0;
    
      m[8]  = 0;
      m[9]  = 0;
      m[10] = q;
      m[11] = -1;
    
      m[12] = 0;
      m[13] = 0;
      m[14] = qn;
      m[15] = 0;
    }

    Variables son:

    • fov: Campo de visión, pi/4 radianes es un buen valor.
    • aspecto: Relación de la altura a la anchura.
    • znear, zfar: se utiliza para el recorte, voy a ignorar estos.

    y la matriz generada es la columna principal, el índice de la siguiente manera en el código anterior:

    0   4   8  12
    1   5   9  13
    2   6  10  14
    3   7  11  15

    De La Ventanilla De Transformación, Las Coordenadas De Pantalla

    Tanto de estas transformaciones requieren de otra matriz matriz para poner las cosas en coordenadas de pantalla, llamó a la ventanilla de la transformación. Que se describe aquí, no voy a cubrir (es muy sencillo).

    Por lo tanto, para que un punto p, se tendría que:

    • Realizar la transformación del modelo de matriz * p, lo que resulta en la tarde.
    • Realizar la matriz de proyección * pm, resultando en pp.
    • De recorte del pp en contra de la visualización de volumen.
    • Realizar la ventanilla de la matriz de transformación * pp, resultando ps: punto de la pantalla.

    Resumen

    Espero que cubre la mayor parte de ella. Hay agujeros en el anterior y es vago en los lugares, publicar cualquier pregunta a continuación. Este tema es generalmente digno de todo un capítulo en un libro de texto, yo he hecho mi mejor esfuerzo para destilar el proceso, esperemos que a su ventaja!

    He enlazado a esta arriba, pero le recomiendo que lea esto, y descargar el archivo binario. Es una excelente herramienta para profundizar en su comprensión de estas transformaciones y cómo se lleva los puntos en la pantalla:

    http://www.songho.ca/opengl/gl_transform.html

    Tan lejos como trabajo real, deberá implementar una matriz de 4×4 clase homogéneo y transformaciones, así como un conjunto homogéneo de la clase point puede multiplicar en contra de aplicar transformaciones (recuerde que [x, y, z, 1]). Necesita generar las transformaciones como se describió anteriormente y en los vínculos. No es tan difícil una vez que usted entiende el procedimiento. La mejor de las suertes :).

    • De largo y de gran respuesta, merece un upvote !
  2. 10

    @BerlinBrown solo como comentario general, usted no debe guardar su rotación de la cámara como X,Y,Z ángulos, ya que esto puede conducir a una ambigüedad.

    Por ejemplo, x=60degrees es el mismo que -300 grados. Cuando el uso de x,y y z el número de ambigua posibilidades son muy altas.

    Lugar, trate de usar dos puntos en el espacio 3D, x1,y1,z1 para la ubicación de la cámara y x2,y2,z2 para la cámara «destino». Los ángulos se pueden atrasadas calculadas a/desde el/lugar de destino, pero en mi opinión esto no es recomendable. El uso de una ubicación de la cámara/objetivo que le permite construir un «LookAt» vector el cual es un vector unitario en la dirección de la cámara (v’). De esto también se puede construir un LookAt matriz, la cual es una matriz de 4×4 que se utiliza para proyectar los objetos en el espacio 3D a los píxeles en el espacio 2D.

    Consulte esta pregunta relacionada con la, donde hablo sobre cómo calcular un vector de R, que es en el plano ortogonal a la cámara.

    Dado un vector de la cámara de destino, v = xi, yj, zk

    Normalizar el vector, v’ = xi, yj, zk /sqrt(x^2 + yj^2 + zk^2)

    Sea U = mundo global un vector u = 0, 0, 1

    Entonces podemos calcular R = Vector Horizontal paralelo a la vista de la cámara en dirección R = v’ ^ U,

    donde ^ es el producto cruzado, dada por

    a ^ b = (a2b3 – a3b2)i + (a3b1 – a1b3)j + (a1b2 – a2b1)k

    Esto le dará un vector que tiene este aspecto.

    Básicos de render 3D de proyección de perspectiva en 2D de la pantalla con la cámara (sin opengl)

    Esto podría ser de utilidad para tu pregunta, ya que una vez que usted tiene el LookAt Vector v’, el ortogonal del vector R, usted puede iniciar el proyecto desde el punto en el espacio 3D en la cámara del avión.

    Básicamente todos estos 3D manipulación problemas se reducen a la transformación de un punto en el espacio del mundo para el espacio local, donde los locales x,y,z son en la orientación de la cámara. ¿Que sentido? Así que si usted tiene un punto, Q=x,y,z y usted sabe R y v’ (cámara de los ejes), a continuación, usted puede proyectar a la «pantalla» uso simple vector de manipulaciones. Los ángulos pueden ser encontrados usando el producto escalar del operador en Vectores.

    Básicos de render 3D de proyección de perspectiva en 2D de la pantalla con la cámara (sin opengl)

    • Esta es una respuesta excelente y simple ortográficas técnica. Un punto, sin embargo: si la cámara y el objetivo no están en el mismo plano XZ (misma altura), entonces usted no puede utilizar el global de «arriba» vector para la proyección de los puntos. En lugar de ello, se derivan R por el cruce de V con U, a continuación se derivan de la real vectorial, por el cruce de R con V para obtener una base ortogonal.
  3. 5

    Según la wikipedia, calcular primero «d»:

    http://upload.wikimedia.org/wikipedia/en/math/6/0/b/60b64ec331ba2493a2b93e8829e864b6.png

    Con el fin de hacer esto, construir esas matrices en el código. Las asignaciones de sus ejemplos para sus variables:

    θ = Camera.angle*

    a = SomePointIn3DSpace

    c = Camera.x | y | z

    O, simplemente, hacer las ecuaciones por separado, sin el uso de matrices, a su elección:

    http://upload.wikimedia.org/wikipedia/en/math/1/c/8/1c89722619b756d05adb4ea38ee6f62b.png

    Ahora podemos calcular «b», un 2D punto:

    http://upload.wikimedia.org/wikipedia/en/math/2/5/6/256a0e12b8e6cc7cd71fa9495c0c3668.png

    En este caso ex y ey son el visor de posición, yo creo que en la mayoría de los sistemas gráficos de la mitad del tamaño de la pantalla (0.5) se utiliza para hacer que (0, 0) en el centro de la pantalla por defecto, pero se puede usar cualquier valor de (jugar). ez es donde el campo de visión entra en juego. Que es la única cosa que faltaba. Elija un campo de visión angular y calcular ez como:

    ez = 1 /tan(fov /2)

    Finalmente, para obtener bx y por píxeles reales, se tiene que de la escala por un factor relacionado con el tamaño de la pantalla. Por ejemplo, si b mapas de (0, 0) a (1, 1) sólo podría escala x 1920 y y por 1080 para un 1920 x 1080 de la pantalla. De esa manera cualquier tamaño de la pantalla se muestran la misma cosa. Por supuesto, hay muchos otros factores que intervienen en un sistema de gráficos 3D, pero esta es la versión básica.

  4. 4

    La conversión de puntos en 3D en un espacio 2D punto en una pantalla, simplemente mediante el uso de un matriz. El uso de una matriz para calcular la posición de la pantalla de tu punto de vista, esto le ahorra un montón de trabajo.

    Cuando se trabaja con cámaras debe considerar el uso de un -en apariencia-de la matriz y multiplicar la mirada en la matriz con la matriz de proyección.

    • Me gusta ese enfoque.
    • Me alegro de que yo le pueda ayudar. Si usted tiene problemas con respecto a las matrices acaba de preguntar aquí y yo voy a publicar algunos ejemplos( tengo un trabajo de la biblioteca para matrices ).
    • Puede agregar o muéstrame donde se convierte a coordenadas 2D después de la matriz de multiplicaciones.
    • Echa un vistazo aquí: answers.yahoo.com/question/index?qid=20090624084105AAmVf6q es una simple multiplicación de la matriz con un 4×1 Matriz ( Vector4; x,y,z,w; w es 1 ). No estoy en mi PC de lo contrario me gustaría copiar el código.
  5. 3

    Suponiendo que la cámara está en (0, 0, 0) y apuntando hacia adelante, las ecuaciones serían:

    ScreenData.x = SomePointIn3DSpace.x / SomePointIn3DSpace.z * constant;
    ScreenData.y = SomePointIn3DSpace.y / SomePointIn3DSpace.z * constant;

    donde «constante» es un valor positivo. Ajuste el ancho de la pantalla en píxeles generalmente da buenos resultados. Si se establece más alto de la escena un aspecto más «zoom-in», y vice-versa.

    Si quieres que la cámara está en una posición diferente o ángulo, entonces usted necesita para mover y rotar la escena de manera que la cámara está en (0, 0, 0) y apuntando hacia adelante, y entonces usted puede utilizar las ecuaciones anteriores.

    Que son, básicamente, calcular el punto de intersección entre una línea que pasa a través de la cámara y el punto 3D, y un plano vertical que está flotando un poco delante de la cámara.

  6. 2

    Usted podría estar interesado en ver cómo GLUT ¿ detrás de las escenas. Todos estos métodos tienen similares documentación que muestra que las matemáticas que va en ellos.

    Las tres primeras conferencias de UCSD podría ser muy convenientes, y contiene varias ilustraciones sobre este tema, que por lo que puedo ver es lo que realmente después.

  7. 0

    Usted desea transformar su escena con una matriz similar a la de OpenGL gluLookAt y, a continuación, calcular la proyección utilizando una matriz de proyección similar a la de OpenGL gluPerspective.

    Usted podría intentar simplemente calcular las matrices y hacer la multiplicación en el software.

    • No estoy usando opengl.
    • No, pero el principio es el mismo. Si usted mira la documentación de estas funciones, usted verá cómo calcular las matrices. Tal vez los puedes utilizar directamente en su programa?
  8. 0

    Ejecutarlo a través de un trazador de rayos:

    Trazador de rayos en C# – Algunos de los objetos que ha será familiar para usted 😉

    Y para probar un LINQ versión.

    No estoy seguro de cuál es el mayor propósito de la aplicación es (debes decirnos, podría despertar mejores ideas), pero aunque está claro que la proyección y el trazado de rayos son diferentes conjuntos de problemas, ellos tienen un montón de superposición.

    Si la aplicación sólo está tratando de sacar toda la escena, esto sería genial.

    Para solucionar el problema #1: Oscurecida puntos de no ser proyectadas.

    Solución: Aunque yo no veo nada acerca de la opacidad o la transparencia en el blog de la página, usted probablemente podría agregar estas propiedades y el código para el proceso de uno de los rayos que rebotan (como es normal) y que continúa en la (para la «transparencia»).

    En la resolución de problemas #2: la Proyección de un solo píxel se requiere una costosa completo de la imagen de rastreo de todos los píxeles.

    Obviamente, si usted sólo quiere dibujar los objetos, utilizar el trazador de rayos para lo que es! Pero si quieres buscar miles de píxeles de la imagen, de partes aleatorias de objetos al azar (por qué?), haciendo un total de ray-trace para cada solicitud sería un gran rendimiento perro.

    Afortunadamente, con más ajustes de su código, usted podría ser capaz de hacer un trazado de rayos frontal (con transparencia), y el caché de los resultados hasta que los objetos de cambio.

    Si usted no está familiarizado con el trazado de rayos, leer la entrada del blog, creo que explica cómo funcionan realmente las cosas al revés de cada 2D de píxeles, a los objetos, las luces, el cual determina el valor de píxel.

    Puede agregar código, así como las intersecciones con los objetos están hechos, que son la creación de listas indexadas por cruzaba los puntos de los objetos, con el elemento actual 2d píxel está siendo rastreado.

    A continuación, cuando usted desea proyectar un punto, vaya a que el objeto de la lista, busque el punto más cercano a la que se desea proyectar, y buscar el 2d de píxeles que te importan. Las matemáticas sería mucho más mínima de las ecuaciones en sus artículos. Desafortunadamente, el uso de, por ejemplo, un diccionario de su objeto+estructura de puntos de mapeo 2d píxeles, no estoy seguro de cómo encontrar el punto más cercano de un objeto sin que se ejecuta a través de toda la lista de asignados los puntos. A pesar de que podría no ser el más lento cosa en el mundo y que probablemente podría averiguar, simplemente no tengo el tiempo para pensar acerca de ello. Nadie?

    buena suerte!

    «También, no entiendo en la entrada de la wiki ¿qué es el visor de posición del vers la posición de la cámara» … estoy 99% seguro de que esta es la misma cosa.

Dejar respuesta

Please enter your comment!
Please enter your name here