HIK2016/humanik/hikdump.h Source File

hikdump.h
Go to the documentation of this file.
1 
11 /**************************************************************************************
12 
13 Copyright (C) 2009 Autodesk, Inc.
14 All Rights Reserved.
15 
16 The coded instructions, statements, computer programs, and/or related material (collectively "Data")
17 in these files contain unpublished information proprietary to Autodesk, Inc., ("Autodesk") which is
18 protected by Canada and United States of America federal copyright law and by international treaties.
19 
20 The Data may not be disclosed or distributed to third parties, in whole or in part, without the prior
21 written consent of Autodesk.
22 
23 THE DATA IS PROVIDED "AS IS" AND WITHOUT WARRANTY. ALL WARRANTIES ARE EXPRESSLY EXCLUDED AND DISCLAIMED.
24 AUTODESK MAKES NO WARRANTY OF ANY KIND WITH RESPECT TO THE DATA, EXPRESS, IMPLIED OR ARISING BY CUSTOM
25 OR TRADE USAGE, AND DISCLAIMS ANY IMPLIED WARRANTIES OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
26 FITNESS FOR A PARTICULAR PURPOSE OR USE. WITHOUT LIMITING THE FOREGOING, AUTODESK DOES NOT WARRANT THAT
27 THE OPERATION OF THE DATA WILL BE UNINTERRUPTED OR ERROR FREE.
28 
29 IN NO EVENT SHALL AUTODESK, ITS AFFILIATES, PARENT COMPANIES, LICENSORS OR SUPPLIERS ("AUTODESK GROUP")
30 BE LIABLE FOR ANY LOSSES, DAMAGES OR EXPENSES OF ANY KIND (INCLUDING WITHOUT LIMITATION PUNITIVE OR
31 MULTIPLE DAMAGES OR OTHER SPECIAL, DIRECT, INDIRECT, EXEMPLARY, INCIDENTAL, LOSS OF PROFITS, REVENUE
32 OR DATA, COST OF COVER OR CONSEQUENTIAL LOSSES OR DAMAGES OF ANY KIND), HOWEVER CAUSED, AND REGARDLESS
33 OF THE THEORY OF LIABILITY, WHETHER DERIVED FROM CONTRACT, TORT (INCLUDING, BUT NOT LIMITED TO,
34 NEGLIGENCE), OR OTHERWISE, ARISING OUT OF OR RELATING TO THE DATA OR ITS USE OR ANY OTHER PERFORMANCE,
35 WHETHER OR NOT AUTODESK HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH LOSS OR DAMAGE.
36 
37 **************************************************************************************/
38 
39 #ifndef HUMANIK_DUMP
40 #define HUMANIK_DUMP
41 
42 #ifndef _CRT_SECURE_NO_WARNINGS
43 #define _CRT_SECURE_NO_WARNINGS
44 #endif
45 
46 #include "humanik.h"
47 #include "hikproperty.h"
48 
49 #include <stdio.h>
50 #include <stddef.h>
51 #include <string.h>
52 
53 #if defined(_MSC_VER) || defined(__INTEL_COMPILER) || defined(__ICL)
54  #include <malloc.h>
55  #define attribute_align(a) __declspec(align(a))
56 #elif defined(__GNUC__) || defined(__SNC__) || defined(__MWERKS__)
57  #include <stdlib.h>
58  #define attribute_align(a) __attribute__ ((aligned(a)))
59 #endif
60 
61 
62 
63 /* *********************************************** */
80 HIKCharacter* HIKLoadCharacter(const char* pFileName, const char* pValidationString, HIKMalloc pMalloc);
81 
93 bool HIKSaveCharacter(const char* pFileName, HIKCharacter* pCharacter, HIKMalloc pMalloc, HIKFree pFree, float pUnitScale = 1.0f);
94 
103 HIKCharacterState* HIKLoadCharacterState(const char* pFileName, HIKCharacter* pCharacter, HIKMalloc pMalloc);
104 
114 bool HIKSaveCharacterState(const char* pFileName, HIKCharacter* pCharacter, HIKCharacterState* pState, int pTransformMode, float pUnitScale = 1.0f);
115 
122 HIKEffectorSetState* HIKLoadEffectorState(const char* pFileName, HIKMalloc pMalloc);
123 
130 bool HIKSaveEffectorState(const char* pFileName, HIKEffectorSetState* pState, float pUnitScale = 1.0f);
131 
138 HIKPropertySetState* HIKLoadPropertySetState(const char* pFileName, HIKMalloc pMalloc);
139 
146 bool HIKSavePropertySetState(const char* pFileName, HIKPropertySetState* pState, float pUnitScale = 1.0f);
147 
158 void* HIKLoadDataBlock(const char* pFileName, HIKDataDescription& pDataDesc, HIKMalloc pMalloc);
159 
170 void* HIKDefaultAlignedMalloc(size_t pSize, size_t pAlignment, HIKMalloc pMalloc);
171 
178 void HIKDefaultAlignedFree(void* pAligned, HIKFree pFree);
179 
189 void HIKSaveDataBlock(const char* pFileName, const HIKDataDescription& pDataDesc, const void* pDataBlock);
190 
191 //Headers are 16 characters long
192 #define HEADERLENGTH 16
193 //123456789012345
194 const char HIKCHARACTER_HEADER[] = "HIKCHARACTER000\0";
195 const char HIKCHARACTERSTATE_HEADER[] = "HIKSTATE0000000\0";
196 const char HIKCHARACTEREFFECTOR_HEADER[] = "HIKEFFECTOR0000\0";
197 const char HIKCHARACTERPROPERTY_HEADER[] = "HIKPROPERTY0000\0";
198 const char HIKCHARACTERDATABLOCK_HEADER[] = "HIKDATABLOCK000\0";
199 const int MagicNumber = 0xabcdef12;
200 
201 class Header
202 {
203  char HeaderStr[HEADERLENGTH];
204 
205 public:
206  bool bSwap;
207 
208  Header():bSwap(false) {}
209  inline void Init(const char *_Header)
210  {
211  #if (_MSC_VER == 1500)
212  strcpy(HeaderStr, _Header);
213  #else
214  strcpy_s(HeaderStr, HEADERLENGTH, _Header);
215  #endif
216  }
217 
218  template<typename HIKFile>
219  inline bool Write(HIKFile pFile) const;
220 
221  template<typename HIKFile>
222  inline bool Read(HIKFile pFile);
223 };
224 
225 template<typename type> bool Write(const char* pFileName, const type& pStream);
226 template<typename type> bool WriteBlock(const char* pFileName, const size_t& pElementSize, const size_t& pElementCount, type& pStream);
227 
228 template<typename type> bool Read(const char* pFileName, type& pStream);
229 template<typename type> bool ReadBlock(const char* pFileName, const size_t pOffset, const size_t& pElementSize, const size_t& pElementCount, type& pStream);
230 
231 inline void SwapBytes4(char* ToSwap)
232 {
233  char temp;
234 
235  temp = ToSwap[0];
236  ToSwap[0] = ToSwap[3];
237  ToSwap[3] = temp;
238  temp = ToSwap[1];
239  ToSwap[1] = ToSwap[2];
240  ToSwap[2] = temp;
241 }
242 
243 template<typename type, int count> class Field
244 {
245 public:
246  typedef type FieldType;
247  enum{
248  eCount = count
249  };
250  FieldType mField[eCount];
251 
252  inline void Init(FieldType pValue) { memset(mField, (int)pValue, sizeof(FieldType)*eCount); }
253 
254  template<typename HIKFile>
255  inline bool Write(HIKFile pFile) const;
256 
257  template<typename HIKFile>
258  inline bool Read(HIKFile pFile, bool bSwap);
259 };
260 
261 template<typename type, int count1, int count2> class Field2D
262 {
263 public:
264  typedef type FieldType;
265  enum{
266  eCount1 = count1,
267  eCount2 = count2,
269  };
270  FieldType mField[eCount1][eCount2];
271 
272  inline void Init(FieldType pValue) { memset(mField, (int)pValue, sizeof(FieldType)*eCount); }
273 
274  template<typename HIKFile>
275  inline bool Write(HIKFile pFile) const;
276 
277  template<typename HIKFile>
278  inline bool Read(HIKFile pFile, bool bSwap);
279 };
280 
281 class HIKCharacterStream
282 {
283 public:
292 
293  inline void Init()
294  {
295  HIKCharHeader.Init(HIKCHARACTER_HEADER);
296 
297  mNodeFlag.Init(HIKNodeNotUsed);
298  mTOffset.Init(0.0f);
299  mQOffset.Init(0.0f);
300  mSOffset.Init(0.0f);
301  mParentTOffset.Init(0.0f);
302  mParentQOffset.Init(0.0f);
303  mParentSOffset.Init(0.0f);
304  }
305 
306  template<typename HIKFile>
307  inline bool Write(HIKFile pFile) const
308  {
309  bool lFlag = false;
310 
311  lFlag = HIKCharHeader.Write(pFile);
312  lFlag = lFlag && mNodeFlag.Write(pFile);
313  lFlag = lFlag && mTOffset.Write(pFile);
314  lFlag = lFlag && mQOffset.Write(pFile);
315  lFlag = lFlag && mSOffset.Write(pFile);
316  lFlag = lFlag && mParentTOffset.Write(pFile);
317  lFlag = lFlag && mParentQOffset.Write(pFile);
318  lFlag = lFlag && mParentSOffset.Write(pFile);
319 
320  return lFlag;
321  }
322 
323  template<typename HIKFile>
324  inline bool Read(HIKFile pFile)
325  {
326  bool lFlag = false;
327 
328  if(HIKCharHeader.Read(pFile))
329  {
330  lFlag = mNodeFlag.Read(pFile, HIKCharHeader.bSwap);
331  lFlag = lFlag && mTOffset.Read(pFile, HIKCharHeader.bSwap);
332  lFlag = lFlag && mQOffset.Read(pFile, HIKCharHeader.bSwap);
333  lFlag = lFlag && mSOffset.Read(pFile, HIKCharHeader.bSwap);
334  lFlag = lFlag && mParentTOffset.Read(pFile, HIKCharHeader.bSwap);
335  lFlag = lFlag && mParentQOffset.Read(pFile, HIKCharHeader.bSwap);
336  lFlag = lFlag && mParentSOffset.Read(pFile, HIKCharHeader.bSwap);
337  }
338 
339  return lFlag;
340  }
341 };
342 
343 inline bool HIKGetCharacterDefinitionFromDump(const char* pFileName, HIKCharacterDefinition& pDef)
344 {
345  // First let retrieve data
346  // We need characterization flag, Default stance pose and Parent offset
347  HIKCharacterStream lStream;
348 
349  lStream.Init();
350 
351  // Load all the data
352  if(Read(pFileName, lStream))
353  {
354  memcpy(pDef.mUsedNodes, lStream.mNodeFlag.mField, sizeof(int)*lStream.mNodeFlag.eCount);
355  return true;
356  }
357  return false;
358 }
359 
360 inline HIKCharacter* HIKLoadCharacter(const char* pFileName,
361  const char* pValidationString,
362  HIKMalloc pMalloc)
363 {
364  // First let retrieve data
365  // We need characterization flag, Default stance pose and Parent offset
366  HIKCharacterStream lStream;
367  HIKCharacter* lCharacter = NULL;
368 
369  lStream.Init();
370 
371  // Load all the data
372  if(Read(pFileName, lStream))
373  {
375 
376  memcpy(lDef.mUsedNodes, lStream.mNodeFlag.mField, sizeof(int)*lStream.mNodeFlag.eCount);
377 
378  lCharacter = HIKCharacterCreate(&lDef, pMalloc, pValidationString);
379  if (!lCharacter)
380  return NULL;
381  int i;
382  for(i=0;i<LastNodeId;i++)
383  {
384  if(lDef.mUsedNodes[i] & HIKNodeUsed)
385  {
386  HIKSetCharacterizeNodeStateTQSfv(lCharacter, i, &lStream.mTOffset.mField[i][0], &lStream.mQOffset.mField[i][0], &lStream.mSOffset.mField[i][0]);
387  }
388 
389  if(lDef.mUsedNodes[i] & HIKNodeParentOffset)
390  {
391  HIKSetParentOffsetfv(lCharacter, i, &lStream.mParentTOffset.mField[i][0], &lStream.mParentQOffset.mField[i][0], &lStream.mParentSOffset.mField[i][0]);
392  }
393  }
394 
395  HIKCharacterizeGeometry(lCharacter);
396  }
397  return lCharacter;
398 }
399 
400 inline bool HIKSaveCharacter(const char* pFileName, HIKCharacter* pCharacter, HIKMalloc pMalloc, HIKFree pFree, float pUnitScale)
401 {
402  // First let prepare data to save
403  // We need characterization flag, Default stance pose and Parent offset
404  HIKCharacterStream lStream;
405 
406  lStream.Init();
407 
408  int i;
409  for(i=0;i<LastNodeId;i++)
410  {
411  lStream.mNodeFlag.mField[i] = HIKGetNodeUse(pCharacter, i);
412  }
413 
414  for(i=0;i<LastNodeId;i++)
415  {
416  if(lStream.mNodeFlag.mField[i] & HIKNodeParentOffset)
417  {
418  HIKGetParentOffsetfv(pCharacter, i, &lStream.mParentTOffset.mField[i][0], &lStream.mParentQOffset.mField[i][0], &lStream.mParentSOffset.mField[i][0]);
419  lStream.mParentTOffset.mField[i][0] *= pUnitScale;
420  lStream.mParentTOffset.mField[i][1] *= pUnitScale;
421  lStream.mParentTOffset.mField[i][2] *= pUnitScale;
422  }
423  }
424 
425  HIKCharacterState* lState = HIKCharacterStateCreate(pCharacter, pMalloc);
426  HIKGetDefaultState(pCharacter, lState);
427 
428  for(i=0;i<LastNodeId;i++)
429  {
430  if(lStream.mNodeFlag.mField[i] & HIKNodeUsed)
431  {
432  HIKGetNodeStateTQSfv(pCharacter, lState, i, &lStream.mTOffset.mField[i][0], &lStream.mQOffset.mField[i][0], &lStream.mSOffset.mField[i][0]);
433  lStream.mTOffset.mField[i][0] *= pUnitScale;
434  lStream.mTOffset.mField[i][1] *= pUnitScale;
435  lStream.mTOffset.mField[i][2] *= pUnitScale;
436  }
437  }
438 
439  HIKCharacterStateDestroy(lState , pFree);
440 
441  return Write(pFileName, lStream);
442 }
443 
445 {
446 public:
451 
452  inline void Init()
453  {
454  mTransformMode.Init(0);
455  mNodeId.Init(HIKLastNode);
456  mTransformData.Init(0.0f);
457  HIKCharStateHeader.Init(HIKCHARACTERSTATE_HEADER);
458  }
459 
460  template<typename HIKFile>
461  inline bool Write(HIKFile pFile) const
462  {
463  bool lFlag = false;
464 
465  lFlag = HIKCharStateHeader.Write(pFile);
466  lFlag = lFlag && mTransformMode.Write(pFile);
467  lFlag = lFlag && mNodeId.Write(pFile);
468  lFlag = lFlag && mTransformData.Write(pFile);
469 
470  return lFlag;
471  }
472 
473  template<typename HIKFile>
474  inline bool Read(HIKFile pFile)
475  {
476  bool lFlag = false;
477 
478  if(HIKCharStateHeader.Read(pFile))
479  {
480  lFlag = mTransformMode.Read(pFile, HIKCharStateHeader.bSwap);
481  lFlag = lFlag && mNodeId.Read(pFile, HIKCharStateHeader.bSwap);
482  lFlag = lFlag && mTransformData.Read(pFile, HIKCharStateHeader.bSwap);
483  }
484 
485  return lFlag;
486  }
487 };
488 
489 
490 inline HIKCharacterState* HIKLoadCharacterState(const char* pFileName, HIKCharacter* pCharacter, HIKMalloc pMalloc)
491 {
492  HIKCharacterStateStream lStateStream;
493  HIKCharacterState* lState = NULL;
494 
495  lStateStream.Init();
496 
497  if(Read(pFileName, lStateStream))
498  {
499  lState = HIKCharacterStateCreate(pCharacter, pMalloc);
500 
501  HIKDataDescription lDataDesc;
502 
503  lDataDesc.mTransformSpace = lStateStream.mTransformMode.mField[0] == HIKDataDescription::HIKLocalSpace ? HIKDataDescription::HIKLocalSpace : HIKDataDescription::HIKGlobalSpace;
504  lDataDesc.mTOffset = 0;
505  lDataDesc.mQOffset = 16;
506  lDataDesc.mSOffset = 32;
507  lDataDesc.mStride = 48;
508  lDataDesc.mHIKNodeId = &lStateStream.mNodeId.mField[0];
509 
510  HIKSetCharacterStateTransformTQS(pCharacter, lState, &lDataDesc, &lStateStream.mTransformData);
511  }
512  return lState;
513 }
514 
515 inline bool HIKSaveCharacterState(const char* pFileName, HIKCharacter* pCharacter, HIKCharacterState* pState, int pTransformMode, float pUnitScale)
516 {
517  HIKCharacterStateStream lStateStream;
518  HIKDataDescription lDataDesc;
519 
520  lStateStream.Init();
521 
522  lDataDesc.mTransformSpace = pTransformMode == HIKDataDescription::HIKLocalSpace ? HIKDataDescription::HIKLocalSpace : HIKDataDescription::HIKGlobalSpace;
523  lDataDesc.mTOffset = 0;
524  lDataDesc.mQOffset = 16;
525  lDataDesc.mSOffset = 32;
526  lDataDesc.mStride = 48;
527  lDataDesc.mHIKNodeId = &lStateStream.mNodeId.mField[0];
528 
529  // First let prepare data to save
530  // We need transform mode and all joint transform
531  int i, lLastId = 0;
532  for(i=0;i<LastNodeId;i++)
533  {
534  if( HIKGetNodeUse(pCharacter, i) & HIKNodeUsed)
535  {
536  lStateStream.mNodeId.mField[lLastId++] = i;
537  }
538  }
539 
540  lStateStream.mNodeId.mField[lLastId] = HIKLastNode;
541  lStateStream.mTransformMode.mField[0] = pTransformMode;
542 
543  HIKGetCharacterStateTransformTQS(pCharacter, pState, &lDataDesc, &lStateStream.mTransformData);
544  for(i=0;i<LastNodeId;i++)
545  {
546  //if(HIKGetNodeUse(pCharacter, i) & HIKNodeUsed)
547  {
548  lStateStream.mTransformData.mField[i][0] *= pUnitScale;
549  lStateStream.mTransformData.mField[i][1] *= pUnitScale;
550  lStateStream.mTransformData.mField[i][2] *= pUnitScale;
551  }
552  }
553 
554  return Write(pFileName, lStateStream);
555 }
556 
558 {
559 public:
565 
569 
570  inline void Init()
571  {
572  mReachT.Init(0.0f);
573  mReachR.Init(0.0f);
574  mResist.Init(0.0f);
575  mPull.Init(0.0f);
576  mHandPullHips.Init(0.0f);
577  mTQS.Init(0.0f);
578  mFloorTQS.Init(0.0f);
579  HIKEffectorHeader.Init(HIKCHARACTEREFFECTOR_HEADER);
580  }
581 
582  template<typename HIKFile>
583  inline bool Write(HIKFile pFile) const
584  {
585  bool lFlag = false;
586 
587  lFlag = HIKEffectorHeader.Write(pFile);
588  lFlag = lFlag && mReachT.Write(pFile);
589  lFlag = lFlag && mReachR.Write(pFile);
590  lFlag = lFlag && mResist.Write(pFile);
591  lFlag = lFlag && mPull.Write(pFile);
592  lFlag = lFlag && mHandPullHips.Write(pFile);
593  lFlag = lFlag && mTQS.Write(pFile);
594  lFlag = lFlag && mFloorTQS.Write(pFile);
595  return lFlag;
596  }
597 
598  template<typename HIKFile>
599  inline bool Read(HIKFile pFile)
600  {
601  bool lFlag = false;
602 
603  if(HIKEffectorHeader.Read(pFile))
604  {
605  lFlag = mReachT.Read(pFile, HIKEffectorHeader.bSwap);
606  lFlag = lFlag && mReachR.Read(pFile, HIKEffectorHeader.bSwap);
607  lFlag = lFlag && mResist.Read(pFile, HIKEffectorHeader.bSwap);
608  lFlag = lFlag && mPull.Read(pFile, HIKEffectorHeader.bSwap);
609  lFlag = lFlag && mHandPullHips.Read(pFile, HIKEffectorHeader.bSwap);
610  lFlag = lFlag && mTQS.Read(pFile, HIKEffectorHeader.bSwap);
611  lFlag = lFlag && mFloorTQS.Read(pFile, HIKEffectorHeader.bSwap);
612  }
613 
614  return lFlag;
615  }
616 };
617 
618 inline HIKEffectorSetState* HIKLoadEffectorState(const char* pFileName, HIKMalloc pMalloc)
619 {
620  HIKEffectorSetStateStream lEffectorStream;
621  HIKEffectorSetState* lState = NULL;
622 
623  lEffectorStream.Init();
624 
625  if(Read(pFileName, lEffectorStream))
626  {
627  lState = HIKEffectorSetStateCreate(pMalloc);
628 
629  int i;
630  for(i=0;i<LastEffectorId;i++)
631  {
632  HIKSetTranslationActive(lState, i, lEffectorStream.mReachT.mField[i]);
633  HIKSetRotationActive(lState, i, lEffectorStream.mReachR.mField[i]);
634  HIKSetResist(lState, i, lEffectorStream.mResist.mField[i]);
635  HIKSetPull(lState, i, lEffectorStream.mPull.mField[i]);
636  HIKSetEffectorStateTQSfv(lState, i, &lEffectorStream.mTQS.mField[i][0],&lEffectorStream.mTQS.mField[i][4], &lEffectorStream.mTQS.mField[i][8]);
637  }
638 
639  HIKSetHandPullHips(lState, 0, lEffectorStream.mHandPullHips.mField[0]);
640  HIKSetHandPullHips(lState, 1, lEffectorStream.mHandPullHips.mField[1]);
641 
642  for(i=0;i<HIKLastFloorId;i++)
643  {
644  HIKSetEffectorFloorStatefv(lState, i, &lEffectorStream.mFloorTQS.mField[i][0]);
645  }
646 
647  }
648  return lState;
649 }
650 
651 inline bool HIKSaveEffectorState(const char* pFileName, HIKEffectorSetState* pState, float pUnitScale)
652 {
653  HIKEffectorSetStateStream lEffectorStream;
654  lEffectorStream.Init();
655 
656  int i;
657  for(i=0;i<LastEffectorId;i++)
658  {
659  lEffectorStream.mReachT.mField[i] = HIKGetTranslationActive(pState, i);
660  lEffectorStream.mReachR.mField[i] = HIKGetRotationActive(pState, i);
661  lEffectorStream.mResist.mField[i] = HIKGetResist(pState, i);
662  lEffectorStream.mPull.mField[i] = HIKGetPull(pState, i);
663 
664  HIKGetEffectorStateTQSfv(pState, i, &lEffectorStream.mTQS.mField[i][0], &lEffectorStream.mTQS.mField[i][4], &lEffectorStream.mTQS.mField[i][8]);
665  lEffectorStream.mTQS.mField[i][0] *= pUnitScale;
666  lEffectorStream.mTQS.mField[i][1] *= pUnitScale;
667  lEffectorStream.mTQS.mField[i][2] *= pUnitScale;
668  }
669 
670  lEffectorStream.mHandPullHips.mField[0] = HIKGetHandPullHips(pState, 0);
671  lEffectorStream.mHandPullHips.mField[1] = HIKGetHandPullHips(pState, 1);
672 
673  for(i=0;i<HIKLastFloorId;i++)
674  {
675  HIKGetEffectorFloorStatefv(pState, i, &lEffectorStream.mFloorTQS.mField[i][0]);
676  lEffectorStream.mFloorTQS.mField[i][0] *= pUnitScale;
677  lEffectorStream.mFloorTQS.mField[i][1] *= pUnitScale;
678  lEffectorStream.mFloorTQS.mField[i][2] *= pUnitScale;
679  }
680 
681  return Write(pFileName, lEffectorStream);
682 }
683 
685 {
686 public:
690 
691  inline void Init()
692  {
693  mMode.Init(0);
694  mValue.Init(0.0f);
695  HIKPropertySetHeader.Init(HIKCHARACTERPROPERTY_HEADER);
696  }
697 
698  template<typename HIKFile>
699  inline bool Write(HIKFile pFile) const
700  {
701  bool lFlag = false;
702 
703  lFlag = HIKPropertySetHeader.Write(pFile);
704  lFlag = lFlag && mMode.Write(pFile);
705  lFlag = lFlag && mValue.Write(pFile);
706 
707  return lFlag;
708  }
709 
710  template<typename HIKFile>
711  inline bool Read(HIKFile pFile)
712  {
713  bool lFlag = false;
714 
715  if(HIKPropertySetHeader.Read(pFile))
716  {
717  lFlag = mMode.Read(pFile, HIKPropertySetHeader.bSwap);
718  lFlag = lFlag && mValue.Read(pFile, HIKPropertySetHeader.bSwap);
719  }
720 
721  return lFlag;
722  }
723 
724 };
725 
726 inline HIKPropertySetState* HIKLoadPropertySetState(const char* pFileName, HIKMalloc pMalloc)
727 {
728  HIKPropertySetStream lStream;
729  HIKPropertySetState* lState = NULL;
730 
731  lStream.Init();
732 
733  if(Read(pFileName, lStream))
734  {
735  lState = HIKPropertySetStateCreate(pMalloc);
736 
737  int i;
738  for(i=0;i<HIKLastPropertyId;i++)
739  {
740  HIKSetPropertyMode(lState, i, lStream.mMode.mField[i]);
741  HIKSetPropertyValue(lState, i, lStream.mValue.mField[i]);
742  }
743  }
744 
745  return lState;
746 }
747 
748 inline bool HIKSavePropertySetState(const char* pFileName, HIKPropertySetState* pState, float pUnitScale)
749 {
750  HIKPropertySetStream lStream;
751  lStream.Init();
752 
753  int i;
754  for(i=0;i<HIKLastPropertyId;i++)
755  {
756  lStream.mMode.mField[i] = HIKGetPropertyMode(pState, i);
757  lStream.mValue.mField[i] = HIKGetPropertyValue(pState, i);
758 
759  // Handle unitScale
760 
761  switch(i)
762  {
763  case HIKHipsTOffsetXId :
764  case HIKHipsTOffsetYId :
765  case HIKHipsTOffsetZId :
766  case HIKChestTOffsetXId :
767  case HIKChestTOffsetYId :
768  case HIKChestTOffsetZId :
769 
771  case HIKFootBackToAnkleId :
774  case HIKFootInToAnkleId :
775  case HIKFootOutToAnkleId :
776 
778  case HIKHandBackToWristId :
781  case HIKHandInToWristId :
782  case HIKHandOutToWristId :
783 
787 
788  lStream.mValue.mField[i] *= pUnitScale;
789  break;
790  }
791  }
792 
793  return Write(pFileName, lStream);
794 }
795 
797 {
798 public:
806 
807  inline void Init()
808  {
809  mTransformSpace.Init(0);
810  mTOffset.Init(0);
811  mQOffset.Init(0);
812  mSOffset.Init(0);
813  mStride.Init(0);
814  mHIKNodeId.Init(0);
815  HIKDataBlockHeader.Init(HIKCHARACTERDATABLOCK_HEADER);
816  }
817 
818  template<typename HIKFile>
819  inline bool Write(HIKFile pFile) const
820  {
821  bool lFlag = false;
822 
823  lFlag = HIKDataBlockHeader.Write(pFile);
824  lFlag = lFlag && mTransformSpace.Write(pFile);
825  lFlag = lFlag && mTOffset.Write(pFile);
826  lFlag = lFlag && mQOffset.Write(pFile);
827  lFlag = lFlag && mSOffset.Write(pFile);
828  lFlag = lFlag && mStride.Write(pFile);
829  lFlag = lFlag && mHIKNodeId.Write(pFile);
830 
831  return lFlag;
832  }
833 
834  template<typename HIKFile>
835  inline bool Read(HIKFile pFile)
836  {
837  bool lFlag = false;
838 
839  if(HIKDataBlockHeader.Read(pFile))
840  {
841  lFlag = mTransformSpace.Read(pFile, HIKDataBlockHeader.bSwap);
842  lFlag = lFlag && mTOffset.Read(pFile, HIKDataBlockHeader.bSwap);
843  lFlag = lFlag && mQOffset.Read(pFile, HIKDataBlockHeader.bSwap);
844  lFlag = lFlag && mSOffset.Read(pFile, HIKDataBlockHeader.bSwap);
845  lFlag = lFlag && mStride.Read(pFile, HIKDataBlockHeader.bSwap);
846  lFlag = lFlag && mHIKNodeId.Read(pFile, HIKDataBlockHeader.bSwap);
847  }
848 
849  return lFlag;
850  }
851 };
852 
853 inline void* HIKDefaultAlignedMalloc(size_t pSize, size_t pAlignment, HIKMalloc pMalloc)
854 {
855  const size_t lPointerSize = sizeof(void*);
856  const size_t lRequestedSize = pSize + pAlignment - 1 + lPointerSize;
857  void* lRawPointer = (*pMalloc)(lRequestedSize);
858  void* lStart = (char*)lRawPointer + lPointerSize;
859  void* lAligned = (void*)(((size_t)((char*)lStart+pAlignment-1)) & ~(pAlignment-1));
860  *(void**)((char*)lAligned-lPointerSize) = lRawPointer;
861  return lAligned;
862 }
863 
864 inline void HIKDefaultAlignedFree(void* pAligned, HIKFree pFree)
865 {
866  void* lRawPointer = *(void**)((char*)pAligned-sizeof(void*));
867  (*pFree)(lRawPointer);
868 }
869 
870 inline void* HIKLoadDataBlock(const char* pFileName, HIKDataDescription& pDataDesc, HIKMalloc pMalloc)
871 {
872  void *lDataBlock = NULL;
873  HIKDataDescriptionStream lStream;
874  lStream.Init();
875 
876  if(Read(pFileName, lStream))
877  {
878  pDataDesc.mTransformSpace = lStream.mTransformSpace.mField[0] == HIKDataDescription::HIKLocalSpace ? HIKDataDescription::HIKLocalSpace : HIKDataDescription::HIKGlobalSpace;;
879  pDataDesc.mTOffset = (size_t)lStream.mTOffset.mField[0];
880  pDataDesc.mQOffset = (size_t)lStream.mQOffset.mField[0];
881  pDataDesc.mSOffset = (size_t)lStream.mSOffset.mField[0];
882  pDataDesc.mStride = (size_t)lStream.mStride.mField[0];
883 
884  int i = 0;
885  do
886  {
887  pDataDesc.mHIKNodeId[i] = lStream.mHIKNodeId.mField[i];
888  }
889  while(lStream.mHIKNodeId.mField[i++] != HIKLastNode);
890 
891  // allocate the data bloc
892  const size_t align = 16;
893  lDataBlock = HIKDefaultAlignedMalloc(pDataDesc.mStride*i-1, align, pMalloc);
894  ReadBlock(pFileName, sizeof(HIKDataDescriptionStream), (size_t)pDataDesc.mStride, (size_t)(i-1), lDataBlock);
895  }
896  return lDataBlock;
897 }
898 
899 inline void HIKSaveDataBlock(const char* pFileName, const HIKDataDescription& pDataDesc, const void* pDataBlock)
900 {
901  HIKDataDescriptionStream lStream;
902  lStream.Init();
903 
904  lStream.mTransformSpace.mField[0] = pDataDesc.mTransformSpace;
905  lStream.mTOffset.mField[0] = (int)pDataDesc.mTOffset;
906  lStream.mQOffset.mField[0] = (int)pDataDesc.mQOffset;
907  lStream.mSOffset.mField[0] = (int)pDataDesc.mSOffset;
908  lStream.mStride.mField[0] = (int)pDataDesc.mStride;
909 
910  int i = 0;
911  do
912  {
913  lStream.mHIKNodeId.mField[i] = pDataDesc.mHIKNodeId[i];
914  }
915  while(pDataDesc.mHIKNodeId[i++] != HIKLastNode);
916 
917  // Save descriptor
918  if(Write(pFileName, lStream))
919  {
920  // Save all the collected data
921  WriteBlock(pFileName, (size_t)pDataDesc.mStride, (size_t)(i-1), pDataBlock);
922  }
923 }
924 
925 
926 #if !defined(__ghs__) && ( defined(_MSC_VER) || defined(__INTEL_COMPILER) || defined(__ICL) || defined(__GNUC__) || defined(__SNC__) )
927  #include "hikdump_std.inl"
928 #endif
929 
930 #endif
Defines the distance from the wrist to the inside edge of the model's hand (the side of the thumb)...
Definition: hikproperty.h:158
void HIKCharacterStateDestroy(HIKCharacterState *pCharacterState, HIKFree pFree)
Destroy HIKCharacterState pCharacterState.
float HIKGetRotationActive(const HIKEffectorSetState *pEffectorSetState, int pEffectorIndex)
Retrieve the Reach Rotation constraint for Effector pEffectorIndex.
Header()
Definition: hikdump.h:208
bool Write(HIKFile pFile) const
Definition: hikdump.h:461
Defines the distance from the ankle to the inside edge of the model's foot (the instep).
Definition: hikproperty.h:151
HIKEffectorSetState * HIKEffectorSetStateCreate(HIKMalloc pMalloc)
Create a new HIKEffectorSetState.
HIKEffectorSetState * HIKLoadEffectorState(const char *pFileName, HIKMalloc pMalloc)
Load file pFileName, and create an HIKEffectorSetState object from its contents.
Definition: hikdump.h:611
Defines the distance from the ankle to the middle of the model's foot (its ball, or toe base)...
Definition: hikproperty.h:149
const char HIKCHARACTERPROPERTY_HEADER[]
Definition: hikdump.h:197
Field< int, LastNodeId > mNodeFlag
Definition: hikdump.h:277
If your source and target character have their ankles at different heights above the floor...
Definition: hikproperty.h:77
int
Definition: code.h:72
Field< int, 1 > mQOffset
Definition: hikdump.h:794
Defines the distance from the wrist to the outside edge of the model's hand (the side with the pinky)...
Definition: hikproperty.h:159
Node is characterized.
Definition: humanik.h:482
bool HIKSaveCharacter(const char *pFileName, HIKCharacter *pCharacter, HIKMalloc pMalloc, HIKFree pFree, float pUnitScale=1.0f)
Save HIKCharacter pCharacter to file pFileName.
Definition: hikdump.h:393
bool bSwap
Definition: hikdump.h:206
void HIKSetEffectorFloorStatefv(HIKEffectorSetState *pEffectorSetState, int pFloor, const float pXForm[16])
Set the transform matrix of the oriented plane that the floor contact engine applies to one of your c...
Definition: asdl.h:9
void HIKSetParentOffsetfv(HIKCharacter *pCharacter, int pNodeId, const float pParentTOffset[4], const float pParentQOffset[4], const float pParentSOffset[4])
Set the parent offset for Node pNodeId.
Field< float, 2 > mHandPullHips
Definition: hikdump.h:557
bool Write(HIKFile pFile) const
Definition: hikdump_std.inl:36
Field2D< float, LastNodeId, 4 > mTOffset
Definition: hikdump.h:278
int HIKGetPropertyMode(HIKPropertySetState *pState, int pPropertyId)
Retrieves the current mode set for property pPropertyId in HIKPropertySetState pState.
bool Write(const char *pFileName, const type &pStream)
Marks the end of the enumeration.
Definition: humanik.h:332
Py_ssize_t i
Definition: abstract.h:1086
void(* HIKFree)(void *)
Memory de-allocator function.
Definition: humanik.h:393
void HIKGetDefaultState(const HIKCharacter *pCharacter, HIKCharacterState *pCharacterState)
Retrieve the default T-stance for character pCharacter, storing it in HIKCharacterState pCharacterSta...
Marks the end of the enumeration.
Definition: humanik.h:257
void HIKGetEffectorFloorStatefv(const HIKEffectorSetState *pEffectorSetState, int pFloor, float pXForm[16])
Retrieve the transform matrix of the oriented plane that the floor contact engine applies to one of y...
Field< int, 1 > mStride
Definition: hikdump.h:796
bool Read(HIKFile pFile)
Definition: hikdump.h:474
float HIKGetHandPullHips(const HIKEffectorSetState *pEffectorSetState, int pLeft)
Retrieve the amount of pull the left or right hand can exert on the hips.
Field< float, LastEffectorId > mResist
Definition: hikdump.h:555
void SwapBytes4(char *ToSwap)
Definition: hikdump.h:224
Defines the distance from the wrist to the bottom of the model's hand.
Definition: hikproperty.h:154
float HIKGetTranslationActive(const HIKEffectorSetState *pEffectorSetState, int pEffectorIndex)
Retrieve the Reach Translation constraint for Effector pEffectorIndex.
Header HIKCharHeader
Definition: hikdump.h:284
#define NULL
Definition: kaydara.h:179
FieldType mField[eCount1][eCount2]
Definition: hikdump.h:263
Field< int, 1 > mTransformSpace
Definition: hikdump.h:792
bool Read(HIKFile pFile)
Definition: hikdump.h:324
bool ReadBlock(const char *pFileName, const size_t pOffset, const size_t &pElementSize, const size_t &pElementCount, type &pStream)
attribute_align(16) Field2D< float
void HIKSetResist(HIKEffectorSetState *pEffectorSetState, int pEffectorIndex, float pValue)
Set the Resist constraint for Effector pEffectorIndex.
void HIKGetEffectorStateTQSfv(const HIKEffectorSetState *pEffectorSetState, int pEffectorIndex, float pT[4], float pQ[4], float pS[4])
Retrieve the translation (T), quaternion rotation (Q) and scaling (S) in global space of Effector pEf...
HIKPropertySetState * HIKPropertySetStateCreate(HIKMalloc pMalloc)
Create a new HIKPropertySetState.
float HIKGetPropertyValue(HIKPropertySetState *pState, int pPropertyId)
Retrieves the current value set for property pPropertyId in HIKPropertySetState pState.
const char HIKCHARACTEREFFECTOR_HEADER[]
Definition: hikdump.h:196
void HIKGetNodeStateTQSfv(const HIKCharacter *pCharacter, const HIKCharacterState *pCharacterState, int pNodeId, float pT[4], float pQ[4], float pS[4])
Retrieve the translation (T), quaternion rotation (Q) and scaling (S) in global space of Node pNodeId...
void * HIKDefaultAlignedMalloc(size_t pSize, size_t pAlignment, HIKMalloc pMalloc)
Allocates a data block aligned to the pAlignment pointer boundary.
Definition: hikdump.h:846
Defines the distance from the ankle to the outside edge of the model's foot.
Definition: hikproperty.h:152
void Init(FieldType pValue)
Definition: hikdump.h:252
Field2D< float, LastEffectorId, 12 > mTQS
Definition: hikdump.h:559
void HIKSetCharacterizeNodeStateTQSfv(HIKCharacter *pCharacter, int pNodeId, const float pT[4], const float pQ[4], const float pS[4])
Set the translation, orientation and scaling for the Node pNodeId when the character is standing in t...
type FieldType
Definition: hikdump.h:246
A description of a data set that contains separate translation, quaternion rotation, and scaling values for multiple different Nodes in an HIKCharacterState.
int type
Definition: node.h:20
int HIKGetNodeUse(const HIKCharacter *pCharacter, int pNodeId)
Retrieve the characterization flag set for Node pNodeId in HIKCharacter pCharacter.
Defines an HIKEffectorSetState.
Definition: humanik.h:418
Defines the distance from the wrist to the back of the model's hand.
Definition: hikproperty.h:155
Definition: hikdump.h:236
#define HEADERLENGTH
Definition: hikdump.h:192
Field2D< float, LastNodeId, 4 > mSOffset
Definition: hikdump.h:280
Indicates the end of the list of Nodes.
Definition: humanik.h:1592
bool Write(HIKFile pFile) const
Definition: hikdump.h:583
Field< int, LastNodeId > mHIKNodeId
Definition: hikdump.h:797
bool WriteBlock(const char *pFileName, const size_t &pElementSize, const size_t &pElementCount, type &pStream)
Field< int, 1 > mTOffset
Definition: hikdump.h:793
float HIKGetPull(const HIKEffectorSetState *pEffectorSetState, int pEffectorIndex)
Retrieve the Pull constraint for Effector pEffectorIndex.
bool Write(HIKFile pFile) const
Definition: hikdump.h:699
void HIKSetPropertyValue(HIKPropertySetState *pState, int pPropertyId, float pValue)
Sets the current value for property pPropertyId in HIKPropertySetState pState.
Defines the distance from the wrist to the front end of the model's fingers.
Definition: hikproperty.h:157
void HIKSetEffectorStateTQSfv(HIKEffectorSetState *pEffectorSetState, int pEffectorIndex, const float pT[4], const float pQ[4], const float pS[4])
Set the translation (T), quaternion rotation (Q) and scaling (S) in global space of Effector pEffecto...
bool Read(HIKFile pFile)
Definition: hikdump.h:835
void Init(FieldType pValue)
Definition: hikdump.h:272
bool HIKCharacterizeGeometry(HIKCharacter *pCharacter)
Set up and initialize character pCharacter for solving.
Field< float, LastEffectorId > mReachT
Definition: hikdump.h:553
bool Read(HIKFile pFile)
Definition: hikdump.h:711
bool Read(HIKFile pFile)
Definition: hikdump_std.inl:45
PyObject char size_t
Definition: import.h:39
The Hips and Chest Offset properties offset the translation of the character's hips and chest along e...
Definition: hikproperty.h:276
Adjusts the height of the target character's hips.
Definition: hikproperty.h:87
Field2D< float, HIKLastFloorId, 16 > mFloorTQS
Definition: hikdump.h:560
Field< int, 1 > mSOffset
Definition: hikdump.h:795
Defines the distance from the ankle to the bottom of the model's foot.
Definition: hikproperty.h:147
Defines a character's properties.
Definition: humanik.h:457
Adjusts the spacing between the left and right ankles of the target character relative to the source ...
Definition: hikproperty.h:82
Field< int, HIKLastPropertyId > mMode
Definition: hikdump.h:680
type FieldType
Definition: hikdump.h:264
Defines the distance from the ankle to the back of the model's foot.
Definition: hikproperty.h:148
void HIKSetHandPullHips(HIKEffectorSetState *pEffectorSetState, int pLeft, float pValue)
Set the amount of pull the left or right hand can exert on the hips.
Field< float, LastEffectorId > mReachR
Definition: hikdump.h:554
void HIKSetTranslationActive(HIKEffectorSetState *pEffectorSetState, int pEffectorIndex, float pValue)
Set the Reach Translation constraint for Effector pEffectorIndex.
HIKCharacterState * HIKLoadCharacterState(const char *pFileName, HIKCharacter *pCharacter, HIKMalloc pMalloc)
Load file pFileName, and create an HIKCharacterState object from its contents.
Definition: hikdump.h:483
bool Write(HIKFile pFile) const
Definition: hikdump.h:307
Field< float, LastEffectorId > mPull
Definition: hikdump.h:556
Defines the distance from the wrist to the middle of the model's hand (its knuckles, or finger base).
Definition: hikproperty.h:156
void HIKGetParentOffsetfv(const HIKCharacter *pCharacter, int pNodeId, float pParentTOffset[4], float pParentQOffset[4], float pParentSOffset[4])
Retrieve the parent offset set for Node pNodeId.
HIKCharacter * HIKLoadCharacter(const char *pFileName, const char *pValidationString, HIKMalloc pMalloc)
Load file pFileName, and create an HIKCharacter object from its contents.
Definition: hikdump.h:353
void * HIKLoadDataBlock(const char *pFileName, HIKDataDescription &pDataDesc, HIKMalloc pMalloc)
Load file pFileName, and create a data set from its contents according to the data description provid...
Definition: hikdump.h:863
const char HIKCHARACTERSTATE_HEADER[]
Definition: hikdump.h:195
bool Read(const char *pFileName, type &pStream)
Field2D< float, LastNodeId, 4 > mParentSOffset
Definition: hikdump.h:283
FieldType mField[eCount]
Definition: hikdump.h:243
Defines a pose for a character.
Definition: humanik.h:441
const char HIKCHARACTER_HEADER[]
Definition: hikdump.h:194
HIKCharacterState * HIKCharacterStateCreate(const HIKCharacter *pCharacter, HIKMalloc pMalloc)
Create a new HIKCharacterState.
Field< int, 1 > mTransformMode
Definition: hikdump.h:440
Field2D< float, LastNodeId, 4 > mQOffset
Definition: hikdump.h:279
bool Read(HIKFile pFile)
Definition: hikdump.h:599
Defines the distance from the ankle to the front end of the model's toes.
Definition: hikproperty.h:150
float HIKGetResist(const HIKEffectorSetState *pEffectorSetState, int pEffectorIndex)
Retrieve the Resist constraint for Effector pEffectorIndex.
Node has a parent unknown to HumanIK, used for local space transform and DoF.
Definition: humanik.h:483
const int MagicNumber
Definition: hikdump.h:199
void *(* HIKMalloc)(size_t)
Memory allocator function.
Definition: humanik.h:388
Header HIKPropertySetHeader
Definition: hikdump.h:682
void HIKSetPull(HIKEffectorSetState *pEffectorSetState, int pEffectorIndex, float pValue)
Set the Pull constraint for Effector pEffectorIndex.
int strcpy_s(char *dst, size_t, const char *src)
Definition: kaydara.h:252
Field< int, LastNodeId > mNodeId
Definition: hikdump.h:441
bool HIKGetCharacterDefinitionFromDump(const char *pFileName, HIKCharacterDefinition &pDef)
Definition: hikdump.h:336
const char HIKCHARACTERDATABLOCK_HEADER[]
Definition: hikdump.h:198
Node is not characterized.
Definition: humanik.h:481
void HIKSaveDataBlock(const char *pFileName, const HIKDataDescription &pDataDesc, const void *pDataBlock)
Save the data set located in memory at pDataBlock to file pFileName.
Definition: hikdump.h:892
bool Read(HIKFile pFile, bool bSwap)
Definition: hikdump_std.inl:73
void HIKSetPropertyMode(HIKPropertySetState *pState, int pPropertyId, int pMode)
Sets the current mode for property pPropertyId in HIKPropertySetState pState.
void HIKSetCharacterStateTransformTQS(const HIKCharacter *pCharacter, HIKCharacterState *pCharacterState, const HIKDataDescription *pDataDescription, const void *pDataSet)
Set the translation (T), quaternion rotation (Q) and scaling (S) of multiple Nodes from data set pDat...
void HIKDefaultAlignedFree(void *pAligned, HIKFree pFree)
Frees a data block allocated using HIKDefaultAlignedMalloc().
Definition: hikdump.h:857
void HIKGetCharacterStateTransformTQS(const HIKCharacter *pCharacter, HIKCharacterState *pCharacterState, const HIKDataDescription *pDataDescription, void *pDataSet)
Retrieve the translation (T), quaternion rotation (Q) and scaling (S) of multiple Nodes from HIKChara...
Marks the end of the enumeration.
Definition: humanik.h:315
const char void * pValue
Definition: fbcontrols.h:2116
Defines which Nodes are to be used by an HIKCharacter.
Field2D< float, LastNodeId, 4 > mParentQOffset
Definition: hikdump.h:282
Defines a character to be used with HumanIK.
void Init(const char *_Header)
Definition: hikdump.h:209
bool Write(HIKFile pFile) const
Definition: hikdump.h:819
bool Write(HIKFile pFile) const
Definition: hikdump_std.inl:66
void HIKSetRotationActive(HIKEffectorSetState *pEffectorSetState, int pEffectorIndex, float pValue)
Set the Reach Rotation constraint for Effector pEffectorIndex.
Field2D< float, LastNodeId, 4 > mParentTOffset
Definition: hikdump.h:281
bool HIKSaveCharacterState(const char *pFileName, HIKCharacter *pCharacter, HIKCharacterState *pState, int pTransformMode, float pUnitScale=1.0f)
Save HIKCharacterState pState to file pFileName.
Definition: hikdump.h:508
bool HIKSavePropertySetState(const char *pFileName, HIKPropertySetState *pState, float pUnitScale=1.0f)
Save HIKPropertySetState pState to file pFileName.
Definition: hikdump.h:741
Field< float, HIKLastPropertyId > mValue
Definition: hikdump.h:681
bool Write(HIKFile pFile) const
Definition: hikdump_std.inl:90
bool Read(HIKFile pFile, bool bSwap)
Definition: hikdump_std.inl:97
bool HIKSaveEffectorState(const char *pFileName, HIKEffectorSetState *pState, float pUnitScale=1.0f)
Save HIKEffectorSetState pState to file pFileName.
Definition: hikdump.h:644
Marks the end of the enumeration.
Definition: hikproperty.h:513
HIKCharacter * HIKCharacterCreate(const HIKCharacterDefinition *pCharacterDefinition, HIKMalloc pMalloc, const char *pValidationString)
Create a new HIKCharacter.
Py_ssize_t count
Definition: abstract.h:1077
HIKPropertySetState * HIKLoadPropertySetState(const char *pFileName, HIKMalloc pMalloc)
Load file pFileName, and create an HIKPropertySetState object from its contents.
Definition: hikdump.h:719