--camera and character controller local math = assert( math ) local mat = require( "mat4" ) local function logistic( x ) return 1.0 / ( 1.0 + math.exp( x ) ) end local player = { turnRate = 0, rate = 0.01, x = 0, y = 0.5, z = 0, vx = 0, vz = 0, yaw = 0, pitch = 0, desx = 0, desz = 0, view = mat.id(), proj = mat.id(), } function player:updateDesiredDirection( forward, left, right, back ) local x = (right and 1 or 0) - (left and 1 or 0) local z = (forward and 1 or 0) - (back and 1 or 0) local c, s = math.cos( self.yaw ), math.sin( self.yaw ) local n = math.sqrt( x * x + z * z ) if n < 0.0001 then n = 1.0 end x, z = x / n, z / n self.desx, self.desz = x * c + z * s, -x * s + z * c end function player:setFOV( fov ) self.proj = mat.projection( 0.05, 100, math.rad( fov or 90 ) ) end function player:setTurnRate( sensitivity ) self.turnRate = 0.001 * logistic( sensitivity ) end function player:turn( dx, dy ) self.yaw = self.yaw + dx * self.turnRate self.pitch = self.pitch + dy * self.turnRate end function player:update() self.vx = self.desx self.vz = self.desz self.x = self.x + self.vx * self.rate self.z = self.z + self.vz * self.rate self.view = mat.view( self.x, self.y, self.z, self.yaw, self.pitch ) end function player:tostring() return ([[ x: %3.2f y: %3.2f z: %3.2f vx: %3.2f vz: %3.2f yaw: %3.2f pitch:%3.2f desx: %3.2f desz: %3.2f ]]):format( player.x, player.y, player.z, player.vx, player.vz, player.yaw, player.pitch, player.desx, player.desz ) end return player