PageRenderTime 55ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/samples/3D/orbitWithMouse/orbitWithMouse.ec

https://github.com/thexa4/sdk
C | 1320 lines | 1047 code | 185 blank | 88 comment | 128 complexity | 00359a0cc24bd1c4e1988c59ab93a29b MD5 | raw file
  1. import "ecere"
  2. #include <GL/gl.h>
  3. #define WINDOW_WIDTH 768
  4. #define WINDOW_HEIGHT 480
  5. #define FULLSCREEN
  6. class Window3D : struct
  7. {
  8. Object cube, front, back, side;
  9. Bitmap bitmap;
  10. Material frontMaterial { };
  11. Material sideMaterial { };
  12. Material backMaterial { };
  13. int id;
  14. Degrees position, wantedPosition;
  15. Euler offset;
  16. };
  17. static char * iconFiles[] =
  18. {
  19. ":slidehex-cinema_guide.png",
  20. ":slidehex-jukebox.png",
  21. ":slidehex-net_radio.png",
  22. ":slidehex-photo_album.png",
  23. ":slidehex-search_guide.png",
  24. ":slidehex-settings.png",
  25. ":slidehex-shopping.png",
  26. ":slidehex-tv_guide.png",
  27. ":slidehex-website.png"
  28. };
  29. #define NUM_ICONS (sizeof(iconFiles)/sizeof(char *))
  30. // #define DOCK_HEIGHT 500
  31. #define DOCK_HEIGHT 400
  32. #define FULL_SWITCH ((int)dock.iconBitmaps[0].width)
  33. #define SMALL_SCALE 0.8f
  34. #define SWITCH_SPEED 700
  35. #define DOCK_TIMER 1
  36. #define SLIDING_SPEED 0.5
  37. #define SWITCHING_SPEED 0.5
  38. #define ENTERING_SPEED 0.5
  39. #define ORBIT_SPEED Degrees { 10 }
  40. #define ORBIT_HEIGHT 1000
  41. // #define ORBIT_HEIGHT 500
  42. #define NUM_WINDOWS 6
  43. typedef struct
  44. {
  45. Bitmap iconBitmaps[NUM_ICONS];
  46. int currentIcon;
  47. float speed, position;
  48. Timer timer;
  49. Seconds lastTime;
  50. } Dock;
  51. static Seconds lastTime;
  52. #define THICKNESS 20
  53. static bool CreateBack(Mesh mesh, int width, int height, int depth, DisplaySystem displaySystem)
  54. {
  55. bool result = false;
  56. if(mesh)
  57. {
  58. if(mesh.Allocate(MeshFeatures { vertices = true, texCoords1 = true }, 24, displaySystem))
  59. {
  60. Vector3Df vertices[24] =
  61. {
  62. { -(float)width/2,-(float)height/2,-(float)depth/2 },
  63. { (float)width/2,-(float)height/2,-(float)depth/2 },
  64. { (float)width/2, (float)height/2,-(float)depth/2 },
  65. { -(float)width/2, (float)height/2,-(float)depth/2 },
  66. { -(float)width/2,-(float)height/2, (float)depth/2 },
  67. { (float)width/2,-(float)height/2, (float)depth/2 },
  68. { (float)width/2, (float)height/2, (float)depth/2 },
  69. { -(float)width/2, (float)height/2, (float)depth/2 },
  70. { -(float)width/2,-(float)height/2,-(float)depth/2 },
  71. { (float)width/2,-(float)height/2,-(float)depth/2 },
  72. { (float)width/2, (float)height/2,-(float)depth/2 },
  73. { -(float)width/2, (float)height/2,-(float)depth/2 },
  74. { -(float)width/2,-(float)height/2, (float)depth/2 },
  75. { (float)width/2,-(float)height/2, (float)depth/2 },
  76. { (float)width/2, (float)height/2, (float)depth/2 },
  77. { -(float)width/2, (float)height/2, (float)depth/2 },
  78. { -(float)width/2,-(float)height/2,-(float)depth/2 },
  79. { (float)width/2,-(float)height/2,-(float)depth/2 },
  80. { (float)width/2, (float)height/2,-(float)depth/2 },
  81. { -(float)width/2, (float)height/2,-(float)depth/2 },
  82. { -(float)width/2,-(float)height/2, (float)depth/2 },
  83. { (float)width/2,-(float)height/2, (float)depth/2 },
  84. { (float)width/2, (float)height/2, (float)depth/2 },
  85. { -(float)width/2, (float)height/2, (float)depth/2 }
  86. };
  87. Pointf texCoords[24] =
  88. {
  89. { 0, 0 }, { 1, 0 }, { 1, 1 }, { 0, 1 },
  90. { 1, 0 }, { 0, 0 }, { 0, 1 }, { 1, 1 },
  91. { 1, 0 }, { 0, 0 }, { 0, 1 }, { 1, 1 },
  92. { 0, 0 }, { 1, 0 }, { 1, 1 }, { 0, 1 },
  93. { 0, 1 }, { 1, 1 }, { 1, 1 }, { 0, 1 },
  94. { 0, 0 }, { 1, 0 }, { 1, 0 }, { 0, 0 }
  95. };
  96. uint16 indices[4] =
  97. {
  98. 5,6,7,4,
  99. };
  100. CopyBytes(mesh.vertices, vertices, sizeof(vertices));
  101. CopyBytes(((Pointf *)mesh.texCoords), texCoords, sizeof(texCoords));
  102. {
  103. PrimitiveGroup group;
  104. group = mesh.AddPrimitiveGroup(quads, 4);
  105. if(group)
  106. {
  107. CopyBytes(group.indices, indices, sizeof(indices));
  108. mesh.UnlockPrimitiveGroup(group);
  109. }
  110. }
  111. mesh.ComputeNormals();
  112. result = true;
  113. mesh.Unlock(MeshFeatures{});
  114. }
  115. }
  116. return result;
  117. }
  118. static bool CreateFront(Mesh mesh, int width, int height, int depth, DisplaySystem displaySystem)
  119. {
  120. bool result = false;
  121. if(mesh)
  122. {
  123. if(mesh.Allocate(MeshFeatures { vertices = true, texCoords1 = true }, 24, displaySystem))
  124. {
  125. Vector3Df vertices[24] =
  126. {
  127. { -(float)width/2,-(float)height/2,-(float)depth/2 },
  128. { (float)width/2,-(float)height/2,-(float)depth/2 },
  129. { (float)width/2, (float)height/2,-(float)depth/2 },
  130. { -(float)width/2, (float)height/2,-(float)depth/2 },
  131. { -(float)width/2,-(float)height/2, (float)depth/2 },
  132. { (float)width/2,-(float)height/2, (float)depth/2 },
  133. { (float)width/2, (float)height/2, (float)depth/2 },
  134. { -(float)width/2, (float)height/2, (float)depth/2 },
  135. { -(float)width/2,-(float)height/2,-(float)depth/2 },
  136. { (float)width/2,-(float)height/2,-(float)depth/2 },
  137. { (float)width/2, (float)height/2,-(float)depth/2 },
  138. { -(float)width/2, (float)height/2,-(float)depth/2 },
  139. { -(float)width/2,-(float)height/2, (float)depth/2 },
  140. { (float)width/2,-(float)height/2, (float)depth/2 },
  141. { (float)width/2, (float)height/2, (float)depth/2 },
  142. { -(float)width/2, (float)height/2, (float)depth/2 },
  143. { -(float)width/2,-(float)height/2,-(float)depth/2 },
  144. { (float)width/2,-(float)height/2,-(float)depth/2 },
  145. { (float)width/2, (float)height/2,-(float)depth/2 },
  146. { -(float)width/2, (float)height/2,-(float)depth/2 },
  147. { -(float)width/2,-(float)height/2, (float)depth/2 },
  148. { (float)width/2,-(float)height/2, (float)depth/2 },
  149. { (float)width/2, (float)height/2, (float)depth/2 },
  150. { -(float)width/2, (float)height/2, (float)depth/2 }
  151. };
  152. Pointf texCoords[24] =
  153. {
  154. { 0, 0 }, { 1, 0 }, { 1, 1 }, { 0, 1 },
  155. { 1, 0 }, { 0, 0 }, { 0, 1 }, { 1, 1 },
  156. { 1, 0 }, { 0, 0 }, { 0, 1 }, { 1, 1 },
  157. { 0, 0 }, { 1, 0 }, { 1, 1 }, { 0, 1 },
  158. { 0, 1 }, { 1, 1 }, { 1, 1 }, { 0, 1 },
  159. { 0, 0 }, { 1, 0 }, { 1, 0 }, { 0, 0 }
  160. };
  161. uint16 indices[4] =
  162. {
  163. 0,3,2,1
  164. };
  165. CopyBytes(mesh.vertices, vertices, sizeof(vertices));
  166. CopyBytes(((Pointf *)mesh.texCoords), texCoords, sizeof(texCoords));
  167. {
  168. PrimitiveGroup group;
  169. group = mesh.AddPrimitiveGroup(quads, 4);
  170. if(group)
  171. {
  172. CopyBytes(group.indices, indices, sizeof(indices));
  173. mesh.UnlockPrimitiveGroup(group);
  174. }
  175. }
  176. mesh.ComputeNormals();
  177. result = true;
  178. mesh.Unlock(MeshFeatures {});
  179. }
  180. }
  181. return result;
  182. }
  183. static bool CreateSide(Mesh mesh, int width, int height, int depth, DisplaySystem displaySystem)
  184. {
  185. bool result = false;
  186. if(mesh)
  187. {
  188. if(mesh.Allocate(MeshFeatures { vertices = true, texCoords1 = true }, 24, displaySystem))
  189. {
  190. Vector3Df vertices[24] =
  191. {
  192. { -(float)width/2,-(float)height/2,-(float)depth/2 },
  193. { (float)width/2,-(float)height/2,-(float)depth/2 },
  194. { (float)width/2, (float)height/2,-(float)depth/2 },
  195. { -(float)width/2, (float)height/2,-(float)depth/2 },
  196. { -(float)width/2,-(float)height/2, (float)depth/2 },
  197. { (float)width/2,-(float)height/2, (float)depth/2 },
  198. { (float)width/2, (float)height/2, (float)depth/2 },
  199. { -(float)width/2, (float)height/2, (float)depth/2 },
  200. { -(float)width/2,-(float)height/2,-(float)depth/2 },
  201. { (float)width/2,-(float)height/2,-(float)depth/2 },
  202. { (float)width/2, (float)height/2,-(float)depth/2 },
  203. { -(float)width/2, (float)height/2,-(float)depth/2 },
  204. { -(float)width/2,-(float)height/2, (float)depth/2 },
  205. { (float)width/2,-(float)height/2, (float)depth/2 },
  206. { (float)width/2, (float)height/2, (float)depth/2 },
  207. { -(float)width/2, (float)height/2, (float)depth/2 },
  208. { -(float)width/2,-(float)height/2,-(float)depth/2 },
  209. { (float)width/2,-(float)height/2,-(float)depth/2 },
  210. { (float)width/2, (float)height/2,-(float)depth/2 },
  211. { -(float)width/2, (float)height/2,-(float)depth/2 },
  212. { -(float)width/2,-(float)height/2, (float)depth/2 },
  213. { (float)width/2,-(float)height/2, (float)depth/2 },
  214. { (float)width/2, (float)height/2, (float)depth/2 },
  215. { -(float)width/2, (float)height/2, (float)depth/2 }
  216. };
  217. Pointf texCoords[24] =
  218. {
  219. { 0, 0 }, { 1, 0 }, { 1, 1 }, { 0, 1 },
  220. { 1, 0 }, { 0, 0 }, { 0, 1 }, { 1, 1 },
  221. { 1, 0 }, { 0, 0 }, { 0, 1 }, { 1, 1 },
  222. { 0, 0 }, { 1, 0 }, { 1, 1 }, { 0, 1 },
  223. { 0, 1 }, { 1, 1 }, { 1, 1 }, { 0, 1 },
  224. { 0, 0 }, { 1, 0 }, { 1, 0 }, { 0, 0 }
  225. };
  226. uint16 indices[16] =
  227. {
  228. // up, down, right, left
  229. 17,21,20,16 ,
  230. 22,18,19,23,
  231. 9,10,14,13,
  232. 12,15,11,8
  233. };
  234. CopyBytes(mesh.vertices, vertices, sizeof(vertices));
  235. CopyBytes(((Pointf *)mesh.texCoords), texCoords, sizeof(texCoords));
  236. {
  237. PrimitiveGroup group;
  238. group = mesh.AddPrimitiveGroup(quads, 16);
  239. if(group)
  240. {
  241. CopyBytes(group.indices, indices, sizeof(indices));
  242. mesh.UnlockPrimitiveGroup(group);
  243. }
  244. }
  245. mesh.ComputeNormals();
  246. result = true;
  247. mesh.Unlock(MeshFeatures{});
  248. }
  249. }
  250. return result;
  251. }
  252. class Desktop3D : Window
  253. {
  254. text = "Orbiting 3D Desktop", size = Size { WINDOW_WIDTH,WINDOW_HEIGHT };
  255. Object lookAt {};
  256. Camera camera
  257. {
  258. lookAt, position = {0, ORBIT_HEIGHT, -2000}, target = lookAt, orientation = Euler { pitch = 15 },
  259. zMin = 1, zMax = 10000, fov = 53
  260. };
  261. Light light;
  262. bool moving;
  263. bool movingCamera;
  264. Vector3Df lastMouse;
  265. // Object knot;
  266. Bitmap puzzle;
  267. Window clippedWindow;
  268. Box clipBox;
  269. Dock dock;
  270. Degrees globalPosition;
  271. int numWindows;
  272. Window poppingWindow;
  273. float poppingPercent;
  274. float poppingBiggest;
  275. // Camera Sliding
  276. Quaternion fromAngle, toAngle;
  277. Vector3D fromPosition, toPosition;
  278. float sliding, switching, entering;
  279. bool dockHidden;
  280. bool fullScreen;
  281. Timer dockTimer
  282. {
  283. this, 0;
  284. bool DelayExpired()
  285. {
  286. Seconds time = GetTime();
  287. Seconds diffTime = time - dock.lastTime;
  288. dock.lastTime = time;
  289. dock.position += (float)(dock.speed * diffTime);
  290. if(dock.position >= FULL_SWITCH)
  291. {
  292. dock.position = 0;
  293. dock.speed = 0;
  294. dock.currentIcon++;
  295. if(dock.currentIcon >= NUM_ICONS)
  296. dock.currentIcon -= NUM_ICONS;
  297. dockTimer.Stop();
  298. }
  299. else if(dock.position <= -FULL_SWITCH)
  300. {
  301. dock.position = 0;
  302. dock.speed = 0;
  303. dock.currentIcon--;
  304. if(dock.currentIcon < 0)
  305. dock.currentIcon += NUM_ICONS;
  306. dockTimer.Stop();
  307. }
  308. return true;
  309. }
  310. };
  311. Timer timer
  312. {
  313. this, 0.05;
  314. bool DelayExpired()
  315. {
  316. //int buttons;
  317. Seconds time = GetTime();
  318. Seconds diffTime = (time - lastTime);
  319. Window child;
  320. Degrees biggest = 0;
  321. //GetMouseState(&buttons, null, null);
  322. /*
  323. eObject_RotateEuler(knot, P3D(diffTime / 10, diffTime / 10, diffTime / 10),
  324. P3D(0,0,0), P3D(0,0,0));
  325. */
  326. Update(null); //Desktop3DSetDesktopDirty();
  327. /*
  328. if(buttons & MOUSE_RIGHT)
  329. {
  330. eCamera_Move(camera, P3D(0,0,1000 * diffTime));
  331. window.dirty = true;
  332. }
  333. else if(buttons & MOUSE_MIDDLE)
  334. {
  335. eCamera_Move(camera, P3D(0,0,-1000 * diffTime));
  336. window.dirty = true;
  337. }
  338. */
  339. // Orbit Rotation
  340. if(!fullScreen)
  341. {
  342. if(sliding == 1 && switching == 1 && entering == 1)
  343. {
  344. globalPosition += (double)diffTime * ORBIT_SPEED;
  345. for(child = firstChild; child; child = child.next)
  346. {
  347. if(child.display != display)
  348. {
  349. Window3D window3D = Desktop3DGetWindowHandle(child);
  350. if(window3D.position < window3D.wantedPosition - 0.000001)
  351. {
  352. window3D.wantedPosition += (double)diffTime * ORBIT_SPEED;
  353. window3D.position += (double)diffTime * (window3D.wantedPosition - window3D.position);
  354. window3D.position = Min(window3D.position, window3D.wantedPosition);
  355. biggest = Max(biggest, window3D.wantedPosition - window3D.position);
  356. }
  357. else if(window3D.position > window3D.wantedPosition + 0.000001)
  358. {
  359. window3D.wantedPosition += (double)diffTime * ORBIT_SPEED;
  360. window3D.position -= (double)diffTime * (window3D.position - window3D.wantedPosition);
  361. window3D.position = Max(window3D.position, window3D.wantedPosition);
  362. biggest = Max(biggest, window3D.position - window3D.wantedPosition);
  363. }
  364. else
  365. {
  366. window3D.wantedPosition += (double)diffTime * ORBIT_SPEED;
  367. window3D.position += (double)diffTime * ORBIT_SPEED;
  368. }
  369. }
  370. }
  371. }
  372. }
  373. #define FIRST_2WINDOWS_POPUP_SPEED 0.5
  374. if(numWindows < 3)
  375. {
  376. poppingPercent += (float)(diffTime * FIRST_2WINDOWS_POPUP_SPEED);
  377. if(poppingPercent < 1)
  378. poppingPercent += (float)((1.0 - poppingPercent) * diffTime * FIRST_2WINDOWS_POPUP_SPEED);
  379. if(poppingPercent > 0.99999)
  380. {
  381. poppingWindow = null;
  382. poppingPercent = 1.0f;
  383. }
  384. }
  385. else if(biggest < 0.000001)
  386. {
  387. poppingPercent = 1;
  388. poppingWindow = null;
  389. }
  390. else
  391. poppingPercent = (float)(1.0 - (Radians)(biggest / poppingBiggest));
  392. poppingPercent = Min(poppingPercent, 1.0);
  393. if(dockHidden && virtualDesktop.activeChild && entering == 1)
  394. {
  395. Window window = virtualDesktop.activeChild;
  396. Window3D window3D = Desktop3DGetWindowHandle(window);
  397. lookAt.transform.position = window3D.cube.transform.position;
  398. lookAt.UpdateTransform();
  399. camera.Update();
  400. toPosition = camera.cPosition;
  401. toAngle = camera.cOrientation;
  402. }
  403. if(sliding < 1 || switching < 1 || entering < 1)
  404. {
  405. Quaternion angle;
  406. Vector3D position;
  407. float factor;
  408. if(sliding < 1)
  409. {
  410. sliding += (float)(diffTime * SLIDING_SPEED);
  411. sliding = Min(sliding, 1.0);
  412. factor = sliding;
  413. }
  414. else if(switching < 1)
  415. {
  416. switching += (float)(diffTime * SWITCHING_SPEED);
  417. switching = Min(switching, 1.0);
  418. factor = switching;
  419. }
  420. else if(entering < 1)
  421. {
  422. entering += (float)(diffTime * ENTERING_SPEED);
  423. entering = Min(entering, 1.0);
  424. factor = entering;
  425. }
  426. angle.Slerp(fromAngle, toAngle, factor);
  427. position.x = fromPosition.x + factor * (toPosition.x - fromPosition.x);
  428. position.y = fromPosition.y + factor * (toPosition.y - fromPosition.y);
  429. position.z = fromPosition.z + factor * (toPosition.z - fromPosition.z);
  430. camera.AdjustAngle(angle);
  431. camera.AdjustPosition(position);
  432. }
  433. Update(null);
  434. lastTime = time;
  435. return true;
  436. }
  437. };
  438. SkyBox sky { size = { 10000, 10000, 10000 }, folder = ":skycube", extension = "jpg" };
  439. bool OnCreate()
  440. {
  441. camera.Update();
  442. fromPosition = toPosition = camera.cPosition;
  443. fromAngle = toAngle = camera.cOrientation;
  444. // Start with dock off
  445. // sliding = 1;
  446. switching = 1;
  447. entering = 1;
  448. light.diffuse = white;
  449. light.specular = white;
  450. light.orientation = Euler { }; //Quaternion { 1,0,Pi,0 };
  451. timer.Start();
  452. return true;
  453. }
  454. void OnResize(int width, int height)
  455. {
  456. camera.Setup(width, height, null);
  457. }
  458. bool OnLoadGraphics()
  459. {
  460. int c;
  461. sky.Create(displaySystem);
  462. /*
  463. eObject_Load(&knot, ":eknot.3ds", null, display);
  464. knot->transform.scaling = P3D(10,10,10);
  465. knot->transform.position = P3D(0,0, 2000);
  466. */
  467. // puzzle = eBitmap_Load(":puzzle.jpg", null, display);
  468. // dock.background = Bitmap {};
  469. // dock.background.Load(":background.jpg", null, displaySystem);
  470. for(c = 0; c<NUM_ICONS; c++)
  471. {
  472. dock.iconBitmaps[c] = Bitmap {};
  473. dock.iconBitmaps[c].Load(iconFiles[c], null, displaySystem);
  474. }
  475. lastTime = GetTime();
  476. return true;
  477. }
  478. void OnUnloadGraphics()
  479. {
  480. int c;
  481. //eObject_Free(cube, display);
  482. for(c = 0; c<NUM_ICONS; c++)
  483. dock.iconBitmaps[c].Free();
  484. }
  485. #define DOCK_SLIDING_DISTANCE 180
  486. void Dock_OnRedraw(Surface surface)
  487. {
  488. int c, icon = dock.currentIcon;
  489. float x = -120 - dock.position, starty = DOCK_HEIGHT;
  490. byte alpha = 255;
  491. if(sliding < 1)
  492. {
  493. if(dockHidden)
  494. {
  495. starty += sliding * DOCK_SLIDING_DISTANCE;
  496. alpha = 255 - (byte)(255*sliding);
  497. }
  498. else
  499. {
  500. starty += DOCK_SLIDING_DISTANCE - (sliding * DOCK_SLIDING_DISTANCE);
  501. alpha = (byte)(255*sliding);
  502. }
  503. }
  504. if(!dockHidden || sliding < 1)
  505. {
  506. icon -= 2;
  507. if(icon < 0) icon += NUM_ICONS;
  508. /*
  509. eSurface_Blit(surface, dock.background, 0,0,0,0,
  510. dock.background->width, dock.background->height);
  511. */
  512. for(c = 0; c<NUM_ICONS; c++)
  513. {
  514. Bitmap bitmap;
  515. int dx, dy, w, h;
  516. float scaling = SMALL_SCALE;
  517. float y;
  518. bitmap = dock.iconBitmaps[icon];
  519. y = starty;
  520. if(dock.speed > 0)
  521. {
  522. float a = dock.position / FULL_SWITCH;
  523. if(icon == dock.currentIcon)
  524. {
  525. // The old one
  526. scaling = (float)(1 - (1-SMALL_SCALE) * a);
  527. }
  528. else if(icon == (dock.currentIcon + 1) % NUM_ICONS)
  529. {
  530. // The upcoming one
  531. scaling = (float)(SMALL_SCALE + (1-SMALL_SCALE) * a);
  532. }
  533. }
  534. else if(dock.speed < 0)
  535. {
  536. float a = -dock.position / FULL_SWITCH;
  537. if(icon == dock.currentIcon)
  538. {
  539. // The old one
  540. scaling = 1 - (1-SMALL_SCALE) * a;
  541. }
  542. else if((icon + 1) % NUM_ICONS == dock.currentIcon)
  543. {
  544. // The upcoming one
  545. scaling = SMALL_SCALE + (1-SMALL_SCALE) * a;
  546. }
  547. }
  548. else if(icon == dock.currentIcon)
  549. {
  550. scaling = 1;
  551. if(poppingWindow)
  552. {
  553. float percent = poppingPercent; // * poppingPercent * poppingPercent * poppingPercent;
  554. y += (float) sin(percent * 2*Pi*3) * 4 + 0.5f;
  555. }
  556. }
  557. w = (int)(bitmap.width * scaling);
  558. h = (int)(bitmap.height * scaling);
  559. dx = (int)(x - w/2);
  560. dy = (int)(y - h/2);
  561. surface.SetForeground(ColorAlpha{alpha, white});
  562. surface.Stretch(bitmap, dx, dy, 0,0, w, h, bitmap.width, bitmap.height);
  563. x += FULL_SWITCH;
  564. icon ++;
  565. if(icon == NUM_ICONS) icon = 0;
  566. }
  567. }
  568. }
  569. #define ORBIT_RADIUS 800
  570. void OnRedraw(Surface surface)
  571. {
  572. Window child;
  573. surface.Clear(depthBuffer);
  574. //PrintLn("position: ", camera.cPosition);
  575. display.SetLight(0, &light);
  576. display.SetCamera(surface, camera);
  577. sky.Render(camera, display);
  578. for(child = firstChild; child; child = child.next)
  579. {
  580. if(child.is3D)
  581. {
  582. Window3D window3D = Desktop3DGetWindowHandle(child);
  583. Mesh mesh = window3D.front.mesh;
  584. int w, h;
  585. if(mesh.Lock(MeshFeatures { texCoords1 = true }))
  586. {
  587. ((Pointf *)mesh.texCoords)[3].x = 0;
  588. ((Pointf *)mesh.texCoords)[3].y = 0;
  589. ((Pointf *)mesh.texCoords)[2].x = (float)child.size.w / window3D.bitmap.width;
  590. ((Pointf *)mesh.texCoords)[2].y = 0;
  591. ((Pointf *)mesh.texCoords)[1].x = (float)child.size.w / window3D.bitmap.width;
  592. ((Pointf *)mesh.texCoords)[1].y = (float)child.size.h / window3D.bitmap.height;
  593. ((Pointf *)mesh.texCoords)[0].x = 0;
  594. ((Pointf *)mesh.texCoords)[0].y = (float)child.size.h / window3D.bitmap.height;
  595. mesh.Unlock(MeshFeatures {});
  596. }
  597. {
  598. float alpha = 0.5f;
  599. if(child == poppingWindow)
  600. alpha = 0.5f * poppingPercent * poppingPercent * poppingPercent;
  601. else if(child == virtualDesktop.activeChild)
  602. {
  603. if(entering < 1)
  604. {
  605. if(fullScreen)
  606. alpha = 0.5f + entering / 2.0f;
  607. else
  608. alpha = 1.0f - entering / 2.0f;
  609. }
  610. else if(fullScreen)
  611. alpha = 1.0f;
  612. }
  613. window3D.frontMaterial.opacity = alpha;
  614. window3D.sideMaterial.opacity = alpha;
  615. window3D.backMaterial.opacity = alpha;
  616. }
  617. if(numWindows > 6)
  618. {
  619. w = (int)(2*Pi*ORBIT_RADIUS / (numWindows+1));
  620. h = w * WINDOW_HEIGHT / WINDOW_WIDTH;
  621. }
  622. else
  623. {
  624. w = child.size.w;
  625. h = child.size.h;
  626. }
  627. if(child == poppingWindow)
  628. {
  629. Vector3D finalPosition;
  630. Vector3D startPositionProjected = { - 120 + 284, DOCK_HEIGHT, 1.0f };
  631. Vector3D startPositionView, startPositionWorld;
  632. camera.Unproject(startPositionProjected, startPositionView);
  633. camera.Untransform(startPositionView, startPositionWorld);
  634. finalPosition.x = (float)(cos(window3D.position) * ORBIT_RADIUS);
  635. finalPosition.y = 0;
  636. finalPosition.z = (float)(sin(window3D.position) * ORBIT_RADIUS);
  637. window3D.cube.transform = Transform
  638. {
  639. position =
  640. {
  641. startPositionWorld.x + (finalPosition.x - startPositionWorld.x) * poppingPercent,
  642. startPositionWorld.y + (finalPosition.y - startPositionWorld.y) * poppingPercent,
  643. startPositionWorld.z + (finalPosition.z - startPositionWorld.z) * poppingPercent
  644. },
  645. orientation = Euler { window3D.position - 90 + poppingPercent * 2 * 360, 10, 0 },
  646. scaling = { w * poppingPercent, h * poppingPercent, 1 }
  647. };
  648. }
  649. else
  650. {
  651. Vector3Df scaling = Vector3Df { 1,1,1 };
  652. if(poppingWindow)
  653. {
  654. int wb, hb;
  655. if(numWindows-1 > 6)
  656. {
  657. wb = (int)(2*Pi*ORBIT_RADIUS / (numWindows));
  658. hb = (int)(wb * WINDOW_HEIGHT / WINDOW_WIDTH);
  659. }
  660. else
  661. {
  662. wb = child.size.w;
  663. hb = child.size.h;
  664. }
  665. scaling.x = wb + (w - wb);// * poppingPercent;
  666. scaling.y = hb + (h - hb);// * poppingPercent;
  667. }
  668. else
  669. {
  670. scaling.x = w;
  671. scaling.y = h;
  672. }
  673. window3D.cube.transform = Transform
  674. {
  675. position = { (float)(cos(window3D.position) * ORBIT_RADIUS), 0, (float)(sin(window3D.position) * ORBIT_RADIUS) },
  676. orientation = Euler { window3D.position - 90 + window3D.offset.yaw, 10 + window3D.offset.pitch, 0 },
  677. scaling = { (float)scaling.x, (float)scaling.y, (float)scaling.z };
  678. };
  679. }
  680. window3D.cube.UpdateTransform();
  681. display.DrawObject(window3D.cube);
  682. }
  683. }
  684. // display.DrawObject(knot);
  685. display.SetCamera(null, null);
  686. Dock_OnRedraw(surface);
  687. }
  688. Window GetCursorLocation(int x, int y, int * mx, int * my, bool * back)
  689. {
  690. Window window = null;
  691. Window3D window3D;
  692. Vector3D viewSpace, worldSpace, local;
  693. display.StartSelection(x, y, 1, 1);
  694. display.IntersectPolygons();
  695. display.SetCamera(null, camera);
  696. if(clippedWindow)
  697. {
  698. window = clippedWindow;
  699. window3D = Desktop3DGetWindowHandle(window);
  700. display.pickingPlanes = true;
  701. display.DrawObject(window3D.cube.Find("Front"));
  702. }
  703. else
  704. {
  705. HitRecord hit;
  706. OldList list;
  707. display.CollectHits();
  708. for(window = virtualDesktop.firstChild; window; window = window.next)
  709. {
  710. if(window.is3D)
  711. {
  712. window3D = Desktop3DGetWindowHandle(window);
  713. display.DrawObject(window3D.cube);
  714. }
  715. }
  716. display.GetHits(list);
  717. hit = list.first;
  718. if(hit && hit.numTags)
  719. {
  720. window = (Window)hit.tags[0];
  721. window3D = Desktop3DGetWindowHandle(window);
  722. }
  723. list.Free(null);
  724. }
  725. if(window)
  726. {
  727. display.GetIntersect(viewSpace);
  728. camera.Untransform(viewSpace, worldSpace);
  729. local.DivideMatrix(worldSpace, window3D.cube.matrix);
  730. *mx = (int)(local.x * window.size.w + window.size.w/2 + 0.5) + window.absPosition.x;
  731. *my = (int)(local.y * window.size.h + window.size.h/2 + 0.5) + window.absPosition.y;
  732. *back = local.z > 0;
  733. }
  734. display.SetCamera(null, null);
  735. display.StopSelection();
  736. display.pickingPlanes = false;
  737. /*
  738. if(clippedWindow)
  739. {
  740. int oldx = *mx, oldy = *my;
  741. oldx = *mx;
  742. oldy = *my;
  743. if(*mx < clipBox.left) *mx = clipBox.left;
  744. if(*my < clipBox.top) *my = clipBox.top;
  745. if(*mx > clipBox.right) *mx = clipBox.right;
  746. if(*my > clipBox.bottom) *my = clipBox.bottom;
  747. if(oldx != *mx || oldy != *my)
  748. {
  749. Vector3Df viewSpace, worldSpace;
  750. local.x = ((float) *mx - window.absPosition.x - window.size.w/2.0 + 0.5) / (float)window.size.w;
  751. local.y = ((float) *my - window.absPosition.y - window.size.h/2.0 + 0.5) / (float)window.size.h;
  752. local.z = -THICKNESS/2;
  753. worldSpace.MultMatrix(local, matrix);
  754. camera.TransformPoint(viewSpace, worldSpace);
  755. camera.Project(viewSpace, point);
  756. x = point.x + 0.5;
  757. y = point.y + 0.5;
  758. SetMousePosition(x, y);
  759. }
  760. }
  761. */
  762. return window;
  763. }
  764. bool OnMouseMove(int x, int y, Modifiers mods)
  765. {
  766. if(moving)
  767. {
  768. int dx = (int)(x - lastMouse.x), dy = (int)(lastMouse.y - y);
  769. if(movingCamera)
  770. {
  771. camera.RotateYaw(-dx, 0,0);
  772. camera.RotatePitch(dy, 0,0);
  773. }
  774. else
  775. {
  776. Window child = activeChild;
  777. Window3D window3D = Desktop3DGetWindowHandle(child);
  778. window3D.offset.yaw += dx;
  779. window3D.offset.pitch += dy;
  780. }
  781. // window.dirty = true;
  782. Update(null); // ?
  783. lastMouse.x = x;
  784. lastMouse.y = y;
  785. }
  786. else
  787. {
  788. int mx, my;
  789. bool back;
  790. Window clickedWindow = GetCursorLocation(x,y, &mx, &my, &back);
  791. if(clickedWindow)
  792. {
  793. if(Desktop3DMouseMessage(clickedWindow, 24, mx, my, &mods, false, true))
  794. {
  795. }
  796. }
  797. }
  798. return true;
  799. }
  800. bool OnLeftButtonDown(int x, int y, Modifiers mods)
  801. {
  802. if(!moving)
  803. {
  804. int mx, my;
  805. bool back;
  806. Window clickedWindow = GetCursorLocation(x,y, &mx, &my, &back);
  807. if(clickedWindow)
  808. {
  809. if(back || Desktop3DTitleBarClicked(clickedWindow, mx, my))
  810. {
  811. clickedWindow.Activate();
  812. movingCamera = false;
  813. Capture();
  814. moving = true;
  815. }
  816. else if(Desktop3DMouseMessage(clickedWindow, 25, mx, my, &mods, false, true))
  817. {
  818. }
  819. }
  820. else
  821. {
  822. movingCamera = true;
  823. Capture();
  824. moving = true;
  825. }
  826. lastMouse.x = x;
  827. lastMouse.y = y;
  828. }
  829. return true;
  830. }
  831. bool OnLeftButtonUp(int x, int y, Modifiers mods)
  832. {
  833. int mx, my;
  834. bool back;
  835. Window clickedWindow = GetCursorLocation(x, y, &mx, &my, &back);
  836. if(clickedWindow)
  837. {
  838. Desktop3DMouseMessage(clickedWindow, 26, mx, my, &mods, false, true);
  839. }
  840. if(moving)
  841. {
  842. ReleaseCapture();
  843. moving = false;
  844. }
  845. return true;
  846. }
  847. bool OnKeyHit(Key key, unichar character)
  848. {
  849. static int id = 0;
  850. static char * shotFileNames[] =
  851. {
  852. ":shot1.jpg", ":shot2.jpg", ":shot3.jpg", ":shot4.jpg"
  853. };
  854. switch(key)
  855. {
  856. case left:
  857. if(dockHidden)
  858. {
  859. Window3D window3D;
  860. virtualDesktop.CycleChildren(true, false, false, true);
  861. window3D = Desktop3DGetWindowHandle(virtualDesktop.activeChild);
  862. fromAngle = camera.cOrientation;
  863. fromPosition = camera.cPosition;
  864. lookAt.transform.position = window3D.cube.transform.position;
  865. lookAt.UpdateTransform();
  866. camera.position = {};
  867. camera.orientation = Euler{};
  868. switching = 0;
  869. camera.Update();
  870. toPosition = camera.cPosition;
  871. toAngle = camera.cOrientation;
  872. camera.AdjustAngle(fromAngle);
  873. camera.AdjustPosition(fromPosition);
  874. }
  875. else
  876. {
  877. if(!dockTimer.started)
  878. {
  879. dock.lastTime = GetTime();
  880. dockTimer.Start();
  881. dock.speed = -SWITCH_SPEED;
  882. }
  883. }
  884. break;
  885. case right:
  886. if(dockHidden)
  887. {
  888. Window3D window3D;
  889. virtualDesktop.CycleChildren(false, false, false, true);
  890. window3D = Desktop3DGetWindowHandle(virtualDesktop.activeChild);
  891. fromAngle = camera.cOrientation;
  892. fromPosition = camera.cPosition;
  893. lookAt.transform.position = window3D.cube.transform.position;
  894. lookAt.UpdateTransform();
  895. switching = 0;
  896. camera.Update();
  897. toPosition = camera.cPosition;
  898. toAngle = camera.cOrientation;
  899. camera.AdjustAngle(fromAngle);
  900. camera.AdjustPosition(fromPosition);
  901. }
  902. else
  903. {
  904. if(!dockTimer.started)
  905. {
  906. dock.lastTime = GetTime();
  907. dockTimer.Start();
  908. dock.speed = SWITCH_SPEED;
  909. }
  910. }
  911. break;
  912. case enter:
  913. {
  914. if(!dockHidden)
  915. {
  916. if(!poppingWindow)
  917. {
  918. /*if(dock.currentIcon == 1)
  919. {
  920. EditBox
  921. {
  922. this, multiLine = true, is3D = true, borderStyle = Fixed, hasClose = true, text = "Video",
  923. size = Size { WINDOW_WIDTH, WINDOW_HEIGHT }, fileName = ":430.flc"
  924. }.Create();
  925. }
  926. else*/
  927. {
  928. Picture
  929. {
  930. this, is3D = true, borderStyle = fixed, hasClose = true, text = "3D Window",
  931. size = Size { WINDOW_WIDTH, WINDOW_HEIGHT }, image = BitmapResource { fileName = shotFileNames[id] }, opacity = 1, inactive = false
  932. }.Create();
  933. }
  934. id++;
  935. id %= sizeof(shotFileNames) / sizeof(char *);
  936. }
  937. }
  938. else if(!fullScreen)
  939. {
  940. float distance;
  941. Window window = virtualDesktop.activeChild;
  942. Window3D window3D = Desktop3DGetWindowHandle(window);
  943. fromAngle = camera.cOrientation;
  944. fromPosition = camera.cPosition;
  945. distance = window3D.cube.transform.scaling.x * (float)camera.focal.w / virtualDesktop.clientSize.w;
  946. distance += THICKNESS/2;
  947. camera.type = attached;
  948. camera.position = {0,0,-distance};
  949. camera.orientation = Euler{};
  950. lookAt.transform.position = window3D.cube.transform.position;
  951. lookAt.transform.orientation = window3D.cube.transform.orientation;
  952. lookAt.UpdateTransform();
  953. entering = 0;
  954. camera.Update();
  955. toPosition = camera.cPosition;
  956. toAngle = camera.cOrientation;
  957. camera.AdjustAngle(fromAngle);
  958. camera.AdjustPosition(fromPosition);
  959. fullScreen = true;
  960. }
  961. break;
  962. }
  963. case f1:
  964. {
  965. if(dockHidden)
  966. {
  967. Window window = virtualDesktop.activeChild;
  968. Window3D window3D = Desktop3DGetWindowHandle(window);
  969. if(fullScreen)
  970. {
  971. fromAngle = camera.cOrientation;
  972. fromPosition = camera.cPosition;
  973. camera.type = lookAt;
  974. camera.position = {};
  975. camera.orientation = Euler{};
  976. lookAt.transform.position = window3D.cube.transform.position;
  977. lookAt.transform.orientation = Euler { };
  978. lookAt.UpdateTransform();
  979. entering = 0;
  980. camera.Update();
  981. toPosition = camera.cPosition;
  982. toAngle = camera.cOrientation;
  983. camera.AdjustAngle(fromAngle);
  984. camera.AdjustPosition(fromPosition);
  985. // window.Deactivate();
  986. entering = 0;
  987. fullScreen = false;
  988. }
  989. }
  990. break;
  991. }
  992. case up:
  993. {
  994. if(sliding == 1.0 && !dockHidden)
  995. {
  996. Quaternion fa, ta;
  997. Vector3D fp, tp;
  998. Window window = virtualDesktop.activeChild;
  999. Window3D window3D = Desktop3DGetWindowHandle(window);
  1000. camera.Update();
  1001. fa = fromAngle = camera.cOrientation;
  1002. fp = fromPosition = camera.cPosition;
  1003. camera.type = lookAt;
  1004. camera.position = { 0,0,0 };
  1005. camera.orientation = Euler {};
  1006. lookAt.transform.position = window3D.cube.transform.position;
  1007. lookAt.transform.orientation = Euler {};
  1008. lookAt.UpdateTransform();
  1009. sliding = 0;
  1010. dockHidden = true;
  1011. camera.Update();
  1012. tp = toPosition = camera.cPosition;
  1013. ta = toAngle = camera.cOrientation;
  1014. camera.AdjustAngle(fromAngle);
  1015. camera.AdjustPosition(fromPosition);
  1016. }
  1017. break;
  1018. }
  1019. case down:
  1020. {
  1021. if(sliding == 1.0 && dockHidden)
  1022. {
  1023. fromAngle = camera.cOrientation;
  1024. fromPosition = camera.cPosition;
  1025. camera.type = lookAt;
  1026. camera.position = {0, ORBIT_HEIGHT, -2000};
  1027. camera.orientation = Euler { pitch = 15 };
  1028. lookAt.transform.position = {};
  1029. lookAt.transform.orientation = Euler {};
  1030. lookAt.UpdateTransform();
  1031. sliding = 0;
  1032. dockHidden = false;
  1033. fullScreen = false;
  1034. camera.Update();
  1035. toPosition = camera.cPosition;
  1036. toAngle = camera.cOrientation;
  1037. camera.AdjustAngle(fromAngle);
  1038. camera.AdjustPosition(fromPosition);
  1039. break;
  1040. }
  1041. }
  1042. case escape:
  1043. Destroy(0);
  1044. break;
  1045. }
  1046. return true;
  1047. }
  1048. }
  1049. static Window3D Setup3DWindow(Window window, int w, int h)
  1050. {
  1051. Window3D window3D {};
  1052. Window child;
  1053. window3D.bitmap = Bitmap {};
  1054. window3D.bitmap.AllocateDD(virtualDesktop.displaySystem, w, h);
  1055. // window3D.bitmap.AllocateDD(virtualDesktop.displaySystem, TEXTURE_SIZE, TEXTURE_SIZE);
  1056. window3D.cube = Object {};
  1057. window3D.cube.tag = window;
  1058. window3D.frontMaterial.diffuse = white;
  1059. window3D.frontMaterial.opacity = 0.5f;
  1060. window3D.frontMaterial.baseMap = window3D.bitmap;
  1061. window3D.frontMaterial.flags = MaterialFlags { translucent = true, doubleSided = true };
  1062. window3D.backMaterial.diffuse = white;
  1063. window3D.backMaterial.opacity = 0.5f;
  1064. window3D.backMaterial.flags = MaterialFlags { translucent = true, doubleSided = true };
  1065. window3D.sideMaterial.diffuse = white;
  1066. window3D.sideMaterial.opacity = 0.5f;
  1067. window3D.sideMaterial.flags = MaterialFlags { translucent = true, doubleSided = true };
  1068. window3D.cube.AddName((window3D.back = Object {}), "Back");
  1069. window3D.back.InitializeMesh(virtualDesktop.displaySystem);
  1070. CreateBack(window3D.back.mesh, 1, 1, THICKNESS, virtualDesktop.displaySystem);
  1071. window3D.back.mesh.ApplyMaterial(window3D.backMaterial);
  1072. window3D.back.mesh.ApplyTranslucency(window3D.back);
  1073. window3D.cube.AddName((window3D.front = Object {}), "Front");
  1074. window3D.front.InitializeMesh(virtualDesktop.displaySystem);
  1075. CreateFront(window3D.front.mesh, 1, 1, THICKNESS, virtualDesktop.displaySystem);
  1076. window3D.front.mesh.ApplyMaterial(window3D.frontMaterial);
  1077. window3D.front.mesh.ApplyTranslucency(window3D.front);
  1078. window3D.cube.AddName((window3D.side = Object {}), "Side");
  1079. window3D.side.InitializeMesh(virtualDesktop.displaySystem);
  1080. CreateSide(window3D.side.mesh, 1, 1, THICKNESS, virtualDesktop.displaySystem);
  1081. window3D.side.mesh.ApplyMaterial(window3D.sideMaterial);
  1082. window3D.side.mesh.ApplyTranslucency(window3D.side);
  1083. window3D.cube.SetMinMaxRadius(true);
  1084. window3D.id = virtualDesktop.numWindows;
  1085. virtualDesktop.poppingBiggest = 0;
  1086. for(child = virtualDesktop.firstChild; child; child = child.next)
  1087. {
  1088. if(child.is3D) //display != virtualDesktop.display)
  1089. {
  1090. Window3D child3D = Desktop3DGetWindowHandle(child);
  1091. if(child == window)
  1092. child3D = window3D;
  1093. child3D.wantedPosition = virtualDesktop.globalPosition +
  1094. child3D.id * 2*Pi / (virtualDesktop.numWindows+1);
  1095. if(child == window)
  1096. window3D.position = window3D.wantedPosition;
  1097. virtualDesktop.poppingBiggest = Max(virtualDesktop.poppingBiggest,
  1098. child3D.position - child3D.wantedPosition);
  1099. }
  1100. }
  1101. virtualDesktop.numWindows++;
  1102. virtualDesktop.poppingWindow = window;
  1103. virtualDesktop.poppingPercent = 0;
  1104. return window3D;
  1105. }
  1106. static void Update3DWindow(Window window, Box box)
  1107. {
  1108. Window3D window3D = Desktop3DGetWindowHandle(window);
  1109. int w = box.right - box.left + 1;
  1110. int h = box.bottom - box.top + 1;
  1111. glBindTexture(GL_TEXTURE_2D, (int)window3D.bitmap.driverData);
  1112. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  1113. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  1114. glCopyTexSubImage2D(GL_TEXTURE_2D, 0,
  1115. box.left,
  1116. window.size.h - h - box.top,
  1117. box.left + virtualDesktop.clientStart.x,
  1118. virtualDesktop.size.h - virtualDesktop.clientStart.y - h - box.top, w, h);
  1119. }
  1120. class Orbit : GuiApplication
  1121. {
  1122. driver = "OpenGL";
  1123. bool Init()
  1124. {
  1125. Desktop3DInitialize(virtualDesktop, Setup3DWindow, Update3DWindow);
  1126. return true;
  1127. }
  1128. }
  1129. Desktop3D virtualDesktop {};