Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Vertices

Iniciado por zupervaca, 03 de Agosto de 2005, 12:55:55 PM

« anterior - próximo »

zupervaca

 es que eso ya depende del motor y como se quiera hacer, si quieres que cualquier modelo tenga colisiones, el tener definirle mas estructuras para comprobar las colisiones puede ser un problema (mas que nada de memoria), si quieres algo muy especifico como por ejemplo colisiones contra un decorado estatico, bsps, etc pues es mejor tener estructuras ya generadas con muchos calculos precalculados, es que ya te digo todo depende de lo que se quiera hacer

saludos

Pogacha

 
Cita de: "_Grey"Yo sumaria las normales de todos los poligonos adyacentes, y dividiria por la cantidad de normales calculadas, y luego mas vale que normalices la normal resultante :P
No sirve de nada dividir por la cantidad si luego normalizas ... y no hay regla para esto (encontrar la normal del vertice compartido), en realidad deberias parametrizar las curvas de las caras y así calcular la normal, pero como entonces se deberian especificar mas parametros por cara ... en definitiva sumas todas las normales y luego normalizas suponiendo una curva suave y homogenea ...
Saludos

Miki

 Holaps,
Yo lo que hago es sumar la normal de todas las faces adyacentes al vertice del cual keremos sacar la normal, luego divido entre el nº de faces, y finalmente normalizo la normal resultante. Este algoritmo es muy útil cuando NO TENEMOS la normal de ningún vertice de la malla. De hecho, para k no kepa ninguna duda, akí teneis el código del método en cuestión:
NOTE: No os hagais la picha un lio con las llamadas al Device. No es Direct3D ni OpenGL, es una capa abstracta.


[SIZE=1]//--------------------------------------------------------------------------------------------
// Name: ComputeNormals()
// Desc: Compute vertex-based normals
//--------------------------------------------------------------------------------------------
/*BOOL8 cResMesh::ComputeNormals()
{
// Esta función hay k mirarla bien antes de activarla.
// Todo debería correr perfectamente, pero no está preparada para la posibilidad de usar un
// solo stream buffer: cStreamBuffers::IsUniqueStream().
return false;

if( !m_pBuffers || !m_pBuffers->m_tVB.m_pBuffer || !m_pBuffers->m_tIB.m_pBuffer )
 return false;

if( !m_pBuffers->IsUniqueStream() && !m_pBuffers->m_tNB.m_pBuffer )
 return false;

LPRETVECTOR3 pVB = 0;
LPRETVECTOR3 pNB = 0;
LPUNSIG16 pIB16 = 0;
LPUNSIG32 pIB32 = 0;

// Lock buffers

if( !RASTER->LockVertexBuffer( &(m_pBuffers->m_tVB), (LPVOID*)&pVB ) )  return false;
if( !RASTER->LockVertexBuffer( &(m_pBuffers->m_tNB), (LPVOID*)&pNB ) )  return false;

if( m_pBuffers->Is32BitIndexed() )
{
 if( !RASTER->LockIndexBuffer( &(m_pBuffers->m_tIB), (LPVOID*)&pIB32 ) )  return false;
}
else
{
 if( !RASTER->LockIndexBuffer( &(m_pBuffers->m_tIB), (LPVOID*)&pIB16 ) )  return false;
}

RETVECTOR3 vSum, vNormal;
FLOAT32 fShared = 0;
UNSIG32 i, j;

for( i = 0; i < m_pBuffers->m_dwNumVerts; i++ )
{
 for( j = 0; j < m_pBuffers->m_dwNumFaces; j++ )
 {
  // Check if the vertex is shared by another face. All to do is add
  // the un-normalized normal of the shared face and them increase "shared"
  if( pIB16 )
  {
   if( pIB16[j+0] == i || pIB16[j+1] == i || pIB16[j+2] == i )
   {
    // Calculate the cross product to obtain the normal
    vNormal = ( pVB[pIB16[j*3+0]] - pVB[pIB16[j*3+2]] )  ^  ( pVB[pIB16[j*3+0]] - pVB[pIB16[j*3+1]] );

    vSum += vNormal;
    fShared += 1.f;
   }
  }
  else
  {
   if( pIB32[j+0] == i || pIB32[j+1] == i || pIB32[j+2] == i )
   {
    // Calculate the cross product to obtain the normal
    vNormal = ( pVB[pIB32[j*3+0]] - pVB[pIB32[j*3+2]] )  ^  ( pVB[pIB32[j*3+0]] - pVB[pIB32[j*3+1]] );

    vSum += vNormal;
    fShared += 1.f;
   }
  }
 }
 
 // Get the normal by dividing the sum by the shared counter
 // We must negate the shared for OpenGL, but not for D3D, so it has the normals pointing out
 if( RASTER->IsD3D() )
  pNB[i] = vSum / fShared;
 else
  pNB[i] = vSum / -fShared;

 // Normalize it to get final vertex normal
 pNB[i].SetNormalized();

 vSum.SetZero();  // Reset the sum
 fShared = 0.f;  // Reset the shared
}

// Unlock buffers
RASTER->UnlockIndexBuffer ( &(m_pBuffers->m_tIB) );
RASTER->UnlockVertexBuffer( &(m_pBuffers->m_tVB) );
RASTER->UnlockVertexBuffer( &(m_pBuffers->m_tNB) );

return true;
}[/SIZE]


Sobre lo que decía Haddd de los smoothing groups..... Esto es realmente un problema GORDO, sobretodo a la hora de hacer un importador/exportador para MAX o cualkier otro programa de diseño 3D. Al final (después de 1 mes de trabajo) conseguí hacer un exportador en max script k te sacara posición de vertice, normal, color de vertice, coord de textura (hasta 3 sets de coordenadas), indices...cada elemento en un stream independiente. Así, para cargar luego la malla en el motor, el algoritmo es muy sencillo y extremadamente rápido (solo hay k crear los buffers y rellenarlos con la info). El problema de dicho exportador es que si la malla k se keire exportar sobrepasa X vértices, es posible k tarde unas cuantas....horas....en realizar la exportación. Y aún así, haciendo pruebas con los smoothing groups, notifiké un par de fallos k aún tengo k arreglar  (nooo) Todavía me fata por exportar bones, pero eso lo dejaré para la otra vida  (uoh)

Salud2

Pogacha

 No se quien hizo ese algoritmo, pero lo unico que hace con dividir por fshared es invertir la normal en caso que no se use D3D y dar error de división si haces una malla de un solo vertice.

Matematicamente:

CitarV : Vector arbitrario;

Nv : vector normalizado -> |Nv| = 1;

a : escalar modulo arbitrario <> 0

tal que

V = aNv;

|V| = a;

Nv = V / |V|

lo que implica que

Nv = (aNv) / (a)

y por propiedad del producto y division:

J = bV;

Nj = J / |J|

|J| = b|V| = ba

Nj = (bV) / (ba) = (ba Nv) /  (ba)

Nj = Nv

Lo cual demuestra indefectiblemente que para normalizar no hay que multiplicar o dividir un vector por nada, cuando normalizas le estas sacando el modulo!!!.

Saludos.

zupervaca

 puedes hacer una optimizacion que notaras bastante, este codigo es mortal
for( i = 0; i < m_pBuffers->m_dwNumVerts; i++ )
{
for( j = 0; j < m_pBuffers->m_dwNumFaces; j++ )
{

recorre solo las caras, calculas la normal de esa cara y se la metes a los tres vertices sumandola contra la anterior que habia y la divides entre dos, al final recorres una vez mas los vertices y normalizas ya si quieres, de una pasada por las caras haces todo el calculo, si quieres saber como calcular la normal correctamente pasate por mi web y descarga el codigo de c++ clase vector

saludos

vincent

Desarrollo en .Net y metodologías http://devnettips.blogspot.com

visualcubb

Cita de: "zupervaca"puedes hacer una optimizacion que notaras bastante, este codigo es mortal
for( i = 0; i < m_pBuffers->m_dwNumVerts; i++ )
{
for( j = 0; j < m_pBuffers->m_dwNumFaces; j++ )
{

recorre solo las caras, calculas la normal de esa cara y se la metes a los tres vertices sumandola contra la anterior que habia y la divides entre dos, al final recorres una vez mas los vertices y normalizas ya si quieres, de una pasada por las caras haces todo el calculo, si quieres saber como calcular la normal correctamente pasate por mi web y descarga el codigo de c++ clase vector

saludos
Hay un detalle con ese algoritmo colega, ¿qué pasa si un vertice pertenece a más de una cara?, entonces el vertice quedará con la normal de la última cara a la que pertenezca mostrando datos de iluminación erroneos cuando se referencie en caras anteriores, la única solución para eliminar ese problema es con smooth de normales, sacar una normal promedio de todas las normales que tiene el vértice, lo que no es muy simple.
Si esto no se hace se van a ver efectos de iluminación bastante extraños sobre el modelo.

Saludos.
quot;Y conocereis la verdad y la verdad os hara libres" Juan 8:32.

http://www.openglubb.info/

zupervaca

 
Cita de: "visualcubb"
Cita de: "zupervaca"puedes hacer una optimizacion que notaras bastante, este codigo es mortal
for( i = 0; i < m_pBuffers->m_dwNumVerts; i++ )
{
for( j = 0; j < m_pBuffers->m_dwNumFaces; j++ )
{

recorre solo las caras, calculas la normal de esa cara y se la metes a los tres vertices sumandola contra la anterior que habia y la divides entre dos, al final recorres una vez mas los vertices y normalizas ya si quieres, de una pasada por las caras haces todo el calculo, si quieres saber como calcular la normal correctamente pasate por mi web y descarga el codigo de c++ clase vector

saludos
Hay un detalle con ese algoritmo colega, ¿qué pasa si un vertice pertenece a más de una cara?, entonces el vertice quedará con la normal de la última cara a la que pertenezca mostrando datos de iluminación erroneos cuando se referencie en caras anteriores, la única solución para eliminar ese problema es con smooth de normales, sacar una normal promedio de todas las normales que tiene el vértice, lo que no es muy simple.
Si esto no se hace se van a ver efectos de iluminación bastante extraños sobre el modelo.

Saludos.
veamos si pertenece a mas de una cara, los indices de las caras ya resuelven este problema, para algo hay indices de las caras digo yo, lo correcto es usar un solo for
for( j = 0; j < m_pBuffers->m_dwNumFaces; j++ )
tampoco quedaria la ultima ya que se hace esto como dije anteriormente, no se si no lo leiste
Citarse la metes a los tres vertices sumandola contra la anterior que habia y la divides entre dos

saludos






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.