samples/3D: (#992) Added acquired input / 3D demo 'walkAround'
[sdk] / samples / 3D / walkAround / walkAround.ec
1 import "ecere"
2
3 class WalkAroundApp : GuiApplication
4 {
5    driver = "OpenGL";
6    // driver = "Direct3D";
7    timerResolution = 60;
8    appName = "3D Walkaround Sample";
9    Time lastTime;
10    bool wasProcessingMoves;
11
12    bool Cycle(bool idle)
13    {
14       bool processMoves = form && form.acquiredInput;
15       if(processMoves)
16       {
17          Time time = GetTime(), diffTime;
18          int xd = 0, yd = 0;
19          MouseButtons buttons;
20          if(wasProcessingMoves != processMoves)
21          {
22             lastTime = time;
23             GetMouseState(&buttons, &xd, &yd);
24          }
25          diffTime = time - lastTime;
26          lastTime = time;
27          GetMouseState(&buttons, &xd, &yd);
28          if(form)
29          {
30             bool updateCamera = false;
31             float speed = 50;
32             float cameraSpeed = 0.5;
33             Vector3D movement { };
34             Euler orientation = camera.orientation;
35             Euler euler = orientation;
36             euler.roll = 0;
37             orientation.roll = 0;
38
39             euler.yaw -= xd * cameraSpeed;
40             euler.pitch -= yd * cameraSpeed;
41             if(GetKeyState(right)) euler.yaw   -= diffTime * cameraSpeed;
42             if(GetKeyState(left))  euler.yaw   += diffTime * cameraSpeed;
43             if(GetKeyState(up))    euler.pitch -= diffTime * cameraSpeed;
44             if(GetKeyState(down))  euler.pitch += diffTime * cameraSpeed;
45             euler.pitch = Min(Max(euler.pitch, Degrees { -89.9 }), Degrees { 89.9 });
46             if(orientation.yaw != euler.yaw || orientation.pitch != euler.pitch || orientation.roll != euler.roll)
47             {
48                camera.orientation = euler;
49                updateCamera = true;
50             }
51
52             if(GetKeyState(e))                  movement.y -= diffTime * speed;
53             if(GetKeyState(c))                  movement.y += diffTime * speed;
54             if(GetKeyState(s) || buttons.right) movement.z -= diffTime * speed;
55             if(GetKeyState(w) || buttons.left)  movement.z += diffTime * speed;
56             if(GetKeyState(a))                  movement.x -= diffTime * speed;
57             if(GetKeyState(d))                  movement.x += diffTime * speed;
58             if(movement.x || movement.y || movement.z)
59             {
60                camera.Move(movement);
61                updateCamera = true;
62             }
63
64             if(updateCamera)
65             {
66                camera.Update();
67                form.Update(null);
68             }
69          }
70       }
71       wasProcessingMoves = processMoves;
72       return true;
73    }
74 };
75
76 define app = (WalkAroundApp)__thisModule.application;
77
78 Camera camera
79 {
80    fixed,
81    position = Vector3D { 0, -100, -200 },
82    orientation = Euler { 0, 0, 0 },
83    fov = 70;
84 };
85
86 Light light
87 {
88    diffuse = white;
89    specular = white;
90    orientation = Euler { 0, 70 };
91 };
92
93 define width = 10;
94 define height = 10;
95 define tileSize = 30;
96 define gap = 5;
97
98 class WalkAroundForm : Window
99 {
100    caption = "3D Walkaround Sample";
101    background = black;
102
103    borderStyle = sizable;
104    hasMaximize = true;
105    hasMinimize = true;
106    hasClose = true;
107    clientSize = { 632, 438 };
108
109    Array<Material> materials { size = 8 };
110    Array<int> map { size = width * height };
111    Array<int> elv { size = width * height };
112    Array<Color> colors { [ black, red, green, blue, cyan, magenta, white, gray, orange, yellow, brown, aquamarine, goldenrod ] };
113    Array<Cube> cubes { };
114
115    Material sideMat { opacity = 0.5f, diffuse = teal, ambient = teal, flags = { doubleSided = true, translucent = true } };
116    Material dolphin1Mat { opacity = 1.0f, diffuse = skyBlue, ambient = skyBlue };
117    Material dolphin2Mat { opacity = 1.0f, diffuse = lightGray, ambient = lightGray };
118    Object dolphinModel { };
119    Object dolphin1 { };
120    Object dolphin2 { };
121    Cube cube { };
122    Array<Bitmap> textures { };
123    bool acquiredInput;
124
125    WalkAroundForm()
126    {
127       RandomSeed(1234);
128       GenerateMap();
129    }
130
131    void GenerateMap()
132    {
133       int i;
134       for(i = 0; i < map.count; i++)
135       {
136          int num = map[i] = GetRandom(0, 7);
137          elv[i] = GetRandom(1, 100);
138       }
139    }
140
141    bool OnLoadGraphics()
142    {
143       Bitmap textureFile { };
144       int i, x, y;
145       PrimitiveGroup group;
146
147       dolphinModel.Load(":dolphin.3ds", null, displaySystem);
148       dolphinModel.Merge(displaySystem);
149       dolphinModel.mesh.ApplyMaterial(null);
150
151       dolphin1.Duplicate(dolphinModel);
152       dolphin1.transform.position = { -20, -50, 10 };
153       dolphin1.transform.scaling = { 0.2, 0.2, 0.2 };
154       dolphin1.UpdateTransform();
155       dolphin1.material = dolphin1Mat;
156
157       dolphin2.Duplicate(dolphinModel);
158       dolphin2.transform.position = { 60, -30, -5 };
159       dolphin2.transform.scaling = { 0.2, 0.2, 0.2 };
160       dolphin2.UpdateTransform();
161       dolphin2.material = dolphin2Mat;
162
163       if(textureFile.Load(":texture1.pcx", null, null))
164       {
165          int count = 8;
166          int height = textureFile.height / count;
167          for(i = 0; i < count; i++)
168          {
169             Bitmap tex { };
170             tex.Allocate(null, textureFile.width, height, 0, pixelFormat888, false);
171             tex.Grab(textureFile, 0, i * height);
172             tex.MakeMipMaps(displaySystem);
173             textures.Add(tex);
174
175             materials[i] =
176             {
177                ambient = white;
178                diffuse = white;
179                baseMap = tex;
180                opacity = 1.0f;
181             };
182          }
183       }
184       delete textureFile;
185
186       for(y = 0; y < height; y++)
187       {
188          for(x = 0; x < width; x++)
189          {
190             int ix = y * width + x;
191             int num = map[ix];
192             int xs = -((tileSize+gap) * width) / 2;
193             int ys = -((tileSize+gap) * height) / 2;
194             float h = elv[ix];
195             Cube cube { };
196
197             PrimitiveGroup face;
198             cubes.Add(cube);
199             cube.Create(displaySystem);
200             cube.flags.translucent = true;
201
202             for(face = cube.mesh.groups.first; face; face = face.next)
203                face.material = face.prev ? sideMat : materials[num];
204             cube.mesh.ApplyTranslucency(cube);
205             cube.transform.position = { x * (tileSize + gap), -h/2, y * (tileSize + gap) };
206             cube.transform.scaling = { tileSize, h, tileSize };
207             cube.transform.orientation = Euler { 0, 0, 0 };
208             cube.UpdateTransform();
209          }
210       }
211       return true;
212    }
213
214    void OnUnloadGraphics()
215    {
216       for(c : cubes)
217          c.Free(displaySystem);
218       dolphinModel.Free(displaySystem);
219       dolphin1.Free(displaySystem);
220       dolphin2.Free(displaySystem);
221       cubes.Free();
222    }
223
224    void OnResize(int w, int h)
225    {
226       camera.Setup(w, h, null);
227       camera.Update();
228    }
229
230    void OnRedraw(Surface surface)
231    {
232       surface.Clear(depthBuffer);
233       display.SetCamera(surface, camera);
234       display.SetLight(0, light);
235       display.ambient = Color { 100, 100, 100 };
236
237       for(c : cubes)
238          display.DrawObject(c);
239
240       display.DrawObject(dolphin1);
241       display.DrawObject(dolphin2);
242
243       display.SetCamera(surface, null);
244
245       if(!acquiredInput)
246       {
247          surface.foreground = white;
248          surface.WriteTextf(50, 50, "Press I to acquire mouse Input, F for Full screen.");
249       }
250    }
251
252    bool OnKeyHit(Key key, unichar ch)
253    {
254       switch(key)
255       {
256          case escape: Destroy(0); break;
257          case wheelDown:
258             camera.Move({ 0, -4, 0 });
259             camera.Update();
260             Update(null);
261             break;
262          case wheelUp:
263             camera.Move({ 0, 4, 0 });
264             camera.Update();
265             Update(null);
266             break;
267          case i:
268          {
269             acquiredInput ^= true;
270             AcquireInput(acquiredInput);
271             Update(null);
272             break;
273          }
274          case f:
275          {
276             bool fullScreen = !app.fullScreen;
277             AcquireInput(false);
278             if(fullScreen)
279             {
280                anchor = { 0, 0, 0, 0 };
281                borderStyle = none;
282             }
283             else
284             {
285                borderStyle = sizable;
286                nativeDecorations = true;
287                hasMaximize = true;
288                hasMinimize = true;
289                hasClose = true;
290                state = normal;
291                anchor = { };
292                clientSize = { 632, 438 };
293                position = position;
294             }
295             app.fullScreen = fullScreen;
296             AcquireInput(acquiredInput);
297             break;
298          }
299       }
300       return true;
301    }
302 }
303
304 WalkAroundForm form {};