diff options
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/Scene.cs')
-rw-r--r-- | OpenSim/Region/Framework/Scenes/Scene.cs | 397 |
1 files changed, 5 insertions, 392 deletions
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 7cce3b6..ebf5a06 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs | |||
@@ -1113,7 +1113,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1113 | } | 1113 | } |
1114 | 1114 | ||
1115 | /// <summary> | 1115 | /// <summary> |
1116 | /// | 1116 | /// Create a terrain texture for this scene |
1117 | /// </summary> | 1117 | /// </summary> |
1118 | public void CreateTerrainTexture(bool temporary) | 1118 | public void CreateTerrainTexture(bool temporary) |
1119 | { | 1119 | { |
@@ -1125,398 +1125,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
1125 | return; | 1125 | return; |
1126 | 1126 | ||
1127 | if (terrain == null) | 1127 | if (terrain == null) |
1128 | { | 1128 | return; |
1129 | #region Fallback default maptile generation | ||
1130 | |||
1131 | int tc = Environment.TickCount; | ||
1132 | m_log.Info("[MAPTILE]: Generating Maptile Step 1: Terrain"); | ||
1133 | Bitmap mapbmp = new Bitmap(256, 256); | ||
1134 | double[,] hm = Heightmap.GetDoubles(); | ||
1135 | bool ShadowDebugContinue = true; | ||
1136 | //Color prim = Color.FromArgb(120, 120, 120); | ||
1137 | //Vector3 RayEnd = new Vector3(0, 0, 0); | ||
1138 | //Vector3 RayStart = new Vector3(0, 0, 0); | ||
1139 | //Vector3 direction = new Vector3(0, 0, -1); | ||
1140 | //Vector3 AXOrigin = new Vector3(); | ||
1141 | //Vector3 AXdirection = new Vector3(); | ||
1142 | //Ray testRay = new Ray(); | ||
1143 | //EntityIntersection rt = new EntityIntersection(); | ||
1144 | bool terraincorruptedwarningsaid = false; | ||
1145 | |||
1146 | float low = 255; | ||
1147 | float high = 0; | ||
1148 | for (int x = 0; x < 256; x++) | ||
1149 | { | ||
1150 | for (int y = 0; y < 256; y++) | ||
1151 | { | ||
1152 | float hmval = (float)hm[x, y]; | ||
1153 | if (hmval < low) | ||
1154 | low = hmval; | ||
1155 | if (hmval > high) | ||
1156 | high = hmval; | ||
1157 | } | ||
1158 | } | ||
1159 | |||
1160 | float mid = (high + low) * 0.5f; | ||
1161 | |||
1162 | // temporary initializer | ||
1163 | float hfvalue = (float)m_regInfo.RegionSettings.WaterHeight; | ||
1164 | float hfvaluecompare = hfvalue; | ||
1165 | float hfdiff = hfvalue; | ||
1166 | int hfdiffi = 0; | ||
1167 | |||
1168 | for (int x = 0; x < 256; x++) | ||
1169 | { | ||
1170 | //int tc = System.Environment.TickCount; | ||
1171 | for (int y = 0; y < 256; y++) | ||
1172 | { | ||
1173 | //RayEnd = new Vector3(x, y, 0); | ||
1174 | //RayStart = new Vector3(x, y, 255); | ||
1175 | |||
1176 | //direction = Vector3.Norm(RayEnd - RayStart); | ||
1177 | //AXOrigin = new Vector3(RayStart.X, RayStart.Y, RayStart.Z); | ||
1178 | //AXdirection = new Vector3(direction.X, direction.Y, direction.Z); | ||
1179 | |||
1180 | //testRay = new Ray(AXOrigin, AXdirection); | ||
1181 | //rt = m_sceneGraph.GetClosestIntersectingPrim(testRay); | ||
1182 | |||
1183 | //if (rt.HitTF) | ||
1184 | //{ | ||
1185 | //mapbmp.SetPixel(x, y, prim); | ||
1186 | //} | ||
1187 | //else | ||
1188 | //{ | ||
1189 | //float tmpval = (float)hm[x, y]; | ||
1190 | float heightvalue = (float)hm[x, y]; | ||
1191 | |||
1192 | if (heightvalue > (float)m_regInfo.RegionSettings.WaterHeight) | ||
1193 | { | ||
1194 | // scale height value | ||
1195 | heightvalue = low + mid * (heightvalue - low) / mid; | ||
1196 | |||
1197 | if (heightvalue > 255) | ||
1198 | heightvalue = 255; | ||
1199 | |||
1200 | if (heightvalue < 0) | ||
1201 | heightvalue = 0; | ||
1202 | |||
1203 | if (Single.IsInfinity(heightvalue) || Single.IsNaN(heightvalue)) | ||
1204 | heightvalue = 0; | ||
1205 | |||
1206 | try | ||
1207 | { | ||
1208 | Color green = Color.FromArgb((int)heightvalue, 100, (int)heightvalue); | ||
1209 | |||
1210 | // Y flip the cordinates | ||
1211 | mapbmp.SetPixel(x, (256 - y) - 1, green); | ||
1212 | |||
1213 | //X | ||
1214 | // . | ||
1215 | // | ||
1216 | // Shade the terrain for shadows | ||
1217 | if ((x - 1 > 0) && (y - 1 > 0)) | ||
1218 | { | ||
1219 | hfvalue = (float)hm[x, y]; | ||
1220 | hfvaluecompare = (float)hm[x - 1, y - 1]; | ||
1221 | |||
1222 | if (Single.IsInfinity(hfvalue) || Single.IsNaN(hfvalue)) | ||
1223 | hfvalue = 0; | ||
1224 | |||
1225 | if (Single.IsInfinity(hfvaluecompare) || Single.IsNaN(hfvaluecompare)) | ||
1226 | hfvaluecompare = 0; | ||
1227 | |||
1228 | hfdiff = hfvaluecompare - hfvalue; | ||
1229 | |||
1230 | if (hfdiff > 0.3f) | ||
1231 | { | ||
1232 | |||
1233 | } | ||
1234 | else if (hfdiff < -0.3f) | ||
1235 | { | ||
1236 | // We have to desaturate and blacken the land at the same time | ||
1237 | // we use floats, colors use bytes, so shrink are space down to | ||
1238 | // 0-255 | ||
1239 | |||
1240 | try | ||
1241 | { | ||
1242 | hfdiffi = Math.Abs((int)((hfdiff * 4) + (hfdiff * 0.5))) + 1; | ||
1243 | if (hfdiff % 1 != 0) | ||
1244 | { | ||
1245 | hfdiffi = hfdiffi + Math.Abs((int)(((hfdiff % 1) * 0.5f) * 10f) - 1); | ||
1246 | } | ||
1247 | } | ||
1248 | catch (OverflowException) | ||
1249 | { | ||
1250 | m_log.Debug("[MAPTILE]: Shadow failed at value: " + hfdiff.ToString()); | ||
1251 | ShadowDebugContinue = false; | ||
1252 | } | ||
1253 | |||
1254 | if (ShadowDebugContinue) | ||
1255 | { | ||
1256 | if ((256 - y) - 1 > 0) | ||
1257 | { | ||
1258 | Color Shade = mapbmp.GetPixel(x - 1, (256 - y) - 1); | ||
1259 | |||
1260 | int r = Shade.R; | ||
1261 | |||
1262 | int g = Shade.G; | ||
1263 | int b = Shade.B; | ||
1264 | Shade = Color.FromArgb((r - hfdiffi > 0) ? r - hfdiffi : 0, (g - hfdiffi > 0) ? g - hfdiffi : 0, (b - hfdiffi > 0) ? b - hfdiffi : 0); | ||
1265 | //Console.WriteLine("d:" + hfdiff.ToString() + ", i:" + hfdiffi + ", pos: " + x + "," + y + " - R:" + Shade.R.ToString() + ", G:" + Shade.G.ToString() + ", B:" + Shade.G.ToString()); | ||
1266 | mapbmp.SetPixel(x - 1, (256 - y) - 1, Shade); | ||
1267 | } | ||
1268 | } | ||
1269 | } | ||
1270 | } | ||
1271 | } | ||
1272 | catch (ArgumentException) | ||
1273 | { | ||
1274 | if (!terraincorruptedwarningsaid) | ||
1275 | { | ||
1276 | m_log.WarnFormat("[MAPIMAGE]: Your terrain is corrupted in region {0}, it might take a few minutes to generate the map image depending on the corruption level", RegionInfo.RegionName); | ||
1277 | terraincorruptedwarningsaid = true; | ||
1278 | } | ||
1279 | Color black = Color.Black; | ||
1280 | mapbmp.SetPixel(x, (256 - y) - 1, black); | ||
1281 | } | ||
1282 | } | ||
1283 | else | ||
1284 | { | ||
1285 | // Y flip the cordinates | ||
1286 | heightvalue = (float)m_regInfo.RegionSettings.WaterHeight - heightvalue; | ||
1287 | if (heightvalue > 19) | ||
1288 | heightvalue = 19; | ||
1289 | if (heightvalue < 0) | ||
1290 | heightvalue = 0; | ||
1291 | |||
1292 | heightvalue = 100 - (heightvalue * 100) / 19; | ||
1293 | |||
1294 | if (heightvalue > 255) | ||
1295 | heightvalue = 255; | ||
1296 | |||
1297 | if (heightvalue < 0) | ||
1298 | heightvalue = 0; | ||
1299 | |||
1300 | if (Single.IsInfinity(heightvalue) || Single.IsNaN(heightvalue)) | ||
1301 | heightvalue = 0; | ||
1302 | |||
1303 | try | ||
1304 | { | ||
1305 | Color water = Color.FromArgb((int)heightvalue, (int)heightvalue, 255); | ||
1306 | mapbmp.SetPixel(x, (256 - y) - 1, water); | ||
1307 | } | ||
1308 | catch (ArgumentException) | ||
1309 | { | ||
1310 | if (!terraincorruptedwarningsaid) | ||
1311 | { | ||
1312 | m_log.WarnFormat("[MAPIMAGE]: Your terrain is corrupted in region {0}, it might take a few minutes to generate the map image depending on the corruption level", RegionInfo.RegionName); | ||
1313 | terraincorruptedwarningsaid = true; | ||
1314 | } | ||
1315 | Color black = Color.Black; | ||
1316 | mapbmp.SetPixel(x, (256 - y) - 1, black); | ||
1317 | } | ||
1318 | } | ||
1319 | } | ||
1320 | //} | ||
1321 | |||
1322 | //tc = System.Environment.TickCount - tc; | ||
1323 | //m_log.Info("[MAPTILE]: Completed One row in " + tc + " ms"); | ||
1324 | } | ||
1325 | |||
1326 | m_log.Info("[MAPTILE]: Generating Maptile Step 1: Done in " + (Environment.TickCount - tc) + " ms"); | ||
1327 | |||
1328 | bool drawPrimVolume = true; | ||
1329 | |||
1330 | try | ||
1331 | { | ||
1332 | IConfig startupConfig = m_config.Configs["Startup"]; | ||
1333 | drawPrimVolume = startupConfig.GetBoolean("DrawPrimOnMapTile", true); | ||
1334 | } | ||
1335 | catch | ||
1336 | { | ||
1337 | m_log.Warn("[MAPTILE]: Failed to load StartupConfig"); | ||
1338 | } | ||
1339 | |||
1340 | if (drawPrimVolume) | ||
1341 | { | ||
1342 | tc = Environment.TickCount; | ||
1343 | m_log.Info("[MAPTILE]: Generating Maptile Step 2: Object Volume Profile"); | ||
1344 | List<EntityBase> objs = GetEntities(); | ||
1345 | |||
1346 | lock (objs) | ||
1347 | { | ||
1348 | foreach (EntityBase obj in objs) | ||
1349 | { | ||
1350 | // Only draw the contents of SceneObjectGroup | ||
1351 | if (obj is SceneObjectGroup) | ||
1352 | { | ||
1353 | SceneObjectGroup mapdot = (SceneObjectGroup)obj; | ||
1354 | Color mapdotspot = Color.Gray; // Default color when prim color is white | ||
1355 | // Loop over prim in group | ||
1356 | foreach (SceneObjectPart part in mapdot.Children.Values) | ||
1357 | { | ||
1358 | if (part == null) | ||
1359 | continue; | ||
1360 | |||
1361 | // Draw if the object is at least 1 meter wide in any direction | ||
1362 | if (part.Scale.X > 1f || part.Scale.Y > 1f || part.Scale.Z > 1f) | ||
1363 | { | ||
1364 | // Try to get the RGBA of the default texture entry.. | ||
1365 | // | ||
1366 | try | ||
1367 | { | ||
1368 | if (part == null) | ||
1369 | continue; | ||
1370 | |||
1371 | if (part.Shape == null) | ||
1372 | continue; | ||
1373 | |||
1374 | if (part.Shape.PCode == (byte)PCode.Tree || part.Shape.PCode == (byte)PCode.NewTree) | ||
1375 | continue; // eliminates trees from this since we don't really have a good tree representation | ||
1376 | // if you want tree blocks on the map comment the above line and uncomment the below line | ||
1377 | //mapdotspot = Color.PaleGreen; | ||
1378 | |||
1379 | if (part.Shape.Textures == null) | ||
1380 | continue; | ||
1381 | |||
1382 | if (part.Shape.Textures.DefaultTexture == null) | ||
1383 | continue; | ||
1384 | |||
1385 | Color4 texcolor = part.Shape.Textures.DefaultTexture.RGBA; | ||
1386 | |||
1387 | // Not sure why some of these are null, oh well. | ||
1388 | |||
1389 | int colorr = 255 - (int)(texcolor.R * 255f); | ||
1390 | int colorg = 255 - (int)(texcolor.G * 255f); | ||
1391 | int colorb = 255 - (int)(texcolor.B * 255f); | ||
1392 | |||
1393 | if (!(colorr == 255 && colorg == 255 && colorb == 255)) | ||
1394 | { | ||
1395 | //Try to set the map spot color | ||
1396 | try | ||
1397 | { | ||
1398 | // If the color gets goofy somehow, skip it *shakes fist at Color4 | ||
1399 | mapdotspot = Color.FromArgb(colorr, colorg, colorb); | ||
1400 | } | ||
1401 | catch (ArgumentException) | ||
1402 | { | ||
1403 | } | ||
1404 | } | ||
1405 | } | ||
1406 | catch (IndexOutOfRangeException) | ||
1407 | { | ||
1408 | // Windows Array | ||
1409 | } | ||
1410 | catch (ArgumentOutOfRangeException) | ||
1411 | { | ||
1412 | // Mono Array | ||
1413 | } | ||
1414 | |||
1415 | Vector3 pos = part.GetWorldPosition(); | ||
1416 | |||
1417 | // skip prim outside of retion | ||
1418 | if (pos.X < 0f || pos.X > 256f || pos.Y < 0f || pos.Y > 256f) | ||
1419 | continue; | ||
1420 | |||
1421 | // skip prim in non-finite position | ||
1422 | if (Single.IsNaN(pos.X) || Single.IsNaN(pos.Y) || Single.IsInfinity(pos.X) | ||
1423 | || Single.IsInfinity(pos.Y)) | ||
1424 | continue; | ||
1425 | |||
1426 | // Figure out if object is under 256m above the height of the terrain | ||
1427 | bool isBelow256AboveTerrain = false; | ||
1428 | |||
1429 | try | ||
1430 | { | ||
1431 | isBelow256AboveTerrain = (pos.Z < ((float)hm[(int)pos.X, (int)pos.Y] + 256f)); | ||
1432 | } | ||
1433 | catch (Exception) | ||
1434 | { | ||
1435 | } | ||
1436 | |||
1437 | if (isBelow256AboveTerrain) | ||
1438 | { | ||
1439 | // Translate scale by rotation so scale is represented properly when object is rotated | ||
1440 | Vector3 scale = part.Shape.Scale; | ||
1441 | Quaternion rot = part.GetWorldRotation(); | ||
1442 | scale *= rot; | ||
1443 | |||
1444 | // negative scales don't work in this situation | ||
1445 | scale.X = Math.Abs(scale.X); | ||
1446 | scale.Y = Math.Abs(scale.Y); | ||
1447 | scale.Z = Math.Abs(scale.Z); | ||
1448 | |||
1449 | // This scaling isn't very accurate and doesn't take into account the face rotation :P | ||
1450 | int mapdrawstartX = (int)(pos.X - scale.X); | ||
1451 | int mapdrawstartY = (int)(pos.Y - scale.Y); | ||
1452 | int mapdrawendX = (int)(pos.X + scale.X); | ||
1453 | int mapdrawendY = (int)(pos.Y + scale.Y); | ||
1454 | |||
1455 | // If object is beyond the edge of the map, don't draw it to avoid errors | ||
1456 | if (mapdrawstartX < 0 || mapdrawstartX > 255 || mapdrawendX < 0 || mapdrawendX > 255 | ||
1457 | || mapdrawstartY < 0 || mapdrawstartY > 255 || mapdrawendY < 0 | ||
1458 | || mapdrawendY > 255) | ||
1459 | continue; | ||
1460 | |||
1461 | int wy = 0; | ||
1462 | |||
1463 | bool breakYN = false; // If we run into an error drawing, break out of the | ||
1464 | // loop so we don't lag to death on error handling | ||
1465 | for (int wx = mapdrawstartX; wx < mapdrawendX; wx++) | ||
1466 | { | ||
1467 | for (wy = mapdrawstartY; wy < mapdrawendY; wy++) | ||
1468 | { | ||
1469 | //m_log.InfoFormat("[MAPDEBUG]: {0},{1}({2})", wx, (255 - wy),wy); | ||
1470 | try | ||
1471 | { | ||
1472 | // Remember, flip the y! | ||
1473 | mapbmp.SetPixel(wx, (255 - wy), mapdotspot); | ||
1474 | } | ||
1475 | catch (ArgumentException) | ||
1476 | { | ||
1477 | breakYN = true; | ||
1478 | } | ||
1479 | |||
1480 | if (breakYN) | ||
1481 | break; | ||
1482 | } | ||
1483 | |||
1484 | if (breakYN) | ||
1485 | break; | ||
1486 | } | ||
1487 | } // Object is within 256m Z of terrain | ||
1488 | } // object is at least a meter wide | ||
1489 | } // loop over group children | ||
1490 | } // entitybase is sceneobject group | ||
1491 | } // foreach loop over entities | ||
1492 | } // lock entities objs | ||
1493 | |||
1494 | m_log.Info("[MAPTILE]: Generating Maptile Step 2: Done in " + (Environment.TickCount - tc) + " ms"); | ||
1495 | } // end if drawPrimOnMaptle | ||
1496 | |||
1497 | byte[] data; | ||
1498 | try | ||
1499 | { | ||
1500 | data = OpenJPEG.EncodeFromImage(mapbmp, false); | ||
1501 | } | ||
1502 | catch (Exception) | ||
1503 | { | ||
1504 | return; | ||
1505 | } | ||
1506 | |||
1507 | LazySaveGeneratedMaptile(data,temporary); | ||
1508 | 1129 | ||
1509 | #endregion | 1130 | byte[] data = terrain.WriteJpeg2000Image("defaultstripe.png"); |
1510 | } | 1131 | if (data != null) |
1511 | else | 1132 | LazySaveGeneratedMaptile(data, temporary); |
1512 | { | ||
1513 | // Use the module to generate the maptile. | ||
1514 | byte[] data = terrain.WriteJpeg2000Image("defaultstripe.png"); | ||
1515 | if (data != null) | ||
1516 | { | ||
1517 | LazySaveGeneratedMaptile(data,temporary); | ||
1518 | } | ||
1519 | } | ||
1520 | } | 1133 | } |
1521 | 1134 | ||
1522 | public void LazySaveGeneratedMaptile(byte[] data, bool temporary) | 1135 | public void LazySaveGeneratedMaptile(byte[] data, bool temporary) |