Sprache Deutsch Language English

Script Dokumentation LS 2015 - VehicleCamera (Patch 1.3)

Script Dokumentation Übersicht

scripts/vehicles/VehicleCamera.lua

Copyright (c) 2008-2015 GIANTS Software GmbH, Confidential, All Rights Reserved.
This document is to be published solely by ls-mods.de
1--
2-- VehicleCamera
3-- Camera for vehicles
4--
5-- @author Stefan Geiger
6-- @date 09/08/07
7--
8-- Copyright (C) GIANTS Software GmbH, Confidential, All Rights Reserved.
9
10VehicleCamera = {};
11VehicleCamera.doCameraSmoothing = false;
12
13local VehicleCamera_mt = Class(VehicleCamera);
14
15function VehicleCamera:new(vehicle, customMt)
16
17 local instance = {};
18 if customMt ~= nil then
19 setmetatable(instance, customMt);
20 else
21 setmetatable(instance, VehicleCamera_mt);
22 end;
23
24
25 instance.vehicle = vehicle;
26 instance.isActivated = false;
27
28 --instance.smoothZoom = false;
29 --instance.smoothZoomOffset = 0;
30
31
32 --instance.posXLast = -1;
33 --instance.posYLast = -1;
34 --instance.posXDelta = 0;
35 --instance.posYDelta = 0;
36 instance.smoothUpdateDt = 0;
37
38 instance.limitRotXDelta = 0;
39
40 instance.raycastDistance = 0;
41 instance.normalX = 0;
42 instance.normalY = 0;
43 instance.normalZ = 0;
44
45 instance.raycastNodes = {};
46 instance.disableCollisionTime = -1;
47
48 instance.targetLookAtPosition = {0,0,0};
49 instance.targetPosition = {0,0,0};
50 instance.lastCamX, instance.lastCamY, instance.lastCamZ = 0,0,0;
51 instance.lastCamLookX, instance.lastCamLookY, instance.lastCamLookZ = 0,0,0;
52 instance.separatedFromVehicleUpdateDt = 0;
53
54
55
56 --clearAdsOcclusionRegionGroup(AdSystemHelper.GROUP_VEHICLECAMERA); -- is registered only once in AdSystemHelper:init()
57 --addAdsOcclusionRegion(
58 -- AdSystemHelper.GROUP_VEHICLECAMERA,
59 -- 0.0, 0.0,
60 -- 1.0, 1.0);
61 --setActiveStateAdsOcclusionRegionGroup(AdSystemHelper.GROUP_VEHICLECAMERA, false);
62
63
64 return instance;
65end;
66
67function VehicleCamera:loadFromXML(xmlFile, key)
68 --cameraNode, isRotatable, rotateNode, limit, rotMinX, rotMaxX, transMin, transMax, isInside,
69
70 local camIndexStr = getXMLString(xmlFile, key .. "#index");
71 self.cameraNode = Utils.indexToObject(self.vehicle.components, camIndexStr);
72 if self.cameraNode == nil or not getHasClassId(self.cameraNode, ClassIds.CAMERA) then
73 print("Error loading camera "..key..": invalid camera node");
74 return false;
75 end;
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 print("Error loading camera "..key..": missing limit values");
87 return false;
88 end;
89 end;
90 self.isInside = Utils.getNoNil(getXMLBool(xmlFile, key .. "#isInside"), false);
91 if self.isRotatable then
92 self.rotateNode = Utils.indexToObject(self.vehicle.components, getXMLString(xmlFile, key .. "#rotateNode"));
93 end;
94 self.allowTranslation = (self.rotateNode ~= nil and self.rotateNode ~= self.cameraNode);
95
96 self.useMirror = Utils.getNoNil(getXMLBool(xmlFile, key .. "#useMirror"), false);
97
98 self.useWorldXZRotation = Utils.getNoNil(getXMLBool(xmlFile, key .. "#useWorldXZRotation"), false);
99
100 self.positionSmoothingParameter = 0;
101 self.lookAtSmoothingParameter = 0;
102 self.positionSmoothingResolution = 0.5;
103 if Utils.getNoNil(getXMLBool(xmlFile, key .. "#useDefaultPositionSmoothing"), self.useWorldXZRotation and self.allowTranslation and (not self.limit or math.abs(self.transMax - self.transMin) > 0.01)) then
104 if self.isInside then
105 self.positionSmoothingParameter = 0.095;
106 self.lookAtSmoothingParameter = 0.12;
107 else
108 self.positionSmoothingParameter = 0.016;
109 self.lookAtSmoothingParameter = 0.022;
110 end
111 end
112 self.positionSmoothingParameter = Utils.getNoNil(getXMLFloat(xmlFile, key .. "#positionSmoothingParameter"), self.positionSmoothingParameter);
113 self.lookAtSmoothingParameter = Utils.getNoNil(getXMLFloat(xmlFile, key .. "#lookAtSmoothingParameter"), self.lookAtSmoothingParameter);
114
115 self.positionSmoothingParameter = 1-math.pow(1-self.positionSmoothingParameter, self.positionSmoothingResolution);
116 self.lookAtSmoothingParameter = 1-math.pow(1-self.lookAtSmoothingParameter, self.positionSmoothingResolution);
117
118 self.cameraPositionNode = self.cameraNode;
119 if self.positionSmoothingParameter > 0 then
120 -- create a node which indicates the target position of the camera
121 self.cameraPositionNode = createTransformGroup("cameraPositionNode");
122 local camIndex = getChildIndex(self.cameraNode);
123 link(getParent(self.cameraNode), self.cameraPositionNode, camIndex);
124 local x,y,z = getTranslation(self.cameraNode);
125 local rx,ry,rz = getRotation(self.cameraNode);
126 setTranslation(self.cameraPositionNode, x,y,z);
127 setRotation(self.cameraPositionNode, rx,ry,rz);
128
129 unlink(self.cameraNode);
130 end;
131 self.rotYSteeringRotSpeed = math.rad(Utils.getNoNil(getXMLFloat(xmlFile, key .. "#rotYSteeringRotSpeed"), 0));
132
133 if self.rotateNode == nil or self.rotateNode == self.cameraNode then
134 self.rotateNode = self.cameraPositionNode;
135 end;
136 --[[if VehicleCamera.doCameraSmoothing then
137 link(getParent(self.rotateNode), self.cameraNode);
138 end;]]
139
140 self.origRotX, self.origRotY, self.origRotZ = getRotation(self.rotateNode);
141 self.rotX = self.origRotX;
142 self.rotY = self.origRotY;
143 self.rotZ = self.origRotZ;
144
145 self.origTransX, self.origTransY, self.origTransZ = getTranslation(self.cameraPositionNode);
146 self.transX = self.origTransX;
147 self.transY = self.origTransY;
148 self.transZ = self.origTransZ;
149
150 local transLength = Utils.vector3Length(self.origTransX, self.origTransY, self.origTransZ);
151 self.zoom = transLength
152 self.zoomTarget = transLength;
153 self.zoomLimitedTarget = -1;
154
155 local trans1OverLength = 1.0/transLength;
156 self.transDirX = trans1OverLength*self.origTransX;
157 self.transDirY = trans1OverLength*self.origTransY;
158 self.transDirZ = trans1OverLength*self.origTransZ;
159 if self.allowTranslation then
160 if transLength <= 0.01 then
161 print("Warning: Invalid camera translation in "..key..". Distance needs to be bigger than 0.01");
162 end
163 end
164
165 table.insert(self.raycastNodes, self.rotateNode);
166 local i=0;
167 while true do
168 local raycastKey = key..string.format(".raycastNode(%d)", i);
169 if not hasXMLProperty(xmlFile, raycastKey) then
170 break;
171 end;
172
173 local node = Utils.indexToObject(self.vehicle.components, getXMLString(xmlFile, raycastKey .. "#index"));
174 if node ~= nil then
175 table.insert(self.raycastNodes, node);
176 end;
177
178 i=i+1;
179 end;
180
181 local sx,sy,sz = getScale(self.cameraNode);
182 if sx ~= 1 or sy ~= 1 or sz ~= 1 then
183 print("Warning: Vehicle camera with scale found in "..self.vehicle.configFileName.." ("..key.."). Resetting to scale 1");
184 setScale(self.cameraNode, 1,1,1);
185 end
186
187 return true;
188end;
189
190function VehicleCamera:delete()
191 --delete(self.cameraNode);
192 if self.positionSmoothingParameter > 0 then
193 delete(self.cameraNode);
194 end;
195end;
196
197function VehicleCamera:addZoom(offset)
198 self.zoomTarget = self.zoomTarget+offset;
199 if self.limit then
200 self.zoomTarget = math.min(self.transMax, math.max(self.transMin, self.zoomTarget));
201 end;
202 self.zoomTarget = math.max(self.zoomTarget, 0.01);
203 self.zoom = self.zoomTarget;
204 --self.transX = self.transX+self.transDirX*offset;
205 --self.transY = self.transY+self.transDirY*offset;
206 --self.transZ = self.transZ+self.transDirZ*offset;
207end;
208
209function VehicleCamera:zoomSmoothly(offset)
210 self.zoomTarget = self.zoomTarget+offset;
211 if self.limit then
212 self.zoomTarget = math.min(self.transMax, math.max(self.transMin, self.zoomTarget));
213 end;
214 self.zoomTarget = math.max(self.zoomTarget, 0.01);
215 --self.smoothZoom = true;
216 --self.smoothZoomOffset = self.smoothZoomOffset + offset;
217end;
218
219function VehicleCamera:mouseEvent(posX, posY, isDown, isUp, button)
220 if self.isActivated then
221 --[[if self.posXLast == -1 or self.posYLast == -1 then
222 self.posXLast = posX;
223 self.posYLast = posY;
224 end;
225
226 self.posXDelta = posX - self.posXLast;
227 self.posYDelta = self.posYLast - posY;]]
228
229 local translateMode = Input.isMouseButtonPressed(Input.MOUSE_BUTTON_LEFT) or Input.isMouseButtonPressed(Input.MOUSE_BUTTON_RIGHT) or Input.isMouseButtonPressed(Input.MOUSE_BUTTON_MIDDLE);
230 if self.isRotatable and not translateMode then -- only rotate if neither left or right mouse button is pressed
231 if self.limitRotXDelta > 0.001 then
232 self.rotX = math.min(self.rotX + InputBinding.mouseMovementY, self.rotX);
233 elseif self.limitRotXDelta < -0.001 then
234 self.rotX = math.max(self.rotX + InputBinding.mouseMovementY, self.rotX);
235 else
236 self.rotX = self.rotX + InputBinding.mouseMovementY;
237 end;
238 self.rotY = self.rotY - InputBinding.mouseMovementX; -- - (posX-self.posXLast);
239 end;
240 end;
241end;
242
243function VehicleCamera:keyEvent(unicode, sym, modifier, isDown)
244end;
245
246function VehicleCamera:raycastCallback(transformId, x, y, z, distance, nx, ny, nz)
247 self.raycastDistance = distance;
248 self.normalX = nx;
249 self.normalY = ny;
250 self.normalZ = nz;
251 self.raycastTransformId = transformId;
252end;
253
254function VehicleCamera:update(dt)
255 self.smoothUpdateDt = self.smoothUpdateDt + dt;
256
257 local smoothDt = 25; -- update with constant 40fps
258 while self.smoothUpdateDt > smoothDt do
259 local target = self.zoomTarget;
260 if self.zoomLimitedTarget >= 0 then
261 target = math.min(self.zoomLimitedTarget, self.zoomTarget);
262 end;
263 self.zoom = 0.9*self.zoom + 0.1*target;
264 --[[if self.smoothZoom then
265 self.transX = self.transX + self.transDirX * self.smoothZoomOffset;
266 self.transY = self.transY + self.transDirY * self.smoothZoomOffset;
267 self.transZ = self.transZ + self.transDirZ * self.smoothZoomOffset;
268
269 self.smoothZoomOffset = self.smoothZoomOffset / 1.5;
270
271 if math.abs(self.smoothZoomOffset) < 0.005 then
272 self.smoothZoomOffset = 0;
273 self.smoothZoom = false;
274 end;
275 end;]]
276 self.smoothUpdateDt = self.smoothUpdateDt-smoothDt;
277 end;
278 if self.isActivated then
279 if self.isRotatable then
280
281 local rotSpeed = 0.001*dt;
282 local inputW = InputBinding.getDigitalInputAxis(InputBinding.AXIS_LOOK_UPDOWN_VEHICLE);
283 local inputZ = InputBinding.getDigitalInputAxis(InputBinding.AXIS_LOOK_LEFTRIGHT_VEHICLE);
284 if InputBinding.isAxisZero(inputW) then
285 inputW = InputBinding.getAnalogInputAxis(InputBinding.AXIS_LOOK_UPDOWN_VEHICLE);
286 end;
287 if InputBinding.isAxisZero(inputZ) then
288 inputZ = InputBinding.getAnalogInputAxis(InputBinding.AXIS_LOOK_LEFTRIGHT_VEHICLE);
289 end;
290 if self.limitRotXDelta > 0.001 then
291 self.rotX = math.min(self.rotX - rotSpeed*inputW, self.rotX);
292 elseif self.limitRotXDelta < -0.001 then
293 self.rotX = math.max(self.rotX - rotSpeed*inputW, self.rotX);
294 else
295 self.rotX = self.rotX - rotSpeed*inputW;
296 end;
297 --self.rotX = self.rotX - rotSpeed*inputW;
298 self.rotY = self.rotY - rotSpeed*inputZ;
299 end;
300 end;
301
302
303 local useScaledTrans = false;
304 local scaledTransDist = 0;
305 if self.limit then
306 self.rotX = math.min(self.rotMaxX, math.max(self.rotMinX, self.rotX));
307 end;
308
309 self:updateRotateNodeRotation();
310
311
312 if self.limit then
313 -- adjust rotation to avoid clipping with terrain
314 if self.isRotatable and self.useWorldXZRotation then
315
316 local numIterations = 4;
317 for i=1, numIterations do
318 local transX, transY, transZ = self.transDirX*self.zoom, self.transDirY*self.zoom, self.transDirZ*self.zoom;
319 local x,y,z = localToWorld(getParent(self.cameraPositionNode), transX, transY, transZ);
320
321 local terrainHeight = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, x, 0, z);
322
323 local minHeight = terrainHeight + 0.9;
324 if y < minHeight then
325 local h = math.sin(self.rotX)*self.zoom;
326 local h2 = h-(minHeight-y);
327 self.rotX = math.asin(Utils.clamp(h2/self.zoom, -1, 1));
328 self:updateRotateNodeRotation();
329 else
330 break;
331 end;
332 end;
333 end;
334
335 -- adjust zoom to avoid collision with objects
336 if self.allowTranslation then
337
338 self.limitRotXDelta = 0;
339
340 --local len = Utils.vector3Length(self.transX, self.transY, self.transZ);
341 --len = math.min(self.transMax, math.max(self.transMin, len));
342 --self.transX, self.transY, self.transZ = self.transDirX*len, self.transDirY*len, self.transDirZ*len;
343 local hasCollision, collisionDistance, nx,ny,nz, normalDotDir = self:getCollisionDistance();
344 if hasCollision then
345 local distOffset = 0.1;
346 if normalDotDir ~= nil then
347 local absNormalDotDir = math.abs(normalDotDir)
348 distOffset = Utils.lerp(1.2, 0.1, absNormalDotDir*absNormalDotDir*(3-2*absNormalDotDir));
349 end
350 collisionDistance = math.max(collisionDistance-distOffset, 0.01);
351 self.disableCollisionTime = g_currentMission.time+400;
352 self.zoomLimitedTarget = collisionDistance;
353 if collisionDistance < self.zoom then
354 self.zoom = collisionDistance;
355 end;
356 if self.isRotatable and nx ~= nil and collisionDistance < self.transMin then
357 local lnx,lny,lnz = worldDirectionToLocal(self.rotateNode, nx,ny,nz);
358 --print("normal: "..nx.." "..ny.. " "..nz.. " local: "..lnx .. " "..lny.." "..lnz);
359 if lny > 0.5 then
360 self.limitRotXDelta = 1;
361 --self.rotX = self.rotX - dt*0.0001;
362 elseif lny < -0.5 then
363 self.limitRotXDelta = -1;
364 --self.rotX = self.rotX + dt*0.0001;
365 end;
366 end;
367 else
368 if self.disableCollisionTime <= g_currentMission.time then
369 self.zoomLimitedTarget = -1;
370 end;
371 end;
372 end;
373
374 end;
375 self.transX, self.transY, self.transZ = self.transDirX*self.zoom, self.transDirY*self.zoom, self.transDirZ*self.zoom;
376 setTranslation(self.cameraPositionNode, self.transX, self.transY, self.transZ);
377
378 --[[if self.useWorldXRotation then
379 setRotation(self.rotateNode, 0, self.rotY, self.rotZ);
380 local dx,dy,dz = localDirectionToWorld(self.rotateNode, 0,0,1);
381 local s = math.cos(self.rotX)/math.sqrt(dx*dx + dz*dz); -- normalize and scale to new length
382 dx = dx*s;
383 dz = dz*s;
384 dy = -math.sin(self.rotX);
385
386 local sx,sy,sz = worldDirectionToLocal(getParent(self.rotateNode), localDirectionToWorld(self.rotateNode, 1,0,0));
387 local dx,dy,dz = worldDirectionToLocal(getParent(self.rotateNode), dx,dy,dz);
388 local upx,upy,upz = Utils.crossProduct(dx,dy,dz, sx,sy,sz);
389
390 setDirection(self.rotateNode, dx,dy,dz, upx,upy,upz);
391 else
392 setRotation(self.rotateNode, self.rotX, self.rotY, self.rotZ);
393 end;]]
394
395 if self.positionSmoothingParameter > 0 then
396
397 local interpDt = g_physicsDt;
398 if g_server == nil then
399 -- on clients, we interpolate the vehicles with g_physicsDtUnclamped, thus we need to use the same for camera interpolation
400 interpDt = g_physicsDtUnclamped;
401 end
402
403 local xlook,ylook,zlook = getWorldTranslation(self.rotateNode);
404 -- 1-math.pow(1-0.02, resolution)
405 self.targetLookAtPosition[1], self.targetLookAtPosition[2], self.targetLookAtPosition[3] =
406 self:getSmoothed(self.lookAtSmoothingParameter, self.positionSmoothingResolution, self.targetLookAtPosition[1], self.targetLookAtPosition[2], self.targetLookAtPosition[3],
407 self.lastCamLookX, self.lastCamLookY, self.lastCamLookZ, xlook,ylook,zlook, interpDt);
408 self.lastCamLookX, self.lastCamLookY, self.lastCamLookZ = xlook,ylook,zlook;
409
410 local x,y,z = getWorldTranslation(self.cameraPositionNode);
411 -- 1-math.pow(1-0.014, resolution)
412 self.targetPosition[1], self.targetPosition[2], self.targetPosition[3] =
413 self:getSmoothed(self.positionSmoothingParameter, self.positionSmoothingResolution, self.targetPosition[1], self.targetPosition[2], self.targetPosition[3],
414 self.lastCamX, self.lastCamY, self.lastCamZ, x,y,z, interpDt)
415 --print(string.format("dt: %1.2f pdt %1.2f",dt,interpDt));
416 self.lastCamX, self.lastCamY, self.lastCamZ = x,y,z;
417
418 self:setSeparateCameraPose();
419 end;
420
421 --[[if self.isActivated then
422 wrapMousePosition(0.5, 0.5);
423 self.posXLast = 0.5;
424 self.posYLast = 0.5;
425 end;]]
426end;
427
428-- if alpha is known for resultion 1, it can be adjusted to true resolution with (alpha = 1-math.pow(1-alpha, resolution))
429function VehicleCamera:getSmoothed(alpha, resolution, curX,curY,curZ,startX,startY,startZ,endX,endY,endZ, dt)
430 dt = math.modf(dt, resolution);
431 local scale = resolution/dt;
432 local dx,dy,dz = (endX-startX)*scale, (endY-startY)*scale, (endZ-startZ)*scale;
433 local x,y,z = startX, startY, startZ;
434 for i=resolution,dt,resolution do
435 x,y,z = x + dx, y + dy, z + dz;
436 curX = curX + (x-curX)*alpha;
437 curY = curY + (y-curY)*alpha;
438 curZ = curZ + (z-curZ)*alpha;
439 end
440
441 return curX,curY,curZ;
442end
443
444function VehicleCamera:onActivate()
445
446 self.isActivated = true;
447 self:resetCamera();
448 setCamera(self.cameraNode);
449
450
451 if self.positionSmoothingParameter > 0 then
452 local xlook,ylook,zlook = getWorldTranslation(self.rotateNode);
453 self.targetLookAtPosition[1] = xlook;
454 self.targetLookAtPosition[2] = ylook;
455 self.targetLookAtPosition[3] = zlook;
456 local x,y,z = getWorldTranslation(self.cameraPositionNode);
457 self.targetPosition[1] = x;
458 self.targetPosition[2] = y;
459 self.targetPosition[3] = z;
460
461 self.lastCamLookX, self.lastCamLookY, self.lastCamLookZ = xlook, ylook, zlook;
462 self.lastCamX, self.lastCamY, self.lastCamZ = x,y,z;
463
464 local rx,ry,rz = getWorldRotation(self.rotateNode);
465
466 --link(getRootNode(), self.cameraNode);
467 setRotation(self.cameraNode, rx,ry,rz);
468 --setDirection(self.cameraNode, x-xlook, y-ylook, z-zlook, 0, 1, 0);
469 setTranslation(self.cameraNode, x,y,z);
470 end;
471
472 --[[if (self.isInside) then
473 setActiveStateAdsOcclusionRegionGroup(AdSystemHelper.GROUP_VEHICLECAMERA, true);
474 end;]]
475end;
476
477function VehicleCamera:onDeactivate()
478 self:resetCamera();
479 self.isActivated = false;
480
481 --[[if (self.isInside) then
482 setActiveStateAdsOcclusionRegionGroup(AdSystemHelper.GROUP_VEHICLECAMERA, false);
483 end;]]
484end;
485
486function VehicleCamera:resetCamera()
487 self.rotX = self.origRotX;
488 self.rotY = self.origRotY;
489 self.rotZ = self.origRotZ;
490 --self.posXLast = -1;
491 --self.posYLast = -1;
492
493 self.transX = self.origTransX;
494 self.transY = self.origTransY;
495 self.transZ = self.origTransZ;
496
497 local transLength = Utils.vector3Length(self.origTransX, self.origTransY, self.origTransZ);
498 self.zoom = transLength
499 self.zoomTarget = transLength;
500 self.zoomLimitedTarget = -1;
501
502 --setRotation(self.rotateNode, self.rotX, self.rotY, self.rotZ);
503 self:updateRotateNodeRotation();
504 setTranslation(self.cameraPositionNode, self.transX, self.transY, self.transZ);
505
506 if self.positionSmoothingParameter > 0 then
507 local xlook,ylook,zlook = getWorldTranslation(self.rotateNode);
508 self.targetLookAtPosition[1] = xlook;
509 self.targetLookAtPosition[2] = ylook;
510 self.targetLookAtPosition[3] = zlook;
511 local x,y,z = getWorldTranslation(self.cameraPositionNode);
512 self.targetPosition[1] = x;
513 self.targetPosition[2] = y;
514 self.targetPosition[3] = z;
515
516 self.lastCamLookX, self.lastCamLookY, self.lastCamLookZ = xlook, ylook, zlook;
517 self.lastCamX, self.lastCamY, self.lastCamZ = x,y,z;
518
519 self:setSeparateCameraPose();
520 end;
521end;
522
523function VehicleCamera:updateRotateNodeRotation()
524 local rotY = self.rotY;
525 if self.rotYSteeringRotSpeed ~= 0 and self.vehicle.rotatedTime ~= nil then
526 rotY = rotY + self.vehicle.rotatedTime*self.rotYSteeringRotSpeed;
527 end
528
529 if self.useWorldXZRotation then
530 local upx,upy,upz = 0,1,0;
531
532 local dx,dy,dz = localDirectionToWorld(getParent(self.rotateNode), 0,0,1);
533 local invLen = 1/math.sqrt(dx*dx + dz*dz);
534 dx = dx*invLen;
535 dz = dz*invLen;
536
537
538
539 local newDx = math.cos(self.rotX) * (math.cos(rotY)*dx + math.sin(rotY)*dz);
540 local newDy = -math.sin(self.rotX);
541 local newDz = math.cos(self.rotX) * (-math.sin(rotY)*dx + math.cos(rotY)*dz);
542
543
544 newDx,newDy,newDz = worldDirectionToLocal(getParent(self.rotateNode), newDx,newDy,newDz);
545 upx,upy,upz = worldDirectionToLocal(getParent(self.rotateNode), upx,upy,upz);
546
547 setDirection(self.rotateNode, newDx,newDy,newDz, upx,upy,upz);
548 else
549 setRotation(self.rotateNode, self.rotX, rotY, self.rotZ);
550 end;
551end;
552
553function VehicleCamera:setSeparateCameraPose()
554 if self.rotateNode ~= self.cameraPositionNode then
555 local dx = self.targetPosition[1] - self.targetLookAtPosition[1];
556 local dy = self.targetPosition[2] - self.targetLookAtPosition[2];
557 local dz = self.targetPosition[3] - self.targetLookAtPosition[3];
558
559 local upx,upy,upz = 0,1,0;
560 if math.abs(dx) < 0.001 and math.abs(dz) < 0.001 then
561 upx = 0.1;
562 --upx,upy,upz = localDirectionToWorld(self.cameraNode, 0,1,0);
563 end;
564
565 --local dx,dy,dz = worldDirectionToLocal(getParent(self.cameraNode), self.targetPosition[1]-self.targetLookAtPosition[1], self.targetPosition[2]-self.targetLookAtPosition[2], self.targetPosition[3]-self.targetLookAtPosition[3]);
566 --local upx,upy,upz = worldDirectionToLocal(getParent(self.cameraNode), 0, 1, 0);
567 --local x,y,z = worldToLocal(getParent(self.cameraNode), self.targetPosition[1],self.targetPosition[2],self.targetPosition[3]);
568
569 setDirection(self.cameraNode, dx,dy,dz, upx,upy,upz);
570 else
571 local rx,ry,rz = getWorldRotation(self.rotateNode);
572 setRotation(self.cameraNode, rx,ry,rz);
573 end
574 setTranslation(self.cameraNode, self.targetPosition[1],self.targetPosition[2],self.targetPosition[3]);
575end;
576
577function VehicleCamera:getCollisionDistance()
578
579 local raycastMask = 32+64+128+256+4096;
580
581 local targetCamX, targetCamY, targetCamZ = localToWorld(self.rotateNode, self.transDirX*self.zoomTarget, self.transDirY*self.zoomTarget, self.transDirZ*self.zoomTarget);
582
583 local hasCollision = false;
584 local collisionDistance = -1;
585 local normalX,normalY,normalZ;
586 local normalDotDir;
587 for _, raycastNode in ipairs(self.raycastNodes) do
588
589 hasCollision = false;
590
591 local nodeX, nodeY, nodeZ = getWorldTranslation(raycastNode);
592 local dirX, dirY, dirZ = targetCamX-nodeX, targetCamY-nodeY, targetCamZ-nodeZ;
593 local dirLength = Utils.vector3Length(dirX, dirY, dirZ);
594 dirX = dirX / dirLength;
595 dirY = dirY / dirLength;
596 dirZ = dirZ / dirLength;
597
598 local startX = nodeX;
599 local startY = nodeY;
600 local startZ = nodeZ;
601 --local outsideObject = 0;
602 local currentDistance = 0;
603 local minDistance = self.transMin;
604 --local worldTransDirX, worldTransDirY, worldTransDirZ = localDirectionToWorld(self.rotateNode, self.transDirX, self.transDirY, self.transDirZ);
605 while (true) do
606 --local worldStartX, worldStartY, worldStartZ = localToWorld(self.rotateNode, startX, startY, startZ);
607 if (dirLength-currentDistance) <= 0 then
608 break;
609 end;
610 self.raycastDistance = 0;
611 raycastClosest(startX, startY, startZ, dirX, dirY, dirZ, "raycastCallback", dirLength-currentDistance, self, raycastMask, true);
612
613 if self.raycastDistance ~= 0 then
614 currentDistance = currentDistance + self.raycastDistance+0.001;
615 local ndotd = Utils.dotProduct(self.normalX, self.normalY, self.normalZ, dirX, dirY, dirZ);
616 if self.vehicle:getIsAttachedVehicleNode(self.raycastTransformId) or self.vehicle:getIsDynamicallyMountedNode(self.raycastTransformId) then
617 if ndotd > 0 then
618 --outsideObject = outsideObject +1;
619 minDistance = math.max(minDistance, currentDistance);
620 end;
621 else
622 hasCollision = true;
623 -- we take the distance from the rotate node
624 if raycastNode == self.rotateNode then
625 normalX,normalY,normalZ = self.normalX, self.normalY, self.normalZ;
626 collisionDistance = math.max(self.transMin, currentDistance);
627 normalDotDir = ndotd
628 end;
629 break;
630 end;
631 startX = nodeX+dirX*currentDistance;
632 startY = nodeY+dirY*currentDistance;
633 startZ = nodeZ+dirZ*currentDistance;
634 else
635 break;
636 end;
637 end;
638 if not hasCollision then
639 break;
640 end;
641 end;
642 return hasCollision, collisionDistance, normalX,normalY,normalZ, normalDotDir;
643end;
Copyright (c) 2008-2015 GIANTS Software GmbH, Confidential, All Rights Reserved.
This document is to be published solely by ls-mods.de
Script Dokumentation Übersicht