Introducción a Bullet

Transcripción

Introducción a Bullet
VIDEOJUEGOS 2
Introducción a Bullet
Motores de físicas
V2
Puntos a tratar
•
•
•
•
•
•
•
•
•
Arquitectura de Bullet
Fases del motor
Algoritmos de detección de colisiones
Configuración del motor
Etapa de la simulación
Cuerpos rígidos
Cuerpos blandos
Contactos
Herramientas
Videojuegos II
© 2013-2014 Depto. Ciencia de la Computación e IA
Introducción a Bullet
!2
V2
Motores de físicas
Motor de físicas Bullet
• Motor de físicas Open Source escrito en C++
• Soporta la mayoría de las plataformas
• Utiliza aceleración por hardware
• GPU utilizando OpenCL (requiere ATI Radeon 5870 o nVidia 470)
• NEON en Android / iOS (SIMD)
• Cell SPU en Playstation 3
• Permite almacenar y recuperar los datos de la física de ficheros
• Blender
• Maya (plugin Dynamica Bullet Maya)
• Formatos
• COLLADA (obsoleto)
• Formato propio (.bullet)
Videojuegos II
© 2013-2014 Depto. Ciencia de la Computación e IA
Introducción a Bullet
!3
V2
Motores de físicas
Arquitectura de la librería
Dinámica de cuerpos
blandos
Paralelización en SPU (Playstation 3)
BulletSoftDynamics
BulletMultiThreaded
Dinámica de cuerpos rígidos
BulletDynamics
Detección de colisiones
BulletCollision
Álgebra lineal
LinearMath
Videojuegos II
© 2013-2014 Depto. Ciencia de la Computación e IA
Introducción a Bullet
!4
V2
Motores de físicas
Arquitectura de clases de Bullet
• Sigue una arquitectura modular
Clase principal que representa el mundo de la simulación física
Utiliza los siguientes módulos:
btDynamicsWorld
Detección gruesa de
colisiones (AABB)
!
!
!
!
!
!
btBroadphaseInterface
Videojuegos II
Detección de
colisiones y puntos
de contacto
!
!
btDispatcher
Configuración de los
algoritmos a utilizar
!
btCollisionConfiguration
© 2013-2014 Depto. Ciencia de la Computación e IA
Resolución de
restricciones y
contactos
!
!
!
!
!
btConstraintSolver
Introducción a Bullet
!5
V2
Motores de físicas
Arquitectura de clases de Bullet
• Podemos reemplazar distintos módulos
btDiscriteDynamicsWorld
btSoftRigidDynamicsWorld
btDynamicsWorld
btGpu3DGrid
btCollisionDispatcher
btParallelConstraintSolver
btMultiSapBroadphase
SpuGatheringCollisionDispatcher
btSequentialImpulseConstraintSolver
btAxisSweep3
btDispatcher
btDbvtBroadphase
btDefaultCollisionConfigurator
btBroadphaseInterface
Videojuegos II
btCollisionConfiguration
© 2013-2014 Depto. Ciencia de la Computación e IA
btConstraintSolver
Introducción a Bullet
!6
V2
Motores de físicas
Fases de la simulación
Detección de colisiones
Detección gruesa
(broadphase)
Videojuegos II
Detección fina
(narrowphase)
Simulación física
Resolución de
contactos
© 2013-2014 Depto. Ciencia de la Computación e IA
Integración
Introducción a Bullet
!7
V2
Motores de físicas
Algoritmos de broad phase
Dynamic
Bounding
Volume
(AABB) Tree
Sweep And
Prune (SAP)
• btDbvtBroadphase • Utiliza una jerarquía de BVs (AABB)
• Apropiado para mundos con gran cantidad de
objetos dinámicos
• btAxisSweep3 • bt32AxisSweep3 (Versión de 32 bits)
• Requiere un tamaño fijo del mundo, conocido de
antemano
• Apropiado cuando la mayoría de objetos tienen
poco o ningún movimiento
Fast Uniform
Grid
Videojuegos II
• btGpu3DGrid • Acelerado por hardware
© 2013-2014 Depto. Ciencia de la Computación e IA
Introducción a Bullet
!8
V2
Motores de físicas
Inicialización del motor
btCollisionConfiguration *collisionConfiguration = new btDefaultCollisionConfiguration();
!
btBroadphaseInterface *broadPhase = new btAxisSweep3(btVector3(-1000, -1000, -1000), btVector3(1000, 1000, 1000));
!
btDispatcher *dispatcher = new btCollisionDispatcher(collisionConfiguration);
Fijamos límites
del mundo
para SAP
!
btConstraintSolver *solver = new btSequentialImpulseConstraintSolver();
!
world = new btDiscreteDynamicsWorld(dispatcher, broadPhase, solver, collisionConfiguration);
Videojuegos II
© 2013-2014 Depto. Ciencia de la Computación e IA
Introducción a Bullet
!9
V2
Motores de físicas
Paso de la simulación
• En cada iteración actualizamos la simulación con
!
Opcionales
!
world-­‐>stepSimulation(timeStep, maxSubSteps, fixedTimeStep);
!
Tiempo transcurrido desde
!
la última actualización (s)
Por defecto 1
Por defecto (1.0 / 60.0)
!
!
¡CUIDADO! Los tiempos se indican en segundos
!
• La simulación se ejecuta a una tasa fija de 60 fps por defecto
• Periodicidad de 16.6 ms (1 / 60)
• Se trata de la resolución de la simulación
• Podemos cambiarlo con fixedTimeStep
Videojuegos II
© 2013-2014 Depto. Ciencia de la Computación e IA
Introducción a Bullet
!10
V2
Motores de físicas
Cambios en el framerate
• Si el ciclo itera más rápido que la periodicidad fija establecida
• No vuelve a realizar simulación cada iteración
• Simula el tiempo correspondiente a la tasa fija (por defecto 16.6 ms)
• Interpola los resultados según el tiempo real transcurrido (menor que
la tasa fija), hasta que haya que volver a simular
!
Ejemplo:
• Tasa fija 60 fps (16.6ms)
• Tasa real 120 fps (8.3ms)
!
• Si el ciclo itera más lento
y
#1 (0 ms)
Simulado
#2 (8.3 ms)
Interpolado
#3 (16.6 ms)
x
Simulado
• Se puede realizar más de una simulación al llamar a stepSimulation
• Se puede limitar el número máximo de simulaciones con
maxSubSteps, debiendo cumplir:
timeStep < maxSubSteps * fixedTimeStep
Videojuegos II
© 2013-2014 Depto. Ciencia de la Computación e IA
En caso de no cumplirse la
simulación irá más lenta
Introducción a Bullet
!11
V2
Motores de físicas
Tipos básicos
btScalar
Valor escalar. Su precisión por defecto es de
float, pero se puede cambiar a double
btVector3
Vector 3D con componentes (x, y, z)
btQuaternion
Representa una rotación mediante un quaternion
btMatrix3x3
Representa una rotación mediante una matriz de
transformación 3x3
btTransform
Combina rotación y traslación
Videojuegos II
© 2013-2014 Depto. Ciencia de la Computación e IA
Introducción a Bullet
!12
V2
Motores de físicas
Objetos del mundo
• Encontramos
!
btRigidBody
!
btCollisionObject
• Sus propiedades son
Masa
btScalar
Será 0 para objetos estáticos
Forma!
btCollisionShape
Caja, Esfera, Cono, Maya, etc
Tensor de inercia
btVector3
Sólo elementos de la diagonal
Resistencia al aire
btScalar
Lineal y angular (damping)
Fricción
btScalar
Lineal y para formas redondas
Restitución
btScalar
Coeficiente de restitución
(para colisiones)
Videojuegos II
© 2013-2014 Depto. Ciencia de la Computación e IA
Introducción a Bullet
!13
V2
Motores de físicas
Creación de un cuerpo
• Debemos instanciar un objeto btRigidBody
!
btRigidBody *body = new btRigidBody(mass, motionState, shape, localInertia);
• Por lo menos debemos proporcionar los anteriores parámetros
!
Mass
Si especificamos masa 0 será estático, en otro caso dinámico
! Motion State
Indica la posición y orientación inicial del cuerpo
!
Shape
Forma geométrica del cuerpo
!Local intertia
Tensor de inercia del cuerpo
• Podemos añadir datos de usuario (por ejemplo un nodo de Irrlicht)
!
body->setUserPointer((void *)(irrNode));
• Finalmente, añadiremos el cuerpo al mundo
world->addRigidBody(body);
Videojuegos II
© 2013-2014 Depto. Ciencia de la Computación e IA
Introducción a Bullet
!14
V2
Motores de físicas
Posición y orientación de los objetos
• El objeto btMotionState facilita el acceso a esa información
• Almacena esta información como btTransform
• Incluye métodos para guardar y consultar este información
!
!
btTransform transform;
transform.setIdentity();
transform.setOrigin(position);
! !
!
!
btDefaultMotionState *motionState = new btDefaultMotionState(transform);
motionState->setWorldTransform(transform);
...
Se le pasa el objeto donde
motionState->getWorldTransform(transform);
leer por referencia
!
• Al crear el cuerpo se proporciona un objeto btMotionState
• Bullet coge de este objeto la posición al crear el cuerpo
Videojuegos II
© 2013-2014 Depto. Ciencia de la Computación e IA
Introducción a Bullet
!15
V2
Motores de físicas
Lectura de la posición y orientación
• Podemos consultar en motion state la posición tras cada iteración
• Bullet guarda la posición del objeto con setWorldTransform
!
• Implementación por defecto btDefaultMotionState
• Se pueden crear especializaciones mediante herencia
• Por ejemplo, hacer render dentro de setWorldTransform
!
• También podemos acceder directamente al objeto para obtener
su posición y orientación
btVector3 posicion = body->getCenterOfMassPosition();
const btQuaternion& orientacion = body->getOrientation();
Videojuegos II
© 2013-2014 Depto. Ciencia de la Computación e IA
La posición de los
objetos siempre se
da respecto a su
centro de masas
Introducción a Bullet
!16
V2
Motores de físicas
Tipos de cuerpos
Estáticos
Cinemáticos
Dinámicos
Videojuegos II
• Tienen masa 0
• El usuario nunca los debe mover
• Tienen masa 0
• En cada iteración Bullet lee su motion state
• Por lo tanto, el usuario puede moverlos
cambiando su motion state
• Tienen masa superior a 0
• La posición es determinada por la simulación
• El usuario puede leer el motion state para
actualizar los gráficos
© 2013-2014 Depto. Ciencia de la Computación e IA
Introducción a Bullet
!17
V2
Motores de físicas
Cuerpos cinemáticos
• Se crea como un cuerpo btRigidBody con masa 0
• Esto hará que las fuerzas del mundo no le afecten
• Si este cuerpo va a cambiar de posición, debemos marcarlo
como cinemático
!
!
!
body->setCollisionFlags(body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); body->setActivationState(DISABLE_DEACTIVATION);
!
• Esto hará que Bullet consulte su motion state antes de cada
iteración
• El motion state puede ser modificado antes de cada actualización
de la simulación
Videojuegos II
© 2013-2014 Depto. Ciencia de la Computación e IA
Introducción a Bullet
!18
V2
Motores de físicas
Tensor de inercia
• Se almacenen sólo los elementos de la diagonal del tensor de
inercia, en forma de vector de 3 componentes (btVector3)
!
• Se puede calcular automáticamente a partir de la forma y la masa
de los objetos
• La clase btCollisionShape proporciona métodos para calcularlo
btCollisionShape *shape = new btSphereShape(radio);
!
btVector3 localInertia;
shape->calculateLocalInertia(masa, localInertia);
Videojuegos II
© 2013-2014 Depto. Ciencia de la Computación e IA
Introducción a Bullet
!19
V2
Motores de físicas
Formas para la colisión
Objetos estáticos
Mapa de alturas
Otros
btHeightfieldTerrainShape
btStaticPlaneShape
btBvhTriangleMeshShape
btScaledBvhTriangleMeshShape
Objetos dinámicos
btBoxShape
btSphereShape
btCapsuleShape btCylinderShape
btConeShape
btConvexHullShape (forma convexa, limitar número de vértices <100)
btCompoundShape (combinación de formas convexas)
btGimpactTriangleMeshShape (evitar siempre que sea posible)
Videojuegos II
© 2013-2014 Depto. Ciencia de la Computación e IA
Introducción a Bullet
!20
V2
Motores de físicas
Ejemplo completo de creación de un cuerpo
• Recibimos como entrada mass, scale y position
btTransform transform;
transform.setIdentity();
transform.setOrigin(position);
!
btDefaultMotionState *motionState = new btDefaultMotionState(transform);
!
btVector3 halfExtents(scale.X * 0.5f, scale.Y * 0.5f, scale.Z * 0.5f);
btCollisionShape *shape = new btBoxShape(halfExtents);
!
btVector3 localInertia;
shape->calculateLocalInertia(mass, localInertia);
!
btRigidBody *body = new btRigidBody(mass, motionState, shape, localInertia);
!
body->setUserPointer((void *)(irrNode));
!
world->addRigidBody(body);
Videojuegos II
© 2013-2014 Depto. Ciencia de la Computación e IA
Introducción a Bullet
!21
V2
Motores de físicas
Actualización de un cuerpo en el mundo
• Actualizaremos un nodo de la escena en Irrlicht
• Recibimos como entrada el cuerpo body
ISceneNode *irrNode = static_cast<ISceneNode *>(body->getUserPointer());
!
// Actualización de la posición
btVector3 pos = body->getCenterOfMassPosition();
irrNode->setPosition(vector3df((f32)pos[0], (f32)pos[1], (f32)pos[2]));
!
// Actualización de la orientación
vector3df euler;
const btQuaternion& quat = body->getOrientation();
quaternion q(quat.getX(), quat.getY(), quat.getZ(), quat.getW());
q.toEuler(euler);
euler *= RADTODEG;
irrNode->setRotation(euler);
Videojuegos II
© 2013-2014 Depto. Ciencia de la Computación e IA
Introducción a Bullet
!22
V2
Motores de físicas
Depuración
• Bullet permite dibujar datos del mundo físico para depuración
•
•
•
•
Maya de colisión
Puntos de contacto y normales
Bounding Volumes
Restricciones y límites
!
• Utilizaremos una clase de tipo btIDebugDraw
• Sólo se proporciona una interfaz
• Deberemos crear una implementación adaptada al motor gráfico
• En ella volcaremos los datos de la física a las estructuras específicas
de nuestro motor gráfico
Videojuegos II
© 2013-2014 Depto. Ciencia de la Computación e IA
Introducción a Bullet
!23
V2
Motores de físicas
Depuración con Irrlicht (I)
class DebugDraw : public btIDebugDraw {
private:
int mode;
IVideoDriver* const driver;
ILogger* logger;
!
Implementamos
la interfaz de
btIDebugDraw
Volcaremos datos de Bullet
a estructuras de Irrlicht
public:
DebugDraw(IrrlichtDevice* const device) :
mode(DBG_NoDebug), driver(device->getVideoDriver()), logger(device->getLogger()) { }
!
!
!
!
!
void drawLine(const btVector3& from, const btVector3& to, const btVector3& color) {
SColor newColor(255, color[0]*255.0, color[1]*255.0, color[2]*255.0);
this->driver->draw3DLine(vector3df(from[0], from[1], from[2]),
vector3df(to[0], to[1], to[2]), newColor);
}
void drawContactPoint(const btVector3& PointOnB, const btVector3& normalOnB, btScalar distance, int lifeTime, const btVector3& color) {
static const SColor CONTACTPOINT_COLOR(255, 255, 255, 0);
const btVector3 to(PointOnB + normalOnB*distance);
this->driver->draw3DLine(vector3df(PointOnB[0], PointOnB[1], PointOnB[2]),
vector3df(to[0], to[1], to[2]), CONTACTPOINT_COLOR);
}
void reportErrorWarning(const char* text) {
this->logger->log(text, ELL_ERROR);
}
Único método
que debemos
implementar
obligatoriamente
void draw3dText(const btVector3& location, const char* text) { }
void setDebugMode(int mode) { this->mode = mode; }
int getDebugMode() const { return this->mode; }
};
Videojuegos II
© 2013-2014 Depto. Ciencia de la Computación e IA
Introducción a Bullet
!24
V2
Motores de físicas
Depuración con Irrlicht (II)
• Una vez definida la clase, la vinculamos al mundo físico
!
!
DebugDraw debugDraw(device);
debugDraw.setDebugMode(btIDebugDraw::DBG_DrawWireframe);
world->setDebugDrawer(&debugDraw);
!
!
• Dibujamos los datos de depuración en cada iteración
SMaterial debugMat;
debugMat.Lighting = false;
!
driver->setMaterial(debugMat);
driver->setTransform(ETS_WORLD, IdentityMatrix);
world->debugDrawWorld();
Videojuegos II
© 2013-2014 Depto. Ciencia de la Computación e IA
Es importante
restablecer la
matriz de
transformación
Introducción a Bullet
!25
V2
Motores de físicas
Restricciones
• Crean conexiones entre los cuerpos o limitan grados de libertad
• Al menos uno de los cuerpos de la conexión debe ser dinámico
• Todas derivan de btTypedConstraint
• Tipos
Point2Point
Los objetos están unidos por un único punto. Podemos
utilizarla para encadenar objetos.
Hinge
La rotación pierde 2 grados de libertad (puede rotar
alrededor de un único eje). Por ejemplo para puertas.
Slider
Puede rotar y desplazarse a lo largo de un único eje.
ConeTwist
Generic6Dof
Videojuegos II
Tipo especial de Point2Point que limita el número de
grados que puede girar. Util para articulaciones en ragdolls.
Permite personalizar los grados de libertad que queremos
limitar.
© 2013-2014 Depto. Ciencia de la Computación e IA
Introducción a Bullet
!26
V2
Motores de físicas
Cuerpos blandos
• Los cuerpos blandos no tienen una única posición
!
• Se componen de partículas conectadas de forma elástica
• Se pueden crear a partir de una triangle mesh
btSoftBodyHelpers::CreateFromTriMesh
!
• Cada partícula (nodo) se puede tratar de forma independiente
• Tienen su propia posición
• Tienen su propia masa (incluso alguna puede ser estática)
!
softbody->setMass(node, 0.0f);
• Se les puede aplicar fuerzas de forma individual
softbody->addForce(force, node);
Videojuegos II
© 2013-2014 Depto. Ciencia de la Computación e IA
Introducción a Bullet
!27
V2
Motores de físicas
Layering
• Para implementar layering en Bullet utilizamos máscaras binarias
!
• Al añadir el cuerpo al mundo podemos especificar la máscara
!
int group = 4; // 0100
int mask = 3; // 0011
world->addRigidBody(body, group, mask);
!
!
• En broad phase sólo se seleccionarán aquellos cuyas máscaras
coincidan al menos en un bit con el grupo de nuestro objeto
Grupos
0 1 1 1
Jugadores
Videojuegos II
Máscaras
Muros
NPC
0 0 1 1
0 1 0 1
0 0 0 0
Jugadores
colisionan con
NPCs y muros
NPCs con
jugadores y
muros
Muros no
colisionan con
nada
© 2013-2014 Depto. Ciencia de la Computación e IA
Introducción a Bullet
!28
V2
Motores de físicas
Información de contactos
• Proporcionados por el dispatcher
• La información de contactos se representa como un objeto de
tipo contact manifold
• Contiene una serie de puntos de contacto
int numManifolds = world->getDispatcher()->getNumManifolds();
for (int i=0;i<numManifolds;i++) {
btPersistentManifold* contactManifold = world->getDispatcher()->getManifoldByIndexInternal(i);
const btCollisionObject* obA = static_cast<const btCollisionObject*>(contactManifold->getBody0());
const btCollisionObject* obB = static_cast<const btCollisionObject*>(contactManifold->getBody1());
!
}
int numContacts = contactManifold->getNumContacts();
for (int j=0;j<numContacts;j++) {
btManifoldPoint& pt = contactManifold->getContactPoint(j);
}
Videojuegos II
© 2013-2014 Depto. Ciencia de la Computación e IA
Introducción a Bullet
!29
V2
Motores de físicas
Sensores (triggers)
• Podemos obtener aviso de contactos sin simular colisión
• P.ej., cuando una pelota atraviesa la portería
!
• Utilizamos para ello sensores o triggers
• En Bullet deberemos marcarlos con el flag de colisión
CF_NO_CONTACT_RESPONSE
!
!
body->setCollisionFlags(cubeBody->getCollisionFlags() | btCollisionObject::CF_NO_CONTACT_RESPONSE);
!
• Nos informará de contactos en el manifold
• La simulación no resolverá la colisión (este cuerpo será atravesado
por otros)
Videojuegos II
© 2013-2014 Depto. Ciencia de la Computación e IA
Introducción a Bullet
!30
V2
Motores de físicas
Trazado de rayos
!
• Podemos trazar rayos hacia los objetos del mundo de Bullet
btVector3 start(0,0,0);
btVector3 end(0,0,1);
!
btCollisionWorld::ClosestRayResultCallback rayCallback(start, end);
!
world->rayTest(start, end, rayCallback);
!
if(rayCallback.hasHit()) {
btVector3 point = rayCallback.m_hitPointWorld;
btVector3 normal = rayCallback.m_hitNormalWorld;
btCollisionObject *object = rayCallback.m_collisionObject;
}
Videojuegos II
© 2013-2014 Depto. Ciencia de la Computación e IA
Introducción a Bullet
!31
V2
Motores de físicas
Objetos de colisión
• Bullet no detecta colisiones entre cuerpos cinemáticos y estáticos
• Siempre debe intervenir un cuerpo dinámico
!
• Tenemos la opción de utilizar objetos de colisión
Se implementan con btCollisionObject (o subclases)
Se comportan de forma similar a cuerpos cinemáticos
Permiten detectar colisiones sin simulación física
NO son cuerpos rígidos
•
•
•
•
btCollisionObject platform = new btCollisionObject();
!
btCollisionShape *platformShape = new btBoxShape(btVector3(25,0.5, 25));
platform->setCollisionShape(platformShape);
world->addCollisionObject(platform);
Videojuegos II
© 2013-2014 Depto. Ciencia de la Computación e IA
Introducción a Bullet
!32
V2
Motores de físicas
Ghost Objects
• Optimizan la detección de colisiones
• Especialización de los objetos de colisión
• Permiten consultar sólo las colisiones que se producen con ellos
• Mantiene una caché de parejas con las que puede colisionar
!
btPairCachingGhostObject
*platform = new btPairCachingGhostObject();
!
!
btCollisionShape *platformShape = new btBoxShape(btVector3(25,0.5, 25));
platform->setCollisionShape(platformShape);
!
world->addCollisionObject(platform);
!
• Para que el ghost object mantenga su lista de colisiones deberemos
además configurar el siguiente callback
world->getBroadphase()->getOverlappingPairCache()->
setInternalGhostPairCallback(new btGhostPairCallback());
Videojuegos II
© 2013-2014 Depto. Ciencia de la Computación e IA
Introducción a Bullet
!33
V2
Motores de físicas
Revisar los contactos del Ghost Object
btManifoldArray manifoldArray;
btBroadphasePairArray &pairs = body->getOverlappingPairCache()->getOverlappingPairArray();
!
for(int i=0;i< pairs.size();;i++) {
manifoldArray.clear();
const btBroadphasePair &pair = pairs[i];
btBroadphasePair *collisionPair = world->getPairCache()->findPair(pair.m_pProxy0, pair.m_pProxy1);
if(!collisionPair)
continue;
!
if(collisionPair->m_algorithm) {
collisionPair->m_algorithm->getAllContactManifolds(manifoldArray);
}
}
for(int j=0;j<manifoldArray.size();j++) {
btPersistentManifold *manifold = manifoldArray[j];
for(int p=0;p<manifold->getNumContacts();p++) {
const btManifoldPoint &contact = manifold->getContactPoint(p);
}
}
!
Videojuegos II
© 2013-2014 Depto. Ciencia de la Computación e IA
Introducción a Bullet
!34
V2
Motores de físicas
Controlador de personajes
• Para nuestro personaje o NPCs podemos utilizar una forma de
colisión de tipo cápsula
• Deberemos evitar que el personaje pueda rotar
!
!
body->setAngularFactor(0);
• Existe un controlador cinemático experimental implementado
btPairCachingGhostObject *ghostObject = new btPairCachingGhostObject();
ghostObject->setWorldTransform(transform);
!
Utiliza un ghost object para
detectar colisiones
btScalar characterHeight=1.75;
btScalar characterWidth =1.75;
btConvexShape* capsule = new btCapsuleShape(characterWidth,characterHeight);
!
Recomendable utilizar cápsula
ghostObject->setCollisionShape (capsule);
ghostObject->setCollisionFlags (btCollisionObject::CF_CHARACTER_OBJECT);
!
btScalar stepHeight = btScalar(0.35);
character = new btKinematicCharacterController(ghostObject,capsule,stepHeight);
Videojuegos II
© 2013-2014 Depto. Ciencia de la Computación e IA
Introducción a Bullet
!35
V2
Motores de físicas
Herramientas
• Incluyen
• Definición de formas de colisión
• Propiedades de cuerpos rígidos y restricciones
!
• Herramientas disponibles
• Dynamica Maya Plugin
• Blender
!
• Formatos
• Formato propio .bullet (permite serializar/deserializar a este
formato)
• COLLADA (obsoleto)
Videojuegos II
© 2013-2014 Depto. Ciencia de la Computación e IA
Introducción a Bullet
!36
V2
Motores de físicas
Definir físicas con Blender
• Definiremos la física en el modo Blender Game
Panel de
físicas
Propiedades
físicas del
material
Videojuegos II
© 2013-2014 Depto. Ciencia de la Computación e IA
Introducción a Bullet
!37
V2
Motores de físicas
Exportar físicas
• Creamos un script para exportar físicas a un fichero .bullet
!
!
!
¡CUIDADO!
Bullet utiliza un sistema
de coordenadas en el
que el eje Z es la altura
!
• Añadimos un sensor vinculado con el script
Al pulsar la tecla P
durante la simulación se
almacenarán los datos
Videojuegos II
© 2013-2014 Depto. Ciencia de la Computación e IA
Introducción a Bullet
!38
V2
Motores de físicas
Importar físicas
• Debemos incluir el módulo de importación
!
¡CUIDADO!
Irrlicht utiliza un sistema
de coordenadas en el
que el eje Y es la altura
#include <BulletWorldImporter/btBulletWorldImporter.h>
!
• Importamos los datos grabados
!
!
btBulletWorldImporter* fileLoader = new btBulletWorldImporter(world);
fileLoader->loadFile("escenario.bullet");
world->setGravity(btVector3(0,-10,0));
!
• Podemos consultar los objetos importados
for(int i=0;i<objects.size();i++) {
btCollisionObject *obj = objects[i];
printf("Encontrado cuerpo de tipo %d", obj->getCollisionShape()->getShapeType());
}
Videojuegos II
© 2013-2014 Depto. Ciencia de la Computación e IA
Introducción a Bullet
!39
V2
Motores de físicas
Sistemas de coordenadas
• Podemos hacer coincidir los sistemas de
coordenadas Blender - Irrlicht
!
• Exportamos modelo gráfico en Blender con
• Y up
• -Z forward
!
• Para la maya de colisión, transformamos el
modelo con
• Giro de -90º alrededor de x
• Escalado de -1 en x (mirror)
• Aplicamos la transformación (Object > Apply)
• Exportamos y deshacemos los cambios
Videojuegos II
© 2013-2014 Depto. Ciencia de la Computación e IA
Introducción a Bullet
!40
V2
Motores de físicas
Recomendaciones para la exportación
• Es posible agrupar todo el escenario
en un único objeto
• Abrimos el cuadro de herramientas con T
• Utilizamos la herramienta Join de Blender
• Por defecto se exportará como
ScaledBvhTriangleMesh
!
• Reducir la poligonización
• Podemos utilizar la herramienta Decimate
de Blender
Videojuegos II
© 2013-2014 Depto. Ciencia de la Computación e IA
Introducción a Bullet
!41
V2
Motores de físicas
Optimización del modelo importado
• Por defecto Blender no construye el BVH del modelo exportado
• Podemos construirlo con Bullet al importar
!
for(int
i=0;i<objects.size();i++) {
btCollisionObject *obj = objects[i];
!
if(obj->getCollisionShape()->getShapeType()==
SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE) {
!
btScaledBvhTriangleMeshShape *shape = static_cast<btScaledBvhTriangleMeshShape *>(obj->getCollisionShape());
!
if(!shape->getChildShape()->getOwnsBvh()) {
! shape->getChildShape()->buildOptimizedBvh();
}
! }
}
!
• Si el proceso resulta lento, podemos serializar el objeto
btOptimizedBvh • Métodos serializeInPlace y deSerializeInPlace
Videojuegos II
© 2013-2014 Depto. Ciencia de la Computación e IA
Introducción a Bullet
!42
V2
Motores de físicas
¿Preguntas...?
Videojuegos II
© 2013-2014 Depto. Ciencia de la Computación e IA
Introducción a Bullet
!43

Documentos relacionados