mirror of
https://github.com/overte-org/overte.git
synced 2025-04-21 06:44:06 +02:00
more virtual entity work
This commit is contained in:
parent
ec0c350f60
commit
c449ba27a9
6 changed files with 148 additions and 74 deletions
|
@ -124,14 +124,15 @@ public:
|
|||
|
||||
glm::vec3 getMinimumPoint() const { return _position - glm::vec3(_radius, _radius, _radius); }
|
||||
glm::vec3 getMaximumPoint() const { return _position + glm::vec3(_radius, _radius, _radius); }
|
||||
AACube getAACube() const { return AACube(getMinimumPoint(), getSize()); } /// AACube in domain scale units (0.0 - 1.0)
|
||||
AACube getAACube() const { return AACube(getMinimumPoint(), getMaxDimension()); } /// AACube in domain scale units (0.0 - 1.0)
|
||||
void debugDump() const;
|
||||
|
||||
// properties of all entities
|
||||
EntityTypes::EntityType_t getType() const { return _type; }
|
||||
const glm::vec3& getPosition() const { return _position; }
|
||||
float getRadius() const { return _radius; }
|
||||
glm::vec3 getSize() const { return glm::vec3(_radius, _radius, _radius) * 2.0f; }
|
||||
float getMaxDimension() const { return _radius * 2.0f; }
|
||||
glm::vec3 getDimensions() const { return glm::vec3(_radius, _radius, _radius) * 2.0f; }
|
||||
const glm::quat& getRotation() const { return _rotation; }
|
||||
bool getShouldBeDeleted() const { return _shouldBeDeleted; }
|
||||
|
||||
|
|
|
@ -242,20 +242,23 @@ EntityItem* EntityTree::getOrCreateEntityItem(const EntityItemID& entityID, cons
|
|||
class UpdateEntityOperator : public RecurseOctreeOperator {
|
||||
public:
|
||||
UpdateEntityOperator(EntityTree* tree, EntityTreeElement* containingElement,
|
||||
EntityItem* oldEntity, const EntityItemProperties& properties);
|
||||
EntityItem* existingEntity, const EntityItemProperties& properties);
|
||||
|
||||
virtual bool PreRecursion(OctreeElement* element);
|
||||
virtual bool PostRecursion(OctreeElement* element);
|
||||
virtual OctreeElement* PossiblyCreateChildAt(OctreeElement* element, int childIndex);
|
||||
private:
|
||||
EntityTree* _tree;
|
||||
const EntityItem* _newEntity;
|
||||
const EntityItem* _oldEntity;
|
||||
const EntityItem* _existingEntity;
|
||||
EntityTreeElement* _containingElement;
|
||||
EntityItemID _entityItemID;
|
||||
bool _foundOld;
|
||||
bool _foundNew;
|
||||
bool _removeOld;
|
||||
quint64 _changeTime;
|
||||
AABox _oldEntityCube;
|
||||
AABox _newEntityCube;
|
||||
|
||||
AACube _oldEntityCube;
|
||||
AACube _newEntityCube;
|
||||
|
||||
bool subTreeContainsOldEntity(OctreeElement* element);
|
||||
bool subTreeContainsNewEntity(OctreeElement* element);
|
||||
|
@ -263,20 +266,21 @@ private:
|
|||
|
||||
UpdateEntityOperator::UpdateEntityOperator(EntityTree* tree,
|
||||
EntityTreeElement* containingElement,
|
||||
EntityItem* oldEntity,
|
||||
EntityItem* existingEntity,
|
||||
const EntityItemProperties& properties) :
|
||||
_tree(tree),
|
||||
_newEntity(NULL),
|
||||
_oldEntity(oldEntity),
|
||||
_existingEntity(existingEntity),
|
||||
_containingElement(containingElement),
|
||||
_entityItemID(existingEntity->getEntityItemID()),
|
||||
_foundOld(false),
|
||||
_foundNew(false),
|
||||
_removeOld(false),
|
||||
_changeTime(usecTimestampNow())
|
||||
{
|
||||
// caller must have verified existence of containingElement and oldEntity
|
||||
assert(_containingElement && _oldEntity);
|
||||
assert(_containingElement && _existingEntity);
|
||||
|
||||
_oldEntityCube = _oldEntity->getAACube();
|
||||
_oldEntityCube = _existingEntity->getAACube();
|
||||
|
||||
// If our new properties don't have bounds details (no change to position, etc) or if this containing element would
|
||||
// be the best fit for our new properties, then just do the new portion of the store pass, since the change path will
|
||||
|
@ -285,34 +289,24 @@ UpdateEntityOperator::UpdateEntityOperator(EntityTree* tree,
|
|||
_foundOld = true;
|
||||
_newEntityCube = _oldEntityCube;
|
||||
} else {
|
||||
_newEntityCube = _oldEntity->getAACube();
|
||||
_newEntityCube = properties.getAACube();
|
||||
_removeOld = true; // our properties are going to move us, so remember this for later processing
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// does this model tree element contain the old model
|
||||
bool UpdateEntityOperator::subTreeContainsOldEntity(OctreeElement* element) {
|
||||
bool containsEntity = false;
|
||||
|
||||
// If we don't have an old model, then we don't contain the model, otherwise
|
||||
// check the bounds
|
||||
if (_oldEntity) {
|
||||
AACube elementCube = element->getAACube();
|
||||
AACube modelCube = _oldEntity->getAACube();
|
||||
containsEntity = elementCube.contains(modelCube);
|
||||
}
|
||||
return containsEntity;
|
||||
return element->getAACube().contains(_oldEntityCube);
|
||||
}
|
||||
|
||||
bool UpdateEntityOperator::subTreeContainsNewEntity(OctreeElement* element) {
|
||||
AACube elementCube = element->getAACube();
|
||||
AACube modelCube = _newEntity.getAACube();
|
||||
return elementCube.contains(modelCube);
|
||||
return element->getAACube().contains(_newEntityCube);
|
||||
}
|
||||
|
||||
|
||||
bool UpdateEntityOperator::PreRecursion(OctreeElement* element) {
|
||||
EntityTreeElement* modelTreeElement = static_cast<EntityTreeElement*>(element);
|
||||
EntityTreeElement* entityTreeElement = static_cast<EntityTreeElement*>(element);
|
||||
|
||||
// In Pre-recursion, we're generally deciding whether or not we want to recurse this
|
||||
// path of the tree. For this operation, we want to recurse the branch of the tree if
|
||||
|
@ -331,19 +325,19 @@ bool UpdateEntityOperator::PreRecursion(OctreeElement* element) {
|
|||
|
||||
// If this is the element we're looking for, then ask it to remove the old model
|
||||
// and we can stop searching.
|
||||
if (modelTreeElement == _containingElement) {
|
||||
if (entityTreeElement == _containingElement) {
|
||||
|
||||
// If the containgElement IS NOT the best fit for the new model properties
|
||||
// then we need to remove it, and the updateEntity below will store it in the
|
||||
// correct element.
|
||||
if (!_containingElement->bestFitEntityBounds(&_newEntity)) {
|
||||
modelTreeElement->removeEntityWithEntityItemID(_newEntity.getEntityItemID());
|
||||
if (!_removeOld) {
|
||||
entityTreeElement->removeEntityItem(_existingEntity); // NOTE: only removes the entity, doesn't delete it
|
||||
|
||||
// If we haven't yet found the new location, then we need to
|
||||
// make sure to remove our model to element map, because for
|
||||
// now we're not in that map
|
||||
if (!_foundNew) {
|
||||
_tree->setContainingElement(_newEntity.getEntityItemID(), NULL);
|
||||
_tree->setContainingElement(_entityItemID, NULL);
|
||||
}
|
||||
}
|
||||
_foundOld = true;
|
||||
|
@ -357,15 +351,19 @@ bool UpdateEntityOperator::PreRecursion(OctreeElement* element) {
|
|||
// model, then we need to keep searching.
|
||||
if (!_foundNew && subTreeContainsNewEntity(element)) {
|
||||
|
||||
// Note: updateEntity() will only operate on correctly found models and/or add them
|
||||
// to the element if they SHOULD be stored there.
|
||||
if (modelTreeElement->updateEntity(_newEntity)) {
|
||||
//qDebug() << "UpdateEntityOperator::PreRecursion()... model was updated!";
|
||||
_foundNew = true;
|
||||
// NOTE: don't change the keepSearching here, if it came in here
|
||||
// false then we stay false, if it came in here true, then it
|
||||
// means we're still searching for our old model and this branch
|
||||
// contains our old model. In which case we want to keep searching.
|
||||
// If this element is the best fit for the new entity properties, then add/or update it
|
||||
if (entityTreeElement->bestFitBounds(_newEntityCube)) {
|
||||
|
||||
if (entityTreeElement->addOrUpdateEntity(_existingEntity, properties)) {
|
||||
|
||||
//qDebug() << "UpdateEntityOperator::PreRecursion()... model was updated!";
|
||||
_foundNew = true;
|
||||
// NOTE: don't change the keepSearching here, if it came in here
|
||||
// false then we stay false, if it came in here true, then it
|
||||
// means we're still searching for our old model and this branch
|
||||
// contains our old model. In which case we want to keep searching.
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
keepSearching = true;
|
||||
|
|
|
@ -190,6 +190,14 @@ bool EntityTreeElement::bestFitBounds(const EntityItemProperties& properties) co
|
|||
return bestFitBounds(properties.getMinimumPoint(), properties.getMaximumPoint());
|
||||
}
|
||||
|
||||
bool EntityTreeElement::containsBounds(const AACube& bounds) const {
|
||||
return containsBounds(bounds.getMinimumPoint(), bounds.getMaximumPoint());
|
||||
}
|
||||
|
||||
bool EntityTreeElement::bestFitBounds(const AACube& bounds) const {
|
||||
return bestFitBounds(bounds.getMinimumPoint(), bounds.getMaximumPoint());
|
||||
}
|
||||
|
||||
bool EntityTreeElement::containsBounds(const glm::vec3& minPoint, const glm::vec3& maxPoint) const {
|
||||
glm::vec3 clampedMin = glm::clamp(minPoint, 0.0f, 1.0f);
|
||||
glm::vec3 clampedMax = glm::clamp(maxPoint, 0.0f, 1.0f);
|
||||
|
@ -265,13 +273,13 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con
|
|||
while(entityItr != entityEnd) {
|
||||
EntityItem* entity = (*entityItr);
|
||||
|
||||
AACube entityCube = entity.getAACube();
|
||||
AACube entityCube = entity->getAACube();
|
||||
float localDistance;
|
||||
BoxFace localFace;
|
||||
|
||||
// if the ray doesn't intersect with our cube, we can stop searching!
|
||||
if (entityCube.findRayIntersection(origin, direction, localDistance, localFace)) {
|
||||
const FBXGeometry* fbxGeometry = _myTree->getGeometryForEntity(entity);
|
||||
const FBXGeometry* fbxGeometry = _myTree->getGeometryForEntity(*entity);
|
||||
if (fbxGeometry && fbxGeometry->meshExtents.isValid()) {
|
||||
Extents extents = fbxGeometry->meshExtents;
|
||||
|
||||
|
@ -284,7 +292,7 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con
|
|||
// size is our "target size in world space"
|
||||
// we need to set our entity scale so that the extents of the mesh, fit in a cube that size...
|
||||
float maxDimension = glm::distance(extents.maximum, extents.minimum);
|
||||
float scale = entity.getSize() / maxDimension;
|
||||
float scale = entity->getSize() / maxDimension;
|
||||
|
||||
glm::vec3 halfDimensions = (extents.maximum - extents.minimum) * 0.5f;
|
||||
glm::vec3 offset = -extents.minimum - halfDimensions;
|
||||
|
@ -297,10 +305,10 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con
|
|||
|
||||
Extents rotatedExtents = extents;
|
||||
|
||||
calculateRotatedExtents(rotatedExtents, entity.getRotation());
|
||||
calculateRotatedExtents(rotatedExtents, entity->getRotation());
|
||||
|
||||
rotatedExtents.minimum += entity.getPosition();
|
||||
rotatedExtents.maximum += entity.getPosition();
|
||||
rotatedExtents.minimum += entity->getPosition();
|
||||
rotatedExtents.maximum += entity->getPosition();
|
||||
|
||||
|
||||
AABox rotatedExtentsBox(rotatedExtents.minimum, (rotatedExtents.maximum - rotatedExtents.minimum));
|
||||
|
@ -309,8 +317,8 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con
|
|||
if (rotatedExtentsBox.findRayIntersection(origin, direction, localDistance, localFace)) {
|
||||
|
||||
// extents is the entity relative, scaled, centered extents of the entity
|
||||
glm::mat4 rotation = glm::mat4_cast(entity.getRotation());
|
||||
glm::mat4 translation = glm::translate(entity.getPosition());
|
||||
glm::mat4 rotation = glm::mat4_cast(entity->getRotation());
|
||||
glm::mat4 translation = glm::translate(entity->getPosition());
|
||||
glm::mat4 entityToWorldMatrix = translation * rotation;
|
||||
glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix);
|
||||
|
||||
|
@ -348,9 +356,9 @@ bool EntityTreeElement::findSpherePenetration(const glm::vec3& center, float rad
|
|||
QList<EntityItem*>::iterator entityItr = _entityItems->begin();
|
||||
QList<EntityItem*>::const_iterator entityEnd = _entityItems->end();
|
||||
while(entityItr != entityEnd) {
|
||||
EntityItem& entity = (*entityItr);
|
||||
glm::vec3 entityCenter = entity.getPosition();
|
||||
float entityRadius = entity.getRadius();
|
||||
EntityItem* entity = (*entityItr);
|
||||
glm::vec3 entityCenter = entity->getPosition();
|
||||
float entityRadius = entity->getRadius();
|
||||
|
||||
// don't penetrate yourself
|
||||
if (entityCenter == center && entityRadius == radius) {
|
||||
|
@ -359,7 +367,7 @@ bool EntityTreeElement::findSpherePenetration(const glm::vec3& center, float rad
|
|||
|
||||
if (findSphereSpherePenetration(center, radius, entityCenter, entityRadius, penetration)) {
|
||||
// return true on first valid entity penetration
|
||||
*penetratedObject = (void*)(&entity);
|
||||
*penetratedObject = (void*)(entity);
|
||||
return true;
|
||||
}
|
||||
++entityItr;
|
||||
|
@ -367,6 +375,41 @@ bool EntityTreeElement::findSpherePenetration(const glm::vec3& center, float rad
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
// TODO... how do we handle older/newer with this interface?
|
||||
bool EntityTreeElement::addOrUpdateEntity(EntityItem* entity, const EntityItemProperties& properties) {
|
||||
const bool wantDebug = false;
|
||||
if (wantDebug) {
|
||||
EntityItemID entityItemID = entity->getEntityItemID();
|
||||
qDebug() << "EntityTreeElement::updateEntity(entity) entityID.id="
|
||||
<< entityItemID.id << "creatorTokenID=" << entityItemID.creatorTokenID;
|
||||
}
|
||||
|
||||
// NOTE: this method must first lookup the entity by ID, hence it is O(N)
|
||||
// and "entity is not found" is worst-case (full N) but maybe we don't care?
|
||||
// (guaranteed that num entities per elemen is small?)
|
||||
uint16_t numberOfEntities = _entityItems->size();
|
||||
for (uint16_t i = 0; i < numberOfEntities; i++) {
|
||||
EntityItem* thisEntity = (*_entityItems)[i];
|
||||
if (thisEntity == entity) {
|
||||
if (wantDebug) {
|
||||
qDebug() << "found the entity";
|
||||
}
|
||||
thisEntity->setProperties(properties);
|
||||
markWithChangedTime();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// If we didn't find the entity here, then let's check to see if we should add it...
|
||||
_entityItems->push_back(entity);
|
||||
markWithChangedTime();
|
||||
// Since we're adding this item to this element, we need to let the tree know about it
|
||||
_myTree->setContainingElement(entity->getEntityItemID(), this);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: the old entity code has support for sittingPoints... need to determine how to handle this...
|
||||
// for local editors, the old updateModels(id, properties) had this code...
|
||||
// if (found) {
|
||||
|
@ -375,6 +418,7 @@ bool EntityTreeElement::findSpherePenetration(const glm::vec3& center, float rad
|
|||
// thisModel.setSittingPoints(_myTree->getGeometryForModel(thisModel)->sittingPoints);
|
||||
// }
|
||||
// ...
|
||||
#if 0
|
||||
bool EntityTreeElement::updateEntity(const EntityItem& entity) {
|
||||
const bool wantDebug = false;
|
||||
if (wantDebug) {
|
||||
|
@ -433,6 +477,7 @@ bool EntityTreeElement::updateEntity(const EntityItem& entity) {
|
|||
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
void EntityTreeElement::updateEntityItemID(FindAndUpdateEntityItemIDArgs* args) {
|
||||
bool wantDebug = false;
|
||||
|
@ -483,7 +528,7 @@ const EntityItem* EntityTreeElement::getClosestEntity(glm::vec3 position) const
|
|||
for (uint16_t i = 0; i < numberOfEntities; i++) {
|
||||
float distanceToEntity = glm::distance(position, (*_entityItems)[i]->getPosition());
|
||||
if (distanceToEntity < closestEntityDistance) {
|
||||
closestEntity = &(*_entityItems)[i];
|
||||
closestEntity = (*_entityItems)[i];
|
||||
}
|
||||
}
|
||||
return closestEntity;
|
||||
|
@ -492,7 +537,7 @@ const EntityItem* EntityTreeElement::getClosestEntity(glm::vec3 position) const
|
|||
void EntityTreeElement::getEntities(const glm::vec3& searchPosition, float searchRadius, QVector<const EntityItem*>& foundEntities) const {
|
||||
uint16_t numberOfEntities = _entityItems->size();
|
||||
for (uint16_t i = 0; i < numberOfEntities; i++) {
|
||||
const EntityItem* entity = &(*_entityItems)[i];
|
||||
const EntityItem* entity = (*_entityItems)[i];
|
||||
float distance = glm::length(entity->getPosition() - searchPosition);
|
||||
if (distance < searchRadius + entity->getRadius()) {
|
||||
foundEntities.push_back(entity);
|
||||
|
@ -582,6 +627,20 @@ bool EntityTreeElement::removeEntityWithEntityItemID(const EntityItemID& id) {
|
|||
return foundEntity;
|
||||
}
|
||||
|
||||
bool EntityTreeElement::removeEntityItem(const EntityItem* entity) {
|
||||
bool foundEntity = false;
|
||||
uint16_t numberOfEntities = _entityItems->size();
|
||||
for (uint16_t i = 0; i < numberOfEntities; i++) {
|
||||
if ((*_entityItems)[i] == entity) {
|
||||
foundEntity = true;
|
||||
_entityItems->removeAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return foundEntity;
|
||||
}
|
||||
|
||||
|
||||
int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
|
||||
ReadBitstreamToTreeParams& args) {
|
||||
|
||||
|
|
|
@ -121,6 +121,9 @@ public:
|
|||
void setTree(EntityTree* tree) { _myTree = tree; }
|
||||
|
||||
bool updateEntity(const EntityItem& entity);
|
||||
bool addOrUpdateEntity(EntityItem* entity, const EntityItemProperties& properties);
|
||||
|
||||
|
||||
void updateEntityItemID(FindAndUpdateEntityItemIDArgs* args);
|
||||
|
||||
const EntityItem* getClosestEntity(glm::vec3 position) const;
|
||||
|
@ -143,6 +146,7 @@ public:
|
|||
|
||||
bool removeEntityWithID(uint32_t id);
|
||||
bool removeEntityWithEntityItemID(const EntityItemID& id);
|
||||
bool removeEntityItem(const EntityItem* entity);
|
||||
|
||||
bool containsEntityBounds(const EntityItem* entity) const;
|
||||
bool bestFitEntityBounds(const EntityItem* entity) const;
|
||||
|
@ -150,6 +154,9 @@ public:
|
|||
bool containsBounds(const EntityItemProperties& properties) const;
|
||||
bool bestFitBounds(const EntityItemProperties& properties) const;
|
||||
|
||||
bool containsBounds(const AACube& bounds) const;
|
||||
bool bestFitBounds(const AACube& bounds) const;
|
||||
|
||||
bool containsBounds(const glm::vec3& minPoint, const glm::vec3& maxPoint) const;
|
||||
bool bestFitBounds(const glm::vec3& minPoint, const glm::vec3& maxPoint) const;
|
||||
|
||||
|
|
|
@ -42,6 +42,11 @@ public:
|
|||
glm::vec3 calcCenter() const;
|
||||
glm::vec3 calcTopFarLeft() const;
|
||||
glm::vec3 getVertex(BoxVertex vertex) const;
|
||||
|
||||
const glm::vec3& getMinimumPoint() const { return _corner; }
|
||||
glm::vec3 getMaximumPoint() const { return calcTopFarLeft(); }
|
||||
|
||||
|
||||
bool contains(const glm::vec3& point) const;
|
||||
bool contains(const AABox& otherBox) const;
|
||||
bool touches(const AABox& otherBox) const;
|
||||
|
|
|
@ -28,27 +28,31 @@ public:
|
|||
AACube();
|
||||
~AACube() {};
|
||||
|
||||
void setBox(const glm::vec3& corner, float scale);
|
||||
glm::vec3 getVertexP(const glm::vec3& normal) const;
|
||||
glm::vec3 getVertexN(const glm::vec3& normal) const;
|
||||
void scale(float scale);
|
||||
const glm::vec3& getCorner() const { return _corner; }
|
||||
float getScale() const { return _scale; }
|
||||
glm::vec3 getDimensions() const { return glm::vec3(_scale,_scale,_scale); }
|
||||
void setBox(const glm::vec3& corner, float scale);
|
||||
glm::vec3 getVertexP(const glm::vec3& normal) const;
|
||||
glm::vec3 getVertexN(const glm::vec3& normal) const;
|
||||
void scale(float scale);
|
||||
const glm::vec3& getCorner() const { return _corner; }
|
||||
float getScale() const { return _scale; }
|
||||
glm::vec3 getDimensions() const { return glm::vec3(_scale,_scale,_scale); }
|
||||
|
||||
glm::vec3 calcCenter() const;
|
||||
glm::vec3 calcTopFarLeft() const;
|
||||
glm::vec3 getVertex(BoxVertex vertex) const;
|
||||
bool contains(const glm::vec3& point) const;
|
||||
bool contains(const AACube& otherCube) const;
|
||||
bool touches(const AACube& otherCube) const;
|
||||
bool contains(const AABox& otherBox) const;
|
||||
bool touches(const AABox& otherBox) const;
|
||||
bool expandedContains(const glm::vec3& point, float expansion) const;
|
||||
bool expandedIntersectsSegment(const glm::vec3& start, const glm::vec3& end, float expansion) const;
|
||||
bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const;
|
||||
bool findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration) const;
|
||||
bool findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius, glm::vec3& penetration) const;
|
||||
glm::vec3 calcCenter() const;
|
||||
glm::vec3 calcTopFarLeft() const;
|
||||
glm::vec3 getVertex(BoxVertex vertex) const;
|
||||
|
||||
const glm::vec3& getMinimumPoint() const { return _corner; }
|
||||
glm::vec3 getMaximumPoint() const { return calcTopFarLeft(); }
|
||||
|
||||
bool contains(const glm::vec3& point) const;
|
||||
bool contains(const AACube& otherCube) const;
|
||||
bool touches(const AACube& otherCube) const;
|
||||
bool contains(const AABox& otherBox) const;
|
||||
bool touches(const AABox& otherBox) const;
|
||||
bool expandedContains(const glm::vec3& point, float expansion) const;
|
||||
bool expandedIntersectsSegment(const glm::vec3& start, const glm::vec3& end, float expansion) const;
|
||||
bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const;
|
||||
bool findSpherePenetration(const glm::vec3& center, float radius, glm::vec3& penetration) const;
|
||||
bool findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius, glm::vec3& penetration) const;
|
||||
|
||||
private:
|
||||
glm::vec3 getClosestPointOnFace(const glm::vec3& point, BoxFace face) const;
|
||||
|
|
Loading…
Reference in a new issue