FloorMesh* TemplateManager::getFloorMesh(const String& fileName) { FloorMesh* floorMesh = floorMeshMap->get(fileName); if (floorMesh == NULL) { // read file IffStream* iffStream = openIffFile(fileName); if (iffStream != NULL) { try { floorMesh = new FloorMesh(); floorMesh->readObject(iffStream); info("parsed " + fileName); } catch (Exception& e) { info("could not parse " + fileName); delete floorMesh; floorMesh = NULL; } delete iffStream; iffStream = NULL; floorMeshMap->put(fileName, floorMesh); } } return floorMesh; //return NULL; }
Vector<float>* CollisionManager::getCellFloorCollision(float x, float y, CellObject* cellObject) { Vector<float>* collisions = NULL; ManagedReference<SceneObject*> rootObject = cellObject->getRootParent(); if (rootObject == NULL) return NULL; SharedObjectTemplate* templateObject = rootObject->getObjectTemplate(); if (templateObject == NULL) return NULL; PortalLayout* portalLayout = templateObject->getPortalLayout(); if (portalLayout == NULL) return NULL; FloorMesh* mesh = portalLayout->getFloorMesh(cellObject->getCellNumber()); if (mesh == NULL) return NULL; AABBTree* tree = mesh->getAABBTree(); if (tree == NULL) return NULL; Vector3 rayStart(x, 16384.f, y); Vector3 rayEnd(x, -16384.f, y); Vector3 norm = rayEnd - rayStart; norm.normalize(); Ray ray(rayStart, norm); SortedVector<IntersectionResult> results(3, 2); tree->intersects(ray, 16384 * 2, results); if (results.size() == 0) return NULL; collisions = new Vector<float>(results.size(), 1); for (int i = 0; i < results.size(); ++i) { float floorHeight = 16384 - results.get(i).getIntersectionDistance(); collisions->add(floorHeight); } return collisions; }
int PortalLayout::getFloorMeshID(int globalNodeID, int floorMeshToExclude) { for (int i = 0; i < cellProperties.size(); ++i) { if (i == floorMeshToExclude) continue; FloorMesh* floorMesh = getFloorMesh(i); PathNode* node = floorMesh->getGlobalNode(globalNodeID); if (node != NULL) return i; } return -1; }
void PortalLayout::connectFloorMeshGraphs() { for (int i = 0; i < cellProperties.size(); ++i) { FloorMesh* floorMesh = getFloorMesh(i); if (floorMesh == NULL) continue; PathGraph* pathGraph = floorMesh->getPathGraph(); if (pathGraph == NULL) continue; Vector<PathNode*> globalNodes = pathGraph->getGlobalNodes(); for (int j = 0; j < globalNodes.size(); ++j) { PathNode* node = globalNodes.get(j); int globalID = node->getGlobalGraphNodeID(); for (int k = 0; k < cellProperties.size(); ++k) { if (i != k) { FloorMesh* newMesh = getFloorMesh(k); if (newMesh != NULL) { PathGraph* newPathGraph = newMesh->getPathGraph(); if (newPathGraph != NULL) { Vector<PathNode*> newGlobalNodes = newPathGraph->getGlobalNodes(); for (int l = 0; l < newGlobalNodes.size(); ++l) { PathNode* newNode = newGlobalNodes.get(l); int newGlobalID = newNode->getGlobalGraphNodeID(); if (globalID == newGlobalID) node->addChild(newNode); } } } } } } } }
float CollisionManager::getWorldFloorCollision(float x, float y, Zone* zone, bool testWater) { SortedVector<ManagedReference<QuadTreeEntry*> > closeObjects; zone->getInRangeObjects(x, y, 128, &closeObjects, true); PlanetManager* planetManager = zone->getPlanetManager(); if (planetManager == NULL) return 0.f; float height = 0; TerrainManager* terrainManager = planetManager->getTerrainManager(); //need to include exclude affectors in the terrain calcs height = terrainManager->getHeight(x, y); Vector3 rayStart(x, 16384.f, y); Vector3 rayEnd(x, -16384.f, y); Triangle* triangle = NULL; if (testWater) { float waterHeight; if (terrainManager->getWaterHeight(x, y, waterHeight)) if (waterHeight > height) height = waterHeight; } float intersectionDistance; for (int i = 0; i < closeObjects.size(); ++i) { BuildingObject* building = dynamic_cast<BuildingObject*>(closeObjects.get(i).get()); if (building == NULL) continue; //building->getObjectTemplate()->get SharedObjectTemplate* templateObject = building->getObjectTemplate(); if (templateObject == NULL) continue; PortalLayout* portalLayout = templateObject->getPortalLayout(); if (portalLayout == NULL) continue; if (portalLayout->getFloorMeshNumber() == 0) continue; //find nearest entrance FloorMesh* exteriorFloorMesh = portalLayout->getFloorMesh(0); // get outside layout AABBTree* aabbTree = exteriorFloorMesh->getAABBTree(); if (aabbTree == NULL) continue; Ray ray = convertToModelSpace(rayStart, rayEnd, building); if (aabbTree->intersects(ray, 16384 * 2, intersectionDistance, triangle, true)) { float floorHeight = 16384 - intersectionDistance; if (floorHeight > height) height = floorHeight; } } return height; }
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::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::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; }