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

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ZJU_fish1996/article/details/73322567



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

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

        


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

       inputcamerafrom:

       

      inputcamerato:

        

        inputcameraup:

        


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

        


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

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

CAMERA_MODE_DEFAULT = 0
CAMERA_MODE_STRAFE = 1
CAMERA_MODE_CLIMBING_LEDGE = 2

g_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 state
	g_gamepadState:update()
	-- update the camera state	
	g_cameraState:update3rdPerson()
	
	-- Compute which foot is forward and store it in a behavior variable
	local 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 then		
		hkbSetVariable("IsRightFootForward", 1)		
	else		
		hkbSetVariable("IsRightFootForward", 0)
	end
	
end

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

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

	-- updates the camera in 3rd person mode
function g_cameraState:update3rdPerson()	
	
	-- update the orbit speed
	if( g_gamepadState.m_rightStickMagnitude < 0.1 ) then					 		
		self.m_orbitSpeedX = self.m_orbitSpeedX - self.m_orbitSpeedX * 0.1
		self.m_orbitSpeedY = self.m_orbitSpeedY - self.m_orbitSpeedY * 0.1
	else
		self.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 moving
	if( (math.abs(self.m_orbitSpeedX) > 0) or (math.abs(self.m_orbitSpeedY) > 0) ) then
			
		-- prevent camera from rotating too high or too low		
		if (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 = 0
			
		end			
		
		-- compute the x axis to rotate about
		local side = hkVector4.new(0, 0, 0)
		side:setCross(self.m_worldUp, self.m_cameraArmLocalSpace)
		side:normalize3()
				
		-- rotate about the x axis
		local 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 axis
		local 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 arm	
	local targetTo = hkVector4.new(0, 0, 0)
	local targetFrom = hkVector4.new(0, 0, 0)
	
	targetTo = hkbGetOldWorldFromModel():getTranslation()
	targetTo[2] = targetTo[2] + 1.6
		
	targetFrom = 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 logic
	local 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] = 0
	forward:normalize3()
	self.m_angle = -math.atan2( forward[0], forward[1] )
	
end


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

        在计算方向差的时候:

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

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

猜你喜欢

转载自blog.csdn.net/ZJU_fish1996/article/details/73322567