VolumeNode.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. //
  2. // Urho3D Engine
  3. // Copyright (c) 2008-2011 Lasse Öörni
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6. // of this software and associated documentation files (the "Software"), to deal
  7. // in the Software without restriction, including without limitation the rights
  8. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. // copies of the Software, and to permit persons to whom the Software is
  10. // furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in
  13. // all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. // THE SOFTWARE.
  22. //
  23. #include "Precompiled.h"
  24. #include "Camera.h"
  25. #include "DebugRenderer.h"
  26. #include "Octree.h"
  27. #include "OctreeQuery.h"
  28. #include "ReplicationUtils.h"
  29. #include "XMLElement.h"
  30. #include "DebugNew.h"
  31. VolumeNode::VolumeNode(unsigned flags, Octant* octant, const std::string& name) :
  32. Node(flags, name),
  33. mOctant(0),
  34. mCastShadows(false),
  35. mOccluder(false),
  36. mVisible(true),
  37. mDrawDistance(0.0f),
  38. mShadowDistance(0.0f),
  39. mViewMask(VIEW_ALL),
  40. mLightMask(VIEW_ALL),
  41. mDistance(0.0f),
  42. mSortValue(0.0f),
  43. mViewFrameNumber(M_MAX_UNSIGNED),
  44. mViewCamera(0),
  45. mWorldBoundingBoxDirty(true)
  46. {
  47. // Insert initially into the specified octant; the node does not have correct
  48. // bounding box size yet, so it will be moved in any case
  49. if (octant)
  50. {
  51. octant->addNode(this);
  52. octant->getRoot()->markNodeForReinsertion(this);
  53. }
  54. }
  55. VolumeNode::~VolumeNode()
  56. {
  57. // If was in octree and is being deleted now, make sure to clear any reference in the update/reinsertion lists
  58. if (mOctant)
  59. {
  60. Octree* octree = mOctant->getRoot();
  61. octree->clearNodeUpdate(this);
  62. octree->clearNodeReinsertion(this);
  63. mOctant->removeNode(this);
  64. }
  65. }
  66. void VolumeNode::save(Serializer& dest)
  67. {
  68. // Write Node properties
  69. Node::save(dest);
  70. // Write VolumeNode properties
  71. dest.writeBool(mCastShadows);
  72. dest.writeBool(mOccluder);
  73. dest.writeBool(mVisible);
  74. dest.writeFloat(mDrawDistance);
  75. dest.writeFloat(mShadowDistance);
  76. dest.writeUInt(mViewMask);
  77. dest.writeUInt(mLightMask);
  78. }
  79. void VolumeNode::load(Deserializer& source, ResourceCache* cache)
  80. {
  81. // Read Node properties
  82. Node::load(source, cache);
  83. // Read VolumeNode properties
  84. mCastShadows = source.readBool();
  85. mOccluder = source.readBool();
  86. mVisible = source.readBool();
  87. mDrawDistance = source.readFloat();
  88. mShadowDistance = source.readFloat();
  89. mViewMask = source.readUInt();
  90. mLightMask = source.readUInt();
  91. }
  92. void VolumeNode::saveXML(XMLElement& dest)
  93. {
  94. // Write Node properties
  95. Node::saveXML(dest);
  96. // Write VolumeNode properties
  97. XMLElement renderElem = dest.createChildElement("render");
  98. renderElem.setBool("castshadows", mCastShadows);
  99. renderElem.setBool("occluder", mOccluder);
  100. renderElem.setBool("visible", mVisible);
  101. XMLElement lodElem = dest.createChildElement("lod");
  102. lodElem.setFloat("drawdistance", mDrawDistance);
  103. lodElem.setFloat("shadowdistance", mShadowDistance);
  104. lodElem.setInt("viewmask", mViewMask);
  105. lodElem.setInt("lightmask", mLightMask);
  106. }
  107. void VolumeNode::loadXML(const XMLElement& source, ResourceCache* cache)
  108. {
  109. // Read Node properties
  110. Node::loadXML(source, cache);
  111. // Read VolumeNode properties
  112. XMLElement renderElem = source.getChildElement("render");
  113. mCastShadows = renderElem.getBool("castshadows");
  114. mOccluder = renderElem.getBool("occluder");
  115. mVisible = renderElem.getBool("visible");
  116. XMLElement lodElem = source.getChildElement("lod");
  117. mDrawDistance = lodElem.getFloat("drawdistance");
  118. mShadowDistance = lodElem.getFloat("shadowdistance");
  119. mViewMask = lodElem.getInt("viewmask");
  120. mLightMask = lodElem.getInt("lightmask");
  121. }
  122. bool VolumeNode::writeNetUpdate(Serializer& dest, Serializer& destRevision, Deserializer& baseRevision, const NetUpdateInfo& info)
  123. {
  124. // Use possibly modified transform in case the parent component is not to be replicated
  125. Vector3 position;
  126. Quaternion rotation;
  127. Vector3 scale;
  128. ComponentRef parentRef;
  129. getNetTransform(position, rotation, scale, parentRef, info);
  130. // Build bitmask of changed properties
  131. unsigned char bits = 0;
  132. checkVector3(position, Vector3::sZero, baseRevision, bits, 1);
  133. checkQuaternion(rotation, Quaternion::sIdentity, baseRevision, bits, 2);
  134. checkVector3(scale, Vector3::sUnity, baseRevision, bits, 4);
  135. checkComponentRef(parentRef, ComponentRef(), baseRevision, bits, 8);
  136. checkBool(mCastShadows, false, baseRevision, bits, 16);
  137. checkBool(mOccluder, false, baseRevision, bits, 16);
  138. checkBool(mVisible, true, baseRevision, bits, 16);
  139. checkFloat(mDrawDistance, 0.0f, baseRevision, bits, 32);
  140. checkFloat(mShadowDistance, 0.0f, baseRevision, bits, 32);
  141. checkUInt(mViewMask, VIEW_ALL, baseRevision, bits, 64);
  142. checkUInt(mLightMask, VIEW_ALL, baseRevision, bits, 64);
  143. // Update replication state fully, and network stream by delta
  144. dest.writeUByte(bits);
  145. writeVector3Delta(position, dest, destRevision, bits & 1);
  146. writePackedQuaternionDelta(rotation, dest, destRevision, bits & 2);
  147. writeVector3Delta(scale, dest, destRevision, bits & 4);
  148. writeComponentRefDelta(parentRef, dest, destRevision, bits & 8);
  149. writeBoolDelta(mCastShadows, dest, destRevision, bits & 16);
  150. writeBoolDelta(mOccluder, dest, destRevision, bits & 16);
  151. writeBoolDelta(mVisible, dest, destRevision, bits & 16);
  152. writeFloatDelta(mDrawDistance, dest, destRevision, bits & 32);
  153. writeFloatDelta(mShadowDistance, dest, destRevision, bits & 32);
  154. writeUIntDelta(mViewMask, dest, destRevision, bits & 64);
  155. writeUIntDelta(mLightMask, dest, destRevision, bits & 64);
  156. return bits != 0;
  157. }
  158. void VolumeNode::readNetUpdate(Deserializer& source, ResourceCache* cache, const NetUpdateInfo& info)
  159. {
  160. unsigned char bits = source.readUByte();
  161. // Interpolate if just position/rotation/scale changes, snap if parent changes
  162. bool interpolate = (bits & 7) && (!(bits & 8));
  163. if (!interpolate)
  164. {
  165. if (bits & 1)
  166. setPosition(source.readVector3());
  167. if (bits & 2)
  168. setRotation(source.readPackedQuaternion());
  169. if (bits & 4)
  170. setScale(source.readVector3());
  171. }
  172. else
  173. {
  174. if (bits & 1)
  175. {
  176. mInterpolationPosition = source.readVector3();
  177. mInterpolationFlags |= INTERP_POS;
  178. }
  179. if (bits & 2)
  180. {
  181. mInterpolationRotation = source.readPackedQuaternion();
  182. mInterpolationFlags |= INTERP_ROT;
  183. }
  184. if (bits & 4)
  185. {
  186. mInterpolationScale = source.readVector3();
  187. mInterpolationFlags |= INTERP_SCALE;
  188. }
  189. }
  190. readComponentRefDelta(mParentRef, source, bits & 8);
  191. readBoolDelta(mCastShadows, source, bits & 16);
  192. readBoolDelta(mOccluder, source, bits & 16);
  193. readBoolDelta(mVisible, source, bits & 16);
  194. readFloatDelta(mDrawDistance, source, bits & 32);
  195. readFloatDelta(mShadowDistance, source, bits & 32);
  196. readUIntDelta(mViewMask, source, bits & 64);
  197. readUIntDelta(mLightMask, source, bits & 64);
  198. }
  199. void VolumeNode::updateNode(const FrameInfo& frame)
  200. {
  201. }
  202. void VolumeNode::updateDistance(const FrameInfo& frame)
  203. {
  204. mDistance = frame.mCamera->getDistance(getWorldPosition());
  205. }
  206. void VolumeNode::overrideTransforms(unsigned batchIndex, Camera& camera, const Matrix4x3** model, const Matrix4x3** view)
  207. {
  208. }
  209. void VolumeNode::processRayQuery(RayOctreeQuery& query, float initialDistance)
  210. {
  211. // By default just store the result from the bounding box raycast
  212. RayQueryResult result;
  213. result.mNode = this;
  214. result.mDistance = initialDistance;
  215. query.mResult.push_back(result);
  216. }
  217. void VolumeNode::drawDebugGeometry(DebugRenderer* debug)
  218. {
  219. debug->addBoundingBox(getWorldBoundingBox(), Color(0.0f, 1.0f, 0.0f), false);
  220. }
  221. void VolumeNode::setCastShadows(bool enable)
  222. {
  223. mCastShadows = enable;
  224. }
  225. void VolumeNode::setOccluder(bool enable)
  226. {
  227. mOccluder = enable;
  228. }
  229. void VolumeNode::setVisible(bool visible)
  230. {
  231. mVisible = visible;
  232. }
  233. void VolumeNode::setDrawDistance(float distance)
  234. {
  235. mDrawDistance = max(distance, 0.0f);
  236. }
  237. void VolumeNode::setShadowDistance(float distance)
  238. {
  239. mShadowDistance = max(distance, 0.0f);
  240. }
  241. void VolumeNode::setViewMask(unsigned mask)
  242. {
  243. mViewMask = mask;
  244. }
  245. void VolumeNode::setLightMask(unsigned mask)
  246. {
  247. mLightMask = mask;
  248. }
  249. float VolumeNode::calculateDrawDistance(const Camera& camera, float minScreenSize)
  250. {
  251. const BoundingBox& box = getWorldBoundingBox();
  252. float diagonal = (box.mMax - box.mMin).getLengthFast();
  253. float halfViewSize = camera.getHalfViewSize();
  254. return diagonal * halfViewSize / minScreenSize;
  255. }
  256. const BoundingBox& VolumeNode::getWorldBoundingBox()
  257. {
  258. if (mWorldBoundingBoxDirty)
  259. {
  260. onWorldBoundingBoxUpdate(mWorldBoundingBox);
  261. mWorldBoundingBoxDirty = false;
  262. }
  263. return mWorldBoundingBox;
  264. }
  265. void VolumeNode::markInView(const FrameInfo& frame)
  266. {
  267. mViewFrameNumber = frame.mFrameNumber;
  268. mViewCamera = frame.mCamera;
  269. }
  270. void VolumeNode::markInShadowView(const FrameInfo& frame)
  271. {
  272. if (mViewFrameNumber != frame.mFrameNumber)
  273. {
  274. mViewFrameNumber = frame.mFrameNumber;
  275. mViewCamera = 0;
  276. }
  277. }
  278. void VolumeNode::setSortValue(float value)
  279. {
  280. mSortValue = value;
  281. }
  282. bool VolumeNode::isInView(unsigned frameNumber) const
  283. {
  284. return mViewFrameNumber == frameNumber;
  285. }
  286. bool VolumeNode::isInView(const FrameInfo& frame) const
  287. {
  288. return (mViewFrameNumber == frame.mFrameNumber) && (mViewCamera == frame.mCamera);
  289. }
  290. void VolumeNode::onMarkedDirty()
  291. {
  292. mWorldBoundingBoxDirty = true;
  293. if (mOctant)
  294. mOctant->getRoot()->markNodeForReinsertion(this);
  295. }
  296. void VolumeNode::markForUpdate()
  297. {
  298. if (mOctant)
  299. mOctant->getRoot()->markNodeForUpdate(this);
  300. }