| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224 |
- //============================================================================================
- // Spirenkov Maxim, 2004
- //============================================================================================
- // Mission objects
- //============================================================================================
- // MissionGeometry
- //============================================================================================
- #include "MissionGeometry.h"
- #define GLUE_DISTANCE 3950.0f
- //============================================================================================
- const MissionGeometry::PGroup MissionGeometry::pgroups[] =
- {
- {ConstString("World"), phys_world},
- {ConstString("Character"), phys_character},
- {ConstString("Player"), phys_player},
- {ConstString("Particles"), phys_particles},
- {ConstString("Ships"), phys_ship},
- {ConstString("Blood"), phys_bloodpatch},
- {ConstString("Boss"), phys_boss}
- };
- MissionGeometry::MissionGeometry()
- {
- bUseDistanceHack = false;
- rigidBody = null;
- model = null;
- events = null;
- shadow = null;
- fadeAlpha = 1.0f;
- alpha = 1.0f;
- fade = fd_none;
- fadeTime = 0.0f;
- isCheckLod = false;
- isPrevLodAlpha = false;
- bNotUseFog = false;
- h_density = 0.0f;
- h_min = 0.0f;
- h_max = 0.0f;
- d_density = 0.0f;
- d_min = 0.0f;
- d_max = 0.0f;
- fog_color = Color(0.0f);
-
- }
- MissionGeometry::~MissionGeometry()
- {
- if(events)
- {
- delete events;
- events = null;
- }
- if(rigidBody) rigidBody->Release();
- rigidBody = null;
- UnloadModel();
- }
- //============================================================================================
- //Инициализировать объект
- bool MissionGeometry::Create(MOPReader & reader)
- {
- if(!GeometryObject::Create(reader)) return false;
- if(rigidBody) rigidBody->Release();
- rigidBody = null;
- if(!events)
- {
- delete events;
- events = null;
- }
- bool res = LoadModel(model, reader.String());
- res |= LoadModel(shadow, reader.String());
- if(!res) return false;
- //Назначаемая анимация
- const char * ani = reader.String().c_str();
- if(ani[0] && model)
- {
- events = NEW AnimationStdEvents();
- events->Init(&Sound(), &Particles(), &Mission());
- model->SetAnimationFile(ani);
- }
- //Позиция
- Vector pos = reader.Position();
- Vector ang = reader.Angles();
- modelMatrix.Build(ang, pos);
- //К кому присоединять
- connectToName = reader.String();
- connectToPtr.Reset();
- if(!reader.Bool())
- {
- connectToName.Empty();
- }
- if( EditMode_IsOn() && connectToName.NotEmpty())
- FindObject(connectToName, connectToPtr);
- //Использование рутовой кости
- bUseRootBone = reader.Bool();
- //Видимость, коллижен
- bool show = reader.Bool();
- bool act = reader.Bool();
- //Группа коллизии
- ConstString gid = reader.Enum();
- PhysicsCollisionGroup physGroup = phys_world;
- for(dword i = 0; i < ARRSIZE(pgroups); i++)
- {
- if(gid == pgroups[i].name)
- {
- physGroup = pgroups[i].group;
- break;
- }
- }
- Assert(i < ARRSIZE(MissionGeometry::pgroups));
- bNotUseFog = reader.Bool();
- //Уровень отрисовки
- level = reader.Long();
- //Цвет
- color = reader.Colors();
- if(model)
- {
- model->SetUserColor(color);
- }
- //Делаем "мягкую" альфу
- bool bSmoothAlpha = reader.Bool();
- if(bSmoothAlpha && model)
- {
- model->SetFloatAlphaReference(0.003921f);
- }
- enableRender = reader.Bool();
- //Уровень отрисовки
- if(!reader.Bool())
- {
- level = (ML_GEOMETRY3 - ML_GEOMETRY1)*level/100 + ML_GEOMETRY1;
- }else{
- level = (ML_ALPHA3 - ML_ALPHA1)*level/100 + ML_ALPHA1;
- }
- //Освещение
- dynamicLighting = reader.Bool();
- if(model)
- {
- model->SetDynamicLightState(dynamicLighting);
- }
- //Теневые дела
- shadowCast = reader.Bool();
- shadowReceive = reader.Bool();
- //Отражение в море
- seaReflection = reader.Bool();
- //Преломление в море
- seaRefraction = reader.Bool();
- //Прятать при скрывании в редакторе
- hideInEditor = reader.Bool();
- //Качатся или нет
- noSwing = reader.Bool();
- //Дистанция лодирования
- float lodDistanceMin = reader.Float();
- float lodDistanceDelta = reader.Float();
- //Использовать distance hack или нет
- bUseDistanceHack = reader.Bool();
- lodDistanceDelta = Clampf(lodDistanceDelta, 0.001f, 1000.0f);
- isPrevLodAlpha = false;
- if(lodDistanceMin > 1e-5f)
- {
- float lodDistanceMax = lodDistanceMin + lodDistanceDelta;
- lodDistanceMin2 = lodDistanceMin*lodDistanceMin;
- lodDistanceK2 = 1.0f/(lodDistanceMax*lodDistanceMax - lodDistanceMin*lodDistanceMin);
- isCheckLod = true;
- }else{
- lodDistanceMin2 = 0.0f;
- lodDistanceK2 = 0.0f;
- isCheckLod = false;
- }
- //Инициализация
- if(!EditMode_IsOn() && events) events->SetScene(model, modelMatrix);
- //Установим матрицу
- if(model)
- {
- model->SetTransform(modelMatrix);
- model->SetShadowReceiveState(shadowReceive);
- rigidBody = model->CreatePhysicsActor(Physics(), false);
- if(rigidBody)
- {
- rigidBody->SetGroup(physGroup);
- rigidBody->SetTransform(modelMatrix);
- }
- }
- //Применение флажков
- fade = fd_none;
- fadeAlpha = 1.0f;
- alpha = 1.0f;
- Show(show);
- Activate(act);
- return true;
- }
- //Вызываеться, когда все объекты созданны но ещё не началось исполнение миссии
- void MissionGeometry::PostCreate()
- {
- if(connectToName.NotEmpty())
- {
- FindObject(connectToName, connectToPtr);
- }
- }
- /*
- //Пересоздать объект
- void MissionGeometry::Restart()
- {
- ReCreate();
- }
- */
- //Обработчик команд для объекта
- void MissionGeometry::Command(const char * id, dword numParams, const char ** params)
- {
- if(string::IsEmpty(id)) return;
- const ConstString cmd(id);
- //Список команд
- static const ConstString cmd_postdraw("postdraw");
- static const ConstString cmd_teleport("teleport");
- static const ConstString cmd_startnode("startnode");
- static const ConstString cmd_actlink("actlink");
- static const ConstString cmd_fadeout("fadeout");
- static const ConstString cmd_fadein("fadein");
- static const ConstString cmd_fade("fade");
- static const ConstString cmd_shadow_cast("shadow_cast");
- static const ConstString cmd_shadow_receive("shadow_receive");
- static const ConstString cmd_collapse("collapse");
- static const ConstString cmd_reset("reset");
- static const ConstString cmd_pause("pause");
- static const ConstString cmd_unpause("unpause");
- static const ConstString cmd_RedirectSoundEvent("RedirectSoundEvent");
- //Исполняем команду
- if(cmd == cmd_postdraw)
- {
- Draw(0.0f, 0);
- }else
- if(cmd == cmd_teleport)
- {
- if(numParams < 1) return;
- MOSafePointer obj;
- if(FindObject(ConstString(params[0]), obj))
- {
- obj.Ptr()->GetMatrix(modelMatrix);
- if(model) model->SetTransform(modelMatrix);
- if(rigidBody)
- {
- rigidBody->SetTransform(modelMatrix);
- }
- LogicDebug("Teleport geometry \"%s\" to mission object \"%s\"", GetObjectID().c_str(), obj.Ptr()->GetObjectID().c_str());
- }else{
- LogicDebugError("Can't teleport geometry \"%s\" to mission object \"%s\", object not found...", GetObjectID().c_str(), params[0]);
- }
- }else
- if(cmd == cmd_startnode)
- {
- if(numParams < 1 || !model) return;
- float blendTime = 0.0f;
- if(numParams >= 2)
- {
- char * pos = null;
- blendTime = (float)strtod(params[1], &pos);
- blendTime = Clampf(blendTime, 0.0f, 100.0f);
- }
- IAnimation * a = model->GetAnimation();
- if(a)
- {
- if(!a->Goto(params[0], blendTime))
- {
- LogicDebugError("Can't start animation node \"%s\" in geometry \"%s\".", params[0], GetObjectID().c_str());
- }
- a->Release();
- }else{
- LogicDebugError("Can't start animation node \"%s\" in geometry \"%s\", geometry not animated.", params[0], GetObjectID().c_str());
- }
- }else
- if(cmd == cmd_actlink)
- {
- if(numParams < 1 || !model) return;
- IAnimation * a = model->GetAnimation();
- if(a)
- {
- if(!ActivateAnimationLink(params[0]))
- {
- LogicDebugError("Can't start animation link \"%s\" in geometry \"%s\".", params[0], GetObjectID().c_str());
- }
- a->Release();
- }else{
- LogicDebugError("Can't start animation node \"%s\" in geometry \"%s\", geometry not animated.", params[0], GetObjectID().c_str());
- }
- }else
- if(cmd == cmd_fadeout)
- {
- if(fade != fd_hide)
- {
- LogicDebug("Fadeout");
- fade = fd_fadeout;
- fadeTime = 0.0f;
- }else{
- LogicDebugError("Fadeout ignore, course work \"Fade\"");
- }
- }else
- if(cmd == cmd_fadein)
- {
- if(fade != fd_hide)
- {
- LogicDebug("Fadein");
- fade = fd_fadein;
- fadeTime = 0.0f;
- }else{
- LogicDebugError("Fadein ignore, course work \"Fade\"");
- }
- }else
- if(cmd == cmd_fade)
- {
- if(fade != fd_hide)
- {
- LogicDebug("Fade");
- fade = fd_hide;
- fadeTime = 0.0f;
- }else{
- LogicDebugError("Ignore fade already work \"Fade\"");
- }
- }else
- if(cmd == cmd_shadow_cast)
- {
- if(numParams >= 1 && params[0][0])
- {
- shadowCast = params[0][0] != '0';
- Show(IsShow());
- LogicDebug("%s state shadow_cast in geometry \"%s\"", shadowCast ? "Enable" : "Disable", GetObjectID().c_str());
- }else{
- LogicDebugError("Can't change shadow_cast state in geometry \"%s\", because no params", GetObjectID().c_str());
- }
- }else
- if(cmd == cmd_shadow_receive)
- {
- if(numParams >= 1 && params[0][0])
- {
- shadowReceive = params[0][0] != '0';
- Show(IsShow());
- LogicDebug("%s state shadow_receive in geometry \"%s\"", shadowReceive ? "Enable" : "Disable", GetObjectID().c_str());
- }else{
- LogicDebugError("Can't change shadow_receive state in geometry \"%s\", because no params", GetObjectID().c_str());
- }
- }else
- if(cmd == cmd_collapse)
- {
- if(numParams >= 1 && params[0][0])
- {
- if(model)
- {
- IAnimation * ani = model->GetAnimation();
- if(ani)
- {
- const char * prms[2];
- static const char * collapse = "Collapse";
- static const char * restore = "Restore";
- if(numParams >= 2)
- {
- prms[0] = (params[1][0] == 't' || params[1][0] == 'T') ? collapse : restore;
- }else{
- prms[0] = collapse;
- }
- prms[1] = params[0];
- LogicDebug("%s bone: %s", prms[0], params[0]);
- if(events)
- {
- events->BoneCollapse(ani, "BoneCollapse", prms, 2);
- }else{
- LogicDebugError("Can't collapse bone in geometry \"%s\", because events not created", GetObjectID().c_str());
- }
- ani->Release();
- }else{
- LogicDebugError("Can't collapse bone in geometry \"%s\", because animation isn't set", GetObjectID().c_str());
- }
- }else{
- LogicDebugError("Can't collapse bone in geometry \"%s\", because model not loaded", GetObjectID().c_str());
- }
- }else{
- LogicDebugError("Can't collapse bone in geometry \"%s\", because no params", GetObjectID().c_str());
- }
- }else
- if(cmd == cmd_reset)
- {
- LogicDebug("Reset events");
- if(events)
- {
- events->ResetParticles();
- events->ResetSounds();
- events->ResetCollapser();
- }
- fadeAlpha = 1.0f;
- alpha = 1.0f;
- fade = fd_none;
- IAnimation * ani = model->GetAnimation();
- if(ani)
- {
- ani->Start();
- ani->Release();
- }else{
- LogicDebugError("Can't reset animation, because it's not set");
- }
- Show(IsShow());
- }else
- if(cmd == cmd_pause)
- {
- IAnimation * ani = model->GetAnimation();
- if(ani)
- {
- LogicDebug("Pause");
- ani->Pause(true);
- ani->Release();
- }
- }else
- if(cmd == cmd_unpause)
- {
- IAnimation * ani = model->GetAnimation();
- if(ani)
- {
- LogicDebug("Unpause");
- ani->Pause(false);
- ani->Release();
- }
- }else
- if(cmd == cmd_RedirectSoundEvent)
- {
- LogicDebug("RedirectSoundEvent");
- IAnimation * ani = model->GetAnimation();
- if(ani && events)
- {
- events->PlaySound(ani, "Snd", params, numParams);
- ani->Release();
- }else{
- LogicDebugError("Animation not set for this geometry");
- }
- }else{
- LogicDebugError("Unknown command: %s", id);
- }
- }
- //Инициализировать объект
- bool MissionGeometry::EditMode_Create(MOPReader & reader)
- {
- Create(reader);
- return true;
- }
- //Обновить параметры
- bool MissionGeometry::EditMode_Update(MOPReader & reader)
- {
- DelUpdate();
- Unregistry(MG_SHADOWCAST);
- Unregistry(MG_SHADOWRECEIVE);
- // Unregistry(MG_DOF);
- Unregistry(MG_SHADOWDONTRECEIVE);
- Create(reader);
- return true;
- }
- //Получить размеры описывающего ящика
- void MissionGeometry::EditMode_GetSelectBox(Vector & min, Vector & max)
- {
- if(model || shadow)
- {
- GetBox(min, max);
- return;
- }
- min = -0.5f;
- max = 0.5f;
- }
- //Получить бокс, описывающий объект в локальных координатах
- void MissionGeometry::GetBox(Vector & min, Vector & max)
- {
- if(model)
- {
- min = model->GetLocalBound().vMin;
- max = model->GetLocalBound().vMax;
- if(bUseRootBone)
- {
- IAnimation * ani = model->GetAnimation();
- if(ani)
- {
- max = (max - min)*0.5f;
- min = -max;
- ani->Release();
- }
- }
- return;
- }else
- if(shadow)
- {
- min = shadow->GetLocalBound().vMin;
- max = shadow->GetLocalBound().vMax;
- return;
- }
- min = 0.0f;
- max = 0.0f;
- }
- //Получить матрицу объекта
- Matrix & MissionGeometry::GetMatrix(Matrix & mtx)
- {
- if(bUseRootBone && model)
- {
- IAnimation * a = model->GetAnimation();
- if(a)
- {
- mtx = a->GetBoneMatrix(0)*modelMatrix;
- a->Release();
- return mtx;
- }
- }else{
- mtx = modelMatrix;
- }
- if(connectToPtr.Validate())
- {
- mtx = mtx*connectToPtr.Ptr()->GetMatrix(Matrix());
- }
- return mtx;
- };
- //Показать/скрыть объект
- void MissionGeometry::Show(bool isShow)
- {
- GeometryObject::Show(isShow);
- if(IsShow())
- {
- LogicDebug("Show");
- PauseAnimation(false);
- long curLevel = level;
- bool isTransp = false;
- if(alpha < 1.0f || fade != fd_none)
- {
- curLevel = c_fadelevel;
- isTransp = true;
- }
- DelUpdate(&MissionGeometry::Draw);
- if(enableRender)
- {
- SetUpdate(&MissionGeometry::Draw, curLevel);
- }
- if(EditMode_IsOn())
- {
- DelUpdate(&MissionGeometry::DrawTransparency);
- }
- if(shadowCast)
- {
- Registry(MG_SHADOWCAST, (MOF_EVENT)&MissionGeometry::ShadowInfo, curLevel);
- }else{
- Unregistry(MG_SHADOWCAST);
- }
- if(shadowReceive)
- {
- Unregistry(MG_SHADOWDONTRECEIVE);
- if(!isTransp)
- {
- Registry(MG_SHADOWRECEIVE, (MOF_EVENT)&MissionGeometry::ShadowRecive, curLevel);
- }else{
- Unregistry(MG_SHADOWRECEIVE);
- }
- }else{
- Unregistry(MG_SHADOWRECEIVE);
- if(curLevel < ML_ALPHA1 && enableRender) Registry(MG_SHADOWDONTRECEIVE, (MOF_EVENT)&MissionGeometry::ShadowRecive, curLevel);
- }
- if(seaReflection)
- {
- Registry(MG_SEAREFLECTION, (MOF_EVENT)&MissionGeometry::SeaReflection, curLevel);
- }else{
- Unregistry(MG_SEAREFLECTION);
- }
-
- if(seaRefraction)
- {
- Registry(MG_SEAREFRACTION, (MOF_EVENT)&MissionGeometry::SeaRefraction, curLevel);
- }else{
- Unregistry(MG_SEAREFRACTION);
- }
- // Registry(MG_DOF, (MOF_EVENT)&MissionGeometry::SeaReflection, curLevel);
- }else{
- LogicDebug("Hide");
- PauseAnimation(true);
- if(events)
- {
- events->ResetParticles();
- }
- DelUpdate(&MissionGeometry::Draw);
- if(EditMode_IsOn() && !hideInEditor)
- {
- SetUpdate(&MissionGeometry::DrawTransparency, ML_ALPHA4);
- }
- // Unregistry(MG_DOF);
- Unregistry(MG_SHADOWCAST);
- Unregistry(MG_SHADOWRECEIVE);
- Unregistry(MG_SEAREFLECTION);
- Unregistry(MG_SEAREFRACTION);
- Unregistry(MG_SHADOWDONTRECEIVE);
- }
- }
- //Активировать/деактивировать объект
- void MissionGeometry::Activate(bool isActive)
- {
- GeometryObject::Activate(isActive);
- if(EditMode_IsOn())
- {
- return;
- }
- if(rigidBody)
- {
- rigidBody->Activate(IsActive());
- if(IsActive())
- {
- LogicDebug("Activate");
- }else{
- LogicDebug("Deactivate");
- }
- }else{
- if(isActive)
- {
- LogicDebugError("Can't activate collision -> no present collision data in file \"%s\"", (model ? model->GetFileName() : ""));
- }else{
- LogicDebug("Deactivate");
- }
- }
- }
- //Нарисовать модельку
- void _cdecl MissionGeometry::Draw(float dltTime, long level)
- {
- if(!EditMode_IsVisible()) return;
- if(!model) return;
- if(fade != fd_none)
- {
- if(fadeTime <= 1e-10f)
- {
- if(level == c_fadelevel)
- {
- static const float fadeSpeed = 2.0f;
- static const float hideSpeed = 0.7f;
- switch(fade)
- {
- case fd_fadeout:
- fadeAlpha -= dltTime*fadeSpeed;
- if(fadeAlpha < 0.3f)
- {
- fadeAlpha = 0.3f;
- fade = fd_none;
- }
- break;
- case fd_fadein:
- fadeAlpha += dltTime*fadeSpeed;
- if(fadeAlpha > 1.0f)
- {
- fadeAlpha = 1.0f;
- fade = fd_none;
- if(!isCheckLod)
- {
- alpha = 1.0f;
- Show(false);
- Show(true);
- }else{
- if(!isPrevLodAlpha)
- {
- alpha = 1.0f;
- Show(false);
- Show(true);
- }
- }
- }
- break;
- case fd_hide:
- fadeAlpha -= dltTime*hideSpeed;
- if(fadeAlpha < 0.0f)
- {
- fadeAlpha = 0.0f;
- Show(false);
- return;
- }
- break;
- }
- }else{
- Show(false);
- Show(true);
- return;
- }
- }else{
- fadeTime -= dltTime;
- }
- }
- Matrix view(false);
- if(isCheckLod)
- {
- const GMXBoundBox & gbb = model->GetLocalBound();
- Vector center = (gbb.vMin + gbb.vMax)*0.5f;
- center = GetMatrix(view)*center;
- float k = (Render().GetView().GetCamPos() - center).GetAttenuation2(lodDistanceMin2, lodDistanceK2);
- if(k < 1.0f)
- {
- alpha = k*fadeAlpha;
- if(!isPrevLodAlpha)
- {
- isPrevLodAlpha = true;
- Show(IsShow());
- }
- }else{
- alpha = fadeAlpha;
- if(isPrevLodAlpha)
- {
- isPrevLodAlpha = false;
- Show(IsShow());
- }
- }
- }else{
- alpha = fadeAlpha;
- }
- float a = color.a*alpha;
- if(a < 1e-5f)
- {
- return;
- }
- if(noSwing)
- {
- view = Render().GetView();
- Render().SetView((Mission().GetInverseSwingMatrix()*Matrix(view).Inverse()).Inverse());
- }
- model->SetUserColor(Color(color.r, color.g, color.b, a));
- Matrix drawMtx;
- BuildViewMatrix(drawMtx);
- if(bUseRootBone)
- {
- Matrix mtx;
- GetMatrix(mtx);
- if(events)
- {
- events->Update(mtx, dltTime);
- }
- model->SetTransform(drawMtx);
- FogParamsSave();
- model->Draw();
- FogParamsRestore();
- }else{
- if(events)
- {
- events->Update(drawMtx, dltTime);
- }
- if (bUseDistanceHack)
- {
- Matrix mModelMatrix;
- CalculateGluedMatrix(drawMtx, mModelMatrix);
- model->SetTransform(mModelMatrix);
- } else
- {
- model->SetTransform(drawMtx);
- }
-
- FogParamsSave();
- model->Draw();
- FogParamsRestore();
- }
- if(noSwing)
- {
- Render().SetView(view);
- }
- };
- //Нарисовать прозрачную модельку
- void _cdecl MissionGeometry::DrawTransparency(float dltTime, long level)
- {
- if(!EditMode_IsVisible()) return;
- if(!Mission().EditMode_IsAdditionalDraw()) return;
- if(model)
- {
- Matrix drawMtx;
- BuildViewMatrix(drawMtx);
- if (bUseDistanceHack)
- {
- const Matrix & mProj = Render().GetProjection();
- const GMXBoundBox & bbox = model->GetLocalBound();
- const GMXBoundSphere& bsphere = model->GetLocalBoundSphere();
- Vector vCamPos = Render().GetView().GetCamPos();
- Matrix mModelMatrix;
- CalculateGluedMatrix(drawMtx, mModelMatrix);
- model->SetTransform(mModelMatrix);
- } else
- {
- model->SetTransform(drawMtx);
- }
- if(bUseRootBone && events)
- {
- Matrix mtx;
- GetMatrix(mtx);
- events->Update(mtx, dltTime);
- }
- model->SetUserColor(Color(color.r, color.g, color.b, color.a*0.1f));
- Matrix view(false);
- if(noSwing)
- {
- view = Render().GetView();
- Render().SetView((Mission().GetInverseSwingMatrix()*Matrix(view).Inverse()).Inverse());
- }
- FogParamsSave();
- model->Draw();
- FogParamsRestore();
- if(noSwing)
- {
- Render().SetView(view);
- }
- model->SetUserColor(color);
- }
- };
- //Нарисовать модельку для тени
- void _cdecl MissionGeometry::ShadowInfo(const char * group, MissionObject * sender)
- {
- if(!EditMode_IsVisible() || !IsShow()) return;
- if(shadow)
- {
- Matrix drawMtx;
- BuildViewMatrix(drawMtx);
- shadow->SetTransform(drawMtx);
- const Vector & vMin = shadow->GetBound().vMin;
- const Vector & vMax = shadow->GetBound().vMax;
- ((MissionShadowCaster *)sender)->AddObject(this, &MissionGeometry::ShadowCast, vMin, vMax);
- }else{
- if(model)
- {
- Matrix drawMtx;
- BuildViewMatrix(drawMtx);
- model->SetTransform(drawMtx);
- const Vector & vMin = model->GetBound().vMin;
- const Vector & vMax = model->GetBound().vMax;
- ((MissionShadowCaster *)sender)->AddObject(this, &MissionGeometry::ShadowCast, vMin, vMax);
- }
- }
- }
- //Нарисовать модельку для тени
- void _cdecl MissionGeometry::ShadowCast(const char * group, MissionObject * sender)
- {
- if(shadow)
- {
- Matrix drawMtx;
- BuildViewMatrix(drawMtx);
- shadow->SetTransform(drawMtx);
- shadow->Draw();
- }else{
- if(model)
- {
- Matrix drawMtx;
- BuildViewMatrix(drawMtx);
- model->SetTransform(drawMtx);
- model->Draw();
- }
- }
- }
- //Нарисовать модельку для тени
- void _cdecl MissionGeometry::ShadowRecive(const char * group, MissionObject * sender)
- {
- if(!EditMode_IsVisible() || !IsShow()) return;
- if(model)
- {
- Matrix drawMtx;
- BuildViewMatrix(drawMtx);
- model->SetTransform(drawMtx);
- model->Draw();
- }
- }
- void _cdecl MissionGeometry::SeaReflection(const char * group, MissionObject * sender)
- {
- if(!EditMode_IsVisible() || !IsShow()) return;
- if(model)
- {
- Matrix view(false);
- if(noSwing)
- {
- view = Render().GetView();
- Render().SetView((Mission().GetInverseSwingMatrix()*Matrix(view).Inverse()).Inverse());
- }
- Matrix drawMtx;
- BuildViewMatrix(drawMtx);
- if (bUseDistanceHack)
- {
- const Matrix & mProj = Render().GetProjection();
- const GMXBoundBox & bbox = model->GetLocalBound();
- const GMXBoundSphere& bsphere = model->GetLocalBoundSphere();
- Vector vCamPos = Render().GetView().GetCamPos();
- Matrix mModelMatrix;
- CalculateGluedMatrix(drawMtx, mModelMatrix);
- model->SetTransform(mModelMatrix);
- } else
- {
- model->SetTransform(drawMtx);
- }
-
- FogParamsSave();
- model->Draw();
- FogParamsRestore();
- if(noSwing)
- {
- Render().SetView(view);
- }
- }
- }
- void _cdecl MissionGeometry::SeaRefraction(const char * group, MissionObject * sender)
- {
- if(!EditMode_IsVisible() || !IsShow()) return;
- if(model)
- {
- Matrix view(false);
- if(noSwing)
- {
- view = Render().GetView();
- Render().SetView((Mission().GetInverseSwingMatrix()*Matrix(view).Inverse()).Inverse());
- }
- Matrix drawMtx;
- BuildViewMatrix(drawMtx);
- if (bUseDistanceHack)
- {
- const Matrix & mProj = Render().GetProjection();
- const GMXBoundBox & bbox = model->GetLocalBound();
- const GMXBoundSphere& bsphere = model->GetLocalBoundSphere();
- Vector vCamPos = Render().GetView().GetCamPos();
- Matrix mModelMatrix;
- CalculateGluedMatrix(drawMtx, mModelMatrix);
- model->SetTransform(mModelMatrix);
- } else
- {
- model->SetTransform(drawMtx);
- }
-
- FogParamsSave();
- model->Draw();
- FogParamsRestore();
- if(noSwing)
- {
- Render().SetView(view);
- }
- }
- }
- //Сгенерировать матрицу отрисовки
- inline void MissionGeometry::BuildViewMatrix(Matrix & m)
- {
- if(!connectToPtr.Validate())
- {
- m = modelMatrix;
- }else{
- m = modelMatrix*connectToPtr.Ptr()->GetMatrix(Matrix());
- }
- }
- //Загрузить модельку
- bool MissionGeometry::LoadModel(IGMXScene * & m, const ConstString & fileName)
- {
- //Создаём новую модельку
- IGMXScene * mdl = Geometry().CreateGMX(fileName.c_str(), &Animation(), &Particles(), &Sound());
- //Удаляем модельку
- if(m) m->Release();
- m = mdl;
- return (m != null);
- };
- //Удалить модельку
- void MissionGeometry::UnloadModel()
- {
- if(model) model->Release();
- model = null;
- if(shadow) shadow->Release();
- shadow = null;
- };
- //Остановить - продолжить проигрывание анимации
- void MissionGeometry::PauseAnimation(bool isPause)
- {
- if(!model) return;
- IAnimation * ani = model->GetAnimation();
- if(ani)
- {
- ani->Pause(isPause);
- ani->Release();
- }
- }
- //Получить сцену
- IGMXScene * MissionGeometry::GetScene()
- {
- return model;
- }
- void MissionGeometry::CalculateGluedMatrix(const Matrix & matrixIn, Matrix & matrixOut)
- {
- float fGlueDistance = GLUE_DISTANCE;
- const Matrix & mProjection = Render().GetProjection();
- const GMXBoundBox & boundBox = model->GetLocalBound();
- const GMXBoundSphere& localBoundSphere = model->GetLocalBoundSphere();
- Vector vCamPos = Render().GetView().GetCamPos();
- Vector vCenter = matrixIn * localBoundSphere.vCenter;
- Vector vDir = vCenter - vCamPos;
- float fDist = vDir.GetLength();
- vDir.y = 0.0f;
- vDir.Normalize();
- float fDistToCompleteVisible = (fGlueDistance-localBoundSphere.fRadius);
- if(fDist < fDistToCompleteVisible)
- {
- matrixOut = matrixIn;
- return;
- }
- Vector4 down = Vector4 (0.0f, boundBox.vMin.y, fDist, 1.0f);
- Vector4 up = Vector4 (0.0f, boundBox.vMax.y, fDist, 1.0f);
- Vector4 down_proj = mProjection.MulVertex(down);
- Vector4 up_proj = mProjection.MulVertex(up);
- down_proj.y = down_proj.y / down_proj.w;
- up_proj.y = up_proj.y / up_proj.w;
- float sizeMustBe = up_proj.y - down_proj.y;
- //ставим нужную дистанцию
- fDist = fDistToCompleteVisible;
- down = Vector4 (0.0f, boundBox.vMin.y, fDist, 1.0f);
- up = Vector4 (0.0f, boundBox.vMax.y, fDist, 1.0f);
- down_proj = mProjection.MulVertex(down);
- up_proj = mProjection.MulVertex(up);
- down_proj.y = down_proj.y / down_proj.w;
- up_proj.y = up_proj.y / up_proj.w;
- float sizeCurrent = up_proj.y - down_proj.y;
- float fScaleK = 0.00000000001f;
- if (sizeCurrent > 0.00001f)
- {
- fScaleK = Clampf (sizeMustBe / sizeCurrent);
- }
- Vector vNewCenter = vCamPos + (vDir * fDistToCompleteVisible);
- vNewCenter.y = vCenter.y;
- // pRS->DrawSphere(vNewCenter, 100.0f, 0xFFFF0000);
- Vector vDeltaCenter = vCenter - vNewCenter;
- Matrix matTransform = matrixIn;
- matTransform.pos -= vDeltaCenter;
- //Надо матрицу которая центрирует по боксу, скейлит и потом обратно сдвигает...
- Matrix mScale;
- mScale.BuildScale(fScaleK, fScaleK, fScaleK);
- Matrix mWorldToBound;
- mWorldToBound.pos = -localBoundSphere.vCenter;
- Matrix mBoundToWorld;
- mBoundToWorld = mWorldToBound;
- mBoundToWorld.Inverse();
- Matrix mScaleAroundPivot = (mWorldToBound * mScale) * mBoundToWorld;
- matrixOut = mScaleAroundPivot * matTransform;
- //т.к. скейлим относительно центра а не относительно нижней плоскости bound Box пододвигаем...
- matrixOut.pos.y = (matrixIn.pos.y * fScaleK);
- }
- inline void MissionGeometry::FogParamsSave()
- {
- if(bNotUseFog == false) return;
- Render().getFogParams(h_density, h_min, h_max, d_density, d_min, d_max, fog_color);
- Render().setFogParams(0.0f, h_min, h_max, 0.0f, d_min, d_max, fog_color);
- }
- inline void MissionGeometry::FogParamsRestore()
- {
- if (bNotUseFog == false) return;
- Render().setFogParams(h_density, h_min, h_max, d_density, d_min, d_max, fog_color);
- }
- //============================================================================================
- //Параметры инициализации
- //============================================================================================
- const char * MissionGeometry::comment =
- "Commands list:\n"
- "----------------------------------------\n"
- " Teleport geometry to position of some\n"
- " mission object\n"
- "----------------------------------------\n"
- " command: teleport\n"
- " parm: name of mission object\n"
- " \n"
- "----------------------------------------\n"
- " Start of any animation node\n"
- "----------------------------------------\n"
- " command: startnode\n"
- " parm: name of animation node\n"
- " [parm: blend time in seconds]\n"
- " * if no blend time, then start node without blend\n"
- " \n"
- "----------------------------------------\n"
- " Move to animation link from\n"
- " current node\n"
- "----------------------------------------\n"
- " command: actlink\n"
- " parm: name of animation link\n"
- " \n"
- "----------------------------------------\n"
- " Fade out model to transparence draw\n"
- "----------------------------------------\n"
- " command: fadeout\n"
- " \n"
- "----------------------------------------\n"
- " Fade in model to solid draw\n"
- "----------------------------------------\n"
- " command: fadein\n"
- " \n"
- "----------------------------------------\n"
- " Fade out model and hide after\n"
- "----------------------------------------\n"
- " command: fade\n"
- " [parm: waiting time before fade]\n"
- " \n"
- "----------------------------------------\n"
- " Change shadow states\n"
- "----------------------------------------\n"
- " command: shadow_cast\n"
- " parm: 0 = disable or 1 = enable\n"
- " \n"
- " command: shadow_receive\n"
- " parm: 0 = disable or 1 = enable\n"
- " \n"
- "----------------------------------------\n"
- " Collapse bone\n"
- "----------------------------------------\n"
- " command: collapse\n"
- " parm: bone name or postfix bone name\n"
- " [parm: true or false] default is true\n"
- " \n"
- "----------------------------------------\n"
- " Reset uncliiapse all bones,\n"
- " restart animation\n"
- "----------------------------------------\n"
- " command: reset\n"
- " \n"
- "----------------------------------------\n"
- " Pause animation\n"
- "----------------------------------------\n"
- " command: pause\n"
- " \n"
- "----------------------------------------\n"
- " UnPause animation\n"
- "----------------------------------------\n"
- " command: unpause\n"
- " \n"
- " ";
- MOP_BEGINLISTCG(MissionGeometry, "Geometry", '1.00', 0, MissionGeometry::comment, "Geometry")
- MOP_ENUMBEG("PhysGroup")
- for(dword i = 0; i < ARRSIZE(MissionGeometry::pgroups); i++)
- {
- MOP_ENUMELEMENT(MissionGeometry::pgroups[i].name.c_str())
- }
- MOP_ENUMEND
- MOP_STRINGC("Name", "", "Name of model file (.gmx)")
- MOP_STRINGC("Shadow", "", "Name of model file (.gmx) for shadow cast")
- MOP_STRINGC("Animation", "", "Name of animation file (.anx) for replace current animation")
- MOP_POSITIONC("Position", Vector(0.0f), "Model position in world")
- MOP_ANGLESC("Angles", Vector(0.0f), "Model orientation in world")
- MOP_STRINGC("Connect to", "", "Connect geometry to object (not for collision)")
- MOP_BOOLC("Make connection", false, "Make connection to object into Edit Mode")
- MOP_BOOLC("Use root bone", false, "Addition root bone transformation for current. (detector's and other using)")
- MOP_BOOLC("Show", true, "Show or hide geometry in start mission time")
- MOP_BOOLC("Active (collision)", false, "Wiht active geometry can collision some objects")
- MOP_ENUM("PhysGroup", "Collision groups")
- MOP_GROUPBEG("Render params")
- MOP_BOOLC("Disable fog", false, "Fog don't affect to this geometry")
- MOP_LONGEXC("Level", 0, 0, 100, "Order of geometry draw")
- MOP_COLOR("Color", Color(0.0f, 0.0f, 0.0f, 1.0f))
- MOP_BOOLC("Smooth alpha", false, "Disable alpha test (Make smooth alpha)")
- MOP_BOOLC("Render", true, "Enable primary render")
- MOP_BOOLC("Transparency", false, "Geometry draw as transparency (i.e. light rays)")
- MOP_BOOL("Dynamic lighting", false)
- MOP_BOOLC("Shadow cast", false, "Geometry can is shadow cast by some objects")
- MOP_BOOLC("Shadow receive", false, "Geometry can is shadow receive from casting objects")
- MOP_BOOLC("Sea reflection", false, "Geometry can reflect in sea")
- MOP_BOOLC("Sea refraction", false, "Geometry can refract in sea")
- MOP_BOOLC("Hide in editor", true, "Hide invisible geometry in editor")
- MOP_BOOLC("No swing", false, "No swing geometry in swing machine")
- MOP_FLOATC("Hide distance", -1.0f, "If distance less 0, then ignore this feature")
- MOP_FLOATEXC("Fade distance", 5.0f, 0.001f, 1000.0f, "When distance for camera great then Hide + Fade, geometry is hidden")
- MOP_BOOLC("Distance hack", false, "Use distance hack to far-far-far-far-far objects")
- MOP_GROUPEND()
-
- MOP_ENDLIST(MissionGeometry)
|