/// <summary>Sorts a list of faces.</summary> /// <param name="faces">The list of faces.</param> /// <param name="dummy">A dummy list of the same length as the list of faces.</param> /// <param name="index">The index in the list at which to start sorting.</param> /// <param name="count">The number of items in the list which to sort.</param> /// <remarks>This method implements a stable merge sort that switches to an in-place stable insertion sort with sufficiently few elements.</remarks> private static void SortPositionedFaces(PositionedFace[] faces, PositionedFace[] dummy, int index, int count) { if (count < 25) { /* * Use an insertion sort for less than 25 elements * */ for (int i = 1; i < count; i++) { int j; for (j = i - 1; j >= 0; j--) { if (faces[index + i].Tag >= faces[index + j].Tag) { break; } } PositionedFace temp = faces[index + i]; for (int k = i; k > j + 1; k--) { faces[index + k] = faces[index + k - 1]; } faces[index + j + 1] = temp; } } else { /* * For more than three elements, split the list in * half, recursively sort the two lists, then merge * them back together. * */ int halfCount = count / 2; SortPositionedFaces(faces, dummy, index, halfCount); SortPositionedFaces(faces, dummy, index + halfCount, count - halfCount); int left = index; int right = index + halfCount; for (int i = index; i < index + count; i++) { if (left == index + halfCount) { while (right != index + count) { dummy[i] = faces[right]; right++; i++; } break; } else if (right == index + count) { while (left != index + halfCount) { dummy[i] = faces[left]; left++; i++; } break; } if (faces[left].Tag <= faces[right].Tag) { dummy[i] = faces[left]; left++; } else { dummy[i] = faces[right]; right++; } } for (int i = index; i < index + count; i++) { faces[i] = dummy[i]; } } }
/// <summary>Adds the face of an object from the object library to this collection.</summary> /// <param name="libraryIndex">The object in the object library.</param> /// <param name="faceIndex">The face of the object.</param> /// <param name="position">The absolute position of the face.</param> /// <param name="orientation">The absolute orientation of the face.</param> /// <returns>A reference to the added face which can be used later to remove it again.</returns> internal object Add(int libraryIndex, int faceIndex, OpenBveApi.Math.Vector3 position, OpenBveApi.Math.Orientation3 orientation) { /* * Only add face-vertex meshes. * */ OpenBveApi.Geometry.FaceVertexMesh mesh = ObjectLibrary.Library.Objects[libraryIndex] as OpenBveApi.Geometry.FaceVertexMesh; if (mesh != null) { /* * Add the face. * */ if (this.FaceCount == this.Faces.Length) { Array.Resize<PositionedFace>(ref this.Faces, this.Faces.Length << 1); int count = this.Lists.Length; Array.Resize<DisplayList>(ref this.Lists, count << 1); for (int i = count; i < this.Lists.Length; i++) { this.Lists[i] = new DisplayList(); } Array.Resize<bool>(ref this.ListsChanged, this.ListsChanged.Length << 1); } PositionedFace face = new PositionedFace(libraryIndex, faceIndex, position, orientation, this.FaceCount); this.Faces[this.FaceCount] = face; this.ListsChanged[this.FaceCount / this.FacesPerDisplayList] = true; this.FaceCount++; /* * Make sure the textures used by the face have been loaded. * */ for (int i = 0; i < mesh.Faces.Length; i++) { int material = mesh.Faces[i].Material; Textures.ApiHandle apiHandle = mesh.Materials[material].DaytimeTexture as Textures.ApiHandle; if (apiHandle != null) { Textures.LoadTexture(apiHandle.TextureIndex, true); } } return (object)face; } else { return null; } }
// static functions /// <summary>Sorts a list of faces.</summary> /// <param name="faces">The list of faces.</param> /// <param name="index">The index in the list at which to start sorting.</param> /// <param name="count">The number of items in the list which to sort.</param> private static void SortPositionedFaces(PositionedFace[] faces, int index, int count) { PositionedFace[] dummy = new PositionedFace[faces.Length]; SortPositionedFaces(faces, dummy, index, count); }