Ogre::AxisAlignedBox OgreDetourTileCache::getWorldSpaceBounds() { Ogre::AxisAlignedBox result; result.setMinimum(m_cfg.bmin[0], m_cfg.bmin[1], m_cfg.bmin[2]); result.setMaximum(m_cfg.bmax[0], m_cfg.bmax[1], m_cfg.bmax[2]); return result; }
void OgreDetourTileCache::buildTiles(InputGeom *inputGeom, const Ogre::AxisAlignedBox *areaToUpdate) { // Use bounding box from inputgeom if no area was explicitly specified Ogre::AxisAlignedBox updateArea; if(!areaToUpdate) updateArea = inputGeom->getBoundingBox(); else updateArea = *areaToUpdate; // Reduce bounding area a little with one cell in size, to be sure that if it was already tile-aligned, we don't select an extra tile updateArea.setMinimum( updateArea.getMinimum() + Ogre::Vector3(m_cellSize, 0, m_cellSize) ); updateArea.setMaximum( updateArea.getMaximum() - Ogre::Vector3(m_cellSize, 0, m_cellSize) ); // Select tiles to build or rebuild (builds a tile-aligned BB) TileSelection selection = getTileSelection(updateArea); // Debug drawing of bounding area that is updated // Remove previous debug drawn bounding box of rebuilt area if(mDebugRebuiltBB) { mDebugRebuiltBB->detachFromParent(); m_recast->m_pSceneMgr->destroyManualObject(mDebugRebuiltBB); mDebugRebuiltBB = NULL; } if(DEBUG_DRAW_REBUILT_BB) mDebugRebuiltBB = InputGeom::drawBoundingBox(selection.bounds, m_recast->m_pSceneMgr); int tilesToBuildX = (selection.maxTx - selection.minTx)+1; // Tile ranges are inclusive int tilesToBuildY = (selection.maxTy - selection.minTy)+1; if(tilesToBuildX * tilesToBuildY > 5) Ogre::LogManager::getSingletonPtr()->logMessage("Building "+Ogre::StringConverter::toString(tilesToBuildX)+" x "+Ogre::StringConverter::toString(tilesToBuildY)+" navmesh tiles."); // Build tiles for (int ty = selection.minTy; ty <= selection.maxTy; ty++) { for (int tx = selection.minTx; tx <= selection.maxTx; tx++) { buildTile(tx, ty, inputGeom); } } }
Ogre::AxisAlignedBox OgreDetourTileCache::getTileBounds(int tx, int ty) { const float* bmin = m_recast->m_cfg.bmin; const float ts = getTileSize(); Ogre::AxisAlignedBox result; result.setMinimum( bmin[0] + tx * ts, bmin[1], bmin[2] + ty * ts ); result.setMaximum( bmin[0] + (tx+1) * ts, m_recast->m_cfg.bmax[1], bmin[2] + (ty+1) * ts ); return result; }
bool ZoneProcessor::processNode(const TiXmlElement* zonesElem, const Ogre::String& resourceGroup, bool loadGameObjects) { if (zonesElem == NULL) { return false; // no zones } for (const TiXmlNode* cur = zonesElem->FirstChild(); cur != NULL; cur = cur->NextSibling()) { if (cur->Type() == TiXmlNode::ELEMENT && hasNodeName(cur, "zone")) { const TiXmlElement* curZoneElem = cur->ToElement(); if (hasAttribute(curZoneElem, "name")) { Ogre::String name = getAttributeValueAsStdString(curZoneElem, "name"); Zone* zone = NULL; if (name == "default") { zone = ZoneManager::getSingleton().getDefaultZone(); } else { // get the zone with that name or create one zone = ZoneManager::getSingleton().getZone(name); if (!zone) { zone = ZoneManager::getSingleton().createZone(name, false); } // multiple areas for (const TiXmlNode* curArea = cur->FirstChild(); curArea != NULL; curArea = curArea->NextSibling()) { if (curArea->Type() == TiXmlNode::ELEMENT && hasNodeName(curArea, "area")) { const TiXmlElement *curAreaElem = curArea->ToElement(); if (hasAttribute(curAreaElem, "type")) { // type Ogre::String type; type = getAttributeValueAsStdString(curAreaElem, "type"); // add or subtract? bool subtract = false; if (hasAttribute(curAreaElem, "subtract")) { subtract = getAttributeValueAsBool(curAreaElem, "subtract"); } // position Vector3 position = Vector3::ZERO; const TiXmlElement* positionElem = getChildNamed(curAreaElem, "position"); if (positionElem) { position = getValueAsVector3(positionElem); } //scale, rotation, offset Vector3 scale = Vector3::UNIT_SCALE; const TiXmlElement* scaleElem = getChildNamed(curAreaElem, "scale"); if (!scaleElem) { scaleElem = getChildNamed(curAreaElem, "size"); } if (scaleElem) { scale = getValueAsVector3(scaleElem); } Vector3 offset = Vector3::ZERO; const TiXmlElement* offsetElem = getChildNamed(curAreaElem, "offset"); if (offsetElem) { offset = getValueAsVector3(offsetElem); } Quaternion rotation = Quaternion::IDENTITY; const TiXmlElement* rotationElem = getChildNamed(curAreaElem, "rotation"); if (rotationElem) { rotation = getValueAsQuaternion(rotationElem); } //transition distance Real transitionDistance = 0; const TiXmlElement* transitionElem = getChildNamed(curAreaElem, "transition_distance"); if (transitionElem) { transitionDistance = getValueAsReal(transitionElem); } if (type == "mesh") { Ogre::String meshName; if (hasAttribute(curAreaElem, "meshfile")) { meshName = getAttributeValueAsStdString(curAreaElem, "meshfile"); if (subtract) { ZoneManager::getSingleton().subtractMeshAreaFromZone(name, meshName, GT_CONVEXHULL, position, scale, offset, rotation, transitionDistance, QUERYFLAG_PLAYER); } else { ZoneManager::getSingleton().addMeshAreaToZone(name, meshName, GT_CONVEXHULL, position, scale, offset, rotation, transitionDistance, QUERYFLAG_PLAYER); } } else { LOG_ERROR(Logger::SCRIPT, "an <area> element with type=\"mesh\" must have attribute 'meshfile'"); } } else { GeometryType geom = GT_NONE; if (type == "sphere") { geom = GT_SPHERE; } else if (type == "box") { geom = GT_BOX; } else if (type == "ellipsoid") { geom = GT_ELLIPSOID; } else if (type == "pyramid") { geom = GT_PYRAMID; } else if (type == "capsule") { geom = GT_CAPSULE; } else { LOG_ERROR(Logger::SCRIPT, "Unknown area type '" + type + "' !"); } if ( geom != GT_NONE) { Ogre::AxisAlignedBox aabb; aabb.setMinimum( - scale / 2.0f); aabb.setMaximum( + scale / 2.0f); if (subtract) ZoneManager::getSingleton().subtractAreaFromZone(name, aabb, geom, position, offset, rotation, transitionDistance, QUERYFLAG_PLAYER); else ZoneManager::getSingleton().addAreaToZone(name, aabb, geom, position, offset, rotation, transitionDistance, QUERYFLAG_PLAYER); } } } else { LOG_ERROR(Logger::SCRIPT, "<area> elemt must have attribute 'type'"); } } } } if (zone) { for (const TiXmlNode* cur = curZoneElem->FirstChild(); cur != NULL; cur = cur->NextSibling()) { if (cur->Type() == TiXmlNode::ELEMENT) { const TiXmlElement* curElem = cur->ToElement(); if (hasNodeName(curElem, "light")) { Ogre::String name = getAttributeValueAsStdString(curElem, "name"); zone->addLight(ActorManager::getSingleton().getActor(name)); } else if (hasNodeName(curElem, "sound")) { Ogre::String name = getAttributeValueAsStdString(curElem, "name"); zone->addSound(name); } else if (hasNodeName(curElem, "trigger")) { Ogre::String classname = getAttributeValueAsStdString(curElem, "classname"); Ogre::String name = getAttributeValueAsStdString(curElem, "name"); Trigger* trigger = ScriptSubsystem::getSingleton().getTriggerFactory() ->createTrigger(classname, name); // add trigger properties for (const TiXmlNode* curProperty = cur->FirstChild(); curProperty != NULL; curProperty = curProperty->NextSibling()) { if (hasNodeName(curProperty, "property")) { PropertyEntry propEntry = processProperty(curProperty->ToElement()); if (propEntry.first != "") { trigger->setProperty(propEntry.first, propEntry.second); } } } zone->addTrigger(trigger); } else if (hasNodeName(curElem, "eaxpreset")) { Ogre::String name = getAttributeValueAsStdString(curElem, "name"); zone->setEaxPreset(name); } } } } else { LOG_ERROR(Logger::SCRIPT, "Zone named '"+name+"' could not be processes."); } } else { LOG_ERROR(Logger::SCRIPT, "<zone> element must have attribute 'name'."); } } } ZoneManager::getSingleton().update(); return true; }