1 /****************************************************************************
2 Ecere 3D Engine Demonstration
4 Copyright (c) 2001-2010 Jerome Jacovella-St-Louis
8 ****************************************************************************/
13 define BACKGROUND = white;
16 // --- Terrain Data Loading ---
17 static Elevation heightMap[1025 * 1025];
19 #define ALTITUDE_FACTOR 1
20 #define ALTITUDE_OFFSET 0 // -5000
22 #define EARTH_RADIUS 6367000
24 #define CELL_LAT_POINTS 1201
25 #define CELL_LON_POINTS 1201
27 #define RESOLUTION_LAT (EARTH_RADIUS * ((Pi / 180) / (CELL_LAT_POINTS - 1)))
28 #define RESOLUTION_LON(LATITUDE) (EARTH_RADIUS * ((float)sin(LATITUDE) * ((Pi / 180) / (CELL_LON_POINTS - 1))))
37 static Array<ElevationColor> colorMap
39 { 0, Color { 0, 0, 0 } },
40 { 1100, Color { 28, 24, 101 } },
41 { 1200, Color { 17, 138, 150 } },
42 { 1300, Color { 0,75,0 } },
43 { 1500, Color { 244,244,144 } },
44 { 2000, Color { 79, 45, 8 } },
45 { 2300, Color { 129, 65, 58 } },
46 { 2600, Color { 185, 185, 185 } },
47 { 3000, Color { 255, 255, 255 } }
50 static void OutputTexture(String fileName)
53 if(bitmap.Allocate(null, 1025, 1025, 0, pixelFormat888, false))
55 ColorAlpha * picture = (ColorAlpha *)bitmap.picture;
58 Array<ColorAlpha> colorTable { size = 65536 };
60 ElevationColor * curKey = colorMap.array, * nextKey = colorMap.array;
61 int keyNum = 0, nextKeyNum = 0;
63 for(altitude = -32768; altitude<32768; altitude++)
67 while(altitude > nextKey->altitude)
69 curKey = nextKey; keyNum = nextKeyNum;
70 if(keyNum < colorMap.count - 1)
73 nextKeyNum = keyNum + 1;
79 if(nextKey->altitude != curKey->altitude)
81 float scale = (float) (altitude - curKey->altitude) / (nextKey->altitude - curKey->altitude);
82 Color cColor = curKey->color, nColor = nextKey->color;
83 int cr = cColor.r, cg = cColor.g, cb = cColor.b;
84 int nr = nColor.r, ng = nColor.g, nb = nColor.b;
85 int r = (int)(cr + (nr - cr) * scale);
86 int g = (int)(cg + (ng - cg) * scale);
87 int b = (int)(cb + (nb - cb) * scale);
88 r = Max(Min(r, 255),0);
89 g = Max(Min(g, 255),0);
90 b = Max(Min(b, 255),0);
91 color = { (byte)r, (byte)g, (byte)b };
94 color = curKey->color;
95 colorTable[altitude + 32768] = { 255, color };
98 for(y = 0; y < bitmap.height; y++)
99 for(x = 0; x < bitmap.width; x++)
100 picture[y * bitmap.width + x] = colorTable[heightMap[y * 1025 + x] + 32768];
103 bitmap.Save(fileName, null, null);
109 static bool LoadTerrain(Terrain terrain, char * fileName, Angle lat)
112 File f = FileOpen(fileName, read);
116 float resLon = (float)RESOLUTION_LON(lat);
117 for(y = 0; y<1025; y++)
120 byte buffer[1201 * 2];
121 if(f.Read(buffer, sizeof(uint16), 1201) < 1201)
123 for(x = 0; x<1025; x++)
125 unsigned char b0 = buffer[2*x], b1 = buffer[2*x+1];
126 short value = (short)((((int)b0 << 8) | b1) - ((b0 & 0x80) ? 0x10000 : 0));
127 if(value > 20000) value = -32768;
128 heightMap[y*1025+x] = value * ALTITUDE_FACTOR + ALTITUDE_OFFSET;
132 // OutputTexture("res/texture.png");
134 if(terrain.Create(heightMap, 16, 1025, 2, resLon, RESOLUTION_LAT, 512,512))
148 type = attachedQuaternion;
149 position = { 0, 0, -10 };
150 orientation = Euler { 180, 30, 0 };
158 SkyBox sky { size = { 100, 100, 100 }, folder = ":skycube", extension = "jpg" };
163 rotation = 22.5; //Pi/8;
164 helixCurveSegments = 48;
170 desoxyriboseWidth = 40;
171 textureFile = ":texture1.pcx";
176 size = { 100, 100, 100 };
180 Material groundMaterial;
181 TerrainMesh terrainMesh { terrain = terrain };
188 Point lastMousePosition, newMousePosition;
189 bool leftDown, rightDown;
192 borderStyle = sizable;
197 text = "3D Camera & Terrain Demo";
202 // Load terrain from SRTM data ( 3 arc seconds data from http://www.viewfinderpanoramas.org/ , L12 Cell)
203 LoadTerrain(terrain, ":N45W110.hgt", Degrees { 45 });
206 fogDensity = 0.0001f;
207 detailBias = 400;//1000;
209 //zMax = 100000; //340000;
212 newMousePosition = lastMousePosition = { MAXINT, MAXINT };
224 static bool firstTime = true;
225 double currentTime = GetTime();
226 double diffTime = currentTime - lastTime;
227 lastTime = currentTime;
231 Quaternion orientation = dna.transform.orientation;
232 orientation.RotateYawPitch(Degrees { (float)30*diffTime }, 0);
233 dna.transform.orientation = orientation;
234 dna.UpdateTransform();
237 //light.orientation.RotatePitch(Radians { 0.02f });
240 ((GuiApplication)__thisModule).GetMouseState(&b, &x, &y);
243 if(lastMousePosition.x != MAXINT)
245 x = newMousePosition.x - lastMousePosition.x;
246 y = newMousePosition.y - lastMousePosition.y;
247 lastMousePosition = newMousePosition;
254 if(leftDown) b.left = true;
255 if(rightDown) b.right = true;
260 player.Animate(frame);
262 if(frame == 100) frame = 0;
264 //player.RotateEuler({ Radians { -x / 60.0f }, Radians { -y / 60.0f } }, { pitch = -90 }, { pitch = 90 });
265 //player.RotateEuler({ roll = Radians { x / 60.0f }, pitch = Radians { y / 60.0f } }, null, null);
266 //player.Rotate({ roll = Radians { x / 60.0f }, pitch = Radians { y / 60.0f } });
268 Quaternion a = player.transform.orientation;
269 a.RotateRoll(Radians { x / 60.0f });
270 a.RotatePitch(Radians { y / 60.0f });
271 player.transform.orientation = a;
272 player.UpdateTransform();
276 player.Move({ 0, 0,-(float)diffTime * (camera.type == attachedQuaternion ? 10 : 1) * speed });
278 player.Move({ 0, 0, (float)diffTime * (camera.type == attachedQuaternion ? 10 : 1) * speed });
280 height = (int)-terrain.GetElevation(
281 (float)player.transform.position.x,
282 (float)player.transform.position.z);
284 if((float)player.transform.position.y > height - 100)
286 player.transform.position.y = height - 100.0f;
287 player.UpdateTransform();
291 if(firstTime || x || y || b)
300 terrainMesh.OptimizeMesh(camera, detailBias, zMax);
309 void OnPosition(int x, int y, int w, int h)
311 camera.Setup(w, h, null);
312 camera.Update(); // This wasn't necessary before!
314 terrainMesh.OptimizeMesh(camera, detailBias, zMax);
321 acquiredInput = AcquireInput(true);
325 bool OnMouseOver(int x, int y, Modifiers mods)
327 lastMousePosition = { x, y };
328 newMousePosition = { x, y };
332 bool OnMouseLeave(Modifiers mods)
334 lastMousePosition = { MAXINT, MAXINT };
335 newMousePosition = { MAXINT, MAXINT };
339 bool OnMouseMove(int x, int y, Modifiers mods)
341 newMousePosition = { x, y };
345 bool OnLeftButtonDown(int x, int y, Modifiers mods)
352 bool OnLeftButtonUp(int x, int y, Modifiers mods)
354 if(leftDown && !rightDown)
360 bool OnRightButtonDown(int x, int y, Modifiers mods)
366 bool OnRightButtonUp(int x, int y, Modifiers mods)
368 if(rightDown && !leftDown)
374 bool OnLoadGraphics()
378 light.ambient = { 0.2f, 0.2f, 0.2f };
379 light.diffuse = light.specular = white;
380 light.orientation = { 1,0,0,0 };
381 light.orientation.RotatePitch(30);
383 if(map.Load(":texture.png", null, null))
387 map.Convert(null, pixelFormat888, null);
388 map.SmoothEdges(256);
389 for(c = 0; c < across * across; c++)
392 textures[c].Allocate(null, 256, 256, 0, map.pixelFormat, true);
393 if(map.pixelFormat == pixelFormat8)
394 memcpy(textures[c].palette, map.palette, 256*4);
395 textures[c].Grab(map,
396 (c % across) * textures[c].width,
397 (c / across) * textures[c].height);
398 textures[c].MakeMipMaps(displaySystem);
403 player.Load(":aircraft/aircraft.3DS", null, displaySystem);
405 camera.target = player;
407 dna.Create(displaySystem);
410 dna.transform.position.y = -2200;
411 dna.UpdateTransform();
415 player.transform.position.y = -2200;
416 player.transform.position.x = 1000;
417 player.transform.orientation = Euler { yaw = 230 };
420 /*detail.Load(":detail.pcx", null, displaySystem);
421 displaySystem.AddTexture("DetailTexture", detail);*/
423 sky.InitializeMesh(displaySystem);
424 sky.Create(displaySystem);
426 terrainMesh.CreateMesh(terrain, 8192*16, 1024, 1024, false, false, displaySystem);
427 lastTime = GetTime();
433 void OnUnloadGraphics()
436 for(c = 0; c<16; c++)
438 terrainMesh.FreeMesh();
441 void OnRedraw(Surface surface)
443 surface.SetBackground(BACKGROUND);
445 surface.Clear(depthBuffer);
447 display.SetCamera(surface, camera);
449 display.SetLight(0, light);
450 display.fogColor = BACKGROUND;
451 display.fogDensity = fogDensity;
452 //display.fogDensity = 0.0000000001f;
454 sky.Render(camera, display);
456 if(!filled) display.fillMode = wireframe;
457 terrainMesh.RenderMesh(display, null, textures);
458 if(!filled) display.fillMode = solid;
460 display.DrawObject(dna);
461 display.DrawObject(player);
463 display.SetCamera(surface, null);
465 surface.SetForeground(black);
466 //surface.WriteTextf(10,10, "Detail: %.0f, ZMax: %.02f, FPS: %.02f", detailBias, zMax, frameRate.fps);
471 bool OnKeyDown(Key key, unichar ch)
478 case w: filled = false; break;
479 case f: filled = true; break;
482 acquiredInput = false;
483 GetMousePosition(&lastMousePosition.x, &lastMousePosition.y);
486 acquiredInput = AcquireInput(true);
490 camera.position = camera.cPosition;
491 camera.orientation = camera.cOrientation;
494 /*camera.type = attached;
495 camera.position = { 0, 0, -30 };
498 camera.type = attachedQuaternion;
499 camera.position = { 0, 0, -10 };
500 camera.orientation = Euler { 180, 30, 0 };
504 camera.type = lookAt;
505 camera.position = camera.cPosition; //{ 1000, -3000, 0 };
506 camera.position.z -= 5;
507 camera.orientation = { 1,0,0,0 };
514 bool OnKeyHit(Key key, unichar ch)
516 float detailBias = this.detailBias;
517 float zMax = this.zMax;
520 case pageUp: detailBias++; break;
521 case pageDown: detailBias--; break;
522 case home: zMax *= 0.9f; break;
523 case end: zMax /= 0.9f; break;
524 case keyPadPlus: camera.position.z /= 0.9f; break;
525 case keyPadMinus: camera.position.z *= 0.9f; break;
526 case f7: camera.RotateYaw(-0.02f, 0, 0); break;
527 case f8: camera.RotateYaw(0.02f, 0, 0); break;
528 case f9: camera.RotatePitch(-0.02f, 0, 0); break;
529 case f10:camera.RotatePitch( 0.02f, 0, 0); break;
531 if(this.detailBias != detailBias || this.zMax != zMax)
533 this.detailBias = Max(0, detailBias);
534 this.zMax = Min(zMax, 340000);
536 terrainMesh.OptimizeMesh(camera, this.detailBias, this.zMax);
543 class CameraDemoApp : GuiApplication
546 timerResolution = 60;