Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Colisiones Con Opcode

Iniciado por senior wapo, 08 de Julio de 2005, 07:48:37 PM

« anterior - próximo »

senior wapo

 Quiero implementar el movimiento de un personaje en un mundo 3D sin fisicas, al estilo de un FPS o MMORPG: resbalar contra las paredes y subir escalones, poco más.

Me gustaria recibir comentarios de gente que lo haya hecho con OPCODE (no ODE, ni tomahawk, ni newton, ni implementarmelo yo, sino con OPCODE).

Ante la falta de superficies de barrido (swept spheres por ejemplo), solo se me ocurre hacer pasitos discretos hasta llegar a la posición destino, como hace quake con su funcion Trace contra los convexhulls, pero usando OPCODE y sus arboles.

Idealmente quiero usar un cilindro o un AABB para el personaje (se ajustan mejor que una esfera) y colisionar contra una malla grande que es el mundo (excepto los posibles elementos repetibles como rocas, barriles,... que pueden ir aparte instanciados/clonados).

Nunca he manejado OPCODE antes, solo he mirado los docs por encima.

¿ Comentarios, sugerencias, trucos, enlaces, observaciones sobre rendimiento, experiencias, ejemplos ?

Gracias.


ProD

 Buenas, pues yo utilicé OPCODE para un simulador de grua torre que hice hace ya un tiempo en el curro. La verdad que es una lib de colisiones bastante maja. La inicialización es bastante sencilla. Luego por cada objeto que quieras que tenga info de colisiones pues creas otra estructura con los vértices e índices y que luego opcode gestiona. más cosas.. bueno luego necesitas una función de tipo callback que opcode necesita para chequear las colisiones entre los objetos. Te voy a poner por aquí algunos ejemplillos a ver si te sirven de ayuda. Yo utilicé la versión 1.2, creo que ya está la 1.3:


// Árbol de AABB para las colisiones
AABBTreeCollider m_TC;

// Opciones del AABB tree
m_TC.SetFirstContact(true);
m_TC.SetFullBoxBoxTest(true);
m_TC.SetFullPrimBoxTest(true);
m_TC.SetTemporalCoherence(true);

// Datos que necesita OPCODE para albergar
// la información de colisión de un objeto

Point  *m_pVertices;  // Vértices de la malla
udword *m_pIndices;   // Índices de la malla

OPCODECREATE oc;
oc.NbTris       = m_NumTris; // Número de triángulos de la malla (caras)
oc.NbVerts    = m_NumVerts;  // Número de vértices de la malla
oc.Tris           = m_pIndices;  // Ojo, tiene que contener los vértices de la malla
oc.Verts         = m_pVertices;  // Ojo, tiene que contener los triángulos de la malla
oc.Rules         = SPLIT_COMPLETE | SPLIT_SPLATTERPOINTS | SPLIT_GEOMCENTER;
oc.NoLeaf      = true;  // Sin hojas
oc.Quantized = true;  // Cuantizado

OPCODE_Model m_CollisionModel;  // Modelo de colisión de la malla

if (!m_CollisionModel.Build(oc))
{
 // Error al construir el modelo de colisión
 return E_FAIL;
}

// CALLBACK que necesita OPCODE para indexar en la geometría

void CCollisionList::_opcodeCallback (udword triangleIndex,
                 VertexPointers &triangle, udword userdata)
{
 CMesh  *Mesh     = reinterpret_cast<CMesh *>(userdata);
 udword *indices  = Mesh->GetIndexBuffer() + (triangleIndex * 3);
 Point  *vertices = Mesh->GetVertexBuffer();

 triangle.Vertex[0] = &vertices[indices[0]];
 triangle.Vertex[1] = &vertices[indices[1]];
 triangle.Vertex[2] = &vertices[indices[2]];
}


Bueno y ahora viene la parte de chequeo de colisiones... para ello necestias comparar dos modelos
de colisión. Esto es, pues dos objetos. En tu caso imagino que siempre tendrás un modelo de colisión fijo, la geometría que envuelve al jugador, etc. y los otros modelos variables, los muros, objetos, etc. Bueno aquí va, yo como utilizo Direct3D pues mis matrices están en mano izquierda, si utilizas otra api como opengl, imagino que tendrás que transponer las matrices. Bueno aquí va el código:



void CCollisionList::CreateCollisionList (list<int> *pIndexList)
{
 assert(pIndexList != NULL);

 // Limpiamos la lista..
 pIndexList->clear();

 list<CollisionNode>::iterator it;
 for (it = m_MeshList.begin(); it != m_MeshList.end(); ++it)
 {
   // Colocamos las callbacks
   m_TC.SetCallback0(_opcodeCallback, udword(m_pMesh));
   m_TC.SetCallback1(_opcodeCallback, udword(it->pMesh));

  // Calculamos la colisión
  m_TC.Collide(it->ColCache, reinterpret_cast<Matrix4x4 *>(m_pMesh->GetTransMatrix()),
                                 reinterpret_cast<Matrix4x4 *>(it->pMesh->GetTransMatrix()));

  // Si hay colisión... añadimos el índice de la malla que colisiona con la malla "master"
  if (m_TC.GetContactStatus())
  {
    pIndexList->push_back(it->index);
  }
 }
}


Bueno una cosa que olvidé, y es que cada nodo de mi lista de colisiones lleva una pequeña cache que se define así:
BVTCache ColCache;  // Cache de colisiones entre la malla "master" y la apuntada por el puntero
Esto lo hace Opcode para acelerar los cálculos. Bueno espero que te sirva de algo. La verdad que a mi me hubiera venido genial que alguien me explicara como iba la lib. Ya que la ayuda no era muy buena que digamos. Tuve que mirar código que utilizaba la lib. Bueno saludos.

ProD
as ideas son capitales que sólo ganan intereses entre las manos del talento

senior wapo

 Muchas gracias, me vendrá muy bien  :D







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.