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 SizeAdapter::fillElementFromGui() { WFMath::AxisBox<3> axisBox; WFMath::Point<3> lowerPoint = axisBox.lowCorner(); WFMath::Point<3> upperPoint = axisBox.highCorner(); if (mWidgets.lowerXWindow) { lowerPoint.x() = atof(mWidgets.lowerXWindow->getText().c_str()); } if (mWidgets.lowerYWindow) { lowerPoint.y() = atof(mWidgets.lowerYWindow->getText().c_str()); } if (mWidgets.lowerZWindow) { lowerPoint.z() = atof(mWidgets.lowerZWindow->getText().c_str()); } if (mWidgets.upperXWindow) { upperPoint.x() = atof(mWidgets.upperXWindow->getText().c_str()); } if (mWidgets.upperYWindow) { upperPoint.y() = atof(mWidgets.upperYWindow->getText().c_str()); } if (mWidgets.upperZWindow) { upperPoint.z() = atof(mWidgets.upperZWindow->getText().c_str()); } axisBox.setCorners(lowerPoint, upperPoint); mEditedValue = axisBox.toAtlas(); }
TerrainDefPointStore TerrainParser::parseTerrain(const Atlas::Message::Element& terrain, const WFMath::Point<3>& offset) const { //_fpreset(); if (!terrain.isMap()) { S_LOG_FAILURE("Terrain is not a map"); } const Atlas::Message::MapType & tmap = terrain.asMap(); Atlas::Message::MapType::const_iterator I = tmap.find("points"); if (I == tmap.end()) { S_LOG_FAILURE("No terrain points"); } Terrain::TerrainDefPointStore pointStore; if (I->second.isList()) { // Legacy support for old list format. const Atlas::Message::ListType& plist = I->second.asList(); Atlas::Message::ListType::const_iterator J = plist.begin(); for (; J != plist.end(); ++J) { if (!J->isList()) { S_LOG_INFO("Non list in points"); continue; } const Atlas::Message::ListType & point = J->asList(); if (point.size() != 3) { S_LOG_INFO("Point without 3 nums."); continue; } Terrain::TerrainDefPoint defPoint(static_cast<int> (point[0].asNum() + offset.x()), static_cast<int> (point[1].asNum() + offset.y()), static_cast<float> (point[3].asNum() + offset.z())); pointStore.push_back(defPoint); } } else if (I->second.isMap()) { const Atlas::Message::MapType& plist = I->second.asMap(); Atlas::Message::MapType::const_iterator J = plist.begin(); for (; J != plist.end(); ++J) { if (!J->second.isList()) { S_LOG_INFO("Non list in points."); continue; } const Atlas::Message::ListType & point = J->second.asList(); if (point.size() != 3) { S_LOG_INFO("Point without 3 nums."); continue; } int x = static_cast<int> (point[0].asNum()); int y = static_cast<int> (point[1].asNum()); float z = point[2].asNum(); Terrain::TerrainDefPoint defPoint(x + offset.x(), y + offset.y(), z + offset.z()); pointStore.push_back(defPoint); } } else { S_LOG_FAILURE("Terrain is the wrong type"); } return pointStore; }
ModelBlock::ModelBlock(Ogre::SceneNode* baseNode,const Carpenter::BuildingBlock* buildingBlock, Model::Model* model, Construction* construction) : mBuildingBlock(buildingBlock) , mModel(model) , mModelNode(0) , mConstruction(construction) { mNode = baseNode->createChildSceneNode(Convert::toOgre(buildingBlock->getPosition()), Convert::toOgre(buildingBlock->getOrientation())); mPointBillBoardSet = mNode->getCreator()->createBillboardSet( std::string("__construction_") + construction->getBluePrint()->getName() + "_" + buildingBlock->getName() + "_billboardset__" + mNode->getName()); mPointBillBoardSet->setDefaultDimensions(1, 1); mPointBillBoardSet->setMaterialName("carpenter/flare"); mPointBillBoardSet->setVisible(false); // Ogre::SceneNode* aNode = EmberOgre::getSingleton().getSceneManager()->getRootSceneNode()->createChildSceneNode(); mNode->attachObject(mPointBillBoardSet); if (model) { JesusPickerObject* pickerObject = new JesusPickerObject(this, 0); model->setUserObject(pickerObject); mModelNode = mNode->createChildSceneNode(); mModelNode->attachObject(model); model->setQueryFlags(Jesus::CM_MODELBLOCK); //only autoscale the model if we've not set the scale in the modeldefinition //TODO: it would of course be best if all models were correctly scaled and this code could be removed if (model->getDefinition()->getScale() == 0) { const Ogre::AxisAlignedBox ogreBoundingBox = model->getBoundingBox(); const Ogre::Vector3 ogreMax = ogreBoundingBox.getMaximum(); const Ogre::Vector3 ogreMin = ogreBoundingBox.getMinimum(); const WFMath::AxisBox<3> wfBoundingBox = buildingBlock->getBuildingBlockSpec()->getBlockSpec()->getBoundingBox(); const WFMath::Point<3> wfMax = wfBoundingBox.highCorner(); const WFMath::Point<3> wfMin = wfBoundingBox.lowCorner(); Ogre::Real scaleX; Ogre::Real scaleY; Ogre::Real scaleZ; scaleX = fabs((wfMax.x() - wfMin.x()) / (ogreMax.x - ogreMin.x)); scaleY = fabs((wfMax.z() - wfMin.z()) / (ogreMax.y - ogreMin.y)); scaleZ = fabs((wfMax.y() - wfMin.y()) / (ogreMax.z - ogreMin.z)); mModelNode->setScale(scaleX, scaleY, scaleZ); } } }
void HeightMapUpdateTask::injectHeightMapSegmentsIntoHeightMap() { for (HeightMapSegmentStore::const_iterator I = mHeightMapSegments.begin(); I != mHeightMapSegments.end(); ++I) { WFMath::Point<2> position = I->first; IHeightMapSegment* heightMapSegment = I->second; mHeightMap.insert(position.x(), position.y(), heightMapSegment); } }
void PolygonPoint::setLocalPosition(const WFMath::Point<2>& position) { mNode->setPosition(position.x(), mNode->getPosition().y, -position.y()); if (mPolygon.getPositionProvider()) { Ogre::Vector3 pos = getNode()->getPosition(); pos.y = mPolygon.getPositionProvider()->getHeightForPosition(Convert::toWF<WFMath::Point<2>>(pos)); getNode()->setPosition(pos); } }
bool SizeAdapter::slider_ValueChanged(const CEGUI::EventArgs& e) { float value = mWidgets.scaler->getCurrentValue(); WFMath::AxisBox<3> newBox; try { newBox.fromAtlas(mOriginalValue); } catch (...) { newBox = WFMath::AxisBox<3>(WFMath::Point<3>(-0.5f, -0.5f, -0.5f), WFMath::Point<3>(0.5, 0.5, 0.5)); } WFMath::Point<3> lowerPoint = newBox.lowCorner(); WFMath::Point<3> upperPoint = newBox.highCorner(); lowerPoint.x() *= value; lowerPoint.y() *= value; lowerPoint.z() *= value; upperPoint.x() *= value; upperPoint.y() *= value; upperPoint.z() *= value; newBox.setCorners(lowerPoint, upperPoint); // newBox *= value; updateGui(newBox.toAtlas()); return true; }
/** * @brief Updates the marker, and any line drawn to it. */ void updateMarker() { //Check if we should adjust to the height of the world WFMath::Point<3> adjustedPoint(mPoint); float height = adjustedPoint.z(); if (mHeightProvider.getHeight(TerrainPosition(mPoint.x(), mPoint.y()), height)) { adjustedPoint.z() = height; } mMarkerNode->setPosition(Convert::toOgre(adjustedPoint)); WFMath::Segment<3> shape(adjustedPoint, mEntity.getViewPosition() + WFMath::Vector<3>(mEntity.getBBox().getCenter())); mMarkerDirectionIndicator->update(shape); }
void SoundService::updateListenerPosition(const WFMath::Point<3>& pos, const WFMath::Vector<3>& direction, const WFMath::Vector<3>& up) { if (!isEnabled()) { return; } alListener3f(AL_POSITION, pos.x(), pos.y(), pos.z()); SoundGeneral::checkAlError("Setting the listener position."); //Set the direction of the listener. ALfloat aluVectors[6]; aluVectors[0] = direction.x(); aluVectors[1] = direction.y(); aluVectors[2] = direction.z(); aluVectors[3] = up.x(); aluVectors[4] = up.y(); aluVectors[5] = up.z(); alListenerfv(AL_ORIENTATION, aluVectors); SoundGeneral::checkAlError("Setting the listener orientation."); }
void FoliageBase::reloadAtPosition(const WFMath::Point<2>& worldPosition) { if (mPagedGeometry) { mPagedGeometry->reloadGeometryPage(Ogre::Vector3(worldPosition.x(), 0, -worldPosition.y()), true); } }
void SoundSource::setPosition(const WFMath::Point<3>& pos) { assert(pos.isValid()); alSource3f(mALSource, AL_POSITION, pos.x(), pos.y(), pos.z()); SoundGeneral::checkAlError("Setting sound source position."); }
void Steering::update() { if (mSteeringEnabled) { if (mUpdateNeeded) { updatePath(); } auto entity = mAvatar.getEntity(); if (!mPath.empty()) { const auto& finalDestination = mPath.back(); auto entity3dPosition = entity->getViewPosition(); const WFMath::Point<2> entityPosition(entity3dPosition.x(), entity3dPosition.z()); //First check if we've arrived at our actual destination. if (WFMath::Distance(WFMath::Point<2>(finalDestination.x(), finalDestination.z()), entityPosition) < 0.1f) { //We've arrived at our destination. If we're moving we should stop. if (mLastSentVelocity.isValid() && mLastSentVelocity != WFMath::Vector<2>::ZERO()) { moveInDirection(WFMath::Vector<2>::ZERO()); } stopSteering(); } else { //We should send a move op if we're either not moving, or we've reached a waypoint, or we need to divert a lot. WFMath::Point<2> nextWaypoint(mPath.front().x(), mPath.front().z()); if (WFMath::Distance(nextWaypoint, entityPosition) < 0.1f) { mPath.pop_front(); nextWaypoint = WFMath::Point<2>(mPath.front().x(), mPath.front().z()); } WFMath::Vector<2> velocity = nextWaypoint - entityPosition; WFMath::Point<2> destination; velocity.normalize(); if (mPath.size() == 1) { //if the next waypoint is the destination we should send a "move to position" update to the server, to make sure that we stop when we've arrived. //otherwise, if there's too much lag, we might end up overshooting our destination and will have to double back destination = nextWaypoint; } //Check if we need to divert in order to avoid colliding. WFMath::Vector<2> newVelocity; bool avoiding = mAwareness.avoidObstacles(entityPosition, velocity * mSpeed, newVelocity); if (avoiding) { auto newMag = newVelocity.mag(); auto relativeMag = mSpeed / newMag; velocity = newVelocity; velocity.normalize(); velocity *= relativeMag; mUpdateNeeded = true; } bool shouldSend = false; if (velocity.isValid()) { if (mLastSentVelocity.isValid()) { //If the entity has stopped, and we're not waiting for confirmation to a movement request we've made, we need to start moving. if (!entity->isMoving() && !mExpectingServerMovement) { shouldSend = true; } else { auto currentTheta = std::atan2(mLastSentVelocity.y(), mLastSentVelocity.x()); auto newTheta = std::atan2(velocity.y(), velocity.x()); //If we divert too much from where we need to go we must adjust. if (std::abs(currentTheta - newTheta) > WFMath::numeric_constants<double>::pi() / 20) { shouldSend = true; } } } else { //If we've never sent a movement update before we should do that now. shouldSend = true; } } if (shouldSend) { //If we're moving to a certain destination and aren't avoiding anything we should tell the server to move to the destination. if (destination.isValid() && !avoiding) { moveToPoint(WFMath::Point<3>(destination.x(), entity3dPosition.y(), destination.y())); } else { moveInDirection(velocity); } } } } else { //We are steering, but the path is empty, which means we can't find any path. If we're moving we should stop movement. //But we won't stop steering; perhaps we'll find a path later. if (mLastSentVelocity.isValid() && mLastSentVelocity != WFMath::Vector<2>::ZERO()) { moveInDirection(WFMath::Vector<2>::ZERO()); } } } }