| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465 |
- //===========================================================================================================================
- // Spirenkov Maxim, 2003
- //===========================================================================================================================//
- //
- //===========================================================================================================================
- // PathTracks
- //============================================================================================
-
- #include "PathTracks.h"
- //#include "..\..\..\AnimationService\anxeditor\ant.h"
- PathTracks::PathTracks(): points(_FL_)
- {
- points.Empty();
- Offset = 0.0f;
- }
- PathTracks::~PathTracks()
- {
- ClearTrack();
- }
- /*
- //Загрузить трек в PathTracks
- bool PathTracks::LoadCTF(const char * fileName)
- {
- ClearTrack();
- //Загружаем файл в память
- void * data = null;
- dword size = 0;
- IFileService * fileServ = (IFileService *)api->GetService("FileService");
-
- if(!fileServ)
- {
- api->Trace("FileService not created!");
- return false;
- }
-
- data = fileServ->Load(fileName, &size);
- if(!data)
- {
- api->Trace("Camera tracks file %s not loaded...", fileName);
- return false;
- }
-
- //Проверяем заголовок
- long nPoints = ((CameraTracksHeader *)data)->numPoints;
-
- if(((CameraTracksHeader *)data)->id != CameraTracksID || nPoints == 0)
- {
- api->Trace("Camera tracks file %s is invalidate...", fileName);
- delete data;
- return false;
- }
-
- if(((CameraTracksHeader *)data)->ver != CameraTracksVer)
- {
- api->Trace("Camera tracks file %s have incorrect version...", fileName);
- delete data;
- return false;
- }
-
- //Проверяем размеры файла
- if(size < sizeof(CameraTracksHeader) + nPoints*sizeof(CameraTracksPoint))
- {
- api->Trace("Camera tracks file %s is invalidate...", fileName);
- delete data;
- return false;
- }
-
- CameraTracksPoint* TracksPoints = (CameraTracksPoint*)((byte *)data + sizeof(CameraTracksHeader));
-
- for(long i = 0; i < nPoints; i++)
- {
- TPoint pt;
-
- pt.p1.x=TracksPoints[i].p1x;
- pt.p1.y=TracksPoints[i].p1y;
- pt.p1.z=TracksPoints[i].p1z;
- pt.p2.x=TracksPoints[i].p2x;
- pt.p2.y=TracksPoints[i].p2y;
- pt.p2.z=TracksPoints[i].p2z;
- pt.p.x=TracksPoints[i].px;
- pt.p.y=TracksPoints[i].py;
- pt.p.z=TracksPoints[i].pz;
- pt.q.x=TracksPoints[i].qx;
- pt.q.y=TracksPoints[i].qy;
- pt.q.z=TracksPoints[i].qz;
- pt.q.w=TracksPoints[i].qw;
- AddPoint(pt);
- }
- delete data;
- return true;
- }*/
- /*
- //Загрузить трек в PathTracks
- bool PathTracks::LoadANT(IFileService * fs, const char * fileName)
- {
- ClearTrack();
- Assert(fs);
- ILoadBuffer * loadBuffer = fs->LoadData(fileName, _FL_);
- if (!loadBuffer)
- {
- api->Trace("Camera tracks file %s not loaded...", fileName);
- return false;
- }
- AntFileHeader* pHeader;
- pHeader = (AntFileHeader*)loadBuffer->Buffer();
- XSwizzleULong(pHeader->id);
- XSwizzleULong(pHeader->ver);
- XSwizzleULong(pHeader->bonesCount);
- XSwizzleULong(pHeader->framesCount);
- XSwizzleULong(pHeader->stringsTableSize);
- XSwizzleFloat(pHeader->defaultFPS);
- //Проверяем заголовок
- if (pHeader->id != ANTFILE_ID || pHeader->bonesCount == 0 ||
- pHeader->framesCount == 0)
- {
- api->Trace("Camera tracks file %s is invalidate...", fileName);
- loadBuffer->Release();
- return false;
- }
- if (pHeader->ver != ANTFILE_VER)
- {
- api->Trace("Camera tracks file %s have incorrect version...", fileName);
- loadBuffer->Release();
- return false;
- }
- AntFileBone * pBoneTable = (AntFileBone*)((byte*)loadBuffer->Buffer() + sizeof(AntFileHeader) + pHeader->stringsTableSize);
- AntFileTrackElement * pFramesTable = (AntFileTrackElement*) ((byte*)loadBuffer->Buffer() + sizeof(AntFileHeader) +
- pHeader->stringsTableSize + pHeader->bonesCount*sizeof(AntFileBone));
- int iBoneCharacter1Index=-1;
- int iBoneCharacter2Index=-1;
- int iBoneCameraIndex=-1;
- int iBoneCameraIndex2=-1;
- string str;
- for (unsigned int i=0;i<pHeader->bonesCount;i++)
- {
- byte* pNamePointer = (byte*)loadBuffer->Buffer() + sizeof(AntFileHeader) + SwizzleDWord(pBoneTable[i].nameIndex);
- char* BoneName = (char*)pNamePointer;
- if (str.EqualPostfix(BoneName,"character1"))
- {
- iBoneCharacter1Index = i;
- }
- else
- if (str.EqualPostfix(BoneName,"character2"))
- {
- iBoneCharacter2Index = i;
- }
- else
- if (str.EqualPostfix(BoneName,"camera"))
- {
- iBoneCameraIndex = i;
- }
- else
- if (str.EqualPostfix(BoneName,"camera1"))
- {
- iBoneCameraIndex2 = i;
- }
- }
- if (iBoneCharacter1Index == -1)
- {
- api->Trace("Can't find Character1 Bone", fileName);
- loadBuffer->Release();
- return false;
- }
- if (iBoneCharacter2Index == -1)
- {
- api->Trace("Can't find Character2 Bone", fileName);
- loadBuffer->Release();
- return false;
- }
- if (iBoneCameraIndex == -1)
- {
- api->Trace("Can't find Camera Bone", fileName);
- loadBuffer->Release();
- return false;
- }
- for (unsigned int i=0;i<pHeader->framesCount;i++)
- {
- TPoint pt;
- AntFileTrackElement & el1 = pFramesTable[i+iBoneCharacter1Index*pHeader->framesCount];
- pt.p1.x=SwizzleFloat(el1.px);
- pt.p1.y=SwizzleFloat(el1.py);
- pt.p1.z=SwizzleFloat(el1.pz);
- AntFileTrackElement & el2 = pFramesTable[i+iBoneCharacter2Index*pHeader->framesCount];
- pt.p2.x=SwizzleFloat(el2.px);
- pt.p2.y=SwizzleFloat(el2.py);
- pt.p2.z=SwizzleFloat(el2.pz);
- AntFileTrackElement & el = pFramesTable[i+iBoneCameraIndex*pHeader->framesCount];
- pt.pt1.x=SwizzleFloat(el.px);
- pt.pt1.y=SwizzleFloat(el.py);
- pt.pt1.z=SwizzleFloat(el.pz);
- pt.q.x=SwizzleFloat(el.qx);
- pt.q.y=SwizzleFloat(el.qy);
- pt.q.z=SwizzleFloat(el.qz);
- pt.q.w=SwizzleFloat(el.qw);
- if (iBoneCameraIndex2!=-1)
- {
- AntFileTrackElement & el3 = pFramesTable[i+iBoneCameraIndex2*pHeader->framesCount];
- pt.pt2.x=SwizzleFloat(el3.px);
- pt.pt2.y=SwizzleFloat(el3.py);
- pt.pt2.z=SwizzleFloat(el3.pz);
- pt.q2.x=SwizzleFloat(el.qx);
- pt.q2.y=SwizzleFloat(el.qy);
- pt.q2.z=SwizzleFloat(el.qz);
- pt.q2.w=SwizzleFloat(el.qw);
- }
- else
- {
- pt.pt2.x=pt.pt1.x;
- pt.pt2.y=pt.pt1.y;
- pt.pt2.z=pt.pt1.z;
- pt.q2.x=pt.q.x;
- pt.q2.y=pt.q.y;
- pt.q2.z=pt.q.z;
- pt.q2.w=pt.q.w;
- }
- AddPoint(pt);
- }
- loadBuffer->Release();
- return true;
- }
- */
- //Нарисовать трек
- void PathTracks::Draw(IRender & render)
- {
- if (points.Size()==0) return;
- render.FlushBufferedLines();
-
- for(dword i = 0; i < points.Size() - 1; i++)
- {
- render.DrawBufferedLine(points[i].p1 + Offset, 0xff00ff00, points[i + 1].p1 + Offset, 0xff00ff00, false);
- render.DrawBufferedLine(points[i].p2 + Offset, 0xff00ff00, points[i + 1].p2 + Offset, 0xff00ff00, false);
- render.DrawBufferedLine(points[i].p1 + Offset, 0xff00ffff, points[ i ].p2 + Offset, 0xff00ffff, false);
- render.DrawBufferedLine(points[i].pt1 + Offset, 0xffff0000, points[i + 1].pt1 + Offset, 0xffff0000, false);
- render.DrawBufferedLine(points[i].pt2 + Offset, 0xffff0000, points[i + 1].pt2 + Offset, 0xffff0000, false);
- render.DrawBufferedLine(points[i].pt1 + Offset, 0xffffff00, points[ i ].pt2 + Offset, 0xffffff00, false);
- render.DrawBufferedLine(points[i].p1 + Offset, 0xffffffff, points[i].pt1 + Offset, 0xffffffff, false);
- render.DrawBufferedLine(points[i].p2 + Offset, 0xffffffff, points[i].pt2 + Offset, 0xffffffff, false);
- }
- render.DrawBufferedLine(points[points.Size() - 1].p1 + Offset, 0xff00ffff, points[points.Size() - 1].p2 + Offset, 0xff00ffff, false);
-
- render.DrawBufferedLine(points[points.Size() - 1].pt1 + Offset, 0xffffff00, points[points.Size() - 1].pt2 + Offset, 0xffffff00, false);
- render.FlushBufferedLines();
- }
- //Найти новую позицию для камеры
- bool PathTracks::Find(const Vector & p, long & index, Vector & cp, Quaternion & cq)
- {
- if(index >= 0)
- {
- //Ищем от текущей позиции
- if(index >= (long)points.Size() - 1) index = points.Size() - 1;
-
- for(dword i = 0; i < points.Size() - 1; i++)
- {
- long i1 = index + i;
- long i2 = index - i;
- if(i1 < (long)points.Size() - 1)
- {
- float k = Test(p, i1);
- if(k >= 0.0f && k < 1.0f)
- {
- index = i1;
- GetLerpCamPos(i1, i1 + 1, p, cp, cq, k);
- return true;
- }
- }
- if(i2 >= 0 && i1 != i2)
- {
- float k = Test(p, i2);
- if(k >= 0.0f && k < 1.0f)
- {
- index = i2;
- GetLerpCamPos(i2, i2 + 1, p, cp, cq, k);
- return true;
- }
- }
- }
- }
- else
- {
- //Ищем по всему треку наиближайший подходящий элемент
- float dist;
- Line line;
- for(long i = 0, idx = -1; i < (long)points.Size() - 1; i++)
- {
- float k = Test(p, i);
- if(k >= 0.0f)
- {
- line.p1 = (points[i].p1 + Offset).GetXZ();
- line.p2 = (points[i].p2 + Offset).GetXZ();
- float d = line.DistanceToLine(p);
- if(idx < 0 || dist > d)
- {
- dist = d;
- idx = i;
- }
- }
- }
-
- if(idx >= 0)
- {
- index = idx;
- return Find(p, index, cp, cq);
- }
- }
- return false;
- }
- //Получить точку трека
- bool PathTracks::GetPoint(float index, Vector & cp, Quaternion & cq)
- {
- if(index < 0 || index >= points.Size()) return false;
- long i1 = long(index);
- long i2 = i1 + 1;
-
- if (i1 >= (long)points.Size()) i1 = points.Size() - 1;
- if (i2 >= (long)points.Size()) i2 = points.Size() - 1;
- Vector cp1, cp2;
- Quaternion cq1, cq2;
- cp1.Lerp(points[i1].pt1 + Offset, points[i2].pt1 + Offset, index - i1);
- cp2.Lerp(points[i1].pt2 + Offset, points[i2].pt2 + Offset, index - i1);
- cq1.SLerp(points[i1].q, points[i2].q, index - i1);
- cq2.SLerp(points[i1].q2, points[i2].q2, index - i1);
- cp.Lerp(cp1, cp2, 0.5f);
- cq.SLerp(cq1, cq2, 0.5f);
-
- return true;
- }
- //Удалить все точки
- void PathTracks::ClearTrack()
- {
- points.DelAll();
- }
- //Добавить точку в трек
- void PathTracks::AddPoint(TPoint pt)
- {
- points.Add(pt);
- }
- //Найти коэфициент для данного участка трека
- inline float PathTracks::Test(const Vector & p, long i)
- {
- Vector s1 = points[i].p1 + Offset;
- Vector e1 = points[i + 1].p1 + Offset;
- Vector s2 = points[i].p2 + Offset;
- Vector e2 = points[i + 1].p2 + Offset;
-
- float c2 = s1.z - e1.z;
- float c4 = e2.x - s2.x - e1.x + s1.x;
- float c6 = e2.z - s2.z - e1.z + s1.z;
- float c8 = s1.x - e1.x;
- float c1 = p.z - s1.z;
- float c3 = s2.x - s1.x;
- float c5 = s2.z - s1.z;
- float c7 = p.x - s1.x;
- float a = c2*c4 - c6*c8;
- float b = c1*c4 + c2*c3 - c5*c8 - c6*c7;
- float c = c1*c3 - c5*c7;
- float k;
-
- if(fabs(a) >= 0.001f)
- {
- float D = b*b - 4*a*c;
- if(D < 0.0f) return -1.0f;
- D = sqrtf(D);
- float k1 = (-b + D)/(2*a);
- float k2 = (-b - D)/(2*a);
- k = -1.0f;
- if(k1 >= 0.0f && k1 <= 1.0f) k = k1;
- if(k2 >= 0.0f && k2 <= 1.0f) k = k2;
- }
- else
- {
- if(fabs(b) < 0.001f) return -1.0f;
- k = -c/b;
- }
- //Проверим попадание в трек
- if(k < 0.0f) return -1.0f;
-
- Vector p1, p2;
- p1.Lerp(s1, e1, k);
- p2.Lerp(s2, e2, k);
- Vector t = p2 - p1;
-
- if(((p - p1) | t) < 0.0f) return -1.0f;
- if(((p2 - p) | t) < 0.0f) return -1.0f;
-
- return k;
- }
- //Получить интерполированую позицию камеры
- inline void PathTracks::GetLerpCamPos(long i1, long i2, const Vector & p, Vector & cp, Quaternion & cq, float k)
- {
- Vector cp1, cp2;
- Quaternion cq1, cq2;
- //Найдём коэфициент
- cp1.Lerp(points[i1].p1 + Offset, points[i2].p1 + Offset, k);
- cp2.Lerp(points[i1].p2 + Offset, points[i2].p2 + Offset, k);
- float t = (p - cp1).GetLength()/(cp2 - cp1).GetLength();
- t = Clampf(t);
- //Проинтерполируем камеру по 2м осям
- cp1.Lerp(points[i1].pt1 + Offset, points[i2].pt1 + Offset, k);
- cp2.Lerp(points[i1].pt2 + Offset, points[i2].pt2 + Offset, k);
- cq1.SLerp(points[i1].q, points[i2].q, k);
- cq2.SLerp(points[i1].q2, points[i2].q2, k);
- cp.Lerp(cp1, cp2, t);
- cq.SLerp(cq1, cq2, t);
- }
|