aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--OpenSim/Framework/ILandObject.cs4
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandObject.cs147
-rwxr-xr-xOpenSim/Region/Framework/Scenes/Scene.cs64
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 }