camera.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848
  1. #include "pch.h"
  2. //////////////////////////////////////////////////////////////////////////////
  3. //
  4. // Camera
  5. //
  6. //////////////////////////////////////////////////////////////////////////////
  7. Camera::Camera() :
  8. Value(
  9. new VectorValue(
  10. Vector(
  11. 0, 0, 0
  12. )
  13. ),
  14. new OrientationValue(
  15. Orientation(
  16. Vector(0, 0, -1),
  17. Vector(0, 1, 0)
  18. )
  19. )
  20. ),
  21. m_znear(-1),
  22. m_zfar(1),
  23. m_focus(0),
  24. m_bInverseValid(false)
  25. {
  26. }
  27. const Vector& Camera::GetPosition()
  28. {
  29. return GetPositionValue()->GetValue();
  30. }
  31. const Orientation& Camera::GetOrientation()
  32. {
  33. return GetOrientationValue()->GetValue();
  34. }
  35. void Camera::Evaluate()
  36. {
  37. if (m_focus == 0) {
  38. //
  39. // orthoganal projection
  40. //
  41. // : what is m_focus for an orthogonal camera?
  42. //
  43. // 1) xscreen = x
  44. // 2) zbuffer = a * z + b
  45. //
  46. // 3) 0 = a * znear + b
  47. // 4) 1 = a * zfar + b
  48. // 5) 3 => b = -a * znear
  49. // 6) 4,5 => 1 = a * zfar - a * znear
  50. // a = 1 / (zfar - znear)
  51. //
  52. float a = 1 / (m_zfar - m_znear);
  53. float b = -a * m_znear;
  54. m_matPerspective.SetIdentity();
  55. m_matPerspective.Set(2, 2, a);
  56. m_matPerspective.Set(2, 3, b);
  57. } else {
  58. //
  59. // perspective projection
  60. //
  61. //
  62. // 1) xscreen = f * x / -z
  63. // 2) zbuffer = (a * z + b) / -z
  64. //
  65. // 3) 0 = (a * znear + b) / -znear
  66. // 4) 1 = (a * zfar + b) / -zfar
  67. // 5) 3 => b = -a * znear
  68. // 6) 4,5 => -zfar = a * zfar - a * znear
  69. // a = zfar / (znear - zfar)
  70. //
  71. //
  72. float a = m_zfar / (m_znear - m_zfar);
  73. float b = -a * m_znear;
  74. m_matPerspective.SetIdentity();
  75. m_matPerspective.Set(0, 0, m_focus);
  76. m_matPerspective.Set(1, 1, m_focus);
  77. m_matPerspective.Set(2, 2, a);
  78. m_matPerspective.Set(2, 3, b);
  79. m_matPerspective.Set(3, 2, -1);
  80. m_matPerspective.Set(3, 3, 0);
  81. }
  82. const Vector& v = GetPosition();
  83. const Orientation& o = GetOrientation();
  84. m_matModel =
  85. Matrix(
  86. o[0][0], o[0][1], o[0][2], 0,
  87. o[1][0], o[1][1], o[1][2], 0,
  88. o[2][0], o[2][1], o[2][2], 0
  89. );
  90. m_matModel.PreTranslate(-v);
  91. m_bInverseValid = false;
  92. }
  93. void Camera::UpdateInverse()
  94. {
  95. if (!m_bInverseValid) {
  96. m_matInverseModel.SetInverse(m_matModel);
  97. }
  98. }
  99. void Camera::SetPosition(const Vector& vec)
  100. {
  101. SetPositionValue(new VectorValue(vec));
  102. }
  103. void Camera::SetOrientation(const Orientation& orientation)
  104. {
  105. SetOrientationValue(new OrientationValue(orientation));
  106. }
  107. void Camera::SetZClip(float znear, float zfar)
  108. {
  109. m_znear = -znear;
  110. m_zfar = -zfar;
  111. Changed();
  112. }
  113. void Camera::SetOrthogonal()
  114. {
  115. m_focus = 0;
  116. Changed();
  117. }
  118. void Camera::SetPerspective(float f)
  119. {
  120. m_focus = f;
  121. Changed();
  122. }
  123. void Camera::SetFOV(float fov)
  124. {
  125. m_fov = fov;
  126. SetPerspective(cos(0.5f * fov) / sin(0.5f * fov));
  127. }
  128. Vector Camera::TransformLocalToEye(const Vector& vec)
  129. {
  130. return GetModelMatrix().Transform(vec);
  131. }
  132. bool Camera::TransformEyeToImage(const Vector& vecEye, Point& point)
  133. {
  134. if (GetFocus() == 0) {
  135. point = Point(vecEye.X(), vecEye.Y());
  136. } else {
  137. if (vecEye.Z() >= 0) {
  138. return false;
  139. }
  140. point = Point(vecEye.X(), vecEye.Y()) * (GetFocus() / -vecEye.Z());
  141. }
  142. return true;
  143. }
  144. bool Camera::TransformLocalToImage(const Vector& vec, Point& point)
  145. {
  146. return TransformEyeToImage(TransformLocalToEye(vec), point);
  147. }
  148. bool Camera::TransformDirectionToImage(const Vector& vec, Point& point)
  149. {
  150. HVector hvec = GetModelMatrix().Transform(HVector(vec.X(), vec.Y(), vec.Z(), 0));
  151. return TransformEyeToImage(Vector(hvec.X(), hvec.Y(), hvec.Z()), point);
  152. }
  153. Vector Camera::TransformImageToDirection(const Point& point)
  154. {
  155. UpdateInverse();
  156. HVector hvec = m_matInverseModel.Transform(HVector(point.X(), point.Y(), -GetFocus(), 0));
  157. return Vector(hvec.X(), hvec.Y(), hvec.Z());
  158. }
  159. //////////////////////////////////////////////////////////////////////////////
  160. //
  161. // MotionCamera
  162. //
  163. //////////////////////////////////////////////////////////////////////////////
  164. class MotionCamera : public Value, public IKeyboardInput {
  165. private:
  166. //////////////////////////////////////////////////////////////////////////////
  167. //
  168. // Types
  169. //
  170. //////////////////////////////////////////////////////////////////////////////
  171. class MotionCameraImage : public Image {
  172. TRef<MotionCamera> m_pcamera;
  173. public:
  174. MotionCameraImage(MotionCamera* pcamera) :
  175. m_pcamera(pcamera)
  176. {
  177. }
  178. MouseResult HitTest(IInputProvider* pprovider, const Point& point, bool bCaptured)
  179. {
  180. return MouseResultHit();
  181. }
  182. void MouseMove(IInputProvider* pprovider, const Point& point, bool bCaptured, bool bInside)
  183. {
  184. m_pcamera->MouseMove(pprovider, point, bCaptured, bInside);
  185. }
  186. MouseResult Button(IInputProvider* pprovider, const Point& point, int button, bool bCaptured, bool bInside, bool bDown)
  187. {
  188. return m_pcamera->Button(pprovider, point, button, bCaptured, bInside, bDown);
  189. }
  190. //
  191. // Value members
  192. //
  193. ZString GetFunctionName() { return "MotionCameraImage"; }
  194. };
  195. class MotionVector : public VectorValue {
  196. MotionCamera* GetMotionCamera() { return MotionCamera::Cast(GetChild(0)); };
  197. public:
  198. MotionVector(MotionCamera* pmotionCamera) :
  199. VectorValue(pmotionCamera)
  200. {
  201. }
  202. //
  203. // Value members
  204. //
  205. void Evaluate()
  206. {
  207. GetValueInternal() = GetMotionCamera()->m_position;
  208. }
  209. };
  210. class MotionOrientation : public OrientationValue {
  211. MotionCamera* GetMotionCamera() { return MotionCamera::Cast(GetChild(0)); };
  212. public:
  213. MotionOrientation(MotionCamera* pmotionCamera) :
  214. OrientationValue(pmotionCamera)
  215. {
  216. }
  217. //
  218. // Value members
  219. //
  220. void Evaluate()
  221. {
  222. GetValueInternal() = GetMotionCamera()->m_orient;
  223. }
  224. };
  225. friend class MotionVector;
  226. friend class MotionOrientation;
  227. //////////////////////////////////////////////////////////////////////////////
  228. //
  229. // members
  230. //
  231. //////////////////////////////////////////////////////////////////////////////
  232. float m_timeLast;
  233. Vector m_position;
  234. Orientation m_orientLast;
  235. Orientation m_orient;
  236. float m_speed;
  237. float m_angleRoll;
  238. float m_angleYaw;
  239. float m_anglePitch;
  240. bool m_bForward;
  241. bool m_bBackward;
  242. bool m_bLeft;
  243. bool m_bRight;
  244. bool m_bUp;
  245. bool m_bDown;
  246. bool m_bAccelerate;
  247. bool m_bLeftButtonDown;
  248. bool m_bRightButtonDown;
  249. Point m_pointStart;
  250. float GetTime() { return Number::Cast(GetChild(0))->GetValue(); }
  251. public:
  252. DefineCastMember(MotionCamera);
  253. MotionCamera(
  254. const Vector& vec,
  255. Number* ptime,
  256. TRef<Image>& pimage,
  257. TRef<VectorValue>& pvectorValue,
  258. TRef<OrientationValue>& porientationValue
  259. ) :
  260. Value(ptime),
  261. m_position(vec)
  262. {
  263. pimage = new MotionCameraImage(this);
  264. pvectorValue = new MotionVector(this);
  265. porientationValue = new MotionOrientation(this);
  266. m_timeLast = ptime->GetValue();
  267. m_anglePitch = 0;
  268. m_angleYaw = 0;
  269. m_angleRoll = 0;
  270. m_speed = 0;
  271. m_bForward = false;
  272. m_bBackward = false;
  273. m_bLeft = false;
  274. m_bRight = false;
  275. m_bUp = false;
  276. m_bDown = false;
  277. m_bAccelerate = false;
  278. m_bLeftButtonDown = false;
  279. m_bRightButtonDown = false;
  280. }
  281. //////////////////////////////////////////////////////////////////////////////
  282. //
  283. // IKeboardInput Methods
  284. //
  285. //////////////////////////////////////////////////////////////////////////////
  286. bool OnKey(IInputProvider* pprovider, const KeyState& ks, bool& fForceTranslate)
  287. {
  288. switch (ks.vk) {
  289. case 'W' : m_bForward = ks.bDown; return true;
  290. case 'S' : m_bBackward = ks.bDown; return true;
  291. case 'A' : m_bLeft = ks.bDown; return true;
  292. case 'D' : m_bRight = ks.bDown; return true;
  293. case 'E' : m_bUp = ks.bDown; return true;
  294. case 'Q' : m_bDown = ks.bDown; return true;
  295. case VK_SHIFT : m_bAccelerate = ks.bDown; return true;
  296. }
  297. return false;
  298. }
  299. void MouseDown(IInputProvider* pprovider, const Point& point)
  300. {
  301. ZAssert(m_angleYaw == 0);
  302. m_angleRoll = 0;
  303. m_angleYaw = 0;
  304. m_anglePitch = 0;
  305. m_pointStart = point;
  306. //pprovider->ShowCursor(false);
  307. }
  308. void MouseUp(IInputProvider* pprovider)
  309. {
  310. m_orientLast = m_orient;
  311. m_bLeftButtonDown = false;
  312. m_bRightButtonDown = false;
  313. m_angleRoll = 0;
  314. m_angleYaw = 0;
  315. m_anglePitch = 0;
  316. //pprovider->SetCursorPos(m_pointStart);
  317. //pprovider->ShowCursor(true);
  318. }
  319. //////////////////////////////////////////////////////////////////////////////
  320. //
  321. // IMouseInput Methods
  322. //
  323. //////////////////////////////////////////////////////////////////////////////
  324. void MouseMove(IInputProvider* pprovider, const Point& point, bool bCaptured, bool bInside)
  325. {
  326. if (bCaptured) {
  327. if (point != m_pointStart) {
  328. float scale = 0.0025f;
  329. float dx = scale * (point.X() - m_pointStart.X());
  330. float dy = scale * (point.Y() - m_pointStart.Y());
  331. if (m_bRightButtonDown) {
  332. m_angleRoll -= dx;
  333. } else {
  334. m_angleYaw -= dx;
  335. m_anglePitch =
  336. bound(
  337. m_anglePitch + dy,
  338. -pi/2,
  339. pi/2
  340. );
  341. }
  342. pprovider->SetCursorPos(m_pointStart);
  343. Changed();
  344. }
  345. }
  346. }
  347. MouseResult Button(IInputProvider* pprovider, const Point& point, int button, bool bCaptured, bool bInside, bool bDown)
  348. {
  349. switch (button) {
  350. case 0:
  351. if (bDown) {
  352. if (!m_bRightButtonDown) {
  353. m_bLeftButtonDown = true;
  354. MouseDown(pprovider, point);
  355. return MouseResultCapture();
  356. }
  357. } else {
  358. if (m_bLeftButtonDown) {
  359. m_bLeftButtonDown = false;
  360. MouseUp(pprovider);
  361. return MouseResultRelease();
  362. }
  363. }
  364. break;
  365. case 1:
  366. if (bDown) {
  367. if (!m_bLeftButtonDown) {
  368. m_bRightButtonDown = true;
  369. MouseDown(pprovider, point);
  370. return MouseResultCapture();
  371. }
  372. } else {
  373. if (m_bRightButtonDown) {
  374. m_bRightButtonDown = false;
  375. MouseUp(pprovider);
  376. return MouseResultRelease();
  377. }
  378. }
  379. break;
  380. }
  381. return MouseResult();
  382. }
  383. //////////////////////////////////////////////////////////////////////////////
  384. //
  385. // Value methods
  386. //
  387. //////////////////////////////////////////////////////////////////////////////
  388. void Evaluate()
  389. {
  390. float time = GetTime();
  391. float dtime = time - m_timeLast;
  392. m_timeLast = time;
  393. //
  394. // The orientation
  395. //
  396. m_orient = m_orientLast;
  397. if (m_bLeftButtonDown || m_bRightButtonDown) {
  398. m_orient.Yaw(m_angleYaw);
  399. m_orient.Pitch(m_anglePitch);
  400. m_orient.Roll(m_angleRoll);
  401. }
  402. //
  403. // The position
  404. //
  405. Vector vecDPos(0, 0, 0);
  406. if (m_bForward) {
  407. vecDPos -= m_orient.GetBackward() * dtime;
  408. }
  409. if (m_bBackward) {
  410. vecDPos += m_orient.GetBackward() * dtime;
  411. }
  412. if (m_bRight) {
  413. vecDPos += m_orient.GetRight() * dtime;
  414. }
  415. if (m_bLeft) {
  416. vecDPos -= m_orient.GetRight() * dtime;
  417. }
  418. if (m_bUp) {
  419. vecDPos += m_orient.GetUp() * dtime;
  420. }
  421. if (m_bDown) {
  422. vecDPos -= m_orient.GetUp() * dtime;
  423. }
  424. if (
  425. m_bAccelerate
  426. && (m_bForward || m_bBackward || m_bRight || m_bLeft || m_bUp || m_bDown)
  427. ) {
  428. m_speed *= 1.1f;
  429. if (m_speed > 100) {
  430. m_speed = 100;
  431. }
  432. } else {
  433. m_speed = 10;
  434. }
  435. //
  436. // Setup the camera
  437. //
  438. m_position += vecDPos * m_speed;
  439. }
  440. ZString GetFunctionName() { return "MotionCamera"; }
  441. };
  442. //////////////////////////////////////////////////////////////////////////////
  443. //
  444. // MotionCamera
  445. //
  446. //////////////////////////////////////////////////////////////////////////////
  447. TRef<Camera> CreateMotionCamera(
  448. const Vector& vec,
  449. Number* ptime,
  450. TRef<Image>& pimage,
  451. TRef<IKeyboardInput>& pkeyboardInput
  452. ) {
  453. TRef<VectorValue> pvectorValue;
  454. TRef<OrientationValue> porientationValue;
  455. TRef<MotionCamera> pmotionCamera =
  456. new MotionCamera(
  457. vec,
  458. ptime,
  459. pimage,
  460. pvectorValue,
  461. porientationValue
  462. );
  463. pkeyboardInput = pmotionCamera;
  464. return new Camera(pvectorValue, porientationValue);
  465. }
  466. //////////////////////////////////////////////////////////////////////////////
  467. //
  468. // SmoothPosition
  469. //
  470. //////////////////////////////////////////////////////////////////////////////
  471. class SmoothPosition : public ISmoothPosition {
  472. //////////////////////////////////////////////////////////////////////////////
  473. //
  474. // Types
  475. //
  476. //////////////////////////////////////////////////////////////////////////////
  477. class Data : public IObject {
  478. public:
  479. Vector m_vec;
  480. float m_dtime;
  481. Data(const Vector& vec, float dtime) :
  482. m_vec(vec),
  483. m_dtime(dtime)
  484. {
  485. }
  486. };
  487. typedef TList<TRef<Data> > DataList;
  488. //////////////////////////////////////////////////////////////////////////////
  489. //
  490. // members
  491. //
  492. //////////////////////////////////////////////////////////////////////////////
  493. float GetTime() { return Number::Cast(GetChild(0))->GetValue(); }
  494. DataList m_listData;
  495. Vector m_positionStart;
  496. float m_timeStart;
  497. public:
  498. SmoothPosition(
  499. Number* ptime,
  500. const Vector& vec
  501. ) :
  502. ISmoothPosition(ptime),
  503. m_positionStart(vec),
  504. m_timeStart(0)
  505. {
  506. GetValueInternal() = m_positionStart;
  507. }
  508. void Goto(const Vector& vector, float dtime)
  509. {
  510. if (m_listData.IsEmpty()) {
  511. m_timeStart = GetTime();
  512. }
  513. m_listData.PushEnd(new Data(vector, dtime));
  514. }
  515. //////////////////////////////////////////////////////////////////////////////
  516. //
  517. // Value members
  518. //
  519. //////////////////////////////////////////////////////////////////////////////
  520. void Evaluate()
  521. {
  522. float time = GetTime();
  523. float dtime = time - m_timeStart;
  524. Data* pdata;
  525. while (true) {
  526. if (m_listData.IsEmpty()) {
  527. return;
  528. }
  529. pdata = m_listData.GetFront();
  530. if (dtime <= pdata->m_dtime) {
  531. break;
  532. }
  533. GetValueInternal() = pdata->m_vec;
  534. m_positionStart = pdata->m_vec;
  535. m_timeStart += pdata->m_dtime;
  536. dtime -= pdata->m_dtime;
  537. m_listData.PopFront();
  538. }
  539. GetValueInternal() =
  540. Interpolate(
  541. m_positionStart,
  542. pdata->m_vec,
  543. SmoothInterpolant(dtime / pdata->m_dtime)
  544. );
  545. }
  546. };
  547. TRef<ISmoothPosition> CreateSmoothPosition(Number* ptime, const Vector& vec)
  548. {
  549. return new SmoothPosition(ptime, vec);
  550. }
  551. //////////////////////////////////////////////////////////////////////////////
  552. //
  553. // SmoothOrientation
  554. //
  555. //////////////////////////////////////////////////////////////////////////////
  556. class SmoothOrientation : public ISmoothOrientation
  557. {
  558. //////////////////////////////////////////////////////////////////////////////
  559. //
  560. // Types
  561. //
  562. //////////////////////////////////////////////////////////////////////////////
  563. class Data : public IObject
  564. {
  565. public:
  566. Quaternion m_quaternion;
  567. float m_dtime;
  568. Data(const Orientation& orientation, float dtime)
  569. :
  570. m_quaternion(orientation),
  571. m_dtime(dtime)
  572. {
  573. }
  574. };
  575. typedef TList<TRef<Data> > DataList;
  576. //////////////////////////////////////////////////////////////////////////////
  577. //
  578. // members
  579. //
  580. //////////////////////////////////////////////////////////////////////////////
  581. float GetTime() { return Number::Cast(GetChild(0))->GetValue(); }
  582. DataList m_listData;
  583. Quaternion m_qStart;
  584. float m_timeStart;
  585. public:
  586. SmoothOrientation(Number* ptime,
  587. const Orientation& orientation)
  588. :
  589. ISmoothOrientation(ptime),
  590. m_qStart(orientation),
  591. m_timeStart(0)
  592. {
  593. GetValueInternal() = orientation;
  594. }
  595. void Goto(const Orientation& orientation, float dtime)
  596. {
  597. if (m_listData.IsEmpty())
  598. {
  599. m_timeStart = GetTime();
  600. }
  601. m_listData.PushEnd(new Data(orientation, dtime));
  602. }
  603. //////////////////////////////////////////////////////////////////////////////
  604. //
  605. // Value members
  606. //
  607. //////////////////////////////////////////////////////////////////////////////
  608. void Evaluate()
  609. {
  610. if (m_listData.IsEmpty())
  611. return;
  612. float time = GetTime();
  613. float dtime = time - m_timeStart;
  614. Data* pdata;
  615. while (true)
  616. {
  617. pdata = m_listData.GetFront();
  618. if (dtime <= pdata->m_dtime)
  619. break;
  620. m_qStart = pdata->m_quaternion;
  621. m_timeStart += pdata->m_dtime;
  622. dtime -= pdata->m_dtime;
  623. m_listData.PopFront();
  624. if (m_listData.IsEmpty())
  625. {
  626. GetValueInternal() = m_qStart;
  627. return;
  628. }
  629. }
  630. GetValueInternal() = Slerp(m_qStart, pdata->m_quaternion, dtime / pdata->m_dtime);
  631. }
  632. };
  633. TRef<ISmoothOrientation> CreateSmoothOrientation(Number* ptime, const Orientation& o)
  634. {
  635. return new SmoothOrientation(ptime, o);
  636. }
  637. //////////////////////////////////////////////////////////////////////////////
  638. //
  639. // LookAtOrientation
  640. //
  641. //////////////////////////////////////////////////////////////////////////////
  642. class LookAtOrientation : public OrientationValue {
  643. //////////////////////////////////////////////////////////////////////////////
  644. //
  645. // Arguments
  646. //
  647. //////////////////////////////////////////////////////////////////////////////
  648. const Vector& GetAt() { return VectorValue::Cast(GetChild(0))->GetValue(); }
  649. const Vector& GetFrom() { return VectorValue::Cast(GetChild(1))->GetValue(); }
  650. const Vector& GetUp() { return VectorValue::Cast(GetChild(2))->GetValue(); }
  651. //////////////////////////////////////////////////////////////////////////////
  652. //
  653. // Value members
  654. //
  655. //////////////////////////////////////////////////////////////////////////////
  656. void Evaluate()
  657. {
  658. const Vector& vecAt = GetAt();
  659. const Vector& vecFrom = GetFrom();
  660. const Vector& vecUp = GetUp();
  661. GetValueInternal().Set(
  662. (vecAt - vecFrom).Normalize(),
  663. vecUp
  664. );
  665. }
  666. //////////////////////////////////////////////////////////////////////////////
  667. //
  668. // members
  669. //
  670. //////////////////////////////////////////////////////////////////////////////
  671. public:
  672. LookAtOrientation(
  673. VectorValue* pvectorAt,
  674. VectorValue* pvectorFrom,
  675. VectorValue* pvectorUp
  676. ) :
  677. OrientationValue(
  678. pvectorAt,
  679. pvectorFrom,
  680. pvectorUp
  681. )
  682. {
  683. }
  684. };
  685. TRef<OrientationValue> CreateLookAtOrientation(
  686. VectorValue* pvectorAt,
  687. VectorValue* pvectorFrom,
  688. VectorValue* pvectorUp
  689. ) {
  690. return new LookAtOrientation(pvectorAt, pvectorFrom, pvectorUp);
  691. }