| 1 |
#include "stdafx.h" |
| 2 |
#include "RailMap.h" |
| 3 |
#include "CInterface.h" |
| 4 |
#include "CScene.h" |
| 5 |
#include "CSurfacePlugin.h" |
| 6 |
#include "CRailPlanCurve.h" |
| 7 |
#include "CRailBuilder.h" |
| 8 |
#include "CRailWay.h" |
| 9 |
#include "CStation.h" |
| 10 |
#include "CRailPlugin.h" |
| 11 |
#include "CTiePlugin.h" |
| 12 |
#include "CGirderPlugin.h" |
| 13 |
#include "CSkinPlugin.h" |
| 14 |
|
| 15 |
// 内部定数 |
| 16 |
extern const float CORNER_MIN_DIST = 4.5f; // 制御点間最小距離 |
| 17 |
|
| 18 |
// 内部グローバル |
| 19 |
CPlatformInst *g_PlatformInst = NULL; // カレントプラットフォーム |
| 20 |
list<list<list<CRailWay *> > > g_MultiTrackRailList; // 複線レールリスト |
| 21 |
ILLPRailWay g_MultiTrackSegment; // カレント複線セグメント |
| 22 |
ILPRailWay g_SingleTrackSegment; // カレント単線セグメント |
| 23 |
|
| 24 |
// static メンバ |
| 25 |
int CRailBuilder::ms_CurrentTrack; |
| 26 |
int CRailBuilder::ms_TrackNum; |
| 27 |
float CRailBuilder::ms_TrackInterval; |
| 28 |
float CRailBuilder::ms_TrackShift; |
| 29 |
bool CRailBuilder::ms_LiftRailSurface; |
| 30 |
VEC3 CRailBuilder::ms_BeginPosSum; |
| 31 |
VEC3 CRailBuilder::ms_BeginDirSum; |
| 32 |
VEC3 CRailBuilder::ms_EndPosSum; |
| 33 |
VEC3 CRailBuilder::ms_EndDirSum; |
| 34 |
|
| 35 |
/* |
| 36 |
* [static] |
| 37 |
* ベクトル総和リセット |
| 38 |
*/ |
| 39 |
void CRailBuilder::ResetDirSum(){ |
| 40 |
ms_BeginPosSum = ms_EndPosSum = V3ZERO; |
| 41 |
ms_BeginDirSum = ms_EndDirSum = V3ZERO; |
| 42 |
g_MultiTrackRailList.clear(); |
| 43 |
} |
| 44 |
|
| 45 |
/* |
| 46 |
* [static] |
| 47 |
* トラック情報設定 |
| 48 |
*/ |
| 49 |
void CRailBuilder::SetTrack( |
| 50 |
int cur, // 現在のトラック |
| 51 |
int tnum, // 線数 |
| 52 |
float tint, // 線間隔 |
| 53 |
bool lift // レール持ち上げ |
| 54 |
){ |
| 55 |
ms_CurrentTrack = cur; |
| 56 |
ms_TrackNum = tnum; |
| 57 |
ms_TrackInterval = tint; |
| 58 |
ms_LiftRailSurface = lift; |
| 59 |
float p = ms_TrackNum==ms_CurrentTrack ? 0.0f : 0.5f*(ms_TrackNum-1)-ms_CurrentTrack; |
| 60 |
CRailPlanCurve::SetRadiusDrawPos(p); |
| 61 |
ms_TrackShift = ms_TrackInterval*p; |
| 62 |
g_MultiTrackSegment = g_MultiTrackRailList.begin(); |
| 63 |
} |
| 64 |
|
| 65 |
/* |
| 66 |
* コンストラクタ |
| 67 |
*/ |
| 68 |
CRailBuilder::CRailBuilder( |
| 69 |
VEC3 pos, // 座標 |
| 70 |
CRailBuilder *prev // 前 |
| 71 |
){ |
| 72 |
m_Pos = pos; |
| 73 |
m_HitFlag = false; |
| 74 |
if(m_Prev = prev) m_Prev->m_Next = this; |
| 75 |
m_Next = NULL; |
| 76 |
} |
| 77 |
|
| 78 |
/* |
| 79 |
* デストラクタ |
| 80 |
*/ |
| 81 |
CRailBuilder::~CRailBuilder(){ |
| 82 |
DELETE_V(m_Next); |
| 83 |
} |
| 84 |
|
| 85 |
/* |
| 86 |
* 制御点削除 |
| 87 |
*/ |
| 88 |
CRailBuilder *CRailBuilder::Pop(){ |
| 89 |
if(!IsLinkEmpty()){ |
| 90 |
if(m_Link.rbegin()->m_Link){ |
| 91 |
m_Link.pop_back(); |
| 92 |
if(m_Link.size()) m_Link.pop_back(); |
| 93 |
else goto POP; |
| 94 |
}else{ |
| 95 |
m_Link.pop_back(); |
| 96 |
} |
| 97 |
return this; |
| 98 |
} |
| 99 |
POP: |
| 100 |
CRailBuilder *prev = m_Prev; |
| 101 |
if(prev){ |
| 102 |
prev->m_Pos = m_Pos; |
| 103 |
prev->m_Next = NULL; |
| 104 |
} |
| 105 |
delete this; |
| 106 |
return prev; |
| 107 |
} |
| 108 |
|
| 109 |
/* |
| 110 |
* 座標設定 |
| 111 |
*/ |
| 112 |
VEC3 CRailBuilder::SetPos( |
| 113 |
VEC3 p, // 座標 |
| 114 |
int clip // クリップモード (1: 地下, 2: 高架) |
| 115 |
){ |
| 116 |
m_Pos = p; |
| 117 |
m_HitFlag = g_Scene->ClipAlt(&m_Pos, &m_HitPos, &m_HitNorm, clip); |
| 118 |
return m_Pos; |
| 119 |
} |
| 120 |
|
| 121 |
/* |
| 122 |
* リンク設定 |
| 123 |
*/ |
| 124 |
bool CRailBuilder::SetLink( |
| 125 |
CRailLinkTemp &link // リンク |
| 126 |
){ |
| 127 |
if(m_Link.size()) m_Link.rbegin()->m_Link = NULL; |
| 128 |
else PushLink(); |
| 129 |
if(link.m_Link && m_Prev){ |
| 130 |
if(m_Prev->IsLast()) return false; |
| 131 |
if(m_Prev->CheckLink()){ |
| 132 |
VEC3 tdir; |
| 133 |
V3Norm(&tdir, &(link.m_Pos-m_Prev->GetLink().m_Pos)); |
| 134 |
float dpdot = V3Dot(&tdir, &m_Prev->GetLink().m_Dir); |
| 135 |
float dddot = -V3Dot(&link.m_Dir, &m_Prev->GetLink().m_Dir); |
| 136 |
if(dddot<-0.999f && fabsf(dpdot)>0.999f |
| 137 |
|| dddot>0.999f && dpdot<0.0f) return false; |
| 138 |
} |
| 139 |
} |
| 140 |
if(link.m_Link){ |
| 141 |
*m_Link.rbegin() = link; |
| 142 |
VEC3 tpos = V3ZERO; |
| 143 |
int i, n = 0; |
| 144 |
for(i = 0; i<m_Link.size(); i++){ |
| 145 |
if(m_Link[i].m_Link){ |
| 146 |
tpos += m_Link[i].m_Pos; |
| 147 |
n++; |
| 148 |
} |
| 149 |
} |
| 150 |
SetPos(tpos/n, 0); |
| 151 |
} |
| 152 |
return true; |
| 153 |
} |
| 154 |
|
| 155 |
/* |
| 156 |
* 最終点か調べる |
| 157 |
*/ |
| 158 |
bool CRailBuilder::IsLast(){ |
| 159 |
return !m_Next || m_Prev && m_Link.size()==ms_TrackNum && m_Link[ms_TrackNum-1].m_Link |
| 160 |
|| V3Len(&(m_Next->m_Pos-m_Pos))<CORNER_MIN_DIST; |
| 161 |
} |
| 162 |
|
| 163 |
/* |
| 164 |
* right ベクトル計算 |
| 165 |
*/ |
| 166 |
void CRailBuilder::CalcRight( |
| 167 |
VEC3 *r1, VEC3 *d1, // 点 1 |
| 168 |
VEC3 *r2, VEC3 *d2 // 点 2 |
| 169 |
){ |
| 170 |
V3Norm(r1, &VEC3(-d1->z, 0.0f, d1->x)); |
| 171 |
V3Norm(r2, &VEC3(-d2->z, 0.0f, d2->x)); |
| 172 |
} |
| 173 |
|
| 174 |
/* |
| 175 |
* 分割座標計算 |
| 176 |
*/ |
| 177 |
VEC3 CRailBuilder::CalcSplitPos(){ |
| 178 |
if(m_Next){ |
| 179 |
if(m_Prev && m_Next->m_Next){ |
| 180 |
float len0 = V3Len(&(m_Next->m_Pos-m_Pos)); |
| 181 |
float len1 = V3Len(&(m_Pos-m_Prev->m_Pos)); |
| 182 |
float len2 = V3Len(&(m_Next->m_Next->m_Pos-m_Next->m_Pos)); |
| 183 |
if(!m_Prev->m_Prev) len1 *= 2.0f; |
| 184 |
if(m_Next->m_Next->IsLast()) len2 *= 2.0f; |
| 185 |
if(len0<len1) len1 = len0; |
| 186 |
if(len0<len2) len2 = len0; |
| 187 |
return (len2*m_Pos+len1*m_Next->m_Pos)/(len1+len2); |
| 188 |
}else{ |
| 189 |
return 0.5f*(m_Pos+m_Next->m_Pos); |
| 190 |
} |
| 191 |
}else{ |
| 192 |
return m_Pos; |
| 193 |
} |
| 194 |
} |
| 195 |
|
| 196 |
/* |
| 197 |
* トラック座標計算 |
| 198 |
*/ |
| 199 |
VEC3 CRailBuilder::CalcTrackPos( |
| 200 |
VEC3 *right // 右ベクトル |
| 201 |
){ |
| 202 |
return *right*ms_TrackShift; |
| 203 |
} |
| 204 |
|
| 205 |
/* |
| 206 |
* 曲線計算 |
| 207 |
*/ |
| 208 |
bool CRailBuilder::Curve( |
| 209 |
CRailCurve *curve, // 曲線オブジェクト |
| 210 |
CRailPlugin *rpi, // レールプラグイン |
| 211 |
CTiePlugin *tpi, // 枕木プラグイン |
| 212 |
CGirderPlugin *gpi // 橋桁プラグイン |
| 213 |
){ |
| 214 |
VEC3 hfix = V3ZERO; |
| 215 |
if(ms_LiftRailSurface) hfix.y = rpi ? rpi->m_SurfaceAlt : |
| 216 |
(tpi ? tpi->m_Height : 0.0f)+(gpi ? gpi->m_Height : 0.0f); |
| 217 |
VEC3 pos1, right1, dir1, pos2, right2, dir2; |
| 218 |
bool comp = false, linked1 = false, linked2 = false; |
| 219 |
bool last0 = IsLast(); |
| 220 |
bool last1 = last0 || !m_Next || m_Next->IsLast(); |
| 221 |
bool last2 = last1 || !m_Next->m_Next || m_Next->m_Next->IsLast(); |
| 222 |
if(m_Prev){ |
| 223 |
if(!last0 && !last1){ |
| 224 |
pos1 = CalcSplitPos()+hfix; |
| 225 |
dir1 = m_Next->m_Pos-m_Pos; |
| 226 |
V3Norm(&dir1, &dir1); |
| 227 |
if(m_Next->m_Next->CheckLink()){ |
| 228 |
linked2 = true; |
| 229 |
pos2 = m_Next->m_Next->GetLink().m_Pos; |
| 230 |
dir2 = -m_Next->m_Next->GetLink().m_Dir; |
| 231 |
}else{ |
| 232 |
pos2 = hfix+((comp = !last2) |
| 233 |
? m_Next->CalcSplitPos() : m_Next->m_Next->m_Pos); |
| 234 |
dir2 = m_Next->m_Next->m_Pos-m_Next->m_Pos; |
| 235 |
} |
| 236 |
V3Norm(&dir2, &dir2); |
| 237 |
if(ms_CurrentTrack==ms_TrackNum){ |
| 238 |
if(last2){ |
| 239 |
pos2 = ms_EndPosSum/ms_TrackNum; |
| 240 |
V3Norm(&dir2, &ms_EndDirSum); |
| 241 |
} |
| 242 |
}else{ |
| 243 |
if(last2){ |
| 244 |
ms_EndPosSum += pos2; |
| 245 |
ms_EndDirSum += dir2; |
| 246 |
} |
| 247 |
} |
| 248 |
CalcRight(&right1, &dir1, &right2, &dir2); |
| 249 |
if(linked2) right2 = V3ZERO; |
| 250 |
curve->Curve(R2L(pos1+CalcTrackPos(&right1)), dir1, |
| 251 |
R2L(pos2+CalcTrackPos(&right2)), dir2, comp, true); |
| 252 |
return true; |
| 253 |
} |
| 254 |
}else{ |
| 255 |
if(!last0){ |
| 256 |
if(CheckLink()){ |
| 257 |
linked1 = true; |
| 258 |
pos1 = GetLink().m_Pos; |
| 259 |
dir1 = GetLink().m_Dir; |
| 260 |
}else{ |
| 261 |
pos1 = m_Pos+hfix; |
| 262 |
dir1 = m_Next->m_Pos-m_Pos; |
| 263 |
} |
| 264 |
V3Norm(&dir1, &dir1); |
| 265 |
if(last1){ |
| 266 |
if(m_Next->CheckLink()){ |
| 267 |
linked2 = true; |
| 268 |
pos2 = m_Next->GetLink().m_Pos; |
| 269 |
dir2 = -m_Next->GetLink().m_Dir; |
| 270 |
if(!CheckLink()){ |
| 271 |
VEC3 r = pos2-pos1; |
| 272 |
V3Norm(&r, &r); |
| 273 |
dir1 = -dir2+2.0f*V3Dot(&r, &dir2)*r; |
| 274 |
} |
| 275 |
}else{ |
| 276 |
pos2 = m_Next->m_Pos+hfix; |
| 277 |
if(CheckLink()){ |
| 278 |
VEC3 r = pos2-pos1; |
| 279 |
V3Norm(&r, &r); |
| 280 |
dir2 = -dir1+2.0f*V3Dot(&r, &dir1)*r; |
| 281 |
}else{ |
| 282 |
dir2 = dir1; |
| 283 |
} |
| 284 |
} |
| 285 |
}else{ |
| 286 |
if(m_Next->m_Next->CheckLink()){ |
| 287 |
linked2 = true; |
| 288 |
pos2 = m_Next->m_Next->GetLink().m_Pos; |
| 289 |
dir2 = -m_Next->m_Next->GetLink().m_Dir; |
| 290 |
}else{ |
| 291 |
pos2 = hfix+((comp = !last2) |
| 292 |
? m_Next->CalcSplitPos() : m_Next->m_Next->m_Pos); |
| 293 |
dir2 = m_Next->m_Next->m_Pos-m_Next->m_Pos; |
| 294 |
} |
| 295 |
} |
| 296 |
V3Norm(&dir2, &dir2); |
| 297 |
if(ms_CurrentTrack==ms_TrackNum){ |
| 298 |
pos1 = ms_BeginPosSum/ms_TrackNum; |
| 299 |
V3Norm(&dir1, &ms_BeginDirSum); |
| 300 |
if(last1 || last2){ |
| 301 |
pos2 = ms_EndPosSum/ms_TrackNum; |
| 302 |
V3Norm(&dir2, &ms_EndDirSum); |
| 303 |
} |
| 304 |
}else{ |
| 305 |
ms_BeginPosSum += pos1; |
| 306 |
ms_BeginDirSum += dir1; |
| 307 |
if(last1 || last2){ |
| 308 |
ms_EndPosSum += pos2; |
| 309 |
ms_EndDirSum += dir2; |
| 310 |
} |
| 311 |
} |
| 312 |
CalcRight(&right1, &dir1, &right2, &dir2); |
| 313 |
if(linked1) right1 = V3ZERO; |
| 314 |
if(linked2) right2 = V3ZERO; |
| 315 |
curve->Curve(R2L(pos1+CalcTrackPos(&right1)), dir1, |
| 316 |
R2L(pos2+CalcTrackPos(&right2)), dir2, comp, true); |
| 317 |
return true; |
| 318 |
} |
| 319 |
} |
| 320 |
return false; |
| 321 |
} |
| 322 |
|
| 323 |
/* |
| 324 |
* レンダリング |
| 325 |
*/ |
| 326 |
void CRailBuilder::Render( |
| 327 |
CLineDumpL *dump, // ダンパ |
| 328 |
CRailPlugin *rpi, // レールプラグイン |
| 329 |
CTiePlugin *tpi, // 枕木プラグイン |
| 330 |
CGirderPlugin *gpi, // 枕木プラグイン |
| 331 |
bool draw // 描画フラグ |
| 332 |
){ |
| 333 |
VEC3 hfix = V3ZERO; |
| 334 |
if(ms_LiftRailSurface) hfix.y = rpi ? rpi->m_SurfaceAlt : |
| 335 |
(tpi ? tpi->m_Height : 0.0f)+(gpi ? gpi->m_Height : 0.0f); |
| 336 |
if(draw){ |
| 337 |
bool renderlink = !IsLinkEmpty(); |
| 338 |
int i, lnum = 0; |
| 339 |
if(renderlink){ |
| 340 |
devSetZRead(TRUE); |
| 341 |
devSetZWrite(TRUE); |
| 342 |
devSetLighting(TRUE); |
| 343 |
for(i = 0; i<m_Link.size() && i<ms_TrackNum; i++){ |
| 344 |
if(!m_Link[i].m_Link) continue; |
| 345 |
lnum++; |
| 346 |
g_LinkObject.SetPos(m_Link[i].m_Pos); |
| 347 |
g_LinkObject.SetDir(m_Link[i].m_Dir, m_Link[i].m_Up); |
| 348 |
g_LinkObject.Render(); |
| 349 |
} |
| 350 |
} |
| 351 |
if(!m_Prev || renderlink){ |
| 352 |
devSetZRead(FALSE); |
| 353 |
devSetZWrite(FALSE); |
| 354 |
devSetLighting(FALSE); |
| 355 |
devResetMaterial(); |
| 356 |
devResetMatrix(); |
| 357 |
if(renderlink){ |
| 358 |
if(m_Prev) g_StrTex->RenderLeft( |
| 359 |
TILE_QUAD, TILE_UNIT*4+TILE_QUAD, 0xffffffff, 0xff000000, |
| 360 |
FlashIn("%s: %d/%d", lang(JointDest), lnum, ms_TrackNum)); |
| 361 |
else g_StrTex->RenderLeft( |
| 362 |
TILE_QUAD, TILE_UNIT*3+TILE_QUAD, 0xffffffff, 0xff000000, |
| 363 |
FlashIn("%s: %d/%d", lang(JointSrc), lnum, ms_TrackNum)); |
| 364 |
} |
| 365 |
} |
| 366 |
} |
| 367 |
devResetMatrix(); |
| 368 |
CRailPlanCurve curve(dump); |
| 369 |
Curve(&curve, rpi, tpi, gpi); |
| 370 |
if(m_HitFlag){ |
| 371 |
DrawTangent(m_HitPos, m_HitNorm, 0xffff0000, dump); |
| 372 |
dump->Add(m_HitPos, 0xffff0000, m_Pos, 0x80ff0000); |
| 373 |
//RailMapLine(m_HitPos, 0xffff0000, m_Pos, 0x80ff0000, false); |
| 374 |
} |
| 375 |
if(IsLast()){ |
| 376 |
if(m_Next){ |
| 377 |
if(m_Next->m_HitFlag){ |
| 378 |
DrawTangent(m_Next->m_HitPos, m_Next->m_HitNorm, 0xff0000ff, dump); |
| 379 |
dump->Add(m_Next->m_HitPos, 0xff0000ff, m_Next->m_Pos, 0x800000ff); |
| 380 |
//RailMapLine(m_Next->m_HitPos, 0xff0000ff, m_Next->m_Pos, 0x800000ff, false); |
| 381 |
} |
| 382 |
VEC3 pp1 = m_Pos+(CheckLink() ? -hfix : V3ZERO); |
| 383 |
VEC3 pp2 = m_Next->m_Pos+(m_Next->CheckLink() ? -hfix : V3ZERO); |
| 384 |
dump->Add(pp1, 0xc0ff0000, pp2, 0xc0ff0000); |
| 385 |
RailMapLine(pp1, 0xc0ff0000, pp2, 0xc0ff0000, false); |
| 386 |
} |
| 387 |
if(draw){ |
| 388 |
dump->Render(true); |
| 389 |
devSetZRead(TRUE); |
| 390 |
devSetZWrite(TRUE); |
| 391 |
devSetLighting(TRUE); |
| 392 |
g_ArrowObject.SetPos(m_Next ? m_Next->m_Pos : m_Pos); |
| 393 |
g_ArrowObject.RotY(2.0f*D3DX_PI/MAXFPS); |
| 394 |
g_ArrowObject.Render(); |
| 395 |
} |
| 396 |
}else{ |
| 397 |
VEC3 pp1 = m_Pos+(CheckLink() ? -hfix : V3ZERO); |
| 398 |
VEC3 pp2 = m_Next->m_Pos+(m_Next->CheckLink() ? -hfix : V3ZERO); |
| 399 |
dump->Add(pp1, 0xc0ff0000, pp2, 0xc0ff0000); |
| 400 |
RailMapLine(pp1, 0xc0ff0000, pp2, 0xc0ff0000, false); |
| 401 |
m_Next->Render(dump, rpi, tpi, gpi, draw); |
| 402 |
} |
| 403 |
} |
| 404 |
|
| 405 |
/* |
| 406 |
* 建設 |
| 407 |
*/ |
| 408 |
void CRailBuilder::BuildRail( |
| 409 |
CRailConnectorLink &begin, // 開始リンク |
| 410 |
CRailConnectorLink &end, // 終了リンク |
| 411 |
CRailPlugin *rpi, // レールプラグイン |
| 412 |
CTiePlugin *tpi, // 枕木プラグイン |
| 413 |
CGirderPlugin *gpi // 枕木プラグイン |
| 414 |
){ |
| 415 |
if(!ms_CurrentTrack){ |
| 416 |
g_MultiTrackRailList.push_back(list<list<CRailWay *> >()); |
| 417 |
g_MultiTrackSegment = --g_MultiTrackRailList.end(); |
| 418 |
} |
| 419 |
g_MultiTrackSegment->push_back(list<CRailWay *>()); |
| 420 |
g_SingleTrackSegment = --g_MultiTrackSegment->end(); |
| 421 |
if(m_Next->IsLast() || m_Next->m_Next && m_Next->m_Next->IsLast()){ |
| 422 |
CRailBuildCurve curve(begin, end, rpi, tpi, gpi); |
| 423 |
Curve(&curve, rpi, tpi, gpi); |
| 424 |
}else{ |
| 425 |
CRailBuildCurve curve(begin, R2L(CRailConnectorLink()), rpi, tpi, gpi); |
| 426 |
Curve(&curve, rpi, tpi, gpi); |
| 427 |
g_MultiTrackSegment++; |
| 428 |
m_Next->BuildRail(curve.GetNext(), end, rpi, tpi, gpi); |
| 429 |
} |
| 430 |
} |
| 431 |
|
| 432 |
//////////////////////////////////////////////////////////////////////////////// |
| 433 |
//////////////////////////////////////////////////////////////////////////////// |
| 434 |
|
| 435 |
/* |
| 436 |
* コンストラクタ |
| 437 |
*/ |
| 438 |
CRailLinkTemp::CRailLinkTemp( |
| 439 |
int side, // サイド |
| 440 |
float sumlen, // 積算距離 |
| 441 |
VEC3 &pos, // 座標 |
| 442 |
VEC3 &right, // right |
| 443 |
VEC3 &up, // up |
| 444 |
VEC3 &dir, // dir |
| 445 |
CRailWay *link, // 接続レール |
| 446 |
IRailSplitter sit // splice 位置 |
| 447 |
){ |
| 448 |
m_Side = side; |
| 449 |
m_SumLen = sumlen; |
| 450 |
m_SpliceItr = sit; |
| 451 |
m_Pos = pos; |
| 452 |
m_Right = right; |
| 453 |
m_Up = up; |
| 454 |
m_Dir = dir; |
| 455 |
m_Link = link; |
| 456 |
} |