d61b3fe61e4c71ee5accdd85ed8d6c7f56707b2d
[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 import globe
28
29 redef class App
30
31 # All available models
32 var models: Array[Model] = [
33 new LeafModel(new Cube, new SmoothMaterial.default),
34 new LeafModel(new Mesh.uv_sphere(4.0, 32, 16), new SmoothMaterial.default),
35 new LeafModel(new Mesh.uv_sphere(4.0, 32, 16), new NormalsMaterial),
36 new Model("models/Tree_01.obj"),
37 new Model("models/Oak_Fall_01.obj"),
38 new Model("models/Quandtum_BA-2_v1_1.obj"),
39 new GlobeModel]
40
41 # Index of the current model in `models`
42 var model_index = 0
43
44 # Texture "Previous model"
45 var ui_prev = new Texture("ui/prev.png")
46
47 # Texture "Next model"
48 var ui_next = new Texture("ui/next.png")
49
50 redef fun on_create
51 do
52 super
53
54 # Show splash screen
55 var logo = new Texture("splash.png")
56 show_splash_screen logo
57
58 # Load all models passed as command line argument
59 for arg in args.to_a.reversed do
60 # Force an absolute path, this only works on desktop, but so does command args
61 arg = getcwd / arg
62
63 var model = new Model(arg)
64 models.unshift model
65 end
66
67 world_camera.near = 0.1
68 world_camera.far = 100.0
69
70 for model in models do model.load
71 for texture in asset_textures_by_name.values do texture.load
72
73 # Display the first model
74 model = models[model_index]
75
76 # Setup UI
77 # Use 800 px in height as screen reference
78 ui_camera.reset_height 800.0
79
80 var prev_sprite = new Sprite(ui_prev,
81 ui_camera.bottom_left.offset(200, 40, 0))
82 prev_sprite.scale = 0.5
83 ui_sprites.add prev_sprite
84
85 var next_sprite = new Sprite(ui_next,
86 ui_camera.bottom_right.offset(-165, 40, 0))
87 next_sprite.scale = 0.5
88 ui_sprites.add next_sprite
89 end
90
91 # Set the currently displayed model
92 fun model=(model: Model)
93 do
94 if model isa ModelAsset then print "Model: {model.path}"
95
96 var actor = new Actor(model, new Point3d[Float](0.0, 0.0, 0.0))
97
98 # Align on Y only
99 actor.center.y -= model.center.y
100
101 # Fit in viewport
102 var height = model.dimensions.x
103 height = height.max(model.dimensions.y)
104 height = height.max(model.dimensions.z)
105 world_camera.reset_height(height * 1.5)
106
107 actors.clear
108 actors.add actor
109 end
110
111 # Cycle to the next or previous model, changing the index by `d`
112 fun cycle_model(d: Int)
113 do
114 model_index = (model_index + d + models.length) % models.length
115 model = models[model_index]
116 end
117
118 redef fun accept_event(event)
119 do
120 var display = display
121 if display == null then return super
122
123 if event isa QuitEvent then
124 exit 0
125 else if event isa KeyEvent and event.is_down then
126 if event.is_arrow_right then
127 cycle_model 1
128 else if event.is_arrow_left then
129 cycle_model -1
130 end
131 else if event isa PointerEvent and not event.is_move and event.depressed then
132 if event.x.to_i > display.width / 2 then
133 cycle_model 1
134 else cycle_model -1
135 end
136
137 return super
138 end
139
140 private var clock = new Clock
141
142 redef fun update(dt)
143 do
144 super
145
146 var t = clock.total.to_f
147
148 # Rotate the model
149 actors.first.rotation = t
150
151 # Move the light source
152 var dist_to_light = 20.0
153 t *= 1.33
154 light.position.x = dist_to_light * t.cos
155 light.position.y = 4.0
156 light.position.z = dist_to_light * t.sin
157 end
158 end