//--------------------------------------------------------------------------------------- // # Skookum: Vector3@unrotate_by(Rotation rot) Vector3 // # Author(s): Markus Breyer static void mthd_unrotate_by(SkInvokedMethod * scope_p, SkInstance ** result_pp) { // Do nothing if result not desired if (result_pp) { const FVector & vec = scope_p->this_as<SkVector3>(); const FQuat rot = scope_p->get_arg<SkRotation>(SkArg_1); *result_pp = SkVector3::new_instance(rot.Inverse().RotateVector(vec)); } }
//--------------------------------------------------------------------------------------- // # Skookum: Vector3@unrotate_by(Rotation rot) Vector3 // # Author(s): Markus Breyer static void mthd_unrotate_by(SSInvokedMethod * scope_p, SSInstance ** result_pp) { // Do nothing if result not desired if (result_pp) { const FVector & vec = *scope_p->this_as<FVector>(); const FQuat rot = *scope_p->get_arg<FQuat>(SSArg_1); *result_pp = as_instance(rot.Inverse().RotateVector(vec)); } }
FVector FGearVR::GetNeckPosition(const FQuat& CurrentOrientation, const FVector& CurrentPosition, const FVector& PositionScale) { const auto frame = GetFrame(); if (!frame) { return FVector::ZeroVector; } FVector UnrotatedPos = CurrentOrientation.Inverse().RotateVector(CurrentPosition); UnrotatedPos.X -= frame->Settings->NeckToEyeInMeters.X * frame->WorldToMetersScale; UnrotatedPos.Z -= frame->Settings->NeckToEyeInMeters.Y * frame->WorldToMetersScale; return UnrotatedPos; }
FRotator UKismetMathLibrary::NegateRotator( FRotator A ) { FQuat AQuat = FQuat(A); return FRotator(AQuat.Inverse()); }
void FViewExtension::PreRenderView_RenderThread(FRHICommandListImmediate& RHICmdList, FSceneView& View) { check(IsInRenderingThread()); FViewExtension& RenderContext = *this; FGameFrame* CurrentFrame = static_cast<FGameFrame*>(RenderContext.RenderFrame.Get()); if (!RenderContext.ShowFlags.Rendering || !CurrentFrame || !CurrentFrame->Settings->IsStereoEnabled()) { return; } const ovrEyeType eyeIdx = (View.StereoPass == eSSP_LEFT_EYE) ? ovrEye_Left : ovrEye_Right; if (RenderContext.ShowFlags.Rendering && CurrentFrame->Settings->Flags.bUpdateOnRT) { FQuat CurrentEyeOrientation; FVector CurrentEyePosition; CurrentFrame->PoseToOrientationAndPosition(RenderContext.CurEyeRenderPose[eyeIdx], CurrentEyeOrientation, CurrentEyePosition); FQuat ViewOrientation = View.ViewRotation.Quaternion(); // recalculate delta control orientation; it should match the one we used in CalculateStereoViewOffset on a game thread. FVector GameEyePosition; FQuat GameEyeOrient; CurrentFrame->PoseToOrientationAndPosition(CurrentFrame->EyeRenderPose[eyeIdx], GameEyeOrient, GameEyePosition); const FQuat DeltaControlOrientation = ViewOrientation * GameEyeOrient.Inverse(); // make sure we use the same viewrotation as we had on a game thread check(View.ViewRotation == CurrentFrame->CachedViewRotation[eyeIdx]); if (CurrentFrame->Flags.bOrientationChanged) { // Apply updated orientation to corresponding View at recalc matrices. // The updated position will be applied from inside of the UpdateViewMatrix() call. const FQuat DeltaOrient = View.BaseHmdOrientation.Inverse() * CurrentEyeOrientation; View.ViewRotation = FRotator(ViewOrientation * DeltaOrient); //UE_LOG(LogHMD, Log, TEXT("VIEWDLT: Yaw %.3f Pitch %.3f Roll %.3f"), DeltaOrient.Rotator().Yaw, DeltaOrient.Rotator().Pitch, DeltaOrient.Rotator().Roll); } if (!CurrentFrame->Flags.bPositionChanged) { // if no positional change applied then we still need to calculate proper stereo disparity. // use the current head pose for this calculation instead of the one that was saved on a game thread. FQuat HeadOrientation; CurrentFrame->PoseToOrientationAndPosition(RenderContext.CurHeadPose, HeadOrientation, View.BaseHmdLocation); } // The HMDPosition already has HMD orientation applied. // Apply rotational difference between HMD orientation and ViewRotation // to HMDPosition vector. const FVector DeltaPosition = CurrentEyePosition - View.BaseHmdLocation; const FVector vEyePosition = DeltaControlOrientation.RotateVector(DeltaPosition) + CurrentFrame->Settings->PositionOffset; View.ViewLocation += vEyePosition; //UE_LOG(LogHMD, Log, TEXT("VDLTPOS: %.3f %.3f %.3f"), vEyePosition.X, vEyePosition.Y, vEyePosition.Z); if (CurrentFrame->Flags.bOrientationChanged || CurrentFrame->Flags.bPositionChanged) { View.UpdateViewMatrix(); } } FSettings* FrameSettings = CurrentFrame->GetSettings(); check(FrameSettings); FrameSettings->EyeLayer.EyeFov.RenderPose[eyeIdx] = RenderContext.CurEyeRenderPose[eyeIdx]; }
void vtIcoGlobe::CreateUnfoldableDymax() { int i; for (i = 0; i < 22; i++) { m_mface[i].xform = new vtTransform; m_mface[i].surfgroup = new vtGroup; m_mface[i].surfgroup->SetEnabled(false); m_mface[i].geode = new vtGeode; m_mface[i].xform->addChild(m_mface[i].geode); m_mface[i].xform->addChild(m_mface[i].surfgroup); vtString str; str.Format("IcoFace %d", i); m_mface[i].xform->setName(str); int face = dymax_subfaces[i].face; int subfaces = dymax_subfaces[i].subfaces; bool which; int mat = GetMaterialForFace(face, which); add_face2(m_mesh[i], face, i, subfaces, which); m_mface[i].geode->SetMaterials(m_earthmats); m_mface[i].geode->AddMesh(m_mesh[i], m_globe_mat[mat]); } m_top->addChild(m_mface[0].xform); m_mface[0].local_origin.Set(0,0,0); for (i = 1; i < 22; i++) FindLocalOrigin(i); for (i = 1; i < 22; i++) SetMeshConnect(i); // Determine necessary rotation to orient flat map toward viewer. FQuat qface; DPoint3 v0 = m_verts[icosa_face_v[0][0]]; DPoint3 v1 = m_verts[icosa_face_v[0][1]]; DPoint3 v2 = m_verts[icosa_face_v[0][2]]; // Create a rotation to turn the globe so that a specific edge // is pointed down -X for proper map orientation DPoint3 edge = v2 - v0; edge.Normalize(); // compose face norm and face quaternion DPoint3 fnorm = (v0 + v1 + v2).Normalize(); qface.SetFromVectors(edge, fnorm); // desired vector points down -X FQuat qdesired; qdesired.SetFromVectors(FPoint3(-1,0,0),FPoint3(0,0,1)); // determine rotational difference m_diff = qface.Inverse() * qdesired; #if 0 // scaffolding mesh for debugging vtMesh *sm = new vtMesh(GL_LINES, VT_Colors, 12); sm->AddVertex(v0*1.0001f); sm->AddVertex(v1*1.0001f); sm->AddVertex(v2*1.0001f); sm->AddVertex(v0*1.0001f+fnorm); sm->SetVtxColor(0, RGBf(1,0,0)); sm->SetVtxColor(1, RGBf(0,1,0)); sm->SetVtxColor(2, RGBf(0,0,1)); sm->SetVtxColor(3, RGBf(1,1,0)); sm->AddLine(0,1); sm->AddLine(0,2); sm->AddLine(0,3); m_geom[0]->AddMesh(sm, m_red); sm->Release(); #endif // Show axis of rotation (north and south poles) vtMaterialArray *pMats = new vtMaterialArray; int green = pMats->AddRGBMaterial1(RGBf(0,1,0), false, false); m_pAxisGeom = new vtGeode; m_pAxisGeom->setName("AxisGeom"); m_pAxisGeom->SetMaterials(pMats); m_pAxisGeom->SetEnabled(false); vtMesh *pMesh = new vtMesh(osg::PrimitiveSet::LINES, 0, 6); pMesh->AddVertex(FPoint3(0,2,0)); pMesh->AddVertex(FPoint3(0,-2,0)); pMesh->AddLine(0,1); m_pAxisGeom->AddMesh(pMesh, green); m_top->addChild(m_pAxisGeom); #if 0 axis = WireAxis(RGBf(1,1,1), 1.1f); m_top->addChild(axis); #endif }
void FLeapMotionInputDevice::ParseEvents() { //Optimization: If we don't have any delegates, skip if (EventDelegates.Num() == 0) { return; } //Pointers Leap::Frame Frame = ControllerData.LeapController.frame(); Leap::Frame PastFrame = ControllerData.LeapController.frame(1); //Calculate HMD Timewarp if valid if (GEngine->HMDDevice.IsValid() && ControllerData.bTimeWarpEnabled) { LeapHMDSnapshot ThenSnapshot = HMDSamples->HMDSampleClosestToTimestamp(Frame.timestamp()); LeapHMDSnapshot NowSnapShot = HMDSamples->CurrentHMDSample(); LeapHMDSnapshot HistorySnapshot = HMDSamples->LastHMDSample(); //reduce jitter //ControllerData.TimeWarpSnapshot = NowSnapShot.Difference(ThenSnapshot, ControllerData.TimeWarpFactor);// * ControllerData.TimeWarpFactor; FQuat WarpQuat = NowSnapShot.Orientation;//FQuat::Slerp(NowSnapShot.Orientation, HistorySnapshot.Orientation, ControllerData.TimeWarpTween); FQuat ThenTweened = FQuat::Slerp(ThenSnapshot.Orientation, HistorySnapshot.Orientation, ControllerData.TimeWarpTween); ControllerData.TimeWarpSnapshot.Orientation = (WarpQuat.Inverse() * ControllerData.TimeWarpFactor) * ThenTweened; ControllerData.TimeWarpAmountMs = (ControllerData.TimeWarpSnapshot.Timestamp) / 1000.f; } //-Hands- //Hand Count int HandCount = Frame.hands().count(); if (PastState->HandCount != HandCount) { CallFunctionOnDelegates([&](UObject* EventDelegate) { ILeapEventInterface::Execute_HandCountChanged(EventDelegate, HandCount); }); //Zero our input mapping orientations (akin to letting go of a joystick) if (HandCount == 0) { EmitAnalogInputEventForKey(EKeysLeap::LeapLeftPalmPitch, 0, 0, 0); EmitAnalogInputEventForKey(EKeysLeap::LeapLeftPalmYaw, 0, 0, 0); EmitAnalogInputEventForKey(EKeysLeap::LeapLeftPalmRoll, 0, 0, 0); EmitAnalogInputEventForKey(EKeysLeap::LeapRightPalmPitch, 0, 0, 0); EmitAnalogInputEventForKey(EKeysLeap::LeapRightPalmYaw, 0, 0, 0); EmitAnalogInputEventForKey(EKeysLeap::LeapRightPalmRoll, 0, 0, 0); } } //Cycle through each hand for (int i = 0; i < HandCount; i++) { Leap::Hand Hand = Frame.hands()[i]; LeapHandStateData PastHandState = PastState->StateForId(Hand.id()); //we use a custom class to hold reliable state tracking based on id's //Make a ULeapHand if (PEventHand == nullptr) { PEventHand = NewObject<ULeapHand>(); PEventHand->AddToRoot(); } PEventHand->SetHand(Hand); //Emit hand CallFunctionOnDelegates([&](UObject* EventDelegate) { ILeapEventInterface::Execute_LeapHandMoved(EventDelegate, PEventHand); }); //Left/Right hand forwarding if (Hand.isRight()) { CallFunctionOnDelegates([&](UObject* EventDelegate) { ILeapEventInterface::Execute_LeapRightHandMoved(EventDelegate, PEventHand); }); //Input Mapping FRotator PalmOrientation = PEventHand->PalmOrientation; EmitAnalogInputEventForKey(EKeysLeap::LeapRightPalmPitch, PalmOrientation.Pitch * LEAP_IM_SCALE, 0, 0); EmitAnalogInputEventForKey(EKeysLeap::LeapRightPalmYaw, PalmOrientation.Yaw * LEAP_IM_SCALE, 0, 0); EmitAnalogInputEventForKey(EKeysLeap::LeapRightPalmRoll, PalmOrientation.Roll * LEAP_IM_SCALE, 0, 0); } else if (Hand.isLeft()) { CallFunctionOnDelegates([&](UObject* EventDelegate) { ILeapEventInterface::Execute_LeapLeftHandMoved(EventDelegate, PEventHand); }); //Input Mapping FRotator PalmOrientation = PEventHand->PalmOrientation; EmitAnalogInputEventForKey(EKeysLeap::LeapLeftPalmPitch, PalmOrientation.Pitch * LEAP_IM_SCALE, 0, 0); EmitAnalogInputEventForKey(EKeysLeap::LeapLeftPalmYaw, PalmOrientation.Yaw * LEAP_IM_SCALE, 0, 0); EmitAnalogInputEventForKey(EKeysLeap::LeapLeftPalmRoll, PalmOrientation.Roll * LEAP_IM_SCALE, 0, 0); } //Grabbing float GrabStrength = Hand.grabStrength(); bool Grabbed = HandClosed(GrabStrength); if (Grabbed) { CallFunctionOnDelegates([&](UObject* EventDelegate) { ILeapEventInterface::Execute_LeapHandGrabbing(EventDelegate, GrabStrength, PEventHand); }); } if (Grabbed && !PastHandState.Grabbed) { CallFunctionOnDelegates([&](UObject* EventDelegate) { ILeapEventInterface::Execute_LeapHandGrabbed(EventDelegate, GrabStrength, PEventHand); }); //input mapping if (PEventHand->HandType == LeapHandType::HAND_LEFT) { EmitKeyDownEventForKey(EKeysLeap::LeapLeftGrab, 0, 0); } else { EmitKeyDownEventForKey(EKeysLeap::LeapRightGrab, 0, 0); } } else if (!Grabbed && PastHandState.Grabbed) { CallFunctionOnDelegates([&](UObject* EventDelegate) { ILeapEventInterface::Execute_LeapHandReleased(EventDelegate, GrabStrength, PEventHand); }); //input mapping if (PEventHand->HandType == LeapHandType::HAND_LEFT) { EmitKeyUpEventForKey(EKeysLeap::LeapLeftGrab, 0, 0); } else { EmitKeyUpEventForKey(EKeysLeap::LeapRightGrab, 0, 0); } } //Pinching float PinchStrength = Hand.pinchStrength(); bool Pinched = HandPinched(PinchStrength); //While grabbing disable pinching detection, this helps to reduce spam as pose confidence plummets if (Grabbed) { Pinched = PastHandState.Pinched; } else { if (Pinched) { CallFunctionOnDelegates([&](UObject* EventDelegate) { ILeapEventInterface::Execute_LeapHandPinching(EventDelegate, PinchStrength, PEventHand); }); } if (Pinched && !PastHandState.Pinched) { CallFunctionOnDelegates([&](UObject* EventDelegate) { ILeapEventInterface::Execute_LeapHandPinched(EventDelegate, PinchStrength, PEventHand); }); //input mapping if (PEventHand->HandType == LeapHandType::HAND_LEFT) { EmitKeyDownEventForKey(EKeysLeap::LeapLeftPinch, 0, 0); } else { EmitKeyDownEventForKey(EKeysLeap::LeapRightPinch, 0, 0); } } else if (!Pinched && PastHandState.Pinched) { CallFunctionOnDelegates([&](UObject* EventDelegate) { ILeapEventInterface::Execute_LeapHandUnpinched(EventDelegate, PinchStrength, PEventHand); }); //input mapping if (PEventHand->HandType == LeapHandType::HAND_LEFT) { EmitKeyUpEventForKey(EKeysLeap::LeapLeftPinch, 0, 0); } else { EmitKeyUpEventForKey(EKeysLeap::LeapRightPinch, 0, 0); } } } //-Fingers- Leap::FingerList Fingers = Hand.fingers(); //Count int FingerCount = Fingers.count(); if ((PastHandState.FingerCount != FingerCount)) { CallFunctionOnDelegates([&](UObject* EventDelegate) { ILeapEventInterface::Execute_FingerCountChanged(EventDelegate, FingerCount); }); } if (PEventFinger == nullptr) { PEventFinger = NewObject<ULeapFinger>(); PEventFinger->AddToRoot(); } Leap::Finger Finger; //Cycle through each finger for (int j = 0; j < FingerCount; j++) { Finger = Fingers[j]; PEventFinger->SetFinger(Finger); //Finger Moved if (Finger.isValid()) { CallFunctionOnDelegates([&](UObject* EventDelegate) { ILeapEventInterface::Execute_LeapFingerMoved(EventDelegate, PEventFinger); }); } } //Do these last so we can easily override debug shapes //Leftmost Finger = Fingers.leftmost(); PEventFinger->SetFinger(Finger); CallFunctionOnDelegates([&](UObject* EventDelegate) { ILeapEventInterface::Execute_LeapLeftMostFingerMoved(EventDelegate, PEventFinger); }); //Rightmost Finger = Fingers.rightmost(); PEventFinger->SetFinger(Finger); CallFunctionOnDelegates([&](UObject* EventDelegate) { ILeapEventInterface::Execute_LeapRightMostFingerMoved(EventDelegate, PEventFinger); }); //Frontmost Finger = Fingers.frontmost(); PEventFinger->SetFinger(Finger); CallFunctionOnDelegates([&](UObject* EventDelegate) { ILeapEventInterface::Execute_LeapFrontMostFingerMoved(EventDelegate, PEventFinger); }); //touch only for front-most finger, most common use case float touchDistance = Finger.touchDistance(); if (touchDistance <= 0.f) { CallFunctionOnDelegates([&](UObject* EventDelegate) { ILeapEventInterface::Execute_LeapFrontFingerTouch(EventDelegate, PEventFinger); }); } //Set the state data for next cycle PastHandState.Grabbed = Grabbed; PastHandState.Pinched = Pinched; PastHandState.FingerCount = FingerCount; PastState->SetStateForId(PastHandState, Hand.id()); } PastState->HandCount = HandCount; //Gestures for (int i = 0; i < Frame.gestures().count(); i++) { Leap::Gesture Gesture = Frame.gestures()[i]; Leap::Gesture::Type Type = Gesture.type(); switch (Type) { case Leap::Gesture::TYPE_CIRCLE: if (PEventCircleGesture == nullptr) { PEventCircleGesture = NewObject<ULeapCircleGesture>(); PEventCircleGesture->AddToRoot(); } PEventCircleGesture->SetGesture(Leap::CircleGesture(Gesture)); CallFunctionOnDelegates([&](UObject* EventDelegate) { ILeapEventInterface::Execute_CircleGestureDetected(EventDelegate, PEventCircleGesture); }); PEventGesture = PEventCircleGesture; break; case Leap::Gesture::TYPE_KEY_TAP: if (PEventKeyTapGesture == nullptr) { PEventKeyTapGesture = NewObject<ULeapKeyTapGesture>(); PEventKeyTapGesture->AddToRoot(); } PEventKeyTapGesture->SetGesture(Leap::KeyTapGesture(Gesture)); CallFunctionOnDelegates([&](UObject* EventDelegate) { ILeapEventInterface::Execute_KeyTapGestureDetected(EventDelegate, PEventKeyTapGesture); }); PEventGesture = PEventKeyTapGesture; break; case Leap::Gesture::TYPE_SCREEN_TAP: if (PEventScreenTapGesture == nullptr) { PEventScreenTapGesture = NewObject<ULeapScreenTapGesture>(); PEventScreenTapGesture->AddToRoot(); } PEventScreenTapGesture->SetGesture(Leap::ScreenTapGesture(Gesture)); CallFunctionOnDelegates([&](UObject* EventDelegate) { ILeapEventInterface::Execute_ScreenTapGestureDetected(EventDelegate, PEventScreenTapGesture); }); PEventGesture = PEventScreenTapGesture; break; case Leap::Gesture::TYPE_SWIPE: if (PEventSwipeGesture == nullptr) { PEventSwipeGesture = NewObject<ULeapSwipeGesture>(); PEventSwipeGesture->AddToRoot(); } PEventSwipeGesture->SetGesture(Leap::SwipeGesture(Gesture)); CallFunctionOnDelegates([&](UObject* EventDelegate) { ILeapEventInterface::Execute_SwipeGestureDetected(EventDelegate, PEventSwipeGesture); }); PEventGesture = PEventSwipeGesture; break; default: break; } //emit gesture if (Type != Leap::Gesture::TYPE_INVALID) { CallFunctionOnDelegates([&](UObject* EventDelegate) { ILeapEventInterface::Execute_GestureDetected(EventDelegate, PEventGesture); }); } } //Image if (ControllerData.bAllowImageEvents && ControllerData.bImageEventsEnabled) { int ImageCount = Frame.images().count(); //We only support getting both images if (ImageCount >= 2) { Leap::Image Image1 = Frame.images()[0]; if (PEventImage1 == nullptr) { PEventImage1 = NewObject<ULeapImage>(); PEventImage1->AddToRoot(); } PEventImage1->UseGammaCorrection = ControllerData.bUseGammaCorrection; PEventImage1->SetLeapImage(Image1); CallFunctionOnDelegates([&](UObject* EventDelegate) { ILeapEventInterface::Execute_RawImageReceived(EventDelegate, PEventImage1->Texture(), PEventImage1); }); Leap::Image Image2 = Frame.images()[1]; if (PEventImage2 == nullptr) { PEventImage2 = NewObject<ULeapImage>(); PEventImage2->AddToRoot(); } PEventImage2->UseGammaCorrection = ControllerData.bUseGammaCorrection; PEventImage2->SetLeapImage(Image2); CallFunctionOnDelegates([&](UObject* EventDelegate) { ILeapEventInterface::Execute_RawImageReceived(EventDelegate, PEventImage2->Texture(), PEventImage2); }); } } }