AABBTree* CollisionManager::getAABBTree(SceneObject* scno, int collisionBlockFlags) { SharedObjectTemplate* templateObject = scno->getObjectTemplate(); if (templateObject == NULL) return NULL; if (!(templateObject->getCollisionActionBlockFlags() & collisionBlockFlags)) return NULL; PortalLayout* portalLayout = templateObject->getPortalLayout(); MeshAppearanceTemplate* mesh = NULL; if (portalLayout != NULL) { mesh = portalLayout->getMeshAppearanceTemplate(0); } else { AppearanceTemplate* appTemplate = templateObject->getAppearanceTemplate(); if (appTemplate == NULL) return NULL; mesh = dynamic_cast<MeshAppearanceTemplate*>(appTemplate->getFirstMesh()); } if (mesh == NULL) return NULL; return mesh->getAABBTree(); }
bool CollisionManager::checkLineOfSightWorldToCell(const Vector3& rayOrigin, const Vector3& rayEnd, float distance, CellObject* cellObject) { ManagedReference<SceneObject*> building = cellObject->getParent(); if (building == NULL) return true; SharedObjectTemplate* objectTemplate = building->getObjectTemplate(); PortalLayout* portalLayout = objectTemplate->getPortalLayout(); if (portalLayout == NULL) return true; Ray ray = convertToModelSpace(rayOrigin, rayEnd, building); if (cellObject->getCellNumber() >= portalLayout->getAppearanceTemplatesSize()) return true; MeshAppearanceTemplate* app = portalLayout->getMeshAppearanceTemplate(cellObject->getCellNumber()); AABBTree* aabbTree = app->getAABBTree(); if (aabbTree == NULL) return true; float intersectionDistance; Triangle* triangle = NULL; if (aabbTree->intersects(ray, distance, intersectionDistance, triangle, true)) return false; return true; }
bool CollisionManager::checkLineOfSightInParentCell(SceneObject* object, Vector3& endPoint) { ManagedReference<SceneObject*> parent = object->getParent(); if (parent == NULL || !parent->isCellObject()) return true; CellObject* cell = cast<CellObject*>( parent.get()); SharedObjectTemplate* objectTemplate = parent->getRootParent().get()->getObjectTemplate(); PortalLayout* portalLayout = objectTemplate->getPortalLayout(); MeshAppearanceTemplate* appearanceMesh = NULL; if (portalLayout == NULL) return true; try { appearanceMesh = portalLayout->getMeshAppearanceTemplate(cell->getCellNumber()); } catch (Exception& e) { return true; } if (appearanceMesh == NULL) { //info("null appearance mesh "); return true; } AABBTree* aabbTree = appearanceMesh->getAABBTree(); if (aabbTree == NULL) return true; //switching Y<->Z, adding 0.1 to account floor Vector3 startPoint = object->getPosition(); startPoint.set(startPoint.getX(), startPoint.getY(), startPoint.getZ() + 0.1f); endPoint.set(endPoint.getX(), endPoint.getY(), endPoint.getZ() + 0.1f); Vector3 dir = endPoint - startPoint; dir.normalize(); float distance = endPoint.distanceTo(startPoint); float intersectionDistance; Ray ray(startPoint, dir); Triangle* triangle = NULL; //nothing in the middle if (aabbTree->intersects(ray, distance, intersectionDistance, triangle, true)) return false; Ray ray2(endPoint, Vector3(0, -1, 0)); //check if we are in the cell with dir (0, -1, 0) if (!aabbTree->intersects(ray2, 64000.f, intersectionDistance, triangle, true)) return false; return true; }
bool CollisionManager::checkLineOfSightInBuilding(SceneObject* object1, SceneObject* object2, SceneObject* building) { SharedObjectTemplate* objectTemplate = building->getObjectTemplate(); PortalLayout* portalLayout = objectTemplate->getPortalLayout(); if (portalLayout == NULL) return true; //we are in model space... in cells Vector3 rayOrigin = object1->getPosition(); rayOrigin.set(rayOrigin.getX(), rayOrigin.getY(), rayOrigin.getZ() + 1.f); Vector3 rayEnd = object2->getPosition(); rayEnd.set(rayEnd.getX(), rayEnd.getY(), rayEnd.getZ() + 1.f); Vector3 direction(Vector3(rayEnd - rayOrigin)); direction.normalize(); float distance = rayEnd.distanceTo(rayOrigin); float intersectionDistance; Ray ray(rayOrigin, direction); Triangle* triangle = NULL; // we check interior cells for (int i = 1; i < portalLayout->getAppearanceTemplatesSize(); ++i) { MeshAppearanceTemplate* app = portalLayout->getMeshAppearanceTemplate(i); AABBTree* aabbTree = app->getAABBTree(); if (aabbTree == NULL) continue; if (aabbTree->intersects(ray, distance, intersectionDistance, triangle, true)) return false; } return true; }