Vector<WorldCoordinates>* PathFinderManager::findPathFromCellToCell(const WorldCoordinates& pointA, const WorldCoordinates& pointB) { CellObject* ourCell = pointA.getCell(); CellObject* targetCell = pointB.getCell(); if (ourCell != targetCell) return findPathFromCellToDifferentCell(pointA, pointB); int ourCellID = ourCell->getCellNumber(); ManagedReference<BuildingObject*> building = cast<BuildingObject*>( ourCell->getParent().get().get()); SharedObjectTemplate* templateObject = building->getObjectTemplate(); if (templateObject == NULL) return NULL; PortalLayout* portalLayout = templateObject->getPortalLayout(); if (portalLayout == NULL) return NULL; FloorMesh* floorMesh1 = portalLayout->getFloorMesh(ourCellID); PathGraph* pathGraph1 = floorMesh1->getPathGraph(); Vector<WorldCoordinates>* path = new Vector<WorldCoordinates>(5, 1); path->add(pointA); // adding source //info("same cell... trying to calculate triangle path", true); Vector<Triangle*>* trianglePath = NULL; //info("searching floorMesh for cellID " + String::valueOf(ourCellID), true); int res = getFloorPath(pointA.getPoint(), pointB.getPoint(), floorMesh1, trianglePath); if (res == -1) { //points in the same triangle path->add(pointB); return path; } if (trianglePath == NULL) { // returning NULL, no path found //error("path NULL"); delete path; return findPathFromCellToDifferentCell(pointA, pointB); } else { //info("path found", true); addTriangleNodeEdges(pointA.getPoint(), pointB.getPoint(), trianglePath, path, ourCell); delete trianglePath; path->add(pointB); //adding destination return path; } return path; }
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; }
Vector<WorldCoordinates>* PathFinderManager::findPathFromCellToWorld(const WorldCoordinates& pointA, const WorldCoordinates& pointB, Zone *zone) { Vector<WorldCoordinates>* path = new Vector<WorldCoordinates>(5, 1); if (path == NULL) return NULL; path->add(pointA); CellObject* ourCell = pointA.getCell(); ManagedReference<BuildingObject*> building = cast<BuildingObject*>( ourCell->getParent().get().get()); int ourCellID = ourCell->getCellNumber(); SharedObjectTemplate* templateObject = ourCell->getParent().get()->getObjectTemplate(); if (templateObject == NULL) { delete path; return NULL; } PortalLayout* portalLayout = templateObject->getPortalLayout(); if (portalLayout == NULL) { delete path; return NULL; } FloorMesh* sourceFloorMesh = portalLayout->getFloorMesh(ourCellID); if (sourceFloorMesh == NULL) { delete path; return NULL; } PathGraph* sourcePathGraph = sourceFloorMesh->getPathGraph(); if (sourcePathGraph == NULL) { delete path; return NULL; } FloorMesh* exteriorFloorMesh = portalLayout->getFloorMesh(0); if (exteriorFloorMesh == NULL) { delete path; return NULL; } PathGraph* exteriorPathGraph = exteriorFloorMesh->getPathGraph(); if (exteriorPathGraph == NULL) { delete path; return NULL; } // we need to move world position into model space Vector3 transformedPosition = transformToModelSpace(pointB.getPoint(), building); //find exit node in our cell //PathNode* exitNode = sourcePathGraph->findNearestNode(pointA.getPoint()); TriangleNode* nearestTargetNodeTriangle = CollisionManager::getTriangle(pointA.getPoint(), sourceFloorMesh); if (nearestTargetNodeTriangle == NULL) { delete path; return NULL; } PathNode* exitNode = CollisionManager::findNearestPathNode(nearestTargetNodeTriangle, sourceFloorMesh, transformedPosition);//targetPathGraph->findNearestNode(pointB.getPoint()); if (exitNode == NULL) { delete path; return NULL; } //find exterior node PathNode* exteriorNode = exteriorPathGraph->findNearestGlobalNode(transformedPosition); if (exteriorNode == NULL) { delete path; return NULL; } //find path to the exit Vector<PathNode*>* exitPath = portalLayout->getPath(exitNode, exteriorNode); if (exitPath == NULL) { error("exitPath == NULL"); delete path; return NULL; } //find triangle path to exitNode Vector<Triangle*>* trianglePath = NULL; int res = getFloorPath(pointA.getPoint(), exitNode->getPosition(), sourceFloorMesh, trianglePath); if (res != -1 && trianglePath != NULL) addTriangleNodeEdges(pointA.getPoint(), exitNode->getPosition(), trianglePath, path, ourCell); if (trianglePath != NULL) delete trianglePath; path->add(WorldCoordinates(exitNode->getPosition(), ourCell)); //populate cell traversing for (int i = 0; i < exitPath->size(); ++i) { PathNode* pathNode = exitPath->get(i); PathGraph* pathGraph = pathNode->getPathGraph(); FloorMesh* floorMesh = pathGraph->getFloorMesh(); int cellID = floorMesh->getCellID(); if (cellID == 0) { // we are outside WorldCoordinates coord(pathNode->getPosition(), ourCell); path->add(WorldCoordinates(coord.getWorldPosition(), NULL)); } else { // we are inside the building CellObject* pathCell = building->getCell(cellID); path->add(WorldCoordinates(pathNode->getPosition(), pathCell)); } } delete exitPath; exitPath = NULL; if (path->size()) { Vector<WorldCoordinates>* newPath = findPathFromWorldToWorld(path->get(path->size()-1), pointB, zone); if (newPath) { path->addAll(*newPath); delete newPath; } } else path->add(pointB); return path; }
Vector<WorldCoordinates>* PathFinderManager::findPathFromCellToDifferentCell(const WorldCoordinates& pointA, const WorldCoordinates& pointB) { //info ("findPathFromCellToDifferentCell", true); CellObject* ourCell = pointA.getCell(); CellObject* targetCell = pointB.getCell(); int ourCellID = ourCell->getCellNumber(); int targetCellID = targetCell->getCellNumber(); ManagedReference<BuildingObject*> building1 = cast<BuildingObject*>( ourCell->getParent().get().get()); ManagedReference<BuildingObject*> building2 = cast<BuildingObject*>( targetCell->getParent().get().get()); if (building1 != building2) // TODO: implement path finding between 2 buildings return NULL; SharedObjectTemplate* templateObject = building1->getObjectTemplate(); if (templateObject == NULL) return NULL; PortalLayout* portalLayout = templateObject->getPortalLayout(); if (portalLayout == NULL) return NULL; FloorMesh* floorMesh1 = portalLayout->getFloorMesh(ourCellID); FloorMesh* floorMesh2 = portalLayout->getFloorMesh(targetCellID); if (floorMesh2->getCellID() != targetCellID) error("floorMes2 cellID != targetCellID"); //info("targetCellID:" + String::valueOf(targetCellID), true); PathGraph* pathGraph1 = floorMesh1->getPathGraph(); PathGraph* pathGraph2 = floorMesh2->getPathGraph(); Vector<WorldCoordinates>* path = new Vector<WorldCoordinates>(5, 1); path->add(pointA); // adding source //PathNode* source = pathGraph1->findNearestNode(pointA.getPoint()); TriangleNode* nearestSourceNodeTriangle = CollisionManager::getTriangle(pointA.getPoint(), floorMesh1); if (nearestSourceNodeTriangle == NULL) { delete path; return NULL; } PathNode* source = CollisionManager::findNearestPathNode(nearestSourceNodeTriangle, floorMesh1, pointB.getPoint());//targetPathGraph->findNearestNode(pointB.getPoint()); if (source == NULL) { delete path; return NULL; } //PathNode* target = pathGraph2->findNearestNode(pointB.getPoint()); TriangleNode* nearestTargetNodeTriangle = CollisionManager::getTriangle(pointB.getPoint(), floorMesh2); if (nearestTargetNodeTriangle == NULL) { delete path; return NULL; } PathNode* target = CollisionManager::findNearestPathNode(nearestTargetNodeTriangle, floorMesh2, pointB.getPoint());//targetPathGraph->findNearestNode(pointB.getPoint()); if (target == NULL) { delete path; return NULL; } Vector<PathNode*>* nodes = portalLayout->getPath(source, target); if (nodes == NULL) { StringBuffer str; str << "Could not find path from node: " << source->getID() << " to node: " << target->getID() << " in building: " << templateObject->getFullTemplateString(); log(str.toString()); delete path; return NULL; } // FIXME (dannuic): Sometimes nodes only have one entry.... why? if (nodes->size() == 1) { error("Only one node"); delete path; return NULL; } // path from our position to path node Vector<Triangle*>* trianglePath = NULL; int res = getFloorPath(pointA.getPoint(), nodes->get(1)->getPosition(), floorMesh1, trianglePath); if (res != -1 && trianglePath != NULL) addTriangleNodeEdges(pointA.getPoint(), nodes->get(1)->getPosition(), trianglePath, path, ourCell); if (trianglePath != NULL) { delete trianglePath; trianglePath = NULL; } path->add(WorldCoordinates(source->getPosition(), ourCell)); //traversing cells for (int i = 1; i < nodes->size(); ++i) { PathNode* pathNode = nodes->get(i); PathGraph* pathGraph = pathNode->getPathGraph(); FloorMesh* floorMesh = pathGraph->getFloorMesh(); int cellID = floorMesh->getCellID(); if (cellID == 0) { //info("cellID == 0", true); WorldCoordinates coord(pathNode->getPosition(), ourCell); path->add(WorldCoordinates(coord.getWorldPosition(), NULL)); } else { CellObject* pathCell = building1->getCell(cellID); WorldCoordinates coord(pathNode->getPosition(), pathCell); path->add(coord); //info("cellID:" + String::valueOf(cellID), true); if (i == nodes->size() - 1) { if (pathNode != target) { StringBuffer msg; msg << "pathNode != target pathNode: " << pathNode->getID() << " target:" << target->getID(); error(msg.toString()); } if (pathCell != targetCell) { error("final cell not target cell"); } } } } delete nodes; nodes = NULL; // path from cell entrance to destination point trianglePath = NULL; res = getFloorPath(path->get(path->size() - 1).getPoint(), pointB.getPoint(), floorMesh2, trianglePath); if (res != -1 && trianglePath != NULL) addTriangleNodeEdges(path->get(path->size() - 1).getPoint(), pointB.getPoint(), trianglePath, path, targetCell); if (trianglePath != NULL) delete trianglePath; path->add(pointB); return path; }
Vector<WorldCoordinates>* PathFinderManager::findPathFromWorldToCell(const WorldCoordinates& pointA, const WorldCoordinates& pointB, Zone *zone) { CellObject* targetCell = pointB.getCell(); if (targetCell == NULL) return NULL; ManagedReference<BuildingObject*> building = dynamic_cast<BuildingObject*>(targetCell->getParent().get().get()); if (building == NULL) { error("building == NULL in PathFinderManager::findPathFromWorldToCell"); return NULL; } SharedObjectTemplate* templateObject = building->getObjectTemplate(); if (templateObject == NULL) return NULL; PortalLayout* portalLayout = templateObject->getPortalLayout(); if (portalLayout == NULL) return NULL; //find nearest entrance FloorMesh* exteriorFloorMesh = portalLayout->getFloorMesh(0); // get outside layout if (exteriorFloorMesh == NULL) return NULL; PathGraph* exteriorPathGraph = exteriorFloorMesh->getPathGraph(); FloorMesh* targetFloorMesh = portalLayout->getFloorMesh(targetCell->getCellNumber()); PathGraph* targetPathGraph = targetFloorMesh->getPathGraph(); Vector<WorldCoordinates>* path = new Vector<WorldCoordinates>(5, 1); path->add(pointA); Vector3 transformedPosition = transformToModelSpace(pointA.getPoint(), building); PathNode* nearestEntranceNode = exteriorPathGraph->findNearestNode(transformedPosition); if (nearestEntranceNode == NULL) { error("NULL entrance node for building " + templateObject->getFullTemplateString()); delete path; return NULL; } //PathNode* nearestTargetNode = targetPathGraph->findNearestNode(pointB.getPoint()); TriangleNode* nearestTargetNodeTriangle = CollisionManager::getTriangle(pointB.getPoint(), targetFloorMesh); if (nearestTargetNodeTriangle == NULL) { delete path; return NULL; } PathNode* nearestTargetNode = CollisionManager::findNearestPathNode(nearestTargetNodeTriangle, targetFloorMesh, pointB.getPoint());//targetPathGraph->findNearestNode(pointB.getPoint()); if (nearestTargetNode == NULL) { delete path; return NULL; } /*if (nearestEntranceNode == nearestTargetNode) info("nearestEntranceNode == nearestTargetNode", true);*/ //find graph from outside to appropriate cell Vector<PathNode*>* pathToCell = portalLayout->getPath(nearestEntranceNode, nearestTargetNode); if (pathToCell == NULL) { error("pathToCell = portalLayout->getPath(nearestEntranceNode, nearestTargetNode); == NULL"); delete path; return NULL; } for (int i = 0; i < pathToCell->size(); ++i) { PathNode* pathNode = pathToCell->get(i); PathGraph* pathGraph = pathNode->getPathGraph(); FloorMesh* floorMesh = pathGraph->getFloorMesh(); int cellID = floorMesh->getCellID(); //info("cellID:" + String::valueOf(cellID), true); if (cellID == 0) { // we are still outside WorldCoordinates coord(pathNode->getPosition(), targetCell); path->add(WorldCoordinates(coord.getWorldPosition(), NULL)); } else { // we are inside the building CellObject* pathCell = building->getCell(cellID); path->add(WorldCoordinates(pathNode->getPosition(), pathCell)); if (i == pathToCell->size() - 1) if (pathCell != targetCell) { error("final cell not target cell"); } } } delete pathToCell; pathToCell = NULL; // path from cell path node to destination point Vector<Triangle*>* trianglePath = NULL; int res = getFloorPath(path->get(path->size() - 1).getPoint(), pointB.getPoint(), targetFloorMesh, trianglePath); if (res != -1 && trianglePath != NULL) addTriangleNodeEdges(path->get(path->size() - 1).getPoint(), pointB.getPoint(), trianglePath, path, targetCell); if (trianglePath != NULL) delete trianglePath; path->add(pointB); return path; }