I think that would be very useful! But I'm not sure I get what the adding offsets would do (other than making the view direction something else? If there are offsets ofc).
I've made a crude reset view in the modified Castle Basic demo posted below. I figured I should use another object to help with this. Please excuse the crude "spaceship" thing
(attached file in case you want to test it). Just something I quickly carved out with Wings3D (I haven't got that texturing down yet either..). I have not looked into rotating the ship on it's Z or X axis yet, so I'll just post this for now (I want to look into it later though).
It's not perfect, there are some things I haven't sorted out yet (like parenting the ship to the player, and more). But in essence it's what I'm after for a reset view. But as you see you have to "follow" the player's rotation (with RotatePlayerLocalY( value ) even when setting it with SetPlayerRotation( x, y, z). For one I think this has the potential for some rounding errors if done a lot of times? I'm not sure if that will be an issue though. For another it would be easier with setting a global view direction (I think).
I'm using a HTC Vive btw.
Controls:
Left controller button 1: Reset player heading to HMD direction (should probably be used first, at the start)
Right controller button 1: Reset view (in this case place player in the cockpit)
WASD - controls the ship
Up / Down - arrows: Ship altitude
Then the rest as before in the original Castle Basic (left controller thumb pad = direction, right controller thumb pad = move player)
//******************************************************
// AGKVR Demo 1 - Castle Basic
// ( With very basic "Reset View"
// and Reset Player heading direction to unlocked HMD )
//******************************************************
//This demo application will help you get to know AGKVR
SetErrorMode(0)
//Load the AGKVR plugin
#import_plugin AGKVR
//Init App
SetWindowTitle( "AGKVR Demo 1 - Castle Basic" )
SetSyncRate(0, 0)
SetWindowSize( 1024, 768, 0 )
SetScissor(0, 0, 0, 0)
//Hand Model ID numbers
RightHandModel as integer = 100
LeftHandModel as integer = 101
HandModelImg as integer = 100
//Generate Mipmaps for nicer looking textures
SetGenerateMipmaps( 1 )
//Create Skybox
SetSkyBoxHorizonColor( 200, 200, 255 )
SetSkyBoxHorizonSize( 10, 2 )
SetSkyBoxSkyColor( 50, 50, 255)
SetSkyBoxSunColor( 255,255,255 )
SetSkyBoxVisible( 1 )
SetSkyBoxSunSize( 1, 3.0 )
SetSkyBoxSunVisible( 1 )
//Load Hand Models
//---------------------------
//Right Hand
LoadObjectWithChildren(RightHandModel,"RHand.FBX")
SetObjectScale(RightHandModel,1.15,1.15,1.15)
SetObjectPosition(RightHandModel,0.0,0.0,-0.07)
SetObjectRotation(RightHandModel,0.0,180.0,90.0)
FixObjectPivot(RightHandModel)
SetObjectAnimationSpeed(RightHandModel,20)
LoadImage(HandModelImg,"Hand.png")
SetObjectImage(RightHandModel,HandModelImg,0)
SetObjectVisible(RightHandModel,0)
SetObjectCollisionMode(RightHandModel,0)
//Left Hand
LoadObjectWithChildren(LeftHandModel,"LHand.FBX")
SetObjectScale(LeftHandModel,1.15,1.15,1.15)
SetObjectPosition(LeftHandModel,0.0,0.0,-0.07)
SetObjectRotation(LeftHandModel,0.0,180.0,270.0)
FixObjectPivot(LeftHandModel)
SetObjectAnimationSpeed(LeftHandModel,20)
SetObjectImage(LeftHandModel,HandModelImg,0)
SetObjectVisible(LeftHandModel,0)
SetObjectCollisionMode(LeftHandModel,0)
//Call function to load world models
LoadWorld( )
// Make test vehicle
`objShip = CreateObjectCone( 4, 2, 4 )
objShip = LoadObject( "testship 2.x" )
SetObjectScale( objShip, 2, 2, 2 )
SetObjectPosition( objShip, 0, 0, 0 )
SetObjectRotation( objShip, 0, 90, 0 )
FixObjectPivot( objShip )
SetObjectPosition( objShip, 0, 0.2, 20 )
`SetObjectMeshImage( objShip, 1, 5, 0 )
type something3D
x as float
y as float
z as float
endtype
shipPos as something3D
shipAng as something3D
moveShip as something3D
rotateShip as something3D
shipPos.x = 0
shipPos.y = 0.2
shipPos.z = 20
shipAng.x = 0
shipAng.y = 0
shipAng.z = 0
//Set the Camera Range in AGKVR
//It is necessary to use this command for setting the camera's range instead of the standard AGK SetCameraRange command
AGKVR.SetCameraRange( 0.01, 1000.0 )
//Initialiaze AGKVR
//------------------------------------------------
// The parameters are the Right and Left Eye image ID's that will be used to render to the HMD
InitError As Integer
RightEyeImg As Integer = 500
LeftEyeImg As Integer = 501
InitError = AGKVR.Init( RightEyeImg, LeftEyeImg )
// InitError = 0: SUCCESS!
// InitError = 1: Unable to init VR runtime
// InitError = 2: Compositor initialization failed.
//This command will lock the player's heading direction
//to follow the turn angle of the HMD. This would be common in FPS games, where
//you want the forward moving direction's turn angle to change based on where the
//player is looking. LockPlayerTurn is ON(1) by default
AGKVR.LockPlayerTurn( 0 )
//This command will lock the player's heading direction (forward on the Z axis)
//to follow the pitch angle of the HMD. This would be useful in a freeflight style game
//where you want the forward moving direction's pitch angle to change based on where the
//player is looking. LockPlayerPitch is OFF(0) by default
AGKVR.LockPlayerPitch( 0 )
// Set tracking space to Seated
AGKVR.SetTrackingSpace( 0 )
offset as float
offset = 0
do
//Get AGKVR's Player container's current Position, which will be used later for collision purposes:
PlayerPosX as float
PlayerPosY as float
PlayerPosZ as float
//Control Player Turn Angle with Left Controller Joystick
valx as float
valz as float
valx = AGKVR.LeftController_JoyX( )
AGKVR.RotatePlayerLocalY( valx )
// Keep track of player world rotation
offset = offset + valx
if( offset > 360 ) then offset = offset - 360
if( offset < 0 ) then offset = offset + 360
// Reset forward direction to HMD
if AGKVR.LeftController_Button1() = 1
//AGKVR.ResetSeatedZeroPose() // Doesn't work for reset seated position?
offset = AGKVR.GetHMDAngleY()
endif
// Reset view to ship cockpit
if AGKVR.RightController_Button1() = 1
valx = shipAng.y - offset
offset = shipAng.y
AGKVR.RotatePlayerLocalY( valx )
AGKVR.SetPlayerPosition( shipPos.x, shipPos.y + 0.7, shipPos.z )
endif
//Move ship with the Keyboard
moveShip.x = 0
moveShip.y = 0
moveShip.z = 0
rotateShip.x = 0
rotateShip.y = 0
rotateShip.z = 0
// A-D strafe
if GetRawKeyState( 65 ) then moveShip.x = -0.1
if GetRawKeyState( 68 ) then moveShip.x = 0.1
// Arrow up and down for height
if GetRawKeyState( 38 ) then moveShip.y = 0.1
if GetRawKeyState( 40 ) then moveShip.y = -0.1
// W-S forward-backwards
if GetRawKeyState( 87 ) then moveShip.z = 0.2
if GetRawKeyState( 83 ) then moveShip.z = -0.2
// Q-E for simple turning
if GetRawKeyState( 81 ) then rotateShip.y = -1
if GetRawKeyState( 69 ) then rotateShip.y = 1
MoveObjectLocalX( objShip, moveShip.x )
MoveObjectLocalY( objShip, moveShip.y )
MoveObjectLocalZ( objShip, moveShip.z )
RotateObjectLocalX( objShip, rotateShip.x )
RotateObjectLocalY( objShip, rotateShip.y )
RotateObjectLocalZ( objShip, rotateShip.z )
// Move player with ship if inside (or near) it
if PlayerNearShip( PlayerPosX, PlayerPosY, PlayerPosZ, shipPos, 2.0 )
// But only if player is not moving with player controllers
if AGKVR.LeftController_JoyX() = 0 and AGKVR.RightController_JoyX() = 0 and AGKVR.RightController_JoyY() = 0
// Quick'n'dirty simple reset view for now
valx = shipAng.y - offset
offset = shipAng.y
AGKVR.RotatePlayerLocalY( valx )
AGKVR.SetPlayerPosition( shipPos.x, shipPos.y + 0.7, shipPos.z )
endif
endif
AGKVR.SetPlayerRotation( 0, offset, 0 )
// Get ship position
shipPos.x = GetObjectWorldX( objShip )
shipPos.y = GetObjectWorldY( objShip )
shipPos.z = GetObjectWorldZ( objShip )
shipAng.x = GetObjectAngleX( objShip )
shipAng.y = GetObjectAngleY( objShip )
shipAng.z = GetObjectAngleZ( objShip )
// Get player position
PlayerPosX = AGKVR.GetPlayerX()
PlayerPosY = AGKVR.GetPlayerY()
PlayerPosZ = AGKVR.GetPlayerZ()
//Control Player Movement based on Right Controller Joystick
valx = AGKVR.RightController_JoyX( )
valz = AGKVR.RightController_JoyY( )
AGKVR.MovePlayerLocalZ( valz*0.06 )
AGKVR.MovePlayerLocalX( valx*0.06 )
//Collision
New_PlayerPosX as float
New_PlayerPosY as float
New_PlayerPosZ as float
//Get the Player's ground position now that any movement has occured.
New_PlayerPosX = AGKVR.GetPlayerX()
New_PlayerPosY = AGKVR.GetPlayerY()
New_PlayerPosZ = AGKVR.GetPlayerZ()
//Check for collision from previous position to new position (add the radius to the Y position)
if ObjectSphereSlide(0,PlayerPosX,PlayerPosY+0.5,PlayerPosZ,New_PlayerPosX,New_PlayerPosY+0.5,New_PlayerPosZ,0.5)>0
//Get the collision point (Subtract the collision radius from the Y position)
New_PlayerPosX = GetObjectRayCastSlideX(0)
New_PlayerPosY = GetObjectRayCastSlideY(0)-0.5
New_PlayerPosZ = GetObjectRayCastSlideZ(0)
//Set the player position to the collision point
AGKVR.SetPlayerPosition( New_PlayerPosX, New_PlayerPosY, New_PlayerPosZ )
endif
//Control Hand animation based on Trigger feedback
Rvalue as float
Lvalue as float
Rvalue = AGKVR.RightController_Trigger( )
Lvalue = AGKVR.LeftController_Trigger( )
SetObjectAnimationFrame(RightHandModel, GetObjectAnimationName( RightHandModel, 1 ), GetObjectAnimationDuration(RightHandModel,GetObjectAnimationName( RightHandModel, 1 ))*Rvalue,0)
SetObjectAnimationFrame(LeftHandModel, GetObjectAnimationName( LeftHandModel, 1 ), GetObjectAnimationDuration(LeftHandModel,GetObjectAnimationName( LeftHandModel, 1 ))*Lvalue,0)
//Now that the player's position and orientation has been modified,
//the UpdatePlayer command is called to update all the components of
//AGKVR's player framework
AGKVR.UpdatePlayer( )
//Position Hand Objects
if AGKVR.RightControllerFound( ) = 1
SetObjectPosition( RightHandModel, AGKVR.GetRightHandX(), AGKVR.GetRightHandY(), AGKVR.GetRightHandZ())
SetObjectRotation( RightHandModel, AGKVR.GetRightHandAngleX(), AGKVR.GetRightHandAngleY(), AGKVR.GetRightHandAngleZ())
SetObjectVisible( RightHandModel, 1 )
else
SetObjectVisible( RightHandModel, 0 )
endif
if AGKVR.LeftControllerFound( ) = 1
SetObjectPosition( LeftHandModel, AGKVR.GetLeftHandX(), AGKVR.GetLeftHandY(), AGKVR.GetLeftHandZ())
SetObjectRotation( LeftHandModel, AGKVR.GetLeftHandAngleX(), AGKVR.GetLeftHandAngleY(), AGKVR.GetLeftHandAngleZ())
SetObjectVisible( LeftHandModel, 1 )
else
SetObjectVisible( LeftHandModel, 0 )
endif
//This command renders to the HMD.
AGKVR.Render( )
//The camera's position and rotation will determine what is displayed on the monitor, not the HMD
SetCameraPosition( 1, AGKVR.GetHMDX(), AGKVR.GetHMDY(), AGKVR.GetHMDZ())
SetCameraRotation( 1, AGKVR.GetHMDAngleX(), AGKVR.GetHMDAngleY(), AGKVR.GetHMDAngleZ())
Print( ScreenFPS() )
//Display some controller feedbacks on the monitor
if AGKVR.RightController_Grip() = 1
Print( "Right Grip Pressed" )
endif
if AGKVR.LeftController_Grip() = 1
Print( "Left Grip Pressed" )
endif
if AGKVR.LeftController_Button1() = 1
Print( "Left Button 1 Pressed" )
endif
if AGKVR.RightController_Button1() = 1
Print( "Right Button 1 Pressed" )
endif
if AGKVR.LeftController_Button2() = 1
Print( "Left Button 2 Pressed" )
endif
if AGKVR.RightController_Button2() = 1
Print( "Right Button 2 Pressed" )
endif
printc ( "X HMD: " )
printc ( AGKVR.GetHMDX() )
printc ( " Player: " )
print ( AGKVR.GetPlayerX() )
printc ( "Z HMD: " )
printc ( AGKVR.GetHMDZ() )
printc ( " Player: " )
print ( AGKVR.GetPlayerZ() )
printc ( "Angle HMD: " )
printc ( AGKVR.GetHMDAngleY() )
printc ( " Player: " )
printc ( AGKVR.GetPlayerAngleY() )
printc ( " Offset: " )
print ( offset )
//Sync to update the monitor display (the HMD display is updated through AGKVR's Render Command
//so this Sync is not necessary to for rendering to the HMD)
Sync()
loop
function LoadWorld( )
scaleval as float = 0.037
LoadObject(1,"Castle.fbx")
SetObjectScale(1,scaleval,scaleval,scaleval)
LoadImage(1,"banquet hall_D.png")
LoadImage(2,"portcullis_D.png")
LoadImage(3,"stable_D.png")
LoadImage(4,"well_D.png")
LoadImage(5,"wall.png")
LoadImage(6,"tower.png")
LoadImage(7,"kings apartment_D.png")
SetObjectMeshImage( 1, 1, 2, 0 )
SetObjectMeshImage( 1, 2, 5, 0 )
SetObjectMeshImage( 1, 4, 6, 0 )
SetObjectMeshImage( 1, 5, 7, 0 )
SetObjectMeshImage( 1, 6, 1, 0 )
SetObjectMeshImage( 1, 7, 3, 0 )
SetObjectMeshImage( 1, 8, 4, 0 )
SetObjectMeshImage( 1, 9, 1, 0 )
//Field
LoadImage(50,"TerrainGrass.png")
LoadObject(50,"field.fbx")
SetObjectRotation(50,0,0,0)
SetObjectScale(50,5,5,5)
SetObjectImage(50,50,0)
SetObjectMeshUVScale( 50, 1, 0, 100, 100 )
SetImageWrapU(50,1)
SetImageWrapV(50,1)
endfunction
function PlayerNearShip( PlayerPosX, PlayerPosY, PlayerPosZ, shipPos as something3D, distance as float )
result = 0
if abs( PlayerPosX - shipPos.x ) < distance
if abs( PlayerPosY - shipPos.y ) < distance
if abs( PlayerPosZ - shipPos.z ) < distance then result = 1
endif
endif
endfunction result
Apologies for any typos and strange grammar.