Beispiel #1
0
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;
	}
}
Beispiel #2
0
void NodeController::updatePosition()
{
	WFMath::Point<3> pos = mAttachment.getAttachedEntity().getPredictedPos();
	WFMath::Quaternion orientation = mAttachment.getAttachedEntity().getOrientation();
	WFMath::Vector<3> velocity = mAttachment.getAttachedEntity().getPredictedVelocity();
	mAttachment.setPosition(pos.isValid() ? pos : WFMath::Point<3>::ZERO(), orientation.isValid() ? orientation : orientation.identity(), velocity.isValid() ? velocity : WFMath::Vector<3>::ZERO());
}
Beispiel #3
0
void EmberEntityLoader::EmberEntity_VisibilityChanged(bool visible, EmberEntity* entity)
{
	WFMath::Point<3> viewPos = entity->getViewPosition();
	if (viewPos.isValid()) {
		//When the visibility changes, we only need to reload the page the entity is on.
		mGeom.reloadGeometryPage(Convert::toOgre(viewPos));
	}
}
void WorldAttachment::getOffsetForContainedNode(const IEntityAttachment& attachment, const WFMath::Point<3>& localPosition, WFMath::Vector<3>& offset)
{
	assert(localPosition.isValid());
	assert(offset.isValid());
	float height = 0;
	if (mTerrainManager.getHeight(WFMath::Point<2>(localPosition.x(), localPosition.y()), height)) {
		offset.z() = height - localPosition.z();
	}
}
Beispiel #5
0
void EntityEditor::addMarker(const std::string& entityId, const WFMath::Point<3>& point)
{
	delete mMarker;
	mMarker = 0;
	if (point.isValid()) {

		Eris::Entity* entity = mWorld.getView().getEntity(entityId);
		if (entity) {
			const WFMath::Point<3> worldPosition = entity->getViewPosition() + WFMath::Vector<3>(point);
			delete mMarker;
			mMarker = new EntityPointMarker(mEntity, mWorld.getSceneManager(), mWorld.getTerrainManager(), worldPosition);
			mMarker->updateMarker();
		}
	}
}
Beispiel #6
0
void PolygonPointMover::setPosition(const WFMath::Point<3>& position)
{
	if (position.isValid()) {
		//We need to offset into local space.
		Ogre::Vector3 posOffset = Ogre::Vector3::ZERO;
		if (getActivePoint()->getNode()->getParent()) {
			posOffset = getActivePoint()->getNode()->getParent()->_getDerivedPosition();
		}
		Ogre::Vector3 newPos = Convert::toOgre(position) - posOffset;
		newPos = getActivePoint()->getNode()->getParent()->_getDerivedOrientation().Inverse() * newPos;

		WFMath::Vector<3> translation = Convert::toWF<WFMath::Vector<3>>(newPos - getActivePoint()->getNode()->getPosition());
		//adjust it so that it moves according to the ground for example
		getActivePoint()->translate(WFMath::Vector<2>(translation.x(), translation.y()));
		mPolygon.updateRender();
	}
}
Beispiel #7
0
void EmberEntityLoader::removeEmberEntity(EmberEntity* entity)
{
	if (!entity) {
		S_LOG_WARNING("Tried to remove a null ref entity from the paged geometry.");
		return;
	}
#if EMBERENTITYLOADER_USEBATCH
	EntityLookup::iterator I = mEntityLookup.find(entity);
	if (I != mEntityLookup.end()) {
		EntityStore::iterator J = mEntities.find(I->second.first);
		if (J != mEntities.end()) {
			EntityColumn& column(J->second);
			EntityColumn::iterator K = column.find(I->second.second);
			if (K != column.end()) {
				EntityMap& entityMap(K->second);
				EntityMap::iterator L = entityMap.find(entity->getId());
				if (L != entityMap.end()) {
					L->second.movedConnection.disconnect();
					L->second.beingDeletedConnection.disconnect();
					entityMap.erase(L);
					mEntityLookup.erase(I);
				}
			}
		}
	}
#else
	EntityMap::iterator I = mEntities.find(entity->getId());
	if (I != mEntities.end()) {
		ModelRepresentationInstance& instance(I->second);
		Model::ModelRepresentation* modelRepresentation(instance.modelRepresentation);
		instance.movedConnection.disconnect();
		instance.beingDeletedConnection.disconnect();
		//Reset the rendering distance to the one set by the model def.
		modelRepresentation->getModel().setRenderingDistance(modelRepresentation->getModel().getDefinition()->getRenderingDistance());
		mEntities.erase(I);
	}

#endif

	WFMath::Point<3> pos = entity->getViewPosition();
	if (pos.isValid()) {
		//Rebuild geometry if necessary.
		mGeom.reloadGeometryPage(Convert::toOgre(pos));
	}
}
Beispiel #8
0
void EmberEntityLoader::EmberEntity_Moved(EmberEntity* entity)
{
	EntityMap* entityMap(getStoreForEntity(entity));
	if (entityMap) {
		EntityMap::iterator I = entityMap->find(entity->getId());
		if (I != entityMap->end()) {
			ModelRepresentationInstance& instance(I->second);
			if (!instance.lastPosition.isNaN()) {
				mGeom.reloadGeometryPage(instance.lastPosition);
			}
			WFMath::Point<3> viewPos = entity->getViewPosition();
			if (viewPos.isValid()) {
				mGeom.reloadGeometryPage(Convert::toOgre(viewPos));
				instance.lastPosition = Convert::toOgre(viewPos);
			}
		}
	}
}
Beispiel #9
0
void EntityMoverBase::setPosition(const WFMath::Point<3>& position)
{
    WFMath::Point<3> finalPosition(position);
    if (position.isValid()) {
        WFMath::Vector<3> adjustment;
        EmberEntity* entity = nullptr;
        if (mSnapping.get() && mSnapping->testSnapTo(position, getOrientation(), adjustment, &entity)) {
            finalPosition = finalPosition.shift(adjustment);
        }

        //We need to offset into local space.
        Ogre::Vector3 posOffset = Ogre::Vector3::ZERO;
        if (mNode->getParent()) {
            posOffset = mNode->getParent()->_getDerivedPosition();
        }
        mNode->setPosition(Convert::toOgre(finalPosition) - posOffset);
        newEntityPosition(mNode->getPosition());
        Moved.emit();
    }
}
Beispiel #10
0
void EmberEntityLoader::loadPage(::Forests::PageInfo & page)
{
	static Ogre::ColourValue colour(1, 1, 1, 1);

#if EMBERENTITYLOADER_USEBATCH
	const int batchX = static_cast<int>(Ogre::Math::Floor(page.bounds.left/ mBatchSize));
	const int batchY = static_cast<int>(Ogre::Math::Floor(page.bounds.top / mBatchSize));
	EntityMap& entities(mEntities[batchX][batchY]);
#else
	EntityMap& entities(mEntities);
#endif

	for (EntityMap::iterator I = entities.begin(); I != entities.end(); ++I) {
		ModelRepresentationInstance& instance(I->second);
		Model::ModelRepresentation* modelRepresentation(instance.modelRepresentation);
		EmberEntity& emberEntity = modelRepresentation->getEntity();
		if (emberEntity.isVisible()) {
			WFMath::Point<3> viewPos = emberEntity.getViewPosition();
			if (viewPos.isValid()) {
				Ogre::Vector3 pos(Convert::toOgre(viewPos));
				Model::Model& model(modelRepresentation->getModel());
				Ogre::Node* node = model.getParentNode();
				if (node) {
					const Ogre::Vector3& pos = node->_getDerivedPosition();
					if (pos.x > page.bounds.left && pos.x < page.bounds.right && pos.z > page.bounds.top && pos.z < page.bounds.bottom) {
						for (Model::Model::SubModelSet::const_iterator J = model.getSubmodels().begin(); J != model.getSubmodels().end(); ++J) {
							// 				if (!(*J)->getEntity()->getParentSceneNode()) {
							// 					model->getParentSceneNode()->attachObject((*J)->getEntity());
							// 				}
							//  				if ((*J)->getEntity()->isVisible()) {
							addEntity((*J)->getEntity(), pos, node->_getDerivedOrientation(), modelRepresentation->getScale(), colour);
							// 					(*J)->getEntity()->setVisible(false);
							//  				}
						}
					}
				}
			}
		}
	}
}
Beispiel #11
0
void EmberEntityLoader::addEmberEntity(Model::ModelRepresentation* modelRepresentation)
{
	if (!modelRepresentation) {
		S_LOG_WARNING("Tried to add a null ref entity to the paged geometry.");
		return;
	}
	EmberEntity& entity = modelRepresentation->getEntity();
	ModelRepresentationInstance instance;
	instance.movedConnection = entity.Moved.connect(sigc::bind(sigc::mem_fun(*this, &EmberEntityLoader::EmberEntity_Moved), &entity));
	instance.beingDeletedConnection = entity.BeingDeleted.connect(sigc::bind(sigc::mem_fun(*this, &EmberEntityLoader::EmberEntity_BeingDeleted), &entity));
	instance.visibilityChangedConnection = entity.VisibilityChanged.connect(sigc::bind(sigc::mem_fun(*this, &EmberEntityLoader::EmberEntity_VisibilityChanged), &entity));
	instance.modelRepresentation = modelRepresentation;

	WFMath::Point<3> viewPosition = entity.getViewPosition();
	Ogre::Vector3 position(std::numeric_limits<Ogre::Real>::quiet_NaN(), std::numeric_limits<Ogre::Real>::quiet_NaN(), std::numeric_limits<Ogre::Real>::quiet_NaN());

	bool isValidPos = false;
	if (viewPosition.isValid()) {
		isValidPos = true;
		position = Convert::toOgre(viewPosition);
	}
	instance.lastPosition = position;
#if EMBERENTITYLOADER_USEBATCH
	const int batchX = Ogre::Math::Floor(position.x / mBatchSize);
	const int batchY = Ogre::Math::Floor(position.y / mBatchSize);
	mEntityLookup[entity] = std::pair<int, int>(batchX, batchY);

	EntityMap& entities(mEntities[batchX][batchY]);
#else
	EntityMap& entities(mEntities);
#endif
	entities[entity.getId()] = instance;

	if (isValidPos) {
		//Rebuild geometry if necessary
		mGeom.reloadGeometryPage(position);
	}

}
Beispiel #12
0
bool SnapToMovement::testSnapTo(const WFMath::Point<3>& position, const WFMath::Quaternion& orientation, WFMath::Vector<3>& adjustment, EmberEntity* snappedToEntity)
{
	try {
		for (std::vector<Ogre::SceneNode*>::iterator I = mDebugNodes.begin(); I != mDebugNodes.end(); ++I) {
			Ogre::SceneNode* node = *I;
			node->setVisible(false);
			Ogre::Entity* sphereEntity = static_cast<Ogre::Entity*> (node->getAttachedObject(0));
			sphereEntity->setMaterialName("/global/authoring/point");
		}
	} catch (const std::exception& ex) {
		S_LOG_WARNING("Error when setting up debug nodes for snapping." << ex);
	}

	std::vector<Ogre::SceneNode*>::iterator nodeIterator = mDebugNodes.begin();

	//Use an auto pointer to allow both for undefined values and automatic cleanup when exiting the method.
	std::auto_ptr<SnapPointCandidate> closestSnapping(0);

	WFMath::AxisBox<3> currentBbox = mEntity.getBBox();
	//Translate the bbox into a rotbox
	WFMath::RotBox<3> currentRotbox;
	currentRotbox.size() = currentBbox.highCorner() - currentBbox.lowCorner();
	currentRotbox.corner0() = currentBbox.lowCorner();
	currentRotbox.orientation().identity();
	currentRotbox.rotatePoint(orientation, WFMath::Point<3>(0, 0, 0));
	currentRotbox.shift(WFMath::Vector<3>(position));

	//See if we should visualize debug nodes for the moved entity
	for (size_t j = 0; j < currentRotbox.numCorners(); ++j) {
		WFMath::Point<3> currentPoint = currentRotbox.getCorner(j);
		if (currentPoint.isValid() && nodeIterator != mDebugNodes.end()) {

			Ogre::SceneNode* node = *nodeIterator;
			node->setPosition(Convert::toOgre(currentPoint));
			node->setVisible(true);
			nodeIterator++;
		}
	}

	//First find all entities which are close enough
	//Then try to do a snap movement based on the points of the eris bounding boxes. I.e. we only provide support for snapping one corner of a bounding box to another corner (for now).
	WFMath::Ball<3> boundingSphere = mEntity.getBBox().boundingSphere();
	Ogre::Sphere sphere(mNode._getDerivedPosition(), boundingSphere.radius() * 2);
	Ogre::SphereSceneQuery* query = mSceneManager.createSphereQuery(sphere);
	Ogre::SceneQueryResult& result = query->execute();
	for (Ogre::SceneQueryResultMovableList::const_iterator I = result.movables.begin(); I != result.movables.end(); ++I) {
		Ogre::MovableObject* movable = *I;
		if (movable->getUserAny().getType() == typeid(EmberEntityUserObject::SharedPtr)) {
			EmberEntityUserObject* anUserObject = Ogre::any_cast<EmberEntityUserObject::SharedPtr>(movable->getUserAny()).get();
			EmberEntity& entity = anUserObject->getEmberEntity();
			if (&entity != &mEntity && entity.hasBBox()) {
				//Ok, we have an entity which is close to our entity. Now check if any of the points of the bounding box is close.
				WFMath::AxisBox<3> bbox = entity.getBBox();
				if (bbox.isValid()) {
					WFMath::RotBox<3> rotbox;
					rotbox.size() = bbox.highCorner() - bbox.lowCorner();
					rotbox.corner0() = bbox.lowCorner();
					rotbox.orientation().identity();
					rotbox.rotatePoint(entity.getViewOrientation(), WFMath::Point<3>(0, 0, 0));
					rotbox.shift(WFMath::Vector<3>(entity.getViewPosition()));

					for (size_t i = 0; i < rotbox.numCorners(); ++i) {
						WFMath::Point<3> point = rotbox.getCorner(i);
						Ogre::SceneNode* currentNode(0);
						//If there is any unclaimed debug node left we'll use it to visualize the corner
						if (nodeIterator != mDebugNodes.end()) {
							currentNode = *nodeIterator;
							currentNode->setPosition(Convert::toOgre(point));
							currentNode->setVisible(true);
							nodeIterator++;
						}
						point.z() = 0;
						for (size_t j = 0; j < currentRotbox.numCorners(); ++j) {
							WFMath::Point<3> currentPoint = currentRotbox.getCorner(j);
							currentPoint.z() = 0;
							WFMath::CoordType distance = WFMath::Distance(currentPoint, point);
							if (distance <= mSnapThreshold) {
								if (currentNode) {
									Ogre::Entity* sphereEntity = static_cast<Ogre::Entity*> (currentNode->getAttachedObject(0));
									if (sphereEntity) {
										try {
											sphereEntity->setMaterialName("/global/authoring/point/moved");
										} catch (const std::exception& ex) {
											S_LOG_WARNING("Error when setting material for point." << ex);
										}
									}
								}
								if (!closestSnapping.get()) {
									closestSnapping = std::auto_ptr<SnapPointCandidate>(new SnapPointCandidate());
									closestSnapping->entity = &entity;
									closestSnapping->distance = distance;
									closestSnapping->adjustment = point - currentPoint;
								} else if (distance < closestSnapping->distance) {
									closestSnapping->entity = &entity;
									closestSnapping->distance = distance;
									closestSnapping->adjustment = point - currentPoint;
								}
							}
						}
					}
				}
			}
		}
	}
	mSceneManager.destroyQuery(query);
	if (closestSnapping.get()) {
		adjustment = closestSnapping->adjustment;
		snappedToEntity = closestSnapping->entity;
		return true;
	}
	return false;
}
Beispiel #13
0
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.");
}
Beispiel #14
0
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());
			}
		}
	}

}
Beispiel #15
0
	WFMath::Point<3> SoundEntity::getPosition() const
	{
		WFMath::Point<3> pos = mParentEntity.getViewPosition();
		return pos.isValid() ? pos : WFMath::Point<3>::ZERO();
	}