Skip to main content
Up and Coming
April 28, 2013

Changing pitch/roll?

Has anyone had any luck changing the pitch and roll independent of the head tracking? It seems to be impossible. Always using the pitch / roll of the head tracker might work well for FPS's but not for everything. For instance, in an airplane game, if the plane does a barrel roll. With the current implementation, it's impossible to make the player do a barrel roll.
    This topic has been closed for replies.

    29 replies

    Up and Coming
    October 24, 2013
    In September OUDK, it is possible to prevent HMD from updating player's viewpoint. You need to call Oculus.EnablePlayerViewUpdating(false). After this you can update your camera position manually (see the post of 'centurionwithatophat ' above: you can use Oculus.GetCurrentOrientation to get current HMD orientation Quaternion (you can convert it to Rotator, if you'd like)).
    For the cockpit-style games you may use Oculus.GetAdjustedOrientation() instead of GetCurrentOrientation(): the difference is that you can reset to the 'forward direction' by calling ResetMotionInput().
    Let me know if there are any issues with this approach.
    boone188Author
    Up and Coming
    October 29, 2013
    This is really great news. When I get some time (really tough with work and all the projects I have going on) I will implement this in RiftCoaster.
    Up and Coming
    November 20, 2013
    "artyom17" wrote:
    In September OUDK, it is possible to prevent HMD from updating player's viewpoint. You need to call Oculus.EnablePlayerViewUpdating(false)....

    For the cockpit-style games you may use Oculus.GetAdjustedOrientation()


    I did a seach in UnCodeX for EnablePlayerViewUpdating but found nothing. Is this a hidden function? Same with GetAdjustedOrientation. Or am I being thick? :?

    EDIT: I was being thick :oops:
    Up and Coming
    December 23, 2013
    Here's a dirty rough way to get a cockpit style game working with Oculus Rift. You can yaw, pitch, roll the pawn and also look around the cockpit while this yawing and pitching and rolling is going on. Obviously there's a lot of refinement to be made and obviously you'll need your own pawn mesh with a cockpit mesh attached or whatever. In this example I'm just using the default SkeletalMesh'CH_LIAM_Cathode.Mesh.SK_CH_LIAM_Cathode' character.

    Thanks to

    slowJusko, centurionwithatophat (see earlier post on page 1) , UDK: Six Degrees of Freedom by Maximilian Schulz

    for tips.

    I haven't implemented any gamepad controls (or at least I haven't purposefully) and I haven't
    checked to see if controller works. I have used the keyboard and mouse.

    *****************************************************************************

    First, a couple of checks.

    Modify UDKInput.ini (in ..\<UDK install dir>\UDKGame\Config) to have the following bindings.

    [Engine.PlayerInput]
    .
    .
    .
    Bindings=(Name="GBA_RollLeft",Command="Axis aBaseZ Speed=+200.0")
    Bindings=(Name="GBA_RollRight",Command="Axis aBaseZ Speed=-200.0")
    .
    .
    .
    Bindings=(Name="E",Command="GBA_RollRight")
    Bindings=(Name="Q",Command="GBA_RollLeft")
    .
    .
    .
    ========================

    And in UDKEngine.ini under [Engine.Oculus] make sure MouseAimMode is set as

    MouseAimMode=OMA_Separate

    (you can set to =OMA_Normal if you wish but I prefer OMA_Seperate which allows you more shooting freedom)

    =======================

    And also in UDKEngine.ini under [UnrealEd.EditorEngine] add

    ModEditPackages=CameraTest

    to the end of that section.

    ========================


    Create a directory under ..\<UDK install dir>\Development\Src called CameraTest.

    In that directory create a directory called Classes

    In that directory create three files called "CameraTest.uc" , "CameraTestPawn.uc", and "CameraTestPlayerController.uc"

    Copy and paste the following into those files:


    CameraTest.uc

    class CameraTest extends UTDeathMatch;

    function RestartPlayer(Controller aPlayer)
    {
    super.RestartPlayer(aPlayer);
    if (aPlayer.Pawn != none)
    aPlayer.Pawn.SetPhysics(PHYS_Flying);
    }

    defaultproperties
    {
    DefaultPawnClass=class'CameraTest.CameraTestPawn'
    PlayerControllerClass=class'CameraTest.CameraTestPlayerController'

    }


    CameraTestPawn.uc

    class CameraTestPawn extends UTPawn;

    var name EyeSocket;
    /*
    CalcCamera

    Called from UTPlayerController::GetPlayerViewPoint(),
    which is called by the current camera.
    */
    simulated function bool CalcCamera( float fDeltaTime, out vector out_CamLoc, out rotator out_CamRot, out float out_FOV )
    {
    local bool bCameraCalc;

    // if we are the local player, make sure our head is normal size.
    // This will make it visible again in third person views and give us the correct bone positions later.
    // NOTE: A better way to do this is to make sure the head is a separate mesh/component and stop it being rendered to the owner.
    if (WorldInfo.NetMode != NM_DedicatedServer && IsHumanControlled() && IsLocallyControlled() && (HeadScale != 1.0f))
    {
    SetHeadScale(1.0f);

    // since we've just un-shrunk the head, force the skeleton to update, just in case
    Mesh.ForceSkelUpdate();
    }

    // Call the proper CalcCamera function and remember the result
    bCameraCalc = Super.CalcCamera(fDeltaTime, out_CamLoc, out_CamRot, out_FOV);

    // now that we've run the proper calcs, shrink the head again,
    // but only if we're the local player and in a first person view
    if (WorldInfo.NetMode != NM_DedicatedServer && IsHumanControlled() && IsLocallyControlled() && IsFirstPerson() && !bFixedView)
    {
    SetHeadScale(0.0f);

    // force the skeleton to update, just in case
    Mesh.ForceSkelUpdate();
    }

    // send the result back to UTPlayerController::GetPlayerViewPoint()...
    return bCameraCalc;
    }

    /*
    GetPawnViewLocation

    Someone wants the position of our eyes - lets give it to them.
    Its probably CalcCamera() anyway (see above).
    */
    simulated event Vector GetPawnViewLocation()
    {
    local vector viewLoc;

    // no eye socket? No way I can tell you a location based on this socket then...
    if (EyeSocket == '')
    return Location + BaseEyeHeight * vect(0,0,1);

    // HACK - force the first person weapon and arm models to hide
    // NOTE: You should remove all first person only weapon/arm meshes instead.
    SetWeaponVisibility(false);

    // HACK - force the world model and attachments to be visible
    // NOTE: You should make sure the mesh/attachments are always rendered.
    SetMeshVisibility(true);

    Mesh.GetSocketWorldLocationAndRotation(EyeSocket, viewLoc);

    return viewLoc;
    }

    /*
    Dying

    Instead of switching to a third person view,
    match the camera to the location and rotation of the eye socket.
    */
    simulated State Dying
    {
    // skip UTPawn's fancy damage/third person views
    simulated function bool CalcCamera( float fDeltaTime, out vector out_CamLoc, out rotator out_CamRot, out float out_FOV )
    {
    return Global.CalcCamera(fDeltaTime, out_CamLoc, out_CamRot, out_FOV);
    }

    /*
    GetViewRotation
    */
    simulated event rotator GetViewRotation()
    {
    local vector out_Loc;
    local rotator out_Rot;

    // no eye socket? No way I can tell you a rotation based on this socket then...
    if (EyeSocket == '')
    return Super.GetViewRotation();

    Mesh.GetSocketWorldLocationAndRotation(EyeSocket, out_Loc, out_Rot);

    return out_Rot;
    }
    }

    DefaultProperties
    {
    EyeSocket=Eyes

    // Allow full pitch circle
    ViewPitchMin=-32767
    ViewPitchMax=32767

    bRollToDesired = true // allows pawn to roll
    AirSpeed = 800.0 // maximum speed
    AccelRate = 800.0 // acceleration speed
    }




    CameraTestPlayerController.uc

    class CameraTestPlayerController extends UTPlayerController;

    var Oculus _OC;
    var PlayerController fakeController;

    simulated function PostBeginPlay()
    {
    super.PostBeginPlay();
    fakeController=Spawn(class'PlayerController');
    _OC = new class'Oculus';

    }
    // Player movement.
    // Player Standing, walking, running, falling.
    state PlayerWalking
    {
    ignores SeePlayer, HearNoise, Bump;


    function ProcessMove(float DeltaTime, vector NewAccel, eDoubleClickDir DoubleClickMove, rotator DeltaRot)
    {

    if( Pawn == None )
    {
    return;
    }

    if (Role == ROLE_Authority)
    {
    // Update ViewPitch for remote clients
    Pawn.SetRemoteViewPitch( Rotation.Pitch );
    }

    Pawn.Acceleration = NewAccel;

    CheckJumpOrDuck();
    }

    function PlayerMove( float DeltaTime )
    {
    local vector X,Y,Z, NewAccel;
    local eDoubleClickDir DoubleClickMove;
    local rotator OldRotation;


    if( Pawn == None )
    {
    GotoState('Dead');
    }
    else
    {
    GetAxes(Pawn.Rotation,X,Y,Z); // Movement is in whatever direction the pawn is facing,
    // not the direction the camera is facing

    // Update acceleration.
    NewAccel = PlayerInput.aForward*X + PlayerInput.aStrafe*Y + PlayerInput.aUp*Z;
    //NewAccel.Z = 0;
    NewAccel = Pawn.AccelRate * Normal(NewAccel);

    if (IsLocalPlayerController())
    {
    AdjustPlayerWalkingMoveAccel(NewAccel);
    }

    // DoubleClickMove = PlayerInput.CheckForDoubleClickMove( DeltaTime/WorldInfo.TimeDilation );
    DoubleClickMove = DCLICK_None; // double-tapping not needed during flying

    // Update rotation.
    OldRotation = Rotation;
    UpdateRotation( DeltaTime );

    if( Role < ROLE_Authority ) // then save this move and replicate it
    {
    ReplicateMove(DeltaTime, NewAccel, DoubleClickMove, OldRotation - Rotation);
    }
    else
    {
    ProcessMove(DeltaTime, NewAccel, DoubleClickMove, OldRotation - Rotation);
    }

    }
    }

    Begin:
    }



    simulated function UpdateRotation( float DeltaTime )
    {
    local Rotator DeltaRot, ViewRotation, r, currentOCRotator, previousOCRotator, PawnRot;
    //local Rotator NewRotation;
    local vector v;
    local Oculus OC;


    _OC.UpdatePlayerViewPoint(fakeController, v, r);
    currentOCRotator = QuatToRotator(fakeController.CurHmdOrientation);
    previousOCRotator = QuatToRotator(fakeController.BaseHmdOrientation);

    ViewRotation = Rotation;
    if (Pawn!=none)
    {
    Pawn.SetDesiredRotation(ViewRotation);
    PawnRot = Pawn.Rotation; // Get current rotation of pawn
    }

    // Calculate Delta to be applied on ViewRotation
    DeltaRot.Yaw = PlayerInput.aTurn;
    DeltaRot.Pitch = PlayerInput.aLookUp;
    // add roll to DeltaRot using aBase.Z which is mapped in UDKInput.ini to keys Q and E
    DeltaRot.Roll = -PlayerInput.aBaseZ; // the minus sign infront makes the roll work correctly. Don't ask!

    // Oculus
    OC = class'Oculus'.static.GetGlobals();
    OC.EnablePlayerViewUpdating(false); // turn off HMD view updating

    if (OC != None && OC.IsPlayer(self))
    {

    if (OC.bDisableControllerPitch)
    DeltaRot.Pitch = 0;

    MouseAim.Yaw += PlayerInput.aMouseAimX;
    MouseAim.Pitch += PlayerInput.aMouseAimY;
    MouseAim = Normalize(MouseAim);

    if (MouseAim.Yaw >= OC.MouseAimLimit)
    {
    DeltaRot.Yaw += (MouseAim.Yaw - OC.MouseAimLimit);
    MouseAim.Yaw = OC.MouseAimLimit;
    }
    else if (MouseAim.Yaw <= -OC.MouseAimLimit)
    {
    DeltaRot.Yaw += (MouseAim.Yaw + OC.MouseAimLimit);
    MouseAim.Yaw = -OC.MouseAimLimit;
    }
    if (MouseAim.Pitch >= OC.MouseAimPitchLimit)
    {
    DeltaRot.Pitch += (MouseAim.Pitch - OC.MouseAimPitchLimit); // add pitch to DeltaRot
    MouseAim.Pitch = OC.MouseAimPitchLimit;
    }
    else if (MouseAim.Pitch <= -OC.MouseAimPitchLimit)
    {
    DeltaRot.Pitch += (MouseAim.Pitch + OC.MouseAimPitchLimit);
    MouseAim.Pitch = -OC.MouseAimPitchLimit;
    }


    }

    // add rotation obtained from mouse movement (yaw and pitch) + roll to rotator holding the Pawn rotation
    PawnRot += DeltaRot;


    // add HMD rotation to rotation obtained from mouse
    DeltaRot += (currentOCRotator - previousOCRotator);

    ProcessViewRotation( DeltaTime, ViewRotation, DeltaRot ); // update camera view rotation

    // If Camera is animating, do not apply the HMD rotation yet, because it will not be
    // used by the Camera, leading to bad headlook behavior.
    if (OC != None && OC.IsPlayer(self) && (PlayerCamera == None || !PlayerCamera.IsAnimActive()))
    {
    // OC.ApplyHmdRotation(self, ViewRotation);
    }

    SetRotation(ViewRotation); // Actually apply the rotation to camera

    ViewShake( deltaTime );

    if (Pawn != None)
    {
    //NewRotation = ViewRotation;
    //Pawn.FaceRotation(NewRotation, deltatime);

    // the Pawn's rotation should only be affected by mouse movement (pitch and yaw) + roll.
    Pawn.SetRotation(PawnRot);
    }
    }

    defaultproperties
    {
    }



    ======================================

    Notice in the CameraTestPawn in the DefaultProperties section there is a reference to Eyes (EyeSocket=Eyes).
    Well, Eyes is a socket that is added to the LiAM mesh as per this tutorial by slowJusko:

    http://forums.epicgames.com/threads/765437-True-First-Person-Weld-camera-to-bone-or-socket-Body-Awareness

    Follow that tutorial (and you'll see that the pawn code is lifted entirely from there)
    to set the 'Eyes' socket (on the b_head bone) on the head. Note the circled Roll, Pitch, and Yaw values in that
    screenshot. You can move the socket position to wherever you like around the head.

    Anyway you'll notice (once you've got it working) that something weird is happening when doing a full pitch turn i.e. looping by moving the mouse up and up and up.


    If it makes it easier you can create a CameraTest.bat file somewhere and inside this file enter:

    <drive>:\<UDK install dir>\Binaries\Win64\UDK.exe CameraTestMap?Game=CameraTest.CameraTest -log


    Or if using a 32-bit version of UDK3, type:

    <drive>:\<UDK install dir>\Binaries\Win32\UDK.exe CameraTestMap?Game=CameraTest.CameraTest -log


    This assumes you have a map called CameraTestMap.udk in the ..\<UDK install dir>\UDKGame\Content\Maps directory
    Up and Coming
    March 13, 2014
    This looks very promising. I wanted to add a roller coaster to the end of my last level and without changing pitch/roll it won't be realistic. Now I understand why the original roller coaster demo seemed off to me.

    I am going to work on this tonight to see if I can bind the view angle to the coaster. I imagine this is going to take a while. If I get it working I will post an update here.

    UPDATE #1

    I fought with this for 3 hours. It does not work for me. UDK wouldn't properly recognize the custom game when I set it in world properties (that was really weird stuff). It compiled fine but something was funky. When I started melding the code into my personal custom game classes UDK blew up. The restart player method appears to be missing this at the top of it: super.RestartPlayer(aPlayer);

    I want this to work so I'll beat it into submission but it caused me the expected grief that all unrealscript does. This isn't a rock solid language like java. This code always feels fragile. When it works it is great but getting it there is always a pain.

    If you had a zip file of the code & map you'd be my hero for the week.

    I have gotten away with never playing with player meshes up to now.
    Here are some step-by-step instructions for adding the eye:

    If you search for your content you will find your default mesh: SK_CH_LIAM_Cathode
    > SkeletalMesh'CH_LIAM_Cathode.Mesh.SK_CH_LIAM_Cathode'

    1. open the character mesh
    2. menu : Mesh : Socket Manager
    3. click "New Socket"
    4. select bone name "b_head"
    5. call it "Eyes"
    6. adjust "Relative Location"
    x = 6
    7. adjust "Relative Rotation"
    Roll = 90
    Pitch = 0
    Yaw = -90
    8. close the socket manager
    9. close the mesh
    10. save the change (right click on mesh and save it)
    > warning: you have just adjusted a standard mesh.
    future updates will blow your change away...

    ------

    UPDATE #2

    I don't know which part of this example it was, but my game slowed down about 15% with it included. It caused all my long jumps to come up way short. I had to abandon it for now. I think I'll add a wonkavator instead of a roller coaster
    New Participant
    April 4, 2014
    Hi,

    I'm not sure this will solve the issue you have with cockpit views, but I could force rotations of the Player's view by assigning a CameraActor to the Player, in Kismet.

    Bascially, I used the SetCameraTarget node from Kismet, and assign an existing CameraActor to player.

    This CameraActor can be attached to any other moving actor (HardAttached) or moved independently (I used Matinee to move it). With the tests I did, when the Camera is rotated, the view of the player using oculus is forced rotated accordingly. Player is still able to look around with oculus, of course, moving with the camera, or countering its movement. (I'm not sure it works for camera roll, but pitch and yaw are working fine in my small prototype).

    Again, I'm not sure if it can solve your problem, but that's all I got :).

    But on my side, it creates a new problem:
    I'm using Kismet only, and when I use SetCameraTarget to assign a CameraActor to the Player, I loose the possibility to use the LineOfSight event.
    Basically, in my proto, I need to test if Player is looking at some objects. If Player looks at them (with a radius margin), this object is highlighted. If player clicks at this moment, I trigger some movements... It's kind of a 3D menu navigation.

    For this, I use a LineOfSight event from Kismet. It works fine as long as the Camera of Player is the default one. As long as I assign a CameraActor to Player, the LineOfSight event is only triggered when the CameraActor is actually looking at the concerned objects. Player's "real" orientation, inputted through oculus, is not taken in consideration. I'm screwed...

    Does anybody have any idea, how, through Kismet, I can detect if an object is looked at (by oculus), in another way than LineOfSight event ?
    Or at least make the LineOfSight event work in my case of CameraActor assigned to Player ?

    Any help is welcome :) :
    Up and Coming
    April 4, 2014
    Bonjour DaceSHG, welcome to the forums !
    (as this was your first post)

    When you say issue "you" have, I am guessing you are meaning me (the post user), I have to say that was a while ago (April 28, 2013 !) I couldn't wait for oculus to fix things, it was a back and forth between epic and Oculus.. so I didn't wait.)
    Which was a good idea : fix came in september (2013 )!!
    Because of that I changed my project to something where this was not a crucial issue... ^_^

    Also in the recent news, Unreal Engine 4 came, so I switched to UE4 (probably like everybody else).

    I can't help you much with your issue on Kismet, I would say use a tracer, but I have no idea how ^_^
    I am not much of a coder so I am happy to forget all the Unreal Script I learned.

    How did you attach your camera to your pawn ? did you use the socket attachment or another method ?
    Because if you know your pawn orientation and your hmd orientation it should be an easy mathematical operation to add the value of that to your camera, for correct line of sight. No ?

    As a warning, as UE4 is out, and most of the SDK for 3d engine are not, and will be in the next few month, it's possible you won't get support for OUDK for any new hardware (Omni, Stem, PrioVR).
    There is no news on that, but maybe it will be wise to consider transfering to UE4 just to be "future proof"
    Welcome to http://www.SynthesisUniverse.com it's out there, on the Oculus Share : https://share.oculus.com/app/synthesis-universe--maze--intro-experience
    New Participant
    April 4, 2014
    Hi Olivier,

    Thanks for your prompt reply.
    Indeed, your post is pretty old, I guessed you probably found another way to solve your issue, but I replied anyway...

    To answer your question, I assigned the Player's camera to an existing CameraActor (instantiated in my level) using a Kismet node "SetCameraTarget":
    https://lh3.googleusercontent.com/_AyW7DrNa_6s/TXxbvxl72PI/AAAAAAAAADY/LCDmqluQijc/s800/Kismet-CameraTarget.JPG

    This way, I can re orient the camera as I like (but carefully, to avoid motion sickness..).

    The way I'm doing is probably very dirty and dumb, but I'm only using Kismet as I don't have coding skills, my technical background is essentially Level Designer.
    Still, for another small proto, I've created some custom Kismet nodes using Unreal script, but mainly by using already existing scripts picked form various forums, that I compiled following instructions step by step :-P

    It limits a lot the possibilities, but the oculus prototype I'm working on is not ambitious, it's just a proof of concept, I'm stuck only by this LoS stuff (but without it, it invalidates everything I want to try :-( ).

    I worked too much already on my proto for not wanting to switch to UE4, trying to finish it as it is.
    I understood UE 4 is not free, as opposed to UDK (am I correct, though ?)

    Overall, what I want to do would be pretty simple with code skills, but seems harder using only Kismet:
    Player can look around at some pre-defined objects (with the oculus, of course), these objects are basically spots on the walls. When sighting a spot and tapping a key, I play a "fly to" movement to the object (predefined, using Matinee). When the object is reached, I want to reorient the camera to face another direction (if not the player is facing the wall).
    I want to force this camera redirection, player is not supposed to have any pad or mouse.

    This is where is my problem:
    - The LoS event (used to aim at the spots) works only when Player's camera is the default one,
    - Redirecting the Player's POV works only when I assign an existing CameraActor to Player (and keep it assigned permanently, if not when I come back to default Player's cam)

    I tried different stuff that didn't work:
    - using console commands: ResetMotionInput
    - getting player's bone head orientation and trace from it

    But indeed, if I can get the HMDOrientation (independently from the CameraActor orientation), maybe I can do something. But I didn't see anything like that in Kismet. I'll try to investigate this a bit more.

    Anyway, I guess my problem is really specific and you're already kind enough to have read till this line :).

    Tell me if you have time for additional thoughts or advices !

    Thanks

    David
    New Participant
    October 18, 2017
    Now 2017 and problem still present. The issue is in 2 rows of code in Oculus plugin:

    // Pitch from other sources is never good, because there is an absolute up and down that must be respected to avoid motion sickness.
    // Same with roll.
    DeltaControlRotation.Pitch = 0;
    DeltaControlRotation.Roll = 0;
      We are making zero gravity game and for me such behavior looks very weird and not obvious. I have to build custom version of Unreal just to comment this 2 lines of code and describe above workaround is old and not acceptable. Just question to Oculus without hope to get answer: isn't it more logical to put such behavior in setting and give developer freedom decide to what to do? Smth like this:

    if (Settings->Flags.bDoNotPitchAndRoll)
    {
    DeltaControlRotation.Pitch = 0;
    DeltaControlRotation.Roll = 0;
    }

    BR, Kate