diff options
9 files changed, 541 insertions, 351 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index ced3fb5..6f3a084 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | |||
@@ -3955,7 +3955,35 @@ namespace OpenSim.Region.Framework.Scenes | |||
3955 | } | 3955 | } |
3956 | } | 3956 | } |
3957 | } | 3957 | } |
3958 | 3958 | ||
3959 | public Vector3 GetGeometricCenter() | ||
3960 | { | ||
3961 | // this is not real geometric center but a average of positions relative to root prim acording to | ||
3962 | // http://wiki.secondlife.com/wiki/llGetGeometricCenter | ||
3963 | // ignoring tortured prims details since sl also seems to ignore | ||
3964 | // so no real use in doing it on physics | ||
3965 | |||
3966 | Vector3 gc = Vector3.Zero; | ||
3967 | |||
3968 | int nparts = m_parts.Count; | ||
3969 | if (nparts <= 1) | ||
3970 | return gc; | ||
3971 | |||
3972 | SceneObjectPart[] parts = m_parts.GetArray(); | ||
3973 | nparts = parts.Length; // just in case it changed | ||
3974 | if (nparts <= 1) | ||
3975 | return gc; | ||
3976 | |||
3977 | // average all parts positions | ||
3978 | for (int i = 0; i < nparts; i++) | ||
3979 | gc += parts[i].GetWorldPosition(); | ||
3980 | gc /= nparts; | ||
3981 | |||
3982 | // relative to root: | ||
3983 | gc -= AbsolutePosition; | ||
3984 | return gc; | ||
3985 | } | ||
3986 | |||
3959 | public float GetMass() | 3987 | public float GetMass() |
3960 | { | 3988 | { |
3961 | float retmass = 0f; | 3989 | float retmass = 0f; |
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 969ddaf..511ab19 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | |||
@@ -122,6 +122,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
122 | /// Denote all sides of the prim | 122 | /// Denote all sides of the prim |
123 | /// </value> | 123 | /// </value> |
124 | public const int ALL_SIDES = -1; | 124 | public const int ALL_SIDES = -1; |
125 | |||
126 | private const scriptEvents PhyscicsNeededSubsEvents = ( | ||
127 | scriptEvents.collision | scriptEvents.collision_start | scriptEvents.collision_end | | ||
128 | scriptEvents.land_collision | scriptEvents.land_collision_start | scriptEvents.land_collision_end | ||
129 | ); | ||
125 | 130 | ||
126 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 131 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
127 | 132 | ||
@@ -1821,18 +1826,20 @@ namespace OpenSim.Region.Framework.Scenes | |||
1821 | /// </summary> | 1826 | /// </summary> |
1822 | /// <param name="rootObjectFlags"></param> | 1827 | /// <param name="rootObjectFlags"></param> |
1823 | /// <param name="VolumeDetectActive"></param> | 1828 | /// <param name="VolumeDetectActive"></param> |
1829 | /// <param name="building"></param> | ||
1824 | 1830 | ||
1825 | public void ApplyPhysics(uint rootObjectFlags, bool VolumeDetectActive, bool building) | 1831 | public void ApplyPhysics(uint _ObjectFlags, bool _VolumeDetectActive, bool building) |
1826 | { | 1832 | { |
1833 | VolumeDetectActive = _VolumeDetectActive; //?? as is used this is redundante | ||
1834 | |||
1827 | if (!ParentGroup.Scene.CollidablePrims) | 1835 | if (!ParentGroup.Scene.CollidablePrims) |
1828 | return; | 1836 | return; |
1829 | 1837 | ||
1830 | if (PhysicsShapeType == (byte)PhysShapeType.none) | 1838 | if (PhysicsShapeType == (byte)PhysShapeType.none) |
1831 | return; | 1839 | return; |
1832 | 1840 | ||
1833 | bool isPhysical = (rootObjectFlags & (uint) PrimFlags.Physics) != 0; | 1841 | bool isPhysical = (_ObjectFlags & (uint) PrimFlags.Physics) != 0; |
1834 | bool isPhantom = (rootObjectFlags & (uint) PrimFlags.Phantom) != 0; | 1842 | bool isPhantom = (_ObjectFlags & (uint) PrimFlags.Phantom) != 0; |
1835 | |||
1836 | 1843 | ||
1837 | if (IsJoint()) | 1844 | if (IsJoint()) |
1838 | { | 1845 | { |
@@ -1840,68 +1847,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
1840 | } | 1847 | } |
1841 | else | 1848 | else |
1842 | { | 1849 | { |
1843 | // Special case for VolumeDetection: If VolumeDetection is set, the phantom flag is locally ignored | 1850 | if ((!isPhantom || isPhysical || _VolumeDetectActive) && !ParentGroup.IsAttachment |
1844 | // if (VolumeDetectActive) | 1851 | && !(Shape.PathCurve == (byte)Extrusion.Flexible)) |
1845 | // isPhantom = false; | 1852 | AddToPhysics(isPhysical, isPhantom, building, true); |
1846 | 1853 | else | |
1847 | // The only time the physics scene shouldn't know about the prim is if it's phantom or an attachment, which is phantom by definition | 1854 | PhysActor = null; // just to be sure |
1848 | // or flexible | ||
1849 | // if (!isPhantom && !ParentGroup.IsAttachment && !(Shape.PathCurve == (byte)Extrusion.Flexible)) | ||
1850 | if ((!isPhantom || isPhysical || VolumeDetectActive) && !ParentGroup.IsAttachment && !(Shape.PathCurve == (byte)Extrusion.Flexible)) | ||
1851 | { | ||
1852 | Vector3 velocity = Velocity; | ||
1853 | Vector3 rotationalVelocity = AngularVelocity; | ||
1854 | try | ||
1855 | { | ||
1856 | PhysActor = ParentGroup.Scene.PhysicsScene.AddPrimShape( | ||
1857 | string.Format("{0}/{1}", Name, UUID), | ||
1858 | Shape, | ||
1859 | AbsolutePosition, | ||
1860 | Scale, | ||
1861 | GetWorldRotation(), | ||
1862 | isPhysical, | ||
1863 | isPhantom, | ||
1864 | PhysicsShapeType, | ||
1865 | m_localId); | ||
1866 | } | ||
1867 | catch | ||
1868 | { | ||
1869 | m_log.ErrorFormat("[SCENE]: caught exception meshing object {0}. Object set to phantom.", m_uuid); | ||
1870 | PhysActor = null; | ||
1871 | } | ||
1872 | |||
1873 | PhysicsActor pa = PhysActor; | ||
1874 | |||
1875 | if (pa != null) | ||
1876 | { | ||
1877 | pa.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info | ||
1878 | pa.SetMaterial(Material); | ||
1879 | |||
1880 | // if root part apply vehicle | ||
1881 | if (m_vehicle != null && LocalId == ParentGroup.RootPart.LocalId) | ||
1882 | m_vehicle.SetVehicle(pa); | ||
1883 | |||
1884 | DoPhysicsPropertyUpdate(isPhysical, true); | ||
1885 | if(VolumeDetectActive) // change if not the default only | ||
1886 | pa.SetVolumeDetect(1); | ||
1887 | |||
1888 | if (!building) | ||
1889 | pa.Building = false; | ||
1890 | |||
1891 | Velocity = velocity; | ||
1892 | AngularVelocity = rotationalVelocity; | ||
1893 | pa.Velocity = velocity; | ||
1894 | pa.RotationalVelocity = rotationalVelocity; | ||
1895 | |||
1896 | // if not vehicle and root part apply force and torque | ||
1897 | if ((m_vehicle == null || m_vehicle.Type == Vehicle.TYPE_NONE) | ||
1898 | && LocalId == ParentGroup.RootPart.LocalId) | ||
1899 | { | ||
1900 | pa.Force = Force; | ||
1901 | pa.Torque = Torque; | ||
1902 | } | ||
1903 | } | ||
1904 | } | ||
1905 | } | 1855 | } |
1906 | } | 1856 | } |
1907 | 1857 | ||
@@ -2310,18 +2260,29 @@ namespace OpenSim.Region.Framework.Scenes | |||
2310 | 2260 | ||
2311 | public Vector3 GetGeometricCenter() | 2261 | public Vector3 GetGeometricCenter() |
2312 | { | 2262 | { |
2313 | PhysicsActor pa = PhysActor; | 2263 | // this is not real geometric center but a average of positions relative to root prim acording to |
2314 | 2264 | // http://wiki.secondlife.com/wiki/llGetGeometricCenter | |
2315 | if (pa != null) | 2265 | // ignoring tortured prims details since sl also seems to ignore |
2316 | { | 2266 | // so no real use in doing it on physics |
2317 | Vector3 vtmp = pa.CenterOfMass; | 2267 | if (ParentGroup.IsDeleted) |
2318 | return vtmp; | ||
2319 | } | ||
2320 | else | ||
2321 | return new Vector3(0, 0, 0); | 2268 | return new Vector3(0, 0, 0); |
2269 | |||
2270 | return ParentGroup.GetGeometricCenter(); | ||
2271 | |||
2272 | /* | ||
2273 | PhysicsActor pa = PhysActor; | ||
2274 | |||
2275 | if (pa != null) | ||
2276 | { | ||
2277 | Vector3 vtmp = pa.CenterOfMass; | ||
2278 | return vtmp; | ||
2279 | } | ||
2280 | else | ||
2281 | return new Vector3(0, 0, 0); | ||
2282 | */ | ||
2322 | } | 2283 | } |
2323 | 2284 | ||
2324 | public float GetMass() | 2285 | public float GetMass() |
2325 | { | 2286 | { |
2326 | PhysicsActor pa = PhysActor; | 2287 | PhysicsActor pa = PhysActor; |
2327 | 2288 | ||
@@ -4628,7 +4589,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
4628 | /// <param name="SetTemporary"></param> | 4589 | /// <param name="SetTemporary"></param> |
4629 | /// <param name="SetPhantom"></param> | 4590 | /// <param name="SetPhantom"></param> |
4630 | /// <param name="SetVD"></param> | 4591 | /// <param name="SetVD"></param> |
4631 | // public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD) | ||
4632 | public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD, bool building) | 4592 | public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD, bool building) |
4633 | { | 4593 | { |
4634 | bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0); | 4594 | bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0); |
@@ -4639,209 +4599,92 @@ namespace OpenSim.Region.Framework.Scenes | |||
4639 | if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD)) | 4599 | if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD)) |
4640 | return; | 4600 | return; |
4641 | 4601 | ||
4642 | // do this first | ||
4643 | if (building && PhysActor != null && PhysActor.Building != building) | ||
4644 | PhysActor.Building = building; | ||
4645 | |||
4646 | // Special cases for VD. VD can only be called from a script | ||
4647 | // and can't be combined with changes to other states. So we can rely | ||
4648 | // that... | ||
4649 | // ... if VD is changed, all others are not. | ||
4650 | // ... if one of the others is changed, VD is not. | ||
4651 | |||
4652 | /* | ||
4653 | if (SetVD) // VD is active, special logic applies | ||
4654 | |||
4655 | volume detection is now independent of phantom in sl | ||
4656 | |||
4657 | { | ||
4658 | // State machine logic for VolumeDetect | ||
4659 | // More logic below | ||
4660 | |||
4661 | |||
4662 | bool phanReset = (SetPhantom != wasPhantom) && !SetPhantom; | ||
4663 | |||
4664 | if (phanReset) // Phantom changes from on to off switch VD off too | ||
4665 | { | ||
4666 | SetVD = false; // Switch it of for the course of this routine | ||
4667 | VolumeDetectActive = false; // and also permanently | ||
4668 | if (PhysActor != null) | ||
4669 | PhysActor.SetVolumeDetect(0); // Let physics know about it too | ||
4670 | } | ||
4671 | else | ||
4672 | { | ||
4673 | // If volumedetect is active we don't want phantom to be applied. | ||
4674 | // If this is a new call to VD out of the state "phantom" | ||
4675 | // this will also cause the prim to be visible to physics | ||
4676 | SetPhantom = false; | ||
4677 | } | ||
4678 | } | ||
4679 | else if (wasVD) | ||
4680 | { | ||
4681 | // Correspondingly, if VD is turned off, also turn off phantom | ||
4682 | SetPhantom = false; | ||
4683 | } | ||
4684 | |||
4685 | if (UsePhysics && IsJoint()) | ||
4686 | { | ||
4687 | SetPhantom = true; | ||
4688 | } | ||
4689 | */ | ||
4690 | if (UsePhysics) | 4602 | if (UsePhysics) |
4691 | { | ||
4692 | AddFlag(PrimFlags.Physics); | 4603 | AddFlag(PrimFlags.Physics); |
4693 | /* | ||
4694 | if (!wasUsingPhysics) | ||
4695 | { | ||
4696 | DoPhysicsPropertyUpdate(UsePhysics, false); | ||
4697 | |||
4698 | if (!ParentGroup.IsDeleted) | ||
4699 | { | ||
4700 | if (LocalId == ParentGroup.RootPart.LocalId) | ||
4701 | { | ||
4702 | ParentGroup.CheckSculptAndLoad(); | ||
4703 | } | ||
4704 | } | ||
4705 | } | ||
4706 | */ | ||
4707 | } | ||
4708 | else | 4604 | else |
4709 | { | ||
4710 | RemFlag(PrimFlags.Physics); | 4605 | RemFlag(PrimFlags.Physics); |
4711 | /* | ||
4712 | if (wasUsingPhysics) | ||
4713 | { | ||
4714 | DoPhysicsPropertyUpdate(UsePhysics, false); | ||
4715 | } | ||
4716 | */ | ||
4717 | } | ||
4718 | 4606 | ||
4719 | if (SetPhantom) | 4607 | if (SetPhantom) |
4720 | AddFlag(PrimFlags.Phantom); | 4608 | AddFlag(PrimFlags.Phantom); |
4721 | else | 4609 | else |
4722 | RemFlag(PrimFlags.Phantom); | 4610 | RemFlag(PrimFlags.Phantom); |
4723 | 4611 | ||
4612 | if (SetTemporary) | ||
4613 | AddFlag(PrimFlags.TemporaryOnRez); | ||
4614 | else | ||
4615 | RemFlag(PrimFlags.TemporaryOnRez); | ||
4616 | |||
4617 | VolumeDetectActive = SetVD; | ||
4618 | |||
4619 | if (ParentGroup.Scene == null) | ||
4620 | return; | ||
4621 | |||
4622 | PhysicsActor pa = PhysActor; | ||
4623 | |||
4624 | if (pa != null && building && pa.Building != building) | ||
4625 | pa.Building = building; | ||
4626 | |||
4724 | if ((SetPhantom && !UsePhysics) || ParentGroup.IsAttachment || PhysicsShapeType == (byte)PhysShapeType.none | 4627 | if ((SetPhantom && !UsePhysics) || ParentGroup.IsAttachment || PhysicsShapeType == (byte)PhysShapeType.none |
4725 | || (Shape.PathCurve == (byte)Extrusion.Flexible)) // note: this may have been changed above in the case of joints | 4628 | || (Shape.PathCurve == (byte)Extrusion.Flexible)) |
4726 | { | 4629 | { |
4727 | // AddFlag(PrimFlags.Phantom); | 4630 | if (pa != null) |
4631 | { | ||
4632 | ParentGroup.Scene.RemovePhysicalPrim(1); | ||
4633 | RemoveFromPhysics(); | ||
4634 | } | ||
4728 | 4635 | ||
4729 | Velocity = new Vector3(0, 0, 0); | 4636 | Velocity = new Vector3(0, 0, 0); |
4730 | Acceleration = new Vector3(0, 0, 0); | 4637 | Acceleration = new Vector3(0, 0, 0); |
4731 | if (ParentGroup.RootPart == this) | 4638 | if (ParentGroup.RootPart == this) |
4732 | AngularVelocity = new Vector3(0, 0, 0); | 4639 | AngularVelocity = new Vector3(0, 0, 0); |
4733 | |||
4734 | if (PhysActor != null) | ||
4735 | { | ||
4736 | ParentGroup.Scene.RemovePhysicalPrim(1); | ||
4737 | RemoveFromPhysics(); | ||
4738 | } | ||
4739 | } | 4640 | } |
4740 | else | 4641 | else |
4741 | { | 4642 | { |
4742 | if (ParentGroup.Scene == null) | ||
4743 | return; | ||
4744 | |||
4745 | if (ParentGroup.Scene.CollidablePrims) | 4643 | if (ParentGroup.Scene.CollidablePrims) |
4746 | { | 4644 | { |
4747 | if (PhysActor == null) | 4645 | if (pa == null) |
4748 | { | 4646 | { |
4749 | PhysActor = ParentGroup.Scene.PhysicsScene.AddPrimShape( | 4647 | AddToPhysics(UsePhysics, SetPhantom, building , false); |
4750 | string.Format("{0}/{1}", Name, UUID), | 4648 | pa = PhysActor; |
4751 | Shape, | 4649 | |
4752 | AbsolutePosition, | 4650 | if (pa != null) |
4753 | Scale, | ||
4754 | GetWorldRotation(), //physics wants world rotation like all other functions send | ||
4755 | UsePhysics, | ||
4756 | SetPhantom, | ||
4757 | PhysicsShapeType, | ||
4758 | m_localId); | ||
4759 | |||
4760 | PhysActor.SetMaterial(Material); | ||
4761 | |||
4762 | // if root part apply vehicle | ||
4763 | if (m_vehicle != null && LocalId == ParentGroup.RootPart.LocalId) | ||
4764 | m_vehicle.SetVehicle(PhysActor); | ||
4765 | |||
4766 | DoPhysicsPropertyUpdate(UsePhysics, true); | ||
4767 | |||
4768 | if (!ParentGroup.IsDeleted) | ||
4769 | { | 4651 | { |
4770 | if (LocalId == ParentGroup.RootPart.LocalId) | 4652 | if ( |
4653 | // ((AggregateScriptEvents & scriptEvents.collision) != 0) || | ||
4654 | // ((AggregateScriptEvents & scriptEvents.collision_end) != 0) || | ||
4655 | // ((AggregateScriptEvents & scriptEvents.collision_start) != 0) || | ||
4656 | // ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) || | ||
4657 | // ((AggregateScriptEvents & scriptEvents.land_collision) != 0) || | ||
4658 | // ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) || | ||
4659 | ((AggregateScriptEvents & PhyscicsNeededSubsEvents) != 0) || (CollisionSound != UUID.Zero) | ||
4660 | // (CollisionSound != UUID.Zero) | ||
4661 | ) | ||
4771 | { | 4662 | { |
4772 | ParentGroup.CheckSculptAndLoad(); | 4663 | pa.OnCollisionUpdate += PhysicsCollision; |
4664 | pa.SubscribeEvents(1000); | ||
4773 | } | 4665 | } |
4774 | } | 4666 | } |
4775 | |||
4776 | if ( | ||
4777 | ((AggregateScriptEvents & scriptEvents.collision) != 0) || | ||
4778 | ((AggregateScriptEvents & scriptEvents.collision_end) != 0) || | ||
4779 | ((AggregateScriptEvents & scriptEvents.collision_start) != 0) || | ||
4780 | ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) || | ||
4781 | ((AggregateScriptEvents & scriptEvents.land_collision) != 0) || | ||
4782 | ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) || | ||
4783 | (CollisionSound != UUID.Zero) | ||
4784 | ) | ||
4785 | { | ||
4786 | PhysActor.OnCollisionUpdate += PhysicsCollision; | ||
4787 | PhysActor.SubscribeEvents(1000); | ||
4788 | } | ||
4789 | } | 4667 | } |
4668 | |||
4790 | else // it already has a physical representation | 4669 | else // it already has a physical representation |
4791 | { | 4670 | { |
4792 | DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status. | 4671 | DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status. |
4793 | 4672 | ||
4794 | if (!ParentGroup.IsDeleted) | 4673 | if(VolumeDetectActive) |
4795 | { | 4674 | pa.SetVolumeDetect(1); |
4796 | if (LocalId == ParentGroup.RootPart.LocalId) | 4675 | else |
4797 | { | 4676 | pa.SetVolumeDetect(0); |
4798 | ParentGroup.CheckSculptAndLoad(); | ||
4799 | } | ||
4800 | } | ||
4801 | } | ||
4802 | } | ||
4803 | } | ||
4804 | 4677 | ||
4805 | PhysicsActor pa = PhysActor; | 4678 | if (pa.Building != building) |
4806 | if (SetVD) | 4679 | pa.Building = building; |
4807 | { | 4680 | } |
4808 | // If the above logic worked (this is urgent candidate to unit tests!) | ||
4809 | // we now have a physicsactor. | ||
4810 | // Defensive programming calls for a check here. | ||
4811 | // Better would be throwing an exception that could be catched by a unit test as the internal | ||
4812 | // logic should make sure, this Physactor is always here. | ||
4813 | if (pa != null) | ||
4814 | { | ||
4815 | pa.SetVolumeDetect(1); | ||
4816 | // AddFlag(PrimFlags.Phantom); // We set this flag also if VD is active | ||
4817 | this.VolumeDetectActive = true; | ||
4818 | } | ||
4819 | } | ||
4820 | else | ||
4821 | { | ||
4822 | // Remove VolumeDetect in any case. Note, it's safe to call SetVolumeDetect as often as you like | ||
4823 | // (mumbles, well, at least if you have infinte CPU powers :-)) | ||
4824 | if (pa != null) | ||
4825 | { | ||
4826 | pa.SetVolumeDetect(0); | ||
4827 | this.VolumeDetectActive = false; | ||
4828 | } | 4681 | } |
4829 | } | 4682 | } |
4830 | |||
4831 | if (SetTemporary) | ||
4832 | { | ||
4833 | AddFlag(PrimFlags.TemporaryOnRez); | ||
4834 | } | ||
4835 | else | ||
4836 | { | ||
4837 | RemFlag(PrimFlags.TemporaryOnRez); | ||
4838 | } | ||
4839 | 4683 | ||
4840 | // m_log.Debug("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString()); | 4684 | // m_log.Debug("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString()); |
4841 | 4685 | ||
4842 | // and last in case we have a new actor and not building | 4686 | // and last in case we have a new actor and not building |
4843 | if (pa != null && pa.Building != building) | 4687 | |
4844 | pa.Building = building; | ||
4845 | if (ParentGroup != null) | 4688 | if (ParentGroup != null) |
4846 | { | 4689 | { |
4847 | ParentGroup.HasGroupChanged = true; | 4690 | ParentGroup.HasGroupChanged = true; |
@@ -4853,48 +4696,104 @@ namespace OpenSim.Region.Framework.Scenes | |||
4853 | 4696 | ||
4854 | /// <summary> | 4697 | /// <summary> |
4855 | /// Adds this part to the physics scene. | 4698 | /// Adds this part to the physics scene. |
4699 | /// and sets the PhysActor property | ||
4856 | /// </summary> | 4700 | /// </summary> |
4857 | /// <remarks>This method also sets the PhysActor property.</remarks> | 4701 | /// <param name="isPhysical">Add this prim as physical.</param> |
4858 | /// <param name="rigidBody">Add this prim with a rigid body.</param> | 4702 | /// <param name="isPhantom">Add this prim as phantom.</param> |
4859 | /// <returns> | 4703 | /// <param name="building">tells physics to delay full construction of object</param> |
4860 | /// The physics actor. null if there was a failure. | 4704 | /// <param name="applyDynamics">applies velocities, force and torque</param> |
4861 | /// </returns> | 4705 | private void AddToPhysics(bool isPhysical, bool isPhantom, bool building, bool applyDynamics) |
4862 | private PhysicsActor AddToPhysics(bool rigidBody) | 4706 | { |
4863 | { | ||
4864 | PhysicsActor pa; | 4707 | PhysicsActor pa; |
4865 | 4708 | ||
4709 | Vector3 velocity = Velocity; | ||
4710 | Vector3 rotationalVelocity = AngularVelocity;; | ||
4711 | |||
4866 | try | 4712 | try |
4867 | { | 4713 | { |
4868 | pa = ParentGroup.Scene.PhysicsScene.AddPrimShape( | 4714 | pa = ParentGroup.Scene.PhysicsScene.AddPrimShape( |
4869 | string.Format("{0}/{1}", Name, UUID), | 4715 | string.Format("{0}/{1}", Name, UUID), |
4870 | Shape, | 4716 | Shape, |
4871 | AbsolutePosition, | 4717 | AbsolutePosition, |
4872 | Scale, | 4718 | Scale, |
4873 | RotationOffset, | 4719 | GetWorldRotation(), |
4874 | rigidBody, | 4720 | isPhysical, |
4875 | m_localId); | 4721 | isPhantom, |
4722 | PhysicsShapeType, | ||
4723 | m_localId); | ||
4876 | } | 4724 | } |
4877 | catch | 4725 | catch (Exception ex) |
4878 | { | 4726 | { |
4879 | m_log.ErrorFormat("[SCENE]: caught exception meshing object {0}. Object set to phantom.", m_uuid); | 4727 | m_log.ErrorFormat("[SCENE]: AddToPhysics object {0} failed: {1}", m_uuid, ex.Message); |
4880 | pa = null; | 4728 | pa = null; |
4881 | } | 4729 | } |
4882 | 4730 | ||
4883 | // FIXME: Ideally we wouldn't set the property here to reduce situations where threads changing physical | ||
4884 | // properties can stop on each other. However, DoPhysicsPropertyUpdate() currently relies on PhysActor | ||
4885 | // being set. | ||
4886 | PhysActor = pa; | ||
4887 | |||
4888 | // Basic Physics can also return null as well as an exception catch. | ||
4889 | if (pa != null) | 4731 | if (pa != null) |
4890 | { | 4732 | { |
4891 | pa.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info | 4733 | pa.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info |
4892 | pa.SetMaterial(Material); | 4734 | pa.SetMaterial(Material); |
4893 | DoPhysicsPropertyUpdate(rigidBody, true); | 4735 | |
4736 | if (VolumeDetectActive) // change if not the default only | ||
4737 | pa.SetVolumeDetect(1); | ||
4738 | |||
4739 | if (m_vehicle != null && LocalId == ParentGroup.RootPart.LocalId) | ||
4740 | m_vehicle.SetVehicle(pa); | ||
4741 | |||
4742 | // we are going to tell rest of code about physics so better have this here | ||
4743 | PhysActor = pa; | ||
4744 | |||
4745 | // DoPhysicsPropertyUpdate(isPhysical, true); | ||
4746 | // lets expand it here just with what it really needs to do | ||
4747 | |||
4748 | if (isPhysical) | ||
4749 | { | ||
4750 | if (ParentGroup.RootPart.KeyframeMotion != null) | ||
4751 | ParentGroup.RootPart.KeyframeMotion.Stop(); | ||
4752 | ParentGroup.RootPart.KeyframeMotion = null; | ||
4753 | ParentGroup.Scene.AddPhysicalPrim(1); | ||
4754 | |||
4755 | pa.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate; | ||
4756 | pa.OnOutOfBounds += PhysicsOutOfBounds; | ||
4757 | |||
4758 | if (ParentID != 0 && ParentID != LocalId) | ||
4759 | { | ||
4760 | PhysicsActor parentPa = ParentGroup.RootPart.PhysActor; | ||
4761 | |||
4762 | if (parentPa != null) | ||
4763 | { | ||
4764 | pa.link(parentPa); | ||
4765 | } | ||
4766 | } | ||
4767 | } | ||
4768 | |||
4769 | if (applyDynamics) | ||
4770 | // do independent of isphysical so parameters get setted (at least some) | ||
4771 | { | ||
4772 | Velocity = velocity; | ||
4773 | AngularVelocity = rotationalVelocity; | ||
4774 | pa.Velocity = velocity; | ||
4775 | pa.RotationalVelocity = rotationalVelocity; | ||
4776 | |||
4777 | // if not vehicle and root part apply force and torque | ||
4778 | if ((m_vehicle == null || m_vehicle.Type == Vehicle.TYPE_NONE) | ||
4779 | && LocalId == ParentGroup.RootPart.LocalId) | ||
4780 | { | ||
4781 | pa.Force = Force; | ||
4782 | pa.Torque = Torque; | ||
4783 | } | ||
4784 | } | ||
4785 | |||
4786 | if (Shape.SculptEntry) | ||
4787 | CheckSculptAndLoad(); | ||
4788 | else | ||
4789 | ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa); | ||
4790 | |||
4791 | if (!building) | ||
4792 | pa.Building = false; | ||
4894 | } | 4793 | } |
4895 | 4794 | ||
4896 | return pa; | 4795 | PhysActor = pa; |
4897 | } | 4796 | } |
4898 | 4797 | ||
4899 | /// <summary> | 4798 | /// <summary> |
4900 | /// This removes the part from the physics scene. | 4799 | /// This removes the part from the physics scene. |
@@ -5103,10 +5002,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
5103 | PhysicsActor pa = PhysActor; | 5002 | PhysicsActor pa = PhysActor; |
5104 | if (pa != null) | 5003 | if (pa != null) |
5105 | { | 5004 | { |
5106 | const scriptEvents NeededSubsEvents = ( | ||
5107 | scriptEvents.collision | scriptEvents.collision_start| scriptEvents.collision_end | | ||
5108 | scriptEvents.land_collision | scriptEvents.land_collision_start | scriptEvents.land_collision_end | ||
5109 | ); | ||
5110 | if ( | 5005 | if ( |
5111 | // ((AggregateScriptEvents & scriptEvents.collision) != 0) || | 5006 | // ((AggregateScriptEvents & scriptEvents.collision) != 0) || |
5112 | // ((AggregateScriptEvents & scriptEvents.collision_end) != 0) || | 5007 | // ((AggregateScriptEvents & scriptEvents.collision_end) != 0) || |
@@ -5114,7 +5009,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
5114 | // ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) || | 5009 | // ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) || |
5115 | // ((AggregateScriptEvents & scriptEvents.land_collision) != 0) || | 5010 | // ((AggregateScriptEvents & scriptEvents.land_collision) != 0) || |
5116 | // ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) || | 5011 | // ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) || |
5117 | ((AggregateScriptEvents & NeededSubsEvents) != 0) || (CollisionSound != UUID.Zero) | 5012 | ((AggregateScriptEvents & PhyscicsNeededSubsEvents) != 0) || (CollisionSound != UUID.Zero) |
5118 | ) | 5013 | ) |
5119 | { | 5014 | { |
5120 | // subscribe to physics updates. | 5015 | // subscribe to physics updates. |
diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs index 3e2b71c..77ea2af 100644 --- a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs | |||
@@ -179,6 +179,8 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
179 | public bool m_outofBounds; | 179 | public bool m_outofBounds; |
180 | private float m_density = 10.000006836f; // Aluminum g/cm3; | 180 | private float m_density = 10.000006836f; // Aluminum g/cm3; |
181 | 181 | ||
182 | private float m_primMass = 10.000006836f; // Aluminum g/cm3; | ||
183 | |||
182 | private byte m_shapetype; | 184 | private byte m_shapetype; |
183 | private byte m_taintshapetype; | 185 | private byte m_taintshapetype; |
184 | 186 | ||
@@ -538,7 +540,11 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
538 | 540 | ||
539 | public override float Mass | 541 | public override float Mass |
540 | { | 542 | { |
541 | get { return CalculateMass(); } | 543 | get |
544 | { | ||
545 | CalculateMass(); | ||
546 | return m_primMass; | ||
547 | } | ||
542 | } | 548 | } |
543 | 549 | ||
544 | public override Vector3 Force | 550 | public override Vector3 Force |
@@ -1316,6 +1322,9 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1316 | 1322 | ||
1317 | 1323 | ||
1318 | 1324 | ||
1325 | m_primMass = returnMass; | ||
1326 | if (m_primMass > _parent_scene.maximumMassObject) | ||
1327 | m_primMass = _parent_scene.maximumMassObject; | ||
1319 | 1328 | ||
1320 | // Recursively calculate mass | 1329 | // Recursively calculate mass |
1321 | bool HasChildPrim = false; | 1330 | bool HasChildPrim = false; |
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs index c4dc793..f739183 100644 --- a/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs | |||
@@ -395,7 +395,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
395 | 395 | ||
396 | public override float Mass | 396 | public override float Mass |
397 | { | 397 | { |
398 | get { return _mass; } | 398 | get { return primMass; } |
399 | } | 399 | } |
400 | 400 | ||
401 | public override Vector3 Force | 401 | public override Vector3 Force |
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/OdeApi.cs b/OpenSim/Region/Physics/UbitOdePlugin/OdeApi.cs index 2b6bc59..f5129cb 100644 --- a/OpenSim/Region/Physics/UbitOdePlugin/OdeApi.cs +++ b/OpenSim/Region/Physics/UbitOdePlugin/OdeApi.cs | |||
@@ -107,16 +107,17 @@ namespace OdeAPI | |||
107 | ConvexClass, | 107 | ConvexClass, |
108 | GeomTransformClass, | 108 | GeomTransformClass, |
109 | TriMeshClass, | 109 | TriMeshClass, |
110 | HeightfieldClass, | 110 | HeightfieldClass, |
111 | FirstSpaceClass, | 111 | FirstSpaceClass, |
112 | SimpleSpaceClass = FirstSpaceClass, | 112 | SimpleSpaceClass = FirstSpaceClass, |
113 | HashSpaceClass, | 113 | HashSpaceClass, |
114 | QuadTreeSpaceClass, | 114 | QuadTreeSpaceClass, |
115 | LastSpaceClass = QuadTreeSpaceClass, | 115 | LastSpaceClass = QuadTreeSpaceClass, |
116 | UbitTerrainClass, | ||
116 | FirstUserClass, | 117 | FirstUserClass, |
117 | LastUserClass = FirstUserClass + MaxUserClasses - 1, | 118 | LastUserClass = FirstUserClass + MaxUserClasses - 1, |
118 | NumClasses, | 119 | NumClasses, |
119 | MaxUserClasses = 4 | 120 | MaxUserClasses = 5 |
120 | } | 121 | } |
121 | 122 | ||
122 | public enum JointType : int | 123 | public enum JointType : int |
@@ -201,8 +202,11 @@ namespace OdeAPI | |||
201 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] | 202 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] |
202 | public delegate void GeomDtorFn(IntPtr o); | 203 | public delegate void GeomDtorFn(IntPtr o); |
203 | 204 | ||
204 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] | 205 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] |
205 | public delegate dReal HeightfieldGetHeight(IntPtr p_user_data, int x, int z); | 206 | public delegate dReal HeightfieldGetHeight(IntPtr p_user_data, int x, int z); |
207 | |||
208 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] | ||
209 | public delegate dReal UbitTerrainGetHeight(IntPtr p_user_data, int x, int z); | ||
206 | 210 | ||
207 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] | 211 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] |
208 | public delegate void NearCallback(IntPtr data, IntPtr geom1, IntPtr geom2); | 212 | public delegate void NearCallback(IntPtr data, IntPtr geom1, IntPtr geom2); |
@@ -729,6 +733,18 @@ namespace OdeAPI | |||
729 | return CreateiHeightfield(space, data, bPlaceable); | 733 | return CreateiHeightfield(space, data, bPlaceable); |
730 | } | 734 | } |
731 | 735 | ||
736 | [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreateUbitTerrain"), SuppressUnmanagedCodeSecurity] | ||
737 | public static extern IntPtr CreateiUbitTerrain(IntPtr space, IntPtr data, int bPlaceable); | ||
738 | public static IntPtr CreateUbitTerrain(IntPtr space, IntPtr data, int bPlaceable) | ||
739 | { | ||
740 | NTotalGeoms++; | ||
741 | return CreateiUbitTerrain(space, data, bPlaceable); | ||
742 | } | ||
743 | |||
744 | |||
745 | |||
746 | |||
747 | |||
732 | [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreateGeom"), SuppressUnmanagedCodeSecurity] | 748 | [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dCreateGeom"), SuppressUnmanagedCodeSecurity] |
733 | public static extern IntPtr CreateiGeom(int classnum); | 749 | public static extern IntPtr CreateiGeom(int classnum); |
734 | public static IntPtr CreateGeom(int classnum) | 750 | public static IntPtr CreateGeom(int classnum) |
@@ -964,6 +980,8 @@ namespace OdeAPI | |||
964 | dReal width, dReal depth, int widthSamples, int depthSamples, | 980 | dReal width, dReal depth, int widthSamples, int depthSamples, |
965 | dReal scale, dReal offset, dReal thickness, int bWrap); | 981 | dReal scale, dReal offset, dReal thickness, int bWrap); |
966 | 982 | ||
983 | |||
984 | |||
967 | [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataBuildDouble"), SuppressUnmanagedCodeSecurity] | 985 | [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldDataBuildDouble"), SuppressUnmanagedCodeSecurity] |
968 | public static extern void GeomHeightfieldDataBuildDouble(IntPtr d, double[] pHeightData, int bCopyHeightData, | 986 | public static extern void GeomHeightfieldDataBuildDouble(IntPtr d, double[] pHeightData, int bCopyHeightData, |
969 | dReal width, dReal depth, int widthSamples, int depthSamples, | 987 | dReal width, dReal depth, int widthSamples, int depthSamples, |
@@ -989,6 +1007,33 @@ namespace OdeAPI | |||
989 | [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldSetHeightfieldData"), SuppressUnmanagedCodeSecurity] | 1007 | [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomHeightfieldSetHeightfieldData"), SuppressUnmanagedCodeSecurity] |
990 | public static extern void GeomHeightfieldSetHeightfieldData(IntPtr g, IntPtr d); | 1008 | public static extern void GeomHeightfieldSetHeightfieldData(IntPtr g, IntPtr d); |
991 | 1009 | ||
1010 | |||
1011 | [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomUbitTerrainDataBuild"), SuppressUnmanagedCodeSecurity] | ||
1012 | public static extern void GeomUbitTerrainDataBuild(IntPtr d, float[] pHeightData, int bCopyHeightData, | ||
1013 | dReal sampleSize, int widthSamples, int depthSamples, | ||
1014 | dReal offset, dReal thickness, int bWrap); | ||
1015 | |||
1016 | [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomUbitTerrainDataBuild"), SuppressUnmanagedCodeSecurity] | ||
1017 | public static extern void GeomUbitTerrainDataBuild(IntPtr d, IntPtr pHeightData, int bCopyHeightData, | ||
1018 | dReal sampleSize, int widthSamples, int depthSamples, | ||
1019 | dReal thickness, int bWrap); | ||
1020 | |||
1021 | [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomUbitTerrainDataCreate"), SuppressUnmanagedCodeSecurity] | ||
1022 | public static extern IntPtr GeomUbitTerrainDataCreate(); | ||
1023 | |||
1024 | [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomUbitTerrainDataDestroy"), SuppressUnmanagedCodeSecurity] | ||
1025 | public static extern void GeomUbitTerrainDataDestroy(IntPtr d); | ||
1026 | |||
1027 | [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomUbitTerrainDataSetBounds"), SuppressUnmanagedCodeSecurity] | ||
1028 | public static extern void GeomUbitTerrainDataSetBounds(IntPtr d, dReal minHeight, dReal maxHeight); | ||
1029 | |||
1030 | [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomUbitTerrainGetHeightfieldData"), SuppressUnmanagedCodeSecurity] | ||
1031 | public static extern IntPtr GeomUbitTerrainGetHeightfieldData(IntPtr g); | ||
1032 | |||
1033 | [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomUbitTerrainSetHeightfieldData"), SuppressUnmanagedCodeSecurity] | ||
1034 | public static extern void GeomUbitTerrainSetHeightfieldData(IntPtr g, IntPtr d); | ||
1035 | |||
1036 | |||
992 | [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomIsEnabled"), SuppressUnmanagedCodeSecurity] | 1037 | [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGeomIsEnabled"), SuppressUnmanagedCodeSecurity] |
993 | public static extern bool GeomIsEnabled(IntPtr geom); | 1038 | public static extern bool GeomIsEnabled(IntPtr geom); |
994 | 1039 | ||
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs b/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs index 1a6907d..3e0ccef 100644 --- a/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs +++ b/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs | |||
@@ -156,6 +156,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
156 | private readonly ILog m_log; | 156 | private readonly ILog m_log; |
157 | // private Dictionary<string, sCollisionData> m_storedCollisions = new Dictionary<string, sCollisionData>(); | 157 | // private Dictionary<string, sCollisionData> m_storedCollisions = new Dictionary<string, sCollisionData>(); |
158 | 158 | ||
159 | public bool OdeUbitLib = false; | ||
159 | // private int threadid = 0; | 160 | // private int threadid = 0; |
160 | private Random fluidRandomizer = new Random(Environment.TickCount); | 161 | private Random fluidRandomizer = new Random(Environment.TickCount); |
161 | 162 | ||
@@ -374,7 +375,14 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
374 | mesher = meshmerizer; | 375 | mesher = meshmerizer; |
375 | m_config = config; | 376 | m_config = config; |
376 | 377 | ||
377 | // m_log.WarnFormat("ODE configuration: {0}", d.GetConfiguration("ODE")); | 378 | string ode_config = d.GetConfiguration("ODE"); |
379 | m_log.WarnFormat("ODE configuration: {0}", ode_config); | ||
380 | |||
381 | if (ode_config.Contains("ODE_Ubit")) | ||
382 | { | ||
383 | OdeUbitLib = true; | ||
384 | } | ||
385 | |||
378 | /* | 386 | /* |
379 | if (region != null) | 387 | if (region != null) |
380 | { | 388 | { |
@@ -527,13 +535,24 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
527 | 535 | ||
528 | // sets a global contact for a joint for contactgeom , and base contact description) | 536 | // sets a global contact for a joint for contactgeom , and base contact description) |
529 | 537 | ||
530 | private IntPtr CreateContacJoint(ref d.ContactGeom contactGeom, float mu, float bounce,float cfm,float erp) | 538 | private IntPtr CreateContacJoint(ref d.ContactGeom contactGeom, float mu, float bounce, float cfm, float erpscale, float dscale) |
531 | { | 539 | { |
532 | if (GlobalContactsArray == IntPtr.Zero || m_global_contactcount >= maxContactsbeforedeath) | 540 | if (GlobalContactsArray == IntPtr.Zero || m_global_contactcount >= maxContactsbeforedeath) |
533 | return IntPtr.Zero; | 541 | return IntPtr.Zero; |
534 | 542 | ||
543 | float erp = contactGeom.depth; | ||
544 | erp *= erpscale; | ||
545 | if (erp < minERP) | ||
546 | erp = minERP; | ||
547 | else if (erp > MaxERP) | ||
548 | erp = MaxERP; | ||
549 | |||
550 | float depth = contactGeom.depth * dscale; | ||
551 | if (depth > 0.5f) | ||
552 | depth = 0.5f; | ||
553 | |||
535 | d.Contact newcontact = new d.Contact(); | 554 | d.Contact newcontact = new d.Contact(); |
536 | newcontact.geom.depth = contactGeom.depth; | 555 | newcontact.geom.depth = depth; |
537 | newcontact.geom.g1 = contactGeom.g1; | 556 | newcontact.geom.g1 = contactGeom.g1; |
538 | newcontact.geom.g2 = contactGeom.g2; | 557 | newcontact.geom.g2 = contactGeom.g2; |
539 | newcontact.geom.pos = contactGeom.pos; | 558 | newcontact.geom.pos = contactGeom.pos; |
@@ -692,6 +711,10 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
692 | float bounce = 0; | 711 | float bounce = 0; |
693 | float cfm = 0.0001f; | 712 | float cfm = 0.0001f; |
694 | float erp = 0.1f; | 713 | float erp = 0.1f; |
714 | float erpscale = 1.0f; | ||
715 | float dscale = 1.0f; | ||
716 | bool IgnoreNegSides = false; | ||
717 | |||
695 | 718 | ||
696 | ContactData contactdata1 = new ContactData(0, 0, false); | 719 | ContactData contactdata1 = new ContactData(0, 0, false); |
697 | ContactData contactdata2 = new ContactData(0, 0, false); | 720 | ContactData contactdata2 = new ContactData(0, 0, false); |
@@ -781,10 +804,14 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
781 | cfm = p1.Mass; | 804 | cfm = p1.Mass; |
782 | if (cfm > p2.Mass) | 805 | if (cfm > p2.Mass) |
783 | cfm = p2.Mass; | 806 | cfm = p2.Mass; |
784 | cfm = (float)Math.Sqrt(cfm); | 807 | dscale = 10 / cfm; |
785 | cfm *= 0.0001f; | 808 | dscale = (float)Math.Sqrt(dscale); |
786 | if (cfm > 0.8f) | 809 | if (dscale > 1.0f) |
787 | cfm = 0.8f; | 810 | dscale = 1.0f; |
811 | erpscale = cfm * 0.01f; | ||
812 | cfm = 0.0001f / cfm; | ||
813 | if (cfm > 0.01f) | ||
814 | cfm = 0.01f; | ||
788 | 815 | ||
789 | if ((Math.Abs(p2.Velocity.X - p1.Velocity.X) > 0.1f || Math.Abs(p2.Velocity.Y - p1.Velocity.Y) > 0.1f)) | 816 | if ((Math.Abs(p2.Velocity.X - p1.Velocity.X) > 0.1f || Math.Abs(p2.Velocity.Y - p1.Velocity.Y) > 0.1f)) |
790 | mu *= frictionMovementMult; | 817 | mu *= frictionMovementMult; |
@@ -801,11 +828,22 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
801 | if (Math.Abs(p1.Velocity.X) > 0.1f || Math.Abs(p1.Velocity.Y) > 0.1f) | 828 | if (Math.Abs(p1.Velocity.X) > 0.1f || Math.Abs(p1.Velocity.Y) > 0.1f) |
802 | mu *= frictionMovementMult; | 829 | mu *= frictionMovementMult; |
803 | p1.CollidingGround = true; | 830 | p1.CollidingGround = true; |
831 | |||
804 | cfm = p1.Mass; | 832 | cfm = p1.Mass; |
805 | cfm = (float)Math.Sqrt(cfm); | 833 | dscale = 10 / cfm; |
806 | cfm *= 0.0001f; | 834 | dscale = (float)Math.Sqrt(dscale); |
807 | if (cfm > 0.8f) | 835 | if (dscale > 1.0f) |
808 | cfm = 0.8f; | 836 | dscale = 1.0f; |
837 | erpscale = cfm * 0.01f; | ||
838 | cfm = 0.0001f / cfm; | ||
839 | if (cfm > 0.01f) | ||
840 | cfm = 0.01f; | ||
841 | |||
842 | if (d.GeomGetClass(g1) == d.GeomClassID.TriMeshClass) | ||
843 | { | ||
844 | if (curContact.side1 > 0) | ||
845 | IgnoreNegSides = true; | ||
846 | } | ||
809 | 847 | ||
810 | } | 848 | } |
811 | else if (name == "Water") | 849 | else if (name == "Water") |
@@ -830,11 +868,21 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
830 | p2.getContactData(ref contactdata2); | 868 | p2.getContactData(ref contactdata2); |
831 | bounce = contactdata2.bounce * TerrainBounce; | 869 | bounce = contactdata2.bounce * TerrainBounce; |
832 | mu = (float)Math.Sqrt(contactdata2.mu * TerrainFriction); | 870 | mu = (float)Math.Sqrt(contactdata2.mu * TerrainFriction); |
871 | |||
833 | cfm = p2.Mass; | 872 | cfm = p2.Mass; |
834 | cfm = (float)Math.Sqrt(cfm); | 873 | dscale = 10 / cfm; |
835 | cfm *= 0.0001f; | 874 | dscale = (float)Math.Sqrt(dscale); |
836 | if (cfm > 0.8f) | 875 | |
837 | cfm = 0.8f; | 876 | if (dscale > 1.0f) |
877 | dscale = 1.0f; | ||
878 | |||
879 | erpscale = cfm * 0.01f; | ||
880 | cfm = 0.0001f / cfm; | ||
881 | if (cfm > 0.01f) | ||
882 | cfm = 0.01f; | ||
883 | |||
884 | if (curContact.side1 > 0) // should be 2 ? | ||
885 | IgnoreNegSides = true; | ||
838 | 886 | ||
839 | if (Math.Abs(p2.Velocity.X) > 0.1f || Math.Abs(p2.Velocity.Y) > 0.1f) | 887 | if (Math.Abs(p2.Velocity.X) > 0.1f || Math.Abs(p2.Velocity.Y) > 0.1f) |
840 | mu *= frictionMovementMult; | 888 | mu *= frictionMovementMult; |
@@ -862,39 +910,45 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
862 | int i = 0; | 910 | int i = 0; |
863 | while(true) | 911 | while(true) |
864 | { | 912 | { |
865 | if (dop1foot && (p1.Position.Z - curContact.pos.Z) > (p1.Size.Z - avCapRadius) * 0.5f) | ||
866 | p1.IsColliding = true; | ||
867 | if (dop2foot && (p2.Position.Z - curContact.pos.Z) > (p2.Size.Z - avCapRadius) * 0.5f) | ||
868 | p2.IsColliding = true; | ||
869 | 913 | ||
914 | if (IgnoreNegSides && curContact.side1 < 0) | ||
915 | { | ||
916 | if (++i >= count) | ||
917 | break; | ||
870 | 918 | ||
871 | erp = curContact.depth; | 919 | if (!GetCurContactGeom(i, ref curContact)) |
872 | if (erp < minERP) | 920 | break; |
873 | erp = minERP; | 921 | } |
874 | else if (erp > MaxERP) | 922 | else |
875 | erp = MaxERP; | ||
876 | 923 | ||
877 | Joint = CreateContacJoint(ref curContact, mu, bounce,cfm,erp); | 924 | { |
878 | d.JointAttach(Joint, b1, b2); | 925 | if (dop1foot && (p1.Position.Z - curContact.pos.Z) > (p1.Size.Z - avCapRadius) * 0.5f) |
926 | p1.IsColliding = true; | ||
927 | if (dop2foot && (p2.Position.Z - curContact.pos.Z) > (p2.Size.Z - avCapRadius) * 0.5f) | ||
928 | p2.IsColliding = true; | ||
879 | 929 | ||
880 | if (++m_global_contactcount >= maxContactsbeforedeath) | 930 | Joint = CreateContacJoint(ref curContact, mu, bounce, cfm, erpscale, dscale); |
881 | break; | 931 | d.JointAttach(Joint, b1, b2); |
882 | 932 | ||
883 | if(++i >= count) | 933 | if (++m_global_contactcount >= maxContactsbeforedeath) |
884 | break; | 934 | break; |
885 | 935 | ||
886 | if (!GetCurContactGeom(i, ref curContact)) | 936 | if (++i >= count) |
887 | break; | 937 | break; |
888 | 938 | ||
889 | if (curContact.depth > maxDepthContact.PenetrationDepth) | 939 | if (!GetCurContactGeom(i, ref curContact)) |
890 | { | 940 | break; |
891 | maxDepthContact.Position.X = curContact.pos.X; | 941 | |
892 | maxDepthContact.Position.Y = curContact.pos.Y; | 942 | if (curContact.depth > maxDepthContact.PenetrationDepth) |
893 | maxDepthContact.Position.Z = curContact.pos.Z; | 943 | { |
894 | maxDepthContact.SurfaceNormal.X = curContact.normal.X; | 944 | maxDepthContact.Position.X = curContact.pos.X; |
895 | maxDepthContact.SurfaceNormal.Y = curContact.normal.Y; | 945 | maxDepthContact.Position.Y = curContact.pos.Y; |
896 | maxDepthContact.SurfaceNormal.Z = curContact.normal.Z; | 946 | maxDepthContact.Position.Z = curContact.pos.Z; |
897 | maxDepthContact.PenetrationDepth = curContact.depth; | 947 | maxDepthContact.SurfaceNormal.X = curContact.normal.X; |
948 | maxDepthContact.SurfaceNormal.Y = curContact.normal.Y; | ||
949 | maxDepthContact.SurfaceNormal.Z = curContact.normal.Z; | ||
950 | maxDepthContact.PenetrationDepth = curContact.depth; | ||
951 | } | ||
898 | } | 952 | } |
899 | } | 953 | } |
900 | 954 | ||
@@ -1865,13 +1919,12 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1865 | 1919 | ||
1866 | public float GetTerrainHeightAtXY(float x, float y) | 1920 | public float GetTerrainHeightAtXY(float x, float y) |
1867 | { | 1921 | { |
1868 | // assumes 1m size grid and constante size square regions | 1922 | |
1869 | // needs to know about sims around in future | ||
1870 | // region offset in mega position | ||
1871 | 1923 | ||
1872 | int offsetX = ((int)(x / (int)Constants.RegionSize)) * (int)Constants.RegionSize; | 1924 | int offsetX = ((int)(x / (int)Constants.RegionSize)) * (int)Constants.RegionSize; |
1873 | int offsetY = ((int)(y / (int)Constants.RegionSize)) * (int)Constants.RegionSize; | 1925 | int offsetY = ((int)(y / (int)Constants.RegionSize)) * (int)Constants.RegionSize; |
1874 | 1926 | ||
1927 | |||
1875 | IntPtr heightFieldGeom = IntPtr.Zero; | 1928 | IntPtr heightFieldGeom = IntPtr.Zero; |
1876 | 1929 | ||
1877 | // get region map | 1930 | // get region map |
@@ -1903,28 +1956,55 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1903 | 1956 | ||
1904 | int regsize = (int)Constants.RegionSize + 3; // map size see setterrain number of samples | 1957 | int regsize = (int)Constants.RegionSize + 3; // map size see setterrain number of samples |
1905 | 1958 | ||
1906 | // we still have square fixed size regions | 1959 | if (OdeUbitLib) |
1907 | // also flip x and y because of how map is done for ODE fliped axis | ||
1908 | // so ix,iy,dx and dy are inter exchanged | ||
1909 | if (x < regsize - 1) | ||
1910 | { | ||
1911 | iy = (int)x; | ||
1912 | dy = x - (float)iy; | ||
1913 | } | ||
1914 | else // out world use external height | ||
1915 | { | 1960 | { |
1916 | iy = regsize - 1; | 1961 | if (x < regsize - 1) |
1917 | dy = 0; | 1962 | { |
1918 | } | 1963 | ix = (int)x; |
1919 | if (y < regsize - 1) | 1964 | dx = x - (float)ix; |
1920 | { | 1965 | } |
1921 | ix = (int)y; | 1966 | else // out world use external height |
1922 | dx = y - (float)ix; | 1967 | { |
1968 | ix = regsize - 1; | ||
1969 | dx = 0; | ||
1970 | } | ||
1971 | if (y < regsize - 1) | ||
1972 | { | ||
1973 | iy = (int)y; | ||
1974 | dy = y - (float)iy; | ||
1975 | } | ||
1976 | else | ||
1977 | { | ||
1978 | iy = regsize - 1; | ||
1979 | dy = 0; | ||
1980 | } | ||
1923 | } | 1981 | } |
1982 | |||
1924 | else | 1983 | else |
1925 | { | 1984 | { |
1926 | ix = regsize - 1; | 1985 | // we still have square fixed size regions |
1927 | dx = 0; | 1986 | // also flip x and y because of how map is done for ODE fliped axis |
1987 | // so ix,iy,dx and dy are inter exchanged | ||
1988 | if (x < regsize - 1) | ||
1989 | { | ||
1990 | iy = (int)x; | ||
1991 | dy = x - (float)iy; | ||
1992 | } | ||
1993 | else // out world use external height | ||
1994 | { | ||
1995 | iy = regsize - 1; | ||
1996 | dy = 0; | ||
1997 | } | ||
1998 | if (y < regsize - 1) | ||
1999 | { | ||
2000 | ix = (int)y; | ||
2001 | dx = y - (float)ix; | ||
2002 | } | ||
2003 | else | ||
2004 | { | ||
2005 | ix = regsize - 1; | ||
2006 | dx = 0; | ||
2007 | } | ||
1928 | } | 2008 | } |
1929 | 2009 | ||
1930 | float h0; | 2010 | float h0; |
@@ -1951,6 +2031,8 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1951 | 2031 | ||
1952 | return h0 + h1 + h2; | 2032 | return h0 + h1 + h2; |
1953 | } | 2033 | } |
2034 | |||
2035 | |||
1954 | public override void SetTerrain(float[] heightMap) | 2036 | public override void SetTerrain(float[] heightMap) |
1955 | { | 2037 | { |
1956 | if (m_worldOffset != Vector3.Zero && m_parentScene != null) | 2038 | if (m_worldOffset != Vector3.Zero && m_parentScene != null) |
@@ -1972,7 +2054,15 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1972 | } | 2054 | } |
1973 | 2055 | ||
1974 | public void SetTerrain(float[] heightMap, Vector3 pOffset) | 2056 | public void SetTerrain(float[] heightMap, Vector3 pOffset) |
1975 | { | 2057 | { |
2058 | if (OdeUbitLib) | ||
2059 | UbitSetTerrain(heightMap, pOffset); | ||
2060 | else | ||
2061 | OriSetTerrain(heightMap, pOffset); | ||
2062 | } | ||
2063 | |||
2064 | public void OriSetTerrain(float[] heightMap, Vector3 pOffset) | ||
2065 | { | ||
1976 | // assumes 1m size grid and constante size square regions | 2066 | // assumes 1m size grid and constante size square regions |
1977 | // needs to know about sims around in future | 2067 | // needs to know about sims around in future |
1978 | 2068 | ||
@@ -2086,6 +2176,108 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
2086 | } | 2176 | } |
2087 | } | 2177 | } |
2088 | 2178 | ||
2179 | public void UbitSetTerrain(float[] heightMap, Vector3 pOffset) | ||
2180 | { | ||
2181 | // assumes 1m size grid and constante size square regions | ||
2182 | // needs to know about sims around in future | ||
2183 | |||
2184 | float[] _heightmap; | ||
2185 | |||
2186 | uint heightmapWidth = Constants.RegionSize + 2; | ||
2187 | uint heightmapHeight = Constants.RegionSize + 2; | ||
2188 | |||
2189 | uint heightmapWidthSamples = heightmapWidth + 1; | ||
2190 | uint heightmapHeightSamples = heightmapHeight + 1; | ||
2191 | |||
2192 | _heightmap = new float[heightmapWidthSamples * heightmapHeightSamples]; | ||
2193 | |||
2194 | |||
2195 | uint regionsize = Constants.RegionSize; | ||
2196 | |||
2197 | float hfmin = float.MaxValue; | ||
2198 | // float hfmax = float.MinValue; | ||
2199 | float val; | ||
2200 | |||
2201 | |||
2202 | uint maxXXYY = regionsize - 1; | ||
2203 | // adding one margin all around so things don't fall in edges | ||
2204 | |||
2205 | uint xx; | ||
2206 | uint yy = 0; | ||
2207 | uint yt = 0; | ||
2208 | |||
2209 | for (uint y = 0; y < heightmapHeightSamples; y++) | ||
2210 | { | ||
2211 | if (y > 1 && y < maxXXYY) | ||
2212 | yy += regionsize; | ||
2213 | xx = 0; | ||
2214 | for (uint x = 0; x < heightmapWidthSamples; x++) | ||
2215 | { | ||
2216 | if (x > 1 && x < maxXXYY) | ||
2217 | xx++; | ||
2218 | |||
2219 | val = heightMap[yy + xx]; | ||
2220 | if (val < 0.0f) | ||
2221 | val = 0.0f; // no neg terrain as in chode | ||
2222 | _heightmap[yt + x] = val; | ||
2223 | |||
2224 | if (hfmin > val) | ||
2225 | hfmin = val; | ||
2226 | // if (hfmax < val) | ||
2227 | // hfmax = val; | ||
2228 | } | ||
2229 | yt += heightmapWidthSamples; | ||
2230 | } | ||
2231 | lock (OdeLock) | ||
2232 | { | ||
2233 | IntPtr GroundGeom = IntPtr.Zero; | ||
2234 | if (RegionTerrain.TryGetValue(pOffset, out GroundGeom)) | ||
2235 | { | ||
2236 | RegionTerrain.Remove(pOffset); | ||
2237 | if (GroundGeom != IntPtr.Zero) | ||
2238 | { | ||
2239 | if (TerrainHeightFieldHeights.ContainsKey(GroundGeom)) | ||
2240 | { | ||
2241 | TerrainHeightFieldHeightsHandlers[GroundGeom].Free(); | ||
2242 | TerrainHeightFieldHeightsHandlers.Remove(GroundGeom); | ||
2243 | TerrainHeightFieldHeights.Remove(GroundGeom); | ||
2244 | } | ||
2245 | d.SpaceRemove(StaticSpace, GroundGeom); | ||
2246 | d.GeomDestroy(GroundGeom); | ||
2247 | } | ||
2248 | } | ||
2249 | IntPtr HeightmapData = d.GeomHeightfieldDataCreate(); | ||
2250 | |||
2251 | const int wrap = 0; | ||
2252 | float thickness = hfmin; | ||
2253 | if (thickness < 0) | ||
2254 | thickness = 1; | ||
2255 | |||
2256 | GCHandle _heightmaphandler = GCHandle.Alloc(_heightmap, GCHandleType.Pinned); | ||
2257 | |||
2258 | d.GeomUbitTerrainDataBuild(HeightmapData, _heightmaphandler.AddrOfPinnedObject(), 0, 1.0f, | ||
2259 | (int)heightmapWidthSamples, (int)heightmapHeightSamples, | ||
2260 | thickness, wrap); | ||
2261 | |||
2262 | // d.GeomUbitTerrainDataSetBounds(HeightmapData, hfmin - 1, hfmax + 1); | ||
2263 | GroundGeom = d.CreateUbitTerrain(StaticSpace, HeightmapData, 1); | ||
2264 | if (GroundGeom != IntPtr.Zero) | ||
2265 | { | ||
2266 | d.GeomSetCategoryBits(GroundGeom, (int)(CollisionCategories.Land)); | ||
2267 | d.GeomSetCollideBits(GroundGeom, (int)(CollisionCategories.Space)); | ||
2268 | |||
2269 | } | ||
2270 | geom_name_map[GroundGeom] = "Terrain"; | ||
2271 | |||
2272 | d.GeomSetPosition(GroundGeom, pOffset.X + (float)Constants.RegionSize * 0.5f, pOffset.Y + (float)Constants.RegionSize * 0.5f, 0); | ||
2273 | RegionTerrain.Add(pOffset, GroundGeom, GroundGeom); | ||
2274 | // TerrainHeightFieldHeights.Add(GroundGeom, ODElandMap); | ||
2275 | TerrainHeightFieldHeights.Add(GroundGeom, _heightmap); | ||
2276 | TerrainHeightFieldHeightsHandlers.Add(GroundGeom, _heightmaphandler); | ||
2277 | } | ||
2278 | } | ||
2279 | |||
2280 | |||
2089 | public override void DeleteTerrain() | 2281 | public override void DeleteTerrain() |
2090 | { | 2282 | { |
2091 | } | 2283 | } |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 783650c..23158b9 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | |||
@@ -3176,17 +3176,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3176 | } | 3176 | } |
3177 | else | 3177 | else |
3178 | { | 3178 | { |
3179 | if (m_host.IsRoot) | 3179 | // new SL always returns object mass |
3180 | { | 3180 | // if (m_host.IsRoot) |
3181 | // { | ||
3181 | return m_host.ParentGroup.GetMass(); | 3182 | return m_host.ParentGroup.GetMass(); |
3182 | } | 3183 | // } |
3183 | else | 3184 | // else |
3184 | { | 3185 | // { |
3185 | return m_host.GetMass(); | 3186 | // return m_host.GetMass(); |
3186 | } | 3187 | // } |
3187 | } | 3188 | } |
3188 | } | 3189 | } |
3189 | 3190 | ||
3191 | |||
3192 | public LSL_Float llGetMassMKS() | ||
3193 | { | ||
3194 | return 100f * llGetMass(); | ||
3195 | } | ||
3196 | |||
3190 | public void llCollisionFilter(string name, string id, int accept) | 3197 | public void llCollisionFilter(string name, string id, int accept) |
3191 | { | 3198 | { |
3192 | m_host.AddScriptLPS(1); | 3199 | m_host.AddScriptLPS(1); |
@@ -4959,7 +4966,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
4959 | { | 4966 | { |
4960 | float distance = (PusheePos - m_host.AbsolutePosition).Length(); | 4967 | float distance = (PusheePos - m_host.AbsolutePosition).Length(); |
4961 | float distance_term = distance * distance * distance; // Script Energy | 4968 | float distance_term = distance * distance * distance; // Script Energy |
4962 | float pusher_mass = m_host.GetMass(); | 4969 | // use total object mass and not part |
4970 | float pusher_mass = m_host.ParentGroup.GetMass(); | ||
4963 | 4971 | ||
4964 | float PUSH_ATTENUATION_DISTANCE = 17f; | 4972 | float PUSH_ATTENUATION_DISTANCE = 17f; |
4965 | float PUSH_ATTENUATION_SCALE = 5f; | 4973 | float PUSH_ATTENUATION_SCALE = 5f; |
@@ -9964,9 +9972,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
9964 | { | 9972 | { |
9965 | try | 9973 | try |
9966 | { | 9974 | { |
9975 | /* | ||
9967 | SceneObjectPart obj = World.GetSceneObjectPart(World.Entities[key].LocalId); | 9976 | SceneObjectPart obj = World.GetSceneObjectPart(World.Entities[key].LocalId); |
9968 | if (obj != null) | 9977 | if (obj != null) |
9969 | return (double)obj.GetMass(); | 9978 | return (double)obj.GetMass(); |
9979 | */ | ||
9980 | // return total object mass | ||
9981 | SceneObjectGroup obj = World.GetGroupByPrim(World.Entities[key].LocalId); | ||
9982 | if (obj != null) | ||
9983 | return (double)obj.GetMass(); | ||
9984 | |||
9970 | // the object is null so the key is for an avatar | 9985 | // the object is null so the key is for an avatar |
9971 | ScenePresence avatar = World.GetScenePresence(key); | 9986 | ScenePresence avatar = World.GetScenePresence(key); |
9972 | if (avatar != null) | 9987 | if (avatar != null) |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs index b976dc3..5c528977 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs | |||
@@ -148,7 +148,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces | |||
148 | LSL_Vector llGetLocalPos(); | 148 | LSL_Vector llGetLocalPos(); |
149 | LSL_Rotation llGetLocalRot(); | 149 | LSL_Rotation llGetLocalRot(); |
150 | LSL_Float llGetMass(); | 150 | LSL_Float llGetMass(); |
151 | void llGetNextEmail(string address, string subject); | 151 | LSL_Float llGetMassMKS(); |
152 | void llGetNextEmail(string address, string subject); | ||
152 | LSL_String llGetNotecardLine(string name, int line); | 153 | LSL_String llGetNotecardLine(string name, int line); |
153 | LSL_Key llGetNumberOfNotecardLines(string name); | 154 | LSL_Key llGetNumberOfNotecardLines(string name); |
154 | LSL_Integer llGetNumberOfPrims(); | 155 | LSL_Integer llGetNumberOfPrims(); |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs index bf58d13..70c5fcd 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs | |||
@@ -581,6 +581,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase | |||
581 | return m_LSL_Functions.llGetMass(); | 581 | return m_LSL_Functions.llGetMass(); |
582 | } | 582 | } |
583 | 583 | ||
584 | public LSL_Float llGetMassMKS() | ||
585 | { | ||
586 | return m_LSL_Functions.llGetMassMKS(); | ||
587 | } | ||
588 | |||
584 | public void llGetNextEmail(string address, string subject) | 589 | public void llGetNextEmail(string address, string subject) |
585 | { | 590 | { |
586 | m_LSL_Functions.llGetNextEmail(address, subject); | 591 | m_LSL_Functions.llGetNextEmail(address, subject); |