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