[Havok学习笔记(5)] CAMERA TUTORIAL

来源:互联网 发布:怎么看淘宝店铺买家秀 编辑:程序博客网 时间:2024/05/19 12:26



        在上一教程中,我们用了一些简单的脚本来实现通过手柄控制游戏中角色运动的功能。在这一教程中,我们通过加入相机模型引入更多的交互。

        我们将在行为图中加入更多的变量,来控制相机的位置和方向。我们创建如下三个四维向量。

        


       在开始我们的工作之前,我们先给这些变量特定的值。

       inputcamerafrom:

       

      inputcamerato:

        

        inputcameraup:

        


        设置好了值之后,我们使得相机由这三个变量控制,这时相机跳转到我们指定的视角:

        


        相应的代码写在Tutorial_camera.lua中。它的作用是始终跟随着角色的运动。

        一开始,和我们在手柄交互中做的一样,我们先在开头记录一些相机的状态量:

 

CAMERA_MODE_DEFAULT = 0CAMERA_MODE_STRAFE = 1CAMERA_MODE_CLIMBING_LEDGE = 2g_camera = {m_from = hkVector4.new( 0.0, 4.0, 2.5 ),m_to = hkVector4.new( 0.0, 0.0, 1.75 ),m_up = hkVector4.new( 0, 0, 1 ),m_forward = hkVector4.new( 0, 0, 0),m_angle = 0,m_mode = 0,m_targetLeadAmount = hkVector4.new(),m_cameraFollowDistance = 5.0,m_orbitMaxSpeedX = 1.75,m_orbitMaxSpeedY = 1,m_orbitSpeedX = 0.0,m_orbitSpeedY = 0.0,m_cameraArmLocalSpace = hkVector4.new(0, 1.0, 0.0)}

        我们需要计算的是轨道的速度以及局部空间的偏移位置。

        首先,我们把之前的所有节点封装成一个状态机:

        


       为了便于控制,我们在状态机上再封装一个locomotion的脚本:

        


       我们为这个脚本加入一个Update的回调函数

        


function onLocomotionUpdate()-- update the gamepad stateg_gamepadState:update()-- update the camera stateg_cameraState:update3rdPerson()-- Compute which foot is forward and store it in a behavior variablelocal leftLegIndex = hkbGetBoneIndex("LeftLegCalf")local rightLegIndex = hkbGetBoneIndex("RightLegCalf")local leftLegModelSpace = hkbGetOldBoneModelSpace(leftLegIndex)local rightLegModelSpace = hkbGetOldBoneModelSpace(rightLegIndex)local leftForward = leftLegModelSpace:getTranslation():dot3(FORWARD_AXIS)local rightForward = rightLegModelSpace:getTranslation():dot3(FORWARD_AXIS)if rightForward > leftForward thenhkbSetVariable("IsRightFootForward", 1)elsehkbSetVariable("IsRightFootForward", 0)endend

        一开始我们先刷新游戏手柄和相机状态。

        当我们调用了g_cameraState::update3rdPerson()的时候,将会执行如下脚本:

-- updates the camera in 3rd person modefunction g_cameraState:update3rdPerson()-- update the orbit speedif( g_gamepadState.m_rightStickMagnitude < 0.1 ) then self.m_orbitSpeedX = self.m_orbitSpeedX - self.m_orbitSpeedX * 0.1self.m_orbitSpeedY = self.m_orbitSpeedY - self.m_orbitSpeedY * 0.1elseself.m_orbitSpeedX = clamp( self.m_orbitSpeedX + g_gamepadState.m_rightStickX * 0.05,    -self.m_orbitMaxSpeedX, self.m_orbitMaxSpeedX)self.m_orbitSpeedY = clamp(self.m_orbitSpeedY + g_gamepadState.m_rightStickY * 0.05,    -self.m_orbitMaxSpeedY, self.m_orbitMaxSpeedY)end-- rotate the camera arm if the camera is movingif( (math.abs(self.m_orbitSpeedX) > 0) or (math.abs(self.m_orbitSpeedY) > 0) ) then-- prevent camera from rotating too high or too lowif (self.m_cameraArmLocalSpace[2] > 0.7 and self.m_orbitSpeedY > 0) or    (self.m_cameraArmLocalSpace[2] < -0.1 and self.m_orbitSpeedY < 0) then   self.m_orbitSpeedY = 0end-- compute the x axis to rotate aboutlocal side = hkVector4.new(0, 0, 0)side:setCross(self.m_worldUp, self.m_cameraArmLocalSpace)side:normalize3()-- rotate about the x axislocal rotationY = hkQuaternion.new(0, 0, 0, 1)rotationY:setAxisAngle(side, -self.m_orbitSpeedY * hkbGetTimestep() )self.m_cameraArmLocalSpace:setRotatedDir(rotationY, self.m_cameraArmLocalSpace)-- rotate about the y axislocal rotationX = hkQuaternion.new(0, 0, 0, 1)rotationX:setAxisAngle(self.m_worldUp, -self.m_orbitSpeedX * hkbGetTimestep() )self.m_cameraArmLocalSpace:setRotatedDir(rotationX, self.m_cameraArmLocalSpace)end-- compute camera vectors from character position and camera armlocal targetTo = hkVector4.new(0, 0, 0)local targetFrom = hkVector4.new(0, 0, 0)targetTo = hkbGetOldWorldFromModel():getTranslation()targetTo[2] = targetTo[2] + 1.6targetFrom = hkbGetOldWorldFromModel():getTranslation()targetFrom[2] = targetTo[2]targetFrom:addMul4(self.m_cameraArmLocalSpace, self.m_cameraFollowDistance)self.m_to:setInterpolate4(self.m_to, targetTo, .25)self.m_from:setInterpolate4(self.m_from, targetFrom, .33)self.m_up = self.m_worldUp-- set behavior variables to the local camera variables hkbSetVariable("inputcamerafrom", self.m_from)hkbSetVariable("inputcamerato", self.m_to)hkbSetVariable("inputcameraup", self.m_up)-- compute camera angle for locomotion logiclocal forward = hkVector4.new()forward[0] = self.m_from[0] - self.m_to[0]forward[1] = self.m_from[1] - self.m_to[1]forward[2] = 0forward:normalize3()self.m_angle = -math.atan2( forward[0], forward[1] )end


        这时候,我们通过手柄,就可以控制相机的移动了。我们现在要做的是,当人物往特定方向走的时候,相机将会始终跟踪人物当前朝向。

        在计算方向差的时候:

        local directionDifference = g_gamepadState.m_leftStickAngle - g_cameraState.m_angle - characterAngle

        我们已经考虑了相机角度和人物角度的偏差。

原创粉丝点击