overte/libraries/physics/src/ShapeInfo.cpp
2014-11-04 14:54:35 -08:00

165 lines
5.3 KiB
C++

//
// ShapeInfo.cpp
// libraries/physcis/src
//
// Created by Andrew Meadows 2014.10.29
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifdef USE_BULLET_PHYSICS
#include <btBulletDynamicsCommon.h>
#include "ShapeInfo.h"
void ShapeInfo::collectInfo(const btCollisionShape* shape) {
_data.clear();
if (shape) {
_type = (unsigned int)(shape->getShapeType());
switch(_type) {
case BOX_SHAPE_PROXYTYPE:
{
const btBoxShape* boxShape = static_cast<const btBoxShape*>(shape);
_data.push_back(boxShape->getHalfExtentsWithMargin());
}
break;
case SPHERE_SHAPE_PROXYTYPE:
{
const btSphereShape* sphereShape = static_cast<const btSphereShape*>(shape);
_data.push_back(btVector3(0.0f, 0.0f, sphereShape->getRadius()));
}
break;
case CYLINDER_SHAPE_PROXYTYPE:
{
const btCylinderShape* cylinderShape = static_cast<const btCylinderShape*>(shape);
_data.push_back(cylinderShape->getHalfExtentsWithMargin());
}
break;
case CAPSULE_SHAPE_PROXYTYPE:
{
const btCapsuleShape* capsuleShape = static_cast<const btCapsuleShape*>(shape);
_data.push_back(btVector3(capsuleShape->getRadius(), capsuleShape->getHalfHeight(), 0.0f));
// NOTE: we only support capsules with axis along yAxis
}
break;
default:
_type = INVALID_SHAPE_PROXYTYPE;
break;
}
} else {
_type = INVALID_SHAPE_PROXYTYPE;
}
}
void ShapeInfo::setBox(const btVector3& halfExtents) {
_type = BOX_SHAPE_PROXYTYPE;
_data.clear();
_data.push_back(halfExtents);
}
void ShapeInfo::setSphere(float radius) {
_type = SPHERE_SHAPE_PROXYTYPE;
_data.clear();
_data.push_back(btVector3(0.0f, 0.0f, radius));
}
void ShapeInfo::setCylinder(float radius, float height) {
_type = CYLINDER_SHAPE_PROXYTYPE;
_data.clear();
// NOTE: default cylinder has (UpAxis = 1) axis along yAxis and radius stored in X
// halfExtents = btVector3(radius, halfHeight, unused)
_data.push_back(btVector3(radius, 0.5f * height, radius));
}
void ShapeInfo::setCapsule(float radius, float height) {
_type = CAPSULE_SHAPE_PROXYTYPE;
_data.clear();
_data.push_back(btVector3(radius, 0.5f * height, 0.0f));
}
const float MILLIMETERS_PER_METER = 1000.0f;
int ShapeInfo::computeHash() const {
// scramble the bits of the type
// TODO?: provide lookup table for hash of _type?
int primeIndex = 0;
unsigned int hash = DoubleHashKey::hashFunction((unsigned int)_type, primeIndex++);
btVector3 tmpData;
int numData = _data.size();
for (int i = 0; i < numData; ++i) {
tmpData = _data[i];
for (int j = 0; j < 3; ++j) {
// multiply these mm by a new prime
unsigned int floatHash = DoubleHashKey::hashFunction((unsigned int)(tmpData[j] * MILLIMETERS_PER_METER + 0.49f), primeIndex++);
hash ^= floatHash;
}
}
return hash;
}
int ShapeInfo::computeHash2() const {
// scramble the bits of the type
// TODO?: provide lookup table for hash of _type?
unsigned int hash = DoubleHashKey::hashFunction2((unsigned int)_type);
btVector3 tmpData;
int numData = _data.size();
for (int i = 0; i < numData; ++i) {
tmpData = _data[i];
for (int j = 0; j < 3; ++j) {
unsigned int floatHash = DoubleHashKey::hashFunction2((unsigned int)(tmpData[j] * MILLIMETERS_PER_METER + 0.49f));
hash += ~(floatHash << 17);
hash ^= (floatHash >> 11);
hash += (floatHash << 4);
hash ^= (floatHash >> 7);
hash += ~(floatHash << 10);
hash = (hash << 16) | (hash >> 16);
}
}
return hash;
}
btCollisionShape* ShapeInfo::createShape() const {
btCollisionShape* shape = NULL;
int numData = _data.size();
switch(_type) {
case BOX_SHAPE_PROXYTYPE: {
if (numData > 0) {
btVector3 halfExtents = _data[0];
shape = new btBoxShape(halfExtents);
}
}
break;
case SPHERE_SHAPE_PROXYTYPE: {
if (numData > 0) {
float radius = _data[0].getZ();
shape = new btSphereShape(radius);
}
}
break;
case CYLINDER_SHAPE_PROXYTYPE: {
if (numData > 0) {
btVector3 halfExtents = _data[0];
// NOTE: default cylinder has (UpAxis = 1) axis along yAxis and radius stored in X
// halfExtents = btVector3(radius, halfHeight, unused)
shape = new btCylinderShape(halfExtents);
}
}
break;
case CAPSULE_SHAPE_PROXYTYPE: {
if (numData > 0) {
float radius = _data[0].getX();
float height = 2.0f * _data[0].getY();
shape = new btCapsuleShape(radius, height);
}
}
break;
}
return shape;
}
#endif // USE_BULLET_PHYSICS