1 #pragma once 2 #include "SplineBase.h" 3 4 #include <vector> 5 #include <deque> 6 #include <set> 7 8 #include <OgreString.h> 9 #include <OgreVector2.h> 10 #include <OgreVector3.h> 11 #include <OgreVector4.h> 12 13 #include <OgreMesh.h> 14 #include <OgreAxisAlignedBox.h> 15 16 namespace Ogre { class SceneManager; class SceneNode; class Entity; class Terrain; class Camera; } 17 class btTriangleMesh; 18 19 #if defined(_WIN32) && defined(SR_EDITOR) 20 // win doesnt need bullet somehow 21 #else 22 #include "btBulletCollisionCommon.h" 23 #endif 24 25 #ifdef SR_EDITOR 26 #define LogR(a) //LogO(String("~ Road ") + a) 27 #else 28 #define LogR(a) 29 #endif 30 31 #define LODs 4 32 #define MTRs 4 33 #define LoopTypes 8 // for pace notes 34 35 36 struct RoadSeg 37 { 38 struct SegData { 39 Ogre::SceneNode* node; Ogre::Entity* ent; 40 Ogre::MeshPtr mesh; Ogre::String smesh; SegDataRoadSeg::SegData41 SegData() : node(0), ent(0), smesh("") {} 42 }; 43 44 SegData road[LODs], wall[LODs], col, blend[LODs]; 45 Ogre::String sMtrRd,sMtrWall,sMtrB; int mtrId; 46 47 std::vector<Ogre::Vector3> lpos; //points for lod dist 48 int nTri[LODs], mrgLod; 49 50 bool empty; RoadSegRoadSeg51 RoadSeg() : empty(true), mrgLod(0), mtrId(0) { 52 for (int i=0;i<LODs;++i) nTri[i] = 0; 53 } 54 }; 55 56 // insert before first, after chosen, after last 57 enum eIns{ INS_Begin, INS_Cur, INS_CurPre, INS_End }; 58 59 60 class SplineRoad : public SplineMarkEd 61 { 62 public: 63 #ifdef SR_EDITOR 64 class App* pApp; ///* 65 SplineRoad(App* papp); 66 #else 67 class GAME* pGame; ///* 68 SplineRoad(GAME* pgame); 69 #endif 70 virtual ~SplineRoad(); 71 void Defaults(); 72 73 // File 74 bool LoadFile(Ogre::String fname, bool build=true), SaveFile(Ogre::String fname); 75 76 // Rebuild 77 bool RebuildRoadInt(bool editorAlign=false, bool edBulletFull=false); 78 void RebuildRoadPace(); /// Rebuild road only for pacenotes, after RebuildRoadInt 79 void Destroy(), DestroyRoad(), DestroySeg(int id); 80 81 82 // Update 83 void UpdLodVis(/*Camera* pCam,*/ float fBias=1.f, bool bFull=false); 84 void SetForRnd(Ogre::String sMtr),UnsetForRnd(); 85 86 void Pick(Ogre::Camera* mCamera, Ogre::Real mx, Ogre::Real my, 87 bool bRay=true, bool bAddH=false, bool bHide=false); 88 void SelectMarker(bool bHide=false); 89 void ToggleMerge(); 90 91 92 // Insert ------- 93 void Insert(eIns ins); 94 void Delete(), DelSel(); 95 96 bool CopySel(); 97 void Paste(bool reverse=false); 98 99 100 // other 101 const Ogre::String& getMtrStr(int seg); 102 bool isPipe(int seg); 103 104 105 private: 106 /// *** MESH **** 107 //--------------------------------------------------------------------------------------- 108 109 void CreateMesh( Ogre::SubMesh* submesh, Ogre::AxisAlignedBox& aabox, 110 const std::vector<Ogre::Vector3>& pos, const std::vector<Ogre::Vector3>& norm, const std::vector<Ogre::Vector4>& clr, 111 const std::vector<Ogre::Vector2>& tcs, const std::vector<Ogre::uint16>& idx, Ogre::String sMtrName); 112 113 void AddMesh( Ogre::MeshPtr mesh, Ogre::String sMesh, const Ogre::AxisAlignedBox& aabox, 114 Ogre::Entity** pEnt, Ogre::SceneNode** pNode, Ogre::String sEnd); 115 116 std::vector<Ogre::uint16> idx, idxB; // mesh indices 117 118 std::vector<Ogre::Vector3> posBt; // for bullet trimesh 119 std::vector<btTriangleMesh*> vbtTriMesh; // for delete 120 121 const std::vector<Ogre::Vector3>* at_pos; 122 123 // add triangle, with index check 124 void addTri(int f1, int f2, int f3, int i); 125 126 int at_size, at_ilBt; 127 bool bltTri, blendTri; // pars for addTri 128 129 130 /// *** Rebuild Geom DATA *** 131 //--------------------------------------------------------------------------------------- 132 133 struct DataRoad // global 134 { 135 int segs; // count 136 int sMin, sMax; // range 137 138 bool editorAlign, bulletFull; // ed,options 139 DataRoadDataRoad140 DataRoad(bool edAlign, bool bltFull) 141 :editorAlign(edAlign), bulletFull(bltFull) 142 ,segs(0), sMin(0), sMax(0) 143 { } 144 }; 145 146 void PrepassRange(DataRoad& DR); 147 void PrepassAngles(DataRoad& DR); 148 149 struct DataLod0 // at Lod 0 150 { 151 std::vector<int> v0_iL; // length steps 152 std::vector<Ogre::Real> v0_tc; // tex coords 153 std::vector<Ogre::Vector3> v0_N; // normals 154 std::vector<int> v0_Loop; // bool, inside loop ClearDataLod0155 void Clear() 156 { v0_iL.clear(); v0_tc.clear(); v0_N.clear(); v0_Loop.clear(); } 157 } 158 DL0; // stays after build since N is used for SetChecks 159 void SetChecks(); // Init 1st in file load, 2nd time for N 160 161 struct DataLod // for current Lod 162 { 163 //> data at cur lod 164 std::vector<int> v_iL, v_iW; // num Length and Width steps for each seg 165 std::vector<int> v_bMerge; // bool 0 if seg merged, 1 if new 166 167 std::vector<Ogre::Real> v_tc, v_len; // total length 168 std::vector<Ogre::Vector3> v_W; // width dir 169 170 std::vector<std::vector <int> > v_iWL; // width steps per length point, for each seg 171 std::vector<int> v_iwEq; // 1 if equal width steps at whole length, in seg, 0 has transition 172 173 Ogre::Real tcLen; // total tex coord length u 174 Ogre::Real sumLenMrg; // total length to determine merging 175 int mrgCnt; // stats, merges counter 176 177 // LOD vars 178 int lod, iLodDiv; //. 179 Ogre::Real fLenDim; 180 bool isLod0, isPace; 181 DataLodDataLod182 DataLod() 183 :tcLen(0.f), sumLenMrg(0.f), mrgCnt(0) 184 ,lod(0), iLodDiv(1), fLenDim(1.f), 185 isLod0(true), isPace(false) 186 { } 187 }; 188 189 struct StatsLod // stats for cuurent Lod 190 { //# stats 191 Ogre::Real roadLen, rdOnT, rdPipe, rdOnPipe; 192 Ogre::Real avgWidth, stMaxH, stMinH; 193 Ogre::Real bankAvg, bankMax; 194 bool stats; 195 StatsLodStatsLod196 StatsLod() 197 :roadLen(0.f), rdOnT(0.f), rdPipe(0.f), rdOnPipe(0.f) 198 ,avgWidth(0.f), stMaxH(FLT_MIN), stMinH(FLT_MAX) 199 ,bankAvg(0.f), bankMax(0.f) 200 ,stats(0) 201 { } 202 }; 203 204 void PrepassLod( 205 const DataRoad& DR, 206 DataLod0& DL0, DataLod& DL, StatsLod& ST, 207 int lod, bool editorAlign); 208 209 struct DataLodMesh // mesh data for lod (from merged segs) 210 { 211 //> W-wall C-column B-blend 212 std::vector<Ogre::Vector4> clr0/*empty*/, clr, clrB; 213 std::vector<Ogre::Vector3> pos,norm, posW,normW, posC,normC, posLod, posB,normB; 214 std::vector<Ogre::Vector2> tcs, tcsW, tcsC, tcsB; 215 216 int iLmrg, iLmrgW, iLmrgC, iLmrgB; 217 DataLodMeshDataLodMesh218 DataLodMesh() 219 :iLmrg(0), iLmrgW(0), iLmrgC(0), iLmrgB(0) 220 { } 221 void Clear(); 222 }; 223 224 public: /// pacenotes prepass data 225 struct PaceM 226 { 227 Ogre::Vector3 pos, pos2; 228 float aa; 229 int used; bool vis, notReal, onTer; 230 int loop; bool jump,jumpR, onPipe,onPipeE; PaceMPaceM231 PaceM() 232 :used(-1), aa(0.f) 233 ,vis(1), notReal(0), onTer(1) 234 ,loop(0), jump(0),jumpR(0), onPipe(0),onPipeE(0) 235 { } 236 }; 237 std::vector<PaceM> vPace; 238 private: 239 240 struct DataSeg // for segment 241 { 242 int seg,seg1,seg0; 243 int mtrId; 244 bool onTer; 245 bool pipe; 246 bool hasBlend; 247 int iwC; 248 bool jfw0,jfw1,jfw2; // jump front walls 249 }; 250 251 // Build Segment Geometry 252 void BuildSeg( 253 const DataRoad& DR, 254 const DataLod0& DL0, DataLod& DL, StatsLod& ST, 255 DataLodMesh& DLM, DataSeg& DS, int segM, bool full); 256 257 258 void createSeg_Meshes( 259 const DataLod& DL, 260 const DataLodMesh& DLM, DataSeg& DS, RoadSeg& rs); 261 262 void createSeg_Collision( 263 const DataLodMesh& DLM, const DataSeg& DS); 264 265 //--------------------------------------------------------------------------------------- 266 267 268 // vars 269 friend class App; 270 friend class CGui; 271 public: 272 Ogre::Vector3 posHit; bool bHitTer; 273 274 int iOldHide, idStr; // upd var 275 276 bool bMerge; 277 float fLodBias; // upd par, detail 278 279 bool bCastShadow; // true for depth shadows 280 bool bRoadWFullCol; // road wall full collision (all triangles, or just side) 281 282 283 // road data Segments 284 std::deque<RoadSeg> vSegs; 285 286 287 /// params, from xml 288 // materials 289 Ogre::String sMtrPipe[MTRs]; // use SetMtrPipe to set 290 bool bMtrPipeGlass[MTRs]; // glass in mtr name 291 292 Ogre::String sMtrRoad[MTRs], sMtrWall,sMtrWallPipe, sMtrCol; 293 void SetMtrPipe(int i, Ogre::String sMtr); 294 295 296 // geometry ---- 297 // tex coord multipliers (scale) per unit length 298 // road, wall, pipe, pipewall, column 299 Ogre::Real g_tcMul, g_tcMulW, g_tcMulP, g_tcMulPW, g_tcMulC; 300 301 Ogre::Real g_LenDim0; // triangle dim in length 302 int g_iWidthDiv0; // width divisions (const for road, except pipes) 303 304 // skirt for hiding gaps 305 Ogre::Real g_SkirtLen, g_SkirtH; 306 307 // merge for less batches 308 Ogre::Real g_MergeLen; // length below which segments are merged 309 Ogre::Real g_LodPntLen; // length between LOD points 310 311 int g_ColNSides; // column regular polygon sides 312 Ogre::Real g_ColRadius; // column radius 313 Ogre::Real g_P_il_mul, g_P_iw_mul; // length,width steps multipliers for pipe 314 315 316 Ogre::String sTxtDesc; // track description text 317 318 // for editor tool: align terrain to road 319 float ed_Wadd, ed_Wmul; // const added width and width multipler for whole road 320 321 322 // stats ---- 323 struct Stats // for info only 324 { 325 int iMrgSegs, segsMrg; 326 int iVis, iTris; // in upd vis 327 328 Ogre::Real Length, WidthAvg, HeightDiff; 329 Ogre::Real OnTer, Pipes, OnPipe; 330 Ogre::Real bankAvg, bankMax; // banking angle 331 332 Stats(); 333 void Reset(); 334 } st; 335 336 void End0Stats(const DataLod& DL, const StatsLod& ST); 337 void EndStats(const DataRoad& DR, const StatsLod& ST); 338 }; 339