/// <summary>Checks if a block specified by its bounding rectangle intersects any of the specified triangles.</summary>
 /// <param name="block">The bounding rectangle of the block.</param>
 /// <param name="triangles">An array of triangles that was obtained from a call to InitializeBlockClipping.</param>
 /// <returns>Whether the block intersects any of the triangles.</returns>
 private static bool BlockIntersectsTriangles(ObjectGrid.GridBounds block, Triangle[] triangles)
 {
     for (int i = 0; i < triangles.Length; i++) {
         if (BlockIntersectsTriangle(block, triangles[i])) {
             return true;
         }
     }
     return false;
 }
Example #2
0
 /// <summary>Renders the objects attached to a specified populated leaf node.</summary>
 /// <param name="leaf">The leaf node to render.</param>
 private static void RenderGridLeafNode(ObjectGrid.GridPopulatedLeafNode leaf, bool includeVisibleLeafNodes)
 {
     /* Create the display list for the leaf node if not yet available. */
     if (leaf.DisplayList.IsUnavailable()) {
         leaf.CreateOrUpdateDisplayList();
     }
     /* Render the leaf node if the display list is available. */
     if (leaf.DisplayList.IsAvailable()) {
         double x = 0.5 * (leaf.Rectangle.Left + leaf.Rectangle.Right) - Camera.GridLeafNodeCenter.X;
         double y = -Camera.GridLeafNodeCenter.Y;
         double z = 0.5 * (leaf.Rectangle.Near + leaf.Rectangle.Far) - Camera.GridLeafNodeCenter.Z;
         Gl.glPushMatrix();
         Gl.glTranslated(x, y, z);
         leaf.DisplayList.Call();
         Gl.glPopMatrix();
     }
 }
 /// <summary>Checks if a block specified by its bounding rectangle intersects a specified triangle.</summary>
 /// <param name="block">The bounding rectangle of the block.</param>
 /// <param name="triangles">The triangle.</param>
 /// <returns>Whether the block intersects the triangle.</returns>
 private static bool BlockIntersectsTriangle(ObjectGrid.GridBounds block, Triangle triangle)
 {
     /*
      * First, let's check if the bounding rectangle of the
      * block intersects the bounding rectangle of the
      * triangle. If so, we need further checks to ensure
      * that the actual triangle intersects the block,
      * but if not, the triangle cannot intersect the block.
      * */
     if (
         block.Left <= triangle.BoundingRectangle.Right &
         block.Right >= triangle.BoundingRectangle.Left &
         block.Near <= triangle.BoundingRectangle.Far &
         block.Far >= triangle.BoundingRectangle.Near
     ) {
         /*
          * The bounding rectangles intersect. This means that
          * the triangle could intersect the block, but not
          * necessarily. First, let's check if any point of
          * the triangle lies inside the rectangle.
          * */
         if (
             triangle.PointA.X >= block.Left && triangle.PointA.X <= block.Right &&
             triangle.PointA.Y >= block.Near && triangle.PointA.Y <= block.Far
         ) {
             return true;
         } else if (
             triangle.PointB.X >= block.Left && triangle.PointB.X <= block.Right &&
             triangle.PointB.Y >= block.Near && triangle.PointB.Y <= block.Far
         ) {
             return true;
         } else if (
             triangle.PointC.X >= block.Left && triangle.PointC.X <= block.Right &&
             triangle.PointC.Y >= block.Near && triangle.PointC.Y <= block.Far
         ) {
             return true;
         } else {
             /*
              * There is no point of the triangle that lies inside
              * the rectangle. Now, let's check if any point of the
              * rectangle lies inside the triangle.
              * */
             if (IsPointInTriangle(new OpenBveApi.Math.Vector2(block.Left, block.Near), triangle)) {
                 return true;
             } else if (IsPointInTriangle(new OpenBveApi.Math.Vector2(block.Left, block.Far), triangle)) {
                 return true;
             } else if (IsPointInTriangle(new OpenBveApi.Math.Vector2(block.Right, block.Far), triangle)) {
                 return true;
             } else if (IsPointInTriangle(new OpenBveApi.Math.Vector2(block.Right, block.Near), triangle)) {
                 return true;
             } else {
                 /* No point of the rectangle lies inside the triangle.
                  * Now, let's check each edge of the triangle against
                  * each edge of the rectangle for intersection.
                  * */
                 for (int i = 0; i < 3; i++) {
                     OpenBveApi.Math.Vector2 a;
                     OpenBveApi.Math.Vector2 b;
                     if (i == 0) {
                         a = triangle.PointA;
                         b = triangle.PointB;
                     } else if (i == 1) {
                         a = triangle.PointB;
                         b = triangle.PointC;
                     } else {
                         a = triangle.PointC;
                         b = triangle.PointA;
                     }
                     /*
                      * Compare the current triangle edge against the
                      * left and right vertical edges of the rectangle.
                      * */
                     {
                         double denominator = a.X - b.X;
                         if (denominator == 0.0) {
                             if (a.X >= block.Left & a.X <= block.Right) {
                                 if (a.Y <= block.Near & b.Y >= block.Far | a.Y >= block.Far & b.Y <= block.Near) {
                                     return true;
                                 }
                             }
                         } else {
                             for (int j = 0; j < 2; j++) {
                                 double px = j == 0 ? block.Left : block.Right;
                                 double numerator = a.Y * (px - b.X) - b.Y * (px - a.X);
                                 double py = numerator / denominator;
                                 if (py >= block.Near & py <= block.Far) {
                                     double r = (px - a.X) / (b.X - a.X);
                                     if (r >= 0.0 & r <= 1.0) {
                                         return true;
                                     }
                                 }
                             }
                         }
                     }
                     /*
                      * Compare the current triangle edge against the
                      * near and far horizontal edges of the rectangle.
                      * */
                     {
                         double denominator = a.Y - b.Y;
                         if (denominator == 0.0) {
                             if (a.Y >= block.Near & a.Y <= block.Far) {
                                 if (a.X <= block.Left & b.X >= block.Right | a.X >= block.Right & b.X <= block.Left) {
                                     return true;
                                 }
                             }
                         } else {
                             for (int j = 0; j < 2; j++) {
                                 double py = j == 0 ? block.Near : block.Far;
                                 double numerator = a.X * (py - b.Y) - b.X * (py - a.Y);
                                 double px = numerator / denominator;
                                 if (px >= block.Left & px <= block.Right) {
                                     double r = (py - a.Y) / (b.Y - a.Y);
                                     if (r >= 0.0 & r <= 1.0) {
                                         return true;
                                     }
                                 }
                             }
                         }
                     }
                 }
                 /*
                  * No point of the triangle lies inside the rectangle,
                  * no point of the rectangle lies inside the triangle,
                  * and no triangle edge intersects with a rectangle
                  * edge. Thus, the triangle does not intersect the
                  * rectangle.
                  * */
                 return false;
             }
         }
     } else {
         /*
          * The bounding rectangles do not intersect. The
          * triangle itself thus cannot intersect the block.
          * */
         return false;
     }
 }
Example #4
0
 /// <summary>Renders the opaque part of a set of specified static objects.</summary>
 /// <param name="objects">The list of static objects.</param>
 /// <param name="count">The number of static objects.</param>
 /// <param name="count">The current OpenGL state.</param>
 /// <remarks>This function may change the texture or emissive color in the current OpenGL state.</remarks>
 internal static void RenderStaticOpaqueObjects(ObjectGrid.StaticOpaqueObject[] objects, int count, ref OpenGlState state)
 {
     /*
      * Count the number of faces.
      * */
     int faceCount = 0;
     for (int i = 0; i < count; i++) {
         OpenBveApi.Geometry.FaceVertexMesh mesh = ObjectLibrary.Library.Objects[objects[i].LibraryIndex] as OpenBveApi.Geometry.FaceVertexMesh;
         if (mesh != null) {
             faceCount += mesh.Faces.Length;
         }
     }
     /*
      * Sort the faces by shared material properties. This will later increase
      * rendering speed as fewer state changes will be involved in OpenGL.
      * */
     Face[] faces = new Face[faceCount];
     long[] keys = new long[faceCount];
     faceCount = 0;
     for (int i = 0; i < count; i++) {
         OpenBveApi.Geometry.FaceVertexMesh mesh = ObjectLibrary.Library.Objects[objects[i].LibraryIndex] as OpenBveApi.Geometry.FaceVertexMesh;
         if (mesh != null) {
             for (int j = 0; j < mesh.Faces.Length; j++) {
                 int material = mesh.Faces[j].Material;
                 long texture =
                     mesh.Materials[material].DaytimeTexture is Textures.ApiHandle ?
                     (long)(((Textures.ApiHandle)mesh.Materials[material].DaytimeTexture).TextureIndex) + 1 :
                     (long)0;
                 long emissive =
                     (long)(255.0f * mesh.Materials[material].EmissiveColor.R) |
                     (long)(255.0f * mesh.Materials[material].EmissiveColor.G) << 8 |
                     (long)(255.0f * mesh.Materials[material].EmissiveColor.B) << 16;
                 faces[faceCount] = new Face(i, j);
                 keys[faceCount] = texture | emissive << 32;
                 faceCount++;
             }
         }
     }
     Array.Sort<long, Face>(keys, faces);
     /*
      * Render the faces.
      * */
     state.SetAlphaFunction(Gl.GL_EQUAL, 1.0f);
     for (int i = 0; i < faceCount; i++) {
         int objectIndex = faces[i].ObjectIndex;
         OpenBveApi.Geometry.FaceVertexMesh mesh = ObjectLibrary.Library.Objects[objects[objectIndex].LibraryIndex] as OpenBveApi.Geometry.FaceVertexMesh;
         if (mesh != null) {
             int material = mesh.Faces[faces[i].FaceIndex].Material;
             if (mesh.Materials[material].BlendMode == OpenBveApi.Geometry.BlendMode.Normal) {
                 RenderFace(mesh, faces[i].FaceIndex, objects[objectIndex].GridPosition, objects[objectIndex].GridOrientation, ref state);
             }
         }
     }
 }