diff options
Diffstat (limited to 'OpenSim')
-rw-r--r-- | OpenSim/Framework/ILandObject.cs | 4 | ||||
-rw-r--r-- | OpenSim/Region/CoreModules/World/Land/LandObject.cs | 147 | ||||
-rwxr-xr-x | OpenSim/Region/Framework/Scenes/Scene.cs | 64 |
3 files changed, 194 insertions, 21 deletions
diff --git a/OpenSim/Framework/ILandObject.cs b/OpenSim/Framework/ILandObject.cs index 7a50c2a..af072fe 100644 --- a/OpenSim/Framework/ILandObject.cs +++ b/OpenSim/Framework/ILandObject.cs | |||
@@ -64,6 +64,10 @@ namespace OpenSim.Framework | |||
64 | // a estimation of a parcel center. | 64 | // a estimation of a parcel center. |
65 | Vector2 CenterPoint { get; } | 65 | Vector2 CenterPoint { get; } |
66 | 66 | ||
67 | // get positions | ||
68 | Vector2? GetNearestPoint(Vector3 pos); | ||
69 | Vector2? GetNearestPointAlongDirection(Vector3 pos, Vector3 pdirection); | ||
70 | |||
67 | bool ContainsPoint(int x, int y); | 71 | bool ContainsPoint(int x, int y); |
68 | 72 | ||
69 | ILandObject Copy(); | 73 | ILandObject Copy(); |
diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs index ed509fe..378e996 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs | |||
@@ -121,6 +121,147 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
121 | } | 121 | } |
122 | } | 122 | } |
123 | 123 | ||
124 | public Vector2? GetNearestPoint(Vector3 pos) | ||
125 | { | ||
126 | Vector3 direction = new Vector3(m_centerPoint.X - pos.X, m_centerPoint.Y - pos.Y, 0f ); | ||
127 | return GetNearestPointAlongDirection(pos, direction); | ||
128 | } | ||
129 | |||
130 | public Vector2? GetNearestPointAlongDirection(Vector3 pos, Vector3 pdirection) | ||
131 | { | ||
132 | Vector2 testpos; | ||
133 | Vector2 direction; | ||
134 | |||
135 | testpos.X = pos.X / landUnit; | ||
136 | testpos.Y = pos.Y / landUnit; | ||
137 | |||
138 | if(LandBitmap[(int)testpos.X, (int)testpos.Y]) | ||
139 | return new Vector2(pos.X, pos.Y); // we are already here | ||
140 | |||
141 | direction.X = pdirection.X; | ||
142 | direction.Y = pdirection.Y; | ||
143 | |||
144 | if(direction.X == 0f && direction.Y == 0f) | ||
145 | return null; // we can't look anywhere | ||
146 | |||
147 | direction.Normalize(); | ||
148 | |||
149 | int minx = (int)(m_AABBmin.X / landUnit); | ||
150 | int maxx = (int)(m_AABBmax.X / landUnit); | ||
151 | |||
152 | // check against AABB | ||
153 | if(direction.X > 0f) | ||
154 | { | ||
155 | if(testpos.X >= maxx) | ||
156 | return null; // will never get there | ||
157 | if(testpos.X < minx) | ||
158 | testpos.X = minx; | ||
159 | } | ||
160 | else if(direction.X < 0f) | ||
161 | { | ||
162 | if(testpos.X < minx) | ||
163 | return null; // will never get there | ||
164 | if(testpos.X >= maxx) | ||
165 | testpos.X = maxx - 1; | ||
166 | } | ||
167 | else | ||
168 | { | ||
169 | if(testpos.X < minx) | ||
170 | return null; // will never get there | ||
171 | else if(testpos.X >= maxx) | ||
172 | return null; // will never get there | ||
173 | } | ||
174 | |||
175 | int miny = (int)(m_AABBmin.Y / landUnit); | ||
176 | int maxy = (int)(m_AABBmax.Y / landUnit); | ||
177 | |||
178 | if(direction.Y > 0f) | ||
179 | { | ||
180 | if(testpos.Y >= maxy) | ||
181 | return null; // will never get there | ||
182 | if(testpos.Y < miny) | ||
183 | testpos.Y = miny; | ||
184 | } | ||
185 | else if(direction.Y < 0f) | ||
186 | { | ||
187 | if(testpos.Y < miny) | ||
188 | return null; // will never get there | ||
189 | if(testpos.Y >= maxy) | ||
190 | testpos.Y = maxy - 1; | ||
191 | } | ||
192 | else | ||
193 | { | ||
194 | if(testpos.Y < miny) | ||
195 | return null; // will never get there | ||
196 | else if(testpos.Y >= maxy) | ||
197 | return null; // will never get there | ||
198 | } | ||
199 | |||
200 | while(!LandBitmap[(int)testpos.X, (int)testpos.Y]) | ||
201 | { | ||
202 | testpos += direction; | ||
203 | |||
204 | if(testpos.X < minx) | ||
205 | return null; | ||
206 | if (testpos.X >= maxx) | ||
207 | return null; | ||
208 | if(testpos.Y < miny) | ||
209 | return null; | ||
210 | if (testpos.Y >= maxy) | ||
211 | return null; | ||
212 | } | ||
213 | |||
214 | testpos *= landUnit; | ||
215 | float ftmp; | ||
216 | |||
217 | if(Math.Abs(direction.X) > Math.Abs(direction.Y)) | ||
218 | { | ||
219 | if(direction.X < 0) | ||
220 | testpos.X += landUnit - 0.5f; | ||
221 | else | ||
222 | testpos.X += 0.5f; | ||
223 | ftmp = testpos.X - pos.X; | ||
224 | ftmp /= direction.X; | ||
225 | ftmp = Math.Abs(ftmp); | ||
226 | ftmp *= direction.Y; | ||
227 | ftmp += pos.Y; | ||
228 | |||
229 | if(ftmp < testpos.Y + .5f) | ||
230 | ftmp = testpos.Y + .5f; | ||
231 | else | ||
232 | { | ||
233 | testpos.Y += landUnit - 0.5f; | ||
234 | if(ftmp > testpos.Y) | ||
235 | ftmp = testpos.Y; | ||
236 | } | ||
237 | testpos.Y = ftmp; | ||
238 | } | ||
239 | else | ||
240 | { | ||
241 | if(direction.Y < 0) | ||
242 | testpos.Y += landUnit - 0.5f; | ||
243 | else | ||
244 | testpos.Y += 0.5f; | ||
245 | ftmp = testpos.Y - pos.Y; | ||
246 | ftmp /= direction.Y; | ||
247 | ftmp = Math.Abs(ftmp); | ||
248 | ftmp *= direction.X; | ||
249 | ftmp += pos.X; | ||
250 | |||
251 | if(ftmp < testpos.X + .5f) | ||
252 | ftmp = testpos.X + .5f; | ||
253 | else | ||
254 | { | ||
255 | testpos.X += landUnit - 0.5f; | ||
256 | if(ftmp > testpos.X) | ||
257 | ftmp = testpos.X; | ||
258 | } | ||
259 | testpos.X = ftmp; | ||
260 | } | ||
261 | return testpos; | ||
262 | } | ||
263 | |||
264 | |||
124 | #region Constructors | 265 | #region Constructors |
125 | 266 | ||
126 | public LandObject(LandData landData, Scene scene) | 267 | public LandObject(LandData landData, Scene scene) |
@@ -791,7 +932,7 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
791 | { | 932 | { |
792 | for (y = 0; y < LandBitmap.GetLength(1); y++) | 933 | for (y = 0; y < LandBitmap.GetLength(1); y++) |
793 | { | 934 | { |
794 | if (LandBitmap[x, y] == true) | 935 | if (LandBitmap[x, y]) |
795 | { | 936 | { |
796 | if (min_x > x) | 937 | if (min_x > x) |
797 | min_x = x; | 938 | min_x = x; |
@@ -856,7 +997,7 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
856 | m_AABBmin.X = tx; | 997 | m_AABBmin.X = tx; |
857 | m_AABBmin.Y = ty; | 998 | m_AABBmin.Y = ty; |
858 | 999 | ||
859 | if(m_scene == null) | 1000 | if(m_scene == null || m_scene.Heightmap == null) |
860 | LandData.AABBMin = new Vector3(tx, ty, 0f); | 1001 | LandData.AABBMin = new Vector3(tx, ty, 0f); |
861 | else | 1002 | else |
862 | LandData.AABBMin = new Vector3(tx, ty, (float)m_scene.Heightmap[tx, ty]); | 1003 | LandData.AABBMin = new Vector3(tx, ty, (float)m_scene.Heightmap[tx, ty]); |
@@ -874,7 +1015,7 @@ namespace OpenSim.Region.CoreModules.World.Land | |||
874 | m_AABBmax.X = tx; | 1015 | m_AABBmax.X = tx; |
875 | m_AABBmax.Y = ty; | 1016 | m_AABBmax.Y = ty; |
876 | 1017 | ||
877 | if(m_scene == null) | 1018 | if(m_scene == null || m_scene.Heightmap == null) |
878 | LandData.AABBMax = new Vector3(tx, ty, 0f); | 1019 | LandData.AABBMax = new Vector3(tx, ty, 0f); |
879 | else | 1020 | else |
880 | LandData.AABBMax = new Vector3(tx, ty, (float)m_scene.Heightmap[tx - 1, ty - 1]); | 1021 | LandData.AABBMax = new Vector3(tx, ty, (float)m_scene.Heightmap[tx - 1, ty - 1]); |
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 60079e2..9ae0c10 100755 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs | |||
@@ -5783,27 +5783,34 @@ Environment.Exit(1); | |||
5783 | 5783 | ||
5784 | public Vector3 GetNearestAllowedPosition(ScenePresence avatar, ILandObject excludeParcel) | 5784 | public Vector3 GetNearestAllowedPosition(ScenePresence avatar, ILandObject excludeParcel) |
5785 | { | 5785 | { |
5786 | ILandObject nearestParcel = GetNearestAllowedParcel(avatar.UUID, avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y, excludeParcel); | 5786 | Vector3 pos = avatar.AbsolutePosition; |
5787 | |||
5788 | ILandObject nearestParcel = GetNearestAllowedParcel(avatar.UUID, pos.X, pos.Y, excludeParcel); | ||
5789 | |||
5790 | Vector3 retPos = Vector3.Zero; | ||
5787 | 5791 | ||
5788 | if (nearestParcel != null) | 5792 | if (nearestParcel != null) |
5789 | { | 5793 | { |
5790 | Vector3 dir = Vector3.Normalize(Vector3.Multiply(avatar.Velocity, -1)); | 5794 | Vector2? nearestPoint = null; |
5791 | //Try to get a location that feels like where they came from | 5795 | Vector3 dir = -avatar.Velocity; |
5792 | Vector3? nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel); | 5796 | float dirlen = dir.Length(); |
5793 | if (nearestPoint != null) | 5797 | if(dirlen > 1.0f) |
5794 | { | 5798 | //Try to get a location that feels like where they came from |
5795 | m_log.Debug("Found a sane previous position based on velocity, sending them to: " + nearestPoint.ToString()); | 5799 | nearestPoint = nearestParcel.GetNearestPointAlongDirection(pos, dir); |
5796 | return nearestPoint.Value; | 5800 | |
5797 | } | 5801 | if (nearestPoint == null) |
5802 | nearestPoint = nearestParcel.GetNearestPoint(pos); | ||
5798 | 5803 | ||
5799 | //Sometimes velocity might be zero (local teleport), so try finding point along path from avatar to center of nearest parcel | ||
5800 | Vector3 directionToParcelCenter = Vector3.Subtract(GetParcelCenterAtGround(nearestParcel), avatar.AbsolutePosition); | ||
5801 | dir = Vector3.Normalize(directionToParcelCenter); | ||
5802 | nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel); | ||
5803 | if (nearestPoint != null) | 5804 | if (nearestPoint != null) |
5804 | { | 5805 | { |
5805 | m_log.Debug("They had a zero velocity, sending them to: " + nearestPoint.ToString()); | 5806 | retPos.X = nearestPoint.Value.X; |
5806 | return nearestPoint.Value; | 5807 | retPos.Y = nearestPoint.Value.Y; |
5808 | float h = GetGroundHeight(retPos.X, retPos.Y) + 0.8f; | ||
5809 | if(pos.Z > h) | ||
5810 | retPos.Z = pos.Z; | ||
5811 | else | ||
5812 | retPos.Z = h; | ||
5813 | return retPos; | ||
5807 | } | 5814 | } |
5808 | 5815 | ||
5809 | ILandObject dest = LandChannel.GetLandObject(avatar.lastKnownAllowedPosition.X, avatar.lastKnownAllowedPosition.Y); | 5816 | ILandObject dest = LandChannel.GetLandObject(avatar.lastKnownAllowedPosition.X, avatar.lastKnownAllowedPosition.Y); |
@@ -5833,15 +5840,36 @@ Environment.Exit(1); | |||
5833 | 5840 | ||
5834 | private Vector3? GetNearestPointInParcelAlongDirectionFromPoint(Vector3 pos, Vector3 direction, ILandObject parcel) | 5841 | private Vector3? GetNearestPointInParcelAlongDirectionFromPoint(Vector3 pos, Vector3 direction, ILandObject parcel) |
5835 | { | 5842 | { |
5836 | Vector3 unitDirection = Vector3.Normalize(direction); | 5843 | float maxX = RegionInfo.RegionSizeX; |
5844 | float maxY = RegionInfo.RegionSizeY; | ||
5845 | |||
5846 | // reduce resolution since regions can be very large now | ||
5847 | direction *= 4.0f; | ||
5848 | Vector3 testPos = pos; | ||
5837 | //Making distance to search go through some sane limit of distance | 5849 | //Making distance to search go through some sane limit of distance |
5838 | for (float distance = 0; distance < Math.Max(RegionInfo.RegionSizeX, RegionInfo.RegionSizeY) * 2; distance += .5f) | 5850 | while(true) |
5839 | { | 5851 | { |
5840 | Vector3 testPos = Vector3.Add(pos, Vector3.Multiply(unitDirection, distance)); | 5852 | testPos += direction; |
5841 | if (parcel.ContainsPoint((int)testPos.X, (int)testPos.Y)) | 5853 | if (parcel.ContainsPoint((int)testPos.X, (int)testPos.Y)) |
5842 | { | 5854 | { |
5855 | direction *= -0.125f; // .5m resolution | ||
5856 | Vector3 testPos2 = testPos - direction; | ||
5857 | for(int i = 0; i < 7; i++) | ||
5858 | { | ||
5859 | if (!parcel.ContainsPoint((int)testPos2.X, (int)testPos2.Y)) | ||
5860 | return testPos; | ||
5861 | testPos = testPos2; | ||
5862 | } | ||
5843 | return testPos; | 5863 | return testPos; |
5844 | } | 5864 | } |
5865 | if(testPos.X < 0) | ||
5866 | break; | ||
5867 | else if (testPos.X >= maxX) | ||
5868 | break; | ||
5869 | if(testPos.Y < 0) | ||
5870 | break; | ||
5871 | else if (testPos.Y >= maxY) | ||
5872 | break; | ||
5845 | } | 5873 | } |
5846 | return null; | 5874 | return null; |
5847 | } | 5875 | } |