AGCVector.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501
  1. /////////////////////////////////////////////////////////////////////////////
  2. // AGCVector.cpp : Implementation of CAGCVector
  3. //
  4. #include "pch.h"
  5. #include "AGCVector.h"
  6. /////////////////////////////////////////////////////////////////////////////
  7. // CVector
  8. TC_OBJECT_EXTERN_IMPL(CAGCVector)
  9. /////////////////////////////////////////////////////////////////////////////
  10. // Implementation
  11. HRESULT CAGCVector::GetRawVector(IAGCVector* pVector, Vector* pVectorRaw)
  12. {
  13. __try
  14. {
  15. if (!pVector)
  16. return E_POINTER;
  17. IAGCVectorPrivate* pPrivate = NULL;
  18. RETURN_FAILED(pVector->QueryInterface(__uuidof(pPrivate), (void**)&pPrivate));
  19. assert(pPrivate);
  20. if (!pPrivate)
  21. return E_INVALIDARG;
  22. HRESULT hr = pPrivate->CopyVectorTo(pVectorRaw);
  23. pPrivate->Release();
  24. return hr;
  25. }
  26. __except(1)
  27. {
  28. return E_POINTER;
  29. }
  30. }
  31. HRESULT CAGCVector::CreateResultVector(const Vector* pVectorRaw,
  32. IAGCVector** ppResult)
  33. {
  34. CComObject<CAGCVector>* pVector = NULL;
  35. RETURN_FAILED(pVector->CreateInstance(&pVector));
  36. IAGCVectorPtr spVector(pVector);
  37. RETURN_FAILED(pVector->InitFromVector(pVectorRaw));
  38. CLEAROUT(ppResult, (IAGCVector*)spVector);
  39. spVector.Detach();
  40. return S_OK;
  41. }
  42. /////////////////////////////////////////////////////////////////////////////
  43. // ISupportErrorInfo Interface Methods
  44. STDMETHODIMP CAGCVector::InterfaceSupportsErrorInfo(REFIID riid)
  45. {
  46. static const IID* arr[] =
  47. {
  48. &IID_IAGCVector
  49. };
  50. for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++)
  51. {
  52. if (InlineIsEqualGUID(*arr[i],riid))
  53. return S_OK;
  54. }
  55. return S_FALSE;
  56. }
  57. /////////////////////////////////////////////////////////////////////////////
  58. // IPersist Interface Methods
  59. STDMETHODIMP CAGCVector::GetClassID(CLSID* pClassID)
  60. {
  61. __try
  62. {
  63. *pClassID = GetObjectCLSID();
  64. }
  65. __except(1)
  66. {
  67. return E_POINTER;
  68. }
  69. return S_OK;
  70. }
  71. /////////////////////////////////////////////////////////////////////////////
  72. // IPersistStreamInit Interface Methods
  73. STDMETHODIMP CAGCVector::IsDirty()
  74. {
  75. // Return dirty flag
  76. XLock lock(this);
  77. return m_bDirty ? S_OK : S_FALSE;
  78. }
  79. STDMETHODIMP CAGCVector::Load(LPSTREAM pStm)
  80. {
  81. // Read the number of floats being read
  82. long cDims;
  83. RETURN_FAILED(pStm->Read(&cDims, sizeof(cDims), NULL));
  84. if (DIMENSIONS != cDims)
  85. {
  86. assert(DIMENSIONS == cDims);
  87. return ERROR_INVALID_DATA;
  88. }
  89. // Read each float from the stream
  90. float xArg, yArg, zArg;
  91. RETURN_FAILED(pStm->Read(&xArg, sizeof(xArg), NULL));
  92. RETURN_FAILED(pStm->Read(&yArg, sizeof(yArg), NULL));
  93. RETURN_FAILED(pStm->Read(&zArg, sizeof(zArg), NULL));
  94. // Save the values
  95. return InitXYZ(xArg, yArg, zArg);
  96. }
  97. STDMETHODIMP CAGCVector::Save(LPSTREAM pStm, BOOL fClearDirty)
  98. {
  99. // Write out the number of floats being written
  100. long cDims = DIMENSIONS;
  101. RETURN_FAILED(pStm->Write(&cDims, sizeof(cDims), NULL));
  102. // Write each float to the stream
  103. XLock lock(this);
  104. float xArg = m_vector.X(), yArg = m_vector.Y(), zArg = m_vector.Z();
  105. RETURN_FAILED(pStm->Write(&xArg, sizeof(xArg), NULL));
  106. RETURN_FAILED(pStm->Write(&yArg, sizeof(yArg), NULL));
  107. RETURN_FAILED(pStm->Write(&zArg, sizeof(zArg), NULL));
  108. // Clear the dirty flag, if specified
  109. if (fClearDirty)
  110. m_bDirty = false;
  111. // Indicate success
  112. return S_OK;
  113. }
  114. STDMETHODIMP CAGCVector::GetSizeMax(ULARGE_INTEGER* pCbSize)
  115. {
  116. __try
  117. {
  118. // NOTE: This needs to exactly match what's written in Save
  119. pCbSize->LowPart = sizeof(long) + sizeof(float) * DIMENSIONS;
  120. pCbSize->HighPart = 0;
  121. }
  122. __except(1)
  123. {
  124. return E_POINTER;
  125. }
  126. // Indicate success
  127. return S_OK;
  128. }
  129. STDMETHODIMP CAGCVector::InitNew( void)
  130. {
  131. // Initialize the vector object
  132. XLock lock(this);
  133. m_vector = Vector::GetZero();
  134. // Indicate success
  135. return S_OK;
  136. }
  137. /////////////////////////////////////////////////////////////////////////////
  138. // IPersistPropertyBag Interface Methods
  139. STDMETHODIMP CAGCVector::Load(IPropertyBag* pPropBag, IErrorLog* pErrorLog)
  140. {
  141. // Load each dimension (column) of the vector object
  142. CComVariant varX(0.f), varY(0.f), varZ(0.f);
  143. RETURN_FAILED(pPropBag->Read(L"X", &varX, pErrorLog));
  144. RETURN_FAILED(pPropBag->Read(L"Y", &varY, pErrorLog));
  145. RETURN_FAILED(pPropBag->Read(L"Z", &varZ, pErrorLog));
  146. // Save the values
  147. return InitXYZ(V_R4(&varX), V_R4(&varY), V_R4(&varZ));
  148. }
  149. STDMETHODIMP CAGCVector::Save(IPropertyBag* pPropBag, BOOL fClearDirty, BOOL)
  150. {
  151. // Save each dimension (column) of the vector object
  152. XLock lock(this);
  153. RETURN_FAILED(pPropBag->Write(L"X", &CComVariant(m_vector.X())));
  154. RETURN_FAILED(pPropBag->Write(L"Y", &CComVariant(m_vector.Y())));
  155. RETURN_FAILED(pPropBag->Write(L"Z", &CComVariant(m_vector.Z())));
  156. // Clear the dirty flag, if specified
  157. if (fClearDirty)
  158. m_bDirty = false;
  159. // Indicate success
  160. return S_OK;
  161. }
  162. /////////////////////////////////////////////////////////////////////////////
  163. // IAGCVector Interface Methods
  164. STDMETHODIMP CAGCVector::put_X(float Val)
  165. {
  166. XLock lock(this);
  167. if (m_vector.X() != Val)
  168. {
  169. m_vector.SetX(Val);
  170. m_bDirty = true;
  171. }
  172. return S_OK;
  173. }
  174. STDMETHODIMP CAGCVector::get_X(float* pVal)
  175. {
  176. XLock lock(this);
  177. CLEAROUT(pVal, m_vector.X());
  178. return S_OK;
  179. }
  180. STDMETHODIMP CAGCVector::put_Y(float Val)
  181. {
  182. XLock lock(this);
  183. if (m_vector.Y() != Val)
  184. {
  185. m_vector.SetY(Val);
  186. m_bDirty = true;
  187. }
  188. return S_OK;
  189. }
  190. STDMETHODIMP CAGCVector::get_Y(float* pVal)
  191. {
  192. XLock lock(this);
  193. CLEAROUT(pVal, m_vector.Y());
  194. return S_OK;
  195. }
  196. STDMETHODIMP CAGCVector::put_Z(float Val)
  197. {
  198. XLock lock(this);
  199. if (m_vector.Z() != Val)
  200. {
  201. m_vector.SetZ(Val);
  202. m_bDirty = true;
  203. }
  204. return S_OK;
  205. }
  206. STDMETHODIMP CAGCVector::get_Z(float* pVal)
  207. {
  208. XLock lock(this);
  209. CLEAROUT(pVal, m_vector.Z());
  210. return S_OK;
  211. }
  212. STDMETHODIMP CAGCVector::put_DisplayString(BSTR bstrDisplayString)
  213. {
  214. // Invalid if string is empty
  215. if (!BSTRLen(bstrDisplayString))
  216. return E_INVALIDARG;
  217. // Load the format string
  218. CComBSTR bstrFmt;
  219. if (!bstrFmt.LoadString(IDS_FMT_VECTOR))
  220. return HRESULT_FROM_WIN32(::GetLastError());
  221. // Extract the values from the string
  222. float xArg, yArg, zArg;
  223. if (3 != swscanf(bstrDisplayString, bstrFmt, &xArg, &yArg, &zArg))
  224. return E_INVALIDARG;
  225. // Save the values
  226. return InitXYZ(xArg, yArg, zArg);
  227. }
  228. STDMETHODIMP CAGCVector::get_DisplayString(BSTR* pbstrDisplayString)
  229. {
  230. // Load the format string
  231. CComBSTR bstrFmt;
  232. if (!bstrFmt.LoadString(IDS_FMT_VECTOR))
  233. return HRESULT_FROM_WIN32(::GetLastError());
  234. // Format the string
  235. XLock lock(this);
  236. OLECHAR szText[_MAX_PATH];
  237. swprintf(szText, bstrFmt, m_vector.X(), m_vector.Y(), m_vector.Z());
  238. // Detach the string to the [out] parameter
  239. CComBSTR bstr(szText);
  240. CLEAROUT(pbstrDisplayString, (BSTR)bstr);
  241. bstr.Detach();
  242. // Indicate success
  243. return S_OK;
  244. }
  245. STDMETHODIMP CAGCVector::InitXYZ(float xArg, float yArg, float zArg)
  246. {
  247. XLock lock(this);
  248. if (m_vector.X() != xArg || m_vector.Y() != yArg || m_vector.Z() != zArg)
  249. {
  250. m_vector.SetX(xArg);
  251. m_vector.SetY(yArg);
  252. m_vector.SetZ(zArg);
  253. m_bDirty = true;
  254. }
  255. return S_OK;
  256. }
  257. STDMETHODIMP CAGCVector::InitCopy(IAGCVector* pVector)
  258. {
  259. // Get the values of the specified vector
  260. float xArg, yArg, zArg;
  261. RETURN_FAILED(pVector->get_X(&xArg));
  262. RETURN_FAILED(pVector->get_Y(&yArg));
  263. RETURN_FAILED(pVector->get_Z(&zArg));
  264. // Save the values
  265. return InitXYZ(xArg, yArg, zArg);
  266. }
  267. STDMETHODIMP CAGCVector::InitRandomDirection()
  268. {
  269. // Create a random direction
  270. return InitFromVector(&Vector::RandomDirection());
  271. }
  272. STDMETHODIMP CAGCVector::InitRandomPosition(float fRadius)
  273. {
  274. // Create a random position
  275. return InitFromVector(&Vector::RandomPosition(fRadius));
  276. }
  277. STDMETHODIMP CAGCVector::get_IsZero(VARIANT_BOOL* pbIsZero)
  278. {
  279. XLock lock(this);
  280. CLEAROUT(pbIsZero, VARBOOL(m_vector.IsZero()));
  281. return S_OK;
  282. }
  283. STDMETHODIMP CAGCVector::get_IsEqual(IAGCVector* pVector,
  284. VARIANT_BOOL* pbIsEqual)
  285. {
  286. Vector vector;
  287. RETURN_FAILED(GetRawVector(pVector, &vector));
  288. XLock lock(this);
  289. CLEAROUT(pbIsEqual, VARBOOL(vector == m_vector));
  290. return S_OK;
  291. }
  292. STDMETHODIMP CAGCVector::get_Length(float* pfLength)
  293. {
  294. XLock lock(this);
  295. CLEAROUT(pfLength, m_vector.Length());
  296. return S_OK;
  297. }
  298. STDMETHODIMP CAGCVector::get_LengthSquared(float* pfLengthSquared)
  299. {
  300. XLock lock(this);
  301. CLEAROUT(pfLengthSquared, m_vector.LengthSquared());
  302. return S_OK;
  303. }
  304. STDMETHODIMP CAGCVector::get_OrthogonalVector(IAGCVector** ppResult)
  305. {
  306. XLock lock(this);
  307. return CreateResultVector(&m_vector.GetOrthogonalVector(), ppResult);
  308. }
  309. STDMETHODIMP CAGCVector::Add(IAGCVector* pVector, IAGCVector** ppResult)
  310. {
  311. Vector vector;
  312. RETURN_FAILED(GetRawVector(pVector, &vector));
  313. XLock lock(this);
  314. return CreateResultVector(&(m_vector + vector), ppResult);
  315. }
  316. STDMETHODIMP CAGCVector::Subtract(IAGCVector* pVector, IAGCVector** ppResult)
  317. {
  318. Vector vector;
  319. RETURN_FAILED(GetRawVector(pVector, &vector));
  320. XLock lock(this);
  321. return CreateResultVector(&(m_vector - vector), ppResult);
  322. }
  323. STDMETHODIMP CAGCVector::Multiply(float f, IAGCVector** ppResult)
  324. {
  325. XLock lock(this);
  326. return CreateResultVector(&(m_vector * f), ppResult);
  327. }
  328. STDMETHODIMP CAGCVector::Divide(float f, IAGCVector** ppResult)
  329. {
  330. XLock lock(this);
  331. return CreateResultVector(&(m_vector / f), ppResult);
  332. }
  333. STDMETHODIMP CAGCVector::Normalize(IAGCVector** ppResult)
  334. {
  335. XLock lock(this);
  336. return CreateResultVector(&m_vector.Normalize(), ppResult);
  337. }
  338. STDMETHODIMP CAGCVector::CrossProduct(IAGCVector* pVector,
  339. IAGCVector** ppResult)
  340. {
  341. Vector vector;
  342. RETURN_FAILED(GetRawVector(pVector, &vector));
  343. XLock lock(this);
  344. return CreateResultVector(&::CrossProduct(m_vector, vector), ppResult);
  345. }
  346. STDMETHODIMP CAGCVector::Interpolate(IAGCVector* pVector, float fValue,
  347. IAGCVector** ppResult)
  348. {
  349. Vector vector;
  350. RETURN_FAILED(GetRawVector(pVector, &vector));
  351. XLock lock(this);
  352. return CreateResultVector(&::Interpolate(m_vector, vector, fValue), ppResult);
  353. }
  354. STDMETHODIMP CAGCVector::AddInPlace(IAGCVector* pVector)
  355. {
  356. Vector vector;
  357. RETURN_FAILED(GetRawVector(pVector, &vector));
  358. XLock lock(this);
  359. return InitFromVector(&(m_vector + vector));
  360. }
  361. STDMETHODIMP CAGCVector::SubtractInPlace(IAGCVector* pVector)
  362. {
  363. Vector vector;
  364. RETURN_FAILED(GetRawVector(pVector, &vector));
  365. XLock lock(this);
  366. return InitFromVector(&(m_vector - vector));
  367. }
  368. STDMETHODIMP CAGCVector::MultiplyInPlace(float f)
  369. {
  370. XLock lock(this);
  371. return InitFromVector(&(m_vector * f));
  372. }
  373. STDMETHODIMP CAGCVector::DivideInPlace(float f)
  374. {
  375. XLock lock(this);
  376. return InitFromVector(&(m_vector / f));
  377. }
  378. STDMETHODIMP CAGCVector::NormalizeInPlace()
  379. {
  380. XLock lock(this);
  381. m_vector.SetNormalize();
  382. return S_OK;
  383. }
  384. STDMETHODIMP CAGCVector::CrossProductInPlace(IAGCVector* pVector)
  385. {
  386. Vector vector;
  387. RETURN_FAILED(GetRawVector(pVector, &vector));
  388. XLock lock(this);
  389. return InitFromVector(&::CrossProduct(m_vector, vector));
  390. }
  391. STDMETHODIMP CAGCVector::InterpolateInPlace(IAGCVector* pVector, float fValue)
  392. {
  393. Vector vector;
  394. RETURN_FAILED(GetRawVector(pVector, &vector));
  395. XLock lock(this);
  396. return InitFromVector(&::Interpolate(m_vector, vector, fValue));
  397. }
  398. /////////////////////////////////////////////////////////////////////////////
  399. // IAGCVectorPrivate Interface Methods
  400. STDMETHODIMP CAGCVector::InitFromVector(const void* pvVector)
  401. {
  402. Vector vectorTemp;
  403. const Vector* pVector = reinterpret_cast<const Vector*>(pvVector);
  404. if (!pVector)
  405. {
  406. vectorTemp = Vector::GetZero();
  407. pVector = &vectorTemp;
  408. }
  409. return InitXYZ(pVector->X(), pVector->Y(), pVector->Z());
  410. }
  411. STDMETHODIMP CAGCVector::CopyVectorTo(void* pvVector)
  412. {
  413. XLock lock(this);
  414. Vector* pVector = reinterpret_cast<Vector*>(pvVector);
  415. pVector->SetX(m_vector.X());
  416. pVector->SetY(m_vector.Y());
  417. pVector->SetZ(m_vector.Z());
  418. return S_OK;
  419. }