1 #include "pch.h"
2 #include "../ogre/common/Def_Str.h"
3 #include "../vdrift/dbl.h"
4 #include "Road.h"
5
6 #include <OgreCamera.h>
7 #include <OgreTerrain.h>
8 #include <OgreSceneNode.h>
9 using namespace Ogre;
10
11
12 // choose, selection
13 //--------------------------------------------------------------------------------------
ChoosePoint()14 void SplineEdit::ChoosePoint()
15 {
16 iChosen = iSelPoint;
17 }
CopyNewPoint()18 void SplineEdit::CopyNewPoint()
19 {
20 if (iChosen == -1) return;
21 newP = mP[iChosen];
22 }
23
24 // next
PrevPoint()25 void SplineEdit::PrevPoint()
26 {
27 if (getNumPoints() != 0)
28 iChosen = (iChosen-1 + getNumPoints()) % getNumPoints();
29 }
NextPoint()30 void SplineEdit::NextPoint()
31 {
32 if (getNumPoints() != 0)
33 iChosen = (iChosen+1) % getNumPoints();
34 }
35
FirstPoint()36 void SplineEdit::FirstPoint()
37 {
38 if (getNumPoints() != 0)
39 iChosen = 0;
40 }
LastPoint()41 void SplineEdit::LastPoint()
42 {
43 if (getNumPoints() != 0)
44 iChosen = getNumPoints()-1;
45 }
46
47
48 // mark need to rebuild geometry
Rebuild(bool full)49 void SplineEdit::Rebuild(bool full)
50 {
51 rebuild = true;
52 if (full)
53 iDirtyId = -1;
54 else
55 iDirtyId = iChosen;
56 }
57
58
59 // add/rem select
SelAddPoint()60 void SplineEdit::SelAddPoint()
61 {
62 int id = -1;
63 if (iChosen != -1) id = iChosen; else
64 if (iSelPoint != -1) id = iSelPoint;
65 if (id != -1)
66 {
67 if (vSel.find(id) == vSel.end())
68 vSel.insert(id);
69 else
70 vSel.erase(id);
71 }
72 }
SelClear()73 void SplineEdit::SelClear()
74 {
75 vSel.clear();
76 }
SelAll()77 void SplineEdit::SelAll()
78 {
79 vSel.clear();
80 for (size_t i=0; i < mP.size(); ++i)
81 vSel.insert(i);
82 }
GetSelCnt()83 int SplineEdit::GetSelCnt()
84 {
85 return vSel.size();
86 }
87
88
89
90 // Move point
91 ///-------------------------------------------------------------------------------------
Move1(int id,Vector3 relPos)92 void SplineEdit::Move1(int id, Vector3 relPos)
93 {
94 Vector3 pos = getPos(id) + relPos;
95 if (mP[id].onTer)
96 pos.y = getTerH(pos) + g_Height;
97 setPos(id, pos);
98 vMarks[id].setPos(pos); // upd marker
99 }
100
Move(Vector3 relPos)101 void SplineEdit::Move(Vector3 relPos)
102 {
103 if (!vSel.empty()) // move sel
104 { for (std::set<int>::const_iterator it = vSel.begin(); it != vSel.end(); ++it)
105 Move1(*it, relPos);
106 bSelChng = true;
107 return;
108 }
109 if (iChosen == -1) { // move one
110 newP.pos.y += relPos.y; return; }
111 else
112 { Move1(iChosen, relPos);
113 Rebuild(); }
114 }
115
116 // Scale1 (for tools)
Scale1(int id,Real posMul,Real hMul)117 void SplineEdit::Scale1(int id, Real posMul, Real hMul)
118 {
119 Vector3 pos = getPos(id);
120 if (posMul != 0.f)
121 { pos.x *= posMul; pos.z *= posMul; }
122 if (hMul != 0.f)
123 pos.y *= hMul;
124
125 if (mP[id].onTer)
126 pos.y = getTerH(pos) + g_Height;
127 setPos(id, pos);
128 vMarks[id].setPos(pos); // upd marker
129 }
130
131
132 // Update Points onTer
UpdPointsH()133 void SplineEdit::UpdPointsH()
134 {
135 for (int id=0; id < getNumPoints(); ++id)
136 {
137 Vector3 pos = getPos(id);
138 if (mP[id].onTer)
139 { pos.y = getTerH(pos) + g_Height;
140 setPos(id, pos);
141 }
142 vMarks[id].setPos(pos); // upd marker
143 }
144 }
145
getTerH(const Vector3 & p)146 Real SplineEdit::getTerH(const Vector3& p)
147 {
148 return mTerrain ? mTerrain->getHeightAtWorldPosition(p.x, 0.f, p.z) : 0.f;
149 }
150
151
152
153 /// Edit Selected
154 ///-------------------------------------------------------------------------------------
155
getPos0()156 Vector3 SplineEdit::getPos0()
157 {
158 Vector3 pos0(0,0,0);
159 if (iChosen == -1) // geom center
160 {
161 for (std::set<int>::const_iterator it = vSel.begin(); it != vSel.end(); ++it)
162 pos0 += getPos(*it);
163 pos0 /= Real(vSel.size());
164 }
165 else // or chosen point
166 pos0 = getPos(iChosen);
167
168 return pos0;
169 }
170
171 // Scale selected
ScaleSel(Real posMul)172 void SplineEdit::ScaleSel(Real posMul)
173 {
174 Vector3 pos0(0,0,0); // = getPos0() ?
175 if (iChosen != -1) // 0 or chosen point
176 pos0 = getPos(iChosen);
177
178 for (std::set<int>::const_iterator it = vSel.begin(); it != vSel.end(); ++it)
179 { int id = *it;
180 Vector3 pos = (getPos(id) - pos0) * (1.f + posMul) + pos0;
181 if (mP[id].onTer)
182 pos.y = getTerH(pos) + g_Height;
183 setPos(id, pos);
184 vMarks[id].setPos(pos); // upd marker
185 }
186 }
187
188 // Rotate selected
RotateSel(Real relA,Vector3 axis,int addYawRoll)189 void SplineEdit::RotateSel(Real relA, Vector3 axis, int addYawRoll)
190 {
191 if (vSel.empty()) return;
192 Vector3 pos0 = getPos0();
193
194 Quaternion q; q.FromAngleAxis(Degree(relA), axis);
195 Matrix3 m; q.ToRotationMatrix(m);
196
197 // rotate 2d yaw around center
198 for (std::set<int>::const_iterator it = vSel.begin(); it != vSel.end(); ++it)
199 {
200 Vector3 pos = getPos(*it) - pos0;
201 Vector3 npos = pos * m + pos0;
202
203 pos = npos;
204 if (mP[*it].onTer)
205 pos.y = getTerH(pos) + g_Height;
206 setPos(*it, pos);
207
208 if (addYawRoll==1) // todo: get from axis?
209 mP[*it].mYaw -= relA; // rot point yaw
210 else if (addYawRoll==2)
211 // todo: * mul by cos of yaw ?..
212 mP[*it].mRoll -= relA; // rot point roll
213
214 vMarks[*it].setPos(pos);
215 //Move1(*it, npos);
216 }
217 bSelChng = true;
218 }
219
220 // Mirror selected
MirrorSel(bool alt)221 void SplineEdit::MirrorSel(bool alt)
222 {
223 if (vSel.empty()) return;
224
225 std::vector<SplinePoint> mRev;
226 for (std::set<int>::const_reverse_iterator it = vSel.rbegin(); it != vSel.rend(); ++it)
227 mRev.push_back(mP[*it]);
228
229 int i = 0;
230 for (std::set<int>::const_iterator it = vSel.begin(); it != vSel.end(); ++it, ++i)
231 {
232 SplinePoint& p = mP[*it];
233 p = mRev[i];
234 p.mRoll = -p.mRoll;
235 if (p.aType == AT_Manual)
236 { p.mYaw = p.mYaw+180.f;
237 if (p.mYaw > 360.f) p.mYaw -= 360.f;
238 }
239 }
240 recalcTangents();
241 Rebuild(true);
242 }
243
244
245 // Edit modify, controls +-
246 //--------------------------------------------------------------------------------------
247
AddWidth(Real relW)248 void SplineEdit::AddWidth(Real relW) /// Width
249 {
250 if (!vSel.empty()) { // sel
251 for (std::set<int>::const_iterator it = vSel.begin(); it != vSel.end(); ++it)
252 mP[*it].width += relW;
253 bSelChng = true; return; }
254
255 if (iChosen == -1) { // one
256 newP.width += relW; return; }
257
258 mP[iChosen].width += relW;
259
260 Rebuild();
261 }
262
AddYaw(Real relA,Real snapA,bool alt)263 void SplineEdit::AddYaw(Real relA, Real snapA, bool alt) /// Yaw
264 {
265 if (!vSel.empty()) { // rotate sel
266 RotateSel(snapA==0.f ? relA : (relA > 0.f ? snapA : -snapA),
267 // todo: get Z from camera
268 alt ? Vector3::UNIT_Z : Vector3::UNIT_Y, alt ? 2 : 1); return; }
269
270 if (iChosen == -1) { newP.mYaw += relA; return; }
271
272 if (snapA == 0.f) mP[iChosen].mYaw += relA;
273 else
274 { Real a = mP[iChosen].mYaw; int i = a / snapA + (relA > 0.f ? 1 :-1); mP[iChosen].mYaw = i * snapA; }
275
276 Rebuild();
277 }
278
AddRoll(Real relA,Real snapA,bool alt)279 void SplineEdit::AddRoll(Real relA, Real snapA, bool alt) /// Roll
280 {
281 if (!vSel.empty()) { // scale sel
282 ScaleSel(relA * 0.02f);
283 bSelChng = true; return; }
284
285 if (iChosen == -1) { newP.mRoll += relA; return; }
286
287 if (snapA == 0.f) mP[iChosen].mRoll += relA;
288 else
289 { Real a = mP[iChosen].mRoll; int i = a / snapA + (relA > 0.f ? 1 :-1); mP[iChosen].mRoll = i * snapA; }
290
291 Rebuild();
292 }
293
AddPipe(Real relP)294 void SplineEdit::AddPipe(Real relP) /// Pipe
295 {
296 if (!vSel.empty()) { // sel
297 for (std::set<int>::const_iterator it = vSel.begin(); it != vSel.end(); ++it)
298 mP[*it].pipe = std::max(0.f, std::min(1.f, mP[*it].pipe + relP));
299 bSelChng = true; return; }
300
301 if (iChosen == -1) { // one
302 newP.pipe = std::max(0.f, std::min(1.f, newP.pipe + relP)); return; }
303 mP[iChosen].pipe = std::max(0.f, std::min(1.f, mP[iChosen].pipe + relP));
304
305 Rebuild();
306 }
307
308
309 // toggle
310
ToggleOnTerrain()311 void SplineEdit::ToggleOnTerrain() /// On Ter
312 {
313 if (!vSel.empty()) { // sel
314 for (std::set<int>::const_iterator it = vSel.begin(); it != vSel.end(); ++it)
315 mP[*it].onTer = !mP[*it].onTer;
316 bSelChng = true; return; }
317
318 if (iChosen == -1) { // one
319 newP.onTer = !newP.onTer; return; }
320 mP[iChosen].onTer = !mP[iChosen].onTer;
321
322 if (mP[iChosen].onTer)
323 Move(Vector3::ZERO);
324 }
325
ToggleColumn()326 void SplineEdit::ToggleColumn() /// Column
327 {
328 if (!vSel.empty()) { // sel
329 for (std::set<int>::const_iterator it = vSel.begin(); it != vSel.end(); ++it)
330 mP[*it].cols = 1-mP[*it].cols;
331 bSelChng = true; return; }
332
333 if (iChosen == -1) { // one
334 newP.cols = 1-newP.cols; return; }
335
336 mP[iChosen].cols = 1-mP[iChosen].cols;
337 Move(Vector3::ZERO);
338 }
339
ToggleOnPipe(bool old)340 void SplineEdit::ToggleOnPipe(bool old) /// On Pipe (old for stats only, new also flips normal)
341 {
342 #define onp(o) old ? (o ? 0 : 1) : (o ? 0 : 2)
343
344 if (!vSel.empty()) { // sel
345 for (std::set<int>::const_iterator it = vSel.begin(); it != vSel.end(); ++it)
346 mP[*it].onPipe = onp(mP[*it].onPipe);
347 bSelChng = true; return; }
348
349 if (iChosen == -1) { // one
350 newP.onPipe = onp(newP.onPipe); return; }
351
352 mP[iChosen].onPipe = onp(mP[iChosen].onPipe);
353 Move(Vector3::ZERO);
354 }
355
ToggleNotReal()356 void SplineEdit::ToggleNotReal() /// Not Real (not drivable road)
357 {
358 if (!vSel.empty()) { // sel
359 for (std::set<int>::const_iterator it = vSel.begin(); it != vSel.end(); ++it)
360 mP[*it].notReal = !mP[*it].notReal;
361 return; }
362
363 if (iChosen == -1) { // one
364 newP.notReal = !newP.notReal; return; }
365
366 mP[iChosen].notReal = !mP[iChosen].notReal;
367 }
368
ChgLoopType(int rel)369 void SplineEdit::ChgLoopType(int rel) /// Loop type, (camera change on chk, pacenotes)
370 {
371 if (!vSel.empty()) { // sel
372 for (std::set<int>::const_iterator it = vSel.begin(); it != vSel.end(); ++it)
373 mP[*it].loop = (LoopTypes+ mP[*it].loop + rel)%LoopTypes;
374 return; }
375
376 if (iChosen == -1) { // one
377 newP.loop = (LoopTypes+ newP.loop + rel)%LoopTypes; return; }
378
379 mP[iChosen].loop = (LoopTypes+ mP[iChosen].loop + rel)%LoopTypes;
380 }
381
382
ChgMtrId(int rel)383 void SplineEdit::ChgMtrId(int rel) /// Mtr Id
384 {
385 if (!vSel.empty()) { // sel
386 for (std::set<int>::const_iterator it = vSel.begin(); it != vSel.end(); ++it)
387 mP[*it].idMtr = std::max(-1, std::min(MTRs-1, mP[*it].idMtr + rel));
388 bSelChng = true; return; }
389
390 if (iChosen == -1) { // one
391 newP.idMtr = std::max(-1, std::min(MTRs-1, newP.idMtr + rel)); return; }
392 mP[iChosen].idMtr = std::max(-1, std::min(MTRs-1, mP[iChosen].idMtr + rel));
393
394 Move(Vector3::ZERO);
395 }
396
ChgAngType(int rel)397 void SplineEdit::ChgAngType(int rel) /// Ang Type
398 {
399 if (!vSel.empty()) { // sel
400 for (std::set<int>::const_iterator it = vSel.begin(); it != vSel.end(); ++it)
401 mP[*it].aType = (AngType)std::max(0, std::min(AT_ALL-1, mP[*it].aType + rel));
402 bSelChng = true; return; }
403
404 if (iChosen == -1) { // one
405 newP.aType = (AngType)std::max(0, std::min(AT_ALL-1, newP.aType + rel)); return; }
406 mP[iChosen].aType = (AngType)std::max(0, std::min(AT_ALL-1, mP[iChosen].aType + rel));
407
408 Move(Vector3::ZERO);
409 }
410
AngZero()411 void SplineEdit::AngZero() /// Angles set 0
412 {
413 if (!vSel.empty()) { // sel
414 for (std::set<int>::const_iterator it = vSel.begin(); it != vSel.end(); ++it)
415 { mP[*it].mYaw = 0; mP[*it].mRoll = 0; }
416 bSelChng = true; return; }
417
418 if (iChosen == -1) { // one
419 newP.mYaw = 0; newP.mRoll = 0; return; }
420 mP[iChosen].mYaw = 0; mP[iChosen].mRoll = 0;
421
422 Move(Vector3::ZERO);
423 }
424
425
426 //---------------------------------------------------------------------------------------------------------------
427
428 // util
isPipe(int seg)429 bool SplineRoad::isPipe(int seg)
430 {
431 int seg1 = (seg+1) % getNumPoints();
432 return mP[seg].pipe > 0.f || mP[seg1].pipe > 0.f;
433 }
434
435 // info text only
getMtrStr(int seg)436 const String& SplineRoad::getMtrStr(int seg)
437 {
438 static String sHid = "Hidden";
439 if (seg < 0) // new
440 {
441 int i = newP.idMtr;
442 if (i==-1) return sHid;
443 return newP.pipe == 0.f ? sMtrRoad[i] : sMtrPipe[i];
444 }
445 int i = mP[seg].idMtr;
446 if (i==-1) return sHid;
447 return !isPipe(seg) ? sMtrRoad[i] : sMtrPipe[i];
448 }
449
SetMtrPipe(int i,String sMtr)450 void SplineRoad::SetMtrPipe(int i, String sMtr)
451 {
452 sMtrPipe[i] = sMtr; // check if glass in mtr name
453 bMtrPipeGlass[i] = strstr(sMtr.c_str(), "lass") != 0;
454 }
455
456
457 /// Add point
458 ///-------------------------------------------------------------------------------------
Insert(eIns ins)459 void SplineRoad::Insert(eIns ins)
460 {
461 RoadSeg rs; SplinePoint pt = newP; // new
462 pt.chk1st = false; // clear 1st chk
463
464 if (pt.onTer)
465 pt.pos.y = getTerH(pt.pos) + g_Height;
466
467 if (ins == INS_Begin)
468 iChosen = -1;
469
470 if (ins == INS_End) // end
471 {
472 mP.push_back(pt); //recalcTangents();
473 vSegs.push_back(rs);
474 iChosen = getNumPoints()-1; //sel last
475 }
476 else if (iChosen == -1) // begin or none sel
477 {
478 mP.push_front(pt);
479 vSegs.push_front(rs); //recalcTangents();
480 }
481 else // middle
482 {
483 mP.insert(mP.begin()+iChosen+1, pt);
484 vSegs.insert(vSegs.begin()+iChosen+1, rs);
485 if (ins == INS_Cur) // INS_CurPre
486 ++iChosen;
487 }
488 recalcTangents();
489
490 AddMarker(pt.pos);
491 if (ins != INS_End)
492 UpdAllMarkers();/**/
493 Rebuild(/*true*/);
494 }
495
496 /// Delete point
497 ///-------------------------------------------------------------------------------------
Delete()498 void SplineRoad::Delete()
499 {
500 if (iChosen == -1) return;
501 bool last = (iChosen == getNumPoints()-1);
502
503 // remove from sel all ?.
504 vSel.erase(getNumPoints()-1);
505
506 DestroySeg(iChosen);
507 DelLastMarker();/**/
508 lastNdChosen = 0;
509
510 if (last) mP.pop_back();
511 else mP.erase(mP.begin() + iChosen);
512 if (last) vSegs.pop_back();
513 else vSegs.erase(vSegs.begin() + iChosen);
514
515 if (iChosen >= getNumPoints())
516 iChosen = getNumPoints()-1;
517 //iChosen = -1; // cancel sel-
518
519 recalcTangents();
520 UpdAllMarkers();
521 Rebuild(/*true*/);
522 }
523
524
525 /// selection copy, paste, delete
526 //--------------------------------------------------------------------------------------
527
528 std::deque<SplinePoint> SplineBase::mPc; // copy points
529
CopySel()530 bool SplineRoad::CopySel()
531 {
532 if (vSel.empty()) return false;
533
534 mPc.clear();
535 for (std::set<int>::const_iterator it = vSel.begin(); it != vSel.end(); ++it)
536 mPc.push_back(mP[*it]);
537 return true;
538 }
539
Paste(bool reverse)540 void SplineRoad::Paste(bool reverse)
541 {
542 if (!bHitTer || iChosen==-1 || mPc.size()==0) return;
543
544 Vector3 c(0,0,0); // center of sel points
545 for (int i=0; i < mPc.size(); ++i)
546 c += mPc[i].pos;
547 c *= 1.f / Real(mPc.size());
548 c.y = 0.f; //c xz only
549
550 vSel.clear();
551 for (int i=0; i < mPc.size(); ++i)
552 {
553 newP = mPc[i]; // [!reverse ? i : mPc.size()-1-i];
554 newP.pos += posHit - c; // move center to hit pos
555 Insert(INS_Cur/*INS_CurPre*/);
556 vSel.insert(iChosen); // select just inserted
557 }
558 if (reverse) // rot 180
559 RotateSel(180, Vector3::UNIT_Y, 1);
560 Rebuild(true);
561 }
562
DelSel()563 void SplineRoad::DelSel()
564 {
565 if (vSel.empty()) return;
566 for (std::set<int>::reverse_iterator it = vSel.rbegin(); it != vSel.rend(); ++it)
567 {
568 iChosen = *it;
569 //Delete();
570 bool last = (iChosen == getNumPoints()-1);
571
572 DestroySeg(iChosen);
573 DelLastMarker();/**/
574 lastNdChosen = 0;
575
576 if (last) mP.pop_back();
577 else mP.erase(mP.begin() + iChosen);
578 if (last) vSegs.pop_back();
579 else vSegs.erase(vSegs.begin() + iChosen);
580 }
581 if (iChosen >= getNumPoints())
582 iChosen = getNumPoints()-1;
583 vSel.clear();
584
585 recalcTangents();
586 UpdAllMarkers();
587 Rebuild(true);
588 }
589
590
591 /// Pick marker
592 //---------------------------------------------------------------------------------------------------------------
Pick(Camera * mCamera,Real mx,Real my,bool bRay,bool bAddH,bool bHide)593 void SplineRoad::Pick(Camera* mCamera, Real mx, Real my, bool bRay, bool bAddH, bool bHide)
594 {
595 iSelPoint = -1;
596 //if (vMarkNodes.size() != getNumPoints())
597 // return; // assert
598
599 Ray ray = mCamera->getCameraToViewportRay(mx,my); // 0..1
600 const Vector3& pos = mCamera->getDerivedPosition(), dir = ray.getDirection();
601 const Plane& pl = mCamera->getFrustumPlane(FRUSTUM_PLANE_NEAR);
602 Real plDist = FLT_MAX;
603 const Real sphR = 2.4f; //par
604
605 for (int i=0; i < (int)getNumPoints(); ++i)
606 {
607 // ray to sphere dist
608 const Vector3& posSph = getPos(i);
609 const Vector3 ps = pos - posSph;
610 Vector3 crs = ps.crossProduct(dir);
611 Real dist = crs.length() / dir.length();
612 // dist to camera
613 Real plD = pl.getDistance(posSph);
614
615 if (dist < sphR &&
616 plD > 0 && plD < plDist)
617 {
618 plDist = plD;
619 iSelPoint = i;
620 }
621 }
622
623 SelectMarker(bHide);
624
625 // hide/show all markers
626 int iHide = bHide ? 1 : 0;
627 if (iHide != iOldHide)
628 { iOldHide = iHide;
629 for (size_t i=0; i < vMarks.size(); ++i)
630 vMarks[i].setVis(!bHide);
631 }
632
633 // ray terrain hit pos
634 if (bRay && ndHit && mTerrain)
635 {
636 std::pair<bool, Vector3> p = mTerrain->rayIntersects(ray);
637 bHitTer = p.first; //ndHit->setVisible(bHitTer);
638 posHit = p.second;
639
640 if (bHitTer)
641 {
642 Vector3 pos = posHit;
643 //if (iChosen == -1) // for new
644 if (!newP.onTer && bAddH)
645 pos.y = newP.pos.y;
646 ndHit->setPosition(pos);
647 }
648 }
649 }
650