BuildingLink.cpp 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  1. //----------------------------------------------------------------------------
  2. //
  3. // Link.cpp -
  4. //
  5. //---------------------------------------------------------------------------//
  6. // Copyright (C) Microsoft Corporation. All rights reserved. //
  7. //===========================================================================//
  8. #include "mclib.h"
  9. #include "BuildingLink.h"
  10. #include "EditorObjectMgr.h"
  11. #include <algorithm>
  12. #include "celine.h"
  13. BuildingLink::BuildingLink( const EditorObject* pParent )
  14. {
  15. gosASSERT( pParent );
  16. parent.m_ID = pParent->getID();
  17. parent.pos = pParent->getPosition();
  18. }
  19. BuildingLink::BuildingLink( const Stuff::Vector3D& pos )
  20. {
  21. parent.pos = pos;
  22. parent.m_ID = -1;
  23. }
  24. BuildingLink::BuildingLink( const BuildingLink& Src )
  25. {
  26. CopyData( Src );
  27. }
  28. BuildingLink& BuildingLink::operator=( const BuildingLink& Src )
  29. {
  30. if ( &Src != this )
  31. {
  32. CopyData( Src );
  33. }
  34. return *this;
  35. }
  36. void BuildingLink::CopyData( const BuildingLink& Src )
  37. {
  38. parent = Src.parent;
  39. children.Clear();
  40. for ( EList< Info, const Info& >::EConstIterator iter = Src.children.Begin();
  41. !iter.IsDone(); iter++ )
  42. {
  43. children.Append( *iter );
  44. }
  45. }
  46. bool BuildingLink::AddChild( const EditorObject* pObject )
  47. {
  48. int ID = pObject->getID();
  49. for( EList< Info, const Info& >::EIterator iter = children.Begin();
  50. !iter.IsDone(); iter++ )
  51. {
  52. if ( (*iter).pos == pObject->getPosition() &&
  53. (*iter).m_ID == ID )
  54. {
  55. SPEW( (0, "Link::AddChild, not adding an object because it is"
  56. "already there\n" ) );
  57. return false;
  58. }
  59. }
  60. Info tmp;
  61. tmp.pos = pObject->getPosition();
  62. tmp.m_ID = ID;
  63. children.Append( tmp );
  64. return true;
  65. }
  66. int BuildingLink::GetLinkCount( ) const
  67. {
  68. return children.Count();
  69. }
  70. const Stuff::Vector3D& BuildingLink::GetParentPosition() const
  71. {
  72. return parent.pos;
  73. }
  74. bool BuildingLink::HasChild( const EditorObject* pObject ) const
  75. {
  76. int ID = pObject->getID();
  77. pObject->getPosition();
  78. for( EList< Info, const Info& >::EConstIterator iter = children.Begin();
  79. !iter.IsDone(); iter++ )
  80. {
  81. if ( (*iter).pos == pObject->getPosition() )
  82. {
  83. if ( (*iter).m_ID == ID )
  84. return true;
  85. }
  86. }
  87. return false;
  88. }
  89. bool BuildingLink::HasParent( const EditorObject* pObject ) const
  90. {
  91. int ID = pObject->getID();
  92. // ignore damage bit and rotation
  93. if ( parent.pos == pObject->getPosition() && parent.m_ID == ID )
  94. return true;
  95. return false;
  96. }
  97. bool BuildingLink::TypeCanBeParent( const EditorObject* pObject )
  98. {
  99. int Type = pObject->getSpecialType();
  100. switch (Type)
  101. {
  102. case EditorObjectMgr::TURRET_CONTROL:
  103. case EditorObjectMgr::GATE_CONTROL:
  104. case EditorObjectMgr::POWER_STATION:
  105. case EditorObjectMgr::SENSOR_CONTROL:
  106. case EditorObjectMgr::TURRET_GENERATOR:
  107. case EditorObjectMgr::BRIDGE_CONTROL:
  108. case EditorObjectMgr::SPOTLIGHT_CONTROL:
  109. return true;
  110. break;
  111. default:
  112. break;
  113. };
  114. return false;
  115. }
  116. bool BuildingLink::CanLink( const EditorObject* pParent, const EditorObject* pChild )
  117. {
  118. int ParentType = pParent->getSpecialType();
  119. int ChildType = pChild->getSpecialType();
  120. switch (ParentType)
  121. {
  122. case EditorObjectMgr::TURRET_CONTROL:
  123. return (ChildType == EditorObjectMgr::EDITOR_TURRET
  124. || ChildType == EditorObjectMgr::LOOKOUT ) ? true : false;
  125. break;
  126. case EditorObjectMgr::GATE_CONTROL:
  127. return ChildType == EditorObjectMgr::EDITOR_GATE ? true : false;
  128. break;
  129. case EditorObjectMgr::POWER_STATION:
  130. return (ChildType == EditorObjectMgr::BRIDGE_CONTROL
  131. || ChildType == EditorObjectMgr::GATE_CONTROL
  132. || ChildType == EditorObjectMgr::SPOTLIGHT_CONTROL ) ? true : false;
  133. break;
  134. case EditorObjectMgr::SENSOR_CONTROL:
  135. return ChildType == EditorObjectMgr::SENSOR_TOWER ? true : false;
  136. break;
  137. case EditorObjectMgr::TURRET_GENERATOR:
  138. return ChildType == EditorObjectMgr::TURRET_CONTROL ? true : false;
  139. break;
  140. case EditorObjectMgr::SPOTLIGHT_CONTROL:
  141. return ChildType == EditorObjectMgr::SPOTLIGHT ? true : false;
  142. break;
  143. case EditorObjectMgr::BRIDGE_CONTROL:
  144. return ChildType == EditorObjectMgr::EDITOR_BRIDGE ? true : false;
  145. break;
  146. default:
  147. break;
  148. };
  149. return false;
  150. }
  151. bool BuildingLink::RemoveObject( const EditorObject* pObject )
  152. {
  153. if ( HasParent( pObject ) )
  154. {
  155. SPEW(( 0, "BuildingLink::RemoveObject could not remove a parent object\n") );
  156. return false;
  157. }
  158. Stuff::Vector3D pos = pObject->getPosition( );
  159. long ID = pObject->getID();
  160. for ( EList< Info, const Info& >::EIterator iter = children.Begin();
  161. !iter.IsDone(); iter++ )
  162. {
  163. if ( ID == (*iter).m_ID && pos == (*iter).pos )
  164. {
  165. children.Delete( iter );
  166. return true;
  167. }
  168. }
  169. SPEW(( 0, "BuildingLInk::RemoveObject failed because it didn't have the object\n") );
  170. return false;
  171. }
  172. int BuildingLink::GetChildrenPositions( Stuff::Vector3D* pos, int Count ) const
  173. {
  174. if ( children.Count() > (unsigned long)Count )
  175. return children.Count();
  176. int i = 0;
  177. for ( EList< Info, const Info& >::EConstIterator iter = children.Begin();
  178. !iter.IsDone(); iter++ )
  179. {
  180. pos[i++] = (*iter).pos;
  181. }
  182. return i;
  183. }
  184. static bool isInView(const Point3D &position)
  185. {
  186. /* the code in this function was largely swiped from "bool BldgAppearance::recalcBounds (void)" on 4/24/00 */
  187. bool inView = false;
  188. if (eye)
  189. {
  190. //--------------------------------------------------
  191. // First, if we are using perspective, figure out
  192. // if object too far from camera. Far Clip Plane.
  193. if (eye->usePerspective)
  194. {
  195. Stuff::Point3D Distance;
  196. Stuff::Point3D eyePosition(eye->getPosition());
  197. Stuff::Point3D objPosition(position);
  198. Distance.Subtract(objPosition,eyePosition);
  199. float eyeDistance = Distance.GetApproximateLength();
  200. if (eyeDistance > Camera::MaxClipDistance)
  201. {
  202. //hazeFactor = 1.0f;
  203. inView = false;
  204. }
  205. else if (eyeDistance > Camera::MinHazeDistance)
  206. {
  207. Camera::HazeFactor = (eyeDistance - Camera::MinHazeDistance) * Camera::DistanceFactor;
  208. inView = true;
  209. }
  210. else
  211. {
  212. Camera::HazeFactor = 0.0f;
  213. inView = true;
  214. }
  215. //-----------------------------------------------------------------
  216. // If inside farClip plane, check if behind camera.
  217. // Find angle between lookVector of Camera and vector from camPos
  218. // to Target. If angle is less then halfFOV, object is visible.
  219. if (inView)
  220. {
  221. Stuff::Vector3D Distance;
  222. Stuff::Point3D objPosition;
  223. Stuff::Point3D eyePosition(eye->getCameraOrigin());
  224. objPosition.x = -position.x;
  225. objPosition.y = position.z;
  226. objPosition.z = position.y;
  227. Distance.Subtract(objPosition,eyePosition);
  228. Distance.Normalize(Distance);
  229. float cosine = Distance * eye->getLookVector();
  230. if (cosine > eye->cosHalfFOV)
  231. inView = true;
  232. else
  233. inView = false;
  234. }
  235. }
  236. else
  237. {
  238. Camera::HazeFactor = 0.0f;
  239. inView = true;
  240. }
  241. }
  242. return(inView);
  243. }
  244. void BuildingLink::render()
  245. {
  246. Stuff::Vector4D parentScreen;
  247. eye->projectZ( parent.pos, parentScreen );
  248. Stuff::Vector4D childScreen;
  249. for ( EList< Info, const Info& >::EConstIterator iter = children.Begin();
  250. !iter.IsDone(); iter++ )
  251. {
  252. /* Rather than doing true clipping, the link lines are broken into "typical object"
  253. sized pieces and rendered using course culling and relying on guard band clipping
  254. in the fashion that buildings are rendered. */
  255. Stuff::Vector3D diffVect;
  256. diffVect.Subtract((*iter).pos, parent.pos);
  257. float lineLength = diffVect.GetLength();
  258. const float lengthOfATypicalLargeObject = 150.0/*arbitrary*/;
  259. int numSegments = lineLength / lengthOfATypicalLargeObject;
  260. if (1 > numSegments)
  261. {
  262. numSegments = 1;
  263. }
  264. float segmentLength = lineLength / numSegments;
  265. Stuff::Vector3D segVect = diffVect;
  266. segVect.Normalize(segVect);
  267. segVect *= segmentLength;
  268. Stuff::Point3D p1(parent.pos.x, parent.pos.y, parent.pos.z);
  269. bool p1IsInView = isInView(p1);
  270. int i;
  271. for (i = 0 ; i < numSegments; i += 1)
  272. {
  273. Stuff::Point3D p2 = p1;
  274. p2 += segVect;
  275. bool p2IsInView = isInView(p2);
  276. if (p1IsInView || p2IsInView)
  277. {
  278. Stuff::Vector4D screenPos1;
  279. eye->projectZ( p1, screenPos1 );
  280. Stuff::Vector4D screenPos2;
  281. eye->projectZ( p2, screenPos2 );
  282. Stuff::Vector4D vertices[2];
  283. vertices[0].x = screenPos1.x;
  284. vertices[0].y = screenPos1.y;
  285. vertices[1].x = screenPos2.x;
  286. vertices[1].y = screenPos2.y;
  287. vertices[0].z = vertices[1].z = 0.1f;
  288. vertices[0].w = vertices[1].w = 0.9999f;
  289. LineElement elem( vertices[0], vertices[1], 0xffff0000, 0, -1 );
  290. elem.draw();
  291. }
  292. p1 = p2;
  293. p1IsInView = p2IsInView;
  294. }
  295. }
  296. }
  297. void BuildingLink::SetParentAlignment( int alignment )
  298. {
  299. EditorObject* pTmp = EditorObjectMgr::instance()->getObjectAtLocation( parent.pos.x, parent.pos.y );
  300. if ( pTmp )
  301. pTmp->setAlignment( alignment ) ;
  302. else
  303. {
  304. gosASSERT(false);
  305. }
  306. for ( EList<Info, const Info& >::EConstIterator iter = children.Begin();
  307. !iter.IsDone(); iter++ )
  308. {
  309. pTmp = EditorObjectMgr::instance()->getObjectAtLocation( (*iter).pos.x, (*iter).pos.y ) ;
  310. if ( pTmp )
  311. pTmp->setAlignment( alignment );
  312. else
  313. {
  314. gosASSERT(false);
  315. }
  316. }
  317. }
  318. void BuildingLink::FixHeights()
  319. {
  320. parent.pos.z = land->getTerrainElevation( parent.pos );
  321. for ( EList<Info, const Info& >::EIterator iter = children.Begin();
  322. !iter.IsDone(); iter++ )
  323. {
  324. (*iter).pos.z = land->getTerrainElevation((*iter).pos );
  325. }
  326. }
  327. void BuildingLink::SetParentPosition( const Stuff::Vector3D& pos )
  328. {
  329. parent.pos = pos;
  330. }