void GlassLayer::draw(Graphics* const TheGraphics, const Pnt2f& TopLeft, const Pnt2f& BottomRight, const Real32 Opacity) const { Pnt2f IntermediatePosition; Vec3f Bounds(BottomRight- TopLeft); //Setup the Blending equations properly glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); glBegin(GL_TRIANGLE_FAN); glColor4f(getEdgeColor().red(),getEdgeColor().green(),getEdgeColor().blue(),getEdgeColor().alpha() * Opacity); glVertex2f(getStartPosition().x(), getEndPosition().y()); glColor4f(getCenterColor().red(),getCenterColor().green(),getCenterColor().blue(),getCenterColor().alpha() * Opacity); glVertex2fv(getStartPosition().getValues()); for(UInt32 i(0) ; i<_Segments.size(); ++i) { IntermediatePosition.setValues(_Segments[i].x() * Bounds.x(),_Segments[i].y() * Bounds.y()); glVertex2fv(IntermediatePosition.getValues()); } glVertex2fv(getEndPosition().getValues()); glEnd(); glDisable(GL_BLEND); }
void Needle::setTransformFromEndEffectorBoxConstrained(const Vector3d& new_ee_pos, const Matrix3d& new_ee_rot, Box* box) { Vector3d old_ee_pos; Matrix3d old_ee_rot; getEndEffectorTransform(old_ee_pos, old_ee_rot); Vector3d old_proj = (old_ee_pos - position); old_proj.normalize(); Vector3d proj = (new_ee_pos-position).dot(rotation.col(0))*rotation.col(0) + (new_ee_pos-position).dot(rotation.col(2))*rotation.col(2); proj.normalize(); glColor3f(0.8,0.8,0); drawArrow(position, 20*proj); glColor3f(0.8,0,0); drawArrow(position, 20*old_proj); Vector3d normal = proj.cross(old_proj); normal.normalize(); double angle = angle_between(proj, old_proj)*180.0/M_PI; if (angle > 90.0) { angle = 0.0; //TODO return; } else { double sign = ((normal - rotation.col(1)).squaredNorm() < 1e-5) ? -1 : 1; angle = sign*min(angle_between(proj, old_proj)*180.0/M_PI, 5.0); } if (!isnan(angle) && abs(angle)>1e-5 && angle>0.0) { //TODO for now, only allows forward movement of needle through box rotateAboutAxis(angle); if(isThreadAttached()) { thread->updateConstrainedTransform(constraint_ind, getEndPosition(), getEndRotation()); } } if (isThreadAttached()) { Vector3d direction; if (!box->isThreadAttached() && (sphereBoxDistance(getEndPosition(), getThicknessRadius(), box->getPosition(), box->getHalfLength(), direction) < 0)) { cout << "thread gets into the box" << endl; //box->attach(getThread()); box->attachThreadIn(getThread(), getEndPosition(), getEndRotation()); } if (box->isThreadAttached() && !boxCollision(box->getPosition(), box->getHalfLength())) { cout << "thread gets out of the box" << endl; box->attachThreadOut(getThread(), getEndPosition(), getEndRotation()); } } }
void Needle::setTransformFromEndEffector(const Vector3d& ee_pos, const Matrix3d& ee_rot) { vector<Box*> boxes; world->getObjects<Box>(boxes); Box* box = NULL; for (int i = 0; i < boxes.size(); i++) { if (boxes[i]->isNeedleAttached() && (boxes[i]->getNeedle() == this)) { box = boxes[i]; break; } } if (box == NULL) { setTransform(ee_pos + ee_rot*rotation_offset*position_offset, ee_rot * rotation_offset); if(isThreadAttached()) { vector<int> constraint_inds; thread->getConstrainedVerticesNums(constraint_inds); if (constraint_inds.size() != 3) { cout << "adding constraint" << endl; thread->addConstraint(10); //thread->updateRotationOffset(1, (Matrix3d) Angle; } Vector3d position_diff = thread->rotationAtConstraint(1).transpose() * (thread->positionAtConstraint(1) - thread->positionAtConstraint(0)); position_diff = (thread->positionAtConstraint(1) - thread->positionAtConstraint(0)); //Matrix3d rotation_diff = thread->rotationAtConstraint(0).transpose() * thread->rotationAtConstraint(1); Matrix3d rotation_diff = thread->rotationAtConstraint(0).transpose() * thread->rotationAtConstraint(1); assert(constraint_ind == 0); //thread->updateConstrainedTransform(constraint_ind, getEndPosition(), getEndRotation()); thread->updateConstrainedTransform(0, getEndPosition(), getEndRotation()); Matrix3d ee_rot = thread->rotationAtConstraint(0) * rotation_diff; //ee_rot = (Matrix3d) AngleAxisd(ee_rot); // ee_rot.col(1) = ee_rot.col(2).cross(ee_rot.col(0)); // ee_rot.col(2) = ee_rot.col(0).cross(ee_rot.col(1)); // ee_rot.col(0).normalize(); // ee_rot.col(1).normalize(); // ee_rot.col(2).normalize(); //position_diff = Vector3d(-10,0,0); //thread->updateConstrainedTransform(1, ee_rot*position_diff + getEndPosition(), ee_rot); thread->updateConstrainedTransform(1, position_diff + getEndPosition(), ee_rot); //thread->rotationAtConstraint(1); //thread->updateConstrainedRawTransform(1, position_diff + getEndPosition(), ee_rot, ee_rot); //thread->updateConstrainedRawTransform(1, ee_rot*position_diff + getEndPosition(), ee_rot, ee_rot); //thread->minimize_energy(); } } else { setTransformFromEndEffectorBoxConstrained(ee_pos, ee_rot, box); } checkBoxAttach(); }
bool PathFinder::calculate(float destX, float destY, float destZ, bool forceDest) { Vector3 oldDest = getEndPosition(); Vector3 dest(destX, destY, destZ); setEndPosition(dest); float x, y, z; m_sourceUnit->GetPosition(x, y, z); Vector3 start(x, y, z); setStartPosition(start); m_forceDestination = forceDest; DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ PathFinder::calculate() for %u \n", m_sourceUnit->GetGUIDLow()); // make sure navMesh works - we can run on map w/o mmap // check if the start and end point have a .mmtile loaded (can we pass via not loaded tile on the way?) if (!m_navMesh || !m_navMeshQuery || m_sourceUnit->hasUnitState(UNIT_STAT_IGNORE_PATHFINDING) || !HaveTile(start) || !HaveTile(dest) || m_sourceUnit->m_movementInfo.HasMovementFlag(MOVEFLAG_TAXI)) //for transport { BuildShortcut(); m_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); return true; } updateFilter(); BuildPolyPath(start, dest); return true; }
void Needle::rotateAboutAxis(double degrees) { setTransform(position, AngleAxisd(degrees * M_PI/180.0, rotation.col(1)) * rotation); if(isThreadAttached()) { thread->updateConstrainedTransform(constraint_ind, getEndPosition(), getEndRotation()); } }
void PathInfo::Build() { float x, y, z; // set start and a default next position m_sourceObject->GetPosition(x, y, z); setStartPosition(x, y, z); setNextPosition(x, y, z); // get nav mesh m_navMesh = m_sourceObject->GetMap()->GetNavMesh(); if(!m_navMesh) { // if there is no navmesh, just move to destination shortcut(); return; } float extents[3] = {2.0f, 4.0f, 2.0f}; // defines bounds of box for search area dtQueryFilter filter = dtQueryFilter(); // use general filter so we know if we are near navmesh // get start and end positions getStartPosition(x, y, z); float startPos[3] = {y, z, x}; getEndPosition(x, y, z); float endPos[3] = {y, z, x}; // find start and end poly dtPolyRef startPoly = m_navMesh->findNearestPoly(startPos, extents, &filter, 0); dtPolyRef endPoly = m_navMesh->findNearestPoly(endPos, extents, &filter, 0); Build(startPoly, endPoly); }
bool PathFinder::calculate(float destX, float destY, float destZ, bool forceDest) { Vector3 oldDest = getEndPosition(); Vector3 dest(destX, destY, destZ); setEndPosition(dest); float x, y, z; m_sourceUnit->GetPosition(x, y, z); Vector3 start(x, y, z); setStartPosition(start); m_forceDestination = forceDest; DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ PathFinder::calculate() for %u \n", m_sourceUnit->GetGUIDLow()); // make sure navMesh works - we can run on map w/o mmap // check if the start and end point have a .mmtile loaded (can we pass via not loaded tile on the way?) if (!m_navMesh || !m_navMeshQuery || m_sourceUnit->hasUnitState(UNIT_STAT_IGNORE_PATHFINDING) || !HaveTile(start) || !HaveTile(dest) || (m_sourceUnit->GetTypeId() == TYPEID_UNIT && ((Creature*)m_sourceUnit)->IsLevitating())) { BuildShortcut(); m_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); return true; } updateFilter(); { ReadGuard Guard(MMAP::MMapFactory::createOrGetMMapManager()->GetLock(m_sourceUnit->GetMapId())); BuildPolyPath(start, dest); } return true; }
void PathInfo::shortcut() { clear(); float x, y, z; getEndPosition(x, y, z); setNextPosition(x, y, z); m_type = PATHFIND_SHORTCUT; }
bool PathInfo::Update(const float destX, const float destY, const float destZ, bool useStraightPath) { PathNode newDest(destX, destY, m_sourceUnit->GetMap()->GetHeight(destX,destY,destZ,100.0f)); PathNode oldDest = getEndPosition(); setEndPosition(newDest); float x, y, z; m_sourceUnit->GetPosition(x, y, z); PathNode newStart(x, y, m_sourceUnit->GetMap()->GetHeight(x,y,z,100.0f)); PathNode oldStart = getStartPosition(); setStartPosition(newStart); m_useStraightPath = useStraightPath; PATH_DEBUG("++ PathInfo::Update() for %u \n", m_sourceUnit->GetGUID()); // make sure navMesh works - we can run on map w/o mmap if (!m_navMesh || !m_navMeshQuery) { BuildShortcut(); m_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); return true; } float dist = m_sourceUnit->GetObjectBoundingRadius(); bool oldDestInRange = inRange(oldDest, newDest, dist, dist); // this can happen only if caller did a bad job calculating the need for path update if (oldDestInRange && inRange(newStart, oldStart, dist, dist)) { setEndPosition(oldDest); setStartPosition(oldStart); return false; } // check if destination moved - if not we can optimize something here // we are following old, precalculated path? if (oldDestInRange && m_pathPoints.size() > 2) { // our target is not moving - we just coming closer // we are moving on precalculated path - enjoy the ride PATH_DEBUG("++ PathInfo::Update:: precalculated path\n"); m_pathPoints.crop(1, 0); setNextPosition(m_pathPoints[1]); return false; } else { // target moved, so we need to update the poly path BuildPolyPath(newStart, newDest); return true; } }
void MissionObjectiveImplementation::awardReward() { Vector<ManagedReference<CreatureObject*> > players; PlayMusicMessage* pmm = new PlayMusicMessage("sound/music_mission_complete.snd"); Vector3 missionEndPoint = getEndPosition(); ManagedReference<CreatureObject*> owner = getPlayerOwner(); ManagedReference<GroupObject*> group = owner->getGroup(); if (group != NULL) { Locker lockerGroup(group, _this.get()); for(int i = 0; i < group->getGroupSize(); i++) { Reference<CreatureObject*> groupMember = group->getGroupMember(i)->isPlayerCreature() ? (group->getGroupMember(i)).castTo<CreatureObject*>() : NULL; if (groupMember != NULL) { //Play mission complete sound. groupMember->sendMessage(pmm->clone()); if (groupMember->getWorldPosition().distanceTo(missionEndPoint) < 128) { players.add(groupMember); } } } delete pmm; } else { //Play mission complete sound. owner->sendMessage(pmm); players.add(owner); } if (players.size() == 0) { players.add(owner); } ManagedReference<MissionObject* > mission = this->mission.get(); int dividedReward = mission->getRewardCredits() / players.size(); for (int i = 0; i < players.size(); i++) { ManagedReference<CreatureObject*> player = players.get(i); StringIdChatParameter stringId("mission/mission_generic", "success_w_amount"); stringId.setDI(dividedReward); player->sendSystemMessage(stringId); Locker lockerPl(player, _this.get()); player->addBankCredits(dividedReward, true); } StatisticsManager::instance()->completeMission(mission->getTypeCRC() ,mission->getRewardCredits()); }
bool PathFinderMovementGenerator::calculate(float destX, float destY, float destZ, bool forceDest) { if (!SkyFire::IsValidMapCoord(destX, destY, destZ) || !SkyFire::IsValidMapCoord(m_sourceUnit->GetPositionX(), m_sourceUnit->GetPositionY(), m_sourceUnit->GetPositionZ())) return false; Vector3 oldDest = getEndPosition(); Vector3 dest(destX, destY, destZ); setEndPosition(dest); float x, y, z; m_sourceUnit->GetPosition(x, y, z); Vector3 start(x, y, z); setStartPosition(start); m_forceDestination = forceDest; sLog->outDebug(LOG_FILTER_MAPS, "++ PathFinderMovementGenerator::calculate() for %u \n", m_sourceUnit->GetGUIDLow()); // make sure navMesh works - we can run on map w/o mmap // check if the start and end point have a .mmtile loaded (can we pass via not loaded tile on the way?) if (!m_navMesh || !m_navMeshQuery || m_sourceUnit->HasUnitState(UNIT_STATE_IGNORE_PATHFINDING) || !HaveTile(start) || !HaveTile(dest)) { BuildShortcut(); m_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); return true; } updateFilter(); // check if destination moved - if not we can optimize something here // we are following old, precalculated path? float dist = m_sourceUnit->GetObjectSize(); if (inRange(oldDest, dest, dist, dist) && m_pathPoints.size() > 2) { // our target is not moving - we just coming closer // we are moving on precalculated path - enjoy the ride sLog->outStaticDebug("++ PathFinderMovementGenerator::calculate:: precalculated path\n"); m_pathPoints.erase(m_pathPoints.begin()); return false; } else { // target moved, so we need to update the poly path m_navMeshLock->acquire_read(); BuildPolyPath(start, dest); m_navMeshLock->release(); return true; } }
bool PathInfo::Update(const float destX, const float destY, const float destZ, bool useStraightPath, bool forceDest) { PathNode newDest(destX, destY, destZ); PathNode oldDest = getEndPosition(); setEndPosition(newDest); float x, y, z; m_sourceUnit->GetPosition(x, y, z); PathNode newStart(x, y, z); PathNode oldStart = getStartPosition(); setStartPosition(newStart); m_useStraightPath = useStraightPath; m_forceDestination = forceDest; DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ PathInfo::Update() for %u \n", m_sourceUnit->GetGUID()); // make sure navMesh works - we can run on map w/o mmap if (!m_navMesh || !m_navMeshQuery || !HaveTiles(newDest) || m_sourceUnit->hasUnitState(UNIT_STAT_IGNORE_PATHFINDING)) { BuildShortcut(); m_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); return true; } updateFilter(); // check if destination moved - if not we can optimize something here // we are following old, precalculated path? float dist = m_sourceUnit->GetObjectBoundingRadius(); if (inRange(oldDest, newDest, dist, dist) && m_pathPoints.size() > 2) { // our target is not moving - we just coming closer // we are moving on precalculated path - enjoy the ride DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ PathInfo::Update:: precalculated path\n"); m_pathPoints.crop(1, 0); setNextPosition(m_pathPoints[1]); return false; } else { // target moved, so we need to update the poly path BuildPolyPath(newStart, newDest); return true; } }
bool PathFinder::calculate(float destX, float destY, float destZ, bool forceDest) { Vector3 oldDest = getEndPosition(); Vector3 dest(destX, destY, destZ); setEndPosition(dest); float x, y, z; m_sourceUnit->GetPosition(x, y, z); Vector3 start(x, y, z); setStartPosition(start); m_forceDestination = forceDest; DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ PathFinder::calculate() for %u \n", m_sourceUnit->GetGUIDLow()); // make sure navMesh works - we can run on map w/o mmap // check if the start and end point have a .mmtile loaded (can we pass via not loaded tile on the way?) if (!m_navMesh || !m_navMeshQuery || m_sourceUnit->hasUnitState(UNIT_STAT_IGNORE_PATHFINDING) || !HaveTile(start) || !HaveTile(dest)) { BuildShortcut(); m_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); return true; } updateFilter(); // check if destination moved - if not we can optimize something here // we are following old, precalculated path? float dist = m_sourceUnit->GetObjectBoundingRadius(); if (inRange(oldDest, dest, dist, dist) && m_pathPoints.size() > 2) { // our target is not moving - we just coming closer // we are moving on precalculated path - enjoy the ride DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ PathFinder::calculate:: precalculated path\n"); m_pathPoints.erase(m_pathPoints.begin()); return false; } else { // target moved, so we need to update the poly path ReadGuard Guard(MMAP::MMapFactory::createOrGetMMapManager()->GetLock(m_sourceUnit->GetMapId())); BuildPolyPath(start, dest); return true; } }
bool PathInfo::Update(float destX, float destY, float destZ, bool forceDest) { float x, y, z; m_sourceUnit->GetPosition(x, y, z); if (!Oregon::IsValidMapCoord(destX, destY, destZ) || !Oregon::IsValidMapCoord(x, y, z)) { sLog.outMMap("PathInfo::Update() called with invalid map coords, destX: %f destY: %f destZ: %f x: %f y: %f z: %f for creature %u", destX, destY, destZ, x, y, z, m_sourceUnit->GetGUIDLow()); m_type = PATHFIND_NOPATH; return false; } Vector3 oldDest = getEndPosition(); Vector3 newDest(destX, destY, destZ); setEndPosition(newDest); Vector3 newStart(x, y, z); setStartPosition(newStart); m_forceDestination = forceDest; sLog.outMMap("PathInfo::Update() for %u \n", m_sourceUnit->GetGUIDLow()); // make sure navMesh works - we can run on map w/o mmap // check if the start and end point have a .mmtile loaded (can we pass via not loaded tile on the way?) if (!m_navMesh || !m_navMeshQuery || m_sourceUnit->HasUnitState(UNIT_STATE_IGNORE_PATHFINDING) || !HaveTile(newStart) || !HaveTile(newDest)) { BuildShortcut(); m_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); return true; } updateFilter(); BuildPolyPath(newStart, newDest); return true; }
void GlassLayer::updateSegments(void) { //Calculate a Cubic Hermite spline _Segments.clear(); Vec2f Pos; Real32 t, t_sqr, t_cub; for(UInt32 i(1) ; i<getSegments() ; ++i) { t = static_cast<Real32>(i)/static_cast<Real32>(getSegments()); t_sqr = t*t; t_cub = t_sqr*t; Pos = ( 2.0f * t_cub - 3.0f*t_sqr + 1.0f) * getStartPosition().subZero() + ( t_cub - 2.0f*t_sqr + t) * getStartDirection() + (-2.0f * t_cub + 3.0f*t_sqr ) * getEndPosition().subZero() + ( t_cub - t_sqr ) * getEndDirection(); _Segments.push_back(Pos); } }
void PathInfo::Update(const float destX, const float destY, const float destZ) { float x, y, z; // update start and end m_sourceObject->GetPosition(x, y, z); setStartPosition(x, y, z); setEndPosition(destX, destY, destZ); // make sure navMesh works if(!m_navMesh) { m_sourceObject->GetPosition(x, y, z); m_navMesh = m_sourceObject->GetMap()->GetNavMesh(); if(!m_navMesh) { // can't pathfind if navmesh doesn't exist shortcut(); return; } } if(!m_pathPolyRefs) { // path was not built before, most likely because navmesh wasn't working // start from scratch, then return Build(); return; } // should be safe to update path now bool startOffPath = false; bool endOffPath = false; // find start and end poly // navMesh.findNearestPoly is expensive, so first we check just the current path getStartPosition(x, y, z); dtPolyRef startPoly = getPathPolyByPosition(x, y, z); getEndPosition(x, y, z); dtPolyRef endPoly = getPathPolyByPosition(x, y, z); if(startPoly != 0 && endPoly != 0) trim(startPoly, endPoly); else { // start or end is off the path, need to find the polygon float extents[3] = {2.f, 4.f, 2.f}; // bounds of poly search area dtQueryFilter filter = dtQueryFilter(); // filter for poly search if(!startPoly) { getStartPosition(x, y, z); float startPos[3] = {y, z, x}; startOffPath = true; startPoly = m_navMesh->findNearestPoly(startPos, extents, &filter, 0); } if(!endPoly) { getEndPosition(x, y, z); float endPos[3] = {y, z, x}; endOffPath = true; endPoly = m_navMesh->findNearestPoly(endPos, extents, &filter, 0); } if(startPoly == 0 || endPoly == 0) { // source or dest not near navmesh polygons: // flying, falling, swimming, or navmesh has a hole // ignore obstacles/terrain is better than giving up // PATHFIND TODO: prevent walking/swimming mobs from flying into the air shortcut(); return; } } if(startPoly == endPoly) { // start and end are on same polygon // just need to move in straight line // PATHFIND TODO: prevent walking/swimming mobs from flying into the air clear(); m_pathPolyRefs = new dtPolyRef[1]; m_pathPolyRefs[0] = startPoly; m_length = 1; getEndPosition(x, y, z); setNextPosition(x, y, z); m_type = PathType(m_type | PATHFIND_NORMAL); return; } if(startOffPath) { bool adjacent = false; int i; for(i = 0; i < DT_VERTS_PER_POLYGON; ++i) if(startPoly == m_navMesh->getPolyByRef(m_pathPolyRefs[0])->neis[i]) { adjacent = true; break; } if(adjacent) { // startPoly is adjacent to the path, we can add it to the start of the path // 50th poly will fall off of path, shouldn't be an issue because most paths aren't that long m_length = m_length < MAX_PATH_LENGTH ? m_length + 1 : m_length; dtPolyRef* temp = new dtPolyRef[m_length]; temp[0] = startPoly; for(i = 1; i < m_length; ++i) temp[i] = m_pathPolyRefs[i - 1]; delete [] m_pathPolyRefs; m_pathPolyRefs = temp; } else { // waste of time to optimize, just find brand new path Build(startPoly, endPoly); return; } } if(endOffPath) { bool adjacent = false; int i; for(i = 0; i < DT_VERTS_PER_POLYGON; ++i) if(startPoly == m_navMesh->getPolyByRef(m_pathPolyRefs[0])->neis[i]) { adjacent = true; break; } if(adjacent) { if(m_length < MAX_PATH_LENGTH) { // endPoly is adjacent to the path, and we have enough room to add it to the end dtPolyRef* temp = new dtPolyRef[m_length + 1]; for(i = 0; i < m_length; ++i) temp[i] = m_pathPolyRefs[i]; temp[i] = endPoly; delete [] m_pathPolyRefs; m_pathPolyRefs = temp; } //else // ; // endPoly is adjacent to the path, we just don't have room to store it } else { // waste of time to optimize, just find brand new path Build(startPoly, endPoly); return; } } updateNextPosition(); }
void PathFinder::BuildPointPath(const float *startPoint, const float *endPoint) { float pathPoints[MAX_POINT_PATH_LENGTH*VERTEX_SIZE]; uint32 pointCount = 0; dtStatus dtResult = DT_FAILURE; if(m_useStraightPath) { dtResult = m_navMeshQuery->findStraightPath( startPoint, // start position endPoint, // end position m_pathPolyRefs, // current path m_polyLength, // lenth of current path pathPoints, // [out] path corner points NULL, // [out] flags NULL, // [out] shortened path (int*)&pointCount, m_pointPathLimit); // maximum number of points/polygons to use } else { dtResult = findSmoothPath( startPoint, // start position endPoint, // end position m_pathPolyRefs, // current path m_polyLength, // length of current path pathPoints, // [out] path corner points (int*)&pointCount, m_pointPathLimit); // maximum number of points } if(pointCount < 2 || dtResult != DT_SUCCESS) { // only happens if pass bad data to findStraightPath or navmesh is broken // single point paths can be generated here // TODO : check the exact cases sLog->outDebug(LOG_FILTER_PATHFINDING, "++ PathFinder::BuildPointPath FAILED! path sized %d returned\n", pointCount); BuildShortcut(); m_type = PATHFIND_NOPATH; return; } m_pathPoints.resize(pointCount); for(uint32 i = 0; i < pointCount; ++i) m_pathPoints[i] = Vector3(pathPoints[i*VERTEX_SIZE+2], pathPoints[i*VERTEX_SIZE], pathPoints[i*VERTEX_SIZE+1]); // first point is always our current location - we need the next one setActualEndPosition(m_pathPoints[pointCount-1]); // force the given destination, if needed if(m_forceDestination && (!(m_type & PATHFIND_NORMAL) || !inRange(getEndPosition(), getActualEndPosition(), 1.0f, 1.0f))) { // we may want to keep partial subpath if(dist3DSqr(getActualEndPosition(), getEndPosition()) < 0.3f * dist3DSqr(getStartPosition(), getEndPosition())) { setActualEndPosition(getEndPosition()); m_pathPoints[m_pathPoints.size()-1] = getEndPosition(); } else { setActualEndPosition(getEndPosition()); BuildShortcut(); } m_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); } sLog->outDebug(LOG_FILTER_PATHFINDING, "++ PathFinder::BuildPointPath path type %d size %d poly-size %d\n", m_type, pointCount, m_polyLength); }
void PathInfo::BuildPointPath(float *startPoint, float *endPoint) { float pathPoints[MAX_POINT_PATH_LENGTH*VERTEX_SIZE]; uint32 pointCount = 0; dtStatus dtResult = DT_FAILURE; bool usedOffmesh = false; if (m_useStraightPath) { dtResult = m_navMeshQuery->findStraightPath( startPoint, // start position endPoint, // end position m_pathPolyRefs, // current path m_polyLength, // lenth of current path pathPoints, // [out] path corner points NULL, // [out] flags NULL, // [out] shortened path (int*)&pointCount, MAX_POINT_PATH_LENGTH); // maximum number of points/polygons to use } else { dtResult = findSmoothPath( startPoint, // start position endPoint, // end position m_pathPolyRefs, // current path m_polyLength, // length of current path pathPoints, // [out] path corner points (int*)&pointCount, usedOffmesh, MAX_POINT_PATH_LENGTH); // maximum number of points } if (pointCount < 2 || dtResult != DT_SUCCESS) { // only happens if pass bad data to findStraightPath or navmesh is broken // single point paths can be generated here // TODO : check the exact cases DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ PathInfo::BuildPointPath FAILED! path sized %d returned\n", pointCount); BuildShortcut(); m_type = PATHFIND_NOPATH; return; } // we need to flash our poly path to prevent it being used as subpath next cycle // in case of off mesh connection was used if(usedOffmesh) m_polyLength = 0; m_pathPoints.resize(pointCount); for (uint32 i = 0; i < pointCount; ++i) m_pathPoints.set(i, PathNode(pathPoints[i*VERTEX_SIZE+2], pathPoints[i*VERTEX_SIZE], pathPoints[i*VERTEX_SIZE+1])); // first point is always our current location - we need the next one setNextPosition(m_pathPoints[1]); setActualEndPosition(m_pathPoints[pointCount-1]); // force the given destination, if needed if(m_forceDestination && (!(m_type & PATHFIND_NORMAL) || !inRange(getEndPosition(), getActualEndPosition(), 1.0f, 1.0f))) { setActualEndPosition(getEndPosition()); BuildShortcut(); m_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); return; } DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ PathInfo::BuildPointPath path type %d size %d poly-size %d\n", m_type, pointCount, m_polyLength); }
void PathInfo::updateNextPosition() { float x, y, z; getStartPosition(x, y, z); float startPos[3] = {y, z, x}; getEndPosition(x, y, z); float endPos[3] = {y, z, x}; float* pathPoints = new float[MAX_PATH_LENGTH*3]; int pointCount = m_navMesh->findStraightPath( startPos, // start position endPos, // end position m_pathPolyRefs, // current path m_length, // lenth of current path pathPoints, // [out] path corner points 0, // [out] flags 0, // [out] shortened path PATHFIND TODO: see if this is usable (IE, doesn't leave gaps in path) MAX_PATH_LENGTH); // maximum number of points/polygons to use // TODO: imitate PATHFIND_ITER code from RecastDemo so that terrain following is smoother if(pointCount == 0) { delete [] pathPoints; // only happens if pass bad data to findStraightPath or navmesh is broken sLog.outDebug("%u's UpdateNextPosition failed: 0 length path", m_sourceObject->GetGUID()); shortcut(); return; } int ix, iy, iz; if(pointCount == 1) { ix = 2; iy = 0; iz = 1; } else { ix = 5; iy = 3; iz = 4; } setNextPosition(pathPoints[ix], pathPoints[iy], pathPoints[iz]); // if startPosition == nextPosition, NPC will never advance to destination if(isSamePoint(m_startPosition, m_nextPosition) && !isSamePoint(m_nextPosition, m_endPosition)) setNextPosition(pathPoints[ix + 3], pathPoints[iy + 3], pathPoints[iz + 3]); delete [] m_pathPoints; m_pathPoints = pathPoints; m_type = PathType(m_type | PATHFIND_NORMAL); // if end position from findStraightPath isn't the // place we want to go, there is likely no path endPos[0] = pathPoints[(pointCount-1)*3+2]; endPos[1] = pathPoints[(pointCount-1)*3]; endPos[2] = pathPoints[(pointCount-1)*3+1]; if(!dtVequal(endPos, m_endPosition)) m_type = PathType(m_type | PATHFIND_NOPATH); }
void PathFinderMovementGenerator::BuildPointPath(const float *startPoint, const float *endPoint) { float pathPoints[MAX_POINT_PATH_LENGTH*VERTEX_SIZE]; uint32 pointCount = 0; dtStatus dtResult = DT_FAILURE; if (m_useStraightPath) { dtResult = m_navMeshQuery->findStraightPath( startPoint, // start position endPoint, // end position m_pathPolyRefs, // current path m_polyLength, // lenth of current path pathPoints, // [out] path corner points NULL, // [out] flags NULL, // [out] shortened path (int*)&pointCount, m_pointPathLimit); // maximum number of points/polygons to use } else { dtResult = findSmoothPath( startPoint, // start position endPoint, // end position m_pathPolyRefs, // current path m_polyLength, // length of current path pathPoints, // [out] path corner points (int*)&pointCount, m_pointPathLimit); // maximum number of points } if (pointCount < 2 || dtResult != DT_SUCCESS) { // only happens if pass bad data to findStraightPath or navmesh is broken // single point paths can be generated here // TODO : check the exact cases sLog->outDebug(LOG_FILTER_MAPS, "++ PathFinderMovementGenerator::BuildPointPath FAILED! path sized %d returned\n", pointCount); BuildShortcut(); m_type = PATHFIND_NOPATH; return; } else if (pointCount == m_pointPathLimit) { sLog->outDebug(LOG_FILTER_MAPS, "++ PathGenerator::BuildPointPath FAILED! path sized %d returned, lower than limit set to %d\n", pointCount, m_pointPathLimit); BuildShortcut(); m_type = PATHFIND_SHORT; return; } m_pathPoints.resize(pointCount); for (uint32 i = 0; i < pointCount; ++i) m_pathPoints[i] = Vector3(pathPoints[i*VERTEX_SIZE+2], pathPoints[i*VERTEX_SIZE], pathPoints[i*VERTEX_SIZE+1]); // first point is always our current location - we need the next one setActualEndPosition(m_pathPoints[pointCount-1]); // force the given destination, if needed if(m_forceDestination && (!(m_type & PATHFIND_NORMAL) || !inRange(getEndPosition(), getActualEndPosition(), 1.0f, 1.0f))) { // we may want to keep partial subpath if(dist3DSqr(getActualEndPosition(), getEndPosition()) < 0.3f * dist3DSqr(getStartPosition(), getEndPosition())) { setActualEndPosition(getEndPosition()); m_pathPoints[m_pathPoints.size()-1] = getEndPosition(); } else { setActualEndPosition(getEndPosition()); BuildShortcut(); } m_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); } // Custom point for bugged zone - start float startEndDist = dist3DSqr(getStartPosition(), getEndPosition()); // Blade's Edge Arena (mapid) if (m_sourceUnit->GetMapId() == 562) { // Start & End Position // NAPOLOVINA RABOTESHT PILLAR if (startEndDist < 3000.0f && startPoint[1] >= 9.000000f && startPoint[2] <= 6234.335938f && startPoint[2] >= 6224.140430f && startPoint[0] >= 244.160000f && startPoint[0] <= 255.118940f) // southeast pillar { clear(); m_pathPoints.resize(4); m_pathPoints[0] = getStartPosition(); m_pathPoints[1] = Vector3(6231.038574f, 252.630981f, 11.300000f); m_pathPoints[2] = Vector3(6234.254395f, 256.513702f, 11.280000f); m_pathPoints[3] = getEndPosition(); } // Problemna chast: else if (startEndDist < 3000.0f && endPoint[1] >= 9.000000f && endPoint[2] <= 6234.335938f && endPoint[2] >= 6224.140430f && endPoint[0] >= 244.160000f && endPoint[0] <= 255.118940f) // southeast pillar { clear(); m_pathPoints.resize(4); m_pathPoints[0] = getStartPosition(); m_pathPoints[1] = Vector3(6234.254395f, 256.513702f, 11.280000f); m_pathPoints[2] = Vector3(6231.038574f, 252.630981f, 11.300000f); m_pathPoints[3] = getEndPosition(); } // RABOTESHT PILLAR // TODO: (na zemqta ima mqsto na koeto Z e > 9 koeto znachi che moje da se charge i ot dolu -> fail if (startEndDist < 3000.0f && startPoint[1] >= 9.000000f && startPoint[2] >= 6243.385660f && startPoint[2] <= 6254.611660f && startPoint[0] >= 268.757917f && startPoint[0] <= 279.558794f) // northwest pillar { clear(); m_pathPoints.resize(4); m_pathPoints[0] = getStartPosition(); m_pathPoints[1] = Vector3(6246.324219f, 271.570000f, 11.300000f); m_pathPoints[2] = Vector3(6242.942484f, 267.210030f, 11.280000f); m_pathPoints[3] = getEndPosition(); } else if (startEndDist < 3000.0f && endPoint[1] >= 9.000000f && endPoint[2] >= 6243.385660f && endPoint[2] <= 6254.611660f && endPoint[0] >= 268.757917f && endPoint[0] <= 279.558794f) // northwest pillar { clear(); m_pathPoints.resize(4); m_pathPoints[0] = getStartPosition(); m_pathPoints[1] = Vector3(6242.942484f, 267.210030f, 11.280000f); m_pathPoints[2] = Vector3(6246.324219f, 271.570000f, 11.300000f); m_pathPoints[3] = getEndPosition(); } } // Dalaran Sewers if (m_sourceUnit->GetMapId() == 617) { if (startPoint[2] >= 1330.033223f && startPoint[1] >= 9.000000f) // Canal 1# { // Path x,y,z m_pathPoints.resize(5); m_pathPoints[0] = getStartPosition(); m_pathPoints[1] = Vector3(1332.749268f, 816.274780f, 8.355900f); m_pathPoints[2] = Vector3(1325.749268f, 816.602539f, 5.4000000f); m_pathPoints[3] = Vector3(1328.749268f, 816.602539f, 3.4000000f); m_pathPoints[4] = getEndPosition(); } else if (startPoint[2] <= 1253.904785f && startPoint[1] >= 9.000000f) // Canal 2# { // Path x,y,z m_pathPoints.resize(5); m_pathPoints[0] = getStartPosition(); m_pathPoints[1] = Vector3(1252.425395f, 764.971680f, 8.000000f); m_pathPoints[3] = Vector3(1255.425395f, 764.971680f, 5.3559000f); m_pathPoints[3] = Vector3(1257.425395f, 764.971680f, 3.3559000f); m_pathPoints[4] = getEndPosition(); } } // Custom point for bugged zone - end sLog->outDebug(LOG_FILTER_MAPS, "++ PathFinderMovementGenerator::BuildPointPath path type %d size %d poly-size %d\n", m_type, pointCount, m_polyLength); }
void GradientLayer::draw(Graphics* const TheGraphics, const Pnt2f& TopLeft, const Pnt2f& BottomRight, const Real32 Opacity) const { if(getMFColors()->size() == getMFStops()->size()) { if(getMFColors()->size() == 1) { TheGraphics->drawQuad(TopLeft, Pnt2f(BottomRight.x(), TopLeft.y()), BottomRight, Pnt2f(TopLeft.x(), BottomRight.y()), getColors(0), getColors(0), getColors(0), getColors(0), Opacity); } else { Pnt2f StartPosition= TopLeft; StartPosition[0] += getStartPosition()[0]*(BottomRight[0] - TopLeft[0]); StartPosition[1] += getStartPosition()[1]*(BottomRight[1] - TopLeft[1]); Pnt2f EndPosition= TopLeft; EndPosition[0] += getEndPosition()[0]*(BottomRight[0] - TopLeft[0]); EndPosition[1] += getEndPosition()[1]*(BottomRight[1] - TopLeft[1]); //Calculate the coordinate system Vec2f u(EndPosition-StartPosition); u.normalize(); Vec3f v3D(Vec3f(u.x(), u.y(), 0.0f).cross(Vec3f(0.0,0.0,-1.0))); Vec2f v(v3D.x(), v3D.y()); Matrix22<Real32> CoordinateSystem(u.x(), u.y(), v.x(), v.y()); Pnt2f Min; Pnt2f Max; { //Calculate the bounding box in the new coordinate system Pnt2f UVTopLeft(CoordinateSystem*TopLeft), UVBottomRight(CoordinateSystem*BottomRight), UVTopRight(CoordinateSystem*Vec2f(BottomRight.x(), TopLeft.y())), UVBottomLeft(CoordinateSystem*Vec2f(TopLeft.x(), BottomRight.y())); Min.setValues( osgMin(UVTopLeft.x(), osgMin(UVBottomRight.x(), osgMin(UVTopRight.x(), UVBottomLeft.x()))), osgMin(UVTopLeft.y(), osgMin(UVBottomRight.y(), osgMin(UVTopRight.y(), UVBottomLeft.y())))); Max.setValues( osgMax(UVTopLeft.x(), osgMax(UVBottomRight.x(), osgMax(UVTopRight.x(), UVBottomLeft.x()))), osgMax(UVTopLeft.y(), osgMax(UVBottomRight.y(), osgMax(UVTopRight.y(), UVBottomLeft.y())))); } Pnt2f Origin(CoordinateSystem.inverse() * Min); Real32 PreStartLength(((CoordinateSystem*StartPosition).x()-Min.x())/(Max.x() - Min.x())), PostEndLength((Max.x()- (CoordinateSystem*EndPosition).x())/(Max.x() - Min.x())), GradientLength(1.0f-PostEndLength-PreStartLength); if(getSpreadMethod() == SPREAD_REFLECT|| getSpreadMethod() == SPREAD_REPEAT) { //Code for drawing the Gradient with Repeating/Reflection //Determine the Number of Repeats UInt32 RepeatCount = static_cast<UInt32>(osgCeil(1.0f/GradientLength)); //Determine the relative location in the gradient that the Start left is at Real32 StartGradientLocation = PreStartLength - GradientLength * osgCeil(PreStartLength/GradientLength); //Determine whether the start is a reflection or normal bool isReflection = getSpreadMethod() == SPREAD_REFLECT && static_cast<UInt32>(osgCeil(PreStartLength/GradientLength))%2==1; for(UInt32 i(0) ; i<RepeatCount ; ++i) { if(isReflection) { drawGradient(TheGraphics, Origin, Max-Min,u,StartGradientLocation+GradientLength*(i+1),StartGradientLocation+GradientLength*i,Opacity); } else { drawGradient(TheGraphics, Origin, Max-Min,u,StartGradientLocation+GradientLength*i,StartGradientLocation+GradientLength*(i+1),Opacity); } if(getSpreadMethod() == SPREAD_REFLECT) { isReflection = !isReflection; } } } else { //Code for drawing the Gradient with Padding //Front Pad if(PreStartLength != 0.0f) { drawPad(TheGraphics, Origin, Max-Min,u,0.0,PreStartLength,getMFColors()->front(),Opacity); } drawGradient(TheGraphics, Origin, Max-Min,u,PreStartLength,PreStartLength+GradientLength,Opacity); //End Pad if(PostEndLength != 0.0f) { drawPad(TheGraphics, Origin, Max-Min,u,PreStartLength+GradientLength,1.0,getMFColors()->back(),Opacity); } } } } }
void PathInfo::Build(dtPolyRef startPoly, dtPolyRef endPoly) { clear(); float x, y, z; if(startPoly == 0 || endPoly == 0) { // polygon didn't touch the search box // could mean start or end has... // (x,y) outside navmesh // (z) above/below the navmesh sLog.outDebug("%u's Path Build failed: invalid start or end polygon", m_sourceObject->GetGUID()); //if(canFly()) // TODO shortcut(); return; } getStartPosition(x, y, z); float startPos[3] = {y, z, x}; getEndPosition(x, y, z); float endPos[3] = {y, z, x}; bool startOffPoly, endOffPoly; float distanceStart, distanceEnd; startOffPoly = !isPointInPolyBounds(startPos[2], startPos[0], startPos[1], distanceStart, startPoly); endOffPoly = !isPointInPolyBounds(endPos[2], endPos[0], endPos[1], distanceEnd, endPoly); dtQueryFilter filter = createFilter(); // use special filter so we use proper terrain types dtPolyRef pathPolys[MAX_PATH_LENGTH]; m_length = m_navMesh->findPath( startPoly, // start polygon endPoly, // end polygon startPos, // start position endPos, // end position &filter, // polygon search filter pathPolys, // [out] path MAX_PATH_LENGTH); // max number of polygons in output path if(m_length == 0) { // only happens if we passed bad data to findPath(), or navmesh is messed up sLog.outDebug("%u's Path Build failed: 0-length path", m_sourceObject->GetGUID()); shortcut(); return; } // pathPolyRefs was deleted when we entered Build(dtPolyRef, dtPolyRef) m_pathPolyRefs = new dtPolyRef[m_length]; int i; for(i = 0; i < m_length; ++i) m_pathPolyRefs[i] = pathPolys[i]; updateNextPosition(); if(m_length >= MAX_PATH_LENGTH) m_type = PathType(m_type | PATHFIND_INCOMPLETE); m_currentNode = 0; }
void PathFinder::BuildPointPath(const float* startPoint, const float* endPoint) { float pathPoints[MAX_POINT_PATH_LENGTH * VERTEX_SIZE]; uint32 pointCount = 0; dtStatus dtResult = DT_FAILURE; if (m_useStraightPath) { dtResult = m_navMeshQuery->findStraightPath( startPoint, // start position endPoint, // end position m_pathPolyRefs, // current path m_polyLength, // lenth of current path pathPoints, // [out] path corner points NULL, // [out] flags NULL, // [out] shortened path (int*)&pointCount, m_pointPathLimit); // maximum number of points/polygons to use } else { dtResult = findSmoothPath( startPoint, // start position endPoint, // end position m_pathPolyRefs, // current path m_polyLength, // length of current path pathPoints, // [out] path corner points (int*)&pointCount, m_pointPathLimit); // maximum number of points } if (pointCount < 2 || dtStatusFailed(dtResult)) { // only happens if pass bad data to findStraightPath or navmesh is broken // single point paths can be generated here // TODO : check the exact cases DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ PathFinder::BuildPointPath FAILED! path sized %d returned\n", pointCount); BuildShortcut(); m_type = PATHFIND_NOPATH; return; } uint32 tempPointCounter = 2; uint8 cutLimit = 0; PointsArray tempPathPoints; tempPathPoints.resize(pointCount); for (uint32 i = 0; i < pointCount; ++i) tempPathPoints[i] = Vector3(pathPoints[i*VERTEX_SIZE+2], pathPoints[i*VERTEX_SIZE], pathPoints[i*VERTEX_SIZE+1]); // Optimize points for (uint32 i = 1; i < pointCount - 1; ++i) { G3D::Vector3 p = tempPathPoints[i]; // Point G3D::Vector3 p1 = tempPathPoints[i - 1]; // PrevPoint G3D::Vector3 p2 = tempPathPoints[i + 1]; // NextPoint float line = (p1.y - p2.y) * p.x + (p2.x - p1.x) * p.y + (p1.x * p2.y - p2.x * p1.y); if (fabs(line) < LINE_FAULT && cutLimit < SKIP_POINT_LIMIT) { tempPathPoints[i] = Vector3(0, 0, 0); ++cutLimit; } else { ++tempPointCounter; cutLimit = 0; } } m_pathPoints.resize(tempPointCounter); uint32 b = 0; for (uint32 i = 0; i < pointCount; ++i) { if (tempPathPoints[i] != Vector3(0, 0, 0)) { m_pathPoints[b] = tempPathPoints[i]; ++b; } } pointCount = tempPointCounter; // first point is always our current location - we need the next one setActualEndPosition(m_pathPoints[pointCount - 1]); // force the given destination, if needed if (m_forceDestination && (!(m_type & PATHFIND_NORMAL) || !inRange(getEndPosition(), getActualEndPosition(), 1.0f, 1.0f))) { // we may want to keep partial subpath if (dist3DSqr(getActualEndPosition(), getEndPosition()) < 0.3f * dist3DSqr(getStartPosition(), getEndPosition())) { setActualEndPosition(getEndPosition()); m_pathPoints[m_pathPoints.size()-1] = getEndPosition(); } else { setActualEndPosition(getEndPosition()); BuildShortcut(); } m_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); } DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ PathFinder::BuildPointPath path type %d size %d poly-size %d\n", m_type, pointCount, m_polyLength); }