void EntitySimulation::changeEntityInternal(EntityItemPointer entity) { if (entity->isMoving() && !entity->getPhysicsInfo()) { _simpleKinematicEntities.insert(entity); } else { _simpleKinematicEntities.remove(entity); } }
// Note: The "type" property is set in EntityItem::getActionArguments(). QVariantMap ObjectDynamic::getArguments() { QVariantMap arguments; withReadLock([&]{ if (_expires == 0) { arguments["ttl"] = 0.0f; } else { quint64 now = usecTimestampNow(); arguments["ttl"] = (float)(_expires - now) / (float)USECS_PER_SECOND; } arguments["tag"] = _tag; EntityItemPointer entity = _ownerEntity.lock(); if (entity) { ObjectMotionState* motionState = static_cast<ObjectMotionState*>(entity->getPhysicsInfo()); if (motionState) { arguments["::active"] = motionState->isActive(); arguments["::motion-type"] = motionTypeToString(motionState->getMotionType()); } else { arguments["::no-motion-state"] = true; } } arguments["isMine"] = isMine(); }); return arguments; }
void EntitySimulation::addEntityInternal(EntityItemPointer entity) { if (entity->isMovingRelativeToParent() && !entity->getPhysicsInfo()) { QMutexLocker lock(&_mutex); _simpleKinematicEntities.insert(entity); entity->setLastSimulated(usecTimestampNow()); } }
VectorOfMotionStates& PhysicalEntitySimulation::getObjectsToAdd() { _tempVector.clear(); SetOfEntities::iterator entityItr = _pendingAdds.begin(); while (entityItr != _pendingAdds.end()) { EntityItemPointer entity = *entityItr; assert(!entity->getPhysicsInfo()); if (!entity->shouldBePhysical()) { // this entity should no longer be on the internal _pendingAdds entityItr = _pendingAdds.erase(entityItr); if (entity->isMoving()) { _simpleKinematicEntities.insert(entity); } } else if (entity->isReadyToComputeShape()) { ShapeInfo shapeInfo; entity->computeShapeInfo(shapeInfo); btCollisionShape* shape = ObjectMotionState::getShapeManager()->getShape(shapeInfo); if (shape) { EntityMotionState* motionState = new EntityMotionState(shape, entity); entity->setPhysicsInfo(static_cast<void*>(motionState)); _physicalObjects.insert(motionState); _tempVector.push_back(motionState); entityItr = _pendingAdds.erase(entityItr); } else { //qDebug() << "Warning! Failed to generate new shape for entity." << entity->getName(); ++entityItr; } } else { ++entityItr; } } return _tempVector; }
void PhysicalEntitySimulation::getObjectsToAddToPhysics(VectorOfMotionStates& result) { result.clear(); QMutexLocker lock(&_mutex); SetOfEntities::iterator entityItr = _entitiesToAddToPhysics.begin(); while (entityItr != _entitiesToAddToPhysics.end()) { EntityItemPointer entity = (*entityItr); assert(!entity->getPhysicsInfo()); if (entity->isDead()) { prepareEntityForDelete(entity); } else if (!entity->shouldBePhysical()) { // this entity should no longer be on the internal _entitiesToAddToPhysics entityItr = _entitiesToAddToPhysics.erase(entityItr); if (entity->isMoving()) { _simpleKinematicEntities.insert(entity); } } else if (entity->isReadyToComputeShape()) { ShapeInfo shapeInfo; entity->computeShapeInfo(shapeInfo); btCollisionShape* shape = ObjectMotionState::getShapeManager()->getShape(shapeInfo); if (shape) { EntityMotionState* motionState = new EntityMotionState(shape, entity); entity->setPhysicsInfo(static_cast<void*>(motionState)); _physicalObjects.insert(motionState); result.push_back(motionState); entityItr = _entitiesToAddToPhysics.erase(entityItr); } else { //qDebug() << "Warning! Failed to generate new shape for entity." << entity->getName(); ++entityItr; } } else { ++entityItr; } } }
void PhysicalEntitySimulation::changeEntityInternal(EntityItemPointer entity) { // queue incoming changes: from external sources (script, EntityServer, etc) to physics engine assert(entity); EntityMotionState* motionState = static_cast<EntityMotionState*>(entity->getPhysicsInfo()); if (motionState) { if (!entity->shouldBePhysical()) { // the entity should be removed from the physical simulation _pendingChanges.remove(motionState); _physicalObjects.remove(motionState); _pendingRemoves.insert(motionState); _outgoingChanges.remove(motionState); if (entity->isMoving()) { _simpleKinematicEntities.insert(entity); } } else { _pendingChanges.insert(motionState); } } else if (entity->shouldBePhysical()) { // The intent is for this object to be in the PhysicsEngine, but it has no MotionState yet. // Perhaps it's shape has changed and it can now be added? _pendingAdds.insert(entity); _simpleKinematicEntities.remove(entity); // just in case it's non-physical-kinematic } else if (entity->isMoving()) { _simpleKinematicEntities.insert(entity); } else { _simpleKinematicEntities.remove(entity); // just in case it's non-physical-kinematic } }
void EntitySimulation::changeEntityInternal(EntityItemPointer entity) { QMutexLocker lock(&_mutex); if (entity->isMovingRelativeToParent() && !entity->getPhysicsInfo()) { _simpleKinematicEntities.insert(entity); } else { _simpleKinematicEntities.remove(entity); } }
void PhysicalEntitySimulation::removeEntityInternal(EntityItemPointer entity) { EntityMotionState* motionState = static_cast<EntityMotionState*>(entity->getPhysicsInfo()); if (motionState) { motionState->clearObjectBackPointer(); entity->setPhysicsInfo(nullptr); _pendingRemoves.insert(motionState); _outgoingChanges.remove(motionState); } _pendingAdds.remove(entity); }
void PhysicalEntitySimulation::addEntityInternal(EntityItemPointer entity) { assert(entity); if (entity->shouldBePhysical()) { EntityMotionState* motionState = static_cast<EntityMotionState*>(entity->getPhysicsInfo()); if (!motionState) { _pendingAdds.insert(entity); } } else if (entity->isMoving()) { _simpleKinematicEntities.insert(entity); } }
void EntitySimulation::changeEntityInternal(EntityItemPointer entity) { QMutexLocker lock(&_mutex); if (entity->isMovingRelativeToParent() && !entity->getPhysicsInfo()) { int numKinematicEntities = _simpleKinematicEntities.size(); _simpleKinematicEntities.insert(entity); if (numKinematicEntities != _simpleKinematicEntities.size()) { entity->setLastSimulated(usecTimestampNow()); } } else { _simpleKinematicEntities.remove(entity); } }
void PhysicalEntitySimulation::removeEntityInternal(EntityItemPointer entity) { EntitySimulation::removeEntityInternal(entity); QMutexLocker lock(&_mutex); _entitiesToAddToPhysics.remove(entity); EntityMotionState* motionState = static_cast<EntityMotionState*>(entity->getPhysicsInfo()); if (motionState) { _outgoingChanges.remove(motionState); _entitiesToRemoveFromPhysics.insert(entity); } else { _entitiesToDelete.insert(entity); } }
void PhysicalEntitySimulation::addEntityInternal(EntityItemPointer entity) { QMutexLocker lock(&_mutex); assert(entity); assert(!entity->isDead()); if (entity->shouldBePhysical()) { EntityMotionState* motionState = static_cast<EntityMotionState*>(entity->getPhysicsInfo()); if (!motionState) { _entitiesToAddToPhysics.insert(entity); } } else if (entity->isMoving()) { _simpleKinematicEntities.insert(entity); } }
void EntitySimulation::moveSimpleKinematics(const quint64& now) { SetOfEntities::iterator itemItr = _simpleKinematicEntities.begin(); while (itemItr != _simpleKinematicEntities.end()) { EntityItemPointer entity = *itemItr; if (entity->isMoving() && !entity->getPhysicsInfo()) { entity->simulate(now); _entitiesToSort.insert(entity); ++itemItr; } else { // the entity is no longer non-physical-kinematic itemItr = _simpleKinematicEntities.erase(itemItr); } } }
btRigidBody* ObjectDynamic::getOtherRigidBody(EntityItemID otherEntityID) { EntityItemPointer otherEntity = getEntityByID(otherEntityID); if (!otherEntity) { return nullptr; } void* otherPhysicsInfo = otherEntity->getPhysicsInfo(); if (!otherPhysicsInfo) { return nullptr; } ObjectMotionState* otherMotionState = static_cast<ObjectMotionState*>(otherPhysicsInfo); if (!otherMotionState) { return nullptr; } return otherMotionState->getRigidBody(); }
void EntitySimulation::moveSimpleKinematics(const quint64& now) { SetOfEntities::iterator itemItr = _simpleKinematicEntities.begin(); while (itemItr != _simpleKinematicEntities.end()) { EntityItemPointer entity = *itemItr; // The entity-server doesn't know where avatars are, so don't attempt to do simple extrapolation for // children of avatars. See related code in EntityMotionState::remoteSimulationOutOfSync. bool ancestryIsKnown; entity->getMaximumAACube(ancestryIsKnown); bool hasAvatarAncestor = entity->hasAncestorOfType(NestableType::Avatar); if (entity->isMovingRelativeToParent() && !entity->getPhysicsInfo() && ancestryIsKnown && !hasAvatarAncestor) { entity->simulate(now); _entitiesToSort.insert(entity); ++itemItr; } else { // the entity is no longer non-physical-kinematic itemItr = _simpleKinematicEntities.erase(itemItr); } } }
void EntityRenderer::makeStatusGetters(const EntityItemPointer& entity, Item::Status::Getters& statusGetters) { auto nodeList = DependencyManager::get<NodeList>(); const QUuid& myNodeID = nodeList->getSessionUUID(); statusGetters.push_back([entity]() -> render::Item::Status::Value { uint64_t delta = usecTimestampNow() - entity->getLastEditedFromRemote(); const float WAIT_THRESHOLD_INV = 1.0f / (0.2f * USECS_PER_SECOND); float normalizedDelta = delta * WAIT_THRESHOLD_INV; // Status icon will scale from 1.0f down to 0.0f after WAIT_THRESHOLD // Color is red if last update is after WAIT_THRESHOLD, green otherwise (120 deg is green) return render::Item::Status::Value(1.0f - normalizedDelta, (normalizedDelta > 1.0f ? render::Item::Status::Value::GREEN : render::Item::Status::Value::RED), (unsigned char)RenderItemStatusIcon::PACKET_RECEIVED); }); statusGetters.push_back([entity] () -> render::Item::Status::Value { uint64_t delta = usecTimestampNow() - entity->getLastBroadcast(); const float WAIT_THRESHOLD_INV = 1.0f / (0.4f * USECS_PER_SECOND); float normalizedDelta = delta * WAIT_THRESHOLD_INV; // Status icon will scale from 1.0f down to 0.0f after WAIT_THRESHOLD // Color is Magenta if last update is after WAIT_THRESHOLD, cyan otherwise (180 deg is green) return render::Item::Status::Value(1.0f - normalizedDelta, (normalizedDelta > 1.0f ? render::Item::Status::Value::MAGENTA : render::Item::Status::Value::CYAN), (unsigned char)RenderItemStatusIcon::PACKET_SENT); }); statusGetters.push_back([entity] () -> render::Item::Status::Value { ObjectMotionState* motionState = static_cast<ObjectMotionState*>(entity->getPhysicsInfo()); if (motionState && motionState->isActive()) { return render::Item::Status::Value(1.0f, render::Item::Status::Value::BLUE, (unsigned char)RenderItemStatusIcon::ACTIVE_IN_BULLET); } return render::Item::Status::Value(0.0f, render::Item::Status::Value::BLUE, (unsigned char)RenderItemStatusIcon::ACTIVE_IN_BULLET); }); statusGetters.push_back([entity, myNodeID] () -> render::Item::Status::Value { bool weOwnSimulation = entity->getSimulationOwner().matchesValidID(myNodeID); bool otherOwnSimulation = !weOwnSimulation && !entity->getSimulationOwner().isNull(); if (weOwnSimulation) { return render::Item::Status::Value(1.0f, render::Item::Status::Value::BLUE, (unsigned char)RenderItemStatusIcon::SIMULATION_OWNER); } else if (otherOwnSimulation) { return render::Item::Status::Value(1.0f, render::Item::Status::Value::RED, (unsigned char)RenderItemStatusIcon::OTHER_SIMULATION_OWNER); } return render::Item::Status::Value(0.0f, render::Item::Status::Value::BLUE, (unsigned char)RenderItemStatusIcon::SIMULATION_OWNER); }); statusGetters.push_back([entity] () -> render::Item::Status::Value { if (entity->hasActions()) { return render::Item::Status::Value(1.0f, render::Item::Status::Value::GREEN, (unsigned char)RenderItemStatusIcon::HAS_ACTIONS); } return render::Item::Status::Value(0.0f, render::Item::Status::Value::GREEN, (unsigned char)RenderItemStatusIcon::HAS_ACTIONS); }); statusGetters.push_back([entity, myNodeID] () -> render::Item::Status::Value { if (entity->getClientOnly()) { if (entity->getOwningAvatarID() == myNodeID) { return render::Item::Status::Value(1.0f, render::Item::Status::Value::GREEN, (unsigned char)RenderItemStatusIcon::CLIENT_ONLY); } else { return render::Item::Status::Value(1.0f, render::Item::Status::Value::RED, (unsigned char)RenderItemStatusIcon::CLIENT_ONLY); } } return render::Item::Status::Value(0.0f, render::Item::Status::Value::GREEN, (unsigned char)RenderItemStatusIcon::CLIENT_ONLY); }); }
void EntitySimulation::addEntityInternal(EntityItemPointer entity) { if (entity->isMoving() && !entity->getPhysicsInfo()) { QMutexLocker lock(&_mutex); _simpleKinematicEntities.insert(entity); } }