SEA3DLegacy.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720
  1. /**
  2. * SEA3D Legacy for Three.JS
  3. * @author Sunag / http://www.sunag.com.br/
  4. */
  5. 'use strict';
  6. //
  7. // Header
  8. //
  9. Object.assign( THREE.SEA3D.prototype, {
  10. _onHead: THREE.SEA3D.prototype.onHead,
  11. _updateTransform: THREE.SEA3D.prototype.updateTransform,
  12. _readVertexAnimation: THREE.SEA3D.prototype.readVertexAnimation,
  13. _readGeometryBuffer: THREE.SEA3D.prototype.readGeometryBuffer,
  14. _readLine: THREE.SEA3D.prototype.readLine,
  15. _getAnimationType: THREE.SEA3D.prototype.getAnimationType,
  16. _readAnimation: THREE.SEA3D.prototype.readAnimation
  17. } );
  18. //
  19. // Utils
  20. //
  21. THREE.SEA3D.prototype.isLegacy = function ( sea ) {
  22. var sea3d = sea.sea3d;
  23. if ( sea3d.sign == 'S3D' && ! sea._legacy ) {
  24. sea._legacy = sea3d.typeUnique[ sea.type ] == true;
  25. return sea3d.config.legacy;
  26. }
  27. return false;
  28. };
  29. THREE.SEA3D.prototype.flipVec3 = function ( v ) {
  30. if ( ! v ) return;
  31. var i = 2;
  32. while ( i < v.length ) {
  33. v[ i ] = - v[ i ];
  34. i += 3;
  35. }
  36. return v;
  37. };
  38. THREE.SEA3D.prototype.expandJoints = function ( sea ) {
  39. var numJoints = sea.numVertex * 4;
  40. var joint = sea.isBig ? new Uint32Array( numJoints ) : new Uint16Array( numJoints );
  41. var weight = new Float32Array( numJoints );
  42. var w = 0, jpv = sea.jointPerVertex;
  43. for ( var i = 0; i < sea.numVertex; i ++ ) {
  44. var tjsIndex = i * 4;
  45. var seaIndex = i * jpv;
  46. joint[ tjsIndex ] = sea.joint[ seaIndex ];
  47. if ( jpv > 1 ) joint[ tjsIndex + 1 ] = sea.joint[ seaIndex + 1 ];
  48. if ( jpv > 2 ) joint[ tjsIndex + 2 ] = sea.joint[ seaIndex + 2 ];
  49. if ( jpv > 3 ) joint[ tjsIndex + 3 ] = sea.joint[ seaIndex + 3 ];
  50. weight[ tjsIndex ] = sea.weight[ seaIndex ];
  51. if ( jpv > 1 ) weight[ tjsIndex + 1 ] = sea.weight[ seaIndex + 1 ];
  52. if ( jpv > 2 ) weight[ tjsIndex + 2 ] = sea.weight[ seaIndex + 2 ];
  53. if ( jpv > 3 ) weight[ tjsIndex + 3 ] = sea.weight[ seaIndex + 3 ];
  54. w = weight[ tjsIndex ] + weight[ tjsIndex + 1 ] + weight[ tjsIndex + 2 ] + weight[ tjsIndex + 3 ];
  55. weight[ tjsIndex ] += 1 - w;
  56. }
  57. sea.joint = joint;
  58. sea.weight = weight;
  59. sea.jointPerVertex = 4;
  60. };
  61. THREE.SEA3D.prototype.compressJoints = function ( sea ) {
  62. var numJoints = sea.numVertex * 4;
  63. var joint = sea.isBig ? new Uint32Array( numJoints ) : new Uint16Array( numJoints );
  64. var weight = new Float32Array( numJoints );
  65. var w = 0, jpv = sea.jointPerVertex;
  66. for ( var i = 0; i < sea.numVertex; i ++ ) {
  67. var tjsIndex = i * 4;
  68. var seaIndex = i * jpv;
  69. joint[ tjsIndex ] = sea.joint[ seaIndex ];
  70. joint[ tjsIndex + 1 ] = sea.joint[ seaIndex + 1 ];
  71. joint[ tjsIndex + 2 ] = sea.joint[ seaIndex + 2 ];
  72. joint[ tjsIndex + 3 ] = sea.joint[ seaIndex + 3 ];
  73. weight[ tjsIndex ] = sea.weight[ seaIndex ];
  74. weight[ tjsIndex + 1 ] = sea.weight[ seaIndex + 1 ];
  75. weight[ tjsIndex + 2 ] = sea.weight[ seaIndex + 2 ];
  76. weight[ tjsIndex + 3 ] = sea.weight[ seaIndex + 3 ];
  77. w = weight[ tjsIndex ] + weight[ tjsIndex + 1 ] + weight[ tjsIndex + 2 ] + weight[ tjsIndex + 3 ];
  78. weight[ tjsIndex ] += 1 - w;
  79. }
  80. sea.joint = joint;
  81. sea.weight = weight;
  82. sea.jointPerVertex = 4;
  83. };
  84. THREE.SEA3D.prototype.flipIndexes = function ( v ) {
  85. var i = 1; // y >-< z
  86. while ( i < v.length ) {
  87. var idx = v[ i + 1 ];
  88. v[ i + 1 ] = v[ i ];
  89. v[ i ] = idx;
  90. i += 3;
  91. }
  92. return v;
  93. };
  94. THREE.SEA3D.prototype.flipBoneMatrix = function () {
  95. var zero = new THREE.Vector3();
  96. return function ( mtx ) {
  97. var pos = THREE.SEA3D.VECBUF.setFromMatrixPosition( mtx );
  98. pos.z = - pos.z;
  99. mtx.setPosition( zero );
  100. mtx.multiplyMatrices( THREE.SEA3D.MTXBUF.makeRotationZ( THREE.Math.degToRad( 180 ) ), mtx );
  101. mtx.setPosition( pos );
  102. return mtx;
  103. };
  104. }();
  105. THREE.SEA3D.prototype.flipScaleMatrix = function () {
  106. var pos = new THREE.Vector3();
  107. var qua = new THREE.Quaternion();
  108. var slc = new THREE.Vector3();
  109. return function ( local, rotate, parent, parentRotate ) {
  110. if ( parent ) local.multiplyMatrices( parent, local );
  111. local.decompose( pos, qua, slc );
  112. slc.z = - slc.z;
  113. local.compose( pos, qua, slc );
  114. if ( rotate ) {
  115. local.multiplyMatrices( local, THREE.SEA3D.MTXBUF.makeRotationZ( THREE.Math.degToRad( 180 ) ) );
  116. }
  117. if ( parent ) {
  118. parent = parent.clone();
  119. this.flipScaleMatrix( parent, parentRotate );
  120. local.multiplyMatrices( parent.getInverse( parent ), local );
  121. }
  122. return local;
  123. };
  124. }();
  125. //
  126. // Legacy
  127. //
  128. THREE.SEA3D.prototype.flipDefaultAnimation = function () {
  129. var buf1 = new THREE.Matrix4();
  130. var buf2 = new THREE.Matrix4();
  131. var pos = new THREE.Vector3();
  132. var qua = new THREE.Quaternion();
  133. var slc = new THREE.Vector3();
  134. var to_pos = new THREE.Vector3();
  135. var to_qua = new THREE.Quaternion();
  136. var to_slc = new THREE.Vector3();
  137. return function ( animation, obj3d, relative ) {
  138. if ( animation.isFliped ) return;
  139. var dataList = animation.dataList,
  140. t_anm = [];
  141. for ( var i = 0; i < dataList.length; i ++ ) {
  142. var data = dataList[ i ],
  143. raw = data.data,
  144. kind = data.kind,
  145. numFrames = raw.length / data.blockSize;
  146. switch ( kind ) {
  147. case SEA3D.Animation.POSITION:
  148. case SEA3D.Animation.ROTATION:
  149. case SEA3D.Animation.SCALE:
  150. t_anm.push( {
  151. kind: kind,
  152. numFrames: numFrames,
  153. raw: raw
  154. } );
  155. break;
  156. }
  157. }
  158. if ( t_anm.length > 0 ) {
  159. var numFrames = t_anm[ 0 ].numFrames,
  160. parent = undefined;
  161. if ( relative ) {
  162. buf1.identity();
  163. parent = this.flipScaleMatrix( buf2.copy( obj3d.matrixWorld ) );
  164. } else {
  165. if ( obj3d.parent ) {
  166. parent = this.flipScaleMatrix( buf2.copy( obj3d.parent.matrixWorld ) );
  167. }
  168. this.flipScaleMatrix( buf1.copy( obj3d.matrix ), false, parent );
  169. }
  170. buf1.decompose( pos, qua, slc );
  171. for ( var f = 0, t, c; f < numFrames; f ++ ) {
  172. for ( t = 0; t < t_anm.length; t ++ ) {
  173. var raw = t_anm[ t ].raw,
  174. kind = t_anm[ t ].kind;
  175. switch ( kind ) {
  176. case SEA3D.Animation.POSITION:
  177. c = f * 3;
  178. pos.set(
  179. raw[ c ],
  180. raw[ c + 1 ],
  181. raw[ c + 2 ]
  182. );
  183. break;
  184. case SEA3D.Animation.ROTATION:
  185. c = f * 4;
  186. qua.set(
  187. raw[ c ],
  188. raw[ c + 1 ],
  189. raw[ c + 2 ],
  190. raw[ c + 3 ]
  191. );
  192. break;
  193. case SEA3D.Animation.SCALE:
  194. c = f * 4;
  195. slc.set(
  196. raw[ c ],
  197. raw[ c + 1 ],
  198. raw[ c + 2 ]
  199. );
  200. break;
  201. }
  202. }
  203. buf1.compose( pos, qua, slc );
  204. this.flipScaleMatrix( buf1, false, buf2 );
  205. buf1.decompose( to_pos, to_qua, to_slc );
  206. for ( t = 0; t < t_anm.length; t ++ ) {
  207. var raw = t_anm[ t ].raw,
  208. kind = t_anm[ t ].kind;
  209. switch ( kind ) {
  210. case SEA3D.Animation.POSITION:
  211. c = f * 3;
  212. raw[ c ] = to_pos.x;
  213. raw[ c + 1 ] = to_pos.y;
  214. raw[ c + 2 ] = to_pos.z;
  215. break;
  216. case SEA3D.Animation.ROTATION:
  217. c = f * 4;
  218. raw[ c ] = to_qua.x;
  219. raw[ c + 1 ] = to_qua.y;
  220. raw[ c + 2 ] = to_qua.z;
  221. raw[ c + 3 ] = to_qua.w;
  222. break;
  223. case SEA3D.Animation.SCALE:
  224. c = f * 3;
  225. raw[ c ] = to_slc.x;
  226. raw[ c + 1 ] = to_slc.y;
  227. raw[ c + 2 ] = to_slc.z;
  228. break;
  229. }
  230. }
  231. }
  232. }
  233. animation.isFliped = true;
  234. };
  235. }();
  236. THREE.SEA3D.prototype.readAnimation = function ( sea ) {
  237. if ( ! this.isLegacy( sea ) ) {
  238. this._readAnimation( sea );
  239. }
  240. };
  241. THREE.SEA3D.prototype.getAnimationType = function ( req ) {
  242. var sea = req.sea;
  243. if ( this.isLegacy( sea ) ) {
  244. switch ( sea.type ) {
  245. case SEA3D.SkeletonAnimation.prototype.type:
  246. this.readSkeletonAnimationLegacy( sea, req.skeleton );
  247. return sea.tag;
  248. break;
  249. case SEA3D.Animation.prototype.type:
  250. if ( req.scope instanceof THREE.Object3D ) {
  251. this.flipDefaultAnimation( sea, req.scope, req.relative );
  252. }
  253. this._readAnimation( sea );
  254. return sea.tag;
  255. break;
  256. }
  257. }
  258. return this._getAnimationType( req );
  259. };
  260. THREE.SEA3D.prototype.updateTransform = function () {
  261. var buf1 = new THREE.Matrix4();
  262. var identity = new THREE.Matrix4();
  263. return function ( obj3d, sea ) {
  264. if ( this.isLegacy( sea ) ) {
  265. if ( sea.transform ) buf1.elements.set( sea.transform );
  266. else buf1.makeTranslation( sea.position.x, sea.position.y, sea.position.z );
  267. this.flipScaleMatrix(
  268. buf1, false,
  269. obj3d.parent ? obj3d.parent.matrixWorld : identity,
  270. obj3d.parent instanceof THREE.Bone
  271. );
  272. obj3d.position.setFromMatrixPosition( buf1 );
  273. obj3d.scale.setFromMatrixScale( buf1 );
  274. // ignore rotation scale
  275. buf1.scale( THREE.SEA3D.VECBUF.set( 1 / obj3d.scale.x, 1 / obj3d.scale.y, 1 / obj3d.scale.z ) );
  276. obj3d.rotation.setFromRotationMatrix( buf1 );
  277. obj3d.updateMatrixWorld();
  278. } else {
  279. this._updateTransform( obj3d, sea );
  280. }
  281. };
  282. }();
  283. THREE.SEA3D.prototype.readSkeleton = function () {
  284. var mtx_tmp_inv = new THREE.Matrix4(),
  285. mtx_local = new THREE.Matrix4(),
  286. mtx_parent = new THREE.Matrix4(),
  287. pos = new THREE.Vector3(),
  288. qua = new THREE.Quaternion();
  289. return function ( sea ) {
  290. var bones = [],
  291. isLegacy = sea.sea3d.config.legacy;
  292. for ( var i = 0; i < sea.joint.length; i ++ ) {
  293. var bone = sea.joint[ i ];
  294. // get world inverse matrix
  295. mtx_tmp_inv.elements = bone.inverseBindMatrix;
  296. // convert to world matrix
  297. mtx_local.getInverse( mtx_tmp_inv );
  298. // convert to three.js order
  299. if ( isLegacy ) this.flipBoneMatrix( mtx_local );
  300. if ( bone.parentIndex > - 1 ) {
  301. // to world
  302. mtx_tmp_inv.elements = sea.joint[ bone.parentIndex ].inverseBindMatrix;
  303. mtx_parent.getInverse( mtx_tmp_inv );
  304. // convert parent to three.js order
  305. if ( isLegacy ) this.flipBoneMatrix( mtx_parent );
  306. // to local
  307. mtx_parent.getInverse( mtx_parent );
  308. mtx_local.multiplyMatrices( mtx_parent, mtx_local );
  309. }
  310. // apply matrix
  311. pos.setFromMatrixPosition( mtx_local );
  312. qua.setFromRotationMatrix( mtx_local );
  313. bones[ i ] = {
  314. name: bone.name,
  315. pos: [ pos.x, pos.y, pos.z ],
  316. rotq: [ qua.x, qua.y, qua.z, qua.w ],
  317. parent: bone.parentIndex
  318. };
  319. }
  320. return sea.tag = bones;
  321. };
  322. }();
  323. THREE.SEA3D.prototype.readSkeletonAnimationLegacy = function () {
  324. var mtx_tmp_inv = new THREE.Matrix4(),
  325. mtx_local = new THREE.Matrix4(),
  326. mtx_global = new THREE.Matrix4(),
  327. mtx_parent = new THREE.Matrix4();
  328. return function ( sea, skl ) {
  329. if ( sea.tag ) return sea.tag;
  330. var animations = [],
  331. delta = ( 1000 / sea.frameRate ) / 1000,
  332. scale = [ 1, 1, 1 ];
  333. for ( var i = 0; i < sea.sequence.length; i ++ ) {
  334. var seq = sea.sequence[ i ];
  335. var start = seq.start;
  336. var end = start + seq.count;
  337. var animation = {
  338. name: seq.name,
  339. repeat: seq.repeat,
  340. fps: sea.frameRate,
  341. JIT: 0,
  342. length: delta * seq.count,
  343. hierarchy: []
  344. };
  345. var numJoints = sea.numJoints,
  346. raw = sea.raw;
  347. for ( var j = 0; j < numJoints; j ++ ) {
  348. var bone = skl.joint[ j ],
  349. node = { parent: bone.parentIndex, keys: [] },
  350. keys = node.keys,
  351. time = 0;
  352. for ( var frame = start; frame < end; frame ++ ) {
  353. var idx = ( frame * numJoints * 7 ) + ( j * 7 );
  354. mtx_local.makeRotationFromQuaternion( THREE.SEA3D.QUABUF.set( raw[ idx + 3 ], raw[ idx + 4 ], raw[ idx + 5 ], raw[ idx + 6 ] ) );
  355. mtx_local.setPosition( THREE.SEA3D.VECBUF.set( raw[ idx ], raw[ idx + 1 ], raw[ idx + 2 ] ) );
  356. if ( bone.parentIndex > - 1 ) {
  357. // to global
  358. mtx_tmp_inv.elements = skl.joint[ bone.parentIndex ].inverseBindMatrix;
  359. mtx_parent.getInverse( mtx_tmp_inv );
  360. mtx_global.multiplyMatrices( mtx_parent, mtx_local );
  361. // convert to three.js matrix
  362. this.flipBoneMatrix( mtx_global );
  363. // flip parent inverse
  364. this.flipBoneMatrix( mtx_parent );
  365. // to local
  366. mtx_parent.getInverse( mtx_parent );
  367. mtx_local.multiplyMatrices( mtx_parent, mtx_global );
  368. } else {
  369. this.flipBoneMatrix( mtx_local );
  370. }
  371. var posQ = THREE.SEA3D.VECBUF.setFromMatrixPosition( mtx_local );
  372. var newQ = THREE.SEA3D.QUABUF.setFromRotationMatrix( mtx_local );
  373. keys.push( {
  374. time: time,
  375. pos: [ posQ.x, posQ.y, posQ.z ],
  376. rot: [ newQ.x, newQ.y, newQ.z, newQ.w ],
  377. scl: scale
  378. } );
  379. time += delta;
  380. }
  381. animation.hierarchy[ j ] = node;
  382. }
  383. animations.push( THREE.SEA3D.AnimationClip.fromClip( THREE.AnimationClip.parseAnimation( animation, skl.tag ), seq.repeat ) );
  384. }
  385. this.domain.clips = this.clips = this.clips || [];
  386. this.clips.push( this.objects[ sea.name + '.anm' ] = sea.tag = animations );
  387. };
  388. }();
  389. THREE.SEA3D.prototype.readVertexAnimation = function ( sea ) {
  390. if ( this.isLegacy( sea ) ) {
  391. for ( var i = 0, l = sea.frame.length; i < l; i ++ ) {
  392. var frame = sea.frame[ i ];
  393. this.flipVec3( frame.vertex );
  394. this.flipVec3( frame.normal );
  395. }
  396. }
  397. this._readVertexAnimation( sea );
  398. };
  399. THREE.SEA3D.prototype.readGeometryBuffer = function ( sea ) {
  400. if ( this.isLegacy( sea ) ) {
  401. this.flipVec3( sea.vertex, true );
  402. this.flipVec3( sea.normal, true );
  403. this.flipIndexes( sea.indexes );
  404. if ( sea.jointPerVertex > 4 ) this.compressJoints( sea );
  405. else if ( sea.jointPerVertex < 4 ) this.expandJoints( sea );
  406. }
  407. this._readGeometryBuffer( sea );
  408. };
  409. THREE.SEA3D.prototype.readLines = function ( sea ) {
  410. if ( this.isLegacy( sea ) ) {
  411. this.flipVec3( sea.vertex );
  412. }
  413. this._readLines( sea );
  414. };
  415. THREE.SEA3D.prototype.onHead = function ( args ) {
  416. if ( args.sign != "S3D" && args.sign != "TJS" ) {
  417. throw new Error( "Sign '" + args.sign + "' unknown." );
  418. }
  419. };
  420. THREE.SEA3D.EXTENSIONS_LOADER.push( { setTypeRead: function () {
  421. // CONFIG
  422. this.config.legacy = this.config.legacy == undefined ? true : this.config.legacy;
  423. this.file.typeRead[ SEA3D.Skeleton.prototype.type ] = this.readSkeleton;
  424. } } );