/source/octoon/transform_component.cpp

https://github.com/octoon/octoon
C++ | 577 lines | 479 code | 98 blank | 0 comment | 31 complexity | 66b733cdb196cba3b5fd9fc1b6de768a MD5 | raw file
  1. #include <octoon/transform_component.h>
  2. namespace octoon
  3. {
  4. OctoonImplementSubClass(TransformComponent, GameComponent, "TransformComponent")
  5. TransformComponent::TransformComponent() noexcept
  6. : scaling_(math::float3::One)
  7. , translate_(math::float3::Zero)
  8. , euler_angles_(math::float3::Zero)
  9. , rotation_(math::Quaternion::Zero)
  10. , local_scaling_(math::float3::One)
  11. , local_translate_(math::float3::Zero)
  12. , local_euler_angles_(math::float3::Zero)
  13. , local_rotation_(math::Quaternion::Zero)
  14. , local_need_updates_(true)
  15. , world_need_updates_(true)
  16. , allowRelativeMotion_(true)
  17. {
  18. }
  19. TransformComponent::~TransformComponent()
  20. {
  21. }
  22. void
  23. TransformComponent::setTranslate(const math::float3& pos) noexcept
  24. {
  25. if (translate_ != pos)
  26. {
  27. this->onMoveBefore();
  28. translate_ = pos;
  29. world_need_updates_ = true;
  30. this->updateWorldChildren();
  31. this->onMoveAfter();
  32. }
  33. }
  34. void
  35. TransformComponent::setTranslateAccum(const math::float3& v) noexcept
  36. {
  37. this->setTranslate(translate_ + v);
  38. }
  39. const math::float3&
  40. TransformComponent::getTranslate() const noexcept
  41. {
  42. updateWorldTransform();
  43. return translate_;
  44. }
  45. void
  46. TransformComponent::setScale(const math::float3& pos) noexcept
  47. {
  48. if (scaling_ != pos)
  49. {
  50. this->onMoveBefore();
  51. scaling_ = pos;
  52. world_need_updates_ = true;
  53. this->updateWorldChildren();
  54. this->onMoveAfter();
  55. }
  56. }
  57. void
  58. TransformComponent::setScaleAccum(const math::float3& scale) noexcept
  59. {
  60. this->setScale(scaling_ + scale);
  61. }
  62. const math::float3&
  63. TransformComponent::getScale() const noexcept
  64. {
  65. updateWorldTransform();
  66. return scaling_;
  67. }
  68. void
  69. TransformComponent::setQuaternion(const math::Quaternion& quat) noexcept
  70. {
  71. assert(math::abs(math::length(quat) - 1) < 1e-2f);
  72. if (rotation_ != quat)
  73. {
  74. this->onMoveBefore();
  75. rotation_ = quat;
  76. euler_angles_ = math::eulerAngles(quat);
  77. world_need_updates_ = true;
  78. this->updateWorldChildren();
  79. this->onMoveAfter();
  80. }
  81. }
  82. void
  83. TransformComponent::setQuaternionAccum(const math::Quaternion& quat) noexcept
  84. {
  85. assert(math::abs(math::length(quat) - 1) < 1e-2f);
  86. this->setQuaternion(math::normalize(this->getQuaternion() * quat));
  87. }
  88. const math::Quaternion&
  89. TransformComponent::getQuaternion() const noexcept
  90. {
  91. updateWorldTransform();
  92. return rotation_;
  93. }
  94. void
  95. TransformComponent::setEulerAngles(const math::float3& euler) noexcept
  96. {
  97. assert(math::isfinite(euler));
  98. if (euler_angles_ != euler)
  99. {
  100. this->onMoveBefore();
  101. euler_angles_ = euler;
  102. rotation_ = math::normalize(math::Quaternion(euler));
  103. world_need_updates_ = true;
  104. this->updateWorldChildren();
  105. this->onMoveAfter();
  106. }
  107. }
  108. const math::float3&
  109. TransformComponent::getEulerAngles() const noexcept
  110. {
  111. updateWorldTransform();
  112. return euler_angles_;
  113. }
  114. void
  115. TransformComponent::setTransform(const math::float4x4& transform) noexcept
  116. {
  117. this->onMoveBefore();
  118. transform_ = transform.getTransform(translate_, rotation_, scaling_);
  119. transform_inverse_ = math::transformInverse(transform_);
  120. euler_angles_ = math::eulerAngles(rotation_);
  121. world_need_updates_ = false;
  122. this->updateWorldChildren();
  123. this->onMoveAfter();
  124. }
  125. void
  126. TransformComponent::setTransform(const math::float3& translate, const math::Quaternion& quat, const math::float3& scale) noexcept
  127. {
  128. assert(math::abs(math::length(quat) - 1) < 1e-2f);
  129. if (translate != translate_ || rotation_ != quat || scale != scaling_)
  130. {
  131. this->onMoveBefore();
  132. scaling_ = scale;
  133. rotation_ = quat;
  134. translate_ = translate;
  135. euler_angles_ = math::eulerAngles(rotation_);
  136. world_need_updates_ = true;
  137. this->updateWorldChildren();
  138. this->onMoveAfter();
  139. }
  140. }
  141. void
  142. TransformComponent::setTransformOnlyRotate(const math::float4x4& transform) noexcept
  143. {
  144. this->onMoveBefore();
  145. transform_ = transform.getTransformWithoutScaler(translate_, rotation_);
  146. transform_.scale(scaling_);
  147. transform_inverse_ = math::transformInverse(transform_);
  148. euler_angles_ = math::eulerAngles(rotation_);
  149. world_need_updates_ = false;
  150. this->updateWorldChildren();
  151. this->onMoveAfter();
  152. }
  153. const math::float4x4&
  154. TransformComponent::getTransform() const noexcept
  155. {
  156. this->updateWorldTransform();
  157. return transform_;
  158. }
  159. const math::float4x4&
  160. TransformComponent::getTransformInverse() const noexcept
  161. {
  162. this->updateWorldTransform();
  163. return transform_inverse_;
  164. }
  165. const math::float3&
  166. TransformComponent::getRight() const noexcept
  167. {
  168. updateWorldTransform();
  169. return math::right(transform_);
  170. }
  171. const math::float3&
  172. TransformComponent::getUp() const noexcept
  173. {
  174. updateWorldTransform();
  175. return math::up(transform_);
  176. }
  177. const math::float3&
  178. TransformComponent::getForward() const noexcept
  179. {
  180. updateWorldTransform();
  181. return math::forward(transform_);
  182. }
  183. void
  184. TransformComponent::setLocalTranslate(const math::float3& pos) noexcept
  185. {
  186. if (local_translate_ != pos)
  187. {
  188. this->onMoveBefore();
  189. local_translate_ = pos;
  190. local_need_updates_ = true;
  191. this->updateLocalChildren();
  192. this->onMoveAfter();
  193. }
  194. }
  195. void
  196. TransformComponent::setLocalTranslateAccum(const math::float3& v) noexcept
  197. {
  198. this->setLocalTranslate(local_translate_ + v);
  199. }
  200. const math::float3&
  201. TransformComponent::getLocalTranslate() const noexcept
  202. {
  203. updateLocalTransform();
  204. return local_translate_;
  205. }
  206. void
  207. TransformComponent::setLocalScale(const math::float3& scale) noexcept
  208. {
  209. if (local_scaling_ != scale)
  210. {
  211. this->onMoveBefore();
  212. local_scaling_ = scale;
  213. local_need_updates_ = true;
  214. this->updateLocalChildren();
  215. this->onMoveAfter();
  216. }
  217. }
  218. void
  219. TransformComponent::setLocalScaleAll(const float scale) noexcept
  220. {
  221. this->setLocalScale(math::float3(scale, scale, scale));
  222. }
  223. void
  224. TransformComponent::setLocalScaleAccum(const math::float3& scale) noexcept
  225. {
  226. this->setLocalScale(local_scaling_ + scale);
  227. }
  228. const math::float3&
  229. TransformComponent::getLocalScale() const noexcept
  230. {
  231. updateLocalTransform();
  232. return local_scaling_;
  233. }
  234. void
  235. TransformComponent::setLocalQuaternion(const math::Quaternion& quat) noexcept
  236. {
  237. assert(math::abs(math::length(quat) - 1) < 1e-2f);
  238. if (local_rotation_ != quat)
  239. {
  240. this->onMoveBefore();
  241. local_rotation_ = quat;
  242. local_euler_angles_ = math::eulerAngles(quat);
  243. local_need_updates_ = true;
  244. this->updateLocalChildren();
  245. this->onMoveAfter();
  246. }
  247. }
  248. void
  249. TransformComponent::setLocalQuaternionAccum(const math::Quaternion& quat) noexcept
  250. {
  251. assert(math::abs(math::length(quat) - 1) < 1e-2f);
  252. this->setLocalQuaternion(math::normalize(this->getLocalQuaternion() * quat));
  253. }
  254. const math::Quaternion&
  255. TransformComponent::getLocalQuaternion() const noexcept
  256. {
  257. updateLocalTransform();
  258. return local_rotation_;
  259. }
  260. void
  261. TransformComponent::setLocalEulerAngles(const math::float3& euler) noexcept
  262. {
  263. assert(math::isfinite(euler));
  264. if (this->local_euler_angles_ != euler)
  265. {
  266. this->onMoveBefore();
  267. local_euler_angles_ = euler;
  268. local_rotation_ = math::normalize(math::Quaternion(euler));
  269. local_need_updates_ = true;
  270. this->updateLocalChildren();
  271. this->onMoveAfter();
  272. }
  273. }
  274. const math::float3&
  275. TransformComponent::getLocalEulerAngles() const noexcept
  276. {
  277. updateLocalTransform();
  278. return this->local_euler_angles_;
  279. }
  280. void
  281. TransformComponent::setLocalTransform(const math::float4x4& transform) noexcept
  282. {
  283. this->onMoveBefore();
  284. local_transform_ = transform.getTransform(local_translate_, local_rotation_, local_scaling_);
  285. local_need_updates_ = false;
  286. euler_angles_ = math::eulerAngles(rotation_);
  287. this->updateLocalChildren();
  288. this->onMoveAfter();
  289. }
  290. void
  291. TransformComponent::setLocalTransformOnlyRotate(const math::float4x4& transform) noexcept
  292. {
  293. this->onMoveBefore();
  294. local_transform_ = transform.getTransformWithoutScaler(local_translate_, local_rotation_);
  295. local_transform_.scale(local_scaling_);
  296. local_need_updates_ = false;
  297. euler_angles_ = math::eulerAngles(rotation_);
  298. this->updateLocalChildren();
  299. this->onMoveAfter();
  300. }
  301. const math::float4x4&
  302. TransformComponent::getLocalTransform() const noexcept
  303. {
  304. this->updateLocalTransform();
  305. return local_transform_;
  306. }
  307. const math::float4x4&
  308. TransformComponent::getLocalTransformInverse() const noexcept
  309. {
  310. this->updateLocalTransform();
  311. return local_transform_inverse_;
  312. }
  313. const math::float3&
  314. TransformComponent::getLocalRight() const noexcept
  315. {
  316. updateLocalTransform();
  317. return math::right(local_transform_);
  318. }
  319. const math::float3&
  320. TransformComponent::getLocalUp() const noexcept
  321. {
  322. updateLocalTransform();
  323. return math::up(local_transform_);
  324. }
  325. const math::float3&
  326. TransformComponent::getLocalForward() const noexcept
  327. {
  328. updateLocalTransform();
  329. return math::forward(local_transform_);
  330. }
  331. void
  332. TransformComponent::up(float speed) noexcept
  333. {
  334. this->setLocalTranslateAccum(this->getLocalUp() * speed);
  335. }
  336. void
  337. TransformComponent::up(const math::float3& speed) noexcept
  338. {
  339. this->setLocalTranslateAccum(this->getLocalUp() * speed);
  340. }
  341. void
  342. TransformComponent::yaw(float speed) noexcept
  343. {
  344. this->setLocalTranslateAccum(this->getLocalRight() * speed);
  345. }
  346. void
  347. TransformComponent::yaw(const math::float3& speed) noexcept
  348. {
  349. this->setLocalTranslateAccum(this->getLocalRight() * speed);
  350. }
  351. void
  352. TransformComponent::move(float speed) noexcept
  353. {
  354. this->setLocalTranslateAccum(this->getLocalForward() * speed);
  355. }
  356. void
  357. TransformComponent::move(const math::float3& speed) noexcept
  358. {
  359. this->setLocalTranslateAccum(this->getLocalForward() * speed);
  360. }
  361. void
  362. TransformComponent::setAllowRelativeMotion(bool enable) noexcept
  363. {
  364. allowRelativeMotion_ = enable;
  365. }
  366. bool
  367. TransformComponent::isAllowRelativeMotion() const noexcept
  368. {
  369. return allowRelativeMotion_;
  370. }
  371. GameComponentPtr
  372. TransformComponent::clone() const noexcept
  373. {
  374. auto component = std::make_shared<TransformComponent>();
  375. component->setName(this->getName());
  376. component->setLocalScale(this->getLocalScale());
  377. component->setLocalTranslate(this->getLocalTranslate());
  378. component->setLocalQuaternion(this->getLocalQuaternion());
  379. return component;
  380. }
  381. void
  382. TransformComponent::onMoveBefore() except
  383. {
  384. if (this->getGameObject())
  385. this->getGameObject()->onMoveBefore();
  386. }
  387. void
  388. TransformComponent::onMoveAfter() except
  389. {
  390. if (this->getGameObject())
  391. this->getGameObject()->onMoveAfter();
  392. }
  393. void
  394. TransformComponent::updateLocalChildren() const noexcept
  395. {
  396. world_need_updates_ = true;
  397. for (auto& it : this->getGameObject()->getChildren())
  398. it->getComponent<TransformComponent>()->updateLocalChildren();
  399. }
  400. void
  401. TransformComponent::updateWorldChildren() const noexcept
  402. {
  403. this->updateParentTransform();
  404. this->updateLocalChildren();
  405. world_need_updates_ = false;
  406. }
  407. void
  408. TransformComponent::updateLocalTransform() const noexcept
  409. {
  410. if (local_need_updates_)
  411. {
  412. local_transform_.makeTransform(local_translate_, local_rotation_, local_scaling_);
  413. local_transform_inverse_ = math::transformInverse(local_transform_);
  414. local_need_updates_ = false;
  415. }
  416. }
  417. void
  418. TransformComponent::updateWorldTransform() const noexcept
  419. {
  420. if (world_need_updates_)
  421. {
  422. if (this->isAllowRelativeMotion())
  423. {
  424. this->updateLocalTransform();
  425. auto parent = this->getGameObject()->getParent();
  426. if (parent)
  427. {
  428. auto& baseTransform = parent->getComponent<TransformComponent>()->getTransform();
  429. transform_ = math::transformMultiply(baseTransform, local_transform_);
  430. transform_.getTransform(translate_, rotation_, scaling_);
  431. transform_inverse_ = math::transformInverse(transform_);
  432. euler_angles_ = math::eulerAngles(rotation_);
  433. }
  434. else
  435. {
  436. translate_ = local_translate_;
  437. scaling_ = local_scaling_;
  438. euler_angles_ = local_euler_angles_;
  439. rotation_ = local_rotation_;
  440. transform_ = local_transform_;
  441. transform_inverse_ = local_transform_inverse_;
  442. }
  443. }
  444. else
  445. {
  446. this->updateParentTransform();
  447. }
  448. world_need_updates_ = false;
  449. }
  450. }
  451. void
  452. TransformComponent::updateParentTransform() const noexcept
  453. {
  454. if (world_need_updates_)
  455. {
  456. transform_.makeTransform(translate_, rotation_, scaling_);
  457. transform_inverse_ = math::transformInverse(transform_);
  458. world_need_updates_ = false;
  459. }
  460. auto parent = this->getGameObject()->getParent();
  461. if (parent)
  462. {
  463. auto& baseTransformInverse = parent->getComponent<TransformComponent>()->getTransformInverse();
  464. local_transform_ = math::transformMultiply(baseTransformInverse, transform_);
  465. local_transform_.getTransform(local_translate_, local_rotation_, local_scaling_);
  466. local_transform_inverse_ = math::transformInverse(local_transform_);
  467. local_euler_angles_ = math::eulerAngles(local_rotation_);
  468. }
  469. else
  470. {
  471. local_scaling_ = scaling_;
  472. local_rotation_ = rotation_;
  473. local_translate_ = translate_;
  474. local_euler_angles_ = euler_angles_;
  475. local_transform_ = transform_;
  476. local_transform_inverse_ = transform_inverse_;
  477. }
  478. }
  479. }