constraints.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. /**
  2. * Copyright (C) 2014-2016 Triumph LLC
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. "use strict";
  18. /**
  19. * Object constraints API. Please note that these constraints are not the same
  20. * as those assigned in Blender.
  21. * @module constraints
  22. * @local StiffViewportPositioning
  23. */
  24. b4w.module["constraints"] = function(exports, require) {
  25. var m_cam = require("__camera");
  26. var m_cons = require("__constraints");
  27. var m_obj_util = require("__obj_util");
  28. var m_phy = require("__physics");
  29. var m_print = require("__print");
  30. var m_trans = require("__transform");
  31. /**
  32. * An object that defines positioning for the stiff viewport constraint.
  33. * @typedef {Object} StiffViewportPositioning
  34. * @property {Number} [left] Offset from the left edge of the camera's viewport
  35. * @property {Number} [right] Offset from the right edge of the camera's viewport
  36. * @property {Number} [top] Offset from the top edge of the camera's viewport
  37. * @property {Number} [bottom] Offset from the bottom edge of the camera's viewport
  38. * @property {Number} distance Distance from the camera
  39. * @property {Quat} [rotation] Rotation offset
  40. * @property {String} [hor_units="widths"] Left/Right offset units: "heights" or "widths"
  41. * @property {String} [vert_units="heights"] Top/Bottom offset units: "heights" or "widths"
  42. * @cc_externs left right top bottom distance rotation hor_units vert_units
  43. */
  44. /**
  45. * Attach the object to the other object or to the armature bone using a
  46. * stiff constraint. The child object will move, rotate and scale
  47. * together with its parent. Examples: a sword is parented to the
  48. * character's hand; the character is sitting in a vehicle.
  49. *
  50. * @method module:constraints.append_stiff
  51. * @param {Object3D} obj Constrained object
  52. * @param {(Object3D|Array)} target Target object or [Armature object, Bone Name]
  53. * @param {Vec3} offset Offset, in the parent's local space.
  54. * @param {Quat} [rotation_offset=null] Rotation offset, in the
  55. * parent's local space.
  56. * @param {Number} [scale_offset=1] Scale offset, in the parent's local space.
  57. */
  58. exports.append_stiff = function(obj, target, offset, rotation_offset,
  59. scale_offset) {
  60. scale_offset = scale_offset || 1;
  61. if (target instanceof Array && target.length == 2)
  62. m_cons.append_stiff_bone(obj, target[0], target[1], offset,
  63. rotation_offset, scale_offset);
  64. else
  65. m_cons.append_stiff_obj(obj, target, offset, rotation_offset,
  66. scale_offset);
  67. m_trans.update_transform(obj);
  68. m_phy.sync_transform(obj);
  69. }
  70. /**
  71. * Attach the object to the other object using a
  72. * semi-stiff constraint. The child object will move and rotate together with
  73. * its parent, but it will be still possible to rotate it independently
  74. * in the parent's local space. Example: a tank turret.
  75. *
  76. * @method module:constraints.append_semi_stiff
  77. * @param {Object3D} obj Constrained object
  78. * @param {Object3D} target Target object
  79. * @param {Vec3} offset Offset, in the parent's local space
  80. * @param {Quat} [rotation_offset] Initial rotation offset, in the
  81. * parent's local space
  82. */
  83. exports.append_semi_stiff = function(obj, target, offset, rotation_offset) {
  84. m_cons.append_semi_stiff_obj(obj, target, offset, rotation_offset);
  85. m_trans.update_transform(obj);
  86. m_phy.sync_transform(obj);
  87. }
  88. /**
  89. * Attach the EYE camera to the object using a
  90. * semi-stiff constraint. Also apply rotation limits to the camera.
  91. * The camera will move and rotate together with
  92. * its parent, but it will be still possible to rotate it independently
  93. * in the parent's local space. The camera's UP vector will be preserved.
  94. * Example: first-person vehicle view.
  95. *
  96. * @see https://www.blend4web.com/doc/en/camera.html#api
  97. * @method module:constraints.append_semi_stiff_cam
  98. * @param {Object3D} obj Constrained object
  99. * @param {Object3D} target Target object
  100. * @param {Vec3} offset Offset, in the parent's local space
  101. * @param {Quat} [rotation_offset] Initial rotation offset, in the
  102. * parent's local space
  103. * @param {Number} [clamp_left] Left camera rotation limit, in radians
  104. * @param {Number} [clamp_right] Right camera rotation limit, in radians
  105. * @param {Number} [clamp_up] Upward camera rotation limit, in radians
  106. * @param {Number} [clamp_down] Downward camera rotation limit, in radians
  107. */
  108. exports.append_semi_stiff_cam = function(obj, target, offset, rotation_offset,
  109. clamp_left, clamp_right,
  110. clamp_up, clamp_down) {
  111. if (!m_cam.is_eye_camera(obj)) {
  112. m_print.error("append_semi_stiff_cam(): wrong object type, only EYE" +
  113. " camera objects can be parented.");
  114. return;
  115. }
  116. clamp_left = clamp_left || -Math.PI / 2;
  117. clamp_right = clamp_right || Math.PI / 2;
  118. clamp_up = clamp_up || Math.PI / 2;
  119. clamp_down = clamp_down || -Math.PI / 2;
  120. m_cons.append_semi_stiff_cam_obj(obj, target, offset, rotation_offset,
  121. clamp_left, clamp_right,
  122. clamp_up, clamp_down);
  123. m_trans.update_transform(obj);
  124. m_phy.sync_transform(obj);
  125. }
  126. /**
  127. * Attach the EYE camera to the object using a
  128. * semi-soft constraint. The camera will smoothly follow the object's rear.
  129. * Example: third-person character or vehicle views.
  130. *
  131. * @method module:constraints.append_semi_soft_cam
  132. * @param {Object3D} obj Constrained object
  133. * @param {Object3D} target Target object
  134. * @param {Vec3} offset Offset, in the parent's local space
  135. * @param {Number} [softness=0.25] Camera smoothness ratio
  136. */
  137. exports.append_semi_soft_cam = function(obj, target, offset, softness) {
  138. if (!m_cam.is_eye_camera(obj)) {
  139. m_print.error("append_semi_soft_cam(): wrong object type, only EYE" +
  140. " camera objects can be parented.");
  141. return;
  142. }
  143. if (!softness || softness < 0)
  144. softness = 0.25;
  145. m_cons.append_semi_soft_cam_obj(obj, target, offset, softness);
  146. m_trans.update_transform(obj);
  147. m_phy.sync_transform(obj);
  148. }
  149. /**
  150. * Attach the object to the other object using a
  151. * stiff translation constraint. The child object will move together with
  152. * its parent, but will not rotate. It will be still possible to rotate it
  153. * independently from the parent.
  154. *
  155. * Example: attaching the camera to the physics character in order to
  156. * implement the first-person character view. Another example: the character
  157. * jumps in water and splashes' particle emitter is attached to the
  158. * first-person camera using this constraint - the bubbles will follow the
  159. * character but will not be rotated with the camera.
  160. *
  161. * @method module:constraints.append_stiff_trans
  162. * @param {Object3D} obj Constrained object
  163. * @param {Object3D} target Target object
  164. * @param {Vec3} offset Offset, in the parent's local space
  165. */
  166. exports.append_stiff_trans = function(obj, target, offset) {
  167. m_cons.append_stiff_trans_obj(obj, target, offset);
  168. m_trans.update_transform(obj);
  169. m_phy.sync_transform(obj);
  170. }
  171. /**
  172. * Attach the object to the other object using a copy translation constraint.
  173. * The child object will move together with its parent, but will not rotate.
  174. * Note that the offset is specified in the world space.
  175. * Example: a light source attached to the character.
  176. *
  177. * @method module:constraints.append_copy_trans
  178. * @param {Object3D} obj Constrained object
  179. * @param {Object3D} target Target object
  180. * @param {Vec3} offset Offset, in the parent's world space
  181. */
  182. exports.append_copy_trans = function(obj, target, offset) {
  183. m_cons.append_copy_trans_obj(obj, target, offset);
  184. m_trans.update_transform(obj);
  185. m_phy.sync_transform(obj);
  186. }
  187. /**
  188. * Attach the object to the other object using a
  189. * stiff translation/rotation constraint. The child object will move and rotate
  190. * together with its parent, but will not scale. It will be still possible to
  191. * scale it independently from the parent.
  192. *
  193. * Example: smoke emitter attached to the tractor pipe; exhaustion effects
  194. * are achieved by scaling the emitter.
  195. *
  196. * @method module:constraints.append_stiff_trans_rot
  197. * @param {Object3D} obj Constrained object
  198. * @param {Object3D} target Target object
  199. * @param {Vec3} offset Offset, in the parent's local space
  200. * @param {Quat} [rotation_offset] Rotation offset, in
  201. * the parent's local space
  202. */
  203. exports.append_stiff_trans_rot = function(obj, target, offset, rotation_offset) {
  204. m_cons.append_stiff_trans_rot_obj(obj, target, offset, rotation_offset, 1.0);
  205. m_trans.update_transform(obj);
  206. m_phy.sync_transform(obj);
  207. }
  208. /**
  209. * Make the object "looking" at the target object or the position. The object's
  210. * facing direction is considered to be the -Z axis that is vertically
  211. * downwards.
  212. *
  213. * Example: a spot light which is tracking the character; both objects can be
  214. * moved via API or animated.
  215. *
  216. * @method module:constraints.append_track
  217. * @param {Object3D} obj Constrained object
  218. * @param {(Object3D|Vec3)} target Target object or position vector
  219. */
  220. exports.append_track = function(obj, target) {
  221. if (target.length == 3)
  222. m_cons.append_track_point(obj, target);
  223. else
  224. m_cons.append_track_obj(obj, target);
  225. m_trans.update_transform(obj);
  226. m_phy.sync_transform(obj);
  227. }
  228. /**
  229. * Attach the object to the other object using a follow constraint. The child
  230. * object will track and follow its parent position.
  231. *
  232. * Example: a follow-style camera view for the character.
  233. *
  234. * @method module:constraints.append_follow
  235. * @param {Object3D} obj Constrained object
  236. * @param {(Object3D|Vec3)} target Target object or position vector
  237. * @param {Number} dist_min Minimum distance
  238. * @param {Number} dist_max Maximum distance
  239. */
  240. exports.append_follow = function(obj, target, dist_min, dist_max) {
  241. if (target.length == 3)
  242. m_cons.append_follow_point(obj, target, dist_min, dist_max);
  243. else
  244. m_cons.append_follow_obj(obj, target, dist_min, dist_max);
  245. m_trans.update_transform(obj);
  246. m_phy.sync_transform(obj);
  247. }
  248. /**
  249. * Attach the object to the camera using a stiff vieport constraint, so
  250. * the child object will preserve its orientation in the camera viewport.
  251. * This constraint is used to create onscreen 2D/3D user interfaces.
  252. * @method module:constraints.append_stiff_viewport
  253. * @param {Object3D} obj Constrained object
  254. * @param {Object3D} camobj Camera object
  255. * @param {StiffViewportPositioning} positioning Positioning
  256. */
  257. exports.append_stiff_viewport = function(obj, camobj, positioning) {
  258. m_cons.append_stiff_viewport(obj, camobj, positioning);
  259. m_trans.update_transform(obj);
  260. m_phy.sync_transform(obj);
  261. }
  262. /**
  263. * Remove the object's constraint (if any).
  264. * @method module:constraints.remove
  265. * @param {Object3D} obj Constrained object
  266. */
  267. exports.remove = function(obj) {
  268. if (obj.constraint)
  269. m_cons.remove(obj);
  270. }
  271. /**
  272. * Get object's parent object.
  273. * @method module:constraints.get_parent
  274. * @param {Object3D} obj Object
  275. * @returns {?Object3D} Parent object
  276. * @deprecated use {@link module:objects.get_parent|objects.get_parent} instead.
  277. */
  278. exports.get_parent = function(obj) {
  279. m_print.error_deprecated("constraints.get_parent", "objects.get_parent");
  280. return m_obj_util.get_parent(obj);
  281. }
  282. }