PathTracks.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  1. //===========================================================================================================================
  2. // Spirenkov Maxim, 2003
  3. //===========================================================================================================================//
  4. //
  5. //===========================================================================================================================
  6. // PathTracks
  7. //============================================================================================
  8. #include "PathTracks.h"
  9. //#include "..\..\..\AnimationService\anxeditor\ant.h"
  10. PathTracks::PathTracks(): points(_FL_)
  11. {
  12. points.Empty();
  13. Offset = 0.0f;
  14. }
  15. PathTracks::~PathTracks()
  16. {
  17. ClearTrack();
  18. }
  19. /*
  20. //Загрузить трек в PathTracks
  21. bool PathTracks::LoadCTF(const char * fileName)
  22. {
  23. ClearTrack();
  24. //Загружаем файл в память
  25. void * data = null;
  26. dword size = 0;
  27. IFileService * fileServ = (IFileService *)api->GetService("FileService");
  28. if(!fileServ)
  29. {
  30. api->Trace("FileService not created!");
  31. return false;
  32. }
  33. data = fileServ->Load(fileName, &size);
  34. if(!data)
  35. {
  36. api->Trace("Camera tracks file %s not loaded...", fileName);
  37. return false;
  38. }
  39. //Проверяем заголовок
  40. long nPoints = ((CameraTracksHeader *)data)->numPoints;
  41. if(((CameraTracksHeader *)data)->id != CameraTracksID || nPoints == 0)
  42. {
  43. api->Trace("Camera tracks file %s is invalidate...", fileName);
  44. delete data;
  45. return false;
  46. }
  47. if(((CameraTracksHeader *)data)->ver != CameraTracksVer)
  48. {
  49. api->Trace("Camera tracks file %s have incorrect version...", fileName);
  50. delete data;
  51. return false;
  52. }
  53. //Проверяем размеры файла
  54. if(size < sizeof(CameraTracksHeader) + nPoints*sizeof(CameraTracksPoint))
  55. {
  56. api->Trace("Camera tracks file %s is invalidate...", fileName);
  57. delete data;
  58. return false;
  59. }
  60. CameraTracksPoint* TracksPoints = (CameraTracksPoint*)((byte *)data + sizeof(CameraTracksHeader));
  61. for(long i = 0; i < nPoints; i++)
  62. {
  63. TPoint pt;
  64. pt.p1.x=TracksPoints[i].p1x;
  65. pt.p1.y=TracksPoints[i].p1y;
  66. pt.p1.z=TracksPoints[i].p1z;
  67. pt.p2.x=TracksPoints[i].p2x;
  68. pt.p2.y=TracksPoints[i].p2y;
  69. pt.p2.z=TracksPoints[i].p2z;
  70. pt.p.x=TracksPoints[i].px;
  71. pt.p.y=TracksPoints[i].py;
  72. pt.p.z=TracksPoints[i].pz;
  73. pt.q.x=TracksPoints[i].qx;
  74. pt.q.y=TracksPoints[i].qy;
  75. pt.q.z=TracksPoints[i].qz;
  76. pt.q.w=TracksPoints[i].qw;
  77. AddPoint(pt);
  78. }
  79. delete data;
  80. return true;
  81. }*/
  82. /*
  83. //Загрузить трек в PathTracks
  84. bool PathTracks::LoadANT(IFileService * fs, const char * fileName)
  85. {
  86. ClearTrack();
  87. Assert(fs);
  88. ILoadBuffer * loadBuffer = fs->LoadData(fileName, _FL_);
  89. if (!loadBuffer)
  90. {
  91. api->Trace("Camera tracks file %s not loaded...", fileName);
  92. return false;
  93. }
  94. AntFileHeader* pHeader;
  95. pHeader = (AntFileHeader*)loadBuffer->Buffer();
  96. XSwizzleULong(pHeader->id);
  97. XSwizzleULong(pHeader->ver);
  98. XSwizzleULong(pHeader->bonesCount);
  99. XSwizzleULong(pHeader->framesCount);
  100. XSwizzleULong(pHeader->stringsTableSize);
  101. XSwizzleFloat(pHeader->defaultFPS);
  102. //Проверяем заголовок
  103. if (pHeader->id != ANTFILE_ID || pHeader->bonesCount == 0 ||
  104. pHeader->framesCount == 0)
  105. {
  106. api->Trace("Camera tracks file %s is invalidate...", fileName);
  107. loadBuffer->Release();
  108. return false;
  109. }
  110. if (pHeader->ver != ANTFILE_VER)
  111. {
  112. api->Trace("Camera tracks file %s have incorrect version...", fileName);
  113. loadBuffer->Release();
  114. return false;
  115. }
  116. AntFileBone * pBoneTable = (AntFileBone*)((byte*)loadBuffer->Buffer() + sizeof(AntFileHeader) + pHeader->stringsTableSize);
  117. AntFileTrackElement * pFramesTable = (AntFileTrackElement*) ((byte*)loadBuffer->Buffer() + sizeof(AntFileHeader) +
  118. pHeader->stringsTableSize + pHeader->bonesCount*sizeof(AntFileBone));
  119. int iBoneCharacter1Index=-1;
  120. int iBoneCharacter2Index=-1;
  121. int iBoneCameraIndex=-1;
  122. int iBoneCameraIndex2=-1;
  123. string str;
  124. for (unsigned int i=0;i<pHeader->bonesCount;i++)
  125. {
  126. byte* pNamePointer = (byte*)loadBuffer->Buffer() + sizeof(AntFileHeader) + SwizzleDWord(pBoneTable[i].nameIndex);
  127. char* BoneName = (char*)pNamePointer;
  128. if (str.EqualPostfix(BoneName,"character1"))
  129. {
  130. iBoneCharacter1Index = i;
  131. }
  132. else
  133. if (str.EqualPostfix(BoneName,"character2"))
  134. {
  135. iBoneCharacter2Index = i;
  136. }
  137. else
  138. if (str.EqualPostfix(BoneName,"camera"))
  139. {
  140. iBoneCameraIndex = i;
  141. }
  142. else
  143. if (str.EqualPostfix(BoneName,"camera1"))
  144. {
  145. iBoneCameraIndex2 = i;
  146. }
  147. }
  148. if (iBoneCharacter1Index == -1)
  149. {
  150. api->Trace("Can't find Character1 Bone", fileName);
  151. loadBuffer->Release();
  152. return false;
  153. }
  154. if (iBoneCharacter2Index == -1)
  155. {
  156. api->Trace("Can't find Character2 Bone", fileName);
  157. loadBuffer->Release();
  158. return false;
  159. }
  160. if (iBoneCameraIndex == -1)
  161. {
  162. api->Trace("Can't find Camera Bone", fileName);
  163. loadBuffer->Release();
  164. return false;
  165. }
  166. for (unsigned int i=0;i<pHeader->framesCount;i++)
  167. {
  168. TPoint pt;
  169. AntFileTrackElement & el1 = pFramesTable[i+iBoneCharacter1Index*pHeader->framesCount];
  170. pt.p1.x=SwizzleFloat(el1.px);
  171. pt.p1.y=SwizzleFloat(el1.py);
  172. pt.p1.z=SwizzleFloat(el1.pz);
  173. AntFileTrackElement & el2 = pFramesTable[i+iBoneCharacter2Index*pHeader->framesCount];
  174. pt.p2.x=SwizzleFloat(el2.px);
  175. pt.p2.y=SwizzleFloat(el2.py);
  176. pt.p2.z=SwizzleFloat(el2.pz);
  177. AntFileTrackElement & el = pFramesTable[i+iBoneCameraIndex*pHeader->framesCount];
  178. pt.pt1.x=SwizzleFloat(el.px);
  179. pt.pt1.y=SwizzleFloat(el.py);
  180. pt.pt1.z=SwizzleFloat(el.pz);
  181. pt.q.x=SwizzleFloat(el.qx);
  182. pt.q.y=SwizzleFloat(el.qy);
  183. pt.q.z=SwizzleFloat(el.qz);
  184. pt.q.w=SwizzleFloat(el.qw);
  185. if (iBoneCameraIndex2!=-1)
  186. {
  187. AntFileTrackElement & el3 = pFramesTable[i+iBoneCameraIndex2*pHeader->framesCount];
  188. pt.pt2.x=SwizzleFloat(el3.px);
  189. pt.pt2.y=SwizzleFloat(el3.py);
  190. pt.pt2.z=SwizzleFloat(el3.pz);
  191. pt.q2.x=SwizzleFloat(el.qx);
  192. pt.q2.y=SwizzleFloat(el.qy);
  193. pt.q2.z=SwizzleFloat(el.qz);
  194. pt.q2.w=SwizzleFloat(el.qw);
  195. }
  196. else
  197. {
  198. pt.pt2.x=pt.pt1.x;
  199. pt.pt2.y=pt.pt1.y;
  200. pt.pt2.z=pt.pt1.z;
  201. pt.q2.x=pt.q.x;
  202. pt.q2.y=pt.q.y;
  203. pt.q2.z=pt.q.z;
  204. pt.q2.w=pt.q.w;
  205. }
  206. AddPoint(pt);
  207. }
  208. loadBuffer->Release();
  209. return true;
  210. }
  211. */
  212. //Нарисовать трек
  213. void PathTracks::Draw(IRender & render)
  214. {
  215. if (points.Size()==0) return;
  216. render.FlushBufferedLines();
  217. for(dword i = 0; i < points.Size() - 1; i++)
  218. {
  219. render.DrawBufferedLine(points[i].p1 + Offset, 0xff00ff00, points[i + 1].p1 + Offset, 0xff00ff00, false);
  220. render.DrawBufferedLine(points[i].p2 + Offset, 0xff00ff00, points[i + 1].p2 + Offset, 0xff00ff00, false);
  221. render.DrawBufferedLine(points[i].p1 + Offset, 0xff00ffff, points[ i ].p2 + Offset, 0xff00ffff, false);
  222. render.DrawBufferedLine(points[i].pt1 + Offset, 0xffff0000, points[i + 1].pt1 + Offset, 0xffff0000, false);
  223. render.DrawBufferedLine(points[i].pt2 + Offset, 0xffff0000, points[i + 1].pt2 + Offset, 0xffff0000, false);
  224. render.DrawBufferedLine(points[i].pt1 + Offset, 0xffffff00, points[ i ].pt2 + Offset, 0xffffff00, false);
  225. render.DrawBufferedLine(points[i].p1 + Offset, 0xffffffff, points[i].pt1 + Offset, 0xffffffff, false);
  226. render.DrawBufferedLine(points[i].p2 + Offset, 0xffffffff, points[i].pt2 + Offset, 0xffffffff, false);
  227. }
  228. render.DrawBufferedLine(points[points.Size() - 1].p1 + Offset, 0xff00ffff, points[points.Size() - 1].p2 + Offset, 0xff00ffff, false);
  229. render.DrawBufferedLine(points[points.Size() - 1].pt1 + Offset, 0xffffff00, points[points.Size() - 1].pt2 + Offset, 0xffffff00, false);
  230. render.FlushBufferedLines();
  231. }
  232. //Найти новую позицию для камеры
  233. bool PathTracks::Find(const Vector & p, long & index, Vector & cp, Quaternion & cq)
  234. {
  235. if(index >= 0)
  236. {
  237. //Ищем от текущей позиции
  238. if(index >= (long)points.Size() - 1) index = points.Size() - 1;
  239. for(dword i = 0; i < points.Size() - 1; i++)
  240. {
  241. long i1 = index + i;
  242. long i2 = index - i;
  243. if(i1 < (long)points.Size() - 1)
  244. {
  245. float k = Test(p, i1);
  246. if(k >= 0.0f && k < 1.0f)
  247. {
  248. index = i1;
  249. GetLerpCamPos(i1, i1 + 1, p, cp, cq, k);
  250. return true;
  251. }
  252. }
  253. if(i2 >= 0 && i1 != i2)
  254. {
  255. float k = Test(p, i2);
  256. if(k >= 0.0f && k < 1.0f)
  257. {
  258. index = i2;
  259. GetLerpCamPos(i2, i2 + 1, p, cp, cq, k);
  260. return true;
  261. }
  262. }
  263. }
  264. }
  265. else
  266. {
  267. //Ищем по всему треку наиближайший подходящий элемент
  268. float dist;
  269. Line line;
  270. for(long i = 0, idx = -1; i < (long)points.Size() - 1; i++)
  271. {
  272. float k = Test(p, i);
  273. if(k >= 0.0f)
  274. {
  275. line.p1 = (points[i].p1 + Offset).GetXZ();
  276. line.p2 = (points[i].p2 + Offset).GetXZ();
  277. float d = line.DistanceToLine(p);
  278. if(idx < 0 || dist > d)
  279. {
  280. dist = d;
  281. idx = i;
  282. }
  283. }
  284. }
  285. if(idx >= 0)
  286. {
  287. index = idx;
  288. return Find(p, index, cp, cq);
  289. }
  290. }
  291. return false;
  292. }
  293. //Получить точку трека
  294. bool PathTracks::GetPoint(float index, Vector & cp, Quaternion & cq)
  295. {
  296. if(index < 0 || index >= points.Size()) return false;
  297. long i1 = long(index);
  298. long i2 = i1 + 1;
  299. if (i1 >= (long)points.Size()) i1 = points.Size() - 1;
  300. if (i2 >= (long)points.Size()) i2 = points.Size() - 1;
  301. Vector cp1, cp2;
  302. Quaternion cq1, cq2;
  303. cp1.Lerp(points[i1].pt1 + Offset, points[i2].pt1 + Offset, index - i1);
  304. cp2.Lerp(points[i1].pt2 + Offset, points[i2].pt2 + Offset, index - i1);
  305. cq1.SLerp(points[i1].q, points[i2].q, index - i1);
  306. cq2.SLerp(points[i1].q2, points[i2].q2, index - i1);
  307. cp.Lerp(cp1, cp2, 0.5f);
  308. cq.SLerp(cq1, cq2, 0.5f);
  309. return true;
  310. }
  311. //Удалить все точки
  312. void PathTracks::ClearTrack()
  313. {
  314. points.DelAll();
  315. }
  316. //Добавить точку в трек
  317. void PathTracks::AddPoint(TPoint pt)
  318. {
  319. points.Add(pt);
  320. }
  321. //Найти коэфициент для данного участка трека
  322. inline float PathTracks::Test(const Vector & p, long i)
  323. {
  324. Vector s1 = points[i].p1 + Offset;
  325. Vector e1 = points[i + 1].p1 + Offset;
  326. Vector s2 = points[i].p2 + Offset;
  327. Vector e2 = points[i + 1].p2 + Offset;
  328. float c2 = s1.z - e1.z;
  329. float c4 = e2.x - s2.x - e1.x + s1.x;
  330. float c6 = e2.z - s2.z - e1.z + s1.z;
  331. float c8 = s1.x - e1.x;
  332. float c1 = p.z - s1.z;
  333. float c3 = s2.x - s1.x;
  334. float c5 = s2.z - s1.z;
  335. float c7 = p.x - s1.x;
  336. float a = c2*c4 - c6*c8;
  337. float b = c1*c4 + c2*c3 - c5*c8 - c6*c7;
  338. float c = c1*c3 - c5*c7;
  339. float k;
  340. if(fabs(a) >= 0.001f)
  341. {
  342. float D = b*b - 4*a*c;
  343. if(D < 0.0f) return -1.0f;
  344. D = sqrtf(D);
  345. float k1 = (-b + D)/(2*a);
  346. float k2 = (-b - D)/(2*a);
  347. k = -1.0f;
  348. if(k1 >= 0.0f && k1 <= 1.0f) k = k1;
  349. if(k2 >= 0.0f && k2 <= 1.0f) k = k2;
  350. }
  351. else
  352. {
  353. if(fabs(b) < 0.001f) return -1.0f;
  354. k = -c/b;
  355. }
  356. //Проверим попадание в трек
  357. if(k < 0.0f) return -1.0f;
  358. Vector p1, p2;
  359. p1.Lerp(s1, e1, k);
  360. p2.Lerp(s2, e2, k);
  361. Vector t = p2 - p1;
  362. if(((p - p1) | t) < 0.0f) return -1.0f;
  363. if(((p2 - p) | t) < 0.0f) return -1.0f;
  364. return k;
  365. }
  366. //Получить интерполированую позицию камеры
  367. inline void PathTracks::GetLerpCamPos(long i1, long i2, const Vector & p, Vector & cp, Quaternion & cq, float k)
  368. {
  369. Vector cp1, cp2;
  370. Quaternion cq1, cq2;
  371. //Найдём коэфициент
  372. cp1.Lerp(points[i1].p1 + Offset, points[i2].p1 + Offset, k);
  373. cp2.Lerp(points[i1].p2 + Offset, points[i2].p2 + Offset, k);
  374. float t = (p - cp1).GetLength()/(cp2 - cp1).GetLength();
  375. t = Clampf(t);
  376. //Проинтерполируем камеру по 2м осям
  377. cp1.Lerp(points[i1].pt1 + Offset, points[i2].pt1 + Offset, k);
  378. cp2.Lerp(points[i1].pt2 + Offset, points[i2].pt2 + Offset, k);
  379. cq1.SLerp(points[i1].q, points[i2].q, k);
  380. cq2.SLerp(points[i1].q2, points[i2].q2, k);
  381. cp.Lerp(cp1, cp2, t);
  382. cq.SLerp(cq1, cq2, t);
  383. }