DeclAF.cpp 46 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748
  1. /*
  2. ===========================================================================
  3. Doom 3 BFG Edition GPL Source Code
  4. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
  6. Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 BFG Edition Source Code 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. You should have received a copy of the GNU General Public License
  15. along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #include "../idlib/precompiled.h"
  21. #pragma hdrstop
  22. /*
  23. ===============================================================================
  24. idDeclAF
  25. ===============================================================================
  26. */
  27. /*
  28. ================
  29. idAFVector::idAFVector
  30. ================
  31. */
  32. idAFVector::idAFVector() {
  33. type = VEC_COORDS;
  34. vec.Zero();
  35. negate = false;
  36. }
  37. /*
  38. ================
  39. idAFVector::Parse
  40. ================
  41. */
  42. bool idAFVector::Parse( idLexer &src ) {
  43. idToken token;
  44. if ( !src.ReadToken( &token ) ) {
  45. return false;
  46. }
  47. if ( token == "-" ) {
  48. negate = true;
  49. if ( !src.ReadToken( &token ) ) {
  50. return false;
  51. }
  52. }
  53. else {
  54. negate = false;
  55. }
  56. if ( token == "(" ) {
  57. type = idAFVector::VEC_COORDS;
  58. vec.x = src.ParseFloat();
  59. src.ExpectTokenString( "," );
  60. vec.y = src.ParseFloat();
  61. src.ExpectTokenString( "," );
  62. vec.z = src.ParseFloat();
  63. src.ExpectTokenString( ")" );
  64. }
  65. else if ( token == "joint" ) {
  66. type = idAFVector::VEC_JOINT;
  67. src.ExpectTokenString( "(" );
  68. src.ReadToken( &token );
  69. joint1 = token;
  70. src.ExpectTokenString( ")" );
  71. }
  72. else if ( token == "bonecenter" ) {
  73. type = idAFVector::VEC_BONECENTER;
  74. src.ExpectTokenString( "(" );
  75. src.ReadToken( &token );
  76. joint1 = token;
  77. src.ExpectTokenString( "," );
  78. src.ReadToken( &token );
  79. joint2 = token;
  80. src.ExpectTokenString( ")" );
  81. }
  82. else if ( token == "bonedir" ) {
  83. type = idAFVector::VEC_BONEDIR;
  84. src.ExpectTokenString( "(" );
  85. src.ReadToken( &token );
  86. joint1 = token;
  87. src.ExpectTokenString( "," );
  88. src.ReadToken( &token );
  89. joint2 = token;
  90. src.ExpectTokenString( ")" );
  91. }
  92. else {
  93. src.Error( "unknown token %s in vector", token.c_str() );
  94. return false;
  95. }
  96. return true;
  97. }
  98. /*
  99. ================
  100. idAFVector::Finish
  101. ================
  102. */
  103. bool idAFVector::Finish( const char *fileName, const getJointTransform_t GetJointTransform, const idJointMat *frame, void *model ) const {
  104. idMat3 axis;
  105. idVec3 start, end;
  106. switch( type ) {
  107. case idAFVector::VEC_COORDS: {
  108. break;
  109. }
  110. case idAFVector::VEC_JOINT: {
  111. if ( !GetJointTransform( model, frame, joint1, vec, axis ) ) {
  112. common->Warning( "invalid joint %s in joint() in '%s'", joint1.c_str(), fileName );
  113. vec.Zero();
  114. }
  115. break;
  116. }
  117. case idAFVector::VEC_BONECENTER: {
  118. if ( !GetJointTransform( model, frame, joint1, start, axis ) ) {
  119. common->Warning( "invalid joint %s in bonecenter() in '%s'", joint1.c_str(), fileName );
  120. start.Zero();
  121. }
  122. if ( !GetJointTransform( model, frame, joint2, end, axis ) ) {
  123. common->Warning( "invalid joint %s in bonecenter() in '%s'", joint2.c_str(), fileName );
  124. end.Zero();
  125. }
  126. vec = ( start + end ) * 0.5f;
  127. break;
  128. }
  129. case idAFVector::VEC_BONEDIR: {
  130. if ( !GetJointTransform( model, frame, joint1, start, axis ) ) {
  131. common->Warning( "invalid joint %s in bonedir() in '%s'", joint1.c_str(), fileName );
  132. start.Zero();
  133. }
  134. if ( !GetJointTransform( model, frame, joint2, end, axis ) ) {
  135. common->Warning( "invalid joint %s in bonedir() in '%s'", joint2.c_str(), fileName );
  136. end.Zero();
  137. }
  138. vec = ( end - start );
  139. break;
  140. }
  141. default: {
  142. vec.Zero();
  143. break;
  144. }
  145. }
  146. if ( negate ) {
  147. vec = -vec;
  148. }
  149. return true;
  150. }
  151. /*
  152. ================
  153. idAFVector::Write
  154. ================
  155. */
  156. bool idAFVector::Write( idFile *f ) const {
  157. if ( negate ) {
  158. f->WriteFloatString( "-" );
  159. }
  160. switch( type ) {
  161. case idAFVector::VEC_COORDS: {
  162. f->WriteFloatString( "( %f, %f, %f )", vec.x, vec.y, vec.z );
  163. break;
  164. }
  165. case idAFVector::VEC_JOINT: {
  166. f->WriteFloatString( "joint( \"%s\" )", joint1.c_str() );
  167. break;
  168. }
  169. case idAFVector::VEC_BONECENTER: {
  170. f->WriteFloatString( "bonecenter( \"%s\", \"%s\" )", joint1.c_str(), joint2.c_str() );
  171. break;
  172. }
  173. case idAFVector::VEC_BONEDIR: {
  174. f->WriteFloatString( "bonedir( \"%s\", \"%s\" )", joint1.c_str(), joint2.c_str() );
  175. break;
  176. }
  177. default: {
  178. break;
  179. }
  180. }
  181. return true;
  182. }
  183. /*
  184. ================
  185. idAFVector::ToString
  186. ================
  187. */
  188. const char *idAFVector::ToString( idStr &str, const int precision ) {
  189. switch( type ) {
  190. case idAFVector::VEC_COORDS: {
  191. char format[128];
  192. sprintf( format, "( %%.%df, %%.%df, %%.%df )", precision, precision, precision );
  193. sprintf( str, format, vec.x, vec.y, vec.z );
  194. break;
  195. }
  196. case idAFVector::VEC_JOINT: {
  197. sprintf( str, "joint( \"%s\" )", joint1.c_str() );
  198. break;
  199. }
  200. case idAFVector::VEC_BONECENTER: {
  201. sprintf( str, "bonecenter( \"%s\", \"%s\" )", joint1.c_str(), joint2.c_str() );
  202. break;
  203. }
  204. case idAFVector::VEC_BONEDIR: {
  205. sprintf( str, "bonedir( \"%s\", \"%s\" )", joint1.c_str(), joint2.c_str() );
  206. break;
  207. }
  208. default: {
  209. break;
  210. }
  211. }
  212. if ( negate ) {
  213. str = "-" + str;
  214. }
  215. return str.c_str();
  216. }
  217. /*
  218. ================
  219. idDeclAF_Body::SetDefault
  220. ================
  221. */
  222. void idDeclAF_Body::SetDefault( const idDeclAF *file ) {
  223. name = "noname";
  224. modelType = TRM_BOX;
  225. v1.type = idAFVector::VEC_COORDS;
  226. v1.ToVec3().x = v1.ToVec3().y = v1.ToVec3().z = -10.0f;
  227. v2.type = idAFVector::VEC_COORDS;
  228. v2.ToVec3().x = v2.ToVec3().y = v2.ToVec3().z = 10.0f;
  229. numSides = 3;
  230. origin.ToVec3().Zero();
  231. angles.Zero();
  232. density = 0.2f;
  233. inertiaScale.Identity();
  234. linearFriction = file->defaultLinearFriction;
  235. angularFriction = file->defaultAngularFriction;
  236. contactFriction = file->defaultContactFriction;
  237. contents = file->contents;
  238. clipMask = file->clipMask;
  239. selfCollision = file->selfCollision;
  240. frictionDirection.ToVec3().Zero();
  241. contactMotorDirection.ToVec3().Zero();
  242. jointName = "origin";
  243. jointMod = DECLAF_JOINTMOD_AXIS;
  244. containedJoints = "*origin";
  245. }
  246. /*
  247. ================
  248. idDeclAF_Constraint::SetDefault
  249. ================
  250. */
  251. void idDeclAF_Constraint::SetDefault( const idDeclAF *file ) {
  252. name = "noname";
  253. type = DECLAF_CONSTRAINT_UNIVERSALJOINT;
  254. if ( file->bodies.Num() ) {
  255. body1 = file->bodies[0]->name;
  256. }
  257. else {
  258. body1 = "world";
  259. }
  260. body2 = "world";
  261. friction = file->defaultConstraintFriction;
  262. anchor.ToVec3().Zero();
  263. anchor2.ToVec3().Zero();
  264. axis.ToVec3().Set( 1.0f, 0.0f, 0.0f );
  265. shaft[0].ToVec3().Set( 0.0f, 0.0f, -1.0f );
  266. shaft[1].ToVec3().Set( 0.0f, 0.0f, 1.0f );
  267. limit = idDeclAF_Constraint::LIMIT_NONE;
  268. limitAngles[0] =
  269. limitAngles[1] =
  270. limitAngles[2] = 0.0f;
  271. limitAxis.ToVec3().Set( 0.0f, 0.0f, -1.0f );
  272. }
  273. /*
  274. ================
  275. idDeclAF::WriteBody
  276. ================
  277. */
  278. bool idDeclAF::WriteBody( idFile *f, const idDeclAF_Body &body ) const {
  279. idStr str;
  280. f->WriteFloatString( "\nbody \"%s\" {\n", body.name.c_str() );
  281. f->WriteFloatString( "\tjoint \"%s\"\n", body.jointName.c_str() );
  282. f->WriteFloatString( "\tmod %s\n", JointModToString( body.jointMod ) );
  283. switch( body.modelType ) {
  284. case TRM_BOX: {
  285. f->WriteFloatString( "\tmodel box( " );
  286. body.v1.Write( f );
  287. f->WriteFloatString( ", " );
  288. body.v2.Write( f );
  289. f->WriteFloatString( " )\n" );
  290. break;
  291. }
  292. case TRM_OCTAHEDRON: {
  293. f->WriteFloatString( "\tmodel octahedron( " );
  294. body.v1.Write( f );
  295. f->WriteFloatString( ", " );
  296. body.v2.Write( f );
  297. f->WriteFloatString( " )\n" );
  298. break;
  299. }
  300. case TRM_DODECAHEDRON: {
  301. f->WriteFloatString( "\tmodel dodecahedron( " );
  302. body.v1.Write( f );
  303. f->WriteFloatString( ", " );
  304. body.v2.Write( f );
  305. f->WriteFloatString( " )\n" );
  306. break;
  307. }
  308. case TRM_CYLINDER: {
  309. f->WriteFloatString( "\tmodel cylinder( " );
  310. body.v1.Write( f );
  311. f->WriteFloatString( ", " );
  312. body.v2.Write( f );
  313. f->WriteFloatString( ", %d )\n", body.numSides );
  314. break;
  315. }
  316. case TRM_CONE: {
  317. f->WriteFloatString( "\tmodel cone( " );
  318. body.v1.Write( f );
  319. f->WriteFloatString( ", " );
  320. body.v2.Write( f );
  321. f->WriteFloatString( ", %d )\n", body.numSides );
  322. break;
  323. }
  324. case TRM_BONE: {
  325. f->WriteFloatString( "\tmodel bone( " );
  326. body.v1.Write( f );
  327. f->WriteFloatString( ", " );
  328. body.v2.Write( f );
  329. f->WriteFloatString( ", %f )\n", body.width );
  330. break;
  331. }
  332. default:
  333. assert( 0 );
  334. break;
  335. }
  336. f->WriteFloatString( "\torigin " );
  337. body.origin.Write( f );
  338. f->WriteFloatString( "\n" );
  339. if ( body.angles != ang_zero ) {
  340. f->WriteFloatString( "\tangles ( %f, %f, %f )\n", body.angles.pitch, body.angles.yaw, body.angles.roll );
  341. }
  342. f->WriteFloatString( "\tdensity %f\n", body.density );
  343. if ( body.inertiaScale != mat3_identity ) {
  344. const idMat3 &ic = body.inertiaScale;
  345. f->WriteFloatString( "\tinertiaScale (%f %f %f %f %f %f %f %f %f)\n",
  346. ic[0][0], ic[0][1], ic[0][2],
  347. ic[1][0], ic[1][1], ic[1][2],
  348. ic[2][0], ic[2][1], ic[2][2] );
  349. }
  350. if ( body.linearFriction != -1 ) {
  351. f->WriteFloatString( "\tfriction %f, %f, %f\n", body.linearFriction, body.angularFriction, body.contactFriction );
  352. }
  353. f->WriteFloatString( "\tcontents %s\n", ContentsToString( body.contents, str ) );
  354. f->WriteFloatString( "\tclipMask %s\n", ContentsToString( body.clipMask, str ) );
  355. f->WriteFloatString( "\tselfCollision %d\n", body.selfCollision );
  356. if ( body.frictionDirection.ToVec3() != vec3_origin ) {
  357. f->WriteFloatString( "\tfrictionDirection " );
  358. body.frictionDirection.Write( f );
  359. f->WriteFloatString( "\n" );
  360. }
  361. if ( body.contactMotorDirection.ToVec3() != vec3_origin ) {
  362. f->WriteFloatString( "\tcontactMotorDirection " );
  363. body.contactMotorDirection.Write( f );
  364. f->WriteFloatString( "\n" );
  365. }
  366. f->WriteFloatString( "\tcontainedJoints \"%s\"\n", body.containedJoints.c_str() );
  367. f->WriteFloatString( "}\n" );
  368. return true;
  369. }
  370. /*
  371. ================
  372. idDeclAF::WriteFixed
  373. ================
  374. */
  375. bool idDeclAF::WriteFixed( idFile *f, const idDeclAF_Constraint &c ) const {
  376. f->WriteFloatString( "\nfixed \"%s\" {\n", c.name.c_str() );
  377. f->WriteFloatString( "\tbody1 \"%s\"\n", c.body1.c_str() );
  378. f->WriteFloatString( "\tbody2 \"%s\"\n", c.body2.c_str() );
  379. f->WriteFloatString( "}\n" );
  380. return true;
  381. }
  382. /*
  383. ================
  384. idDeclAF::WriteBallAndSocketJoint
  385. ================
  386. */
  387. bool idDeclAF::WriteBallAndSocketJoint( idFile *f, const idDeclAF_Constraint &c ) const {
  388. f->WriteFloatString( "\nballAndSocketJoint \"%s\" {\n", c.name.c_str() );
  389. f->WriteFloatString( "\tbody1 \"%s\"\n", c.body1.c_str() );
  390. f->WriteFloatString( "\tbody2 \"%s\"\n", c.body2.c_str() );
  391. f->WriteFloatString( "\tanchor " );
  392. c.anchor.Write( f );
  393. f->WriteFloatString( "\n" );
  394. f->WriteFloatString( "\tfriction %f\n", c.friction );
  395. if ( c.limit == idDeclAF_Constraint::LIMIT_CONE ) {
  396. f->WriteFloatString( "\tconeLimit " );
  397. c.limitAxis.Write( f );
  398. f->WriteFloatString( ", %f, ", c.limitAngles[0] );
  399. c.shaft[0].Write( f );
  400. f->WriteFloatString( "\n" );
  401. }
  402. else if ( c.limit == idDeclAF_Constraint::LIMIT_PYRAMID ) {
  403. f->WriteFloatString( "\tpyramidLimit " );
  404. c.limitAxis.Write( f );
  405. f->WriteFloatString( ", %f, %f, %f, ", c.limitAngles[0], c.limitAngles[1], c.limitAngles[2] );
  406. c.shaft[0].Write( f );
  407. f->WriteFloatString( "\n" );
  408. }
  409. f->WriteFloatString( "}\n" );
  410. return true;
  411. }
  412. /*
  413. ================
  414. idDeclAF::WriteUniversalJoint
  415. ================
  416. */
  417. bool idDeclAF::WriteUniversalJoint( idFile *f, const idDeclAF_Constraint &c ) const {
  418. f->WriteFloatString( "\nuniversalJoint \"%s\" {\n", c.name.c_str() );
  419. f->WriteFloatString( "\tbody1 \"%s\"\n", c.body1.c_str() );
  420. f->WriteFloatString( "\tbody2 \"%s\"\n", c.body2.c_str() );
  421. f->WriteFloatString( "\tanchor " );
  422. c.anchor.Write( f );
  423. f->WriteFloatString( "\n" );
  424. f->WriteFloatString( "\tshafts " );
  425. c.shaft[0].Write( f );
  426. f->WriteFloatString( ", " );
  427. c.shaft[1].Write( f );
  428. f->WriteFloatString( "\n" );
  429. f->WriteFloatString( "\tfriction %f\n", c.friction );
  430. if ( c.limit == idDeclAF_Constraint::LIMIT_CONE ) {
  431. f->WriteFloatString( "\tconeLimit " );
  432. c.limitAxis.Write( f );
  433. f->WriteFloatString( ", %f\n", c.limitAngles[0] );
  434. }
  435. else if ( c.limit == idDeclAF_Constraint::LIMIT_PYRAMID ) {
  436. f->WriteFloatString( "\tpyramidLimit " );
  437. c.limitAxis.Write( f );
  438. f->WriteFloatString( ", %f, %f, %f\n", c.limitAngles[0], c.limitAngles[1], c.limitAngles[2] );
  439. }
  440. f->WriteFloatString( "}\n" );
  441. return true;
  442. }
  443. /*
  444. ================
  445. idDeclAF::WriteHinge
  446. ================
  447. */
  448. bool idDeclAF::WriteHinge( idFile *f, const idDeclAF_Constraint &c ) const {
  449. f->WriteFloatString( "\nhinge \"%s\" {\n", c.name.c_str() );
  450. f->WriteFloatString( "\tbody1 \"%s\"\n", c.body1.c_str() );
  451. f->WriteFloatString( "\tbody2 \"%s\"\n", c.body2.c_str() );
  452. f->WriteFloatString( "\tanchor " );
  453. c.anchor.Write( f );
  454. f->WriteFloatString( "\n" );
  455. f->WriteFloatString( "\taxis " );
  456. c.axis.Write( f );
  457. f->WriteFloatString( "\n" );
  458. f->WriteFloatString( "\tfriction %f\n", c.friction );
  459. if ( c.limit == idDeclAF_Constraint::LIMIT_CONE ) {
  460. f->WriteFloatString( "\tlimit " );
  461. f->WriteFloatString( "%f, %f, %f", c.limitAngles[0], c.limitAngles[1], c.limitAngles[2] );
  462. f->WriteFloatString( "\n" );
  463. }
  464. f->WriteFloatString( "}\n" );
  465. return true;
  466. }
  467. /*
  468. ================
  469. idDeclAF::WriteSlider
  470. ================
  471. */
  472. bool idDeclAF::WriteSlider( idFile *f, const idDeclAF_Constraint &c ) const {
  473. f->WriteFloatString( "\nslider \"%s\" {\n", c.name.c_str() );
  474. f->WriteFloatString( "\tbody1 \"%s\"\n", c.body1.c_str() );
  475. f->WriteFloatString( "\tbody2 \"%s\"\n", c.body2.c_str() );
  476. f->WriteFloatString( "\taxis " );
  477. c.axis.Write( f );
  478. f->WriteFloatString( "\n" );
  479. f->WriteFloatString( "\tfriction %f\n", c.friction );
  480. f->WriteFloatString( "}\n" );
  481. return true;
  482. }
  483. /*
  484. ================
  485. idDeclAF::WriteSpring
  486. ================
  487. */
  488. bool idDeclAF::WriteSpring( idFile *f, const idDeclAF_Constraint &c ) const {
  489. f->WriteFloatString( "\nspring \"%s\" {\n", c.name.c_str() );
  490. f->WriteFloatString( "\tbody1 \"%s\"\n", c.body1.c_str() );
  491. f->WriteFloatString( "\tbody2 \"%s\"\n", c.body2.c_str() );
  492. f->WriteFloatString( "\tanchor1 " );
  493. c.anchor.Write( f );
  494. f->WriteFloatString( "\n" );
  495. f->WriteFloatString( "\tanchor2 " );
  496. c.anchor2.Write( f );
  497. f->WriteFloatString( "\n" );
  498. f->WriteFloatString( "\tfriction %f\n", c.friction );
  499. f->WriteFloatString( "\tstretch %f\n", c.stretch );
  500. f->WriteFloatString( "\tcompress %f\n", c.compress );
  501. f->WriteFloatString( "\tdamping %f\n", c.damping );
  502. f->WriteFloatString( "\trestLength %f\n", c.restLength );
  503. f->WriteFloatString( "\tminLength %f\n", c.minLength );
  504. f->WriteFloatString( "\tmaxLength %f\n", c.maxLength );
  505. f->WriteFloatString( "}\n" );
  506. return true;
  507. }
  508. /*
  509. ================
  510. idDeclAF::WriteConstraint
  511. ================
  512. */
  513. bool idDeclAF::WriteConstraint( idFile *f, const idDeclAF_Constraint &c ) const {
  514. switch( c.type ) {
  515. case DECLAF_CONSTRAINT_FIXED:
  516. return WriteFixed( f, c );
  517. case DECLAF_CONSTRAINT_BALLANDSOCKETJOINT:
  518. return WriteBallAndSocketJoint( f, c );
  519. case DECLAF_CONSTRAINT_UNIVERSALJOINT:
  520. return WriteUniversalJoint( f, c );
  521. case DECLAF_CONSTRAINT_HINGE:
  522. return WriteHinge( f, c );
  523. case DECLAF_CONSTRAINT_SLIDER:
  524. return WriteSlider( f, c );
  525. case DECLAF_CONSTRAINT_SPRING:
  526. return WriteSpring( f, c );
  527. default:
  528. break;
  529. }
  530. return false;
  531. }
  532. /*
  533. ================
  534. idDeclAF::WriteSettings
  535. ================
  536. */
  537. bool idDeclAF::WriteSettings( idFile *f ) const {
  538. idStr str;
  539. f->WriteFloatString( "\nsettings {\n" );
  540. f->WriteFloatString( "\tmodel \"%s\"\n", model.c_str() );
  541. f->WriteFloatString( "\tskin \"%s\"\n", skin.c_str() );
  542. f->WriteFloatString( "\tfriction %f, %f, %f, %f\n", defaultLinearFriction, defaultAngularFriction, defaultContactFriction, defaultConstraintFriction );
  543. f->WriteFloatString( "\tsuspendSpeed %f, %f, %f, %f\n", suspendVelocity[0], suspendVelocity[1], suspendAcceleration[0], suspendAcceleration[1] );
  544. f->WriteFloatString( "\tnoMoveTime %f\n", noMoveTime );
  545. f->WriteFloatString( "\tnoMoveTranslation %f\n", noMoveTranslation );
  546. f->WriteFloatString( "\tnoMoveRotation %f\n", noMoveRotation );
  547. f->WriteFloatString( "\tminMoveTime %f\n", minMoveTime );
  548. f->WriteFloatString( "\tmaxMoveTime %f\n", maxMoveTime );
  549. f->WriteFloatString( "\ttotalMass %f\n", totalMass );
  550. f->WriteFloatString( "\tcontents %s\n", ContentsToString( contents, str ) );
  551. f->WriteFloatString( "\tclipMask %s\n", ContentsToString( clipMask, str ) );
  552. f->WriteFloatString( "\tselfCollision %d\n", selfCollision );
  553. f->WriteFloatString( "}\n" );
  554. return true;
  555. }
  556. /*
  557. ================
  558. idDeclAF::RebuildTextSource
  559. ================
  560. */
  561. bool idDeclAF::RebuildTextSource() {
  562. int i;
  563. idFile_Memory f;
  564. f.WriteFloatString("\n\n/*\n"
  565. "\tGenerated by the Articulated Figure Editor.\n"
  566. "\tDo not edit directly but launch the game and type 'editAFs' on the console.\n"
  567. "*/\n" );
  568. f.WriteFloatString( "\narticulatedFigure %s {\n", GetName() );
  569. if ( !WriteSettings( &f ) ) {
  570. return false;
  571. }
  572. for ( i = 0; i < bodies.Num(); i++ ) {
  573. if ( !WriteBody( &f, *bodies[i] ) ) {
  574. return false;
  575. }
  576. }
  577. for ( i = 0; i < constraints.Num(); i++ ) {
  578. if ( !WriteConstraint( &f, *constraints[i] ) ) {
  579. return false;
  580. }
  581. }
  582. f.WriteFloatString( "\n}" );
  583. SetText( f.GetDataPtr() );
  584. return true;
  585. }
  586. /*
  587. ================
  588. idDeclAF::Save
  589. ================
  590. */
  591. bool idDeclAF::Save() {
  592. RebuildTextSource();
  593. ReplaceSourceFileText();
  594. modified = false;
  595. return true;
  596. }
  597. /*
  598. ================
  599. idDeclAF::ContentsFromString
  600. ================
  601. */
  602. int idDeclAF::ContentsFromString( const char *str ) {
  603. int c;
  604. idToken token;
  605. idLexer src( str, idStr::Length( str ), "idDeclAF::ContentsFromString" );
  606. c = 0;
  607. while( src.ReadToken( &token ) ) {
  608. if ( token.Icmp( "none" ) == 0 ) {
  609. c = 0;
  610. }
  611. else if ( token.Icmp( "solid" ) == 0 ) {
  612. c |= CONTENTS_SOLID;
  613. }
  614. else if ( token.Icmp( "body" ) == 0 ) {
  615. c |= CONTENTS_BODY;
  616. }
  617. else if ( token.Icmp( "corpse" ) == 0 ) {
  618. c |= CONTENTS_CORPSE;
  619. }
  620. else if ( token.Icmp( "playerclip" ) == 0 ) {
  621. c |= CONTENTS_PLAYERCLIP;
  622. }
  623. else if ( token.Icmp( "monsterclip" ) == 0 ) {
  624. c |= CONTENTS_MONSTERCLIP;
  625. }
  626. else if ( token == "," ) {
  627. continue;
  628. }
  629. else {
  630. return c;
  631. }
  632. }
  633. return c;
  634. }
  635. /*
  636. ================
  637. idDeclAF::ContentsToString
  638. ================
  639. */
  640. const char *idDeclAF::ContentsToString( const int contents, idStr &str ) {
  641. str = "";
  642. if ( contents & CONTENTS_SOLID ) {
  643. if ( str.Length() ) str += ", ";
  644. str += "solid";
  645. }
  646. if ( contents & CONTENTS_BODY ) {
  647. if ( str.Length() ) str += ", ";
  648. str += "body";
  649. }
  650. if ( contents & CONTENTS_CORPSE ) {
  651. if ( str.Length() ) str += ", ";
  652. str += "corpse";
  653. }
  654. if ( contents & CONTENTS_PLAYERCLIP ) {
  655. if ( str.Length() ) str += ", ";
  656. str += "playerclip";
  657. }
  658. if ( contents & CONTENTS_MONSTERCLIP ) {
  659. if ( str.Length() ) str += ", ";
  660. str += "monsterclip";
  661. }
  662. if ( str[0] == '\0' ) {
  663. str = "none";
  664. }
  665. return str.c_str();
  666. }
  667. /*
  668. ================
  669. idDeclAF::JointModFromString
  670. ================
  671. */
  672. declAFJointMod_t idDeclAF::JointModFromString( const char *str ) {
  673. if ( idStr::Icmp( str, "orientation" ) == 0 ) {
  674. return DECLAF_JOINTMOD_AXIS;
  675. }
  676. if ( idStr::Icmp( str, "position" ) == 0 ) {
  677. return DECLAF_JOINTMOD_ORIGIN;
  678. }
  679. if ( idStr::Icmp( str, "both" ) == 0 ) {
  680. return DECLAF_JOINTMOD_BOTH;
  681. }
  682. return DECLAF_JOINTMOD_AXIS;
  683. }
  684. /*
  685. ================
  686. idDeclAF::JointModToString
  687. ================
  688. */
  689. const char * idDeclAF::JointModToString( declAFJointMod_t jointMod ) {
  690. switch( jointMod ) {
  691. case DECLAF_JOINTMOD_AXIS: {
  692. return "orientation";
  693. }
  694. case DECLAF_JOINTMOD_ORIGIN: {
  695. return "position";
  696. }
  697. case DECLAF_JOINTMOD_BOTH: {
  698. return "both";
  699. }
  700. }
  701. return "orientation";
  702. }
  703. /*
  704. =================
  705. idDeclAF::Size
  706. =================
  707. */
  708. size_t idDeclAF::Size() const {
  709. return sizeof( idDeclAF );
  710. }
  711. /*
  712. ================
  713. idDeclAF::ParseContents
  714. ================
  715. */
  716. bool idDeclAF::ParseContents( idLexer &src, int &c ) const {
  717. idToken token;
  718. idStr str;
  719. while( src.ReadToken( &token ) ) {
  720. str += token;
  721. if ( !src.CheckTokenString( "," ) ) {
  722. break;
  723. }
  724. str += ",";
  725. }
  726. c = ContentsFromString( str );
  727. return true;
  728. }
  729. /*
  730. ================
  731. idDeclAF::ParseBody
  732. ================
  733. */
  734. bool idDeclAF::ParseBody( idLexer &src ) {
  735. bool hasJoint = false;
  736. idToken token;
  737. idAFVector angles;
  738. idDeclAF_Body *body = new (TAG_DECL) idDeclAF_Body;
  739. bodies.Alloc() = body;
  740. body->SetDefault( this );
  741. if ( !src.ExpectTokenType( TT_STRING, 0, &token ) ||
  742. !src.ExpectTokenString( "{" ) ) {
  743. return false;
  744. }
  745. body->name = token;
  746. if ( !body->name.Icmp( "origin" ) || !body->name.Icmp( "world" ) ) {
  747. src.Error( "a body may not be named \"origin\" or \"world\"" );
  748. return false;
  749. }
  750. while( src.ReadToken( &token ) ) {
  751. if ( !token.Icmp( "model" ) ) {
  752. if ( !src.ExpectTokenType( TT_NAME, 0, &token ) ) {
  753. return false;
  754. }
  755. if ( !token.Icmp( "box" ) ) {
  756. body->modelType = TRM_BOX;
  757. if ( !src.ExpectTokenString( "(" ) ||
  758. !body->v1.Parse( src ) ||
  759. !src.ExpectTokenString( "," ) ||
  760. !body->v2.Parse( src ) ||
  761. !src.ExpectTokenString( ")" ) ) {
  762. return false;
  763. }
  764. } else if ( !token.Icmp( "octahedron" ) ) {
  765. body->modelType = TRM_OCTAHEDRON;
  766. if ( !src.ExpectTokenString( "(" ) ||
  767. !body->v1.Parse( src ) ||
  768. !src.ExpectTokenString( "," ) ||
  769. !body->v2.Parse( src ) ||
  770. !src.ExpectTokenString( ")" ) ) {
  771. return false;
  772. }
  773. } else if ( !token.Icmp( "dodecahedron" ) ) {
  774. body->modelType = TRM_DODECAHEDRON;
  775. if ( !src.ExpectTokenString( "(" ) ||
  776. !body->v1.Parse( src ) ||
  777. !src.ExpectTokenString( "," ) ||
  778. !body->v2.Parse( src ) ||
  779. !src.ExpectTokenString( ")" ) ) {
  780. return false;
  781. }
  782. } else if ( !token.Icmp( "cylinder" ) ) {
  783. body->modelType = TRM_CYLINDER;
  784. if ( !src.ExpectTokenString( "(" ) ||
  785. !body->v1.Parse( src ) ||
  786. !src.ExpectTokenString( "," ) ||
  787. !body->v2.Parse( src ) ||
  788. !src.ExpectTokenString( "," ) ) {
  789. return false;
  790. }
  791. body->numSides = src.ParseInt();
  792. if ( !src.ExpectTokenString( ")" ) ) {
  793. return false;
  794. }
  795. } else if ( !token.Icmp( "cone" ) ) {
  796. body->modelType = TRM_CONE;
  797. if ( !src.ExpectTokenString( "(" ) ||
  798. !body->v1.Parse( src ) ||
  799. !src.ExpectTokenString( "," ) ||
  800. !body->v2.Parse( src ) ||
  801. !src.ExpectTokenString( "," ) ) {
  802. return false;
  803. }
  804. body->numSides = src.ParseInt();
  805. if ( !src.ExpectTokenString( ")" ) ) {
  806. return false;
  807. }
  808. } else if ( !token.Icmp( "bone" ) ) {
  809. body->modelType = TRM_BONE;
  810. if ( !src.ExpectTokenString( "(" ) ||
  811. !body->v1.Parse( src ) ||
  812. !src.ExpectTokenString( "," ) ||
  813. !body->v2.Parse( src ) ||
  814. !src.ExpectTokenString( "," ) ) {
  815. return false;
  816. }
  817. body->width = src.ParseFloat();
  818. if ( !src.ExpectTokenString( ")" ) ) {
  819. return false;
  820. }
  821. } else if ( !token.Icmp( "custom" ) ) {
  822. src.Error( "custom models not yet implemented" );
  823. return false;
  824. } else {
  825. src.Error( "unkown model type %s", token.c_str() );
  826. return false;
  827. }
  828. } else if ( !token.Icmp( "origin" ) ) {
  829. if ( !body->origin.Parse( src ) ) {
  830. return false;
  831. }
  832. } else if ( !token.Icmp( "angles" ) ) {
  833. if ( !angles.Parse( src ) ) {
  834. return false;
  835. }
  836. body->angles = idAngles( angles.ToVec3().x, angles.ToVec3().y, angles.ToVec3().z );
  837. } else if ( !token.Icmp( "joint" ) ) {
  838. if ( !src.ExpectTokenType( TT_STRING, 0, &token ) ) {
  839. return false;
  840. }
  841. body->jointName = token;
  842. hasJoint = true;
  843. } else if ( !token.Icmp( "mod" ) ) {
  844. if ( !src.ExpectAnyToken( &token ) ) {
  845. return false;
  846. }
  847. body->jointMod = JointModFromString( token.c_str() );
  848. } else if ( !token.Icmp( "density" ) ) {
  849. body->density = src.ParseFloat();
  850. } else if ( !token.Icmp( "inertiaScale" ) ) {
  851. src.Parse1DMatrix( 9, body->inertiaScale[0].ToFloatPtr() );
  852. } else if ( !token.Icmp( "friction" ) ) {
  853. body->linearFriction = src.ParseFloat();
  854. src.ExpectTokenString( "," );
  855. body->angularFriction = src.ParseFloat();
  856. src.ExpectTokenString( "," );
  857. body->contactFriction = src.ParseFloat();
  858. } else if ( !token.Icmp( "contents" ) ) {
  859. ParseContents( src, body->contents );
  860. } else if ( !token.Icmp( "clipMask" ) ) {
  861. ParseContents( src, body->clipMask );
  862. body->clipMask &= ~CONTENTS_CORPSE; // never allow collisions against corpses
  863. } else if ( !token.Icmp( "selfCollision" ) ) {
  864. body->selfCollision = src.ParseBool();
  865. } else if ( !token.Icmp( "containedjoints" ) ) {
  866. if ( !src.ExpectTokenType( TT_STRING, 0, &token ) ) {
  867. return false;
  868. }
  869. body->containedJoints = token;
  870. } else if ( !token.Icmp( "frictionDirection" ) ) {
  871. if ( !body->frictionDirection.Parse( src ) ) {
  872. return false;
  873. }
  874. } else if ( !token.Icmp( "contactMotorDirection" ) ) {
  875. if ( !body->contactMotorDirection.Parse( src ) ) {
  876. return false;
  877. }
  878. } else if ( token == "}" ) {
  879. break;
  880. } else {
  881. src.Error( "unknown token %s in body", token.c_str() );
  882. return false;
  883. }
  884. }
  885. if ( body->modelType == TRM_INVALID ) {
  886. src.Error( "no model set for body" );
  887. return false;
  888. }
  889. if ( !hasJoint ) {
  890. src.Error( "no joint set for body" );
  891. return false;
  892. }
  893. body->clipMask |= CONTENTS_MOVEABLECLIP;
  894. return true;
  895. }
  896. /*
  897. ================
  898. idDeclAF::ParseFixed
  899. ================
  900. */
  901. bool idDeclAF::ParseFixed( idLexer &src ) {
  902. idToken token;
  903. idDeclAF_Constraint *constraint = new (TAG_DECL) idDeclAF_Constraint;
  904. constraint->SetDefault( this );
  905. constraints.Alloc() = constraint;
  906. if ( !src.ExpectTokenType( TT_STRING, 0, &token ) ||
  907. !src.ExpectTokenString( "{" ) ) {
  908. return false;
  909. }
  910. constraint->type = DECLAF_CONSTRAINT_FIXED;
  911. constraint->name = token;
  912. while( src.ReadToken( &token ) ) {
  913. if ( !token.Icmp( "body1" ) ) {
  914. src.ExpectTokenType( TT_STRING, 0, &token );
  915. constraint->body1 = token;
  916. } else if ( !token.Icmp( "body2" ) ) {
  917. src.ExpectTokenType( TT_STRING, 0, &token );
  918. constraint->body2 = token;
  919. } else if ( token == "}" ) {
  920. break;
  921. } else {
  922. src.Error( "unknown token %s in ball and socket joint", token.c_str() );
  923. return false;
  924. }
  925. }
  926. return true;
  927. }
  928. /*
  929. ================
  930. idDeclAF::ParseBallAndSocketJoint
  931. ================
  932. */
  933. bool idDeclAF::ParseBallAndSocketJoint( idLexer &src ) {
  934. idToken token;
  935. idDeclAF_Constraint *constraint = new (TAG_DECL) idDeclAF_Constraint;
  936. constraint->SetDefault( this );
  937. constraints.Alloc() = constraint;
  938. if ( !src.ExpectTokenType( TT_STRING, 0, &token ) ||
  939. !src.ExpectTokenString( "{" ) ) {
  940. return false;
  941. }
  942. constraint->type = DECLAF_CONSTRAINT_BALLANDSOCKETJOINT;
  943. constraint->limit = idDeclAF_Constraint::LIMIT_NONE;
  944. constraint->name = token;
  945. constraint->friction = 0.5f;
  946. constraint->anchor.ToVec3().Zero();
  947. constraint->shaft[0].ToVec3().Zero();
  948. while( src.ReadToken( &token ) ) {
  949. if ( !token.Icmp( "body1" ) ) {
  950. src.ExpectTokenType( TT_STRING, 0, &token );
  951. constraint->body1 = token;
  952. } else if ( !token.Icmp( "body2" ) ) {
  953. src.ExpectTokenType( TT_STRING, 0, &token );
  954. constraint->body2 = token;
  955. } else if ( !token.Icmp( "anchor" ) ) {
  956. if ( !constraint->anchor.Parse( src ) ) {
  957. return false;
  958. }
  959. } else if ( !token.Icmp( "conelimit" ) ) {
  960. if ( !constraint->limitAxis.Parse( src ) ||
  961. !src.ExpectTokenString( "," ) ) {
  962. return false;
  963. }
  964. constraint->limitAngles[0] = src.ParseFloat();
  965. if ( !src.ExpectTokenString( "," ) ||
  966. !constraint->shaft[0].Parse( src ) ) {
  967. return false;
  968. }
  969. constraint->limit = idDeclAF_Constraint::LIMIT_CONE;
  970. } else if ( !token.Icmp( "pyramidlimit" ) ) {
  971. if ( !constraint->limitAxis.Parse( src ) ||
  972. !src.ExpectTokenString( "," ) ) {
  973. return false;
  974. }
  975. constraint->limitAngles[0] = src.ParseFloat();
  976. if ( !src.ExpectTokenString( "," ) ) {
  977. return false;
  978. }
  979. constraint->limitAngles[1] = src.ParseFloat();
  980. if ( !src.ExpectTokenString( "," ) ) {
  981. return false;
  982. }
  983. constraint->limitAngles[2] = src.ParseFloat();
  984. if ( !src.ExpectTokenString( "," ) ||
  985. !constraint->shaft[0].Parse( src ) ) {
  986. return false;
  987. }
  988. constraint->limit = idDeclAF_Constraint::LIMIT_PYRAMID;
  989. } else if ( !token.Icmp( "friction" ) ) {
  990. constraint->friction = src.ParseFloat();
  991. } else if ( token == "}" ) {
  992. break;
  993. } else {
  994. src.Error( "unknown token %s in ball and socket joint", token.c_str() );
  995. return false;
  996. }
  997. }
  998. return true;
  999. }
  1000. /*
  1001. ================
  1002. idDeclAF::ParseUniversalJoint
  1003. ================
  1004. */
  1005. bool idDeclAF::ParseUniversalJoint( idLexer &src ) {
  1006. idToken token;
  1007. idDeclAF_Constraint *constraint = new (TAG_DECL) idDeclAF_Constraint;
  1008. constraint->SetDefault( this );
  1009. constraints.Alloc() = constraint;
  1010. if ( !src.ExpectTokenType( TT_STRING, 0, &token ) ||
  1011. !src.ExpectTokenString( "{" ) ) {
  1012. return false;
  1013. }
  1014. constraint->type = DECLAF_CONSTRAINT_UNIVERSALJOINT;
  1015. constraint->limit = idDeclAF_Constraint::LIMIT_NONE;
  1016. constraint->name = token;
  1017. constraint->friction = 0.5f;
  1018. constraint->anchor.ToVec3().Zero();
  1019. constraint->shaft[0].ToVec3().Zero();
  1020. constraint->shaft[1].ToVec3().Zero();
  1021. while( src.ReadToken( &token ) ) {
  1022. if ( !token.Icmp( "body1" ) ) {
  1023. src.ExpectTokenType( TT_STRING, 0, &token );
  1024. constraint->body1 = token;
  1025. } else if ( !token.Icmp( "body2" ) ) {
  1026. src.ExpectTokenType( TT_STRING, 0, &token );
  1027. constraint->body2 = token;
  1028. } else if ( !token.Icmp( "anchor" ) ) {
  1029. if ( !constraint->anchor.Parse( src ) ) {
  1030. return false;
  1031. }
  1032. } else if ( !token.Icmp( "shafts" ) ) {
  1033. if ( !constraint->shaft[0].Parse( src ) ||
  1034. !src.ExpectTokenString( "," ) ||
  1035. !constraint->shaft[1].Parse( src ) ) {
  1036. return false;
  1037. }
  1038. } else if ( !token.Icmp( "conelimit" ) ) {
  1039. if ( !constraint->limitAxis.Parse( src ) ||
  1040. !src.ExpectTokenString( "," ) ) {
  1041. return false;
  1042. }
  1043. constraint->limitAngles[0] = src.ParseFloat();
  1044. constraint->limit = idDeclAF_Constraint::LIMIT_CONE;
  1045. } else if ( !token.Icmp( "pyramidlimit" ) ) {
  1046. if ( !constraint->limitAxis.Parse( src ) ||
  1047. !src.ExpectTokenString( "," ) ) {
  1048. return false;
  1049. }
  1050. constraint->limitAngles[0] = src.ParseFloat();
  1051. if ( !src.ExpectTokenString( "," ) ) {
  1052. return false;
  1053. }
  1054. constraint->limitAngles[1] = src.ParseFloat();
  1055. if ( !src.ExpectTokenString( "," ) ) {
  1056. return false;
  1057. }
  1058. constraint->limitAngles[2] = src.ParseFloat();
  1059. constraint->limit = idDeclAF_Constraint::LIMIT_PYRAMID;
  1060. } else if ( !token.Icmp( "friction" ) ) {
  1061. constraint->friction = src.ParseFloat();
  1062. } else if ( token == "}" ) {
  1063. break;
  1064. } else {
  1065. src.Error( "unknown token %s in universal joint", token.c_str() );
  1066. return false;
  1067. }
  1068. }
  1069. return true;
  1070. }
  1071. /*
  1072. ================
  1073. idDeclAF::ParseHinge
  1074. ================
  1075. */
  1076. bool idDeclAF::ParseHinge( idLexer &src ) {
  1077. idToken token;
  1078. idDeclAF_Constraint *constraint = new (TAG_DECL) idDeclAF_Constraint;
  1079. constraint->SetDefault( this );
  1080. constraints.Alloc() = constraint;
  1081. if ( !src.ExpectTokenType( TT_STRING, 0, &token ) ||
  1082. !src.ExpectTokenString( "{" ) ) {
  1083. return false;
  1084. }
  1085. constraint->type = DECLAF_CONSTRAINT_HINGE;
  1086. constraint->limit = idDeclAF_Constraint::LIMIT_NONE;
  1087. constraint->name = token;
  1088. constraint->friction = 0.5f;
  1089. constraint->anchor.ToVec3().Zero();
  1090. constraint->axis.ToVec3().Zero();
  1091. while( src.ReadToken( &token ) ) {
  1092. if ( !token.Icmp( "body1" ) ) {
  1093. src.ExpectTokenType( TT_STRING, 0, &token );
  1094. constraint->body1 = token;
  1095. } else if ( !token.Icmp( "body2" ) ) {
  1096. src.ExpectTokenType( TT_STRING, 0, &token );
  1097. constraint->body2 = token;
  1098. } else if ( !token.Icmp( "anchor" ) ) {
  1099. if ( !constraint->anchor.Parse( src ) ) {
  1100. return false;
  1101. }
  1102. } else if ( !token.Icmp( "axis" ) ) {
  1103. if ( !constraint->axis.Parse( src ) ) {
  1104. return false;
  1105. }
  1106. } else if ( !token.Icmp( "limit" ) ) {
  1107. constraint->limitAngles[0] = src.ParseFloat();
  1108. if ( !src.ExpectTokenString( "," ) ) {
  1109. return false;
  1110. }
  1111. constraint->limitAngles[1] = src.ParseFloat();
  1112. if ( !src.ExpectTokenString( "," ) ) {
  1113. return false;
  1114. }
  1115. constraint->limitAngles[2] = src.ParseFloat();
  1116. constraint->limit = idDeclAF_Constraint::LIMIT_CONE;
  1117. } else if ( !token.Icmp( "friction" ) ) {
  1118. constraint->friction = src.ParseFloat();
  1119. } else if ( token == "}" ) {
  1120. break;
  1121. } else {
  1122. src.Error( "unknown token %s in hinge", token.c_str() );
  1123. return false;
  1124. }
  1125. }
  1126. return true;
  1127. }
  1128. /*
  1129. ================
  1130. idDeclAF::ParseSlider
  1131. ================
  1132. */
  1133. bool idDeclAF::ParseSlider( idLexer &src ) {
  1134. idToken token;
  1135. idDeclAF_Constraint *constraint = new (TAG_DECL) idDeclAF_Constraint;
  1136. constraint->SetDefault( this );
  1137. constraints.Alloc() = constraint;
  1138. if ( !src.ExpectTokenType( TT_STRING, 0, &token ) ||
  1139. !src.ExpectTokenString( "{" ) ) {
  1140. return false;
  1141. }
  1142. constraint->type = DECLAF_CONSTRAINT_SLIDER;
  1143. constraint->limit = idDeclAF_Constraint::LIMIT_NONE;
  1144. constraint->name = token;
  1145. constraint->friction = 0.5f;
  1146. while( src.ReadToken( &token ) ) {
  1147. if ( !token.Icmp( "body1" ) ) {
  1148. src.ExpectTokenType( TT_STRING, 0, &token );
  1149. constraint->body1 = token;
  1150. } else if ( !token.Icmp( "body2" ) ) {
  1151. src.ExpectTokenType( TT_STRING, 0, &token );
  1152. constraint->body2 = token;
  1153. } else if ( !token.Icmp( "axis" ) ) {
  1154. if ( !constraint->axis.Parse( src ) ) {
  1155. return false;
  1156. }
  1157. } else if ( !token.Icmp( "friction" ) ) {
  1158. constraint->friction = src.ParseFloat();
  1159. } else if ( token == "}" ) {
  1160. break;
  1161. } else {
  1162. src.Error( "unknown token %s in slider", token.c_str() );
  1163. return false;
  1164. }
  1165. }
  1166. return true;
  1167. }
  1168. /*
  1169. ================
  1170. idDeclAF::ParseSpring
  1171. ================
  1172. */
  1173. bool idDeclAF::ParseSpring( idLexer &src ) {
  1174. idToken token;
  1175. idDeclAF_Constraint *constraint = new (TAG_DECL) idDeclAF_Constraint;
  1176. constraint->SetDefault( this );
  1177. constraints.Alloc() = constraint;
  1178. if ( !src.ExpectTokenType( TT_STRING, 0, &token ) ||
  1179. !src.ExpectTokenString( "{" ) ) {
  1180. return false;
  1181. }
  1182. constraint->type = DECLAF_CONSTRAINT_SPRING;
  1183. constraint->limit = idDeclAF_Constraint::LIMIT_NONE;
  1184. constraint->name = token;
  1185. constraint->friction = 0.5f;
  1186. while( src.ReadToken( &token ) ) {
  1187. if ( !token.Icmp( "body1" ) ) {
  1188. src.ExpectTokenType( TT_STRING, 0, &token );
  1189. constraint->body1 = token;
  1190. } else if ( !token.Icmp( "body2" ) ) {
  1191. src.ExpectTokenType( TT_STRING, 0, &token );
  1192. constraint->body2 = token;
  1193. } else if ( !token.Icmp( "anchor1" ) ) {
  1194. if ( !constraint->anchor.Parse( src ) ) {
  1195. return false;
  1196. }
  1197. } else if ( !token.Icmp( "anchor2" ) ) {
  1198. if ( !constraint->anchor2.Parse( src ) ) {
  1199. return false;
  1200. }
  1201. } else if ( !token.Icmp( "friction" ) ) {
  1202. constraint->friction = src.ParseFloat();
  1203. } else if ( !token.Icmp( "stretch" ) ) {
  1204. constraint->stretch = src.ParseFloat();
  1205. } else if ( !token.Icmp( "compress" ) ) {
  1206. constraint->compress = src.ParseFloat();
  1207. } else if ( !token.Icmp( "damping" ) ) {
  1208. constraint->damping = src.ParseFloat();
  1209. } else if ( !token.Icmp( "restLength" ) ) {
  1210. constraint->restLength = src.ParseFloat();
  1211. } else if ( !token.Icmp( "minLength" ) ) {
  1212. constraint->minLength = src.ParseFloat();
  1213. } else if ( !token.Icmp( "maxLength" ) ) {
  1214. constraint->maxLength = src.ParseFloat();
  1215. } else if ( token == "}" ) {
  1216. break;
  1217. } else {
  1218. src.Error( "unknown token %s in spring", token.c_str() );
  1219. return false;
  1220. }
  1221. }
  1222. return true;
  1223. }
  1224. /*
  1225. ================
  1226. idDeclAF::ParseSettings
  1227. ================
  1228. */
  1229. bool idDeclAF::ParseSettings( idLexer &src ) {
  1230. idToken token;
  1231. if ( !src.ExpectTokenString( "{" ) ) {
  1232. return false;
  1233. }
  1234. while( src.ReadToken( &token ) ) {
  1235. if ( !token.Icmp( "mesh" ) ) {
  1236. if ( !src.ExpectTokenType( TT_STRING, 0, &token ) ) {
  1237. return false;
  1238. }
  1239. } else if ( !token.Icmp( "anim" ) ) {
  1240. if ( !src.ExpectTokenType( TT_STRING, 0, &token ) ) {
  1241. return false;
  1242. }
  1243. } else if ( !token.Icmp( "model" ) ) {
  1244. if ( !src.ExpectTokenType( TT_STRING, 0, &token ) ) {
  1245. return false;
  1246. }
  1247. model = token;
  1248. } else if ( !token.Icmp( "skin" ) ) {
  1249. if ( !src.ExpectTokenType( TT_STRING, 0, &token ) ) {
  1250. return false;
  1251. }
  1252. skin = token;
  1253. } else if ( !token.Icmp( "friction" ) ) {
  1254. defaultLinearFriction = src.ParseFloat();
  1255. if ( !src.ExpectTokenString( "," ) ) {
  1256. return false;
  1257. }
  1258. defaultAngularFriction = src.ParseFloat();
  1259. if ( !src.ExpectTokenString( "," ) ) {
  1260. return false;
  1261. }
  1262. defaultContactFriction = src.ParseFloat();
  1263. if ( src.CheckTokenString( "," ) ) {
  1264. defaultConstraintFriction = src.ParseFloat();
  1265. }
  1266. } else if ( !token.Icmp( "totalMass" ) ) {
  1267. totalMass = src.ParseFloat();
  1268. } else if ( !token.Icmp( "suspendSpeed" ) ) {
  1269. suspendVelocity[0] = src.ParseFloat();
  1270. if ( !src.ExpectTokenString( "," ) ) {
  1271. return false;
  1272. }
  1273. suspendVelocity[1] = src.ParseFloat();
  1274. if ( !src.ExpectTokenString( "," ) ) {
  1275. return false;
  1276. }
  1277. suspendAcceleration[0] = src.ParseFloat();
  1278. if ( !src.ExpectTokenString( "," ) ) {
  1279. return false;
  1280. }
  1281. suspendAcceleration[1] = src.ParseFloat();
  1282. } else if ( !token.Icmp( "noMoveTime" ) ) {
  1283. noMoveTime = src.ParseFloat();
  1284. } else if ( !token.Icmp( "noMoveTranslation" ) ) {
  1285. noMoveTranslation = src.ParseFloat();
  1286. } else if ( !token.Icmp( "noMoveRotation" ) ) {
  1287. noMoveRotation = src.ParseFloat();
  1288. } else if ( !token.Icmp( "minMoveTime" ) ) {
  1289. minMoveTime = src.ParseFloat();
  1290. } else if ( !token.Icmp( "maxMoveTime" ) ) {
  1291. maxMoveTime = src.ParseFloat();
  1292. } else if ( !token.Icmp( "contents" ) ) {
  1293. ParseContents( src, contents );
  1294. } else if ( !token.Icmp( "clipMask" ) ) {
  1295. ParseContents( src, clipMask );
  1296. clipMask &= ~CONTENTS_CORPSE; // never allow collisions against corpses
  1297. } else if ( !token.Icmp( "selfCollision" ) ) {
  1298. selfCollision = src.ParseBool();
  1299. } else if ( token == "}" ) {
  1300. break;
  1301. } else {
  1302. src.Error( "unknown token %s in settings", token.c_str() );
  1303. return false;
  1304. }
  1305. }
  1306. return true;
  1307. }
  1308. /*
  1309. ================
  1310. idDeclAF::Parse
  1311. ================
  1312. */
  1313. bool idDeclAF::Parse( const char *text, const int textLength, bool allowBinaryVersion ) {
  1314. int i, j;
  1315. idLexer src;
  1316. idToken token;
  1317. src.LoadMemory( text, textLength, GetFileName(), GetLineNum() );
  1318. src.SetFlags( DECL_LEXER_FLAGS );
  1319. src.SkipUntilString( "{" );
  1320. while( src.ReadToken( &token ) ) {
  1321. if ( !token.Icmp( "settings" ) ) {
  1322. if ( !ParseSettings( src ) ) {
  1323. return false;
  1324. }
  1325. } else if ( !token.Icmp( "body" ) ) {
  1326. if ( !ParseBody( src ) ) {
  1327. return false;
  1328. }
  1329. } else if ( !token.Icmp( "fixed" ) ) {
  1330. if ( !ParseFixed( src ) ) {
  1331. return false;
  1332. }
  1333. } else if ( !token.Icmp( "ballAndSocketJoint" ) ) {
  1334. if ( !ParseBallAndSocketJoint( src ) ) {
  1335. return false;
  1336. }
  1337. } else if ( !token.Icmp( "universalJoint" ) ) {
  1338. if ( !ParseUniversalJoint( src ) ) {
  1339. return false;
  1340. }
  1341. } else if ( !token.Icmp( "hinge" ) ) {
  1342. if ( !ParseHinge( src ) ) {
  1343. return false;
  1344. }
  1345. } else if ( !token.Icmp( "slider" ) ) {
  1346. if ( !ParseSlider( src ) ) {
  1347. return false;
  1348. }
  1349. } else if ( !token.Icmp( "spring" ) ) {
  1350. if ( !ParseSpring( src ) ) {
  1351. return false;
  1352. }
  1353. } else if ( token == "}" ) {
  1354. break;
  1355. } else {
  1356. src.Error( "unknown keyword %s", token.c_str() );
  1357. return false;
  1358. }
  1359. }
  1360. for ( i = 0; i < bodies.Num(); i++ ) {
  1361. // check for multiple bodies with the same name
  1362. for ( j = i+1; j < bodies.Num(); j++ ) {
  1363. if ( bodies[i]->name == bodies[j]->name ) {
  1364. src.Error( "two bodies with the same name \"%s\"", bodies[i]->name.c_str() );
  1365. }
  1366. }
  1367. }
  1368. for ( i = 0; i < constraints.Num(); i++ ) {
  1369. // check for multiple constraints with the same name
  1370. for ( j = i+1; j < constraints.Num(); j++ ) {
  1371. if ( constraints[i]->name == constraints[j]->name ) {
  1372. src.Error( "two constraints with the same name \"%s\"", constraints[i]->name.c_str() );
  1373. }
  1374. }
  1375. // check if there are two valid bodies set
  1376. if ( constraints[i]->body1 == "" ) {
  1377. src.Error( "no valid body1 specified for constraint '%s'", constraints[i]->name.c_str() );
  1378. }
  1379. if ( constraints[i]->body2 == "" ) {
  1380. src.Error( "no valid body2 specified for constraint '%s'", constraints[i]->name.c_str() );
  1381. }
  1382. }
  1383. // make sure the body which modifies the origin comes first
  1384. for ( i = 0; i < bodies.Num(); i++ ) {
  1385. if ( bodies[i]->jointName == "origin" ) {
  1386. if ( i != 0 ) {
  1387. idDeclAF_Body *b = bodies[0];
  1388. bodies[0] = bodies[i];
  1389. bodies[i] = b;
  1390. }
  1391. break;
  1392. }
  1393. }
  1394. return true;
  1395. }
  1396. /*
  1397. ================
  1398. idDeclAF::DefaultDefinition
  1399. ================
  1400. */
  1401. const char *idDeclAF::DefaultDefinition() const {
  1402. return
  1403. "{\n"
  1404. "\t" "settings {\n"
  1405. "\t\t" "model \"\"\n"
  1406. "\t\t" "skin \"\"\n"
  1407. "\t\t" "friction 0.01, 0.01, 0.8, 0.5\n"
  1408. "\t\t" "suspendSpeed 20, 30, 40, 60\n"
  1409. "\t\t" "noMoveTime 1\n"
  1410. "\t\t" "noMoveTranslation 10\n"
  1411. "\t\t" "noMoveRotation 10\n"
  1412. "\t\t" "minMoveTime -1\n"
  1413. "\t\t" "maxMoveTime -1\n"
  1414. "\t\t" "totalMass -1\n"
  1415. "\t\t" "contents corpse\n"
  1416. "\t\t" "clipMask solid, corpse\n"
  1417. "\t\t" "selfCollision 1\n"
  1418. "\t" "}\n"
  1419. "\t" "body \"body\" {\n"
  1420. "\t\t" "joint \"origin\"\n"
  1421. "\t\t" "mod orientation\n"
  1422. "\t\t" "model box( ( -10, -10, -10 ), ( 10, 10, 10 ) )\n"
  1423. "\t\t" "origin ( 0, 0, 0 )\n"
  1424. "\t\t" "density 0.2\n"
  1425. "\t\t" "friction 0.01, 0.01, 0.8\n"
  1426. "\t\t" "contents corpse\n"
  1427. "\t\t" "clipMask solid, corpse\n"
  1428. "\t\t" "selfCollision 1\n"
  1429. "\t\t" "containedJoints \"*origin\"\n"
  1430. "\t" "}\n"
  1431. "}\n";
  1432. }
  1433. /*
  1434. ================
  1435. idDeclAF::FreeData
  1436. ================
  1437. */
  1438. void idDeclAF::FreeData() {
  1439. modified = false;
  1440. defaultLinearFriction = 0.01f;
  1441. defaultAngularFriction = 0.01f;
  1442. defaultContactFriction = 0.8f;
  1443. defaultConstraintFriction = 0.5f;
  1444. totalMass = -1;
  1445. suspendVelocity.Set( 20.0f, 30.0f );
  1446. suspendAcceleration.Set( 40.0f, 60.0f );
  1447. noMoveTime = 1.0f;
  1448. noMoveTranslation = 10.0f;
  1449. noMoveRotation = 10.0f;
  1450. minMoveTime = -1.0f;
  1451. maxMoveTime = -1.0f;
  1452. selfCollision = true;
  1453. contents = CONTENTS_CORPSE;
  1454. clipMask = CONTENTS_SOLID;
  1455. bodies.DeleteContents( true );
  1456. constraints.DeleteContents( true );
  1457. }
  1458. /*
  1459. ================
  1460. idDeclAF::Finish
  1461. ================
  1462. */
  1463. void idDeclAF::Finish( const getJointTransform_t GetJointTransform, const idJointMat *frame, void *model ) const {
  1464. int i;
  1465. const char *name = GetName();
  1466. for ( i = 0; i < bodies.Num(); i++ ) {
  1467. idDeclAF_Body *body = bodies[i];
  1468. body->v1.Finish( name, GetJointTransform, frame, model );
  1469. body->v2.Finish( name, GetJointTransform, frame, model );
  1470. body->origin.Finish( name, GetJointTransform, frame, model );
  1471. body->frictionDirection.Finish( name, GetJointTransform, frame, model );
  1472. body->contactMotorDirection.Finish( name, GetJointTransform, frame, model );
  1473. }
  1474. for ( i = 0; i < constraints.Num(); i++ ) {
  1475. idDeclAF_Constraint *constraint = constraints[i];
  1476. constraint->anchor.Finish( name, GetJointTransform, frame, model );
  1477. constraint->anchor2.Finish( name, GetJointTransform, frame, model );
  1478. constraint->shaft[0].Finish( name, GetJointTransform, frame, model );
  1479. constraint->shaft[1].Finish( name, GetJointTransform, frame, model );
  1480. constraint->axis.Finish( name, GetJointTransform, frame, model );
  1481. constraint->limitAxis.Finish( name, GetJointTransform, frame, model );
  1482. }
  1483. }
  1484. /*
  1485. ================
  1486. idDeclAF::NewBody
  1487. ================
  1488. */
  1489. void idDeclAF::NewBody( const char *name ) {
  1490. idDeclAF_Body *body;
  1491. body = new (TAG_DECL) idDeclAF_Body();
  1492. body->SetDefault( this );
  1493. body->name = name;
  1494. bodies.Append( body );
  1495. }
  1496. /*
  1497. ================
  1498. idDeclAF::RenameBody
  1499. rename the body with the given name and rename
  1500. all constraint body references
  1501. ================
  1502. */
  1503. void idDeclAF::RenameBody( const char *oldName, const char *newName ) {
  1504. int i;
  1505. for ( i = 0; i < bodies.Num(); i++ ) {
  1506. if ( bodies[i]->name.Icmp( oldName ) == 0 ) {
  1507. bodies[i]->name = newName;
  1508. break;
  1509. }
  1510. }
  1511. for ( i = 0; i < constraints.Num(); i++ ) {
  1512. if ( constraints[i]->body1.Icmp( oldName ) == 0 ) {
  1513. constraints[i]->body1 = newName;
  1514. } else if ( constraints[i]->body2.Icmp( oldName ) == 0 ) {
  1515. constraints[i]->body2 = newName;
  1516. }
  1517. }
  1518. }
  1519. /*
  1520. ================
  1521. idDeclAF::DeleteBody
  1522. delete the body with the given name and delete
  1523. all constraints that reference the body
  1524. ================
  1525. */
  1526. void idDeclAF::DeleteBody( const char *name ) {
  1527. int i;
  1528. for ( i = 0; i < bodies.Num(); i++ ) {
  1529. if ( bodies[i]->name.Icmp( name ) == 0 ) {
  1530. delete bodies[i];
  1531. bodies.RemoveIndex( i );
  1532. break;
  1533. }
  1534. }
  1535. for ( i = 0; i < constraints.Num(); i++ ) {
  1536. if ( constraints[i]->body1.Icmp( name ) == 0 ||
  1537. constraints[i]->body2.Icmp( name ) == 0 ) {
  1538. delete constraints[i];
  1539. constraints.RemoveIndex( i );
  1540. i--;
  1541. }
  1542. }
  1543. }
  1544. /*
  1545. ================
  1546. idDeclAF::NewConstraint
  1547. ================
  1548. */
  1549. void idDeclAF::NewConstraint( const char *name ) {
  1550. idDeclAF_Constraint *constraint;
  1551. constraint = new (TAG_DECL) idDeclAF_Constraint;
  1552. constraint->SetDefault( this );
  1553. constraint->name = name;
  1554. constraints.Append( constraint );
  1555. }
  1556. /*
  1557. ================
  1558. idDeclAF::RenameConstraint
  1559. ================
  1560. */
  1561. void idDeclAF::RenameConstraint( const char *oldName, const char *newName ) {
  1562. int i;
  1563. for ( i = 0; i < constraints.Num(); i++ ) {
  1564. if ( constraints[i]->name.Icmp( oldName ) == 0 ) {
  1565. constraints[i]->name = newName;
  1566. return;
  1567. }
  1568. }
  1569. }
  1570. /*
  1571. ================
  1572. idDeclAF::DeleteConstraint
  1573. ================
  1574. */
  1575. void idDeclAF::DeleteConstraint( const char *name ) {
  1576. int i;
  1577. for ( i = 0; i < constraints.Num(); i++ ) {
  1578. if ( constraints[i]->name.Icmp( name ) == 0 ) {
  1579. delete constraints[i];
  1580. constraints.RemoveIndex( i );
  1581. return;
  1582. }
  1583. }
  1584. }
  1585. /*
  1586. ================
  1587. idDeclAF::idDeclAF
  1588. ================
  1589. */
  1590. idDeclAF::idDeclAF() {
  1591. FreeData();
  1592. }
  1593. /*
  1594. ================
  1595. idDeclAF::~idDeclAF
  1596. ================
  1597. */
  1598. idDeclAF::~idDeclAF() {
  1599. bodies.DeleteContents( true );
  1600. constraints.DeleteContents( true );
  1601. }