Source: extern/constraints.js

  1. import register from "../util/register.js";
  2. import m_cam_fact from "../intern/camera.js";
  3. import m_cons_fact from "../intern/constraints.js";
  4. import m_obj_util_fact from "../intern/obj_util.js";
  5. import m_phy_fact from "../intern/physics.js";
  6. import m_print_fact from "../intern/print.js";
  7. import m_trans_fact from "../intern/transform.js";
  8. import * as m_util from "../intern/util.js";
  9. import * as m_vec3 from "../libs/gl_matrix/vec3.js";
  10. /**
  11. * Object constraints API. Please note that these constraints are not the same
  12. * as those assigned in Blender.
  13. * @module constraints
  14. * @local StiffViewportPositioning
  15. */
  16. function Constraints(ns, exports) {
  17. var m_cam = m_cam_fact(ns);
  18. var m_cons = m_cons_fact(ns);
  19. var m_obj_util = m_obj_util_fact(ns);
  20. var m_phy = m_phy_fact(ns);
  21. var m_print = m_print_fact(ns);
  22. var m_trans = m_trans_fact(ns);
  23. /**
  24. * An object that defines positioning for the stiff viewport constraint.
  25. * @typedef {Object} StiffViewportPositioning
  26. * @property {number} [left] Offset from the left edge of the camera's viewport
  27. * @property {number} [right] Offset from the right edge of the camera's viewport
  28. * @property {number} [top] Offset from the top edge of the camera's viewport
  29. * @property {number} [bottom] Offset from the bottom edge of the camera's viewport
  30. * @property {number} [distance] Distance from the camera
  31. * @property {Quat} [rotation] Rotation offset
  32. * @property {string} [hor_units="widths"] Left/Right offset units: "heights" or "widths"
  33. * @property {string} [vert_units="heights"] Top/Bottom offset units: "heights" or "widths"
  34. * @cc_externs left right top bottom distance rotation hor_units vert_units
  35. */
  36. /**
  37. * Attach the object to the other object or to the armature bone using a
  38. * stiff constraint. The child object will move, rotate and scale
  39. * together with its parent. Examples: a sword is parented to the
  40. * character's hand; the character is sitting in a vehicle.
  41. *
  42. * @method module:constraints.append_stiff
  43. * @param {Object3D} obj Constrained object
  44. * @param {(Object3D|Array)} target Target object or [Armature object, Bone Name]
  45. * @param {Vec3} [offset] Offset, in the parent's local space.
  46. * @param {Quat} [rotation_offset=null] Rotation offset, in the
  47. * parent's local space.
  48. * @param {number} [scale_offset=1] Scale offset, in the parent's local space.
  49. *
  50. * @example var m_scene = require("scenes");
  51. * var m_const = require("constraints");
  52. *
  53. * var my_offset_vector = new Float32Array([2.0, 2.0, 2.0]);
  54. *
  55. * var my_cube = m_scene.get_object_by_name("cube");
  56. * var my_sphere = m_scene.get_object_by_name("Icosphere");
  57. *
  58. * m_const.append_stiff(my_sphere, my_cube, my_offset_vector);
  59. */
  60. exports.append_stiff = function(obj, target, offset, rotation_offset,
  61. scale_offset) {
  62. if (!m_obj_util.is_dynamic(obj)) {
  63. m_print.error("Wrong object: \"" + obj.name + "\" is not dynamic.");
  64. return;
  65. }
  66. if (!m_cons.check_self_applying(obj, target)) {
  67. m_print.error("Can not apply constraint. Object and target must be different.");
  68. return;
  69. }
  70. if (!m_cons.check_compatibility(obj, target)) {
  71. m_print.error("Constraint recursion is forbidden.");
  72. return;
  73. }
  74. offset = offset || new Float32Array(3);
  75. scale_offset = scale_offset || 1;
  76. rotation_offset =
  77. rotation_offset ? rotation_offset : [0, 0, 0, 1];
  78. if (target instanceof Array && target.length == 2)
  79. m_cons.append_stiff_bone(obj, target[0], target[1], offset,
  80. rotation_offset, scale_offset);
  81. else
  82. m_cons.append_stiff_obj(obj, target, offset, rotation_offset,
  83. scale_offset);
  84. m_trans.update_transform(obj);
  85. m_phy.sync_transform(obj);
  86. }
  87. /**
  88. * Attach the object to the other object using a
  89. * semi-stiff constraint. The child object will move and rotate together with
  90. * its parent, but it will be still possible to rotate it independently
  91. * in the parent's local space. Example: a tank turret.
  92. *
  93. * @method module:constraints.append_semi_stiff
  94. * @param {Object3D} obj Constrained object
  95. * @param {Object3D} target Target object
  96. * @param {Vec3} [offset] Offset, in the parent's local space
  97. * @param {Quat} [rotation_offset] Initial rotation offset, in the
  98. * parent's local space
  99. * @param {number} [clamp_left] Left object rotation limit, in radians
  100. * @param {number} [clamp_right] Right object rotation limit, in radians
  101. * @param {number} [clamp_up] Upward object rotation limit, in radians
  102. * @param {number} [clamp_down] Downward object rotation limit, in radians
  103. *
  104. * @example var m_scene = require("scenes");
  105. * var m_const = require("constraints");
  106. *
  107. * var my_offset_vector = new Float32Array([2.0, 2.0, 2.0]);
  108. *
  109. * var my_cube = m_scene.get_object_by_name("cube");
  110. * var my_sphere = m_scene.get_object_by_name("Icosphere");
  111. *
  112. * m_const.append_semi_stiff(my_sphere, my_cube, my_offset_vector);
  113. */
  114. exports.append_semi_stiff = function(obj, target, offset, rotation_offset,
  115. clamp_left, clamp_right,
  116. clamp_up, clamp_down) {
  117. if (!m_obj_util.is_dynamic(obj)) {
  118. m_print.error("Wrong object: \"" + obj.name + "\" is not dynamic.");
  119. return;
  120. }
  121. if (!m_cons.check_self_applying(obj, target)) {
  122. m_print.error("Can not apply constraint. Object and target must be different.");
  123. return;
  124. }
  125. if (!m_cons.check_compatibility(obj, target)) {
  126. m_print.error("Constraint recursion is forbidden.");
  127. return;
  128. }
  129. clamp_left = m_util.isdef(clamp_left) ? clamp_left : Math.PI / 2;
  130. clamp_right = m_util.isdef(clamp_right) ? clamp_right : -Math.PI / 2;
  131. clamp_up = m_util.isdef(clamp_up) ? clamp_up : Math.PI / 2;
  132. clamp_down = m_util.isdef(clamp_down) ? clamp_down : -Math.PI / 2;
  133. offset = offset || new Float32Array(3);
  134. rotation_offset =
  135. rotation_offset ? new Float32Array(rotation_offset) : null;
  136. m_cons.append_semi_stiff_obj(obj, target, offset, rotation_offset,
  137. clamp_left, clamp_right,
  138. clamp_up, clamp_down);
  139. m_trans.update_transform(obj);
  140. m_phy.sync_transform(obj);
  141. }
  142. /**
  143. * Attach the EYE camera to the object using a
  144. * semi-stiff constraint. Also apply rotation limits to the camera.
  145. * The camera will move and rotate together with
  146. * its parent, but it will be still possible to rotate it independently
  147. * in the parent's local space. The camera's UP vector will be preserved.
  148. * Example: first-person vehicle view.
  149. *
  150. * @see https://www.blend4web.com/doc/en/camera.html#api
  151. * @method module:constraints.append_semi_stiff_cam
  152. * @param {Object3D} obj Constrained object
  153. * @param {Object3D} target Target object
  154. * @param {Vec3} [offset] Offset, in the parent's local space
  155. * @param {Quat} [rotation_offset] Initial rotation offset, in the
  156. * parent's local space
  157. * @param {number} [clamp_left] Left camera rotation limit, in radians
  158. * @param {number} [clamp_right] Right camera rotation limit, in radians
  159. * @param {number} [clamp_up] Upward camera rotation limit, in radians
  160. * @param {number} [clamp_down] Downward camera rotation limit, in radians
  161. * @deprecated [17.06] Use {@link module:constraints.append_semi_stiff} instead
  162. */
  163. exports.append_semi_stiff_cam = function(obj, target, offset, rotation_offset,
  164. clamp_left, clamp_right,
  165. clamp_up, clamp_down) {
  166. m_print.error_deprecated("append_semi_stiff_cam", "append_semi_stiff");
  167. if (!m_cam.is_eye_camera(obj)) {
  168. m_print.error("append_semi_stiff_cam(): wrong object type, only EYE" +
  169. " camera objects can be parented.");
  170. return;
  171. }
  172. exports.append_semi_stiff(obj, target, offset, rotation_offset,
  173. clamp_left, clamp_right,
  174. clamp_up, clamp_down);
  175. }
  176. /**
  177. * Attach the EYE camera to the object using a
  178. * semi-soft constraint. The camera will smoothly follow the object's rear.
  179. * Example: third-person character or vehicle views.
  180. *
  181. * @method module:constraints.append_semi_soft_cam
  182. * @param {Object3D} obj Constrained object
  183. * @param {Object3D} target Target object
  184. * @param {Vec3} [offset] Offset, in the parent's local space
  185. * @param {number} [softness=0.25] Camera smoothness ratio
  186. * @deprecated [17.06] Use {@link module:constraints.append_semi_soft} instead
  187. */
  188. exports.append_semi_soft_cam = function(obj, target, offset, softness) {
  189. m_print.error_deprecated("append_semi_soft_cam", "append_semi_soft");
  190. if (!m_cam.is_eye_camera(obj)) {
  191. m_print.error("append_semi_soft_cam(): wrong object type, only EYE" +
  192. " camera objects can be parented.");
  193. return;
  194. }
  195. exports.append_semi_soft(obj, target, offset, softness);
  196. }
  197. /**
  198. * Attach one object to another one using a
  199. * semi-soft constraint. The object will smoothly follow the object's rear.
  200. * Example: third-person character or vehicle views.
  201. *
  202. * @method module:constraints.append_semi_soft
  203. * @param {Object3D} obj Constrained object
  204. * @param {Object3D} target Target object
  205. * @param {Vec3} [offset] Offset, in the parent's local space
  206. * @param {number} [softness=0.25] Object smoothness ratio
  207. *
  208. * @example var m_scene = require("scenes");
  209. * var m_const = require("constraints");
  210. *
  211. * var my_offset_vector = new Float32Array([2.0, 2.0, 2.0]);
  212. *
  213. * var my_cube = m_scene.get_object_by_name("cube");
  214. * var my_sphere = m_scene.get_object_by_name("Icosphere");
  215. *
  216. * m_const.append_semi_soft(my_sphere, my_cube, my_offset_vector, 0.5);
  217. */
  218. exports.append_semi_soft = function(obj, target, offset, softness) {
  219. if (!m_obj_util.is_dynamic(obj)) {
  220. m_print.error("Wrong object: \"" + obj.name + "\" is not dynamic.");
  221. return;
  222. }
  223. if (!m_cons.check_self_applying(obj, target)) {
  224. m_print.error("Can not apply constraint. Object and target must be different.");
  225. return;
  226. }
  227. if (!m_cons.check_compatibility(obj, target)) {
  228. m_print.error("Constraint recursion is forbidden.");
  229. return;
  230. }
  231. if (!m_util.isdef(softness) || softness < 0)
  232. softness = 0.25;
  233. offset = offset || new Float32Array(3);
  234. m_cons.append_semi_soft_obj(obj, target, offset, softness);
  235. m_trans.update_transform(obj);
  236. m_phy.sync_transform(obj);
  237. }
  238. /**
  239. * Attach the object to the other object using a
  240. * stiff translation constraint. The child object will move together with
  241. * its parent, but will not rotate. It will be still possible to rotate it
  242. * independently from the parent.
  243. * <p>
  244. * Example: attaching the camera to the physics character in order to
  245. * implement the first-person character view.
  246. * </p>
  247. * </p>
  248. * Another example: the character
  249. * jumps in water and splashes' particle emitter is attached to the
  250. * first-person camera using this constraint - the bubbles will follow the
  251. * character but will not be rotated with the camera.
  252. * </p>
  253. * @method module:constraints.append_stiff_trans
  254. * @param {Object3D} obj Constrained object
  255. * @param {Object3D} target Target object
  256. * @param {Vec3} [offset] Offset, in the parent's local space
  257. *
  258. * @example var m_scene = require("scenes");
  259. * var m_const = require("constraints");
  260. *
  261. * var my_offset_vector = new Float32Array([-2.0, 2.0, 2.0]);
  262. *
  263. * var my_cube = m_scene.get_object_by_name("cube");
  264. * var my_sphere_4 = m_scene.get_object_by_name("Icosphere");
  265. *
  266. * m_const.append_stiff_trans(my_sphere, my_cube, my_offset_vector);
  267. */
  268. exports.append_stiff_trans = function(obj, target, offset) {
  269. if (!m_obj_util.is_dynamic(obj)) {
  270. m_print.error("Wrong object: \"" + obj.name + "\" is not dynamic.");
  271. return;
  272. }
  273. if (!m_cons.check_self_applying(obj, target)) {
  274. m_print.error("Can not apply constraint. Object and target must be different.");
  275. return;
  276. }
  277. if (!m_cons.check_compatibility(obj, target)) {
  278. m_print.error("Constraint recursion is forbidden.");
  279. return;
  280. }
  281. offset = offset || new Float32Array(3);
  282. m_cons.append_stiff_trans_obj(obj, target, offset);
  283. m_trans.update_transform(obj);
  284. m_phy.sync_transform(obj);
  285. }
  286. /**
  287. * Attach the object to the other object using a copy location constraint.
  288. * The child object will move together with its parent, but will not rotate.
  289. * Note that the offset is the object's location in the world space.
  290. * <p>
  291. * This method works similarly to the <b>Copy Location</b> constraint in Blender.
  292. * </p>
  293. * @method module:constraints.append_copy_loc
  294. * @param {Object3D} obj Constrained object
  295. * @param {Object3D} target Target object
  296. * @param {string} [axes='XYZ'] Copy the target's location
  297. * @param {boolean} [use_offset=false] Add original location into copied location
  298. * @param {number} [influence=1] Amount of influence constraint will have on the final solution
  299. *
  300. * @example var m_scene = require("scenes");
  301. * var m_const = require("constraints");
  302. *
  303. * var my_cube = m_scene.get_object_by_name("cube");
  304. * var my_sphere = m_scene.get_object_by_name("Icosphere");
  305. *
  306. * m_const.append_copy_loc(my_sphere, my_cube, 'XYZ', false, 0.5);
  307. */
  308. exports.append_copy_loc = function(obj, target, axes, use_offset, influence) {
  309. if (!m_obj_util.is_dynamic(obj)) {
  310. m_print.error("Wrong object: \"" + obj.name + "\" is not dynamic.");
  311. return;
  312. }
  313. if (!m_cons.check_self_applying(obj, target)) {
  314. m_print.error("Can not apply constraint. Object and target must be different.");
  315. return;
  316. }
  317. if (!m_cons.check_compatibility(obj, target)) {
  318. m_print.error("Constraint recursion is forbidden.");
  319. return;
  320. }
  321. use_offset = use_offset || false;
  322. axes = axes || "XYZ";
  323. influence = influence || 1;
  324. var offset = m_trans.get_translation(obj, new Float32Array(3));
  325. var used_axes = new Float32Array(3);
  326. used_axes[0] = axes.indexOf("-X") != -1 ? -1 : axes.indexOf("X") != -1 ? 1 : 0;
  327. used_axes[1] = axes.indexOf("-Y") != -1 ? -1 : axes.indexOf("Y") != -1 ? 1 : 0;
  328. used_axes[2] = axes.indexOf("-Z") != -1 ? -1 : axes.indexOf("Z") != -1 ? 1 : 0;
  329. m_cons.append_copy_loc_obj(obj, target, offset, used_axes, use_offset, influence);
  330. m_trans.update_transform(obj);
  331. m_phy.sync_transform(obj);
  332. }
  333. /**
  334. * Attach the object to the other object using a copy transforms constraint.
  335. * The child object will move and rotate together with its parent.
  336. * <p>
  337. * This method works similarly to the <b>Copy Transforms</b> constraint in Blender.
  338. * </p>
  339. * @method module:constraints.append_copy_trans
  340. * @param {Object3D} obj Constrained object
  341. * @param {Object3D} target Target object
  342. * @param {number} [influence=1] Amount of influence constraint will have on the final solution
  343. *
  344. * @example var m_scene = require("scenes");
  345. * var m_const = require("constraints");
  346. *
  347. * var my_cube = m_scene.get_object_by_name("cube");
  348. * var my_sphere = m_scene.get_object_by_name("Icosphere");
  349. *
  350. * m_const.append_copy_trans(my_sphere, my_cube, 0.5);
  351. */
  352. exports.append_copy_trans = function(obj, target, influence) {
  353. if (!m_obj_util.is_dynamic(obj)) {
  354. m_print.error("Wrong object: \"" + obj.name + "\" is not dynamic.");
  355. return;
  356. }
  357. if (!m_cons.check_self_applying(obj, target)) {
  358. m_print.error("Can not apply constraint. Object and target must be different.");
  359. return;
  360. }
  361. if (!m_cons.check_compatibility(obj, target)) {
  362. m_print.error("Constraint recursion is forbidden.");
  363. return;
  364. }
  365. influence = influence || 1;
  366. m_cons.append_copy_trans_obj(obj, target, influence);
  367. m_trans.update_transform(obj);
  368. m_phy.sync_transform(obj);
  369. }
  370. /**
  371. * Attach the object to the other object using a copy rotation constraint.
  372. * The child object will rotate together with its parent, but will not move.
  373. * Note that the offset is the object's rotation in the world space.
  374. * <p>
  375. * This method works similarly to the <b>Copy Rotation</b> constraint in Blender.
  376. * </p>
  377. * @method module:constraints.append_copy_rot
  378. * @param {Object3D} obj Constrained object
  379. * @param {Object3D} target Target object
  380. * @param {string} [axes='XYZ'] Copy the target's location
  381. * @param {boolean} [use_offset=false] Add original location into copied location
  382. * @param {number} [influence=1] Amount of influence constraint will have on the final solution
  383. *
  384. * @example var m_scene = require("scenes");
  385. * var m_const = require("constraints");
  386. *
  387. * var my_cube = m_scene.get_object_by_name("cube");
  388. * var my_sphere = m_scene.get_object_by_name("Icosphere");
  389. *
  390. * m_const.append_copy_rot(my_sphere, my_cube, 'XYZ', 0.5);
  391. */
  392. exports.append_copy_rot = function(obj, target, axes, use_offset, influence) {
  393. if (!m_obj_util.is_dynamic(obj)) {
  394. m_print.error("Wrong object: \"" + obj.name + "\" is not dynamic.");
  395. return;
  396. }
  397. if (!m_cons.check_self_applying(obj, target)) {
  398. m_print.error("Can not apply constraint. Object and target must be different.");
  399. return;
  400. }
  401. if (!m_cons.check_compatibility(obj, target)) {
  402. m_print.error("Constraint recursion is forbidden.");
  403. return;
  404. }
  405. use_offset = use_offset || false;
  406. axes = axes || "XYZ";
  407. influence = influence || 1;
  408. var used_axes = new Float32Array(3);
  409. used_axes[0] = axes.indexOf("-X") != -1 ? -1 : axes.indexOf("X") != -1 ? 1 : 0;
  410. used_axes[1] = axes.indexOf("-Y") != -1 ? -1 : axes.indexOf("Y") != -1 ? 1 : 0;
  411. used_axes[2] = axes.indexOf("-Z") != -1 ? -1 : axes.indexOf("Z") != -1 ? 1 : 0;
  412. m_cons.append_copy_rot_obj(obj, target, used_axes, use_offset, influence);
  413. m_trans.update_transform(obj);
  414. m_phy.sync_transform(obj);
  415. }
  416. /**
  417. * Attach the object to the other object using a
  418. * stiff translation/rotation constraint. The child object will move and rotate
  419. * together with its parent, but will not scale. It will be still possible to
  420. * scale it independently from the parent.
  421. *
  422. * Example: smoke emitter attached to the tractor pipe; exhaustion effects
  423. * are achieved by scaling the emitter.
  424. *
  425. * @method module:constraints.append_stiff_trans_rot
  426. * @param {Object3D} obj Constrained object
  427. * @param {Object3D} target Target object
  428. * @param {Vec3} [offset] Offset, in the parent's local space
  429. * @param {Quat} [rotation_offset] Rotation offset, in
  430. * the parent's local space
  431. *
  432. * @example var m_scene = require("scenes");
  433. * var m_const = require("constraints");
  434. *
  435. * var my_sphere = m_scene.get_object_by_name("Icosphere");
  436. * var my_cube = m_scene.get_object_by_name("cube");
  437. *
  438. * var my_offset_vector = new Float32Array([-2.0, 2.0, 2.0]);
  439. * m_const.append_stiff_trans_rot(my_sphere, my_cube, my_offset_vector);
  440. */
  441. exports.append_stiff_trans_rot = function(obj, target, offset, rotation_offset) {
  442. if (!m_obj_util.is_dynamic(obj)) {
  443. m_print.error("Wrong object: \"" + obj.name + "\" is not dynamic.");
  444. return;
  445. }
  446. if (!m_cons.check_self_applying(obj, target)) {
  447. m_print.error("Can not apply constraint. Object and target must be different.");
  448. return;
  449. }
  450. if (!m_cons.check_compatibility(obj, target)) {
  451. m_print.error("Constraint recursion is forbidden.");
  452. return;
  453. }
  454. offset = offset || new Float32Array(3);
  455. rotation_offset =
  456. rotation_offset ? new Float32Array(rotation_offset) : [0, 0, 0, 1];
  457. m_cons.append_stiff_trans_rot_obj(obj, target, offset, rotation_offset, 1.0);
  458. m_trans.update_transform(obj);
  459. m_phy.sync_transform(obj);
  460. }
  461. /**
  462. * Make the object "looking" at the target object.
  463. *
  464. * Example: a spot light which is tracking the character; both objects can be
  465. * moved via API or animated.
  466. * <p>
  467. * This method works in a similar way to the <b>Track To</b> constraint in Blender.
  468. * </p>
  469. * @method module:constraints.append_track
  470. * @param {Object3D} obj Constrained object
  471. * @param {(Object3D)} target Target object
  472. * @param {string} [track_axis='Y'] Axis that points to the target object
  473. * @param {string} [up_axis='Z'] Axis that points upward
  474. * @param {boolean} [use_target_z=false] Target's Z axis, not World Z axis, will constraint the Up direction
  475. * @param {number} [influence=1] Amount of influence constraint will have on the final solution
  476. *
  477. * @example var m_scene = require("scenes");
  478. * var m_const = require("constraints");
  479. *
  480. * var my_cube = m_scene.get_object_by_name("cube");
  481. * var my_camera = m_scene.get_object_by_name("Camera");
  482. *
  483. * m_const.append_track(my_camera, my_cube, "-X", "Z");
  484. */
  485. exports.append_track = function(obj, target, track_axis, up_axis, use_target_z, influence) {
  486. if (!m_obj_util.is_dynamic(obj)) {
  487. m_print.error("Wrong object: \"" + obj.name + "\" is not dynamic.");
  488. return;
  489. }
  490. if (!m_cons.check_self_applying(obj, target)) {
  491. m_print.error("Can not apply constraint. Object and target must be different.");
  492. return;
  493. }
  494. if (!m_cons.check_compatibility(obj, target)) {
  495. m_print.error("Constraint recursion is forbidden.");
  496. return;
  497. }
  498. var track_axis_vec = m_util.AXIS_Y;
  499. if (track_axis == "-Y")
  500. track_axis_vec = m_util.AXIS_MY;
  501. else if (track_axis == "Y")
  502. track_axis_vec = m_util.AXIS_Y;
  503. else if (track_axis == "-X")
  504. track_axis_vec = m_util.AXIS_MX;
  505. else if (track_axis == "X")
  506. track_axis_vec = m_util.AXIS_X;
  507. else if (track_axis == "-Z")
  508. track_axis_vec = m_util.AXIS_MZ;
  509. else if (track_axis == "Z")
  510. track_axis_vec = m_util.AXIS_Z;
  511. var up_axis_vec = m_util.AXIS_Z;
  512. if (up_axis == "X")
  513. up_axis_vec = m_util.AXIS_X;
  514. else if (up_axis == "Y")
  515. up_axis_vec = m_util.AXIS_Y;
  516. if (Math.abs(m_vec3.dot(track_axis_vec, up_axis_vec)) == 1) {
  517. m_print.error("Can not use parallel vectors for track and up axes.");
  518. return;
  519. }
  520. influence = influence || 1;
  521. use_target_z = use_target_z || false;
  522. m_cons.append_track_obj(obj, target, track_axis_vec, up_axis_vec,
  523. use_target_z, influence);
  524. m_trans.update_transform(obj);
  525. m_phy.sync_transform(obj);
  526. }
  527. /**
  528. * Attach the object to the other object using a follow constraint. The child
  529. * object will track and follow its parent position.
  530. * <p>
  531. * This method works similarly to the <b>Limit Distance</b> constraint in Blender, but, unlike it, does not set a precise distance.
  532. * </p>
  533. * Example: a follow-style camera view for the character.
  534. *
  535. * @method module:constraints.append_follow
  536. * @param {Object3D} obj Constrained object
  537. * @param {Object3D} target Target object
  538. * @param {number} dist_min Minimum distance
  539. * @param {number} dist_max Maximum distance
  540. *
  541. * @example var m_scene = require("scenes");
  542. * var m_const = require("constraints");
  543. *
  544. * var my_cube = m_scene.get_object_by_name("cube");
  545. * var my_camera = m_scene.get_object_by_name("Camera");
  546. *
  547. * m_const.append_follow(my_camera, my_cube, 2.0, 4.0);
  548. */
  549. exports.append_follow = function(obj, target, dist_min, dist_max) {
  550. if (!m_obj_util.is_dynamic(obj)) {
  551. m_print.error("Wrong object: \"" + obj.name + "\" is not dynamic.");
  552. return;
  553. }
  554. if (!m_cons.check_self_applying(obj, target)) {
  555. m_print.error("Can not apply constraint. Object and target must be different.");
  556. return;
  557. }
  558. if (!m_cons.check_compatibility(obj, target)) {
  559. m_print.error("Constraint recursion is forbidden.");
  560. return;
  561. }
  562. m_cons.append_follow_obj(obj, target, dist_min, dist_max);
  563. m_trans.update_transform(obj);
  564. m_phy.sync_transform(obj);
  565. }
  566. /**
  567. * Attach the object to the camera using a stiff viewport constraint, so
  568. * the child object will preserve its orientation in the camera viewport.
  569. * This constraint is used to create onscreen 2D/3D user interfaces.
  570. * @method module:constraints.append_stiff_viewport
  571. * @param {Object3D} obj Constrained object
  572. * @param {Object3D} camobj Camera object
  573. * @param {StiffViewportPositioning} [positioning] Positioning
  574. *
  575. * @example var m_scene = require("scenes");
  576. * var m_const = require("constraints");
  577. *
  578. * var sphere_1 = m_scene.get_object_by_name("Icosphere");
  579. * var my_camera = m_scene.get_object_by_name("Camera");
  580. *
  581. * m_const.append_stiff_viewport(sphere_1, my_camera, {
  582. * left: 150,
  583. * top: 100,
  584. * distance: 1
  585. * });
  586. */
  587. exports.append_stiff_viewport = function(obj, camobj, positioning) {
  588. if (!m_obj_util.is_dynamic(obj)) {
  589. m_print.error("Wrong object: \"" + obj.name + "\" is not dynamic.");
  590. return;
  591. }
  592. if (!m_cons.check_self_applying(obj, camobj)) {
  593. m_print.error("Can not apply constraint. Object and target must be different.");
  594. return;
  595. }
  596. if (!m_cons.check_compatibility(obj, camobj)) {
  597. m_print.error("Constraint recursion is forbidden.");
  598. return;
  599. }
  600. positioning = positioning || {};
  601. m_cons.append_stiff_viewport(obj, camobj, positioning);
  602. m_trans.update_transform(obj);
  603. m_phy.sync_transform(obj);
  604. }
  605. /**
  606. * Remove the object's constraint (if any).
  607. * @method module:constraints.remove
  608. * @param {Object3D} obj Constrained object
  609. * @param {boolean} [restore_transform=false] Restore default transform
  610. *
  611. * @example var m_scene = require("scenes");
  612. * var m_const = require("constraints");
  613. *
  614. * var my_sphere = m_scene.get_object_by_name("Icosphere");
  615. *
  616. * m_const.remove(my_sphere);
  617. */
  618. exports.remove = function(obj, restore_transform) {
  619. restore_transform = restore_transform || false;
  620. if (obj.constraint)
  621. m_cons.remove(obj, restore_transform);
  622. if (restore_transform)
  623. m_trans.update_transform(obj);
  624. }
  625. }
  626. var constraints_factory = register("constraints", Constraints);
  627. export default constraints_factory;