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