diff options
Diffstat (limited to '')
-rwxr-xr-x | OpenSim/Region/PhysicsModules/BulletS/BSPrimLinkable.cs | 349 |
1 files changed, 349 insertions, 0 deletions
diff --git a/OpenSim/Region/PhysicsModules/BulletS/BSPrimLinkable.cs b/OpenSim/Region/PhysicsModules/BulletS/BSPrimLinkable.cs new file mode 100755 index 0000000..55b5da0 --- /dev/null +++ b/OpenSim/Region/PhysicsModules/BulletS/BSPrimLinkable.cs | |||
@@ -0,0 +1,349 @@ | |||
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 copyrightD | ||
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 | using System; | ||
28 | using System.Collections.Generic; | ||
29 | using System.Linq; | ||
30 | using System.Text; | ||
31 | |||
32 | using OpenSim.Framework; | ||
33 | |||
34 | using OMV = OpenMetaverse; | ||
35 | |||
36 | namespace OpenSim.Region.PhysicsModule.BulletS | ||
37 | { | ||
38 | public class BSPrimLinkable : BSPrimDisplaced | ||
39 | { | ||
40 | // The purpose of this subclass is to add linkset functionality to the prim. This overrides | ||
41 | // operations necessary for keeping the linkset created and, additionally, this | ||
42 | // calls the linkset implementation for its creation and management. | ||
43 | |||
44 | #pragma warning disable 414 | ||
45 | private static readonly string LogHeader = "[BULLETS PRIMLINKABLE]"; | ||
46 | #pragma warning restore 414 | ||
47 | |||
48 | // This adds the overrides for link() and delink() so the prim is linkable. | ||
49 | |||
50 | public BSLinkset Linkset { get; set; } | ||
51 | // The index of this child prim. | ||
52 | public int LinksetChildIndex { get; set; } | ||
53 | |||
54 | public BSLinkset.LinksetImplementation LinksetType { get; set; } | ||
55 | |||
56 | public BSPrimLinkable(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, | ||
57 | OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical) | ||
58 | : base(localID, primName, parent_scene, pos, size, rotation, pbs, pisPhysical) | ||
59 | { | ||
60 | // Default linkset implementation for this prim | ||
61 | LinksetType = (BSLinkset.LinksetImplementation)BSParam.LinksetImplementation; | ||
62 | |||
63 | Linkset = BSLinkset.Factory(PhysScene, this); | ||
64 | |||
65 | Linkset.Refresh(this); | ||
66 | } | ||
67 | |||
68 | public override void Destroy() | ||
69 | { | ||
70 | Linkset = Linkset.RemoveMeFromLinkset(this, false /* inTaintTime */); | ||
71 | base.Destroy(); | ||
72 | } | ||
73 | |||
74 | public override void link(OpenSim.Region.PhysicsModules.SharedBase.PhysicsActor obj) | ||
75 | { | ||
76 | BSPrimLinkable parent = obj as BSPrimLinkable; | ||
77 | if (parent != null) | ||
78 | { | ||
79 | BSPhysObject parentBefore = Linkset.LinksetRoot; // DEBUG | ||
80 | int childrenBefore = Linkset.NumberOfChildren; // DEBUG | ||
81 | |||
82 | Linkset = parent.Linkset.AddMeToLinkset(this); | ||
83 | |||
84 | DetailLog("{0},BSPrimLinkable.link,call,parentBefore={1}, childrenBefore=={2}, parentAfter={3}, childrenAfter={4}", | ||
85 | LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren); | ||
86 | } | ||
87 | return; | ||
88 | } | ||
89 | |||
90 | public override void delink() | ||
91 | { | ||
92 | // TODO: decide if this parent checking needs to happen at taint time | ||
93 | // Race condition here: if link() and delink() in same simulation tick, the delink will not happen | ||
94 | |||
95 | BSPhysObject parentBefore = Linkset.LinksetRoot; // DEBUG | ||
96 | int childrenBefore = Linkset.NumberOfChildren; // DEBUG | ||
97 | |||
98 | Linkset = Linkset.RemoveMeFromLinkset(this, false /* inTaintTime*/); | ||
99 | |||
100 | DetailLog("{0},BSPrimLinkable.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ", | ||
101 | LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren); | ||
102 | return; | ||
103 | } | ||
104 | |||
105 | // When simulator changes position, this might be moving a child of the linkset. | ||
106 | public override OMV.Vector3 Position | ||
107 | { | ||
108 | get { return base.Position; } | ||
109 | set | ||
110 | { | ||
111 | base.Position = value; | ||
112 | PhysScene.TaintedObject(LocalID, "BSPrimLinkable.setPosition", delegate() | ||
113 | { | ||
114 | Linkset.UpdateProperties(UpdatedProperties.Position, this); | ||
115 | }); | ||
116 | } | ||
117 | } | ||
118 | |||
119 | // When simulator changes orientation, this might be moving a child of the linkset. | ||
120 | public override OMV.Quaternion Orientation | ||
121 | { | ||
122 | get { return base.Orientation; } | ||
123 | set | ||
124 | { | ||
125 | base.Orientation = value; | ||
126 | PhysScene.TaintedObject(LocalID, "BSPrimLinkable.setOrientation", delegate() | ||
127 | { | ||
128 | Linkset.UpdateProperties(UpdatedProperties.Orientation, this); | ||
129 | }); | ||
130 | } | ||
131 | } | ||
132 | |||
133 | public override float TotalMass | ||
134 | { | ||
135 | get { return Linkset.LinksetMass; } | ||
136 | } | ||
137 | |||
138 | public override OMV.Vector3 CenterOfMass | ||
139 | { | ||
140 | get { return Linkset.CenterOfMass; } | ||
141 | } | ||
142 | |||
143 | public override OMV.Vector3 GeometricCenter | ||
144 | { | ||
145 | get { return Linkset.GeometricCenter; } | ||
146 | } | ||
147 | |||
148 | // Refresh the linkset structure and parameters when the prim's physical parameters are changed. | ||
149 | public override void UpdatePhysicalParameters() | ||
150 | { | ||
151 | base.UpdatePhysicalParameters(); | ||
152 | // Recompute any linkset parameters. | ||
153 | // When going from non-physical to physical, this re-enables the constraints that | ||
154 | // had been automatically disabled when the mass was set to zero. | ||
155 | // For compound based linksets, this enables and disables interactions of the children. | ||
156 | if (Linkset != null) // null can happen during initialization | ||
157 | Linkset.Refresh(this); | ||
158 | } | ||
159 | |||
160 | // When the prim is made dynamic or static, the linkset needs to change. | ||
161 | protected override void MakeDynamic(bool makeStatic) | ||
162 | { | ||
163 | base.MakeDynamic(makeStatic); | ||
164 | if (Linkset != null) // null can happen during initialization | ||
165 | { | ||
166 | if (makeStatic) | ||
167 | Linkset.MakeStatic(this); | ||
168 | else | ||
169 | Linkset.MakeDynamic(this); | ||
170 | } | ||
171 | } | ||
172 | |||
173 | // Body is being taken apart. Remove physical dependencies and schedule a rebuild. | ||
174 | protected override void RemoveDependencies() | ||
175 | { | ||
176 | Linkset.RemoveDependencies(this); | ||
177 | base.RemoveDependencies(); | ||
178 | } | ||
179 | |||
180 | // Called after a simulation step for the changes in physical object properties. | ||
181 | // Do any filtering/modification needed for linksets. | ||
182 | public override void UpdateProperties(EntityProperties entprop) | ||
183 | { | ||
184 | if (Linkset.IsRoot(this) || Linkset.ShouldReportPropertyUpdates(this)) | ||
185 | { | ||
186 | // Properties are only updated for the roots of a linkset. | ||
187 | // TODO: this will have to change when linksets are articulated. | ||
188 | base.UpdateProperties(entprop); | ||
189 | } | ||
190 | /* | ||
191 | else | ||
192 | { | ||
193 | // For debugging, report the movement of children | ||
194 | DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}", | ||
195 | LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, | ||
196 | entprop.Acceleration, entprop.RotationalVelocity); | ||
197 | } | ||
198 | */ | ||
199 | // The linkset might like to know about changing locations | ||
200 | Linkset.UpdateProperties(UpdatedProperties.EntPropUpdates, this); | ||
201 | } | ||
202 | |||
203 | // Called after a simulation step to post a collision with this object. | ||
204 | // This returns 'true' if the collision has been queued and the SendCollisions call must | ||
205 | // be made at the end of the simulation step. | ||
206 | public override bool Collide(uint collidingWith, BSPhysObject collidee, | ||
207 | OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) | ||
208 | { | ||
209 | bool ret = false; | ||
210 | // Ask the linkset if it wants to handle the collision | ||
211 | if (!Linkset.HandleCollide(collidingWith, collidee, contactPoint, contactNormal, pentrationDepth)) | ||
212 | { | ||
213 | // The linkset didn't handle it so pass the collision through normal processing | ||
214 | ret = base.Collide(collidingWith, collidee, contactPoint, contactNormal, pentrationDepth); | ||
215 | } | ||
216 | return ret; | ||
217 | } | ||
218 | |||
219 | // A linkset reports any collision on any part of the linkset. | ||
220 | public long SomeCollisionSimulationStep = 0; | ||
221 | public override bool HasSomeCollision | ||
222 | { | ||
223 | get | ||
224 | { | ||
225 | return (SomeCollisionSimulationStep == PhysScene.SimulationStep) || base.IsColliding; | ||
226 | } | ||
227 | set | ||
228 | { | ||
229 | if (value) | ||
230 | SomeCollisionSimulationStep = PhysScene.SimulationStep; | ||
231 | else | ||
232 | SomeCollisionSimulationStep = 0; | ||
233 | |||
234 | base.HasSomeCollision = value; | ||
235 | } | ||
236 | } | ||
237 | |||
238 | // Convert the existing linkset of this prim into a new type. | ||
239 | public bool ConvertLinkset(BSLinkset.LinksetImplementation newType) | ||
240 | { | ||
241 | bool ret = false; | ||
242 | if (LinksetType != newType) | ||
243 | { | ||
244 | DetailLog("{0},BSPrimLinkable.ConvertLinkset,oldT={1},newT={2}", LocalID, LinksetType, newType); | ||
245 | |||
246 | // Set the implementation type first so the call to BSLinkset.Factory gets the new type. | ||
247 | this.LinksetType = newType; | ||
248 | |||
249 | BSLinkset oldLinkset = this.Linkset; | ||
250 | BSLinkset newLinkset = BSLinkset.Factory(PhysScene, this); | ||
251 | |||
252 | this.Linkset = newLinkset; | ||
253 | |||
254 | // Pick up any physical dependencies this linkset might have in the physics engine. | ||
255 | oldLinkset.RemoveDependencies(this); | ||
256 | |||
257 | // Create a list of the children (mainly because can't interate through a list that's changing) | ||
258 | List<BSPrimLinkable> children = new List<BSPrimLinkable>(); | ||
259 | oldLinkset.ForEachMember((child) => | ||
260 | { | ||
261 | if (!oldLinkset.IsRoot(child)) | ||
262 | children.Add(child); | ||
263 | return false; // 'false' says to continue to next member | ||
264 | }); | ||
265 | |||
266 | // Remove the children from the old linkset and add to the new (will be a new instance from the factory) | ||
267 | foreach (BSPrimLinkable child in children) | ||
268 | { | ||
269 | oldLinkset.RemoveMeFromLinkset(child, true /*inTaintTime*/); | ||
270 | } | ||
271 | foreach (BSPrimLinkable child in children) | ||
272 | { | ||
273 | newLinkset.AddMeToLinkset(child); | ||
274 | child.Linkset = newLinkset; | ||
275 | } | ||
276 | |||
277 | // Force the shape and linkset to get reconstructed | ||
278 | newLinkset.Refresh(this); | ||
279 | this.ForceBodyShapeRebuild(true /* inTaintTime */); | ||
280 | } | ||
281 | return ret; | ||
282 | } | ||
283 | |||
284 | #region Extension | ||
285 | public override object Extension(string pFunct, params object[] pParams) | ||
286 | { | ||
287 | DetailLog("{0} BSPrimLinkable.Extension,op={1},nParam={2}", LocalID, pFunct, pParams.Length); | ||
288 | object ret = null; | ||
289 | switch (pFunct) | ||
290 | { | ||
291 | // physGetLinksetType(); | ||
292 | // pParams = [ BSPhysObject root, null ] | ||
293 | case ExtendedPhysics.PhysFunctGetLinksetType: | ||
294 | { | ||
295 | ret = (object)LinksetType; | ||
296 | DetailLog("{0},BSPrimLinkable.Extension.physGetLinksetType,type={1}", LocalID, ret); | ||
297 | break; | ||
298 | } | ||
299 | // physSetLinksetType(type); | ||
300 | // pParams = [ BSPhysObject root, null, integer type ] | ||
301 | case ExtendedPhysics.PhysFunctSetLinksetType: | ||
302 | { | ||
303 | if (pParams.Length > 2) | ||
304 | { | ||
305 | BSLinkset.LinksetImplementation linksetType = (BSLinkset.LinksetImplementation)pParams[2]; | ||
306 | if (Linkset.IsRoot(this)) | ||
307 | { | ||
308 | PhysScene.TaintedObject(LocalID, "BSPrim.PhysFunctSetLinksetType", delegate() | ||
309 | { | ||
310 | // Cause the linkset type to change | ||
311 | DetailLog("{0},BSPrimLinkable.Extension.physSetLinksetType, oldType={1},newType={2}", | ||
312 | LocalID, Linkset.LinksetImpl, linksetType); | ||
313 | ConvertLinkset(linksetType); | ||
314 | }); | ||
315 | } | ||
316 | ret = (object)(int)linksetType; | ||
317 | } | ||
318 | break; | ||
319 | } | ||
320 | // physChangeLinkType(linknum, typeCode); | ||
321 | // pParams = [ BSPhysObject root, BSPhysObject child, integer linkType ] | ||
322 | case ExtendedPhysics.PhysFunctChangeLinkType: | ||
323 | { | ||
324 | ret = Linkset.Extension(pFunct, pParams); | ||
325 | break; | ||
326 | } | ||
327 | // physGetLinkType(linknum); | ||
328 | // pParams = [ BSPhysObject root, BSPhysObject child ] | ||
329 | case ExtendedPhysics.PhysFunctGetLinkType: | ||
330 | { | ||
331 | ret = Linkset.Extension(pFunct, pParams); | ||
332 | break; | ||
333 | } | ||
334 | // physChangeLinkParams(linknum, [code, value, code, value, ...]); | ||
335 | // pParams = [ BSPhysObject root, BSPhysObject child, object[] [ string op, object opParam, string op, object opParam, ... ] ] | ||
336 | case ExtendedPhysics.PhysFunctChangeLinkParams: | ||
337 | { | ||
338 | ret = Linkset.Extension(pFunct, pParams); | ||
339 | break; | ||
340 | } | ||
341 | default: | ||
342 | ret = base.Extension(pFunct, pParams); | ||
343 | break; | ||
344 | } | ||
345 | return ret; | ||
346 | } | ||
347 | #endregion // Extension | ||
348 | } | ||
349 | } | ||