Camera3D.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  1. #include "Camera3D.h"
  2. #include <d3d11.h>
  3. #include <DirectXMath.h>
  4. #include "Globals.h"
  5. #include "KeyboardEvent.h"
  6. #include "MouseEvent.h"
  7. #include "Shader.h"
  8. #include "World3D.h"
  9. using namespace Framework;
  10. // Contents of the Cam3D class
  11. // Constructor
  12. Cam3D::Cam3D()
  13. : ReferenceCounter(),
  14. rend(0)
  15. {
  16. openingAngle = (float)PI / 4;
  17. minZ = 0.1f;
  18. maxZ = 5000;
  19. pos = Vec3<float>(0, 0, -1000);
  20. rotX = 0;
  21. rotY = 0;
  22. rotZ = 0;
  23. viewport.x = 0;
  24. viewport.y = 0;
  25. viewport.front = 0.f;
  26. viewport.back = 1.f;
  27. viewport.width = 200;
  28. viewport.height = 200;
  29. welt = 0;
  30. style = 0;
  31. speed = 1;
  32. updateMatrix();
  33. }
  34. // Destructor
  35. Cam3D::~Cam3D()
  36. {
  37. if (welt) welt->release();
  38. }
  39. // private
  40. // Updates the view and projection matrices
  41. void Cam3D::updateMatrix()
  42. {
  43. view = view.rotationX(-rotX) * view.rotationY(-rotY) * view.rotationZ(-rotZ)
  44. * view.translation(Vec3<float>(-pos.x, -pos.y, -pos.z));
  45. inverseView = view.getInverse();
  46. proj = proj.projektion(
  47. openingAngle, viewport.width / viewport.height, minZ, maxZ);
  48. inverseProj = proj.getInverse();
  49. }
  50. // Sets the position of the camera in the 3D world
  51. void Cam3D::setPosition(Vec3<float> pos)
  52. {
  53. this->pos = pos;
  54. rend = 1;
  55. updateMatrix();
  56. }
  57. // Zooms in by moving the camera closer to the view target
  58. // val: The length of the distance the camera should move
  59. void Cam3D::scrollIn(float val)
  60. {
  61. Vec3<float> n(0, 0, 1);
  62. Mat4<float> tmp
  63. = tmp.rotationY(rotY) * tmp.rotationX(rotX) * tmp.rotationZ(rotZ);
  64. n = tmp * n * val;
  65. pos += n;
  66. rend = 1;
  67. updateMatrix();
  68. }
  69. // Zooms out by moving the camera away from the view target
  70. // val: The length of the distance the camera should move
  71. void Cam3D::scrollOut(float val)
  72. {
  73. Vec3<float> n(0, 0, 1);
  74. Mat4<float> tmp
  75. = tmp.rotationY(rotY) * tmp.rotationX(rotX) * tmp.rotationZ(rotZ);
  76. n = tmp * n * val;
  77. pos -= n;
  78. rend = 1;
  79. updateMatrix();
  80. }
  81. // Aligns the camera so that it points exactly at a specific point
  82. // ziel: The point the camera should point at
  83. void Cam3D::setViewDirection(Vec3<float> ziel)
  84. {
  85. Vec3<float> target = (ziel - pos).normalize();
  86. if (Vec3<float>(0, target.y, target.z).getLength() == 0)
  87. rotX = 0;
  88. else
  89. rotX = -lowPrecisionACos(
  90. target.z / Vec3<float>(0, target.y, target.z).getLength());
  91. if (target.y < 0) rotX = -rotX;
  92. if (Vec3<float>(target.x, 0, target.z).getLength() == 0)
  93. rotY = 0;
  94. else
  95. rotY = lowPrecisionACos(
  96. abs(target.z) / Vec3<float>(target.x, 0, target.z).getLength());
  97. if (target.x < 0) rotY = -rotY;
  98. rotZ = 0;
  99. rend = 1;
  100. updateMatrix();
  101. }
  102. //! Sets the rotation of the camera around each axis
  103. //! \param rotation The rotation around each axis
  104. void Cam3D::setRotation(Vec3<float> rotation)
  105. {
  106. rotX = rotation.x;
  107. rotY = rotation.y;
  108. rotZ = rotation.z;
  109. rend = 1;
  110. updateMatrix();
  111. }
  112. // Sets the position of the image on the screen
  113. // p: A point with x and y coordinates in pixels
  114. void Cam3D::setScreenPosition(Point p)
  115. {
  116. viewport.x = (float)p.x;
  117. viewport.y = (float)p.y;
  118. }
  119. // Sets the position of the image on the screen
  120. // x: The x coordinate in pixels
  121. // y: The y coordinate in pixels
  122. void Cam3D::setScreenPosition(int x, int y)
  123. {
  124. viewport.x = (float)x;
  125. viewport.y = (float)y;
  126. }
  127. // Sets the size of the image on the screen
  128. // p: A point, with x as width and y as height in pixels
  129. void Cam3D::setScreenSize(Point p)
  130. {
  131. viewport.width = (float)p.x;
  132. viewport.height = (float)p.y;
  133. updateMatrix();
  134. }
  135. // Sets the size of the image on the screen
  136. // br: The width in pixels
  137. // hoe: The height in pixels
  138. void Cam3D::setScreenSize(int br, int hoe)
  139. {
  140. viewport.width = (float)br;
  141. viewport.height = (float)hoe;
  142. updateMatrix();
  143. }
  144. // Sets the world to be drawn
  145. // w: The world
  146. void Cam3D::setWorld(World3D* w)
  147. {
  148. if (welt) welt->release();
  149. welt = w;
  150. }
  151. // Sets the style of the camera
  152. // style: The new style consisting of the flags from the associated Style
  153. // class
  154. void Cam3D::setStyle(__int64 style)
  155. {
  156. this->style = style;
  157. }
  158. // Sets the style of the camera
  159. // style: All Style Flags to be changed
  160. // add_remove: 1 if the style should be added. 0 if the style
  161. // should be removed
  162. void Cam3D::setStyle(__int64 style, bool add_remove)
  163. {
  164. if (add_remove)
  165. this->style |= style;
  166. else if (!add_remove)
  167. this->style &= ~style;
  168. }
  169. // Adds style flags
  170. // style: The style to be added
  171. void Cam3D::addStyle(__int64 style)
  172. {
  173. this->style |= style;
  174. }
  175. // Removes style flags
  176. // style: The style to be removed
  177. void Cam3D::removeStyle(__int64 style)
  178. {
  179. this->style &= ~style;
  180. }
  181. //! Set the movement speed per second if the camera has style Movable
  182. void Cam3D::setMovementSpeed(float speed)
  183. {
  184. this->speed = speed;
  185. }
  186. // Processes the elapsed time
  187. // tickval: The time in seconds since the last call of the function
  188. // has passed return: true, if the image needs to be redrawn,
  189. // false otherwise.
  190. bool Cam3D::tick(double tv)
  191. {
  192. bool ret = rend;
  193. rend = 0;
  194. if (hasStyle(Style::Rotatable))
  195. {
  196. if (getKeyState(T_Oben))
  197. {
  198. rotX -= (float)tv;
  199. ret = 1;
  200. }
  201. if (getKeyState(T_Unten))
  202. {
  203. rotX += (float)tv;
  204. ret = 1;
  205. }
  206. if (getKeyState(T_Links))
  207. {
  208. rotY -= (float)tv;
  209. ret = 1;
  210. }
  211. if (getKeyState(T_Rechts))
  212. {
  213. rotY += (float)tv;
  214. ret = 1;
  215. }
  216. }
  217. if (hasStyle(Style::Movable))
  218. {
  219. Vec3<float> n(0, 0, 1);
  220. Vec3<float> n2(1, 0, 0);
  221. Vec3<float> n3(0, 1, 0);
  222. Mat4<float> tmp = tmp.rotationY(rotY) * tmp.rotationX(rotX);
  223. n = tmp * n;
  224. n = n * (float)tv * speed;
  225. n2 = tmp * n2;
  226. n2 = n2 * (float)tv * speed;
  227. n3 = tmp * n3;
  228. n3 = n3 * (float)tv * speed;
  229. if (getKeyState('W'))
  230. {
  231. pos += n;
  232. ret = 1;
  233. }
  234. if (getKeyState('S'))
  235. {
  236. pos -= n;
  237. ret = 1;
  238. }
  239. if (getKeyState('D'))
  240. {
  241. pos += n2;
  242. ret = 1;
  243. }
  244. if (getKeyState('A'))
  245. {
  246. pos -= n2;
  247. ret = 1;
  248. }
  249. if (getKeyState(' '))
  250. {
  251. pos += n3;
  252. ret = 1;
  253. }
  254. if (getKeyState(T_Shift))
  255. {
  256. pos -= n3;
  257. ret = 1;
  258. }
  259. }
  260. updateMatrix();
  261. if (welt && hasStyle(Style::Tick)) return welt->tick(tv) || ret;
  262. return ret;
  263. }
  264. // Processes a mouse event
  265. // me: The mouse event to be processed
  266. void Cam3D::doMouseEvent(MouseEvent& me)
  267. {
  268. if (me.processed) return;
  269. if (me.mx > viewport.x && me.my > viewport.y
  270. && me.mx < viewport.x + viewport.width
  271. && me.my < viewport.y + viewport.height)
  272. {
  273. MouseEvent3D me3d;
  274. me3d.id = me.id;
  275. me3d.processed = me.processed;
  276. Vec3<float> mouseP
  277. = Vec3<float>((me.mx - viewport.x) / (0.5f * viewport.width) - 1,
  278. (me.my - viewport.y) / (0.5f * viewport.height) - 1,
  279. 0);
  280. Vec3<float> mouseT = Vec3<float>(mouseP.x, mouseP.y, 1);
  281. Mat4<float> mat = proj * view;
  282. mat = mat.getInverse();
  283. mouseP = mat * mouseP;
  284. mouseT = mat * mouseT;
  285. me3d.pos = mouseP;
  286. me3d.dir = mouseT - mouseP;
  287. me.processed = 1;
  288. }
  289. }
  290. // Processes a keyboard event
  291. // te: The keyboard event to be processed
  292. void Cam3D::doKeyboardEvent(KeyboardEvent& te) {}
  293. // Returns whether certain styles are set
  294. // style: The styles to be checked
  295. // return: 1, if all styles in style are set
  296. bool Cam3D::hasStyle(__int64 style) const
  297. {
  298. return (this->style | style) == this->style;
  299. }
  300. // Returns whether certain styles are not set
  301. // style: The styles to be checked
  302. // return: 1, if all styles in style are not set
  303. bool Cam3D::hasStyleNot(__int64 style) const
  304. {
  305. return (this->style | style) != this->style;
  306. }
  307. // Returns a pointer to the viewport
  308. const ViewPort* Cam3D::zViewPort() const
  309. {
  310. return &viewport;
  311. }
  312. // Returns the position of the camera in the world
  313. const Vec3<float>& Cam3D::getWorldPosition() const
  314. {
  315. return pos;
  316. }
  317. // Returns the position in the world
  318. // screen: the screen position to be translated
  319. const Vec3<float> Cam3D::getWorldPosition(Point screen) const
  320. {
  321. Vec3<float> point = Vec3<float>(
  322. (screen.x - viewport.x) / (0.5f * viewport.width) - 1,
  323. (viewport.height - (screen.y - viewport.y)) / (0.5f * viewport.height)
  324. - 1,
  325. 0.1f);
  326. Mat4<float> mat = getProjectionMatrix();
  327. Mat4<float> inv = getViewMatrix().getInverse();
  328. point.x = (point.x * 0.1f) / mat.elements[0][0];
  329. point.y = (point.y * 0.1f) / mat.elements[1][1];
  330. return inv * point;
  331. }
  332. // Returns the direction of the camera in the world
  333. // screen: the screen position to be translated
  334. const Vec3<float> Cam3D::getWorldDirection(Point screen) const
  335. {
  336. Vec3<float> point = Vec3<float>(
  337. (screen.x - viewport.x) / (0.5f * viewport.width) - 1,
  338. (viewport.height - (screen.y - viewport.y)) / (0.5f * viewport.height)
  339. - 1,
  340. 0.1f);
  341. Vec3<float> pointT = Vec3<float>(point.x, point.y, 1);
  342. Mat4<float> mat = getProjectionMatrix();
  343. Mat4<float> inv = getViewMatrix().getInverse();
  344. point.x = (point.x * 0.1f) / mat.elements[0][0];
  345. point.y = (point.y * 0.1f) / mat.elements[1][1];
  346. pointT.x = (pointT.x) / mat.elements[0][0];
  347. pointT.y = (pointT.y) / mat.elements[1][1];
  348. point = inv * point;
  349. pointT = inv * pointT;
  350. return pointT - point;
  351. }
  352. // Returns the projection matrix of the camera
  353. const Mat4<float>& Cam3D::getProjectionMatrix() const
  354. {
  355. return proj;
  356. }
  357. // Returns the view matrix of the camera
  358. const Mat4<float>& Cam3D::getViewMatrix() const
  359. {
  360. return view;
  361. }
  362. const Mat4<float>& Framework::Cam3D::getInverseViewMatrix() const
  363. {
  364. return inverseView;
  365. }
  366. const Mat4<float>& Framework::Cam3D::getInverseProjectionMatrix() const
  367. {
  368. return inverseProj;
  369. }
  370. //! Returns the rotation around each axis
  371. const Vec3<float> Cam3D::getRotation() const
  372. {
  373. return {rotX, rotY, rotZ};
  374. }
  375. //! Returns the position of the camera on the screen
  376. const Point Cam3D::getScreenPos() const
  377. {
  378. return Point((int)viewport.x, (int)viewport.y);
  379. }
  380. //! Returns the size of the camera on the screen
  381. const Point Cam3D::getScreenSize() const
  382. {
  383. return Point((int)viewport.width, (int)viewport.height);
  384. }
  385. // Returns the world
  386. World3D* Cam3D::getWorld() const
  387. {
  388. return welt ? dynamic_cast<World3D*>(welt->getThis()) : 0;
  389. }
  390. // Returns the world
  391. World3D* Cam3D::zWorld() const
  392. {
  393. return welt;
  394. }
  395. void Framework::Cam3D::setMinDistance(float dist)
  396. {
  397. this->minZ = dist;
  398. updateMatrix();
  399. }
  400. float Framework::Cam3D::getMinDistance() const
  401. {
  402. return minZ;
  403. }
  404. void Framework::Cam3D::setMaxDistance(float dist)
  405. {
  406. this->maxZ = dist;
  407. updateMatrix();
  408. }
  409. float Framework::Cam3D::getMaxDistance() const
  410. {
  411. return maxZ;
  412. }