float EmberEntity::getHeight(const WFMath::Point<2>& localPosition) const { if (mHeightProvider) { float height = 0; if (mHeightProvider->getHeight(WFMath::Point<2>(localPosition.x(), localPosition.y()), height)) { return height; } } //A normal EmberEntity shouldn't know anything about the terrain, so we can't handle the area here. //Instead we just pass it on to the parent until we get to someone who knows how to handle this (preferably the terrain). if (getEmberLocation()) { WFMath::Point<2> adjustedLocalPosition(getPredictedPos().x(), getPredictedPos().y()); WFMath::Vector<3> xVec = WFMath::Vector<3>(1.0, 0.0, 0.0).rotate(getOrientation()); double theta = atan2(xVec.y(), xVec.x()); // rotation about Z WFMath::RotMatrix<2> rm; WFMath::Vector<2> adjustment(localPosition.x(), localPosition.y()); adjustment.rotate(rm.rotation(theta)); adjustedLocalPosition += adjustment; return getEmberLocation()->getHeight(adjustedLocalPosition) - getPredictedPos().z(); } WFMath::Point<3> predictedPos = getPredictedPos(); if (predictedPos.isValid()) { return predictedPos.z(); } else { return 0.0f; } }
void Steering::setAwareness() { //If we are loitering we should stop that now. delete mLoitering; mLoitering = nullptr; const auto entityViewPosition = mAvatar.getEntity()->getViewPosition(); WFMath::Point<2> destination2d(mViewDestination.x(), mViewDestination.z()); WFMath::Point<2> entityPosition2d(entityViewPosition.x(), entityViewPosition.z()); WFMath::Vector<2> direction(destination2d - entityPosition2d); auto theta = std::atan2(direction.y(), direction.x()); // rotation about Y WFMath::RotMatrix<2> rm; rm.rotation(theta); WFMath::Point<2> start = entityPosition2d; start -= WFMath::Vector<2>(mPadding, mPadding); WFMath::Vector<2> size(direction.mag() + (mPadding * 2), mPadding * 2); WFMath::RotBox<2> area; area.size() = size; area.corner0() = start; area.orientation() = WFMath::RotMatrix<2>().identity(); area.rotatePoint(rm, entityPosition2d); mAwareness.setAwarenessArea(area, WFMath::Segment<2>(entityPosition2d, destination2d)); }
bool TerrainArea::parseArea() { if (!mEntity.hasAttr("area")) { S_LOG_FAILURE("TerrainArea created for entity with no area attribute"); return false; } const Atlas::Message::Element areaElem(mEntity.valueOfAttr("area")); if (!areaElem.isMap()) { S_LOG_FAILURE("TerrainArea element ('area') must be of map type."); return false; } const Atlas::Message::MapType& areaData(areaElem.asMap()); int layer = 0; WFMath::Polygon<2> poly; TerrainAreaParser parser; if (parser.parseArea(areaData, poly, layer)) { if (!mArea) { mArea = new Mercator::Area(layer, false); } else { //A bit of an ugly hack here since the Mercator system doesn't support changing the layer. We need to swap the old area for a new one if the layer has changed. if (mArea->getLayer() != layer) { mOldArea = mArea; mArea = new Mercator::Area(layer, false); } } // transform polygon into terrain coords WFMath::Vector<3> xVec = WFMath::Vector<3>(1.0, 0.0, 0.0).rotate(mEntity.getOrientation()); double theta = atan2(xVec.y(), xVec.x()); // rotation about Z WFMath::RotMatrix<2> rm; poly.rotatePoint(rm.rotation(theta), WFMath::Point<2>(0, 0)); poly.shift(WFMath::Vector<2>(mEntity.getPosition().x(), mEntity.getPosition().y())); mArea->setShape(poly); return true; } else { return false; } }
Mercator::TerrainMod* InnerTranslatorImpl<ModT, ShapeT>::createInstance(const WFMath::Point<3>& pos, const WFMath::Quaternion& orientation) { ShapeT<2> shape = this->mShape; if (!shape.isValid() || !pos.isValid()) { return nullptr; } if (orientation.isValid()) { /// rotation about Z axis WFMath::Vector<3> xVec = WFMath::Vector<3>(1.0, 0.0, 0.0).rotate(orientation); WFMath::CoordType theta = std::atan2(xVec.y(), xVec.x()); WFMath::RotMatrix<2> rm; shape.rotatePoint(rm.rotation(theta), WFMath::Point<2>(0, 0)); } shape.shift(WFMath::Vector<2>(pos.x(), pos.y())); float level = TerrainModTranslator::parsePosition(pos, this->mData); return new ModT<ShapeT>(level, shape); }
bool TerrainArea::placeArea(WFMath::Polygon<2>& poly) { //If the position if invalid we can't do anything with the area yet. if (!mEntity.getPosition().isValid()) { return false; } // transform polygon into terrain coords if (mEntity.getOrientation().isValid()) { WFMath::Vector<3> xVec = WFMath::Vector<3>(1.0, 0.0, 0.0).rotate(mEntity.getOrientation()); double theta = atan2(xVec.y(), xVec.x()); // rotation about Z WFMath::RotMatrix<2> rm; poly.rotatePoint(rm.rotation(theta), WFMath::Point<2>(0, 0)); } poly.shift(WFMath::Vector<2>(mEntity.getPosition().x(), mEntity.getPosition().y())); return true; }