Vistas puesta en COLLADA

Octubre 31, 2008

Hola

Debido a un error que tengo con el sistema de tangentes en las mallas, me he decidido a hacer una pausa en el desarrollo del motor de render pare centrarme (otra vez) en el apasionante mundo de los exportadores :( .

En la primera versión hacia uso de un programa propio que parseaba nada más ni menos que un fichero en formato ASE para traducirlo a un formato propio del iL-engine. Después de más de 600 líneas de código de parser, el parser exportaba la geometría debidamente, aunque el calculo de las tangentes no se acaba de realizar lo bien que se debería.

Por eso, quería ponerme con MAX Script y su SDK, aunque hoy mismo, buscando por internet, a llegado a mis manos el formato COLLADA, que básicamente es un formato muy configurable en XML que ya me calcula las tangentes, binormales, y demás historias de las mallas.

Lo único que me quedara es transformar seguramente el sistema de coordenadas de mano derecha a mano izquierda.

Página del formato COLLADA aquí.

Un saludo a todos


World View Projection to Frustum planes

Octubre 30, 2008

Hola

Una vez sabida toda la información que os he comentado estos días acerca de los planos 3D y el Frustum de la cámara, hoy os traigo como extraer los 6 planos del frustum de una cámara a partir de su matriz World-View-Projection.

Las variables Mxy representan los números colocados en la matriz 4×4 según su fila y columna de DirectX.

Plano Izquierda:
A = m14 + m11
B = m24 + m21
C = m34 + m31
D = m44 + m41

Plano Derecha:
A = m14 – m11
B = m24 – m21
C = m34 – m31
D = m44 – m41

Plano Arriba:
A = m14 + m12
B = m24 + m22
C = m34 + m32
D = m44 + m42

Plano Abajo:
A = m14 – m12
B = m24 – m22
C = m34 – m32
D = m44 – m42

Plano Cercano:
A = m13
B = m23
C = m34
D = m44

Plano Lejano:
A = m14 – m13
B = m24 – m23
C = m34 – m33
D = m44 – m43

Con estos 6 planos, y sabiendo cómo se comprueba si un punto está por encima o por debajo de un plano, es trivial comprobar si un punto está dentro de la visión de la cámara o no. Solo tenéis que ir plano a plano comprobando que el punto está por encima de los planos.

El volumen interno de la pirámide de visión se corresponde con todos aquellos puntos que están A LA VEZ por encima de los 6 planos.

Si por el contrario lo que queréis es comprobar si una Bounding Box esta dentro o parcialmente dentro del área de visión de una cámara. Tenéis que aplicar la estrategia siguiente.

Debéis comprobar que todos los puntos de la Bounding Box (8 en este caso) están POR DEBAJO de uno de los planos, si esa condición no se cumple por ningún plano, entonces quiere decir que la Bounding Box esta dentro o parcialmente dentro del área de visión de la cámara.

Un saludo


Que es el Frustum?

Octubre 29, 2008

Hola

Hoy os quería explicar que es el frustum de una cámara. El frustum de una cámara es aquel volumen imaginario que esta crea en su área de visión.

En la vida real, nosotros tenemos un campo de visión definido por un volumen. Este volumen depende de lo que nuestros ojos pueden llegar a ver, desde un lado hacia otro y desde lo más cerca posible hasta lo más lejos.

Evidentemente imaginar la forma de ese volumen es un tanto complicado. En cambio, en las cámaras de los videojuegos no es así, es mucho más fácil. EL frustum de una cámara de un videojuego tiene en el 99% de los casos forma de pirámide. Debemos imaginar una pirámide como si estuviera saliendo de nuestro ojo, con la punta de la pirámide tocando a nuestra pupila y la parte más ancha de la pirámide en lo más lejos donde alcance nuestra mirada.

Todo lo que la pirámide sea capaz de englobar será lo que nosotros podremos ver con nuestra cámara, si algo no está dentro de esa pirámide, entonces no lo podremos ver.

Una vez tenemos en mente este concepto, nos deberíamos hacer otra pregunta, ¿Cuántos planos matemáticos son necesarios para hacer una pirámide?

La respuesta corta es 5, pero nosotros usaremos 6. Normalmente se responde 5 por que partimos de la idea de pirámide perfecta, es decir, que esta acaba en punta. Pero en nuestro caso, el de los videojuegos, es mucho mejor partir esa punta y hacer que haya un plano cercano a la punta.

Con todo esto que hemos explicado, ya podemos saber un poco más sobre frustums y del como están creados.

Un saludo


Plano 3D a partir de un vector y un punto

Octubre 28, 2008

Hola

Continuando con la información de los planos, hoy os traigo la manera de crear planos mediante un punto y un vector.

Para hacer un plano mediante un punto (x1,y1,z1) y un vector (x2,y2,z2), es necesario aplicar la fórmula del plano, y darle valor a las 4 letras (A,B,C,D) de la ecuación Ax+By+Cz+D=0.

Hemos de tener en cuenta que el vector que elijamos, será considerado como el vector director del plano, es decir, un vector perpendicular al plano (90º grados).

Por lo tanto tenemos que:

A = x2;
B = y2;
C = z2;

Y para obtener D, aislamos la D de la ecuación donde tendremos:

D = -((x2 * x1) + (y2 * y1) + (z2 * z1));

Fijémonos que el punto es multiplicado por las constantes del plano (A,B,C) que ya han sido substituidas por el vector director del plano.

Una vez tenemos A,B,C,D ya podemos, por ejemplo, comprobar con el método de ayer si un punto está por encima o por debajo del propio plano.

Un saludo


Punto 3D por encima o por debajo de un plano

Octubre 27, 2008

Hola

Hoy os traigo algo que parece y es muy sencillo. ¿Cómo podemos saber si un punto (x,y,z) está por encima o por debajo de un Plano 3D?

Muy sencillo, todo plano nos viene dado por la ecuación Ax+By+Cz+D = 0, esto quiere decir que en nuestro código tendremos los valores (A,B,C,D), los cuales nos definirán el plano en cuestión.

Solo necesitamos substituir las coordenadas (x,y,z) del punto en la ecuación del plano y comprobar el signo del resultado. Si el resultado da un número positivo, entonces el punto está por encima del plano. Si el resultado es un número negativo, el punto está por debajo del plano.

Un saludo


Realimentación

Octubre 24, 2008

Hola

Hoy os traigo una encuesta para realimentarme o lo que es lo mismo, obtener algo de feedback.

¿Os sirve el conocimiento que podéis encontrar aquí?

Un saludo y gracias


Distancia de un punto a un vector

Octubre 23, 2008

Hola

¿Cómo podemos calcular la distancia mínima entre un punto y un vector? Pues de una forma relativamente sencilla utilizando el producto escalar definido para los vectores.

¿Qué es el producto escalar? Una operación que nos da como resultado un número, este número nos indica, una vez proyectado un vector encima del otro, cuantos vectores mide esa proyección.

Por ejemplo, imaginemos que el resultado es 1.5, entonces eso quiere decir que la proyección del vector mide 1.5 veces el vector al cual se ha proyectado el anterior vector.

Como una imagen vale más que mil palabras, vamos a observarla y a explicarlo un poco.

Tenemos inicialmente un vector (x1 -> x2), y el punto x0 con los cuales queremos obtener la distancia MINIMA entre ese vector y ese punto.

La estrategia es usar el producto escalar para proyectar un vector encima de otro, por lo tanto, tenemos el vector original (x1 -> x2) y ahora creamos un nuevo que será el que proyectaremos.

Con lo cual, tenemos los vectores (x1 -> x2) y (x1 -> x0). Si hacemos el producto escalar entre ellos, obtendremos el número de veces que mide la sección entre x1 y el punto ‘p’. Es decir, la proyección de la línea azul (vector x1 -> x0) encima del vector original.

Una vez tenemos ese factor de multiplicación, solo tenemos que multiplicar el vector original por ese factor y sabiendo la primera componente que es x1, sabremos automáticamente cual es el punto (x,y,z) que hay en ‘p’.

Una vez sabido ‘p’, solo nos queda hacer la distancia entre ‘p’ y x0. Para eso creamos el vector (p -> x0) y calculamos su distancia.

El codigo siguiente calcula el punto ‘p’ y luego en otra funcion calcula la distancia.

vector3 ClosestPointOnSegment(vector3 p, vector3 p1, vector3 p2)
{
    vector3 diff = p-p1;
    vector3 dir = p2-p1;
    float t = dot(diff,dir)/dot(dir,dir);
    if (t <= 0.0f)
    {
        return p1;
    }
    else if (t >= 1.0f)
    {
        return p2;
    }
    else
    {
        return p1 + t * dir;
    }
}
//The distance from the point to the segment is then:
float distance = length(p - ClosestPointOnSegment(p,p1,p2));

NOTA: Existen dos variantes, la que calcula esta distancia del punto x0 a la línea definida por el vector (x1 -> x2) y la que calcula la distancia del punto x0 al vector LIMITADO (x1 -> x2). Si queréis la primera, necesitáis eliminar las dos primeras condiciones del anterior código, sino, dejad el código tal cual.

Un saludo


Normal map como desplazamiento

Octubre 22, 2008

Hola

En este post os quería comentar algo que he hecho hace relativamente poco (concretamente hoy). El caso es el poder utilizar una textura de normal map como una textura de desplazamiento para así poder distorsionar otras texturas a tu antojo.

Ejemplos de uso:

  • Distorsionar texturas de líquidos para acercarse al efecto superficial de un líquido.
  • Distorsionar la textura de un césped para simular el movimiento del aire (lo usa el UT 3).
  • Distorsionar la textura de las ramas + hojas de un árbol para simular lo anterior (lo usa el UT 3).
float4 Distorsion_Component = tex2D( DistSampler1, inTexDist1);
Distorsion_Component = 2 * Distorsion_Component - 1;
float4 diffuse_texture1 = tex2D( DiffuseSampler1 , inTexLayer1 + (Distorsion_Component.xy * 0.1f));

En el código anterior podemos ver como obtenemos la información del píxel del normal map, transformamos esa información del rango [0..2] al rango [-1..1] y esa información la sumamos a las coordenadas de textura de la textura que queremos distorsionar.

Un saludo


Matriz para los Billboards

Octubre 21, 2008

Hola

Hoy os traigo el código necesario para poder hacer la matriz que aplicada a un objeto, este siempre mira a la cámara, o lo que es lo mismo, para hacer un Billboard.

EL Billboard se consigue mediante la creación de una matriz a partir de tres vectores, el vector que va desde la cámara al objeto, el vector UP de ese objeto (NO el (0.0f, 1.0f, 0.0f) de toda la vida) y el vector resultante del producto vectorial entre los dos últimos.

void YourCamera::MatrixBillboard(D3DXMATRIX &Matrix, D3DXVECTOR3 &BillboardPos)
{
    //Step 1: Calculate the Billboard's direction vector
    D3DXVECTOR3 BillLook = m_vPosition - BillboardPos;
    D3DXVec3Normalize(&BillLook, &BillLook);

    //Cross the camera's up and billboard's direction to get

    //the billboards "right" vector

    D3DXVECTOR3 BillTRight;
    D3DXVec3Cross(&BillTRight, &m_vUpVector, &BillLook);

    //Cross the look and "right" vector to get the true up vector.

    D3DXVECTOR3 BillUp;
    D3DXVec3Cross(&BillUp, &BillLook, &BillTRight);

    //Plug it all into the matrix
    Matrix._11 = BillTRight.x;
    Matrix._12 = BillTRight.y;
    Matrix._13 = BillTRight.z;
    Matrix._14 = 0.0f;

    Matrix._21 = BillUp.x;
    Matrix._22 = BillUp.y;
    Matrix._23 = BillUp.z;
    Matrix._24 = 0.0f;

    Matrix._31 = BillLook.x;
    Matrix._32 = BillLook.y;
    Matrix._33 = BillLook.z;
    Matrix._34 = 0.0f;

    Matrix._41 = BillboardPos.x;
    Matrix._42 = BillboardPos.y;
    Matrix._43 = BillboardPos.z;
    Matrix._44 = 1.0f;
}

Concretamente aún no me he puesto ha desarrollar el código que yo necesito, pero dentro de poco lo haré y seguro que utilizare el conocimiento que hay en este trozo de código.

Un saludo


Pregunta de examen

Octubre 20, 2008

Holas

Esta pregunta me la encontre en un examen que se me realizó en una entrevista de trabajo. Que pensais vosotros ?

Suerte :)

RESPUESTA: La respuesta correcta es la 2, int B = A & 0×000F, pues esta operacion nos da lo que ’sobra’ de la division por 16, que coincide con el valor hexadecimal 0×000F.

Un saludo