contrib: intro model viewer
[nit.git] / contrib / model_viewer / src / model_viewer.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
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
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
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.
14
15 # Portable game to destroy asteroids
16 module model_viewer is
17 app_name "Model Viewer"
18 app_namespace "org.nitlanguage.model_viewer"
19 app_version(1, 0, git_revision)
20
21 android_manifest_activity """android:screenOrientation="landscape""""
22 android_api_target 15
23 end
24
25 import gamnit::depth
26
27 redef class App
28
29 # All available models
30 var models: Array[Model] = [
31 new LeafModel(new Cube, new SmoothMaterial.default),
32 new LeafModel(new Mesh.uv_sphere(4.0, 32, 16), new SmoothMaterial.default),
33 new LeafModel(new Mesh.uv_sphere(4.0, 32, 16), new NormalsMaterial),
34 new Model("models/Tree_01.obj"),
35 new Model("models/Oak_Fall_01.obj"),
36 new Model("models/Quandtum_BA-2_v1_1.obj")]
37
38 # Index of the current model in `models`
39 var model_index = 0
40
41 # Texture "Previous model"
42 var ui_prev = new Texture("ui/prev.png")
43
44 # Texture "Next model"
45 var ui_next = new Texture("ui/next.png")
46
47 redef fun on_create
48 do
49 super
50
51 if args.length > 0 then
52 # Load a model passed as the first command line argument
53 var model_path = args.first
54 if model_path.has_prefix("assets/") then model_path = model_path.substring_from(7)
55
56 var model = new Model(model_path)
57 models.unshift model
58 end
59
60 world_camera.near = 1.0
61 world_camera.far = 1000.0
62
63 for model in models do model.load
64 for texture in asset_textures_by_name.values do texture.load
65
66 # Display the first model
67 model = models[model_index]
68
69 # Setup UI
70 # Use 800 px in height as screen reference
71 ui_camera.reset_height 800.0
72
73 var prev_sprite = new Sprite(ui_prev,
74 ui_camera.bottom_left.offset(200, -40, 0))
75 prev_sprite.scale = 0.5
76 ui_sprites.add prev_sprite
77
78 var next_sprite = new Sprite(ui_next,
79 ui_camera.bottom_right.offset(-165, -40, 0))
80 next_sprite.scale = 0.5
81 ui_sprites.add next_sprite
82 end
83
84 # Set the currently displayed model
85 fun model=(model: Model)
86 do
87 var actor = new Actor(model, new Point3d[Float](0.0, 0.0, 0.0))
88
89 model = model.leaves.first
90 actor.center.x -= model.mesh.center.x
91 actor.center.y += model.mesh.center.y
92 actor.center.z -= model.mesh.center.z
93
94 var height = model.mesh.dimensions.y
95 world_camera.reset_height(height * 4.0)
96
97 actors.clear
98 actors.add actor
99 end
100
101 # Cycle to the next or previous model, changing the index by `d`
102 fun cycle_model(d: Int)
103 do
104 model_index = (model_index + d + models.length) % models.length
105 model = models[model_index]
106 end
107
108 redef fun accept_event(event)
109 do
110 var display = display
111 if display == null then return super
112
113 if event isa QuitEvent then
114 exit 0
115 else if event isa KeyEvent and event.is_down then
116 if event.is_arrow_right then
117 cycle_model 1
118 else if event.is_arrow_left then
119 cycle_model -1
120 end
121 else if event isa PointerEvent and event.pressed then
122 if event.x.to_i > display.width / 2 then
123 cycle_model 1
124 else cycle_model -1
125 end
126
127 return super
128 end
129
130 private var clock = new Clock
131
132 redef fun update(dt)
133 do
134 super
135
136 var t = clock.total.to_f
137
138 # Rotate the model
139 actors.first.rotation = t
140
141 # Move the light source
142 var dist_to_light = 20.0
143 t *= 1.33
144 light.position.x = dist_to_light * t.cos
145 light.position.y = 4.0
146 light.position.z = dist_to_light * t.sin
147 end
148 end