diff options
author | Robert Adams | 2015-09-08 04:54:16 -0700 |
---|---|---|
committer | Robert Adams | 2015-09-08 04:54:16 -0700 |
commit | e5367d822be9b05e74c859afe2d2956a3e95aa33 (patch) | |
tree | e904050a30715df587aa527d7f313755177726a7 /OpenSim/Region/PhysicsModules/Ode/ODEDynamics.cs | |
parent | add lost admin_reset_land method (diff) | |
parent | Deleted access control spec from [LoginService] section of standalone config.... (diff) | |
download | opensim-SC-e5367d822be9b05e74c859afe2d2956a3e95aa33.zip opensim-SC-e5367d822be9b05e74c859afe2d2956a3e95aa33.tar.gz opensim-SC-e5367d822be9b05e74c859afe2d2956a3e95aa33.tar.bz2 opensim-SC-e5367d822be9b05e74c859afe2d2956a3e95aa33.tar.xz |
Merge of ubitworkvarnew with opensim/master as of 20150905.
This integrates the OpenSim refactoring to make physics, etc into modules.
AVN physics hasn't been moved to new location.
Does not compile yet.
Merge branch 'osmaster' into mbworknew1
Diffstat (limited to 'OpenSim/Region/PhysicsModules/Ode/ODEDynamics.cs')
-rw-r--r-- | OpenSim/Region/PhysicsModules/Ode/ODEDynamics.cs | 974 |
1 files changed, 974 insertions, 0 deletions
diff --git a/OpenSim/Region/PhysicsModules/Ode/ODEDynamics.cs b/OpenSim/Region/PhysicsModules/Ode/ODEDynamics.cs new file mode 100644 index 0000000..8f8e2bd --- /dev/null +++ b/OpenSim/Region/PhysicsModules/Ode/ODEDynamics.cs | |||
@@ -0,0 +1,974 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSimulator Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
28 | /* Revised Aug, Sept 2009 by Kitto Flora. ODEDynamics.cs replaces | ||
29 | * ODEVehicleSettings.cs. It and ODEPrim.cs are re-organised: | ||
30 | * ODEPrim.cs contains methods dealing with Prim editing, Prim | ||
31 | * characteristics and Kinetic motion. | ||
32 | * ODEDynamics.cs contains methods dealing with Prim Physical motion | ||
33 | * (dynamics) and the associated settings. Old Linear and angular | ||
34 | * motors for dynamic motion have been replace with MoveLinear() | ||
35 | * and MoveAngular(); 'Physical' is used only to switch ODE dynamic | ||
36 | * simualtion on/off; VEHICAL_TYPE_NONE/VEHICAL_TYPE_<other> is to | ||
37 | * switch between 'VEHICLE' parameter use and general dynamics | ||
38 | * settings use. | ||
39 | */ | ||
40 | |||
41 | using System; | ||
42 | using System.Collections.Generic; | ||
43 | using System.Reflection; | ||
44 | using System.Runtime.InteropServices; | ||
45 | using log4net; | ||
46 | using OpenMetaverse; | ||
47 | using Ode.NET; | ||
48 | using OpenSim.Framework; | ||
49 | using OpenSim.Region.PhysicsModules.SharedBase; | ||
50 | |||
51 | namespace OpenSim.Region.PhysicsModule.ODE | ||
52 | { | ||
53 | public class ODEDynamics | ||
54 | { | ||
55 | public Vehicle Type | ||
56 | { | ||
57 | get { return m_type; } | ||
58 | } | ||
59 | |||
60 | public IntPtr Body | ||
61 | { | ||
62 | get { return m_body; } | ||
63 | } | ||
64 | |||
65 | private int frcount = 0; // Used to limit dynamics debug output to | ||
66 | // every 100th frame | ||
67 | |||
68 | // private OdeScene m_parentScene = null; | ||
69 | private IntPtr m_body = IntPtr.Zero; | ||
70 | // private IntPtr m_jointGroup = IntPtr.Zero; | ||
71 | // private IntPtr m_aMotor = IntPtr.Zero; | ||
72 | |||
73 | |||
74 | // Vehicle properties | ||
75 | private Vehicle m_type = Vehicle.TYPE_NONE; // If a 'VEHICLE', and what kind | ||
76 | // private Quaternion m_referenceFrame = Quaternion.Identity; // Axis modifier | ||
77 | private VehicleFlag m_flags = (VehicleFlag) 0; // Boolean settings: | ||
78 | // HOVER_TERRAIN_ONLY | ||
79 | // HOVER_GLOBAL_HEIGHT | ||
80 | // NO_DEFLECTION_UP | ||
81 | // HOVER_WATER_ONLY | ||
82 | // HOVER_UP_ONLY | ||
83 | // LIMIT_MOTOR_UP | ||
84 | // LIMIT_ROLL_ONLY | ||
85 | private VehicleFlag m_Hoverflags = (VehicleFlag)0; | ||
86 | private Vector3 m_BlockingEndPoint = Vector3.Zero; | ||
87 | private Quaternion m_RollreferenceFrame = Quaternion.Identity; | ||
88 | // Linear properties | ||
89 | private Vector3 m_linearMotorDirection = Vector3.Zero; // velocity requested by LSL, decayed by time | ||
90 | private Vector3 m_linearMotorDirectionLASTSET = Vector3.Zero; // velocity requested by LSL | ||
91 | private Vector3 m_dir = Vector3.Zero; // velocity applied to body | ||
92 | private Vector3 m_linearFrictionTimescale = Vector3.Zero; | ||
93 | private float m_linearMotorDecayTimescale = 0; | ||
94 | private float m_linearMotorTimescale = 0; | ||
95 | private Vector3 m_lastLinearVelocityVector = Vector3.Zero; | ||
96 | private d.Vector3 m_lastPositionVector = new d.Vector3(); | ||
97 | // private bool m_LinearMotorSetLastFrame = false; | ||
98 | // private Vector3 m_linearMotorOffset = Vector3.Zero; | ||
99 | |||
100 | //Angular properties | ||
101 | private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor | ||
102 | private int m_angularMotorApply = 0; // application frame counter | ||
103 | private Vector3 m_angularMotorVelocity = Vector3.Zero; // current angular motor velocity | ||
104 | private float m_angularMotorTimescale = 0; // motor angular velocity ramp up rate | ||
105 | private float m_angularMotorDecayTimescale = 0; // motor angular velocity decay rate | ||
106 | private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate | ||
107 | private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body | ||
108 | // private Vector3 m_lastVertAttractor = Vector3.Zero; // what VA was last applied to body | ||
109 | |||
110 | //Deflection properties | ||
111 | // private float m_angularDeflectionEfficiency = 0; | ||
112 | // private float m_angularDeflectionTimescale = 0; | ||
113 | // private float m_linearDeflectionEfficiency = 0; | ||
114 | // private float m_linearDeflectionTimescale = 0; | ||
115 | |||
116 | //Banking properties | ||
117 | // private float m_bankingEfficiency = 0; | ||
118 | // private float m_bankingMix = 0; | ||
119 | // private float m_bankingTimescale = 0; | ||
120 | |||
121 | //Hover and Buoyancy properties | ||
122 | private float m_VhoverHeight = 0f; | ||
123 | // private float m_VhoverEfficiency = 0f; | ||
124 | private float m_VhoverTimescale = 0f; | ||
125 | private float m_VhoverTargetHeight = -1.0f; // if <0 then no hover, else its the current target height | ||
126 | private float m_VehicleBuoyancy = 0f; //KF: m_VehicleBuoyancy is set by VEHICLE_BUOYANCY for a vehicle. | ||
127 | // Modifies gravity. Slider between -1 (double-gravity) and 1 (full anti-gravity) | ||
128 | // KF: So far I have found no good method to combine a script-requested .Z velocity and gravity. | ||
129 | // Therefore only m_VehicleBuoyancy=1 (0g) will use the script-requested .Z velocity. | ||
130 | |||
131 | //Attractor properties | ||
132 | private float m_verticalAttractionEfficiency = 1.0f; // damped | ||
133 | private float m_verticalAttractionTimescale = 500f; // Timescale > 300 means no vert attractor. | ||
134 | |||
135 | internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue) | ||
136 | { | ||
137 | switch (pParam) | ||
138 | { | ||
139 | case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY: | ||
140 | if (pValue < 0.01f) pValue = 0.01f; | ||
141 | // m_angularDeflectionEfficiency = pValue; | ||
142 | break; | ||
143 | case Vehicle.ANGULAR_DEFLECTION_TIMESCALE: | ||
144 | if (pValue < 0.01f) pValue = 0.01f; | ||
145 | // m_angularDeflectionTimescale = pValue; | ||
146 | break; | ||
147 | case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE: | ||
148 | if (pValue < 0.01f) pValue = 0.01f; | ||
149 | m_angularMotorDecayTimescale = pValue; | ||
150 | break; | ||
151 | case Vehicle.ANGULAR_MOTOR_TIMESCALE: | ||
152 | if (pValue < 0.01f) pValue = 0.01f; | ||
153 | m_angularMotorTimescale = pValue; | ||
154 | break; | ||
155 | case Vehicle.BANKING_EFFICIENCY: | ||
156 | if (pValue < 0.01f) pValue = 0.01f; | ||
157 | // m_bankingEfficiency = pValue; | ||
158 | break; | ||
159 | case Vehicle.BANKING_MIX: | ||
160 | if (pValue < 0.01f) pValue = 0.01f; | ||
161 | // m_bankingMix = pValue; | ||
162 | break; | ||
163 | case Vehicle.BANKING_TIMESCALE: | ||
164 | if (pValue < 0.01f) pValue = 0.01f; | ||
165 | // m_bankingTimescale = pValue; | ||
166 | break; | ||
167 | case Vehicle.BUOYANCY: | ||
168 | if (pValue < -1f) pValue = -1f; | ||
169 | if (pValue > 1f) pValue = 1f; | ||
170 | m_VehicleBuoyancy = pValue; | ||
171 | break; | ||
172 | // case Vehicle.HOVER_EFFICIENCY: | ||
173 | // if (pValue < 0f) pValue = 0f; | ||
174 | // if (pValue > 1f) pValue = 1f; | ||
175 | // m_VhoverEfficiency = pValue; | ||
176 | // break; | ||
177 | case Vehicle.HOVER_HEIGHT: | ||
178 | m_VhoverHeight = pValue; | ||
179 | break; | ||
180 | case Vehicle.HOVER_TIMESCALE: | ||
181 | if (pValue < 0.01f) pValue = 0.01f; | ||
182 | m_VhoverTimescale = pValue; | ||
183 | break; | ||
184 | case Vehicle.LINEAR_DEFLECTION_EFFICIENCY: | ||
185 | if (pValue < 0.01f) pValue = 0.01f; | ||
186 | // m_linearDeflectionEfficiency = pValue; | ||
187 | break; | ||
188 | case Vehicle.LINEAR_DEFLECTION_TIMESCALE: | ||
189 | if (pValue < 0.01f) pValue = 0.01f; | ||
190 | // m_linearDeflectionTimescale = pValue; | ||
191 | break; | ||
192 | case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE: | ||
193 | if (pValue < 0.01f) pValue = 0.01f; | ||
194 | m_linearMotorDecayTimescale = pValue; | ||
195 | break; | ||
196 | case Vehicle.LINEAR_MOTOR_TIMESCALE: | ||
197 | if (pValue < 0.01f) pValue = 0.01f; | ||
198 | m_linearMotorTimescale = pValue; | ||
199 | break; | ||
200 | case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY: | ||
201 | if (pValue < 0.1f) pValue = 0.1f; // Less goes unstable | ||
202 | if (pValue > 1.0f) pValue = 1.0f; | ||
203 | m_verticalAttractionEfficiency = pValue; | ||
204 | break; | ||
205 | case Vehicle.VERTICAL_ATTRACTION_TIMESCALE: | ||
206 | if (pValue < 0.01f) pValue = 0.01f; | ||
207 | m_verticalAttractionTimescale = pValue; | ||
208 | break; | ||
209 | |||
210 | // These are vector properties but the engine lets you use a single float value to | ||
211 | // set all of the components to the same value | ||
212 | case Vehicle.ANGULAR_FRICTION_TIMESCALE: | ||
213 | m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue); | ||
214 | break; | ||
215 | case Vehicle.ANGULAR_MOTOR_DIRECTION: | ||
216 | m_angularMotorDirection = new Vector3(pValue, pValue, pValue); | ||
217 | m_angularMotorApply = 10; | ||
218 | break; | ||
219 | case Vehicle.LINEAR_FRICTION_TIMESCALE: | ||
220 | m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue); | ||
221 | break; | ||
222 | case Vehicle.LINEAR_MOTOR_DIRECTION: | ||
223 | m_linearMotorDirection = new Vector3(pValue, pValue, pValue); | ||
224 | m_linearMotorDirectionLASTSET = new Vector3(pValue, pValue, pValue); | ||
225 | break; | ||
226 | case Vehicle.LINEAR_MOTOR_OFFSET: | ||
227 | // m_linearMotorOffset = new Vector3(pValue, pValue, pValue); | ||
228 | break; | ||
229 | |||
230 | } | ||
231 | }//end ProcessFloatVehicleParam | ||
232 | |||
233 | internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue) | ||
234 | { | ||
235 | switch (pParam) | ||
236 | { | ||
237 | case Vehicle.ANGULAR_FRICTION_TIMESCALE: | ||
238 | m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); | ||
239 | break; | ||
240 | case Vehicle.ANGULAR_MOTOR_DIRECTION: | ||
241 | m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); | ||
242 | // Limit requested angular speed to 2 rps= 4 pi rads/sec | ||
243 | if (m_angularMotorDirection.X > 12.56f) m_angularMotorDirection.X = 12.56f; | ||
244 | if (m_angularMotorDirection.X < - 12.56f) m_angularMotorDirection.X = - 12.56f; | ||
245 | if (m_angularMotorDirection.Y > 12.56f) m_angularMotorDirection.Y = 12.56f; | ||
246 | if (m_angularMotorDirection.Y < - 12.56f) m_angularMotorDirection.Y = - 12.56f; | ||
247 | if (m_angularMotorDirection.Z > 12.56f) m_angularMotorDirection.Z = 12.56f; | ||
248 | if (m_angularMotorDirection.Z < - 12.56f) m_angularMotorDirection.Z = - 12.56f; | ||
249 | m_angularMotorApply = 10; | ||
250 | break; | ||
251 | case Vehicle.LINEAR_FRICTION_TIMESCALE: | ||
252 | m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); | ||
253 | break; | ||
254 | case Vehicle.LINEAR_MOTOR_DIRECTION: | ||
255 | m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); | ||
256 | m_linearMotorDirectionLASTSET = new Vector3(pValue.X, pValue.Y, pValue.Z); | ||
257 | break; | ||
258 | case Vehicle.LINEAR_MOTOR_OFFSET: | ||
259 | // m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z); | ||
260 | break; | ||
261 | case Vehicle.BLOCK_EXIT: | ||
262 | m_BlockingEndPoint = new Vector3(pValue.X, pValue.Y, pValue.Z); | ||
263 | break; | ||
264 | } | ||
265 | }//end ProcessVectorVehicleParam | ||
266 | |||
267 | internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue) | ||
268 | { | ||
269 | switch (pParam) | ||
270 | { | ||
271 | case Vehicle.REFERENCE_FRAME: | ||
272 | // m_referenceFrame = pValue; | ||
273 | break; | ||
274 | case Vehicle.ROLL_FRAME: | ||
275 | m_RollreferenceFrame = pValue; | ||
276 | break; | ||
277 | } | ||
278 | }//end ProcessRotationVehicleParam | ||
279 | |||
280 | internal void ProcessVehicleFlags(int pParam, bool remove) | ||
281 | { | ||
282 | if (remove) | ||
283 | { | ||
284 | if (pParam == -1) | ||
285 | { | ||
286 | m_flags = (VehicleFlag)0; | ||
287 | m_Hoverflags = (VehicleFlag)0; | ||
288 | return; | ||
289 | } | ||
290 | if ((pParam & (int)VehicleFlag.HOVER_GLOBAL_HEIGHT) == (int)VehicleFlag.HOVER_GLOBAL_HEIGHT) | ||
291 | { | ||
292 | if ((m_Hoverflags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != (VehicleFlag)0) | ||
293 | m_Hoverflags &= ~(VehicleFlag.HOVER_GLOBAL_HEIGHT); | ||
294 | } | ||
295 | if ((pParam & (int)VehicleFlag.HOVER_TERRAIN_ONLY) == (int)VehicleFlag.HOVER_TERRAIN_ONLY) | ||
296 | { | ||
297 | if ((m_Hoverflags & VehicleFlag.HOVER_TERRAIN_ONLY) != (VehicleFlag)0) | ||
298 | m_Hoverflags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY); | ||
299 | } | ||
300 | if ((pParam & (int)VehicleFlag.HOVER_UP_ONLY) == (int)VehicleFlag.HOVER_UP_ONLY) | ||
301 | { | ||
302 | if ((m_Hoverflags & VehicleFlag.HOVER_UP_ONLY) != (VehicleFlag)0) | ||
303 | m_Hoverflags &= ~(VehicleFlag.HOVER_UP_ONLY); | ||
304 | } | ||
305 | if ((pParam & (int)VehicleFlag.HOVER_WATER_ONLY) == (int)VehicleFlag.HOVER_WATER_ONLY) | ||
306 | { | ||
307 | if ((m_Hoverflags & VehicleFlag.HOVER_WATER_ONLY) != (VehicleFlag)0) | ||
308 | m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY); | ||
309 | } | ||
310 | if ((pParam & (int)VehicleFlag.LIMIT_MOTOR_UP) == (int)VehicleFlag.LIMIT_MOTOR_UP) | ||
311 | { | ||
312 | if ((m_flags & VehicleFlag.LIMIT_MOTOR_UP) != (VehicleFlag)0) | ||
313 | m_flags &= ~(VehicleFlag.LIMIT_MOTOR_UP); | ||
314 | } | ||
315 | if ((pParam & (int)VehicleFlag.LIMIT_ROLL_ONLY) == (int)VehicleFlag.LIMIT_ROLL_ONLY) | ||
316 | { | ||
317 | if ((m_flags & VehicleFlag.LIMIT_ROLL_ONLY) != (VehicleFlag)0) | ||
318 | m_flags &= ~(VehicleFlag.LIMIT_ROLL_ONLY); | ||
319 | } | ||
320 | if ((pParam & (int)VehicleFlag.MOUSELOOK_BANK) == (int)VehicleFlag.MOUSELOOK_BANK) | ||
321 | { | ||
322 | if ((m_flags & VehicleFlag.MOUSELOOK_BANK) != (VehicleFlag)0) | ||
323 | m_flags &= ~(VehicleFlag.MOUSELOOK_BANK); | ||
324 | } | ||
325 | if ((pParam & (int)VehicleFlag.MOUSELOOK_STEER) == (int)VehicleFlag.MOUSELOOK_STEER) | ||
326 | { | ||
327 | if ((m_flags & VehicleFlag.MOUSELOOK_STEER) != (VehicleFlag)0) | ||
328 | m_flags &= ~(VehicleFlag.MOUSELOOK_STEER); | ||
329 | } | ||
330 | if ((pParam & (int)VehicleFlag.NO_DEFLECTION_UP) == (int)VehicleFlag.NO_DEFLECTION_UP) | ||
331 | { | ||
332 | if ((m_flags & VehicleFlag.NO_DEFLECTION_UP) != (VehicleFlag)0) | ||
333 | m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP); | ||
334 | } | ||
335 | if ((pParam & (int)VehicleFlag.CAMERA_DECOUPLED) == (int)VehicleFlag.CAMERA_DECOUPLED) | ||
336 | { | ||
337 | if ((m_flags & VehicleFlag.CAMERA_DECOUPLED) != (VehicleFlag)0) | ||
338 | m_flags &= ~(VehicleFlag.CAMERA_DECOUPLED); | ||
339 | } | ||
340 | if ((pParam & (int)VehicleFlag.NO_X) == (int)VehicleFlag.NO_X) | ||
341 | { | ||
342 | if ((m_flags & VehicleFlag.NO_X) != (VehicleFlag)0) | ||
343 | m_flags &= ~(VehicleFlag.NO_X); | ||
344 | } | ||
345 | if ((pParam & (int)VehicleFlag.NO_Y) == (int)VehicleFlag.NO_Y) | ||
346 | { | ||
347 | if ((m_flags & VehicleFlag.NO_Y) != (VehicleFlag)0) | ||
348 | m_flags &= ~(VehicleFlag.NO_Y); | ||
349 | } | ||
350 | if ((pParam & (int)VehicleFlag.NO_Z) == (int)VehicleFlag.NO_Z) | ||
351 | { | ||
352 | if ((m_flags & VehicleFlag.NO_Z) != (VehicleFlag)0) | ||
353 | m_flags &= ~(VehicleFlag.NO_Z); | ||
354 | } | ||
355 | if ((pParam & (int)VehicleFlag.LOCK_HOVER_HEIGHT) == (int)VehicleFlag.LOCK_HOVER_HEIGHT) | ||
356 | { | ||
357 | if ((m_Hoverflags & VehicleFlag.LOCK_HOVER_HEIGHT) != (VehicleFlag)0) | ||
358 | m_Hoverflags &= ~(VehicleFlag.LOCK_HOVER_HEIGHT); | ||
359 | } | ||
360 | if ((pParam & (int)VehicleFlag.NO_DEFLECTION) == (int)VehicleFlag.NO_DEFLECTION) | ||
361 | { | ||
362 | if ((m_flags & VehicleFlag.NO_DEFLECTION) != (VehicleFlag)0) | ||
363 | m_flags &= ~(VehicleFlag.NO_DEFLECTION); | ||
364 | } | ||
365 | if ((pParam & (int)VehicleFlag.LOCK_ROTATION) == (int)VehicleFlag.LOCK_ROTATION) | ||
366 | { | ||
367 | if ((m_flags & VehicleFlag.LOCK_ROTATION) != (VehicleFlag)0) | ||
368 | m_flags &= ~(VehicleFlag.LOCK_ROTATION); | ||
369 | } | ||
370 | } | ||
371 | else | ||
372 | { | ||
373 | if ((pParam & (int)VehicleFlag.HOVER_GLOBAL_HEIGHT) == (int)VehicleFlag.HOVER_GLOBAL_HEIGHT) | ||
374 | { | ||
375 | m_Hoverflags |= (VehicleFlag.HOVER_GLOBAL_HEIGHT | m_flags); | ||
376 | } | ||
377 | if ((pParam & (int)VehicleFlag.HOVER_TERRAIN_ONLY) == (int)VehicleFlag.HOVER_TERRAIN_ONLY) | ||
378 | { | ||
379 | m_Hoverflags |= (VehicleFlag.HOVER_TERRAIN_ONLY | m_flags); | ||
380 | } | ||
381 | if ((pParam & (int)VehicleFlag.HOVER_UP_ONLY) == (int)VehicleFlag.HOVER_UP_ONLY) | ||
382 | { | ||
383 | m_Hoverflags |= (VehicleFlag.HOVER_UP_ONLY | m_flags); | ||
384 | } | ||
385 | if ((pParam & (int)VehicleFlag.HOVER_WATER_ONLY) == (int)VehicleFlag.HOVER_WATER_ONLY) | ||
386 | { | ||
387 | m_Hoverflags |= (VehicleFlag.HOVER_WATER_ONLY | m_flags); | ||
388 | } | ||
389 | if ((pParam & (int)VehicleFlag.LIMIT_MOTOR_UP) == (int)VehicleFlag.LIMIT_MOTOR_UP) | ||
390 | { | ||
391 | m_flags |= (VehicleFlag.LIMIT_MOTOR_UP | m_flags); | ||
392 | } | ||
393 | if ((pParam & (int)VehicleFlag.MOUSELOOK_BANK) == (int)VehicleFlag.MOUSELOOK_BANK) | ||
394 | { | ||
395 | m_flags |= (VehicleFlag.MOUSELOOK_BANK | m_flags); | ||
396 | } | ||
397 | if ((pParam & (int)VehicleFlag.MOUSELOOK_STEER) == (int)VehicleFlag.MOUSELOOK_STEER) | ||
398 | { | ||
399 | m_flags |= (VehicleFlag.MOUSELOOK_STEER | m_flags); | ||
400 | } | ||
401 | if ((pParam & (int)VehicleFlag.NO_DEFLECTION_UP) == (int)VehicleFlag.NO_DEFLECTION_UP) | ||
402 | { | ||
403 | m_flags |= (VehicleFlag.NO_DEFLECTION_UP | m_flags); | ||
404 | } | ||
405 | if ((pParam & (int)VehicleFlag.CAMERA_DECOUPLED) == (int)VehicleFlag.CAMERA_DECOUPLED) | ||
406 | { | ||
407 | m_flags |= (VehicleFlag.CAMERA_DECOUPLED | m_flags); | ||
408 | } | ||
409 | if ((pParam & (int)VehicleFlag.NO_X) == (int)VehicleFlag.NO_X) | ||
410 | { | ||
411 | m_flags |= (VehicleFlag.NO_X); | ||
412 | } | ||
413 | if ((pParam & (int)VehicleFlag.NO_Y) == (int)VehicleFlag.NO_Y) | ||
414 | { | ||
415 | m_flags |= (VehicleFlag.NO_Y); | ||
416 | } | ||
417 | if ((pParam & (int)VehicleFlag.NO_Z) == (int)VehicleFlag.NO_Z) | ||
418 | { | ||
419 | m_flags |= (VehicleFlag.NO_Z); | ||
420 | } | ||
421 | if ((pParam & (int)VehicleFlag.LOCK_HOVER_HEIGHT) == (int)VehicleFlag.LOCK_HOVER_HEIGHT) | ||
422 | { | ||
423 | m_Hoverflags |= (VehicleFlag.LOCK_HOVER_HEIGHT); | ||
424 | } | ||
425 | if ((pParam & (int)VehicleFlag.NO_DEFLECTION) == (int)VehicleFlag.NO_DEFLECTION) | ||
426 | { | ||
427 | m_flags |= (VehicleFlag.NO_DEFLECTION); | ||
428 | } | ||
429 | if ((pParam & (int)VehicleFlag.LOCK_ROTATION) == (int)VehicleFlag.LOCK_ROTATION) | ||
430 | { | ||
431 | m_flags |= (VehicleFlag.LOCK_ROTATION); | ||
432 | } | ||
433 | } | ||
434 | }//end ProcessVehicleFlags | ||
435 | |||
436 | internal void ProcessTypeChange(Vehicle pType) | ||
437 | { | ||
438 | // Set Defaults For Type | ||
439 | m_type = pType; | ||
440 | switch (pType) | ||
441 | { | ||
442 | case Vehicle.TYPE_NONE: | ||
443 | m_linearFrictionTimescale = new Vector3(0, 0, 0); | ||
444 | m_angularFrictionTimescale = new Vector3(0, 0, 0); | ||
445 | m_linearMotorDirection = Vector3.Zero; | ||
446 | m_linearMotorTimescale = 0; | ||
447 | m_linearMotorDecayTimescale = 0; | ||
448 | m_angularMotorDirection = Vector3.Zero; | ||
449 | m_angularMotorTimescale = 0; | ||
450 | m_angularMotorDecayTimescale = 0; | ||
451 | m_VhoverHeight = 0; | ||
452 | m_VhoverTimescale = 0; | ||
453 | m_VehicleBuoyancy = 0; | ||
454 | m_flags = (VehicleFlag)0; | ||
455 | break; | ||
456 | |||
457 | case Vehicle.TYPE_SLED: | ||
458 | m_linearFrictionTimescale = new Vector3(30, 1, 1000); | ||
459 | m_angularFrictionTimescale = new Vector3(1000, 1000, 1000); | ||
460 | m_linearMotorDirection = Vector3.Zero; | ||
461 | m_linearMotorTimescale = 1000; | ||
462 | m_linearMotorDecayTimescale = 120; | ||
463 | m_angularMotorDirection = Vector3.Zero; | ||
464 | m_angularMotorTimescale = 1000; | ||
465 | m_angularMotorDecayTimescale = 120; | ||
466 | m_VhoverHeight = 0; | ||
467 | // m_VhoverEfficiency = 1; | ||
468 | m_VhoverTimescale = 10; | ||
469 | m_VehicleBuoyancy = 0; | ||
470 | // m_linearDeflectionEfficiency = 1; | ||
471 | // m_linearDeflectionTimescale = 1; | ||
472 | // m_angularDeflectionEfficiency = 1; | ||
473 | // m_angularDeflectionTimescale = 1000; | ||
474 | // m_bankingEfficiency = 0; | ||
475 | // m_bankingMix = 1; | ||
476 | // m_bankingTimescale = 10; | ||
477 | // m_referenceFrame = Quaternion.Identity; | ||
478 | m_Hoverflags &= | ||
479 | ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | | ||
480 | VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); | ||
481 | m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP); | ||
482 | break; | ||
483 | case Vehicle.TYPE_CAR: | ||
484 | m_linearFrictionTimescale = new Vector3(100, 2, 1000); | ||
485 | m_angularFrictionTimescale = new Vector3(1000, 1000, 1000); | ||
486 | m_linearMotorDirection = Vector3.Zero; | ||
487 | m_linearMotorTimescale = 1; | ||
488 | m_linearMotorDecayTimescale = 60; | ||
489 | m_angularMotorDirection = Vector3.Zero; | ||
490 | m_angularMotorTimescale = 1; | ||
491 | m_angularMotorDecayTimescale = 0.8f; | ||
492 | m_VhoverHeight = 0; | ||
493 | // m_VhoverEfficiency = 0; | ||
494 | m_VhoverTimescale = 1000; | ||
495 | m_VehicleBuoyancy = 0; | ||
496 | // // m_linearDeflectionEfficiency = 1; | ||
497 | // // m_linearDeflectionTimescale = 2; | ||
498 | // // m_angularDeflectionEfficiency = 0; | ||
499 | // m_angularDeflectionTimescale = 10; | ||
500 | m_verticalAttractionEfficiency = 1f; | ||
501 | m_verticalAttractionTimescale = 10f; | ||
502 | // m_bankingEfficiency = -0.2f; | ||
503 | // m_bankingMix = 1; | ||
504 | // m_bankingTimescale = 1; | ||
505 | // m_referenceFrame = Quaternion.Identity; | ||
506 | m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT); | ||
507 | m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | | ||
508 | VehicleFlag.LIMIT_MOTOR_UP); | ||
509 | m_Hoverflags |= (VehicleFlag.HOVER_UP_ONLY); | ||
510 | break; | ||
511 | case Vehicle.TYPE_BOAT: | ||
512 | m_linearFrictionTimescale = new Vector3(10, 3, 2); | ||
513 | m_angularFrictionTimescale = new Vector3(10,10,10); | ||
514 | m_linearMotorDirection = Vector3.Zero; | ||
515 | m_linearMotorTimescale = 5; | ||
516 | m_linearMotorDecayTimescale = 60; | ||
517 | m_angularMotorDirection = Vector3.Zero; | ||
518 | m_angularMotorTimescale = 4; | ||
519 | m_angularMotorDecayTimescale = 4; | ||
520 | m_VhoverHeight = 0; | ||
521 | // m_VhoverEfficiency = 0.5f; | ||
522 | m_VhoverTimescale = 2; | ||
523 | m_VehicleBuoyancy = 1; | ||
524 | // m_linearDeflectionEfficiency = 0.5f; | ||
525 | // m_linearDeflectionTimescale = 3; | ||
526 | // m_angularDeflectionEfficiency = 0.5f; | ||
527 | // m_angularDeflectionTimescale = 5; | ||
528 | m_verticalAttractionEfficiency = 0.5f; | ||
529 | m_verticalAttractionTimescale = 5f; | ||
530 | // m_bankingEfficiency = -0.3f; | ||
531 | // m_bankingMix = 0.8f; | ||
532 | // m_bankingTimescale = 1; | ||
533 | // m_referenceFrame = Quaternion.Identity; | ||
534 | m_Hoverflags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY | | ||
535 | VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); | ||
536 | m_flags &= ~(VehicleFlag.LIMIT_ROLL_ONLY); | ||
537 | m_flags |= (VehicleFlag.NO_DEFLECTION_UP | | ||
538 | VehicleFlag.LIMIT_MOTOR_UP); | ||
539 | m_Hoverflags |= (VehicleFlag.HOVER_WATER_ONLY); | ||
540 | break; | ||
541 | case Vehicle.TYPE_AIRPLANE: | ||
542 | m_linearFrictionTimescale = new Vector3(200, 10, 5); | ||
543 | m_angularFrictionTimescale = new Vector3(20, 20, 20); | ||
544 | m_linearMotorDirection = Vector3.Zero; | ||
545 | m_linearMotorTimescale = 2; | ||
546 | m_linearMotorDecayTimescale = 60; | ||
547 | m_angularMotorDirection = Vector3.Zero; | ||
548 | m_angularMotorTimescale = 4; | ||
549 | m_angularMotorDecayTimescale = 4; | ||
550 | m_VhoverHeight = 0; | ||
551 | // m_VhoverEfficiency = 0.5f; | ||
552 | m_VhoverTimescale = 1000; | ||
553 | m_VehicleBuoyancy = 0; | ||
554 | // m_linearDeflectionEfficiency = 0.5f; | ||
555 | // m_linearDeflectionTimescale = 3; | ||
556 | // m_angularDeflectionEfficiency = 1; | ||
557 | // m_angularDeflectionTimescale = 2; | ||
558 | m_verticalAttractionEfficiency = 0.9f; | ||
559 | m_verticalAttractionTimescale = 2f; | ||
560 | // m_bankingEfficiency = 1; | ||
561 | // m_bankingMix = 0.7f; | ||
562 | // m_bankingTimescale = 2; | ||
563 | // m_referenceFrame = Quaternion.Identity; | ||
564 | m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | | ||
565 | VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); | ||
566 | m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_MOTOR_UP); | ||
567 | m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY); | ||
568 | break; | ||
569 | case Vehicle.TYPE_BALLOON: | ||
570 | m_linearFrictionTimescale = new Vector3(5, 5, 5); | ||
571 | m_angularFrictionTimescale = new Vector3(10, 10, 10); | ||
572 | m_linearMotorDirection = Vector3.Zero; | ||
573 | m_linearMotorTimescale = 5; | ||
574 | m_linearMotorDecayTimescale = 60; | ||
575 | m_angularMotorDirection = Vector3.Zero; | ||
576 | m_angularMotorTimescale = 6; | ||
577 | m_angularMotorDecayTimescale = 10; | ||
578 | m_VhoverHeight = 5; | ||
579 | // m_VhoverEfficiency = 0.8f; | ||
580 | m_VhoverTimescale = 10; | ||
581 | m_VehicleBuoyancy = 1; | ||
582 | // m_linearDeflectionEfficiency = 0; | ||
583 | // m_linearDeflectionTimescale = 5; | ||
584 | // m_angularDeflectionEfficiency = 0; | ||
585 | // m_angularDeflectionTimescale = 5; | ||
586 | m_verticalAttractionEfficiency = 1f; | ||
587 | m_verticalAttractionTimescale = 100f; | ||
588 | // m_bankingEfficiency = 0; | ||
589 | // m_bankingMix = 0.7f; | ||
590 | // m_bankingTimescale = 5; | ||
591 | // m_referenceFrame = Quaternion.Identity; | ||
592 | m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | | ||
593 | VehicleFlag.HOVER_UP_ONLY); | ||
594 | m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_MOTOR_UP); | ||
595 | m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY); | ||
596 | m_Hoverflags |= (VehicleFlag.HOVER_GLOBAL_HEIGHT); | ||
597 | break; | ||
598 | |||
599 | } | ||
600 | }//end SetDefaultsForType | ||
601 | |||
602 | internal void Enable(IntPtr pBody, OdeScene pParentScene) | ||
603 | { | ||
604 | if (m_type == Vehicle.TYPE_NONE) | ||
605 | return; | ||
606 | |||
607 | m_body = pBody; | ||
608 | } | ||
609 | |||
610 | internal void Step(float pTimestep, OdeScene pParentScene) | ||
611 | { | ||
612 | if (m_body == IntPtr.Zero || m_type == Vehicle.TYPE_NONE) | ||
613 | return; | ||
614 | frcount++; // used to limit debug comment output | ||
615 | if (frcount > 100) | ||
616 | frcount = 0; | ||
617 | |||
618 | MoveLinear(pTimestep, pParentScene); | ||
619 | MoveAngular(pTimestep); | ||
620 | LimitRotation(pTimestep); | ||
621 | }// end Step | ||
622 | |||
623 | private void MoveLinear(float pTimestep, OdeScene _pParentScene) | ||
624 | { | ||
625 | if (!m_linearMotorDirection.ApproxEquals(Vector3.Zero, 0.01f)) // requested m_linearMotorDirection is significant | ||
626 | { | ||
627 | if (!d.BodyIsEnabled(Body)) | ||
628 | d.BodyEnable(Body); | ||
629 | |||
630 | // add drive to body | ||
631 | Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale/pTimestep); | ||
632 | m_lastLinearVelocityVector += (addAmount*10); // lastLinearVelocityVector is the current body velocity vector? | ||
633 | |||
634 | // This will work temporarily, but we really need to compare speed on an axis | ||
635 | // KF: Limit body velocity to applied velocity? | ||
636 | if (Math.Abs(m_lastLinearVelocityVector.X) > Math.Abs(m_linearMotorDirectionLASTSET.X)) | ||
637 | m_lastLinearVelocityVector.X = m_linearMotorDirectionLASTSET.X; | ||
638 | if (Math.Abs(m_lastLinearVelocityVector.Y) > Math.Abs(m_linearMotorDirectionLASTSET.Y)) | ||
639 | m_lastLinearVelocityVector.Y = m_linearMotorDirectionLASTSET.Y; | ||
640 | if (Math.Abs(m_lastLinearVelocityVector.Z) > Math.Abs(m_linearMotorDirectionLASTSET.Z)) | ||
641 | m_lastLinearVelocityVector.Z = m_linearMotorDirectionLASTSET.Z; | ||
642 | |||
643 | // decay applied velocity | ||
644 | Vector3 decayfraction = ((Vector3.One/(m_linearMotorDecayTimescale/pTimestep))); | ||
645 | //Console.WriteLine("decay: " + decayfraction); | ||
646 | m_linearMotorDirection -= m_linearMotorDirection * decayfraction * 0.5f; | ||
647 | //Console.WriteLine("actual: " + m_linearMotorDirection); | ||
648 | } | ||
649 | else | ||
650 | { // requested is not significant | ||
651 | // if what remains of applied is small, zero it. | ||
652 | if (m_lastLinearVelocityVector.ApproxEquals(Vector3.Zero, 0.01f)) | ||
653 | m_lastLinearVelocityVector = Vector3.Zero; | ||
654 | } | ||
655 | |||
656 | // convert requested object velocity to world-referenced vector | ||
657 | m_dir = m_lastLinearVelocityVector; | ||
658 | d.Quaternion rot = d.BodyGetQuaternion(Body); | ||
659 | Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); // rotq = rotation of object | ||
660 | m_dir *= rotq; // apply obj rotation to velocity vector | ||
661 | |||
662 | // add Gravity andBuoyancy | ||
663 | // KF: So far I have found no good method to combine a script-requested | ||
664 | // .Z velocity and gravity. Therefore only 0g will used script-requested | ||
665 | // .Z velocity. >0g (m_VehicleBuoyancy < 1) will used modified gravity only. | ||
666 | Vector3 grav = Vector3.Zero; | ||
667 | // There is some gravity, make a gravity force vector | ||
668 | // that is applied after object velocity. | ||
669 | d.Mass objMass; | ||
670 | d.BodyGetMass(Body, out objMass); | ||
671 | // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; | ||
672 | grav.Z = _pParentScene.gravityz * objMass.mass * (1f - m_VehicleBuoyancy); | ||
673 | // Preserve the current Z velocity | ||
674 | d.Vector3 vel_now = d.BodyGetLinearVel(Body); | ||
675 | m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity | ||
676 | |||
677 | d.Vector3 pos = d.BodyGetPosition(Body); | ||
678 | // Vector3 accel = new Vector3(-(m_dir.X - m_lastLinearVelocityVector.X / 0.1f), -(m_dir.Y - m_lastLinearVelocityVector.Y / 0.1f), m_dir.Z - m_lastLinearVelocityVector.Z / 0.1f); | ||
679 | Vector3 posChange = new Vector3(); | ||
680 | posChange.X = pos.X - m_lastPositionVector.X; | ||
681 | posChange.Y = pos.Y - m_lastPositionVector.Y; | ||
682 | posChange.Z = pos.Z - m_lastPositionVector.Z; | ||
683 | double Zchange = Math.Abs(posChange.Z); | ||
684 | if (m_BlockingEndPoint != Vector3.Zero) | ||
685 | { | ||
686 | if (pos.X >= (m_BlockingEndPoint.X - (float)1)) | ||
687 | { | ||
688 | pos.X -= posChange.X + 1; | ||
689 | d.BodySetPosition(Body, pos.X, pos.Y, pos.Z); | ||
690 | } | ||
691 | if (pos.Y >= (m_BlockingEndPoint.Y - (float)1)) | ||
692 | { | ||
693 | pos.Y -= posChange.Y + 1; | ||
694 | d.BodySetPosition(Body, pos.X, pos.Y, pos.Z); | ||
695 | } | ||
696 | if (pos.Z >= (m_BlockingEndPoint.Z - (float)1)) | ||
697 | { | ||
698 | pos.Z -= posChange.Z + 1; | ||
699 | d.BodySetPosition(Body, pos.X, pos.Y, pos.Z); | ||
700 | } | ||
701 | if (pos.X <= 0) | ||
702 | { | ||
703 | pos.X += posChange.X + 1; | ||
704 | d.BodySetPosition(Body, pos.X, pos.Y, pos.Z); | ||
705 | } | ||
706 | if (pos.Y <= 0) | ||
707 | { | ||
708 | pos.Y += posChange.Y + 1; | ||
709 | d.BodySetPosition(Body, pos.X, pos.Y, pos.Z); | ||
710 | } | ||
711 | } | ||
712 | if (pos.Z < _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y)) | ||
713 | { | ||
714 | pos.Z = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y) + 2; | ||
715 | d.BodySetPosition(Body, pos.X, pos.Y, pos.Z); | ||
716 | } | ||
717 | |||
718 | // Check if hovering | ||
719 | if ((m_Hoverflags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0) | ||
720 | { | ||
721 | // We should hover, get the target height | ||
722 | if ((m_Hoverflags & VehicleFlag.HOVER_WATER_ONLY) != 0) | ||
723 | { | ||
724 | m_VhoverTargetHeight = _pParentScene.GetWaterLevel() + m_VhoverHeight; | ||
725 | } | ||
726 | if ((m_Hoverflags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0) | ||
727 | { | ||
728 | m_VhoverTargetHeight = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight; | ||
729 | } | ||
730 | if ((m_Hoverflags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0) | ||
731 | { | ||
732 | m_VhoverTargetHeight = m_VhoverHeight; | ||
733 | } | ||
734 | |||
735 | if ((m_Hoverflags & VehicleFlag.HOVER_UP_ONLY) != 0) | ||
736 | { | ||
737 | // If body is aready heigher, use its height as target height | ||
738 | if (pos.Z > m_VhoverTargetHeight) m_VhoverTargetHeight = pos.Z; | ||
739 | } | ||
740 | if ((m_Hoverflags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0) | ||
741 | { | ||
742 | if ((pos.Z - m_VhoverTargetHeight) > .2 || (pos.Z - m_VhoverTargetHeight) < -.2) | ||
743 | { | ||
744 | d.BodySetPosition(Body, pos.X, pos.Y, m_VhoverTargetHeight); | ||
745 | } | ||
746 | } | ||
747 | else | ||
748 | { | ||
749 | float herr0 = pos.Z - m_VhoverTargetHeight; | ||
750 | // Replace Vertical speed with correction figure if significant | ||
751 | if (Math.Abs(herr0) > 0.01f) | ||
752 | { | ||
753 | m_dir.Z = -((herr0 * pTimestep * 50.0f) / m_VhoverTimescale); | ||
754 | //KF: m_VhoverEfficiency is not yet implemented | ||
755 | } | ||
756 | else | ||
757 | { | ||
758 | m_dir.Z = 0f; | ||
759 | } | ||
760 | } | ||
761 | |||
762 | // m_VhoverEfficiency = 0f; // 0=boucy, 1=Crit.damped | ||
763 | // m_VhoverTimescale = 0f; // time to acheive height | ||
764 | // pTimestep is time since last frame,in secs | ||
765 | } | ||
766 | |||
767 | if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0) | ||
768 | { | ||
769 | //Start Experimental Values | ||
770 | if (Zchange > .3) | ||
771 | { | ||
772 | grav.Z = (float)(grav.Z * 3); | ||
773 | } | ||
774 | if (Zchange > .15) | ||
775 | { | ||
776 | grav.Z = (float)(grav.Z * 2); | ||
777 | } | ||
778 | if (Zchange > .75) | ||
779 | { | ||
780 | grav.Z = (float)(grav.Z * 1.5); | ||
781 | } | ||
782 | if (Zchange > .05) | ||
783 | { | ||
784 | grav.Z = (float)(grav.Z * 1.25); | ||
785 | } | ||
786 | if (Zchange > .025) | ||
787 | { | ||
788 | grav.Z = (float)(grav.Z * 1.125); | ||
789 | } | ||
790 | float terraintemp = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y); | ||
791 | float postemp = (pos.Z - terraintemp); | ||
792 | if (postemp > 2.5f) | ||
793 | { | ||
794 | grav.Z = (float)(grav.Z * 1.037125); | ||
795 | } | ||
796 | //End Experimental Values | ||
797 | } | ||
798 | if ((m_flags & (VehicleFlag.NO_X)) != 0) | ||
799 | { | ||
800 | m_dir.X = 0; | ||
801 | } | ||
802 | if ((m_flags & (VehicleFlag.NO_Y)) != 0) | ||
803 | { | ||
804 | m_dir.Y = 0; | ||
805 | } | ||
806 | if ((m_flags & (VehicleFlag.NO_Z)) != 0) | ||
807 | { | ||
808 | m_dir.Z = 0; | ||
809 | } | ||
810 | |||
811 | m_lastPositionVector = d.BodyGetPosition(Body); | ||
812 | |||
813 | // Apply velocity | ||
814 | d.BodySetLinearVel(Body, m_dir.X, m_dir.Y, m_dir.Z); | ||
815 | // apply gravity force | ||
816 | d.BodyAddForce(Body, grav.X, grav.Y, grav.Z); | ||
817 | |||
818 | |||
819 | // apply friction | ||
820 | Vector3 decayamount = Vector3.One / (m_linearFrictionTimescale / pTimestep); | ||
821 | m_lastLinearVelocityVector -= m_lastLinearVelocityVector * decayamount; | ||
822 | } // end MoveLinear() | ||
823 | |||
824 | private void MoveAngular(float pTimestep) | ||
825 | { | ||
826 | /* | ||
827 | private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor | ||
828 | private int m_angularMotorApply = 0; // application frame counter | ||
829 | private float m_angularMotorVelocity = 0; // current angular motor velocity (ramps up and down) | ||
830 | private float m_angularMotorTimescale = 0; // motor angular velocity ramp up rate | ||
831 | private float m_angularMotorDecayTimescale = 0; // motor angular velocity decay rate | ||
832 | private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate | ||
833 | private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body | ||
834 | */ | ||
835 | |||
836 | // Get what the body is doing, this includes 'external' influences | ||
837 | d.Vector3 angularVelocity = d.BodyGetAngularVel(Body); | ||
838 | // Vector3 angularVelocity = Vector3.Zero; | ||
839 | |||
840 | if (m_angularMotorApply > 0) | ||
841 | { | ||
842 | // ramp up to new value | ||
843 | // current velocity += error / (time to get there / step interval) | ||
844 | // requested speed - last motor speed | ||
845 | m_angularMotorVelocity.X += (m_angularMotorDirection.X - m_angularMotorVelocity.X) / (m_angularMotorTimescale / pTimestep); | ||
846 | m_angularMotorVelocity.Y += (m_angularMotorDirection.Y - m_angularMotorVelocity.Y) / (m_angularMotorTimescale / pTimestep); | ||
847 | m_angularMotorVelocity.Z += (m_angularMotorDirection.Z - m_angularMotorVelocity.Z) / (m_angularMotorTimescale / pTimestep); | ||
848 | |||
849 | m_angularMotorApply--; // This is done so that if script request rate is less than phys frame rate the expected | ||
850 | // velocity may still be acheived. | ||
851 | } | ||
852 | else | ||
853 | { | ||
854 | // no motor recently applied, keep the body velocity | ||
855 | /* m_angularMotorVelocity.X = angularVelocity.X; | ||
856 | m_angularMotorVelocity.Y = angularVelocity.Y; | ||
857 | m_angularMotorVelocity.Z = angularVelocity.Z; */ | ||
858 | |||
859 | // and decay the velocity | ||
860 | m_angularMotorVelocity -= m_angularMotorVelocity / (m_angularMotorDecayTimescale / pTimestep); | ||
861 | } // end motor section | ||
862 | |||
863 | // Vertical attractor section | ||
864 | Vector3 vertattr = Vector3.Zero; | ||
865 | |||
866 | if (m_verticalAttractionTimescale < 300) | ||
867 | { | ||
868 | float VAservo = 0.2f / (m_verticalAttractionTimescale * pTimestep); | ||
869 | // get present body rotation | ||
870 | d.Quaternion rot = d.BodyGetQuaternion(Body); | ||
871 | Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); | ||
872 | // make a vector pointing up | ||
873 | Vector3 verterr = Vector3.Zero; | ||
874 | verterr.Z = 1.0f; | ||
875 | // rotate it to Body Angle | ||
876 | verterr = verterr * rotq; | ||
877 | // verterr.X and .Y are the World error ammounts. They are 0 when there is no error (Vehicle Body is 'vertical'), and .Z will be 1. | ||
878 | // As the body leans to its side |.X| will increase to 1 and .Z fall to 0. As body inverts |.X| will fall and .Z will go | ||
879 | // negative. Similar for tilt and |.Y|. .X and .Y must be modulated to prevent a stable inverted body. | ||
880 | if (verterr.Z < 0.0f) | ||
881 | { | ||
882 | verterr.X = 2.0f - verterr.X; | ||
883 | verterr.Y = 2.0f - verterr.Y; | ||
884 | } | ||
885 | // Error is 0 (no error) to +/- 2 (max error) | ||
886 | // scale it by VAservo | ||
887 | verterr = verterr * VAservo; | ||
888 | //if (frcount == 0) Console.WriteLine("VAerr=" + verterr); | ||
889 | |||
890 | // As the body rotates around the X axis, then verterr.Y increases; Rotated around Y then .X increases, so | ||
891 | // Change Body angular velocity X based on Y, and Y based on X. Z is not changed. | ||
892 | vertattr.X = verterr.Y; | ||
893 | vertattr.Y = - verterr.X; | ||
894 | vertattr.Z = 0f; | ||
895 | |||
896 | // scaling appears better usingsquare-law | ||
897 | float bounce = 1.0f - (m_verticalAttractionEfficiency * m_verticalAttractionEfficiency); | ||
898 | vertattr.X += bounce * angularVelocity.X; | ||
899 | vertattr.Y += bounce * angularVelocity.Y; | ||
900 | |||
901 | } // else vertical attractor is off | ||
902 | |||
903 | // m_lastVertAttractor = vertattr; | ||
904 | |||
905 | // Bank section tba | ||
906 | // Deflection section tba | ||
907 | |||
908 | // Sum velocities | ||
909 | m_lastAngularVelocity = m_angularMotorVelocity + vertattr; // + bank + deflection | ||
910 | |||
911 | if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0) | ||
912 | { | ||
913 | m_lastAngularVelocity.X = 0; | ||
914 | m_lastAngularVelocity.Y = 0; | ||
915 | } | ||
916 | |||
917 | if (!m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f)) | ||
918 | { | ||
919 | if (!d.BodyIsEnabled (Body)) d.BodyEnable (Body); | ||
920 | } | ||
921 | else | ||
922 | { | ||
923 | m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero. | ||
924 | } | ||
925 | |||
926 | // apply friction | ||
927 | Vector3 decayamount = Vector3.One / (m_angularFrictionTimescale / pTimestep); | ||
928 | m_lastAngularVelocity -= m_lastAngularVelocity * decayamount; | ||
929 | |||
930 | // Apply to the body | ||
931 | d.BodySetAngularVel (Body, m_lastAngularVelocity.X, m_lastAngularVelocity.Y, m_lastAngularVelocity.Z); | ||
932 | |||
933 | } //end MoveAngular | ||
934 | internal void LimitRotation(float timestep) | ||
935 | { | ||
936 | d.Quaternion rot = d.BodyGetQuaternion(Body); | ||
937 | Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); // rotq = rotation of object | ||
938 | d.Quaternion m_rot = new d.Quaternion(); | ||
939 | bool changed = false; | ||
940 | m_rot.X = rotq.X; | ||
941 | m_rot.Y = rotq.Y; | ||
942 | m_rot.Z = rotq.Z; | ||
943 | m_rot.W = rotq.W; | ||
944 | if (m_RollreferenceFrame != Quaternion.Identity) | ||
945 | { | ||
946 | if (rotq.X >= m_RollreferenceFrame.X) | ||
947 | { | ||
948 | m_rot.X = rotq.X - (m_RollreferenceFrame.X / 2); | ||
949 | } | ||
950 | if (rotq.Y >= m_RollreferenceFrame.Y) | ||
951 | { | ||
952 | m_rot.Y = rotq.Y - (m_RollreferenceFrame.Y / 2); | ||
953 | } | ||
954 | if (rotq.X <= -m_RollreferenceFrame.X) | ||
955 | { | ||
956 | m_rot.X = rotq.X + (m_RollreferenceFrame.X / 2); | ||
957 | } | ||
958 | if (rotq.Y <= -m_RollreferenceFrame.Y) | ||
959 | { | ||
960 | m_rot.Y = rotq.Y + (m_RollreferenceFrame.Y / 2); | ||
961 | } | ||
962 | changed = true; | ||
963 | } | ||
964 | if ((m_flags & VehicleFlag.LOCK_ROTATION) != 0) | ||
965 | { | ||
966 | m_rot.X = 0; | ||
967 | m_rot.Y = 0; | ||
968 | changed = true; | ||
969 | } | ||
970 | if (changed) | ||
971 | d.BodySetQuaternion(Body, ref m_rot); | ||
972 | } | ||
973 | } | ||
974 | } | ||