128b955052a127f50323add8c1d1107942dc08a6
[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 && form.active)
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 { };
110    Array<int> map { size = width * height };
111    Array<int> elv { size = width * height };
112    Array<Cube> cubes { };
113
114    BitmapResource spotTex { ":spot_tex.png", window = this };
115    Material sideMat { opacity = 0.5f, diffuse = teal, ambient = teal, flags = { doubleSided = true, translucent = true } };
116    Material cow1Mat { opacity = 1.0f, diffuse = white, ambient = white };
117    Material cow2Mat { opacity = 1.0f, power = 20, diffuse = goldenrod, ambient = goldenrod, specular = goldenrod };
118    Material cow3Mat { opacity = 1.0f, power = 20, diffuse = goldenrod, ambient = goldenrod, specular = goldenrod };
119    Object cowModel { };
120    Object cow1 { };
121    Object cow2 { };
122    Object cow3 { };
123    Cube cube { };
124    Array<Bitmap> textures { };
125    bool acquiredInput;
126
127    WalkAroundForm()
128    {
129       RandomSeed(1234);
130       GenerateMap();
131    }
132
133    void GenerateMap()
134    {
135       int i;
136       for(i = 0; i < map.count; i++)
137       {
138          int num = map[i] = GetRandom(0, 7);
139          elv[i] = GetRandom(1, 100);
140       }
141    }
142
143    bool OnLoadGraphics()
144    {
145       Bitmap textureFile { };
146       int i, x, y;
147       PrimitiveGroup group;
148
149       cowModel.Load(":cow.3DS", null, displaySystem);
150       cowModel.Merge(displaySystem);
151       cowModel.mesh.ApplyMaterial(null);
152
153       cow1.Duplicate(cowModel);
154       cow1.transform.position = { -20, -50, 10 };
155       cow1.transform.scaling = { 20, 20, 20 };
156       cow1.transform.orientation = Euler { yaw = 135 };
157       cow1.UpdateTransform();
158       cow1.material = cow1Mat;
159       cow1Mat.baseMap = spotTex.bitmap;
160
161       cow2.Duplicate(cowModel);
162       cow2.transform.position = { 60, -42, -5 };
163       cow2.transform.scaling = { 20, 20, 20 };
164       cow2.transform.orientation = Euler { yaw = 225 };
165       cow2.UpdateTransform();
166       cow2.material = cow2Mat;
167
168       cow3.Duplicate(cowModel);
169       cow3.transform.position = { 120, -89, 13 };
170       cow3.transform.scaling = { 20, 20, 20 };
171       cow3.transform.orientation = Euler { yaw = 185 };
172       cow3.UpdateTransform();
173       cow3.material = cow3Mat;
174       cow3Mat.baseMap = spotTex.bitmap;
175
176       materials.size = 8;
177       if(textureFile.Load(":texture1.pcx", null, null))
178       {
179          int count = 8;
180          int height = textureFile.height / count;
181          for(i = 0; i < count; i++)
182          {
183             Bitmap tex { };
184             tex.Allocate(null, textureFile.width, height, 0, pixelFormat888, false);
185             tex.Grab(textureFile, 0, i * height);
186             tex.MakeMipMaps(displaySystem);
187             textures.Add(tex);
188
189             materials[i] =
190             {
191                ambient = white;
192                diffuse = white;
193                baseMap = tex;
194                opacity = 1.0f;
195             };
196          }
197       }
198       delete textureFile;
199
200       for(y = 0; y < height; y++)
201       {
202          for(x = 0; x < width; x++)
203          {
204             int ix = y * width + x;
205             int num = map[ix];
206             int xs = -((tileSize+gap) * width) / 2;
207             int ys = -((tileSize+gap) * height) / 2;
208             float h = elv[ix];
209             Cube cube { };
210
211             PrimitiveGroup face;
212             cubes.Add(cube);
213             cube.Create(displaySystem);
214             cube.flags.translucent = true;
215
216             for(face = cube.mesh.groups.first; face; face = face.next)
217                face.material = face.prev ? sideMat : materials[num];
218             cube.mesh.ApplyTranslucency(cube);
219             cube.transform.position = { x * (tileSize + gap), -h/2, y * (tileSize + gap) };
220             cube.transform.scaling = { tileSize, h, tileSize };
221             cube.transform.orientation = Euler { 0, 0, 0 };
222             cube.UpdateTransform();
223          }
224       }
225       return true;
226    }
227
228    void OnUnloadGraphics()
229    {
230       materials.Free();
231       textures.Free();
232
233       for(c : cubes)
234          c.Free(displaySystem);
235       cowModel.Free(displaySystem);
236       cow1.Free(displaySystem);
237       cow2.Free(displaySystem);
238       cow3.Free(displaySystem);
239       cubes.Free();
240    }
241
242    void OnResize(int w, int h)
243    {
244       camera.Setup(w, h, null);
245       camera.Update();
246    }
247
248    void OnRedraw(Surface surface)
249    {
250       surface.Clear(depthBuffer);
251       display.SetCamera(surface, camera);
252       display.SetLight(0, light);
253       display.ambient = Color { 100, 100, 100 };
254
255       for(c : cubes)
256          display.DrawObject(c);
257
258       display.DrawObject(cow1);
259       display.DrawObject(cow2);
260       display.DrawObject(cow3);
261
262       display.SetCamera(surface, null);
263
264       if(!acquiredInput)
265       {
266          surface.foreground = white;
267          surface.WriteTextf(50, 50, "Press I to acquire mouse Input, F for Full screen.");
268       }
269    }
270
271    bool OnKeyHit(Key key, unichar ch)
272    {
273       switch(key)
274       {
275          case escape: Destroy(0); break;
276          case wheelDown:
277             camera.Move({ 0, -4, 0 });
278             camera.Update();
279             Update(null);
280             break;
281          case wheelUp:
282             camera.Move({ 0, 4, 0 });
283             camera.Update();
284             Update(null);
285             break;
286          case i:
287          {
288             acquiredInput ^= true;
289             AcquireInput(acquiredInput);
290             Update(null);
291             break;
292          }
293          case f:
294          {
295             bool fullScreen = !app.fullScreen;
296             AcquireInput(false);
297             if(fullScreen)
298             {
299                anchor = { 0, 0, 0, 0 };
300                borderStyle = none;
301             }
302             else
303             {
304                borderStyle = sizable;
305                nativeDecorations = true;
306                hasMaximize = true;
307                hasMinimize = true;
308                hasClose = true;
309                state = normal;
310                anchor = { };
311                clientSize = { 632, 438 };
312             }
313             app.fullScreen = fullScreen;
314             if(fullScreen)
315                ; // app.resolution = res640x480;
316             else
317                position = position;
318
319             AcquireInput(acquiredInput);
320             break;
321          }
322       }
323       return true;
324    }
325 }
326
327 WalkAroundForm form {};