coverPoint.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2014 Daniel Buckmaster
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "coverPoint.h"
  23. #include "math/mathIO.h"
  24. #include "scene/sceneRenderState.h"
  25. #include "core/stream/bitStream.h"
  26. #include "materials/sceneData.h"
  27. #include "gfx/gfxDebugEvent.h"
  28. #include "gfx/gfxTransformSaver.h"
  29. #include "gfx/gfxDrawUtil.h"
  30. #include "renderInstance/renderPassManager.h"
  31. #include "console/engineAPI.h"
  32. #include "T3D/gameBase/gameConnection.h"
  33. extern bool gEditingMission;
  34. IMPLEMENT_CO_NETOBJECT_V1(CoverPoint);
  35. ConsoleDocClass(CoverPoint,
  36. "@brief A type of marker that designates a location AI characters can take cover.\n\n"
  37. );
  38. ImplementEnumType(CoverPointSize,
  39. "The size of a cover point.\n")
  40. { CoverPoint::Prone, "Prone", "Only provides cover when prone.\n" },
  41. { CoverPoint::Crouch, "Crouch", "Only provides cover when crouching.\n" },
  42. { CoverPoint::Stand, "Stand", "Provides cover when standing.\n" },
  43. EndImplementEnumType;
  44. //-----------------------------------------------------------------------------
  45. // Object setup and teardown
  46. //-----------------------------------------------------------------------------
  47. CoverPoint::CoverPoint()
  48. {
  49. mNetFlags.clear(Ghostable);
  50. mTypeMask |= MarkerObjectType;
  51. mSize = Stand;
  52. mQuality = 1.0f;
  53. mOccupied = false;
  54. mPeekLeft = false;
  55. mPeekRight = false;
  56. mPeekOver = false;
  57. }
  58. CoverPoint::~CoverPoint()
  59. {
  60. }
  61. //-----------------------------------------------------------------------------
  62. // Object Editing
  63. //-----------------------------------------------------------------------------
  64. void CoverPoint::initPersistFields()
  65. {
  66. docsURL;
  67. addGroup("CoverPoint");
  68. addField("size", TYPEID<CoverPointSize>(), Offset(mSize, CoverPoint),
  69. "The size of this cover point.");
  70. addFieldV("quality", TypeRangedF32, Offset(mQuality, CoverPoint), &CommonValidators::NormalizedFloat,
  71. "Reliability of this point as solid cover. (0...1)");
  72. addField("peekLeft", TypeBool, Offset(mPeekLeft, CoverPoint),
  73. "Can characters look left around this cover point?");
  74. addField("peekRight", TypeBool, Offset(mPeekRight, CoverPoint),
  75. "Can characters look right around this cover point?");
  76. addField("peekOver", TypeBool, Offset(mPeekOver, CoverPoint),
  77. "Can characters look over the top of this cover point?");
  78. endGroup("CoverPoint");
  79. Parent::initPersistFields();
  80. }
  81. bool CoverPoint::onAdd()
  82. {
  83. if(!Parent::onAdd())
  84. return false;
  85. // Set up a 1x1x1 bounding box
  86. mObjBox.set(Point3F(-0.5f, -0.5f, -0.5f),
  87. Point3F( 0.5f, 0.5f, 0.5f));
  88. resetWorldBox();
  89. if(gEditingMission)
  90. onEditorEnable();
  91. addToScene();
  92. return true;
  93. }
  94. void CoverPoint::onRemove()
  95. {
  96. if(gEditingMission)
  97. onEditorDisable();
  98. removeFromScene();
  99. Parent::onRemove();
  100. for(U32 i = 0; i < NumSizes; i++)
  101. smVertexBuffer[i] = NULL;
  102. }
  103. void CoverPoint::setTransform(const MatrixF & mat)
  104. {
  105. Parent::setTransform(mat);
  106. setMaskBits(TransformMask);
  107. }
  108. void CoverPoint::onEditorEnable()
  109. {
  110. mNetFlags.set(Ghostable);
  111. }
  112. void CoverPoint::onEditorDisable()
  113. {
  114. mNetFlags.clear(Ghostable);
  115. }
  116. void CoverPoint::inspectPostApply()
  117. {
  118. setMaskBits(TransformMask);
  119. }
  120. U32 CoverPoint::packUpdate(NetConnection *conn, U32 mask, BitStream *stream)
  121. {
  122. U32 retMask = Parent::packUpdate(conn, mask, stream);
  123. stream->writeInt(mSize, 4);
  124. stream->writeFlag(mOccupied);
  125. stream->writeFlag(peekLeft());
  126. stream->writeFlag(peekRight());
  127. stream->writeFlag(peekOver());
  128. // Write our transform information
  129. if(stream->writeFlag(mask & TransformMask))
  130. {
  131. mathWrite(*stream, getTransform());
  132. mathWrite(*stream, getScale());
  133. }
  134. return retMask;
  135. }
  136. void CoverPoint::unpackUpdate(NetConnection *conn, BitStream *stream)
  137. {
  138. Parent::unpackUpdate(conn, stream);
  139. mSize = (Size)stream->readInt(4);
  140. setOccupied(stream->readFlag());
  141. mPeekLeft = stream->readFlag();
  142. mPeekRight = stream->readFlag();
  143. mPeekOver = stream->readFlag();
  144. if(stream->readFlag()) // TransformMask
  145. {
  146. mathRead(*stream, &mObjToWorld);
  147. mathRead(*stream, &mObjScale);
  148. setTransform(mObjToWorld);
  149. }
  150. }
  151. //-----------------------------------------------------------------------------
  152. // Functionality
  153. //-----------------------------------------------------------------------------
  154. Point3F CoverPoint::getNormal() const
  155. {
  156. return getTransform().getForwardVector();
  157. }
  158. DefineEngineMethod(CoverPoint, isOccupied, bool, (),,
  159. "@brief Returns true if someone is already using this cover point.")
  160. {
  161. return object->isOccupied();
  162. }
  163. //-----------------------------------------------------------------------------
  164. // Object Rendering
  165. //-----------------------------------------------------------------------------
  166. GFXStateBlockRef CoverPoint::smNormalSB;
  167. GFXVertexBufferHandle<CoverPoint::VertexType> CoverPoint::smVertexBuffer[CoverPoint::NumSizes];
  168. void CoverPoint::initGFXResources()
  169. {
  170. if(smVertexBuffer[0] != NULL)
  171. return;
  172. static const Point3F planePoints[4] =
  173. {
  174. Point3F(-1.0f, 0.0f, 0.0f), Point3F(-1.0f, 0.0f, 2.0f),
  175. Point3F( 1.0f, 0.0f, 0.0f), Point3F( 1.0f, 0.0f, 2.0f),
  176. };
  177. static const U32 planeFaces[6] =
  178. {
  179. 0, 1, 2,
  180. 1, 2, 3
  181. };
  182. static const Point3F scales[NumSizes] =
  183. {
  184. Point3F(1.0f, 1.0f, 0.5f), // Prone
  185. Point3F(1.0f, 1.0f, 1.0f), // Crouch
  186. Point3F(1.0f, 1.0f, 2.0f) // Stand
  187. };
  188. static const ColorI colours[NumSizes] =
  189. {
  190. ColorI(180, 0, 0, 128), // Prone
  191. ColorI(250, 200, 90, 128), // Crouch
  192. ColorI( 80, 190, 20, 128) // Stand
  193. };
  194. for(U32 i = 0; i < NumSizes; i++)
  195. {
  196. // Fill the vertex buffer
  197. VertexType *pVert = NULL;
  198. smVertexBuffer[i].set(GFX, 6, GFXBufferTypeStatic);
  199. pVert = smVertexBuffer[i].lock();
  200. for(U32 j = 0; j < 6; j++)
  201. {
  202. pVert[j].point = planePoints[planeFaces[j]] * scales[i] * 0.5f;
  203. pVert[j].normal = Point3F(0.0f, -1.0f, 0.0f);
  204. pVert[j].color = colours[i];
  205. }
  206. smVertexBuffer[i].unlock();
  207. }
  208. // Set up our StateBlock
  209. GFXStateBlockDesc desc;
  210. desc.cullDefined = true;
  211. desc.cullMode = GFXCullNone;
  212. desc.setBlend(true);
  213. smNormalSB = GFX->createStateBlock(desc);
  214. }
  215. void CoverPoint::prepRenderImage(SceneRenderState *state)
  216. {
  217. // Allocate an ObjectRenderInst so that we can submit it to the RenderPassManager
  218. ObjectRenderInst *ri = state->getRenderPass()->allocInst<ObjectRenderInst>();
  219. // Now bind our rendering function so that it will get called
  220. ri->renderDelegate.bind(this, &CoverPoint::render);
  221. // Set our RenderInst as a standard object render
  222. ri->type = RenderPassManager::RIT_Editor;
  223. // Set our sorting keys to a default value
  224. ri->defaultKey = 0;
  225. ri->defaultKey2 = 0;
  226. // Submit our RenderInst to the RenderPassManager
  227. state->getRenderPass()->addInst(ri);
  228. }
  229. void CoverPoint::render(ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat)
  230. {
  231. if (!state->isDiffusePass()) return;
  232. GameConnection* conn = GameConnection::getConnectionToServer();
  233. MatrixF camTrans;
  234. conn->getControlCameraTransform(0, &camTrans);
  235. if ((getPosition() - camTrans.getPosition()).lenSquared() > 2500) return; //50 unit clamp
  236. if (overrideMat)
  237. return;
  238. initGFXResources();
  239. if(smVertexBuffer[mSize].isNull())
  240. return;
  241. PROFILE_SCOPE(CoverPoint_Render);
  242. // Set up a GFX debug event (this helps with debugging rendering events in external tools)
  243. GFXDEBUGEVENT_SCOPE(CoverPoint_Render, ColorI::RED);
  244. // GFXTransformSaver is a handy helper class that restores
  245. // the current GFX matrices to their original values when
  246. // it goes out of scope at the end of the function
  247. GFXTransformSaver saver;
  248. // Calculate our object to world transform matrix
  249. MatrixF objectToWorld = getRenderTransform();
  250. objectToWorld.scale(getScale());
  251. // Apply our object transform
  252. GFX->multWorld(objectToWorld);
  253. // Set the state block
  254. GFX->setStateBlock(smNormalSB);
  255. // Set up the "generic" shaders
  256. // These handle rendering on GFX layers that don't support
  257. // fixed function. Otherwise they disable shaders.
  258. GFX->setupGenericShaders(GFXDevice::GSModColorTexture);
  259. // Set the vertex buffer
  260. GFX->setVertexBuffer(smVertexBuffer[mSize]);
  261. // Draw our triangles
  262. GFX->drawPrimitive(GFXTriangleList, 0, 2);
  263. // Data for decorations.
  264. GFXStateBlockDesc desc;
  265. F32 height = (float)(mSize + 1) / (F32)NumSizes * 2.0f;
  266. // Draw an X if we're occupied.
  267. if(isOccupied())
  268. {
  269. GFX->getDrawUtil()->drawArrow(desc, Point3F(-0.5, 0, 0), Point3F(0.5, 0, height), ColorI::RED);
  270. GFX->getDrawUtil()->drawArrow(desc, Point3F(0.5, 0, 0), Point3F(-0.5, 0, height), ColorI::RED);
  271. }
  272. // Draw arrows to represent peek directions.
  273. if(peekLeft())
  274. GFX->getDrawUtil()->drawArrow(desc, Point3F(0, 0, height * 0.5), Point3F(-0.5, 0, height * 0.5), ColorI::GREEN);
  275. if(peekRight())
  276. GFX->getDrawUtil()->drawArrow(desc, Point3F(0, 0, height * 0.5), Point3F(0.5, 0, height * 0.5), ColorI::GREEN);
  277. if(peekOver())
  278. GFX->getDrawUtil()->drawArrow(desc, Point3F(0, 0, height * 0.5), Point3F(0, 0, height), ColorI::GREEN);
  279. }