lib/gamnit depth: discard fragments with a low alpha value
[nit.git] / lib / gamnit / cameras.nit
index 43aae77..0d64395 100644 (file)
@@ -38,7 +38,7 @@ abstract class Camera
        fun mvp_matrix: Matrix is abstract
 end
 
-# Simple camera with perspective oriented with Euler angles (`pitch`, `yaw`, `roll`)
+# Simple camera with perspective oriented with Euler angles (`pitch, yaw, roll`)
 class EulerCamera
        super Camera
 
@@ -63,8 +63,8 @@ class EulerCamera
 
        # Clipping wall the farthest of the camera, in world dimensions
        #
-       # Default at `100.0` but this one should be adapted to each context.
-       var far = 100.0 is writable
+       # Default at `10000.0` but this one should be adapted to each context.
+       var far = 10000.0 is writable
 
        # Look around sensitivity, used by `turn`
        var sensitivity = 0.005 is writable
@@ -98,6 +98,17 @@ class EulerCamera
                position.y += dy
        end
 
+       # Aim the camera at `x, y, z`
+       fun look_at(x, y, z: Float)
+       do
+               var dx = position.x
+               var dy = position.y
+               var dz = position.z
+
+               yaw = atan2(dx, dz)
+               pitch = atan2(-dy, dz)
+       end
+
        # Rotation matrix produced by the current rotation of the camera
        protected fun rotation_matrix: Matrix
        do
@@ -116,7 +127,7 @@ class EulerCamera
                var view = new Matrix.identity(4)
 
                # Translate the world away from the camera
-               view.translate(-position.x/2.0, -position.y/2.0, -position.z/2.0)
+               view.translate(-position.x, -position.y, -position.z)
 
                # Rotate the camera, first by looking left or right, then up or down
                view = view * rotation_matrix
@@ -127,6 +138,30 @@ class EulerCamera
 
                return view * projection
        end
+
+       # Reset the camera position so that `height` world units are visible on the y axis at z=0
+       #
+       # By default, `height` is set to `display.height`.
+       #
+       # After the reset, the camera sits on the Z axis and rotation values are reset to 0.
+       # The X axis is horizontal on the screen and the Y axis is vertical.
+       # Higher values on the Z axis are closer to the camera.
+       fun reset_height(height: nullable Float)
+       do
+               if height == null then height = display.height.to_f
+
+               var opp = height / 2.0
+               var angle = field_of_view_y / 2.0
+               var adj = opp / angle.tan
+
+               position.x = 0.0
+               position.y = 0.0
+               position.z = adj
+
+               pitch = 0.0
+               yaw = 0.0
+               roll = 0.0
+       end
 end
 
 # Orthogonal camera to draw UI objects with services to work with screens of different sizes
@@ -173,6 +208,9 @@ class UICamera
                return new Point[Float](wx, wy)
        end
 
+       # Center of the screen, from the point of view of the camera, at z = 0
+       fun center: Point3d[Float] do return new Point3d[Float](position.x + width / 2.0, position.y + height / 2.0, 0.0)
+
        # Anchor in the top left corner of the screen, at z = 0
        fun top_left: Point3d[Float] do return new Point3d[Float](position.x, position.y, 0.0)
 
@@ -192,7 +230,7 @@ class UICamera
                var view = new Matrix.identity(4)
 
                # Translate the world away from the camera
-               view.translate(-position.x/2.0, -position.y/2.0, -position.z/2.0)
+               view.translate(-position.x, -position.y, -position.z)
 
                # Use a projection matrix with a depth
                var projection = new Matrix.orthogonal(0.0, width, -height, 0.0, near, far)