679 | function VehicleCamera:getCollisionDistance() |
680 | if not self.isCollisionEnabled then |
681 | return false, nil, nil, nil, nil, nil |
682 | end |
683 | |
684 | local raycastMask = 32+64+128+256+4096 |
685 | |
686 | local targetCamX, targetCamY, targetCamZ = localToWorld(self.rotateNode, self.transDirX*self.zoomTarget, self.transDirY*self.zoomTarget, self.transDirZ*self.zoomTarget) |
687 | |
688 | local hasCollision = false |
689 | local collisionDistance = -1 |
690 | local normalX,normalY,normalZ |
691 | local normalDotDir |
692 | for _, raycastNode in ipairs(self.raycastNodes) do |
693 | |
694 | hasCollision = false |
695 | |
696 | local nodeX, nodeY, nodeZ = getWorldTranslation(raycastNode) |
697 | local dirX, dirY, dirZ = targetCamX-nodeX, targetCamY-nodeY, targetCamZ-nodeZ |
698 | local dirLength = MathUtil.vector3Length(dirX, dirY, dirZ) |
699 | dirX = dirX / dirLength |
700 | dirY = dirY / dirLength |
701 | dirZ = dirZ / dirLength |
702 | |
703 | local startX = nodeX |
704 | local startY = nodeY |
705 | local startZ = nodeZ |
706 | local currentDistance = 0 |
707 | local minDistance = self.transMin |
708 | |
709 | while true do |
710 | if (dirLength-currentDistance) <= 0 then |
711 | break |
712 | end |
713 | self.raycastDistance = 0 |
714 | raycastClosest(startX, startY, startZ, dirX, dirY, dirZ, "raycastCallback", dirLength-currentDistance, self, raycastMask, true) |
715 | |
716 | if self.raycastDistance ~= 0 then |
717 | currentDistance = currentDistance + self.raycastDistance+0.001 |
718 | local ndotd = MathUtil.dotProduct(self.normalX, self.normalY, self.normalZ, dirX, dirY, dirZ) |
719 | |
720 | local isAttachedVehicle = false |
721 | local ignoreObject = false |
722 | local object = g_currentMission:getNodeObject(self.raycastTransformId) |
723 | if object ~= nil then |
724 | if object ~= self.vehicle then |
725 | local attached1 = object.getIsAttachedTo ~= nil and object:getIsAttachedTo(self.vehicle) |
726 | local attached2 = self.vehicle.getIsAttachedTo ~= nil and self.vehicle:getIsAttachedTo(object) |
727 | isAttachedVehicle = attached1 or attached2 |
728 | |
729 | local mountObject = object.dynamicMountObject or object.tensionMountObject |
730 | if mountObject ~= nil and (mountObject == self.vehicle or mountObject:getRootVehicle() == self.vehicle) then |
731 | isAttachedVehicle = true |
732 | end |
733 | end |
734 | end |
735 | |
736 | -- ignore cut trees that are loaded to a vehicle |
737 | if getHasClassId(self.raycastTransformId, ClassIds.SHAPE) and getSplitType(self.raycastTransformId) ~= 0 then |
738 | ignoreObject = true |
739 | end |
740 | |
741 | if isAttachedVehicle or object == self.vehicle or ignoreObject then --isAttachedNode or isDynamicallyMounted then |
742 | if ndotd > 0 then |
743 | minDistance = math.max(minDistance, currentDistance) |
744 | end |
745 | else |
746 | hasCollision = true |
747 | -- we take the distance from the rotate node |
748 | if raycastNode == self.rotateNode then |
749 | normalX,normalY,normalZ = self.normalX, self.normalY, self.normalZ |
750 | collisionDistance = math.max(self.transMin, currentDistance) |
751 | normalDotDir = ndotd |
752 | end |
753 | break |
754 | end |
755 | startX = nodeX+dirX*currentDistance |
756 | startY = nodeY+dirY*currentDistance |
757 | startZ = nodeZ+dirZ*currentDistance |
758 | else |
759 | break |
760 | end |
761 | end |
762 | if not hasCollision then |
763 | break |
764 | end |
765 | end |
766 | |
767 | return hasCollision, collisionDistance, normalX,normalY,normalZ, normalDotDir |
768 | end |
64 | function VehicleCamera:loadFromXML(xmlFile, key) |
65 | XMLUtil.checkDeprecatedXMLElements(xmlFile, self.vehicle.configFileName, key .. "#index", "#node") -- FS17 to FS19 |
66 | |
67 | local camIndexStr = getXMLString(xmlFile, key .. "#node") |
68 | self.cameraNode = I3DUtil.indexToObject(self.vehicle.components, camIndexStr, self.vehicle.i3dMappings) |
69 | if self.cameraNode == nil or not getHasClassId(self.cameraNode, ClassIds.CAMERA) then |
70 | g_logManager:xmlWarning(self.vehicle.configFileName, "Invalid camera node for camera '%s'. Must be a camera type!", key) |
71 | return false |
72 | end |
73 | |
74 | self.fovY = calculateFovY(self.cameraNode) |
75 | setFovY(self.cameraNode, self.fovY) |
76 | |
77 | self.isRotatable = Utils.getNoNil(getXMLBool(xmlFile, key .. "#rotatable"), false) |
78 | self.limit = Utils.getNoNil(getXMLBool(xmlFile, key .. "#limit"), false) |
79 | if self.limit then |
80 | self.rotMinX = getXMLFloat(xmlFile, key .. "#rotMinX") |
81 | self.rotMaxX = getXMLFloat(xmlFile, key .. "#rotMaxX") |
82 | |
83 | self.transMin = getXMLFloat(xmlFile, key .. "#transMin") |
84 | self.transMax = getXMLFloat(xmlFile, key .. "#transMax") |
85 | if self.rotMinX == nil or self.rotMaxX == nil or self.transMin == nil or self.transMax == nil then |
86 | g_logManager:xmlWarning(self.vehicle.configFileName, "Missing 'rotMinX', 'rotMaxX', 'transMin' or 'transMax' for camera '%s'", key) |
87 | return false |
88 | end |
89 | end |
90 | |
91 | self.isInside = Utils.getNoNil(getXMLBool(xmlFile, key .. "#isInside"), false) |
92 | if self.isInside then |
93 | self.defaultLowPassGain = Utils.getNoNil(getXMLFloat(xmlFile, key .. "#defaultLowPassGain"), 0.5) |
94 | self.defaultVolume = Utils.getNoNil(getXMLFloat(xmlFile, key .. "#defaultVolume"), 0.9) |
95 | else |
96 | self.defaultLowPassGain = Utils.getNoNil(getXMLFloat(xmlFile, key .. "#defaultLowPassGain"), 1.0) |
97 | self.defaultVolume = Utils.getNoNil(getXMLFloat(xmlFile, key .. "#defaultVolume"), 1.0) |
98 | end |
99 | self.allowHeadTracking = Utils.getNoNil(getXMLBool(xmlFile, key .. "#allowHeadTracking"), self.isInside) |
100 | |
101 | local shadowBoxIndexStr = getXMLString(xmlFile, key .. "#shadowFocusBox") |
102 | self.shadowFocusBoxNode = I3DUtil.indexToObject(self.vehicle.components, shadowBoxIndexStr, self.vehicle.i3dMappings) |
103 | if self.shadowFocusBoxNode ~= nil and not getHasClassId(self.shadowFocusBoxNode, ClassIds.SHAPE) then |
104 | g_logManager:xmlWarning(self.vehicle.configFileName, "Invalid camera shadow focus box '%s'. Must be a shape and cpu mesh", getName(shadowFocusBoxNode)) |
105 | self.shadowFocusBoxNode = nil; |
106 | end |
107 | |
108 | if self.isInside and self.shadowFocusBoxNode == nil then |
109 | g_logManager:xmlDevWarning(self.vehicle.configFileName, "Missing shadow focus box for indoor camera '%s'", key) |
110 | end |
111 | |
112 | self.useOutdoorSounds = Utils.getNoNil(getXMLBool(xmlFile, key .. "#useOutdoorSounds"), not self.isInside) |
113 | |
114 | if self.isRotatable then |
115 | self.rotateNode = I3DUtil.indexToObject(self.vehicle.components, getXMLString(xmlFile, key .. "#rotateNode"), self.vehicle.i3dMappings) |
116 | self.hasExtraRotationNode = self.rotateNode ~= nil |
117 | end |
118 | |
119 | local rotation = StringUtil.getRadiansFromString(getXMLString(xmlFile, key.."#rotation"), 3) |
120 | if rotation ~= nil then |
121 | local rotationNode = self.cameraNode |
122 | if self.rotateNode ~= nil then |
123 | rotationNode = self.rotateNode |
124 | end |
125 | setRotation(rotationNode, unpack(rotation)) |
126 | end |
127 | local translation = StringUtil.getVectorNFromString(getXMLString(xmlFile, key.."#translation"), 3) |
128 | if translation ~= nil then |
129 | setTranslation(self.cameraNode, unpack(translation)) |
130 | end |
131 | |
132 | self.allowTranslation = (self.rotateNode ~= nil and self.rotateNode ~= self.cameraNode) |
133 | |
134 | self.useMirror = Utils.getNoNil(getXMLBool(xmlFile, key .. "#useMirror"), false) |
135 | self.useWorldXZRotation = getXMLBool(xmlFile, key .. "#useWorldXZRotation") -- overrides the ingame setting |
136 | self.resetCameraOnVehicleSwitch = getXMLBool(xmlFile, key .. "#resetCameraOnVehicleSwitch") -- overrides the ingame setting |
137 | |
138 | self.positionSmoothingParameter = 0 |
139 | self.lookAtSmoothingParameter = 0 |
140 | local useDefaultPositionSmoothing = Utils.getNoNil(getXMLBool(xmlFile, key .. "#useDefaultPositionSmoothing"), true) |
141 | if useDefaultPositionSmoothing then |
142 | if self.isInside then |
143 | self.positionSmoothingParameter = 0.128 -- 0.095 |
144 | self.lookAtSmoothingParameter = 0.176 -- 0.12 |
145 | else |
146 | self.positionSmoothingParameter = 0.016 |
147 | self.lookAtSmoothingParameter = 0.022 |
148 | end |
149 | end |
150 | self.positionSmoothingParameter = Utils.getNoNil(getXMLFloat(xmlFile, key .. "#positionSmoothingParameter"), self.positionSmoothingParameter) |
151 | self.lookAtSmoothingParameter = Utils.getNoNil(getXMLFloat(xmlFile, key .. "#lookAtSmoothingParameter"), self.lookAtSmoothingParameter) |
152 | |
153 | local useHeadTracking = g_gameSettings:getValue("isHeadTrackingEnabled") and isHeadTrackingAvailable() and self.allowHeadTracking |
154 | if useHeadTracking then |
155 | self.positionSmoothingParameter = 0 |
156 | self.lookAtSmoothingParameter = 0 |
157 | end |
158 | |
159 | self.cameraPositionNode = self.cameraNode |
160 | if self.positionSmoothingParameter > 0 then |
161 | -- create a node which indicates the target position of the camera |
162 | self.cameraPositionNode = createTransformGroup("cameraPositionNode") |
163 | local camIndex = getChildIndex(self.cameraNode) |
164 | link(getParent(self.cameraNode), self.cameraPositionNode, camIndex) |
165 | local x,y,z = getTranslation(self.cameraNode) |
166 | local rx,ry,rz = getRotation(self.cameraNode) |
167 | setTranslation(self.cameraPositionNode, x,y,z) |
168 | setRotation(self.cameraPositionNode, rx,ry,rz) |
169 | |
170 | unlink(self.cameraNode) |
171 | end |
172 | self.rotYSteeringRotSpeed = math.rad(Utils.getNoNil(getXMLFloat(xmlFile, key .. "#rotYSteeringRotSpeed"), 0)) |
173 | |
174 | if self.rotateNode == nil or self.rotateNode == self.cameraNode then |
175 | self.rotateNode = self.cameraPositionNode |
176 | end |
177 | |
178 | if useHeadTracking then |
179 | local dx,dy,dz = localDirectionToLocal(self.cameraPositionNode, getParent(self.cameraPositionNode), 0,0,1) |
180 | local tx,ty,tz = localToLocal(self.cameraPositionNode, getParent(self.cameraPositionNode), 0,0,0) |
181 | self.headTrackingNode = createTransformGroup("headTrackingNode") |
182 | link(getParent(self.cameraPositionNode), self.headTrackingNode) |
183 | setTranslation(self.headTrackingNode, tx,ty,tz) |
184 | if math.abs(dx)+math.abs(dz) > 0.0001 then |
185 | setDirection(self.headTrackingNode, dx, 0, dz, 0,1,0) |
186 | else |
187 | setRotation(self.headTrackingNode, 0,0,0) |
188 | end |
189 | |
190 | self.headTrackingPitchOffset = math.acos(dy) - 1.57079 |
191 | end |
192 | |
193 | self.origRotX, self.origRotY, self.origRotZ = getRotation(self.rotateNode) |
194 | self.rotX = self.origRotX |
195 | self.rotY = self.origRotY |
196 | self.rotZ = self.origRotZ |
197 | |
198 | self.origTransX, self.origTransY, self.origTransZ = getTranslation(self.cameraPositionNode) |
199 | self.transX = self.origTransX |
200 | self.transY = self.origTransY |
201 | self.transZ = self.origTransZ |
202 | |
203 | local transLength = MathUtil.vector3Length(self.origTransX, self.origTransY, self.origTransZ) + 0.00001 -- prevent devision by zero |
204 | self.zoom = transLength |
205 | self.zoomTarget = transLength |
206 | self.zoomLimitedTarget = -1 |
207 | |
208 | local trans1OverLength = 1.0/transLength |
209 | self.transDirX = trans1OverLength*self.origTransX |
210 | self.transDirY = trans1OverLength*self.origTransY |
211 | self.transDirZ = trans1OverLength*self.origTransZ |
212 | if self.allowTranslation then |
213 | if transLength <= 0.01 then |
214 | g_logManager:xmlWarning(self.vehicle.configFileName, "Invalid camera translation for camera '%s'. Distance needs to be bigger than 0.01", key) |
215 | end |
216 | end |
217 | |
218 | table.insert(self.raycastNodes, self.rotateNode) |
219 | local i=0 |
220 | while true do |
221 | local raycastKey = key..string.format(".raycastNode(%d)", i) |
222 | if not hasXMLProperty(xmlFile, raycastKey) then |
223 | break |
224 | end |
225 | |
226 | XMLUtil.checkDeprecatedXMLElements(xmlFile, self.vehicle.configFileName, raycastKey .. "#index", raycastKey .. "#node") --FS17 to FS19 |
227 | |
228 | local node = I3DUtil.indexToObject(self.vehicle.components, getXMLString(xmlFile, raycastKey .. "#node"), self.vehicle.i3dMappings) |
229 | if node ~= nil then |
230 | table.insert(self.raycastNodes, node) |
231 | end |
232 | |
233 | i=i+1 |
234 | end |
235 | |
236 | local sx,sy,sz = getScale(self.cameraNode) |
237 | if sx ~= 1 or sy ~= 1 or sz ~= 1 then |
238 | g_logManager:xmlWarning(self.vehicle.configFileName, "Vehicle camera with scale found for camera '%s'. Resetting to scale 1", key) |
239 | setScale(self.cameraNode, 1,1,1) |
240 | end |
241 | |
242 | self.headTrackingPositionOffset = {0, 0, 0} |
243 | self.headTrackingRotationOffset = {0, 0, 0} |
244 | |
245 | return true |
246 | end |
502 | function VehicleCamera:onActivate() |
503 | |
504 | self.isActivated = true |
505 | if (self.resetCameraOnVehicleSwitch == nil and g_gameSettings:getValue("resetCamera")) or self.resetCameraOnVehicleSwitch then |
506 | self:resetCamera() |
507 | end |
508 | setCamera(self.cameraNode) |
509 | if self.shadowFocusBoxNode then |
510 | setShadowFocusBox(self.shadowFocusBoxNode) |
511 | end |
512 | |
513 | if self.positionSmoothingParameter > 0 then |
514 | local xlook,ylook,zlook = getWorldTranslation(self.rotateNode) |
515 | self.lookAtPosition[1] = xlook |
516 | self.lookAtPosition[2] = ylook |
517 | self.lookAtPosition[3] = zlook |
518 | self.lookAtLastTargetPosition[1] = xlook |
519 | self.lookAtLastTargetPosition[2] = ylook |
520 | self.lookAtLastTargetPosition[3] = zlook |
521 | local x,y,z = getWorldTranslation(self.cameraPositionNode) |
522 | self.position[1] = x |
523 | self.position[2] = y |
524 | self.position[3] = z |
525 | self.lastTargetPosition[1] = x |
526 | self.lastTargetPosition[2] = y |
527 | self.lastTargetPosition[3] = z |
528 | |
529 | |
530 | local rx,ry,rz = getWorldRotation(self.rotateNode) |
531 | |
532 | setRotation(self.cameraNode, rx,ry,rz) |
533 | setTranslation(self.cameraNode, x,y,z) |
534 | end |
535 | |
536 | self.lastInputValues = {} |
537 | self.lastInputValues.upDown = 0 |
538 | self.lastInputValues.leftRight = 0 |
539 | |
540 | -- activate action event callbacks |
541 | local _, actionEventId1 = g_inputBinding:registerActionEvent(InputAction.AXIS_LOOK_UPDOWN_VEHICLE, self, VehicleCamera.actionEventLookUpDown, false, false, true, true, nil) |
542 | local _, actionEventId2 = g_inputBinding:registerActionEvent(InputAction.AXIS_LOOK_LEFTRIGHT_VEHICLE, self, VehicleCamera.actionEventLookLeftRight, false, false, true, true, nil) |
543 | g_inputBinding:setActionEventTextVisibility(actionEventId1, false) |
544 | g_inputBinding:setActionEventTextVisibility(actionEventId2, false) |
545 | end |
297 | function VehicleCamera:update(dt) |
298 | local target = self.zoomTarget |
299 | if self.zoomLimitedTarget >= 0 then |
300 | target = math.min(self.zoomLimitedTarget, self.zoomTarget) |
301 | end |
302 | self.zoom = target + ( math.pow(0.99579, dt) * (self.zoom - target) ) |
303 | |
304 | -- |
305 | if self.lastInputValues.upDown ~= 0 then |
306 | local value = self.lastInputValues.upDown * g_gameSettings:getValue(GameSettings.SETTING.CAMERA_SENSITIVITY) |
307 | self.lastInputValues.upDown = 0 |
308 | value = g_gameSettings:getValue("invertYLook") and -value or value |
309 | |
310 | if self.isRotatable then |
311 | if self.isActivated and not g_gui:getIsGuiVisible() then |
312 | if self.limitRotXDelta > 0.001 then |
313 | self.rotX = math.min(self.rotX - value, self.rotX) |
314 | elseif self.limitRotXDelta < -0.001 then |
315 | self.rotX = math.max(self.rotX - value, self.rotX) |
316 | else |
317 | self.rotX = self.rotX - value |
318 | end |
319 | |
320 | if self.limit then |
321 | self.rotX = math.min(self.rotMaxX, math.max(self.rotMinX, self.rotX)) |
322 | end |
323 | end |
324 | end |
325 | end |
326 | |
327 | if self.lastInputValues.leftRight ~= 0 then |
328 | local value = self.lastInputValues.leftRight * g_gameSettings:getValue(GameSettings.SETTING.CAMERA_SENSITIVITY) |
329 | self.lastInputValues.leftRight = 0 |
330 | |
331 | if self.isRotatable then |
332 | if self.isActivated and not g_gui:getIsGuiVisible() then |
333 | self.rotY = self.rotY - value |
334 | end |
335 | end |
336 | end |
337 | |
338 | -- |
339 | if g_gameSettings:getValue("isHeadTrackingEnabled") and isHeadTrackingAvailable() and self.allowHeadTracking and self.headTrackingNode ~= nil then |
340 | local tx,ty,tz = getHeadTrackingTranslation() |
341 | local pitch,yaw,roll = getHeadTrackingRotation() |
342 | if pitch ~= nil then |
343 | local camParent = getParent(self.cameraNode) |
344 | local ctx,cty,ctz; |
345 | local crx,cry,crz; |
346 | if camParent ~= 0 then |
347 | ctx, cty, ctz = localToLocal(self.headTrackingNode, camParent, tx, ty, tz); |
348 | crx, cry, crz = localRotationToLocal(self.headTrackingNode, camParent, pitch + self.headTrackingPitchOffset,yaw,roll); |
349 | else |
350 | ctx, cty, ctz = localToWorld(self.headTrackingNode, tx, ty, tz); |
351 | crx, cry, crz = localRotationToWorld(self.headTrackingNode, pitch + self.headTrackingPitchOffset,yaw,roll); |
352 | end |
353 | |
354 | setRotation(self.cameraNode, crx, cry, crz) |
355 | setTranslation(self.cameraNode, ctx, cty, ctz) |
356 | end |
357 | else |
358 | |
359 | self:updateRotateNodeRotation() |
360 | |
361 | |
362 | if self.limit then |
363 | -- adjust rotation to avoid clipping with terrain |
364 | if self.isRotatable and ((self.useWorldXZRotation == nil and g_gameSettings:getValue("useWorldCamera")) or self.useWorldXZRotation) then |
365 | |
366 | local numIterations = 4 |
367 | for i=1, numIterations do |
368 | local transX, transY, transZ = self.transDirX*self.zoom, self.transDirY*self.zoom, self.transDirZ*self.zoom |
369 | local x,y,z = localToWorld(getParent(self.cameraPositionNode), transX, transY, transZ) |
370 | |
371 | local terrainHeight = DensityMapHeightUtil.getHeightAtWorldPos(x,0,z) |
372 | |
373 | local minHeight = terrainHeight + 0.9 |
374 | if y < minHeight then |
375 | local h = math.sin(self.rotX)*self.zoom |
376 | local h2 = h-(minHeight-y) |
377 | self.rotX = math.asin(MathUtil.clamp(h2/self.zoom, -1, 1)) |
378 | self:updateRotateNodeRotation() |
379 | else |
380 | break |
381 | end |
382 | end |
383 | end |
384 | |
385 | -- adjust zoom to avoid collision with objects |
386 | if self.allowTranslation then |
387 | |
388 | self.limitRotXDelta = 0 |
389 | local hasCollision, collisionDistance, nx,ny,nz, normalDotDir = self:getCollisionDistance() |
390 | if hasCollision then |
391 | local distOffset = 0.1 |
392 | if normalDotDir ~= nil then |
393 | local absNormalDotDir = math.abs(normalDotDir) |
394 | distOffset = MathUtil.lerp(1.2, 0.1, absNormalDotDir*absNormalDotDir*(3-2*absNormalDotDir)) |
395 | end |
396 | collisionDistance = math.max(collisionDistance-distOffset, 0.01) |
397 | self.disableCollisionTime = g_currentMission.time+400 |
398 | self.zoomLimitedTarget = collisionDistance |
399 | if collisionDistance < self.zoom then |
400 | self.zoom = collisionDistance |
401 | end |
402 | if self.isRotatable and nx ~= nil and collisionDistance < self.transMin then |
403 | local _,lny,_ = worldDirectionToLocal(self.rotateNode, nx,ny,nz) |
404 | if lny > 0.5 then |
405 | self.limitRotXDelta = 1 |
406 | elseif lny < -0.5 then |
407 | self.limitRotXDelta = -1 |
408 | end |
409 | end |
410 | else |
411 | if self.disableCollisionTime <= g_currentMission.time then |
412 | self.zoomLimitedTarget = -1 |
413 | end |
414 | end |
415 | end |
416 | |
417 | end |
418 | self.transX, self.transY, self.transZ = self.transDirX*self.zoom, self.transDirY*self.zoom, self.transDirZ*self.zoom |
419 | setTranslation(self.cameraPositionNode, self.transX, self.transY, self.transZ) |
420 | |
421 | if self.positionSmoothingParameter > 0 then |
422 | |
423 | local interpDt = g_physicsDt |
424 | |
425 | if self.vehicle.spec_rideable ~= nil then |
426 | interpDt = self.vehicle.spec_rideable.interpolationDt |
427 | end |
428 | |
429 | if g_server == nil then |
430 | -- on clients, we interpolate the vehicles with dt, thus we need to use the same for camera interpolation |
431 | interpDt = dt |
432 | end |
433 | if interpDt > 0 then |
434 | local xlook,ylook,zlook = getWorldTranslation(self.rotateNode) |
435 | local lookAtPos = self.lookAtPosition |
436 | local lookAtLastPos = self.lookAtLastTargetPosition |
437 | lookAtPos[1],lookAtPos[2],lookAtPos[3] = self:getSmoothed(self.lookAtSmoothingParameter, lookAtPos[1],lookAtPos[2],lookAtPos[3], xlook,ylook,zlook, lookAtLastPos[1],lookAtLastPos[2],lookAtLastPos[3], interpDt) |
438 | lookAtLastPos[1],lookAtLastPos[2],lookAtLastPos[3] = xlook,ylook,zlook |
439 | |
440 | local x,y,z = getWorldTranslation(self.cameraPositionNode) |
441 | local pos = self.position |
442 | local lastPos = self.lastTargetPosition |
443 | pos[1],pos[2],pos[3] = self:getSmoothed(self.positionSmoothingParameter, pos[1],pos[2],pos[3], x,y,z, lastPos[1],lastPos[2],lastPos[3], interpDt) |
444 | lastPos[1],lastPos[2],lastPos[3] = x,y,z |
445 | |
446 | self:setSeparateCameraPose() |
447 | end |
448 | end |
449 | |
450 | end |
451 | |
452 | end |