gamnit: 3 Euler rotation angles for actors
[nit.git] / lib / gamnit / depth / depth_core.nit
index 45863dc..db13d81 100644 (file)
@@ -17,26 +17,89 @@ module depth_core
 
 intrude import gamnit::flat
 
-# Visible entity in the game world, represented by its `model` modified by the other attributes
+# Visible 3D entity in the game world
+#
+# Similar to `gamnit::Sprite` which is in 2D.
+#
+# Each actor associates a `model` to the position `center`.
+# The appearance is modified by `rotation`, `scale` and `alpha`,
+# as well as the attributes of `model` itself.
+#
+# ~~~
+# import gamnit::depth
+#
+# # Load model from the assets folder
+# var model = new Model("path/in/assets.obj")
+#
+# # Create and configure an actor
+# var actor = new Actor(model, new Point3d[Float](0.0, 0.0, 0.0))
+# actor.scale = 2.0
+#
+# # Add to the visible game world
+# app.actors.add actor
+# ~~~
 class Actor
 
-       # Model used to dray this actor
+       # Model used to draw this actor
        var model: Model
 
        # Position of this sprite in world coordinates
        var center: Point3d[Float] is writable
 
-       # Rotation on the Z axis
-       var rotation = 0.0 is writable
+       # Rotation around the X axis (+ looks up, - looks down)
+       #
+       # Positive values look up, and negative look down.
+       #
+       # All actor rotations follow the right hand rule.
+       # The default orientation of the model should look towards -Z.
+       var pitch = 0.0 is writable
+
+       # Rotation around the Y axis (+ turns left, - turns right)
+       #
+       # Positive values turn `self` to the left, and negative values to the right.
+       #
+       # All actor rotations follow the right hand rule.
+       # The default orientation of the model should look towards -Z.
+       var yaw = 0.0 is writable
+
+       # Rotation around the Z axis (looking to -Z: + turns counterclockwise, - clockwise)
+       #
+       # From the default camera point of view, looking down on the Z axis,
+       # positive values turn `self` counterclockwise, and negative values clockwise.
+       #
+       # All actor rotations follow the right hand rule.
+       # The default orientation of the model should look towards -Z.
+       var roll = 0.0 is writable
 
-       # Scale applied to this sprite
+       # Scale applied to the model
        var scale = 1.0 is writable
 
-       # Transparency applied to the texture on draw
+       # Transparency applied to the model on draw
+       #
+       # This value may be ignored by some materials.
+       # Non-opaque values may result in artifacts as there is no specialized
+       # support for transparent models and the depth buffer.
        var alpha = 1.0 is writable
 end
 
-# Entire 3D model defined by its `leaves`, an association of `Mesh` to `Material`
+# 3D model composed of `Mesh` and `Material`, loaded from the assets folder by default
+#
+# Instances can be created at any time and must be loaded after or at the end of `on_create`.
+# If loading fails, the model is replaced by `placeholder_model`.
+#
+# ~~~
+# import gamnit::depth
+#
+# var model = new Model("path/in/assets.obj")
+# model.load
+# ~~~
+#
+# The most simple model is `LeafModel`, composed of a single `Mesh` and `Material`.
+# It can be easily created programmatically to display simple geometries.
+# Whereas `CompositeModel` is composed of one or many `LeafModel` and is usually
+# loaded from the assets folder as a `ModelAsset`.
+# Instances of `ModelAsset` must be in the format OBJ and MAT,
+# and their texture in PNG or JPG.
 abstract class Model
 
        # Load this model in memory
@@ -56,7 +119,7 @@ class CompositeModel
        redef var leaves = new Array[LeafModel]
 end
 
-# Single model with a `mesh` and `material`
+# Basic model with a single `mesh` and `material`
 #
 # Only leaves are actually drawn by the `material`.
 class LeafModel
@@ -71,10 +134,28 @@ class LeafModel
        redef var leaves = [self]
 end
 
-# Material for a model or how to draw the model
+# Material for models, or how to draw the model
+#
+# To create a simple basic blueish material, use `new Material`.
+#
+# Each class of material is associated to a `GLProgram` and its GPU shaders.
+# The simple material `SmoothMaterial` allows to set an ambient, diffuse and specular color.
+# To which `TextureMaterial` adds three textures, for each kind of light.
+# The `NormalsMaterial` may be useful for debugging, it show the orientation of
+# the normal vectors as colors.
+#
+# ~~~
+# import gamnit::depth
+#
+# var blueish_material = new Material
+# var redish_material = new SmoothMaterial([0.3, 0.0, 0.0],
+#                                          [0.6, 0.0, 0.0],
+#                                          [1.0, 1.0, 1.0])
+# var normals_material = new NormalsMaterial
+# ~~~
 abstract class Material
 
-       # Draw `actor`
+       # Draw a `model` from `actor`
        #
        # This method should be refined by subclasses as the default implementation is a no-op.
        #
@@ -85,6 +166,17 @@ abstract class Material
 end
 
 # Mesh with all geometry data
+#
+# May be created via `Plane`, `Cube` or `UVSphere`,
+# or loaded from the assets folder indirectly with a `Model`.
+#
+# ~~~
+# import gamnit::depth
+#
+# var plane = new Plane
+# var cube = new Cube
+# var sphere = new UVSphere(1.0, 32, 16)
+# ~~~
 class Mesh
 
        # Vertices coordinates
@@ -105,58 +197,6 @@ class Mesh
 
        # `GLDrawMode` used to display this mesh, defaults to `gl_TRIANGLES`
        fun draw_mode: GLDrawMode do return gl_TRIANGLES
-
-       # Create an UV sphere of `radius` with `n_meridians` and `n_parallels`
-       init uv_sphere(radius: Float, n_meridians, n_parallels: Int)
-       do
-               var w = n_meridians
-               var h = n_parallels
-
-               var vertices = new Array[Float].with_capacity(w*h*3)
-               self.vertices = vertices
-
-               var texture_coords = new Array[Float].with_capacity(w*h*2)
-               self.texture_coords = texture_coords
-
-               var normals = new Array[Float].with_capacity(w*h*3)
-               self.normals = normals
-
-               # Build vertices
-               for m in [0..w[ do
-                       for p in [0..h[ do
-                               var u = m.to_f * 2.0 * pi / (w-1).to_f
-                               var v = p.to_f * pi / (h-1).to_f
-
-                               vertices.add radius * u.cos * v.sin
-                               vertices.add radius * v.cos
-                               vertices.add radius * u.sin * v.sin
-
-                               texture_coords.add (1.0 - m.to_f/(w-1).to_f)
-                               texture_coords.add(p.to_f/(h-1).to_f)
-
-                               normals.add u.cos * v.sin
-                               normals.add v.cos
-                               normals.add u.sin * v.sin
-                       end
-               end
-
-               # Build faces
-               var indices = new Array[Int].with_capacity((w-1)*(h-1)*6)
-               self.indices = indices
-               for m in [0..w-1[ do
-                       for p in [0..h-1[ do
-                               var a = m*h + p
-
-                               indices.add a
-                               indices.add a+h
-                               indices.add a+1
-
-                               indices.add a+h
-                               indices.add a+h+1
-                               indices.add a+1
-                       end
-               end
-       end
 end
 
 # Source of light