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