1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
15 # Base entities of the depth 3D game framework
18 intrude import gamnit
::flat
20 # Visible 3D entity in the game world
22 # Similar to `gamnit::Sprite` which is in 2D.
24 # Each actor associates a `model` to the position `center`.
25 # The appearance is modified by `rotation`, `scale` and `alpha`,
26 # as well as the attributes of `model` itself.
29 # import gamnit::depth
31 # # Load model from the assets folder
32 # var model = new Model("path/in/assets.obj")
34 # # Create and configure an actor
35 # var actor = new Actor(model, new Point3d[Float](0.0, 0.0, 0.0))
38 # # Add to the visible game world
39 # app.actors.add actor
43 # Model used to draw this actor
46 # Position of this sprite in world coordinates
47 var center
: Point3d[Float] is writable
49 # Rotation on the Z axis
50 var rotation
= 0.0 is writable
52 # Scale applied to the model
53 var scale
= 1.0 is writable
55 # Transparency applied to the model on draw
57 # This value may be ignored by some materials.
58 # Non-opaque values may result in artifacts as there is no specialized
59 # support for transparent models and the depth buffer.
60 var alpha
= 1.0 is writable
63 # 3D model composed of `Mesh` and `Material`, loaded from the assets folder by default
65 # Instances can be created at any time and must be loaded after or at the end of `on_create`.
66 # If loading fails, the model is replaced by `placeholder_model`.
69 # import gamnit::depth
71 # var model = new Model("path/in/assets.obj")
75 # The most simple model is `LeafModel`, composed of a single `Mesh` and `Material`.
76 # It can be easily created programmatically to display simple geometries.
77 # Whereas `CompositeModel` is composed of one or many `LeafModel` and is usually
78 # loaded from the assets folder as a `ModelAsset`.
79 # Instances of `ModelAsset` must be in the format OBJ and MAT,
80 # and their texture in PNG or JPG.
83 # Load this model in memory
86 # All `LeafModel` composing this model
88 # Usually, there is one `LeafModel` per material.
89 # At each frame, each material is asked to draw all the live `LeafModel` instaces.
90 fun leaves
: Array[LeafModel] is abstract
93 # Model composed of one or many other `LeafModel`
97 redef var leaves
= new Array[LeafModel]
100 # Basic model with a single `mesh` and `material`
102 # Only leaves are actually drawn by the `material`.
106 # Mesh forming this model
109 # Material applied on this model
110 var material
: Material
112 redef var leaves
= [self]
115 # Material for models, or how to draw the model
117 # To create a simple basic blueish material, use `new Material`.
119 # Each class of material is associated to a `GLProgram` and its GPU shaders.
120 # The simple material `SmoothMaterial` allows to set an ambient, diffuse and specular color.
121 # To which `TextureMaterial` adds three textures, for each kind of light.
122 # The `NormalsMaterial` may be useful for debugging, it show the orientation of
123 # the normal vectors as colors.
126 # import gamnit::depth
128 # var blueish_material = new Material
129 # var redish_material = new SmoothMaterial([0.3, 0.0, 0.0],
132 # var normals_material = new NormalsMaterial
134 abstract class Material
136 # Draw a `model` from `actor`
138 # This method should be refined by subclasses as the default implementation is a no-op.
140 # This method is called on many materials for many `actor` and `model` at each frame.
141 # It is expected to use a `GLProgram` and call an equivalent to `glDrawArrays`.
142 # However, it should not call `glClear` nor `GamnitDisplay::flip`.
143 fun draw
(actor
: Actor, model
: LeafModel) do end
146 # Mesh with all geometry data
148 # May be created via `Plane`, `Cube` or `UVSphere`,
149 # or loaded from the assets folder indirectly with a `Model`.
152 # import gamnit::depth
154 # var plane = new Plane
155 # var cube = new Cube
156 # var sphere = new UVSphere(1.0, 32, 16)
160 # Vertices coordinates
161 var vertices
= new Array[Float] is lazy
, writable
163 # Indices to draw triangles with `glDrawElements`
165 # If `not_empty`, use `glDrawElements`, otherwise use `glDrawArrays`.
166 var indices
= new Array[Int] is lazy
, writable
168 private var indices_c
= new CUInt16Array.from
(indices
) is lazy
, writable
170 # Normals on each vertex
171 var normals
= new Array[Float] is lazy
, writable
173 # Coordinates on the texture per vertex
174 var texture_coords
= new Array[Float] is lazy
, writable
176 # `GLDrawMode` used to display this mesh, defaults to `gl_TRIANGLES`
177 fun draw_mode
: GLDrawMode do return gl_TRIANGLES
182 # Instances of this class define a light source position and type.
185 # TODO point light, spotlight, directional light, etc.
187 # Center of this light source in world coordinates
188 var position
= new Point3d[Float](0.0, 1000.0, 0.0)
193 # Live actors to be drawn on screen
194 var actors
= new Array[Actor]
196 # Single light of the scene
197 var light
= new Light
199 # TODO move `actors & light` to a scene object
200 # TODO support more than 1 light