/* ================ idAFVector::Parse ================ */ bool idAFVector::Parse( idLexer &src ) { idToken token; if ( !src.ReadToken( &token ) ) { return false; } if ( token == "-" ) { negate = true; if ( !src.ReadToken( &token ) ) { return false; } } else { negate = false; } if ( token == "(" ) { type = idAFVector::VEC_COORDS; vec.x = src.ParseFloat(); src.ExpectTokenString( "," ); vec.y = src.ParseFloat(); src.ExpectTokenString( "," ); vec.z = src.ParseFloat(); src.ExpectTokenString( ")" ); } else if ( token == "joint" ) { type = idAFVector::VEC_JOINT; src.ExpectTokenString( "(" ); src.ReadToken( &token ); joint1 = token; src.ExpectTokenString( ")" ); } else if ( token == "bonecenter" ) { type = idAFVector::VEC_BONECENTER; src.ExpectTokenString( "(" ); src.ReadToken( &token ); joint1 = token; src.ExpectTokenString( "," ); src.ReadToken( &token ); joint2 = token; src.ExpectTokenString( ")" ); } else if ( token == "bonedir" ) { type = idAFVector::VEC_BONEDIR; src.ExpectTokenString( "(" ); src.ReadToken( &token ); joint1 = token; src.ExpectTokenString( "," ); src.ReadToken( &token ); joint2 = token; src.ExpectTokenString( ")" ); } else { src.Error( "unknown token %s in vector", token.c_str() ); return false; } return true; }
/* ================ idDeclAF::ParseHinge ================ */ bool idDeclAF::ParseHinge( idLexer &src ) { idToken token; idDeclAF_Constraint *constraint = new idDeclAF_Constraint; constraint->SetDefault( this ); constraints.Alloc() = constraint; if ( !src.ExpectTokenType( TT_STRING, 0, &token ) || !src.ExpectTokenString( "{" ) ) { return false; } constraint->type = DECLAF_CONSTRAINT_HINGE; constraint->limit = idDeclAF_Constraint::LIMIT_NONE; constraint->name = token; constraint->friction = 0.5f; constraint->anchor.ToVec3().Zero(); constraint->axis.ToVec3().Zero(); while( src.ReadToken( &token ) ) { if ( !token.Icmp( "body1" ) ) { src.ExpectTokenType( TT_STRING, 0, &token ); constraint->body1 = token; } else if ( !token.Icmp( "body2" ) ) { src.ExpectTokenType( TT_STRING, 0, &token ); constraint->body2 = token; } else if ( !token.Icmp( "anchor" ) ) { if ( !constraint->anchor.Parse( src ) ) { return false; } } else if ( !token.Icmp( "axis" ) ) { if ( !constraint->axis.Parse( src ) ) { return false; } } else if ( !token.Icmp( "limit" ) ) { constraint->limitAngles[0] = src.ParseFloat(); if ( !src.ExpectTokenString( "," ) ) { return false; } constraint->limitAngles[1] = src.ParseFloat(); if ( !src.ExpectTokenString( "," ) ) { return false; } constraint->limitAngles[2] = src.ParseFloat(); constraint->limit = idDeclAF_Constraint::LIMIT_CONE; } else if ( !token.Icmp( "friction" ) ) { constraint->friction = src.ParseFloat(); } else if ( token == "}" ) { break; } else { src.Error( "unknown token %s in hinge", token.c_str() ); return false; } } return true; }
/* ============ idAASSettings::ParseFloat ============ */ bool idAASSettings::ParseFloat( idLexer &src, float &f ) { if ( !src.ExpectTokenString( "=" ) ) { return false; } f = src.ParseFloat(); return true; }
/* ================ idDeclAF::ParseSlider ================ */ bool idDeclAF::ParseSlider( idLexer& src ) { idToken token; idDeclAF_Constraint* constraint = new( TAG_DECL ) idDeclAF_Constraint; constraint->SetDefault( this ); constraints.Alloc() = constraint; if( !src.ExpectTokenType( TT_STRING, 0, &token ) || !src.ExpectTokenString( "{" ) ) { return false; } constraint->type = DECLAF_CONSTRAINT_SLIDER; constraint->limit = idDeclAF_Constraint::LIMIT_NONE; constraint->name = token; constraint->friction = 0.5f; while( src.ReadToken( &token ) ) { if( !token.Icmp( "body1" ) ) { src.ExpectTokenType( TT_STRING, 0, &token ); constraint->body1 = token; } else if( !token.Icmp( "body2" ) ) { src.ExpectTokenType( TT_STRING, 0, &token ); constraint->body2 = token; } else if( !token.Icmp( "axis" ) ) { if( !constraint->axis.Parse( src ) ) { return false; } } else if( !token.Icmp( "friction" ) ) { constraint->friction = src.ParseFloat(); } else if( token == "}" ) { break; } else { src.Error( "unknown token %s in slider", token.c_str() ); return false; } } return true; }
/* ================ idDeclAF::ParseSpring ================ */ bool idDeclAF::ParseSpring( idLexer &src ) { idToken token; idDeclAF_Constraint *constraint = new idDeclAF_Constraint; constraint->SetDefault( this ); constraints.Alloc() = constraint; if ( !src.ExpectTokenType( TT_STRING, 0, &token ) || !src.ExpectTokenString( "{" ) ) { return false; } constraint->type = DECLAF_CONSTRAINT_SPRING; constraint->limit = idDeclAF_Constraint::LIMIT_NONE; constraint->name = token; constraint->friction = 0.5f; while( src.ReadToken( &token ) ) { if ( !token.Icmp( "body1" ) ) { src.ExpectTokenType( TT_STRING, 0, &token ); constraint->body1 = token; } else if ( !token.Icmp( "body2" ) ) { src.ExpectTokenType( TT_STRING, 0, &token ); constraint->body2 = token; } else if ( !token.Icmp( "anchor1" ) ) { if ( !constraint->anchor.Parse( src ) ) { return false; } } else if ( !token.Icmp( "anchor2" ) ) { if ( !constraint->anchor2.Parse( src ) ) { return false; } } else if ( !token.Icmp( "friction" ) ) { constraint->friction = src.ParseFloat(); } else if ( !token.Icmp( "stretch" ) ) { constraint->stretch = src.ParseFloat(); } else if ( !token.Icmp( "compress" ) ) { constraint->compress = src.ParseFloat(); } else if ( !token.Icmp( "damping" ) ) { constraint->damping = src.ParseFloat(); } else if ( !token.Icmp( "restLength" ) ) { constraint->restLength = src.ParseFloat(); } else if ( !token.Icmp( "minLength" ) ) { constraint->minLength = src.ParseFloat(); } else if ( !token.Icmp( "maxLength" ) ) { constraint->maxLength = src.ParseFloat(); } else if ( token == "}" ) { break; } else { src.Error( "unknown token %s in spring", token.c_str() ); return false; } } return true; }
/* =============== idSoundShader::ParseShader =============== */ bool idSoundShader::ParseShader( idLexer &src ) { int i; idToken token; parms.minDistance = 1; parms.maxDistance = 10; parms.volume = 1; parms.shakes = 0; parms.soundShaderFlags = 0; parms.soundClass = 0; speakerMask = 0; altSound = NULL; for( i = 0; i < SOUND_MAX_LIST_WAVS; i++ ) { leadins[i] = NULL; entries[i] = NULL; } numEntries = 0; numLeadins = 0; int maxSamples = idSoundSystemLocal::s_maxSoundsPerShader.GetInteger(); if ( com_makingBuild.GetBool() || maxSamples <= 0 || maxSamples > SOUND_MAX_LIST_WAVS ) { maxSamples = SOUND_MAX_LIST_WAVS; } while ( 1 ) { if ( !src.ExpectAnyToken( &token ) ) { return false; } // end of definition else if ( token == "}" ) { break; } // minimum number of sounds else if ( !token.Icmp( "minSamples" ) ) { maxSamples = idMath::ClampInt( src.ParseInt(), SOUND_MAX_LIST_WAVS, maxSamples ); } // description else if ( !token.Icmp( "description" ) ) { src.ReadTokenOnLine( &token ); desc = token.c_str(); } // mindistance else if ( !token.Icmp( "mindistance" ) ) { parms.minDistance = src.ParseFloat(); } // maxdistance else if ( !token.Icmp( "maxdistance" ) ) { parms.maxDistance = src.ParseFloat(); } // shakes screen else if ( !token.Icmp( "shakes" ) ) { src.ExpectAnyToken( &token ); if ( token.type == TT_NUMBER ) { parms.shakes = token.GetFloatValue(); } else { src.UnreadToken( &token ); parms.shakes = 1.0f; } } // reverb else if ( !token.Icmp( "reverb" ) ) { int reg0 = src.ParseFloat(); if ( !src.ExpectTokenString( "," ) ) { src.FreeSource(); return false; } int reg1 = src.ParseFloat(); // no longer supported } // volume else if ( !token.Icmp( "volume" ) ) { parms.volume = src.ParseFloat(); } // leadinVolume is used to allow light breaking leadin sounds to be much louder than the broken loop else if ( !token.Icmp( "leadinVolume" ) ) { leadinVolume = src.ParseFloat(); } // speaker mask else if ( !token.Icmp( "mask_center" ) ) { speakerMask |= 1<<SPEAKER_CENTER; } // speaker mask else if ( !token.Icmp( "mask_left" ) ) { speakerMask |= 1<<SPEAKER_LEFT; } // speaker mask else if ( !token.Icmp( "mask_right" ) ) { speakerMask |= 1<<SPEAKER_RIGHT; } // speaker mask else if ( !token.Icmp( "mask_backright" ) ) { speakerMask |= 1<<SPEAKER_BACKRIGHT; } // speaker mask else if ( !token.Icmp( "mask_backleft" ) ) { speakerMask |= 1<<SPEAKER_BACKLEFT; } // speaker mask else if ( !token.Icmp( "mask_lfe" ) ) { speakerMask |= 1<<SPEAKER_LFE; } // soundClass else if ( !token.Icmp( "soundClass" ) ) { parms.soundClass = src.ParseInt(); if ( parms.soundClass < 0 || parms.soundClass >= SOUND_MAX_CLASSES ) { src.Warning( "SoundClass out of range" ); return false; } } // altSound else if ( !token.Icmp( "altSound" ) ) { if ( !src.ExpectAnyToken( &token ) ) { return false; } altSound = declManager->FindSound( token.c_str() ); } // ordered else if ( !token.Icmp( "ordered" ) ) { // no longer supported } // no_dups else if ( !token.Icmp( "no_dups" ) ) { parms.soundShaderFlags |= SSF_NO_DUPS; } // no_flicker else if ( !token.Icmp( "no_flicker" ) ) { parms.soundShaderFlags |= SSF_NO_FLICKER; } // plain else if ( !token.Icmp( "plain" ) ) { // no longer supported } // looping else if ( !token.Icmp( "looping" ) ) { parms.soundShaderFlags |= SSF_LOOPING; } // no occlusion else if ( !token.Icmp( "no_occlusion" ) ) { parms.soundShaderFlags |= SSF_NO_OCCLUSION; } // private else if ( !token.Icmp( "private" ) ) { parms.soundShaderFlags |= SSF_PRIVATE_SOUND; } // antiPrivate else if ( !token.Icmp( "antiPrivate" ) ) { parms.soundShaderFlags |= SSF_ANTI_PRIVATE_SOUND; } // once else if ( !token.Icmp( "playonce" ) ) { parms.soundShaderFlags |= SSF_PLAY_ONCE; } // global else if ( !token.Icmp( "global" ) ) { parms.soundShaderFlags |= SSF_GLOBAL; } // unclamped else if ( !token.Icmp( "unclamped" ) ) { parms.soundShaderFlags |= SSF_UNCLAMPED; } // omnidirectional else if ( !token.Icmp( "omnidirectional" ) ) { parms.soundShaderFlags |= SSF_OMNIDIRECTIONAL; } // onDemand can't be a parms, because we must track all references and overrides would confuse it else if ( !token.Icmp( "onDemand" ) ) { // no longer loading sounds on demand //onDemand = true; } // the wave files else if ( !token.Icmp( "leadin" ) ) { // add to the leadin list if ( !src.ReadToken( &token ) ) { src.Warning( "Expected sound after leadin" ); return false; } if ( soundSystemLocal.soundCache && numLeadins < maxSamples ) { leadins[ numLeadins ] = soundSystemLocal.soundCache->FindSound( token.c_str(), onDemand ); numLeadins++; } } else if ( token.Find( ".wav", false ) != -1 || token.Find( ".ogg", false ) != -1 ) { // add to the wav list if ( soundSystemLocal.soundCache && numEntries < maxSamples ) { token.BackSlashesToSlashes(); idStr lang = cvarSystem->GetCVarString( "sys_lang" ); if ( lang.Icmp( "english" ) != 0 && token.Find( "sound/vo/", false ) >= 0 ) { idStr work = token; work.ToLower(); work.StripLeading( "sound/vo/" ); work = va( "sound/vo/%s/%s", lang.c_str(), work.c_str() ); if ( fileSystem->ReadFile( work, NULL, NULL ) > 0 ) { token = work; } else { // also try to find it with the .ogg extension work.SetFileExtension( ".ogg" ); if ( fileSystem->ReadFile( work, NULL, NULL ) > 0 ) { token = work; } } } entries[ numEntries ] = soundSystemLocal.soundCache->FindSound( token.c_str(), onDemand ); numEntries++; } } else { src.Warning( "unknown token '%s'", token.c_str() ); return false; } } if ( parms.shakes > 0.0f ) { CheckShakesAndOgg(); } return true; }
bool idEFXFile::ReadEffect( idLexer &src, idSoundEffect *effect ) { idToken name, token; if ( !src.ReadToken( &token ) ) return false; // reverb effect if ( token != "reverb" ) { // other effect (not supported at the moment) src.Error( "idEFXFile::ReadEffect: Unknown effect definition" ); return false; } src.ReadTokenOnLine( &token ); name = token; if ( !src.ReadToken( &token ) ) return false; if ( token != "{" ) { src.Error( "idEFXFile::ReadEffect: { not found, found %s", token.c_str() ); return false; } ALenum err; alGetError(); EFXprintf("Loading EFX effect '%s' (#%u)\n", name.c_str(), effect->effect); do { if ( !src.ReadToken( &token ) ) { src.Error( "idEFXFile::ReadEffect: EOF without closing brace" ); return false; } if ( token == "}" ) { effect->name = name; break; } if ( token == "environment" ) { // <+KittyCat> the "environment" token should be ignored (efx has nothing equatable to it) src.ParseInt(); } else if ( token == "environment size" ) { float size = src.ParseFloat(); efxf(AL_EAXREVERB_DENSITY, (size < 2.0f) ? (size - 1.0f) : 1.0f); } else if ( token == "environment diffusion" ) { efxf(AL_EAXREVERB_DIFFUSION, src.ParseFloat()); } else if ( token == "room" ) { efxf(AL_EAXREVERB_GAIN, mB_to_gain(src.ParseInt(), GAIN)); } else if ( token == "room hf" ) { efxf(AL_EAXREVERB_GAINHF, mB_to_gain(src.ParseInt(), GAINHF)); } else if ( token == "room lf" ) { efxf(AL_EAXREVERB_GAINLF, mB_to_gain(src.ParseInt(), GAINLF)); } else if ( token == "decay time" ) { efxf(AL_EAXREVERB_DECAY_TIME, src.ParseFloat()); } else if ( token == "decay hf ratio" ) { efxf(AL_EAXREVERB_DECAY_HFRATIO, src.ParseFloat()); } else if ( token == "decay lf ratio" ) { efxf(AL_EAXREVERB_DECAY_LFRATIO, src.ParseFloat()); } else if ( token == "reflections" ) { efxf(AL_EAXREVERB_REFLECTIONS_GAIN, mB_to_gain(src.ParseInt(), REFLECTIONS_GAIN)); } else if ( token == "reflections delay" ) { efxf(AL_EAXREVERB_REFLECTIONS_DELAY, src.ParseFloat()); } else if ( token == "reflections pan" ) { efxfv(AL_EAXREVERB_REFLECTIONS_PAN, src.ParseFloat(), src.ParseFloat(), src.ParseFloat()); } else if ( token == "reverb" ) { efxf(AL_EAXREVERB_LATE_REVERB_GAIN, mB_to_gain(src.ParseInt(), LATE_REVERB_GAIN)); } else if ( token == "reverb delay" ) { efxf(AL_EAXREVERB_LATE_REVERB_DELAY, src.ParseFloat()); } else if ( token == "reverb pan" ) { efxfv(AL_EAXREVERB_LATE_REVERB_PAN, src.ParseFloat(), src.ParseFloat(), src.ParseFloat()); } else if ( token == "echo time" ) { efxf(AL_EAXREVERB_ECHO_TIME, src.ParseFloat()); } else if ( token == "echo depth" ) { efxf(AL_EAXREVERB_ECHO_DEPTH, src.ParseFloat()); } else if ( token == "modulation time" ) { efxf(AL_EAXREVERB_MODULATION_TIME, src.ParseFloat()); } else if ( token == "modulation depth" ) { efxf(AL_EAXREVERB_MODULATION_DEPTH, src.ParseFloat()); } else if ( token == "air absorption hf" ) { efxf(AL_EAXREVERB_AIR_ABSORPTION_GAINHF, mB_to_gain(src.ParseFloat(), AIR_ABSORPTION_GAINHF)); } else if ( token == "hf reference" ) { efxf(AL_EAXREVERB_HFREFERENCE, src.ParseFloat()); } else if ( token == "lf reference" ) { efxf(AL_EAXREVERB_LFREFERENCE, src.ParseFloat()); } else if ( token == "room rolloff factor" ) { efxf(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR, src.ParseFloat()); } else if ( token == "flags" ) { src.ReadTokenOnLine( &token ); unsigned int flags = token.GetUnsignedLongValue(); efxi(AL_EAXREVERB_DECAY_HFLIMIT, (flags & 0x20) ? AL_TRUE : AL_FALSE); // the other SCALE flags have no equivalent in efx } else { src.ReadTokenOnLine( &token ); src.Error( "idEFXFile::ReadEffect: Invalid parameter in reverb definition" ); } } while ( 1 ); return true; }
/* ================ idDeclAF::ParseBody ================ */ bool idDeclAF::ParseBody( idLexer &src ) { bool hasJoint = false; idToken token; idAFVector angles; idDeclAF_Body *body = new idDeclAF_Body; bodies.Alloc() = body; body->SetDefault( this ); if ( !src.ExpectTokenType( TT_STRING, 0, &token ) || !src.ExpectTokenString( "{" ) ) { return false; } body->name = token; if ( !body->name.Icmp( "origin" ) || !body->name.Icmp( "world" ) ) { src.Error( "a body may not be named \"origin\" or \"world\"" ); return false; } while( src.ReadToken( &token ) ) { if ( !token.Icmp( "model" ) ) { if ( !src.ExpectTokenType( TT_NAME, 0, &token ) ) { return false; } if ( !token.Icmp( "box" ) ) { body->modelType = TRM_BOX; if ( !src.ExpectTokenString( "(" ) || !body->v1.Parse( src ) || !src.ExpectTokenString( "," ) || !body->v2.Parse( src ) || !src.ExpectTokenString( ")" ) ) { return false; } } else if ( !token.Icmp( "octahedron" ) ) { body->modelType = TRM_OCTAHEDRON; if ( !src.ExpectTokenString( "(" ) || !body->v1.Parse( src ) || !src.ExpectTokenString( "," ) || !body->v2.Parse( src ) || !src.ExpectTokenString( ")" ) ) { return false; } } else if ( !token.Icmp( "dodecahedron" ) ) { body->modelType = TRM_DODECAHEDRON; if ( !src.ExpectTokenString( "(" ) || !body->v1.Parse( src ) || !src.ExpectTokenString( "," ) || !body->v2.Parse( src ) || !src.ExpectTokenString( ")" ) ) { return false; } } else if ( !token.Icmp( "cylinder" ) ) { body->modelType = TRM_CYLINDER; if ( !src.ExpectTokenString( "(" ) || !body->v1.Parse( src ) || !src.ExpectTokenString( "," ) || !body->v2.Parse( src ) || !src.ExpectTokenString( "," ) ) { return false; } body->numSides = src.ParseInt(); if ( !src.ExpectTokenString( ")" ) ) { return false; } } else if ( !token.Icmp( "cone" ) ) { body->modelType = TRM_CONE; if ( !src.ExpectTokenString( "(" ) || !body->v1.Parse( src ) || !src.ExpectTokenString( "," ) || !body->v2.Parse( src ) || !src.ExpectTokenString( "," ) ) { return false; } body->numSides = src.ParseInt(); if ( !src.ExpectTokenString( ")" ) ) { return false; } } else if ( !token.Icmp( "bone" ) ) { body->modelType = TRM_BONE; if ( !src.ExpectTokenString( "(" ) || !body->v1.Parse( src ) || !src.ExpectTokenString( "," ) || !body->v2.Parse( src ) || !src.ExpectTokenString( "," ) ) { return false; } body->width = src.ParseFloat(); if ( !src.ExpectTokenString( ")" ) ) { return false; } } else if ( !token.Icmp( "custom" ) ) { src.Error( "custom models not yet implemented" ); return false; } else { src.Error( "unkown model type %s", token.c_str() ); return false; } } else if ( !token.Icmp( "origin" ) ) { if ( !body->origin.Parse( src ) ) { return false; } } else if ( !token.Icmp( "angles" ) ) { if ( !angles.Parse( src ) ) { return false; } body->angles = idAngles( angles.ToVec3().x, angles.ToVec3().y, angles.ToVec3().z ); } else if ( !token.Icmp( "joint" ) ) { if ( !src.ExpectTokenType( TT_STRING, 0, &token ) ) { return false; } body->jointName = token; hasJoint = true; } else if ( !token.Icmp( "mod" ) ) { if ( !src.ExpectAnyToken( &token ) ) { return false; } body->jointMod = JointModFromString( token.c_str() ); } else if ( !token.Icmp( "density" ) ) { body->density = src.ParseFloat(); } else if ( !token.Icmp( "inertiaScale" ) ) { src.Parse1DMatrix( 9, body->inertiaScale[0].ToFloatPtr() ); } else if ( !token.Icmp( "friction" ) ) { body->linearFriction = src.ParseFloat(); src.ExpectTokenString( "," ); body->angularFriction = src.ParseFloat(); src.ExpectTokenString( "," ); body->contactFriction = src.ParseFloat(); } else if ( !token.Icmp( "contents" ) ) { ParseContents( src, body->contents ); } else if ( !token.Icmp( "clipMask" ) ) { ParseContents( src, body->clipMask ); } else if ( !token.Icmp( "selfCollision" ) ) { body->selfCollision = src.ParseBool(); } else if ( !token.Icmp( "containedjoints" ) ) { if ( !src.ExpectTokenType( TT_STRING, 0, &token ) ) { return false; } body->containedJoints = token; } else if ( !token.Icmp( "frictionDirection" ) ) { if ( !body->frictionDirection.Parse( src ) ) { return false; } } else if ( !token.Icmp( "contactMotorDirection" ) ) { if ( !body->contactMotorDirection.Parse( src ) ) { return false; } } else if ( token == "}" ) { break; } else { src.Error( "unknown token %s in body", token.c_str() ); return false; } } if ( body->modelType == TRM_INVALID ) { src.Error( "no model set for body" ); return false; } if ( !hasJoint ) { src.Error( "no joint set for body" ); return false; } body->clipMask |= CONTENTS_MOVEABLECLIP; return true; }
/* ================ idDeclAF::ParseSettings ================ */ bool idDeclAF::ParseSettings( idLexer &src ) { idToken token; if ( !src.ExpectTokenString( "{" ) ) { return false; } while( src.ReadToken( &token ) ) { if ( !token.Icmp( "mesh" ) ) { if ( !src.ExpectTokenType( TT_STRING, 0, &token ) ) { return false; } } else if ( !token.Icmp( "anim" ) ) { if ( !src.ExpectTokenType( TT_STRING, 0, &token ) ) { return false; } } else if ( !token.Icmp( "model" ) ) { if ( !src.ExpectTokenType( TT_STRING, 0, &token ) ) { return false; } model = token; } else if ( !token.Icmp( "skin" ) ) { if ( !src.ExpectTokenType( TT_STRING, 0, &token ) ) { return false; } skin = token; } else if ( !token.Icmp( "friction" ) ) { defaultLinearFriction = src.ParseFloat(); if ( !src.ExpectTokenString( "," ) ) { return false; } defaultAngularFriction = src.ParseFloat(); if ( !src.ExpectTokenString( "," ) ) { return false; } defaultContactFriction = src.ParseFloat(); if ( src.CheckTokenString( "," ) ) { defaultConstraintFriction = src.ParseFloat(); } } else if ( !token.Icmp( "totalMass" ) ) { totalMass = src.ParseFloat(); } else if ( !token.Icmp( "suspendSpeed" ) ) { suspendVelocity[0] = src.ParseFloat(); if ( !src.ExpectTokenString( "," ) ) { return false; } suspendVelocity[1] = src.ParseFloat(); if ( !src.ExpectTokenString( "," ) ) { return false; } suspendAcceleration[0] = src.ParseFloat(); if ( !src.ExpectTokenString( "," ) ) { return false; } suspendAcceleration[1] = src.ParseFloat(); } else if ( !token.Icmp( "noMoveTime" ) ) { noMoveTime = src.ParseFloat(); } else if ( !token.Icmp( "noMoveTranslation" ) ) { noMoveTranslation = src.ParseFloat(); } else if ( !token.Icmp( "noMoveRotation" ) ) { noMoveRotation = src.ParseFloat(); } else if ( !token.Icmp( "minMoveTime" ) ) { minMoveTime = src.ParseFloat(); } else if ( !token.Icmp( "maxMoveTime" ) ) { maxMoveTime = src.ParseFloat(); } else if ( !token.Icmp( "contents" ) ) { ParseContents( src, contents ); } else if ( !token.Icmp( "clipMask" ) ) { ParseContents( src, clipMask ); } else if ( !token.Icmp( "selfCollision" ) ) { selfCollision = src.ParseBool(); } else if ( token == "}" ) { break; } else { src.Error( "unknown token %s in settings", token.c_str() ); return false; } } return true; }
/* ================ idDeclAF::ParseUniversalJoint ================ */ bool idDeclAF::ParseUniversalJoint( idLexer &src ) { idToken token; idDeclAF_Constraint *constraint = new idDeclAF_Constraint; constraint->SetDefault( this ); constraints.Alloc() = constraint; if ( !src.ExpectTokenType( TT_STRING, 0, &token ) || !src.ExpectTokenString( "{" ) ) { return false; } constraint->type = DECLAF_CONSTRAINT_UNIVERSALJOINT; constraint->limit = idDeclAF_Constraint::LIMIT_NONE; constraint->name = token; constraint->friction = 0.5f; constraint->anchor.ToVec3().Zero(); constraint->shaft[0].ToVec3().Zero(); constraint->shaft[1].ToVec3().Zero(); while( src.ReadToken( &token ) ) { if ( !token.Icmp( "body1" ) ) { src.ExpectTokenType( TT_STRING, 0, &token ); constraint->body1 = token; } else if ( !token.Icmp( "body2" ) ) { src.ExpectTokenType( TT_STRING, 0, &token ); constraint->body2 = token; } else if ( !token.Icmp( "anchor" ) ) { if ( !constraint->anchor.Parse( src ) ) { return false; } } else if ( !token.Icmp( "shafts" ) ) { if ( !constraint->shaft[0].Parse( src ) || !src.ExpectTokenString( "," ) || !constraint->shaft[1].Parse( src ) ) { return false; } } else if ( !token.Icmp( "conelimit" ) ) { if ( !constraint->limitAxis.Parse( src ) || !src.ExpectTokenString( "," ) ) { return false; } constraint->limitAngles[0] = src.ParseFloat(); constraint->limit = idDeclAF_Constraint::LIMIT_CONE; } else if ( !token.Icmp( "pyramidlimit" ) ) { if ( !constraint->limitAxis.Parse( src ) || !src.ExpectTokenString( "," ) ) { return false; } constraint->limitAngles[0] = src.ParseFloat(); if ( !src.ExpectTokenString( "," ) ) { return false; } constraint->limitAngles[1] = src.ParseFloat(); if ( !src.ExpectTokenString( "," ) ) { return false; } constraint->limitAngles[2] = src.ParseFloat(); constraint->limit = idDeclAF_Constraint::LIMIT_PYRAMID; } else if ( !token.Icmp( "friction" ) ) { constraint->friction = src.ParseFloat(); } else if ( token == "}" ) { break; } else { src.Error( "unknown token %s in universal joint", token.c_str() ); return false; } } return true; }
/* =============== idEFXFile::ReadEffect =============== */ bool idEFXFile::ReadEffect( idLexer &src, idSoundEffect *effect ) { idToken name, token; if ( !src.ReadToken( &token ) ) return false; // reverb effect if ( token == "reverb" ) { EAXREVERBPROPERTIES *reverb = ( EAXREVERBPROPERTIES * )Mem_Alloc( sizeof( EAXREVERBPROPERTIES ) ); if ( reverb ) { src.ReadTokenOnLine( &token ); name = token; if ( !src.ReadToken( &token ) ) { Mem_Free( reverb ); return false; } if ( token != "{" ) { src.Error( "idEFXFile::ReadEffect: { not found, found %s", token.c_str() ); Mem_Free( reverb ); return false; } do { if ( !src.ReadToken( &token ) ) { src.Error( "idEFXFile::ReadEffect: EOF without closing brace" ); Mem_Free( reverb ); return false; } if ( token == "}" ) { effect->name = name; effect->data = ( void * )reverb; effect->datasize = sizeof( EAXREVERBPROPERTIES ); break; } if ( token == "environment" ) { src.ReadTokenOnLine( &token ); reverb->ulEnvironment = token.GetUnsignedIntValue(); } else if ( token == "environment size" ) { reverb->flEnvironmentSize = src.ParseFloat(); } else if ( token == "environment diffusion" ) { reverb->flEnvironmentDiffusion = src.ParseFloat(); } else if ( token == "room" ) { reverb->lRoom = src.ParseInt(); } else if ( token == "room hf" ) { reverb->lRoomHF = src.ParseInt(); } else if ( token == "room lf" ) { reverb->lRoomLF = src.ParseInt(); } else if ( token == "decay time" ) { reverb->flDecayTime = src.ParseFloat(); } else if ( token == "decay hf ratio" ) { reverb->flDecayHFRatio = src.ParseFloat(); } else if ( token == "decay lf ratio" ) { reverb->flDecayLFRatio = src.ParseFloat(); } else if ( token == "reflections" ) { reverb->lReflections = src.ParseInt(); } else if ( token == "reflections delay" ) { reverb->flReflectionsDelay = src.ParseFloat(); } else if ( token == "reflections pan" ) { reverb->vReflectionsPan.x = src.ParseFloat(); reverb->vReflectionsPan.y = src.ParseFloat(); reverb->vReflectionsPan.z = src.ParseFloat(); } else if ( token == "reverb" ) { reverb->lReverb = src.ParseInt(); } else if ( token == "reverb delay" ) { reverb->flReverbDelay = src.ParseFloat(); } else if ( token == "reverb pan" ) { reverb->vReverbPan.x = src.ParseFloat(); reverb->vReverbPan.y = src.ParseFloat(); reverb->vReverbPan.z = src.ParseFloat(); } else if ( token == "echo time" ) { reverb->flEchoTime = src.ParseFloat(); } else if ( token == "echo depth" ) { reverb->flEchoDepth = src.ParseFloat(); } else if ( token == "modulation time" ) { reverb->flModulationTime = src.ParseFloat(); } else if ( token == "modulation depth" ) { reverb->flModulationDepth = src.ParseFloat(); } else if ( token == "air absorption hf" ) { reverb->flAirAbsorptionHF = src.ParseFloat(); } else if ( token == "hf reference" ) { reverb->flHFReference = src.ParseFloat(); } else if ( token == "lf reference" ) { reverb->flLFReference = src.ParseFloat(); } else if ( token == "room rolloff factor" ) { reverb->flRoomRolloffFactor = src.ParseFloat(); } else if ( token == "flags" ) { src.ReadTokenOnLine( &token ); reverb->ulFlags = token.GetUnsignedIntValue(); } else { src.ReadTokenOnLine( &token ); src.Error( "idEFXFile::ReadEffect: Invalid parameter in reverb definition" ); Mem_Free( reverb ); } } while ( 1 ); return true; } } else { // other effect (not supported at the moment) src.Error( "idEFXFile::ReadEffect: Unknown effect definition" ); } return false; }
/* ==================== idMD5Mesh::ParseMesh ==================== */ void idMD5Mesh::ParseMesh( idLexer& parser, int numJoints, const idJointMat* joints ) { idToken token; idToken name; parser.ExpectTokenString( "{" ); // // parse name // if( parser.CheckTokenString( "name" ) ) { parser.ReadToken( &name ); } // // parse shader // parser.ExpectTokenString( "shader" ); parser.ReadToken( &token ); idStr shaderName = token; shader = declManager->FindMaterial( shaderName ); // // parse texture coordinates // parser.ExpectTokenString( "numverts" ); int count = parser.ParseInt(); if( count < 0 ) { parser.Error( "Invalid size: %s", token.c_str() ); } this->numVerts = count; idList<idVec2> texCoords; idList<int> firstWeightForVertex; idList<int> numWeightsForVertex; texCoords.SetNum( count ); firstWeightForVertex.SetNum( count ); numWeightsForVertex.SetNum( count ); int numWeights = 0; int maxweight = 0; for( int i = 0; i < texCoords.Num(); i++ ) { parser.ExpectTokenString( "vert" ); parser.ParseInt(); parser.Parse1DMatrix( 2, texCoords[ i ].ToFloatPtr() ); firstWeightForVertex[ i ] = parser.ParseInt(); numWeightsForVertex[ i ] = parser.ParseInt(); if( !numWeightsForVertex[ i ] ) { parser.Error( "Vertex without any joint weights." ); } numWeights += numWeightsForVertex[ i ]; if( numWeightsForVertex[ i ] + firstWeightForVertex[ i ] > maxweight ) { maxweight = numWeightsForVertex[ i ] + firstWeightForVertex[ i ]; } } // // parse tris // parser.ExpectTokenString( "numtris" ); count = parser.ParseInt(); if( count < 0 ) { parser.Error( "Invalid size: %d", count ); } idList<int> tris; tris.SetNum( count * 3 ); numTris = count; for( int i = 0; i < count; i++ ) { parser.ExpectTokenString( "tri" ); parser.ParseInt(); tris[ i * 3 + 0 ] = parser.ParseInt(); tris[ i * 3 + 1 ] = parser.ParseInt(); tris[ i * 3 + 2 ] = parser.ParseInt(); } // // parse weights // parser.ExpectTokenString( "numweights" ); count = parser.ParseInt(); if( count < 0 ) { parser.Error( "Invalid size: %d", count ); } if( maxweight > count ) { parser.Warning( "Vertices reference out of range weights in model (%d of %d weights).", maxweight, count ); } idList<vertexWeight_t> tempWeights; tempWeights.SetNum( count ); assert( numJoints < 256 ); // so we can pack into bytes for( int i = 0; i < count; i++ ) { parser.ExpectTokenString( "weight" ); parser.ParseInt(); int jointnum = parser.ParseInt(); if( ( jointnum < 0 ) || ( jointnum >= numJoints ) ) { parser.Error( "Joint Index out of range(%d): %d", numJoints, jointnum ); } tempWeights[ i ].joint = jointnum; tempWeights[ i ].jointWeight = parser.ParseFloat(); parser.Parse1DMatrix( 3, tempWeights[ i ].offset.ToFloatPtr() ); } // create pre-scaled weights and an index for the vertex/joint lookup idVec4* scaledWeights = ( idVec4* ) Mem_Alloc16( numWeights * sizeof( scaledWeights[0] ), TAG_MD5_WEIGHT ); int* weightIndex = ( int* ) Mem_Alloc16( numWeights * 2 * sizeof( weightIndex[0] ), TAG_MD5_INDEX ); memset( weightIndex, 0, numWeights * 2 * sizeof( weightIndex[0] ) ); count = 0; for( int i = 0; i < texCoords.Num(); i++ ) { int num = firstWeightForVertex[i]; for( int j = 0; j < numWeightsForVertex[i]; j++, num++, count++ ) { scaledWeights[count].ToVec3() = tempWeights[num].offset * tempWeights[num].jointWeight; scaledWeights[count].w = tempWeights[num].jointWeight; weightIndex[count * 2 + 0] = tempWeights[num].joint * sizeof( idJointMat ); } weightIndex[count * 2 - 1] = 1; } parser.ExpectTokenString( "}" ); // update counters c_numVerts += texCoords.Num(); c_numWeights += numWeights; c_numWeightJoints++; for( int i = 0; i < numWeights; i++ ) { c_numWeightJoints += weightIndex[i * 2 + 1]; } // // build a base pose that can be used for skinning // idDrawVert* basePose = ( idDrawVert* )Mem_ClearedAlloc( texCoords.Num() * sizeof( *basePose ), TAG_MD5_BASE ); for( int j = 0, i = 0; i < texCoords.Num(); i++ ) { idVec3 v = ( *( idJointMat* )( ( byte* )joints + weightIndex[j * 2 + 0] ) ) * scaledWeights[j]; while( weightIndex[j * 2 + 1] == 0 ) { j++; v += ( *( idJointMat* )( ( byte* )joints + weightIndex[j * 2 + 0] ) ) * scaledWeights[j]; } j++; basePose[i].Clear(); basePose[i].xyz = v; basePose[i].SetTexCoord( texCoords[i] ); } // build the weights and bone indexes into the verts, so they will be duplicated // as necessary at mirror seems static int maxWeightsPerVert; static float maxResidualWeight; const int MAX_VERTEX_WEIGHTS = 4; idList< bool > jointIsUsed; jointIsUsed.SetNum( numJoints ); for( int i = 0; i < jointIsUsed.Num(); i++ ) { jointIsUsed[i] = false; } numMeshJoints = 0; maxJointVertDist = 0.0f; //----------------------------------------- // new-style setup for fixed four weights and normal / tangent deformation // // Several important models have >25% residual weight in joints after the // first four, which is worrisome for using a fixed four joint deformation. //----------------------------------------- for( int i = 0; i < texCoords.Num(); i++ ) { idDrawVert& dv = basePose[i]; // some models do have >4 joint weights, so it is necessary to sort and renormalize // sort the weights and take the four largest int weights[256]; const int numWeights = numWeightsForVertex[ i ]; for( int j = 0; j < numWeights; j++ ) { weights[j] = firstWeightForVertex[i] + j; } // bubble sort for( int j = 0; j < numWeights; j++ ) { for( int k = 0; k < numWeights - 1 - j; k++ ) { if( tempWeights[weights[k]].jointWeight < tempWeights[weights[k + 1]].jointWeight ) { SwapValues( weights[k], weights[k + 1] ); } } } if( numWeights > maxWeightsPerVert ) { maxWeightsPerVert = numWeights; } const int usedWeights = Min( MAX_VERTEX_WEIGHTS, numWeights ); float totalWeight = 0; for( int j = 0; j < numWeights; j++ ) { totalWeight += tempWeights[weights[j]].jointWeight; } assert( totalWeight > 0.999f && totalWeight < 1.001f ); float usedWeight = 0; for( int j = 0; j < usedWeights; j++ ) { usedWeight += tempWeights[weights[j]].jointWeight; } const float residualWeight = totalWeight - usedWeight; if( residualWeight > maxResidualWeight ) { maxResidualWeight = residualWeight; } byte finalWeights[MAX_VERTEX_WEIGHTS] = { 0 }; byte finalJointIndecies[MAX_VERTEX_WEIGHTS] = { 0 }; for( int j = 0; j < usedWeights; j++ ) { const vertexWeight_t& weight = tempWeights[weights[j]]; const int jointIndex = weight.joint; const float fw = weight.jointWeight; assert( fw >= 0.0f && fw <= 1.0f ); const float normalizedWeight = fw / usedWeight; finalWeights[j] = idMath::Ftob( normalizedWeight * 255.0f ); finalJointIndecies[j] = jointIndex; } // Sort the weights and indices for hardware skinning for( int k = 0; k < 3; ++k ) { for( int l = k + 1; l < 4; ++l ) { if( finalWeights[l] > finalWeights[k] ) { SwapValues( finalWeights[k], finalWeights[l] ); SwapValues( finalJointIndecies[k], finalJointIndecies[l] ); } } } // Give any left over to the biggest weight finalWeights[0] += Max( 255 - finalWeights[0] - finalWeights[1] - finalWeights[2] - finalWeights[3], 0 ); dv.color[0] = finalJointIndecies[0]; dv.color[1] = finalJointIndecies[1]; dv.color[2] = finalJointIndecies[2]; dv.color[3] = finalJointIndecies[3]; dv.color2[0] = finalWeights[0]; dv.color2[1] = finalWeights[1]; dv.color2[2] = finalWeights[2]; dv.color2[3] = finalWeights[3]; for( int j = usedWeights; j < 4; j++ ) { assert( dv.color2[j] == 0 ); } for( int j = 0; j < usedWeights; j++ ) { if( !jointIsUsed[finalJointIndecies[j]] ) { jointIsUsed[finalJointIndecies[j]] = true; numMeshJoints++; } const idJointMat& joint = joints[finalJointIndecies[j]]; float dist = ( dv.xyz - joint.GetTranslation() ).Length(); if( dist > maxJointVertDist ) { maxJointVertDist = dist; } } } meshJoints = ( byte* ) Mem_Alloc( numMeshJoints * sizeof( meshJoints[0] ), TAG_MODEL ); numMeshJoints = 0; for( int i = 0; i < numJoints; i++ ) { if( jointIsUsed[i] ) { meshJoints[numMeshJoints++] = i; } } // build the deformInfo and collect a final base pose with the mirror // seam verts properly including the bone weights deformInfo = R_BuildDeformInfo( texCoords.Num(), basePose, tris.Num(), tris.Ptr(), shader->UseUnsmoothedTangents() ); for( int i = 0; i < deformInfo->numOutputVerts; i++ ) { for( int j = 0; j < 4; j++ ) { if( deformInfo->verts[i].color[j] >= numJoints ) { idLib::FatalError( "Bad joint index" ); } } } Mem_Free( basePose ); }
/* ================ idDeclFX::ParseSingleFXAction ================ */ void idDeclFX::ParseSingleFXAction( idLexer &src, idFXSingleAction& FXAction ) { idToken token; FXAction.type = -1; FXAction.sibling = -1; FXAction.data = "<none>"; FXAction.name = "<none>"; FXAction.fire = "<none>"; FXAction.delay = 0.0f; FXAction.duration = 0.0f; FXAction.restart = 0.0f; FXAction.size = 0.0f; FXAction.fadeInTime = 0.0f; FXAction.fadeOutTime = 0.0f; FXAction.shakeTime = 0.0f; FXAction.shakeAmplitude = 0.0f; FXAction.shakeDistance = 0.0f; FXAction.shakeFalloff = false; FXAction.shakeImpulse = 0.0f; FXAction.shakeIgnoreMaster = false; FXAction.lightRadius = 0.0f; FXAction.rotate = 0.0f; FXAction.random1 = 0.0f; FXAction.random2 = 0.0f; FXAction.lightColor = vec3_origin; FXAction.offset = vec3_origin; FXAction.axis = mat3_identity; FXAction.bindParticles = false; FXAction.explicitAxis = false; FXAction.noshadows = false; FXAction.particleTrackVelocity = false; FXAction.trackOrigin = false; FXAction.soundStarted = false; while (1) { if ( !src.ReadToken( &token ) ) { break; } if ( !token.Icmp( "}" ) ) { break; } if ( !token.Icmp( "shake" ) ) { FXAction.type = FX_SHAKE; FXAction.shakeTime = src.ParseFloat(); src.ExpectTokenString(","); FXAction.shakeAmplitude = src.ParseFloat(); src.ExpectTokenString(","); FXAction.shakeDistance = src.ParseFloat(); src.ExpectTokenString(","); FXAction.shakeFalloff = src.ParseBool(); src.ExpectTokenString(","); FXAction.shakeImpulse = src.ParseFloat(); continue; } if ( !token.Icmp( "noshadows" ) ) { FXAction.noshadows = true; continue; } if ( !token.Icmp( "name" ) ) { src.ReadToken( &token ); FXAction.name = token; continue; } if ( !token.Icmp( "fire") ) { src.ReadToken( &token ); FXAction.fire = token; continue; } if ( !token.Icmp( "random" ) ) { FXAction.random1 = src.ParseFloat(); src.ExpectTokenString( "," ); FXAction.random2 = src.ParseFloat(); FXAction.delay = 0.0f; // check random continue; } if ( !token.Icmp( "delay" ) ) { FXAction.delay = src.ParseFloat(); continue; } if ( !token.Icmp( "rotate" ) ) { FXAction.rotate = src.ParseFloat(); continue; } if ( !token.Icmp( "duration" ) ) { FXAction.duration = src.ParseFloat(); continue; } if ( !token.Icmp( "trackorigin" ) ) { FXAction.trackOrigin = src.ParseBool(); continue; } if (!token.Icmp("restart")) { FXAction.restart = src.ParseFloat(); continue; } if ( !token.Icmp( "fadeIn" ) ) { FXAction.fadeInTime = src.ParseFloat(); continue; } if ( !token.Icmp( "fadeOut" ) ) { FXAction.fadeOutTime = src.ParseFloat(); continue; } if ( !token.Icmp( "size" ) ) { FXAction.size = src.ParseFloat(); continue; } if ( !token.Icmp( "offset" ) ) { FXAction.offset.x = src.ParseFloat(); src.ExpectTokenString( "," ); FXAction.offset.y = src.ParseFloat(); src.ExpectTokenString( "," ); FXAction.offset.z = src.ParseFloat(); continue; } if ( !token.Icmp( "axis" ) ) { idVec3 v; v.x = src.ParseFloat(); src.ExpectTokenString( "," ); v.y = src.ParseFloat(); src.ExpectTokenString( "," ); v.z = src.ParseFloat(); v.Normalize(); FXAction.axis = v.ToMat3(); FXAction.explicitAxis = true; continue; } if ( !token.Icmp( "angle" ) ) { idAngles a; a[0] = src.ParseFloat(); src.ExpectTokenString( "," ); a[1] = src.ParseFloat(); src.ExpectTokenString( "," ); a[2] = src.ParseFloat(); FXAction.axis = a.ToMat3(); FXAction.explicitAxis = true; continue; } if ( !token.Icmp( "uselight" ) ) { src.ReadToken( &token ); FXAction.data = token; for( int i = 0; i < events.Num(); i++ ) { if ( events[i].name.Icmp( FXAction.data ) == 0 ) { FXAction.sibling = i; FXAction.lightColor = events[i].lightColor; FXAction.lightRadius = events[i].lightRadius; } } FXAction.type = FX_LIGHT; // precache the light material declManager->FindMaterial( FXAction.data ); continue; } if ( !token.Icmp( "attachlight" ) ) { src.ReadToken( &token ); FXAction.data = token; FXAction.type = FX_ATTACHLIGHT; // precache it declManager->FindMaterial( FXAction.data ); continue; } if ( !token.Icmp( "attachentity" ) ) { src.ReadToken( &token ); FXAction.data = token; FXAction.type = FX_ATTACHENTITY; // precache the model renderModelManager->FindModel( FXAction.data ); continue; } if ( !token.Icmp( "launch" ) ) { src.ReadToken( &token ); FXAction.data = token; FXAction.type = FX_LAUNCH; // precache the entity def declManager->FindType( DECL_ENTITYDEF, FXAction.data ); continue; } if ( !token.Icmp( "useModel" ) ) { src.ReadToken( &token ); FXAction.data = token; for( int i = 0; i < events.Num(); i++ ) { if ( events[i].name.Icmp( FXAction.data ) == 0 ) { FXAction.sibling = i; } } FXAction.type = FX_MODEL; // precache the model renderModelManager->FindModel( FXAction.data ); continue; } if ( !token.Icmp( "light" ) ) { src.ReadToken( &token ); FXAction.data = token; src.ExpectTokenString( "," ); FXAction.lightColor[0] = src.ParseFloat(); src.ExpectTokenString( "," ); FXAction.lightColor[1] = src.ParseFloat(); src.ExpectTokenString( "," ); FXAction.lightColor[2] = src.ParseFloat(); src.ExpectTokenString( "," ); FXAction.lightRadius = src.ParseFloat(); FXAction.type = FX_LIGHT; // precache the light material declManager->FindMaterial( FXAction.data ); continue; } if ( !token.Icmp( "model" ) ) { src.ReadToken( &token ); FXAction.data = token; FXAction.type = FX_MODEL; // precache it renderModelManager->FindModel( FXAction.data ); continue; } if ( !token.Icmp( "particle" ) ) { // FIXME: now the same as model src.ReadToken( &token ); FXAction.data = token; FXAction.type = FX_PARTICLE; // precache it renderModelManager->FindModel( FXAction.data ); continue; } if ( !token.Icmp( "decal" ) ) { src.ReadToken( &token ); FXAction.data = token; FXAction.type = FX_DECAL; // precache it declManager->FindMaterial( FXAction.data ); continue; } if ( !token.Icmp( "particleTrackVelocity" ) ) { FXAction.particleTrackVelocity = true; continue; } if ( !token.Icmp( "sound" ) ) { src.ReadToken( &token ); FXAction.data = token; FXAction.type = FX_SOUND; // precache it declManager->FindSound( FXAction.data ); continue; } if ( !token.Icmp( "ignoreMaster" ) ) { FXAction.shakeIgnoreMaster = true; continue; } if ( !token.Icmp( "shockwave" ) ) { src.ReadToken( &token ); FXAction.data = token; FXAction.type = FX_SHOCKWAVE; // precache the entity def declManager->FindType( DECL_ENTITYDEF, FXAction.data ); continue; } src.Warning( "FX File: bad token" ); continue; } }
/* ==================== idMD5Mesh::ParseMesh ==================== */ void idMD5Mesh::ParseMesh( idLexer &parser, int numJoints, const idJointMat *joints ) { idToken token; idToken name; int num; int count; int jointnum; idStr shaderName; int i, j; idList<int> tris; idList<int> firstWeightForVertex; idList<int> numWeightsForVertex; int maxweight; idList<vertexWeight_t> tempWeights; parser.ExpectTokenString( "{" ); // // parse name // if ( parser.CheckTokenString( "name" ) ) { parser.ReadToken( &name ); } // // parse shader // parser.ExpectTokenString( "shader" ); parser.ReadToken( &token ); shaderName = token; shader = declManager->FindMaterial( shaderName ); // // parse texture coordinates // parser.ExpectTokenString( "numverts" ); count = parser.ParseInt(); if ( count < 0 ) { parser.Error( "Invalid size: %s", token.c_str() ); } texCoords.SetNum( count ); firstWeightForVertex.SetNum( count ); numWeightsForVertex.SetNum( count ); numWeights = 0; maxweight = 0; for( i = 0; i < texCoords.Num(); i++ ) { parser.ExpectTokenString( "vert" ); parser.ParseInt(); parser.Parse1DMatrix( 2, texCoords[ i ].ToFloatPtr() ); firstWeightForVertex[ i ] = parser.ParseInt(); numWeightsForVertex[ i ] = parser.ParseInt(); if ( !numWeightsForVertex[ i ] ) { parser.Error( "Vertex without any joint weights." ); } numWeights += numWeightsForVertex[ i ]; if ( numWeightsForVertex[ i ] + firstWeightForVertex[ i ] > maxweight ) { maxweight = numWeightsForVertex[ i ] + firstWeightForVertex[ i ]; } } // // parse tris // parser.ExpectTokenString( "numtris" ); count = parser.ParseInt(); if ( count < 0 ) { parser.Error( "Invalid size: %d", count ); } tris.SetNum( count * 3 ); numTris = count; for( i = 0; i < count; i++ ) { parser.ExpectTokenString( "tri" ); parser.ParseInt(); tris[ i * 3 + 0 ] = parser.ParseInt(); tris[ i * 3 + 1 ] = parser.ParseInt(); tris[ i * 3 + 2 ] = parser.ParseInt(); } // // parse weights // parser.ExpectTokenString( "numweights" ); count = parser.ParseInt(); if ( count < 0 ) { parser.Error( "Invalid size: %d", count ); } if ( maxweight > count ) { parser.Warning( "Vertices reference out of range weights in model (%d of %d weights).", maxweight, count ); } tempWeights.SetNum( count ); for( i = 0; i < count; i++ ) { parser.ExpectTokenString( "weight" ); parser.ParseInt(); jointnum = parser.ParseInt(); if ( ( jointnum < 0 ) || ( jointnum >= numJoints ) ) { parser.Error( "Joint Index out of range(%d): %d", numJoints, jointnum ); } tempWeights[ i ].joint = jointnum; tempWeights[ i ].jointWeight = parser.ParseFloat(); parser.Parse1DMatrix( 3, tempWeights[ i ].offset.ToFloatPtr() ); } // create pre-scaled weights and an index for the vertex/joint lookup scaledWeights = (idVec4 *) Mem_Alloc16( numWeights * sizeof( scaledWeights[0] ) ); weightIndex = (int *) Mem_Alloc16( numWeights * 2 * sizeof( weightIndex[0] ) ); memset( weightIndex, 0, numWeights * 2 * sizeof( weightIndex[0] ) ); count = 0; for( i = 0; i < texCoords.Num(); i++ ) { num = firstWeightForVertex[i]; for( j = 0; j < numWeightsForVertex[i]; j++, num++, count++ ) { scaledWeights[count].ToVec3() = tempWeights[num].offset * tempWeights[num].jointWeight; scaledWeights[count].w = tempWeights[num].jointWeight; weightIndex[count * 2 + 0] = tempWeights[num].joint * sizeof( idJointMat ); } weightIndex[count * 2 - 1] = 1; } tempWeights.Clear(); numWeightsForVertex.Clear(); firstWeightForVertex.Clear(); parser.ExpectTokenString( "}" ); // update counters c_numVerts += texCoords.Num(); c_numWeights += numWeights; c_numWeightJoints++; for ( i = 0; i < numWeights; i++ ) { c_numWeightJoints += weightIndex[i*2+1]; } // // build the information that will be common to all animations of this mesh: // silhouette edge connectivity and normal / tangent generation information // idDrawVert *verts = (idDrawVert *) _alloca16( texCoords.Num() * sizeof( idDrawVert ) ); for ( i = 0; i < texCoords.Num(); i++ ) { verts[i].Clear(); verts[i].st = texCoords[i]; } TransformVerts( verts, joints ); deformInfo = R_BuildDeformInfo( texCoords.Num(), verts, tris.Num(), tris.Ptr(), shader->UseUnsmoothedTangents() ); }
/* =============== idSoundShader::ParseShader =============== */ bool idSoundShader::ParseShader( idLexer &src ) { idToken token; parms.minDistance = 1; parms.maxDistance = 10; parms.volume = 1; parms.shakes = 0; parms.soundShaderFlags = 0; parms.soundClass = 0; speakerMask = 0; altSound = NULL; entries.Clear(); while ( 1 ) { if ( !src.ExpectAnyToken( &token ) ) { return false; } // end of definition else if ( token == "}" ) { break; } // minimum number of sounds else if ( !token.Icmp( "minSamples" ) ) { src.ParseInt(); } // description else if ( !token.Icmp( "description" ) ) { src.ReadTokenOnLine( &token ); } // mindistance else if ( !token.Icmp( "mindistance" ) ) { parms.minDistance = src.ParseFloat(); } // maxdistance else if ( !token.Icmp( "maxdistance" ) ) { parms.maxDistance = src.ParseFloat(); } // shakes screen else if ( !token.Icmp( "shakes" ) ) { src.ExpectAnyToken( &token ); if ( token.type == TT_NUMBER ) { parms.shakes = token.GetFloatValue(); } else { src.UnreadToken( &token ); parms.shakes = 1.0f; } } // reverb else if ( !token.Icmp( "reverb" ) ) { src.ParseFloat(); if ( !src.ExpectTokenString( "," ) ) { src.FreeSource(); return false; } src.ParseFloat(); // no longer supported } // volume else if ( !token.Icmp( "volume" ) ) { parms.volume = src.ParseFloat(); } // leadinVolume is used to allow light breaking leadin sounds to be much louder than the broken loop else if ( !token.Icmp( "leadinVolume" ) ) { leadinVolume = src.ParseFloat(); leadin = true; } // speaker mask else if ( !token.Icmp( "mask_center" ) ) { speakerMask |= 1<<SPEAKER_CENTER; } // speaker mask else if ( !token.Icmp( "mask_left" ) ) { speakerMask |= 1<<SPEAKER_LEFT; } // speaker mask else if ( !token.Icmp( "mask_right" ) ) { speakerMask |= 1<<SPEAKER_RIGHT; } // speaker mask else if ( !token.Icmp( "mask_backright" ) ) { speakerMask |= 1<<SPEAKER_BACKRIGHT; } // speaker mask else if ( !token.Icmp( "mask_backleft" ) ) { speakerMask |= 1<<SPEAKER_BACKLEFT; } // speaker mask else if ( !token.Icmp( "mask_lfe" ) ) { speakerMask |= 1<<SPEAKER_LFE; } // soundClass else if ( !token.Icmp( "soundClass" ) ) { parms.soundClass = src.ParseInt(); if ( parms.soundClass < 0 || parms.soundClass >= SOUND_MAX_CLASSES ) { src.Warning( "SoundClass out of range" ); return false; } } // altSound else if ( !token.Icmp( "altSound" ) ) { if ( !src.ExpectAnyToken( &token ) ) { return false; } altSound = declManager->FindSound( token.c_str() ); } // ordered else if ( !token.Icmp( "ordered" ) ) { // no longer supported } // no_dups else if ( !token.Icmp( "no_dups" ) ) { parms.soundShaderFlags |= SSF_NO_DUPS; } // no_flicker else if ( !token.Icmp( "no_flicker" ) ) { parms.soundShaderFlags |= SSF_NO_FLICKER; } // plain else if ( !token.Icmp( "plain" ) ) { // no longer supported } // looping else if ( !token.Icmp( "looping" ) ) { parms.soundShaderFlags |= SSF_LOOPING; } // no occlusion else if ( !token.Icmp( "no_occlusion" ) ) { parms.soundShaderFlags |= SSF_NO_OCCLUSION; } // private else if ( !token.Icmp( "private" ) ) { parms.soundShaderFlags |= SSF_PRIVATE_SOUND; } // antiPrivate else if ( !token.Icmp( "antiPrivate" ) ) { parms.soundShaderFlags |= SSF_ANTI_PRIVATE_SOUND; } // once else if ( !token.Icmp( "playonce" ) ) { parms.soundShaderFlags |= SSF_PLAY_ONCE; } // global else if ( !token.Icmp( "global" ) ) { parms.soundShaderFlags |= SSF_GLOBAL; } // unclamped else if ( !token.Icmp( "unclamped" ) ) { parms.soundShaderFlags |= SSF_UNCLAMPED; } // omnidirectional else if ( !token.Icmp( "omnidirectional" ) ) { parms.soundShaderFlags |= SSF_OMNIDIRECTIONAL; } else if ( !token.Icmp( "onDemand" ) ) { // no longer loading sounds on demand } // the wave files else if ( !token.Icmp( "leadin" ) ) { leadin = true; } else if ( token.Find( ".wav", false ) != -1 || token.Find( ".ogg", false ) != -1 ) { if ( token.IcmpPrefixPath( "sound/vo/" ) == 0 || token.IcmpPrefixPath( "sound/guis/" ) == 0 ) { parms.soundShaderFlags |= SSF_VO; } if ( token.IcmpPrefixPath( "sound/musical/" ) == 0 ) { parms.soundShaderFlags |= SSF_MUSIC; } // add to the wav list if ( s_maxSamples.GetInteger() == 0 || ( s_maxSamples.GetInteger() > 0 && entries.Num() < s_maxSamples.GetInteger() ) ) { entries.Append( soundSystemLocal.LoadSample( token.c_str() ) ); } } else { src.Warning( "unknown token '%s'", token.c_str() ); return false; } } return true; }