Read_ASF.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include <Max.h>
  19. #include <istdplug.h>
  20. #include "asf_data.h"
  21. #include "read_asf.h"
  22. #include "exception.h"
  23. //----------------------------------------------------------------------------
  24. // ASF_Lexer::ASF_Lexer
  25. //----------------------------------------------------------------------------
  26. ASF_Lexer::ASF_Lexer
  27. (
  28. const char * file_name
  29. ):
  30. Input_file ( file_name, "r" )
  31. {
  32. Current_char = tolower ( fgetc ( Input_file.fp ) );
  33. advance ();
  34. }
  35. //----------------------------------------------------------------------------
  36. // ASF_Lexer::skip_whitespace
  37. //----------------------------------------------------------------------------
  38. // Skip whitespace and comments, leaving the Current_char pointing to the
  39. // first non-whitespace character in the input stream.
  40. //----------------------------------------------------------------------------
  41. void ASF_Lexer::skip_whitespace ()
  42. {
  43. while (1)
  44. {
  45. if ( Current_char == '#' ) // Strip out comments
  46. {
  47. while ( Current_char != '\n' && Current_char != EOF )
  48. Current_char = tolower ( fgetc ( Input_file.fp ) );
  49. }
  50. else if ( (isspace ( Current_char ) && Current_char != '\n') ||
  51. Current_char == ',' ||
  52. Current_char == '(' ||
  53. Current_char == ')' )
  54. {
  55. Current_char = tolower ( fgetc ( Input_file.fp ) );
  56. }
  57. else
  58. {
  59. break;
  60. }
  61. }
  62. }
  63. //----------------------------------------------------------------------------
  64. // ASF_Lexer::advance
  65. //----------------------------------------------------------------------------
  66. // Advance to the next token in the input stream.
  67. //----------------------------------------------------------------------------
  68. void ASF_Lexer::advance ()
  69. {
  70. skip_whitespace ();
  71. if ( Current_char == EOF )
  72. {
  73. Current_type = EOF_MARKER;
  74. strcpy ( Current_text, "<end of file>" );
  75. return;
  76. }
  77. if ( Current_char == '\n' )
  78. {
  79. Current_type = NEWLINE;
  80. strcpy ( Current_text, "<newline>" );
  81. Current_char = tolower ( fgetc ( Input_file.fp ) );
  82. return;
  83. }
  84. Current_type = TOKEN;
  85. // Read characters into the token text buffer.
  86. int i = 0;
  87. while ( ! isspace (Current_char) &&
  88. Current_char != '#' &&
  89. Current_char != ',' &&
  90. Current_char != '(' &&
  91. Current_char != ')' &&
  92. Current_char != EOF )
  93. {
  94. if ( i >= (MAX_TOKEN_LENGTH - 1) )
  95. {
  96. // Abort -- maximum token length exceeded.
  97. throw Parse_Error ( "Maximum token length exceeded." );
  98. }
  99. Current_text [i] = Current_char;
  100. ++ i;
  101. Current_char = tolower ( fgetc ( Input_file.fp ) );
  102. }
  103. Current_text [i] = '\0';
  104. }
  105. //----------------------------------------------------------------------------
  106. // Skeleton_Class::Skeleton_Class
  107. //----------------------------------------------------------------------------
  108. Skeleton_Class::Skeleton_Class
  109. (
  110. const char * file_name,
  111. ImpInterface * iface,
  112. Interface * gi
  113. ) :
  114. Angle_multiplier (DEGREES_TO_RADIANS),
  115. Length_multiplier (1.0f),
  116. First_bone (NULL),
  117. Import_interface (iface),
  118. Max_interface (gi)
  119. {
  120. ASF_Lexer lexer ( file_name );
  121. parse_units_block ( lexer );
  122. parse_root_block ( lexer );
  123. parse_bonedata_block ( lexer );
  124. parse_hierarchy_block ( lexer );
  125. }
  126. //----------------------------------------------------------------------------
  127. // Skeleton_Class::~Skeleton_Class
  128. //----------------------------------------------------------------------------
  129. Skeleton_Class::~Skeleton_Class ()
  130. {
  131. Bone_Class * p = First_bone;
  132. while ( p != NULL )
  133. {
  134. Bone_Class * delete_p = p;
  135. p = p->next_bone ();
  136. delete delete_p;
  137. }
  138. }
  139. //----------------------------------------------------------------------------
  140. // Skeleton_Class::parse_units_block
  141. //----------------------------------------------------------------------------
  142. void Skeleton_Class::parse_units_block ( ASF_Lexer & lexer )
  143. {
  144. skip_unrecognized_blocks ( lexer );
  145. match_token ( lexer, ":units" );
  146. match_newline ( lexer );
  147. BOOL mass_defined = FALSE;
  148. BOOL length_defined = FALSE;
  149. BOOL angle_defined = FALSE;
  150. while (1)
  151. {
  152. verify_token ( lexer );
  153. if ( strcmp ( lexer.text (), "mass" ) == 0 )
  154. {
  155. if ( mass_defined )
  156. throw Parse_Error ( "Multiple mass definitions." );
  157. lexer.advance ();
  158. skip_token ( lexer ); // Ignore the mass definition.
  159. match_newline ( lexer );
  160. mass_defined = TRUE;
  161. }
  162. else if ( strcmp ( lexer.text (), "length" ) == 0 )
  163. {
  164. if ( length_defined )
  165. throw Parse_Error ( "Multiple length definitions." );
  166. lexer.advance ();
  167. verify_token ( lexer );
  168. Length_multiplier = 1.0f / float_token ( lexer );
  169. match_newline ( lexer );
  170. length_defined = TRUE;
  171. }
  172. else if ( strcmp ( lexer.text (), "angle" ) == 0 )
  173. {
  174. if ( angle_defined )
  175. throw Parse_Error ( "Multiple angle definitions." );
  176. lexer.advance ();
  177. verify_token ( lexer );
  178. if ( strcmp ( lexer.text (), "deg" ) == 0 )
  179. Angle_multiplier = DEGREES_TO_RADIANS;
  180. else if ( strcmp ( lexer.text (), "rad" ) == 0 )
  181. Angle_multiplier = 1.0f;
  182. else
  183. throw Parse_Error
  184. ( "\"deg\" or \"rad\" expected after angle keyword." );
  185. lexer.advance ();
  186. match_newline ( lexer );
  187. angle_defined = TRUE;
  188. }
  189. else
  190. {
  191. break;
  192. }
  193. }
  194. }
  195. //----------------------------------------------------------------------------
  196. // Skeleton_Class::parse_root_block
  197. //----------------------------------------------------------------------------
  198. void Skeleton_Class::parse_root_block ( ASF_Lexer & lexer )
  199. {
  200. skip_unrecognized_blocks ( lexer );
  201. match_token ( lexer, ":root" );
  202. match_newline ( lexer );
  203. // Create a root bone.
  204. Bone_Class * new_bone = new Bone_Class;
  205. new_bone->set_name ( "root" );
  206. // The rotation order for orientation offset.
  207. match_token ( lexer, "axis" );
  208. skip_token ( lexer ); // &&& get rotation order for orientation offset.
  209. match_newline ( lexer );
  210. // The order of transformations for root.
  211. match_token ( lexer, "order" );
  212. for ( int i = 0; i < 6; ++ i )
  213. {
  214. verify_token ( lexer );
  215. if ( strcmp ( lexer.text (), "rx" ) == 0 )
  216. new_bone->add_axis ( ROTATE_X );
  217. else if ( strcmp ( lexer.text (), "ry" ) == 0 )
  218. new_bone->add_axis ( ROTATE_Y );
  219. else if ( strcmp ( lexer.text (), "rz" ) == 0 )
  220. new_bone->add_axis ( ROTATE_Z );
  221. else if ( strcmp ( lexer.text (), "tx" ) == 0 )
  222. new_bone->add_axis ( TRANSLATE_X );
  223. else if ( strcmp ( lexer.text (), "ty" ) == 0 )
  224. new_bone->add_axis ( TRANSLATE_Y );
  225. else if ( strcmp ( lexer.text (), "tz" ) == 0 )
  226. new_bone->add_axis ( TRANSLATE_Z );
  227. else
  228. throw Parse_Error ( "Unrecognized order token in :root." );
  229. lexer.advance ();
  230. }
  231. match_newline ( lexer );
  232. // Translation data for root node.
  233. match_token ( lexer, "position" );
  234. skip_token ( lexer ); // &&&
  235. skip_token ( lexer ); // &&&
  236. skip_token ( lexer ); // &&&
  237. match_newline ( lexer );
  238. // Rotation data to orient the skeleton.
  239. match_token ( lexer, "orientation" );
  240. float rot0 = float_token ( lexer ) * Angle_multiplier;
  241. float rot1 = float_token ( lexer ) * Angle_multiplier;
  242. float rot2 = float_token ( lexer ) * Angle_multiplier;
  243. match_newline ( lexer );
  244. Matrix3 axis_tm;
  245. axis_tm.IdentityMatrix ();
  246. axis_tm.RotateX ( rot0 );
  247. axis_tm.RotateY ( rot1 );
  248. axis_tm.RotateZ ( rot2 );
  249. new_bone->set_axis_tm ( axis_tm );
  250. new_bone->set_direction ( Point3 (0,0,0) );
  251. new_bone->set_length ( 0.0f );
  252. add_bone_to_list ( new_bone );
  253. new_bone->create_node ( Import_interface, Max_interface );
  254. // Add an AppData chunk to the root node to indicate how much to scale
  255. // its position keys.
  256. Position_Key_Scale_Chunk * data_p = (Position_Key_Scale_Chunk *)
  257. malloc ( sizeof (Position_Key_Scale_Chunk) );
  258. data_p->Position_Key_Scale = Length_multiplier;
  259. new_bone->add_app_data ( 2, data_p, sizeof (Position_Key_Scale_Chunk) );
  260. }
  261. //----------------------------------------------------------------------------
  262. // Skeleton_Class::parse_bonedata_block
  263. //----------------------------------------------------------------------------
  264. void Skeleton_Class::parse_bonedata_block ( ASF_Lexer & lexer )
  265. {
  266. skip_unrecognized_blocks ( lexer );
  267. match_token ( lexer, ":bonedata" );
  268. match_newline ( lexer );
  269. // Parse bone definition blocks.
  270. while (1)
  271. {
  272. verify_token ( lexer );
  273. if ( strcmp ( lexer.text (), "begin" ) == 0 )
  274. {
  275. parse_bone ( lexer );
  276. }
  277. else
  278. {
  279. break;
  280. }
  281. }
  282. }
  283. //----------------------------------------------------------------------------
  284. // Skeleton_Class::parse_hierarchy_block
  285. //----------------------------------------------------------------------------
  286. void Skeleton_Class::parse_hierarchy_block ( ASF_Lexer & lexer )
  287. {
  288. skip_unrecognized_blocks ( lexer );
  289. match_token ( lexer, ":hierarchy" );
  290. match_newline ( lexer );
  291. match_token ( lexer, "begin" );
  292. match_newline ( lexer );
  293. while (1)
  294. {
  295. verify_token ( lexer );
  296. if ( strcmp ( lexer.text (), "end" ) == 0 )
  297. {
  298. break;
  299. }
  300. else
  301. {
  302. parse_hierarchy_line ( lexer );
  303. }
  304. }
  305. lexer.advance ();
  306. match_newline ( lexer );
  307. }
  308. //----------------------------------------------------------------------------
  309. // Skeleton_Class::parse_hierarchy_line
  310. //----------------------------------------------------------------------------
  311. void Skeleton_Class::parse_hierarchy_line ( ASF_Lexer & lexer )
  312. {
  313. verify_token ( lexer );
  314. Bone_Class * parent_bone = find_bone ( lexer.text () );
  315. if ( parent_bone == NULL )
  316. throw Parse_Error ( "Undefined parent bone." );
  317. lexer.advance ();
  318. while ( lexer.type () == TOKEN )
  319. {
  320. Bone_Class * child_bone = find_bone ( lexer.text () );
  321. if ( child_bone == NULL )
  322. throw Parse_Error ( "Undefined child bone." );
  323. child_bone->set_parent ( parent_bone );
  324. lexer.advance ();
  325. }
  326. match_newline ( lexer );
  327. }
  328. //----------------------------------------------------------------------------
  329. // Skeleton_Class::find_bone
  330. //----------------------------------------------------------------------------
  331. Bone_Class * Skeleton_Class::find_bone ( const char * name )
  332. {
  333. Bone_Class * p = First_bone;
  334. while ( p != NULL )
  335. {
  336. if ( strcmp ( name, p->name () ) == 0 )
  337. break;
  338. p = p->next_bone ();
  339. }
  340. return p;
  341. }
  342. //----------------------------------------------------------------------------
  343. // lh_to_rh
  344. //----------------------------------------------------------------------------
  345. static Point3 lh_to_rh ( Point3 point )
  346. {
  347. Point3 new_point;
  348. new_point.x = point.x;
  349. new_point.y = -point.z;
  350. new_point.z = point.y;
  351. return new_point;
  352. }
  353. //----------------------------------------------------------------------------
  354. // Skeleton_Class::parse_bone
  355. //----------------------------------------------------------------------------
  356. void Skeleton_Class::parse_bone ( ASF_Lexer & lexer )
  357. {
  358. match_token ( lexer, "begin" );
  359. match_newline ( lexer );
  360. // Create a new bone object.
  361. Bone_Class * new_bone = new Bone_Class;
  362. // Optional ID number.
  363. verify_token ( lexer );
  364. if ( strcmp ( lexer.text (), "id" ) == 0 )
  365. {
  366. lexer.advance ();
  367. skip_token ( lexer ); // Ignore the bone ID number for now.
  368. match_newline ( lexer );
  369. }
  370. // Name.
  371. match_token ( lexer, "name" );
  372. verify_token ( lexer );
  373. new_bone->set_name ( lexer.text () );
  374. lexer.advance ();
  375. match_newline ( lexer );
  376. // Direction vector.
  377. match_token ( lexer, "direction" );
  378. Point3 direction;
  379. direction.x = float_token ( lexer );
  380. direction.y = float_token ( lexer );
  381. direction.z = float_token ( lexer );
  382. new_bone->set_direction ( direction );
  383. match_newline ( lexer );
  384. // Length.
  385. match_token ( lexer, "length" );
  386. new_bone->set_length ( float_token ( lexer ) * Length_multiplier / (float)GetMasterScale(UNITS_INCHES));
  387. match_newline ( lexer );
  388. // Rotation axis in world coordinates, with order of rotations.
  389. match_token ( lexer, "axis" );
  390. float rot0 = float_token ( lexer ) * Angle_multiplier;
  391. float rot1 = float_token ( lexer ) * Angle_multiplier;
  392. float rot2 = float_token ( lexer ) * Angle_multiplier;
  393. // &&& Ultimately this should handle any order of rotations.
  394. match_token ( lexer, "xyz" );
  395. match_newline ( lexer );
  396. Matrix3 axis_tm;
  397. axis_tm.IdentityMatrix ();
  398. axis_tm.RotateX ( rot0 );
  399. axis_tm.RotateY ( rot1 );
  400. axis_tm.RotateZ ( rot2 );
  401. new_bone->set_axis_tm ( axis_tm );
  402. // Optional mass of skinbody associated with this bone.
  403. verify_token ( lexer );
  404. if ( strcmp ( lexer.text (), "bodymass" ) == 0 )
  405. {
  406. lexer.advance ();
  407. skip_token ( lexer ); // Ignore the bodymass.
  408. match_newline ( lexer );
  409. }
  410. // Optional position of center of mass along the bone.
  411. verify_token ( lexer );
  412. if ( strcmp ( lexer.text (), "cofmass" ) == 0 )
  413. {
  414. lexer.advance ();
  415. skip_token ( lexer ); // Ignore the center of mass position.
  416. match_newline ( lexer );
  417. }
  418. // Optional degrees of freedom.
  419. verify_token ( lexer );
  420. if ( strcmp ( lexer.text (), "dof" ) == 0 )
  421. {
  422. lexer.advance ();
  423. if ( lexer.type () == TOKEN && strcmp ( lexer.text (), "rx" ) == 0 )
  424. {
  425. new_bone->add_axis ( ROTATE_X );
  426. lexer.advance ();
  427. }
  428. if ( lexer.type () == TOKEN && strcmp ( lexer.text (), "ry" ) == 0 )
  429. {
  430. new_bone->add_axis ( ROTATE_Y );
  431. lexer.advance ();
  432. }
  433. if ( lexer.type () == TOKEN && strcmp ( lexer.text (), "rz" ) == 0 )
  434. {
  435. new_bone->add_axis ( ROTATE_Z );
  436. lexer.advance ();
  437. }
  438. if ( lexer.type () == TOKEN && strcmp ( lexer.text (), "l" ) == 0 )
  439. {
  440. new_bone->add_axis ( TRANSLATE_LENGTH );
  441. lexer.advance ();
  442. }
  443. match_newline ( lexer );
  444. // Limits for the given degrees of freedom.
  445. match_token ( lexer, "limits" );
  446. // &&&
  447. while ( strcmp ( lexer.text (), "end" ) != 0 )
  448. lexer.advance ();
  449. }
  450. match_token ( lexer, "end" );
  451. match_newline ( lexer );
  452. // Add the bone to the list of bones.
  453. add_bone_to_list ( new_bone );
  454. new_bone->create_node ( Import_interface, Max_interface );
  455. }
  456. //----------------------------------------------------------------------------
  457. // Skeleton_Class::skip_unrecognized_blocks
  458. //----------------------------------------------------------------------------
  459. // It is assumed that the current lexeme is the first on a line.
  460. //----------------------------------------------------------------------------
  461. void Skeleton_Class::skip_unrecognized_blocks
  462. (
  463. ASF_Lexer & lexer
  464. )
  465. {
  466. while (1)
  467. {
  468. if ( lexer.type () == EOF_MARKER )
  469. break;
  470. if ( strcmp ( lexer.text (), ":units" ) == 0 )
  471. break;
  472. if ( strcmp ( lexer.text (), ":root" ) == 0 )
  473. break;
  474. if ( strcmp ( lexer.text (), ":bonedata" ) == 0 )
  475. break;
  476. if ( strcmp ( lexer.text (), ":hierarchy" ) == 0 )
  477. break;
  478. skip_to_next_line ( lexer );
  479. }
  480. }
  481. //----------------------------------------------------------------------------
  482. // Skeleton_Class::skip_to_next_line
  483. //----------------------------------------------------------------------------
  484. void Skeleton_Class::skip_to_next_line
  485. (
  486. ASF_Lexer & lexer
  487. )
  488. {
  489. while ( lexer.type () != NEWLINE &&
  490. lexer.type () != EOF_MARKER )
  491. lexer.advance ();
  492. if ( lexer.type () == NEWLINE )
  493. lexer.advance ();
  494. }
  495. //----------------------------------------------------------------------------
  496. // Skeleton_Class::match_newline
  497. //----------------------------------------------------------------------------
  498. void Skeleton_Class::match_newline
  499. (
  500. ASF_Lexer & lexer
  501. )
  502. {
  503. char message_buffer [ 512 ];
  504. if ( lexer.type () != NEWLINE )
  505. {
  506. sprintf ( message_buffer, "Expected newline; found \"%s\" instead.",
  507. lexer.text () );
  508. throw Parse_Error ( message_buffer );
  509. }
  510. lexer.advance ();
  511. }
  512. //----------------------------------------------------------------------------
  513. // Skeleton_Class::verify_token
  514. //----------------------------------------------------------------------------
  515. void Skeleton_Class::verify_token
  516. (
  517. ASF_Lexer & lexer
  518. )
  519. {
  520. char message_buffer [ 512 ];
  521. if ( lexer.type () != TOKEN )
  522. {
  523. sprintf ( message_buffer, "Expected token; found \"%s\" instead.",
  524. lexer.text () );
  525. throw Parse_Error ( message_buffer );
  526. }
  527. }
  528. //----------------------------------------------------------------------------
  529. // Skeleton_Class::skip_token
  530. //----------------------------------------------------------------------------
  531. void Skeleton_Class::skip_token
  532. (
  533. ASF_Lexer & lexer
  534. )
  535. {
  536. verify_token ( lexer );
  537. lexer.advance ();
  538. }
  539. //----------------------------------------------------------------------------
  540. // Skeleton_Class::float_token
  541. //----------------------------------------------------------------------------
  542. float Skeleton_Class::float_token
  543. (
  544. ASF_Lexer & lexer
  545. )
  546. {
  547. verify_token ( lexer );
  548. float value = (float) strtod ( lexer.text (), NULL );
  549. lexer.advance ();
  550. return value;
  551. }
  552. //----------------------------------------------------------------------------
  553. // Skeleton_Class::match_token
  554. //----------------------------------------------------------------------------
  555. void Skeleton_Class::match_token
  556. (
  557. ASF_Lexer & lexer,
  558. const char * token_text
  559. )
  560. {
  561. char message_buffer [ 512 ];
  562. verify_token ( lexer );
  563. if ( strcmp ( lexer.text (), token_text ) != 0 )
  564. {
  565. sprintf ( message_buffer, "Expected \"%s\"; found \"%s\" instead.",
  566. token_text, lexer.text () );
  567. throw Parse_Error ( message_buffer );
  568. }
  569. lexer.advance ();
  570. }
  571. //----------------------------------------------------------------------------
  572. // Skeleton_Class::add_bone_to_list
  573. //----------------------------------------------------------------------------
  574. void Skeleton_Class::add_bone_to_list
  575. (
  576. Bone_Class * new_bone
  577. )
  578. {
  579. new_bone->set_next_bone ( First_bone );
  580. First_bone = new_bone;
  581. }
  582. //----------------------------------------------------------------------------
  583. // Bone_Class::create_node
  584. //----------------------------------------------------------------------------
  585. void Bone_Class::create_node
  586. (
  587. ImpInterface * import_interface,
  588. Interface * max_interface
  589. )
  590. {
  591. Node = import_interface->CreateNode ();
  592. Node->SetName ( Name );
  593. // Create a box object.
  594. GeomObject * obj = (GeomObject *) max_interface->CreateInstance
  595. ( GEOMOBJECT_CLASS_ID, Class_ID (BOXOBJ_CLASS_ID, 0) );
  596. IParamArray *iBoxParams = obj->GetParamBlock();
  597. assert(iBoxParams);
  598. // Set the value of width, height and length.
  599. int width_index = obj->GetParamBlockIndex(BOXOBJ_WIDTH);
  600. assert(width_index >= 0);
  601. iBoxParams->SetValue(width_index,TimeValue(0),Length / 4);
  602. int height_index = obj->GetParamBlockIndex(BOXOBJ_HEIGHT);
  603. assert(height_index >= 0);
  604. iBoxParams->SetValue(height_index,TimeValue(0),Length);
  605. int length_index = obj->GetParamBlockIndex(BOXOBJ_LENGTH);
  606. assert(length_index >= 0);
  607. iBoxParams->SetValue(length_index,TimeValue(0),Length / 4);
  608. Node->Reference ( (Object *) obj );
  609. Node->GetINode ()->SetNodeTM ( 0, Axis_tm );
  610. // Add the node to the scene.
  611. import_interface->AddNodeToScene ( Node );
  612. // Add an AppData chunk to the inode to indicate which transformation
  613. // axes are active.
  614. ASF_Data_Chunk * data_p = (ASF_Data_Chunk *)
  615. malloc ( sizeof (ASF_Data_Chunk) );
  616. *data_p = Active_axes;
  617. add_app_data ( 1, data_p, sizeof (ASF_Data_Chunk) );
  618. }
  619. //----------------------------------------------------------------------------
  620. // Bone_Class::set_parent
  621. //----------------------------------------------------------------------------
  622. void Bone_Class::set_parent ( Bone_Class * parent_bone )
  623. {
  624. Parent_bone = parent_bone;
  625. parent_bone->Node->GetINode ()->AttachChild ( Node->GetINode () );
  626. // Build the child node's transform matrix.
  627. Matrix3 parent_tm = Node->GetINode ()->GetParentTM ( 0 );
  628. Matrix3 child_tm = Axis_tm;
  629. child_tm.Translate ( Normalize (parent_bone->Direction) *
  630. parent_bone->Length );
  631. child_tm.Translate ( parent_tm.GetTrans () );
  632. Node->GetINode ()->SetNodeTM ( 0, child_tm );
  633. }
  634. //----------------------------------------------------------------------------
  635. // Bone_Class::add_app_data
  636. //----------------------------------------------------------------------------
  637. void Bone_Class::add_app_data ( int chunk_id, void * data, int data_size )
  638. {
  639. Node->GetINode ()->AddAppDataChunk
  640. (
  641. Class_ID(0x74975aa6, 0x1810323f),
  642. SCENE_IMPORT_CLASS_ID,
  643. chunk_id,
  644. data_size,
  645. data
  646. );
  647. }