opensim – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 eva 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.Text;
30  
31 using OMV = OpenMetaverse;
32  
33 namespace OpenSim.Region.Physics.BulletSPlugin
34 {
35  
36 public abstract class BSLinkset
37 {
38 // private static string LogHeader = "[BULLETSIM LINKSET]";
39  
40 public enum LinksetImplementation
41 {
42 Constraint = 0, // linkset tied together with constraints
43 Compound = 1, // linkset tied together as a compound object
44 Manual = 2 // linkset tied together manually (code moves all the pieces)
45 }
46 // Create the correct type of linkset for this child
47 public static BSLinkset Factory(BSScene physScene, BSPrimLinkable parent)
48 {
49 BSLinkset ret = null;
50  
51 switch (parent.LinksetType)
52 {
53 case LinksetImplementation.Constraint:
54 ret = new BSLinksetConstraints(physScene, parent);
55 break;
56 case LinksetImplementation.Compound:
57 ret = new BSLinksetCompound(physScene, parent);
58 break;
59 case LinksetImplementation.Manual:
60 // ret = new BSLinksetManual(physScene, parent);
61 break;
62 default:
63 ret = new BSLinksetCompound(physScene, parent);
64 break;
65 }
66 if (ret == null)
67 {
68 physScene.Logger.ErrorFormat("[BULLETSIM LINKSET] Factory could not create linkset. Parent name={1}, ID={2}", parent.Name, parent.LocalID);
69 }
70 return ret;
71 }
72  
73 public class BSLinkInfo
74 {
75 public BSPrimLinkable member;
76 public BSLinkInfo(BSPrimLinkable pMember)
77 {
78 member = pMember;
79 }
80 public virtual void ResetLink() { }
81 public virtual void SetLinkParameters(BSConstraint constrain) { }
82 // Returns 'true' if physical property updates from the child should be reported to the simulator
83 public virtual bool ShouldUpdateChildProperties() { return false; }
84 }
85  
86 public LinksetImplementation LinksetImpl { get; protected set; }
87  
88 public BSPrimLinkable LinksetRoot { get; protected set; }
89  
90 protected BSScene m_physicsScene { get; private set; }
91  
92 static int m_nextLinksetID = 1;
93 public int LinksetID { get; private set; }
94  
95 // The children under the root in this linkset.
96 // protected HashSet<BSPrimLinkable> m_children;
97 protected Dictionary<BSPrimLinkable, BSLinkInfo> m_children;
98  
99 // We lock the diddling of linkset classes to prevent any badness.
100 // This locks the modification of the instances of this class. Changes
101 // to the physical representation is done via the tainting mechenism.
102 protected object m_linksetActivityLock = new Object();
103  
104 // We keep the prim's mass in the linkset structure since it could be dependent on other prims
105 public float LinksetMass { get; protected set; }
106  
107 public virtual bool LinksetIsColliding { get { return false; } }
108  
109 public OMV.Vector3 CenterOfMass
110 {
111 get { return ComputeLinksetCenterOfMass(); }
112 }
113  
114 public OMV.Vector3 GeometricCenter
115 {
116 get { return ComputeLinksetGeometricCenter(); }
117 }
118  
119 protected BSLinkset(BSScene scene, BSPrimLinkable parent)
120 {
121 // A simple linkset of one (no children)
122 LinksetID = m_nextLinksetID++;
123 // We create LOTS of linksets.
124 if (m_nextLinksetID <= 0)
125 m_nextLinksetID = 1;
126 m_physicsScene = scene;
127 LinksetRoot = parent;
128 m_children = new Dictionary<BSPrimLinkable, BSLinkInfo>();
129 LinksetMass = parent.RawMass;
130 Rebuilding = false;
131  
132 parent.ClearDisplacement();
133 }
134  
135 // Link to a linkset where the child knows the parent.
136 // Parent changing should not happen so do some sanity checking.
137 // We return the parent's linkset so the child can track its membership.
138 // Called at runtime.
139 public BSLinkset AddMeToLinkset(BSPrimLinkable child)
140 {
141 lock (m_linksetActivityLock)
142 {
143 // Don't add the root to its own linkset
144 if (!IsRoot(child))
145 AddChildToLinkset(child);
146 LinksetMass = ComputeLinksetMass();
147 }
148 return this;
149 }
150  
151 // Remove a child from a linkset.
152 // Returns a new linkset for the child which is a linkset of one (just the
153 // orphened child).
154 // Called at runtime.
155 public BSLinkset RemoveMeFromLinkset(BSPrimLinkable child, bool inTaintTime)
156 {
157 lock (m_linksetActivityLock)
158 {
159 if (IsRoot(child))
160 {
161 // Cannot remove the root from a linkset.
162 return this;
163 }
164 RemoveChildFromLinkset(child, inTaintTime);
165 LinksetMass = ComputeLinksetMass();
166 }
167  
168 // The child is down to a linkset of just itself
169 return BSLinkset.Factory(m_physicsScene, child);
170 }
171  
172 // Return 'true' if the passed object is the root object of this linkset
173 public bool IsRoot(BSPrimLinkable requestor)
174 {
175 return (requestor.LocalID == LinksetRoot.LocalID);
176 }
177  
178 public int NumberOfChildren { get { return m_children.Count; } }
179  
180 // Return 'true' if this linkset has any children (more than the root member)
181 public bool HasAnyChildren { get { return (m_children.Count > 0); } }
182  
183 // Return 'true' if this child is in this linkset
184 public bool HasChild(BSPrimLinkable child)
185 {
186 bool ret = false;
187 lock (m_linksetActivityLock)
188 {
189 ret = m_children.ContainsKey(child);
190 }
191 return ret;
192 }
193  
194 // Perform an action on each member of the linkset including root prim.
195 // Depends on the action on whether this should be done at taint time.
196 public delegate bool ForEachMemberAction(BSPrimLinkable obj);
197 public virtual bool ForEachMember(ForEachMemberAction action)
198 {
199 bool ret = false;
200 lock (m_linksetActivityLock)
201 {
202 action(LinksetRoot);
203 foreach (BSPrimLinkable po in m_children.Keys)
204 {
205 if (action(po))
206 break;
207 }
208 }
209 return ret;
210 }
211  
212 public bool TryGetLinkInfo(BSPrimLinkable child, out BSLinkInfo foundInfo)
213 {
214 bool ret = false;
215 BSLinkInfo found = null;
216 lock (m_linksetActivityLock)
217 {
218 ret = m_children.TryGetValue(child, out found);
219 }
220 foundInfo = found;
221 return ret;
222 }
223 // Perform an action on each member of the linkset including root prim.
224 // Depends on the action on whether this should be done at taint time.
225 public delegate bool ForEachLinkInfoAction(BSLinkInfo obj);
226 public virtual bool ForEachLinkInfo(ForEachLinkInfoAction action)
227 {
228 bool ret = false;
229 lock (m_linksetActivityLock)
230 {
231 foreach (BSLinkInfo po in m_children.Values)
232 {
233 if (action(po))
234 break;
235 }
236 }
237 return ret;
238 }
239  
240 // Check the type of the link and return 'true' if the link is flexible and the
241 // updates from the child should be sent to the simulator so things change.
242 public virtual bool ShouldReportPropertyUpdates(BSPrimLinkable child)
243 {
244 bool ret = false;
245  
246 BSLinkInfo linkInfo;
247 if (m_children.TryGetValue(child, out linkInfo))
248 {
249 ret = linkInfo.ShouldUpdateChildProperties();
250 }
251  
252 return ret;
253 }
254  
255 // Called after a simulation step to post a collision with this object.
256 // Return 'true' if linkset processed the collision. 'false' says the linkset didn't have
257 // anything to add for the collision and it should be passed through normal processing.
258 // Default processing for a linkset.
259 public virtual bool HandleCollide(uint collidingWith, BSPhysObject collidee,
260 OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth)
261 {
262 bool ret = false;
263  
264 // prims in the same linkset cannot collide with each other
265 BSPrimLinkable convCollidee = collidee as BSPrimLinkable;
266 if (convCollidee != null && (LinksetID == convCollidee.Linkset.LinksetID))
267 {
268 // By returning 'true', we tell the caller the collision has been 'handled' so it won't
269 // do anything about this collision and thus, effectivily, ignoring the collision.
270 ret = true;
271 }
272 else
273 {
274 // Not a collision between members of the linkset. Must be a real collision.
275 // So the linkset root can know if there is a collision anywhere in the linkset.
276 LinksetRoot.SomeCollisionSimulationStep = m_physicsScene.SimulationStep;
277 }
278  
279 return ret;
280 }
281  
282 // I am the root of a linkset and a new child is being added
283 // Called while LinkActivity is locked.
284 protected abstract void AddChildToLinkset(BSPrimLinkable child);
285  
286 // I am the root of a linkset and one of my children is being removed.
287 // Safe to call even if the child is not really in my linkset.
288 protected abstract void RemoveChildFromLinkset(BSPrimLinkable child, bool inTaintTime);
289  
290 // When physical properties are changed the linkset needs to recalculate
291 // its internal properties.
292 // May be called at runtime or taint-time.
293 public virtual void Refresh(BSPrimLinkable requestor)
294 {
295 LinksetMass = ComputeLinksetMass();
296 }
297  
298 // Flag denoting the linkset is in the process of being rebuilt.
299 // Used to know not the schedule a rebuild in the middle of a rebuild.
300 protected bool Rebuilding { get; set; }
301  
302 // The object is going dynamic (physical). Do any setup necessary
303 // for a dynamic linkset.
304 // Only the state of the passed object can be modified. The rest of the linkset
305 // has not yet been fully constructed.
306 // Return 'true' if any properties updated on the passed object.
307 // Called at taint-time!
308 public abstract bool MakeDynamic(BSPrimLinkable child);
309  
310 // The object is going static (non-physical). Do any setup necessary
311 // for a static linkset.
312 // Return 'true' if any properties updated on the passed object.
313 // Called at taint-time!
314 public abstract bool MakeStatic(BSPrimLinkable child);
315  
316 // Called when a parameter update comes from the physics engine for any object
317 // of the linkset is received.
318 // Passed flag is update came from physics engine (true) or the user (false).
319 // Called at taint-time!!
320 public abstract void UpdateProperties(UpdatedProperties whichUpdated, BSPrimLinkable physObject);
321  
322 // Routine used when rebuilding the body of the root of the linkset
323 // Destroy all the constraints have have been made to root.
324 // This is called when the root body is changing.
325 // Returns 'true' of something was actually removed and would need restoring
326 // Called at taint-time!!
327 public abstract bool RemoveDependencies(BSPrimLinkable child);
328  
329 // ================================================================
330 // Some physical setting happen to all members of the linkset
331 public virtual void SetPhysicalFriction(float friction)
332 {
333 ForEachMember((member) =>
334 {
335 if (member.PhysBody.HasPhysicalBody)
336 m_physicsScene.PE.SetFriction(member.PhysBody, friction);
337 return false; // 'false' says to continue looping
338 }
339 );
340 }
341 public virtual void SetPhysicalRestitution(float restitution)
342 {
343 ForEachMember((member) =>
344 {
345 if (member.PhysBody.HasPhysicalBody)
346 m_physicsScene.PE.SetRestitution(member.PhysBody, restitution);
347 return false; // 'false' says to continue looping
348 }
349 );
350 }
351 public virtual void SetPhysicalGravity(OMV.Vector3 gravity)
352 {
353 ForEachMember((member) =>
354 {
355 if (member.PhysBody.HasPhysicalBody)
356 m_physicsScene.PE.SetGravity(member.PhysBody, gravity);
357 return false; // 'false' says to continue looping
358 }
359 );
360 }
361 public virtual void ComputeAndSetLocalInertia(OMV.Vector3 inertiaFactor, float linksetMass)
362 {
363 ForEachMember((member) =>
364 {
365 if (member.PhysBody.HasPhysicalBody)
366 {
367 OMV.Vector3 inertia = m_physicsScene.PE.CalculateLocalInertia(member.PhysShape.physShapeInfo, linksetMass);
368 member.Inertia = inertia * inertiaFactor;
369 m_physicsScene.PE.SetMassProps(member.PhysBody, linksetMass, member.Inertia);
370 m_physicsScene.PE.UpdateInertiaTensor(member.PhysBody);
371 DetailLog("{0},BSLinkset.ComputeAndSetLocalInertia,m.mass={1}, inertia={2}", member.LocalID, linksetMass, member.Inertia);
372  
373 }
374 return false; // 'false' says to continue looping
375 }
376 );
377 }
378 public virtual void SetPhysicalCollisionFlags(CollisionFlags collFlags)
379 {
380 ForEachMember((member) =>
381 {
382 if (member.PhysBody.HasPhysicalBody)
383 m_physicsScene.PE.SetCollisionFlags(member.PhysBody, collFlags);
384 return false; // 'false' says to continue looping
385 }
386 );
387 }
388 public virtual void AddToPhysicalCollisionFlags(CollisionFlags collFlags)
389 {
390 ForEachMember((member) =>
391 {
392 if (member.PhysBody.HasPhysicalBody)
393 m_physicsScene.PE.AddToCollisionFlags(member.PhysBody, collFlags);
394 return false; // 'false' says to continue looping
395 }
396 );
397 }
398 public virtual void RemoveFromPhysicalCollisionFlags(CollisionFlags collFlags)
399 {
400 ForEachMember((member) =>
401 {
402 if (member.PhysBody.HasPhysicalBody)
403 m_physicsScene.PE.RemoveFromCollisionFlags(member.PhysBody, collFlags);
404 return false; // 'false' says to continue looping
405 }
406 );
407 }
408 // ================================================================
409 protected virtual float ComputeLinksetMass()
410 {
411 float mass = LinksetRoot.RawMass;
412 if (HasAnyChildren)
413 {
414 lock (m_linksetActivityLock)
415 {
416 foreach (BSPrimLinkable bp in m_children.Keys)
417 {
418 mass += bp.RawMass;
419 }
420 }
421 }
422 return mass;
423 }
424  
425 // Computes linkset's center of mass in world coordinates.
426 protected virtual OMV.Vector3 ComputeLinksetCenterOfMass()
427 {
428 OMV.Vector3 com;
429 lock (m_linksetActivityLock)
430 {
431 com = LinksetRoot.Position * LinksetRoot.RawMass;
432 float totalMass = LinksetRoot.RawMass;
433  
434 foreach (BSPrimLinkable bp in m_children.Keys)
435 {
436 com += bp.Position * bp.RawMass;
437 totalMass += bp.RawMass;
438 }
439 if (totalMass != 0f)
440 com /= totalMass;
441 }
442  
443 return com;
444 }
445  
446 protected virtual OMV.Vector3 ComputeLinksetGeometricCenter()
447 {
448 OMV.Vector3 com;
449 lock (m_linksetActivityLock)
450 {
451 com = LinksetRoot.Position;
452  
453 foreach (BSPrimLinkable bp in m_children.Keys)
454 {
455 com += bp.Position;
456 }
457 com /= (m_children.Count + 1);
458 }
459  
460 return com;
461 }
462  
463 #region Extension
464 public virtual object Extension(string pFunct, params object[] pParams)
465 {
466 return null;
467 }
468 #endregion // Extension
469  
470 // Invoke the detailed logger and output something if it's enabled.
471 protected void DetailLog(string msg, params Object[] args)
472 {
473 if (m_physicsScene.PhysicsLogging.Enabled)
474 m_physicsScene.DetailLog(msg, args);
475 }
476 }
477 }