BVB Source Codes

CRYENGINE Show AttachmentVCloth.cpp Source code

Return Download CRYENGINE: download AttachmentVCloth.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. #include "stdafx.h"
  4.  
  5. #include "AttachmentBase.h"
  6. #include "CharacterManager.h"
  7. #include "CharacterInstance.h"
  8. #include "Vertex/VertexData.h"
  9. #include "Vertex/VertexCommand.h"
  10. #include "Vertex/VertexCommandBuffer.h"
  11. #include "AttachmentManager.h"
  12. #include "AttachmentVCloth.h"
  13. #include <CryRenderer/IRenderAuxGeom.h>
  14. #include <CryRenderer/IShader.h>
  15. #include "ModelMesh.h"
  16. #include <CryMath/QTangent.h>
  17. #include <CryThreading/IJobManager_JobDelegator.h>
  18.  
  19. void CAttachmentVCLOTH::ReleaseSoftwareRenderMeshes()
  20. {
  21.         m_pRenderMeshsSW[0] = NULL;
  22.         m_pRenderMeshsSW[1] = NULL;
  23. }
  24.  
  25. uint32 CAttachmentVCLOTH::Immediate_AddBinding( IAttachmentObject* pIAttachmentObject,ISkin* pISkinRender,uint32 nLoadingFlags )
  26. {
  27.         if (pIAttachmentObject==0)
  28.                 return 0; //no attachment objects
  29.  
  30.         if (pISkinRender==0)
  31.                 CryFatalError("CryAnimation: if you create the binding for a Skin-Attachment, then you have to pass the pointer to an ISkin as well");
  32.  
  33.         uint32 nLogWarnings = (nLoadingFlags&CA_DisableLogWarnings)==0;
  34.         CSkin* pCSkinRenderModel = (CSkin*)pISkinRender;
  35.  
  36.         //only the SKIN-Instance is allowed to keep a smart-ptr CSkin object
  37.         //this should prevent ptr-hijacking in the future
  38.         if (m_pRenderSkin!=pCSkinRenderModel)
  39.         {
  40.                 ReleaseRenderSkin();
  41.                 g_pCharacterManager->RegisterInstanceVCloth(pCSkinRenderModel,this); //register this CAttachmentVCLOTH instance in CSkin.
  42.                 m_pRenderSkin=pCSkinRenderModel;            //increase the Ref-Counter         
  43.         }
  44.  
  45.         CCharInstance* pInstanceSkel = m_pAttachmentManager->m_pSkelInstance;
  46.         CDefaultSkeleton* pDefaultSkeleton = pInstanceSkel->m_pDefaultSkeleton;
  47.  
  48.         const char* pSkelFilePath = pDefaultSkeleton->GetModelFilePath();
  49.         const char* pSkinFilePath = m_pRenderSkin->GetModelFilePath();
  50.  
  51.         uint32 numJointsSkel = pDefaultSkeleton->m_arrModelJoints.size();
  52.         uint32 numJointsSkin = m_pRenderSkin->m_arrModelJoints.size();
  53.  
  54.         uint32 NotMatchingNames=0;
  55.         m_arrRemapTable.resize(numJointsSkin, 0);
  56.         for(uint32 js=0; js<numJointsSkin; js++)
  57.         {
  58.                 const int32 nID = pDefaultSkeleton->GetJointIDByCRC32(m_pRenderSkin->m_arrModelJoints[js].m_nJointCRC32Lower);
  59.                 if (nID>=0)
  60.                         m_arrRemapTable[js]=nID;
  61. #ifdef EDITOR_PCDEBUGCODE
  62.                 else
  63.                         NotMatchingNames++,g_pILog->LogError ("The joint-name (%s) of SKIN (%s) was not found in SKEL:  %s",m_pRenderSkin->m_arrModelJoints[js].m_NameModelSkin.c_str(),pSkinFilePath,pSkelFilePath);
  64. #endif
  65.         } //for loop
  66.  
  67.         if (NotMatchingNames)
  68.         {
  69.                 if (pInstanceSkel->m_CharEditMode)
  70.                 {
  71.                         //for now limited to CharEdit
  72.                         RecreateDefaultSkeleton(pInstanceSkel,nLoadingFlags);
  73.                 }
  74.                 else
  75.                 {
  76.                         if (nLogWarnings)
  77.                         {
  78.                                 CryLogAlways("SKEL: %s",pDefaultSkeleton->GetModelFilePath() );
  79.                                 CryLogAlways("SKIN: %s",m_pRenderSkin->GetModelFilePath() );
  80.                                 uint32 numJointCount = pDefaultSkeleton->GetJointCount();
  81.                                 for (uint32 i=0; i<numJointCount; i++)
  82.                                 {
  83.                                         const char* pJointName = pDefaultSkeleton->GetJointNameByID(i);
  84.                                         CryLogAlways("%03d JointName: %s",i,pJointName );
  85.                                 }
  86.                         }
  87.  
  88.                         // Free the new attachment as we cannot use it
  89.                         SAFE_RELEASE(pIAttachmentObject);
  90.                         return 0; //critical! incompatible skeletons. cant create skin-attachment
  91.                 }
  92.         }
  93.  
  94.         // Patch the remapping
  95.         for (size_t i=0; i<m_pRenderSkin->GetNumLODs(); i++)
  96.         {
  97.                 CModelMesh* pModelMesh = m_pRenderSkin->GetModelMesh(i);
  98.                 IRenderMesh* pRenderMesh = pModelMesh->m_pIRenderMesh;
  99.                 if (!pRenderMesh)
  100.                         continue;
  101.                 pRenderMesh->CreateRemappedBoneIndicesPair(m_arrRemapTable, pDefaultSkeleton->GetGuid(), this);
  102.         }
  103.  
  104.         SAFE_RELEASE(m_pIAttachmentObject);
  105.         m_pIAttachmentObject=pIAttachmentObject;
  106.         return 1;
  107. }
  108.  
  109. void CAttachmentVCLOTH::ComputeClothCacheKey()
  110. {
  111.         uint32 keySimMesh = CCrc32::ComputeLowercase(m_pSimSkin->GetModelFilePath());
  112.         uint32 keyRenderMesh = CCrc32::ComputeLowercase(m_pRenderSkin->GetModelFilePath());
  113.         m_clothCacheKey = (((uint64)keySimMesh) << 32) | keyRenderMesh;
  114. }
  115.  
  116. void CAttachmentVCLOTH::AddClothParams(const SVClothParams& clothParams)
  117. {
  118.         m_clothPiece.SetClothParams(clothParams);
  119. }
  120.  
  121. bool CAttachmentVCLOTH::InitializeCloth()
  122. {
  123.         return m_clothPiece.Initialize(this);
  124. }
  125.  
  126. const SVClothParams& CAttachmentVCLOTH::GetClothParams()
  127. {
  128.         return m_clothPiece.GetClothParams();
  129. }
  130.  
  131. uint32 CAttachmentVCLOTH::AddSimBinding( const ISkin& pISkinRender,uint32 nLoadingFlags )
  132. {
  133.         uint32 nLogWarnings = (nLoadingFlags&CA_DisableLogWarnings)==0;
  134.         CSkin* pCSkinRenderModel = (CSkin*)&pISkinRender;
  135.  
  136.         //only the VCLOTH-Instance is allowed to keep a smart-ptr CSkin object
  137.         //this should prevent ptr-hijacking in the future
  138.         if (m_pSimSkin!=pCSkinRenderModel)
  139.         {
  140.                 ReleaseSimSkin();
  141.                 g_pCharacterManager->RegisterInstanceVCloth(pCSkinRenderModel,this); //register this CAttachmentVCLOTH instance in CSkin.
  142.                 m_pSimSkin=pCSkinRenderModel;            //increase the Ref-Counter            
  143.         }
  144.  
  145.         CCharInstance* pInstanceSkel = m_pAttachmentManager->m_pSkelInstance;
  146.         CDefaultSkeleton* pDefaultSkeleton = pInstanceSkel->m_pDefaultSkeleton;
  147.  
  148.         const char* pSkelFilePath = pDefaultSkeleton->GetModelFilePath();
  149.         const char* pSkinFilePath = m_pSimSkin->GetModelFilePath();
  150.  
  151.         uint32 numJointsSkel = pDefaultSkeleton->m_arrModelJoints.size();
  152.         uint32 numJointsSkin = m_pSimSkin->m_arrModelJoints.size();
  153.  
  154.         uint32 NotMatchingNames=0;
  155.         m_arrSimRemapTable.resize(numJointsSkin, 0);
  156.         for(uint32 js=0; js<numJointsSkin; js++)
  157.         {
  158.                 const int32 nID = pDefaultSkeleton->GetJointIDByCRC32(m_pSimSkin->m_arrModelJoints[js].m_nJointCRC32Lower);
  159.                 if (nID>=0)
  160.                         m_arrSimRemapTable[js]=nID;
  161. #ifdef EDITOR_PCDEBUGCODE
  162.                 else
  163.                         NotMatchingNames++,g_pILog->LogError ("The joint-name (%s) of SKIN (%s) was not found in SKEL:  %s",m_pSimSkin->m_arrModelJoints[js].m_NameModelSkin.c_str(),pSkinFilePath,pSkelFilePath);
  164. #endif
  165.         } //for loop
  166.  
  167.         if (NotMatchingNames)
  168.         {
  169.                 CryFatalError("CryAnimation: the simulation-attachment is supposed to have the same skeleton as the render-attachment");
  170.                 return 0; //critical! incompatible skeletons. cant create skin-attachment
  171.         }
  172.  
  173.         return 1;
  174. }
  175.  
  176. void CAttachmentVCLOTH::Immediate_ClearBinding(uint32 nLoadingFlags)
  177. {
  178.         if (m_pIAttachmentObject)
  179.         {
  180.                 m_pIAttachmentObject->Release();
  181.                 m_pIAttachmentObject = 0;
  182.  
  183.                 ReleaseRenderSkin();
  184.                 ReleaseSimSkin();
  185.  
  186.                 if (nLoadingFlags&CA_SkipSkelRecreation)
  187.                         return;
  188.                 //for now limited to CharEdit
  189. //              CCharInstance* pInstanceSkel = m_pAttachmentManager->m_pSkelInstance;
  190. //              if (pInstanceSkel->GetCharEditMode())
  191. //                      RecreateDefaultSkeleton(pInstanceSkel,CA_CharEditModel|nLoadingFlags);
  192.         }
  193. };
  194.  
  195. void CAttachmentVCLOTH::RecreateDefaultSkeleton(CCharInstance* pInstanceSkel, uint32 nLoadingFlags)
  196. {
  197.         CDefaultSkeleton* const pDefaultSkeleton = pInstanceSkel->m_pDefaultSkeleton;
  198.  
  199.         const char* pOriginalFilePath = pDefaultSkeleton->GetModelFilePath();
  200.         if (pDefaultSkeleton->GetModelFilePathCRC64() && pOriginalFilePath[0]=='_')
  201.         {
  202.                 pOriginalFilePath++; // All extended skeletons have an '_' in front of the filepath to not confuse them with regular skeletons.
  203.         }
  204.  
  205.         CDefaultSkeleton* pOrigDefaultSkeleton = g_pCharacterManager->CheckIfModelSKELLoaded(pOriginalFilePath,nLoadingFlags);
  206.         if (!pOrigDefaultSkeleton)
  207.         {
  208.                 return;
  209.         }
  210.  
  211.         pOrigDefaultSkeleton->SetKeepInMemory(true);
  212.  
  213.         std::vector<const char*> mismatchingSkins;
  214.         uint64 nExtendedCRC64 = CCrc32::ComputeLowercase(pOriginalFilePath);
  215.         for (auto && pAttachment : m_pAttachmentManager->m_arrAttachments)
  216.         {
  217.                 if (pAttachment->GetType() != CA_VCLOTH)
  218.                 {
  219.                         continue;
  220.                 }
  221.  
  222.                 const CSkin* const pSkin = static_cast<CAttachmentVCLOTH*>(pAttachment.get())->m_pRenderSkin;
  223.                 if (!pSkin)
  224.         {
  225.                         continue;
  226.                 }
  227.  
  228.                 const char* const pSkinFilename = pSkin->GetModelFilePath();
  229.                 mismatchingSkins.push_back(pSkinFilename);
  230.                 nExtendedCRC64 += CCrc32::ComputeLowercase(pSkinFilename);
  231.         }
  232.  
  233.         CDefaultSkeleton* const pExtDefaultSkeleton = g_pCharacterManager->CreateExtendedSkel(pInstanceSkel, pOrigDefaultSkeleton, nExtendedCRC64, mismatchingSkins, nLoadingFlags);
  234.         if (pExtDefaultSkeleton)
  235.         {
  236.                 pInstanceSkel->RuntimeInit(pExtDefaultSkeleton);
  237.                 m_pAttachmentManager->m_TypeSortingRequired++;
  238.                 m_pAttachmentManager->UpdateAllRemapTables();
  239.         }
  240. }
  241.  
  242. void CAttachmentVCLOTH::UpdateRemapTable()
  243. {
  244.         if (m_pRenderSkin==0)
  245.                 return;
  246.  
  247.         ReleaseRenderRemapTablePair();
  248.         ReleaseSimRemapTablePair();
  249.         CCharInstance* pInstanceSkel = m_pAttachmentManager->m_pSkelInstance;
  250.         CDefaultSkeleton* pDefaultSkeleton = pInstanceSkel->m_pDefaultSkeleton;
  251.  
  252.         const char* pSkelFilePath = pDefaultSkeleton->GetModelFilePath();
  253.         const char* pSkinFilePath = m_pRenderSkin->GetModelFilePath();
  254.  
  255.         uint32 numJointsSkel = pDefaultSkeleton->m_arrModelJoints.size();
  256.         uint32 numJointsSkin = m_pRenderSkin->m_arrModelJoints.size();
  257.  
  258.         m_arrRemapTable.resize(numJointsSkin, 0);
  259.         for(uint32 js=0; js<numJointsSkin; js++)
  260.         {
  261.                 const int32 nID = pDefaultSkeleton->GetJointIDByCRC32(m_pRenderSkin->m_arrModelJoints[js].m_nJointCRC32Lower);
  262.                 if (nID>=0)
  263.                         m_arrRemapTable[js]=nID;
  264.                 else
  265.                         CryFatalError("ModelError: data-corruption when executing UpdateRemapTable for SKEL (%s) and SKIN (%s) ",pSkelFilePath,pSkinFilePath); //a fail in this case is virtually impossible, because the SKINs are alread attached
  266.         }
  267.  
  268.         // Patch the remapping
  269.         for (size_t i=0; i<m_pRenderSkin->GetNumLODs(); i++)
  270.         {
  271.                 CModelMesh* pModelMesh = m_pRenderSkin->GetModelMesh(i);
  272.                 IRenderMesh* pRenderMesh = pModelMesh->m_pIRenderMesh;
  273.                 if (!pRenderMesh)
  274.                         continue;
  275.                 pRenderMesh->CreateRemappedBoneIndicesPair(m_arrRemapTable, pDefaultSkeleton->GetGuid(), this);
  276.         }
  277.  
  278.         CModelMesh* pSimModelMesh = m_pSimSkin->GetModelMesh(0);
  279.         IRenderMesh* pSimRenderMesh = pSimModelMesh->m_pIRenderMesh;
  280.         if (pSimRenderMesh)
  281.                 pSimRenderMesh->CreateRemappedBoneIndicesPair(m_arrSimRemapTable, pDefaultSkeleton->GetGuid(), this);
  282. }
  283.  
  284. void CAttachmentVCLOTH::ReleaseSimRemapTablePair()
  285. {
  286.         if (!m_pSimSkin)
  287.                 return;
  288.  
  289.         CCharInstance* pInstanceSkel = m_pAttachmentManager->m_pSkelInstance;
  290.         CDefaultSkeleton* pModelSkel = pInstanceSkel->m_pDefaultSkeleton;
  291.         const uint skeletonGuid = pModelSkel->GetGuid();
  292.  
  293.         CModelMesh* pModelSimMesh = m_pSimSkin->GetModelMesh(0);
  294.         IRenderMesh* pSimRenderMesh = pModelSimMesh->m_pIRenderMesh;
  295.         if (pSimRenderMesh)
  296.                 pSimRenderMesh->ReleaseRemappedBoneIndicesPair(skeletonGuid);
  297. }
  298.  
  299. void CAttachmentVCLOTH::ReleaseRenderRemapTablePair()
  300. {
  301.         if (!m_pRenderSkin)
  302.                 return;
  303.  
  304.         CCharInstance* pInstanceSkel = m_pAttachmentManager->m_pSkelInstance;
  305.         CDefaultSkeleton* pModelSkel = pInstanceSkel->m_pDefaultSkeleton;
  306.         const uint skeletonGuid = pModelSkel->GetGuid();
  307.         for (size_t i=0; i<m_pRenderSkin->GetNumLODs(); i++)
  308.         {
  309.                 CModelMesh* pModelMesh = m_pRenderSkin->GetModelMesh(i);
  310.                 IRenderMesh* pRenderMesh = pModelMesh->m_pIRenderMesh;
  311.                 if (!pRenderMesh)
  312.                         continue;
  313.                 pRenderMesh->ReleaseRemappedBoneIndicesPair(skeletonGuid);
  314.         }
  315. }
  316.  
  317. uint32 CAttachmentVCLOTH::Immediate_SwapBinding(IAttachment* pNewAttachment)
  318. {
  319.         CryWarning(VALIDATOR_MODULE_ANIMATION, VALIDATOR_WARNING, "[Cloth] CAttachmentVCLOTH::SwapBinding attempting to swap skin attachment bindings this is not supported");
  320.         return 0;
  321. }
  322.  
  323. float CAttachmentVCLOTH::GetExtent(EGeomForm eForm)
  324. {
  325.         if (m_pRenderSkin)
  326.         {
  327.                 int nLOD = m_pRenderSkin->SelectNearestLoadedLOD(0);
  328.                 if (IRenderMesh* pMesh = m_pRenderSkin->GetIRenderMesh(nLOD))
  329.                         return pMesh->GetExtent(eForm);
  330.         }
  331.         return 0.f;
  332. }
  333.  
  334. void CAttachmentVCLOTH::GetRandomPos(PosNorm& ran, CRndGen& seed, EGeomForm eForm) const
  335. {
  336.         int nLOD = m_pRenderSkin->SelectNearestLoadedLOD(0);
  337.         IRenderMesh* pMesh = m_pRenderSkin->GetIRenderMesh(nLOD);
  338.  
  339.         SSkinningData* pSkinningData = NULL;
  340.         int nFrameID = gEnv->pRenderer->EF_GetSkinningPoolID();
  341.         for (int n = 0; n < 3; n++)
  342.         {
  343.                 int nList = (nFrameID-n) % 3;
  344.                 if (m_arrSkinningRendererData[nList].nFrameID == nFrameID-n)
  345.                 {
  346.                         pSkinningData = m_arrSkinningRendererData[nList].pSkinningData;
  347.                         break;
  348.                 }
  349.         }
  350.  
  351.         pMesh->GetRandomPos(ran, seed, eForm, pSkinningData);
  352. }
  353.  
  354. const QuatTS CAttachmentVCLOTH::GetAttWorldAbsolute() const
  355. {
  356.         QuatTS rPhysLocation = m_pAttachmentManager->m_pSkelInstance->m_location;
  357.         return rPhysLocation;
  358. };
  359.  
  360. void CAttachmentVCLOTH::UpdateAttModelRelative()
  361. {
  362. }
  363.  
  364. int CAttachmentVCLOTH::GetGuid() const
  365. {
  366.         return m_pAttachmentManager->m_pSkelInstance->m_pDefaultSkeleton->GetGuid();
  367. }
  368.  
  369. void CAttachmentVCLOTH::ReleaseRenderSkin()
  370. {
  371.         if (m_pRenderSkin)
  372.         {
  373.                 g_pCharacterManager->UnregisterInstanceVCloth(m_pRenderSkin,this);
  374.                 ReleaseRenderRemapTablePair();
  375.                 m_pRenderSkin = 0;
  376.         }
  377. }
  378.  
  379. void CAttachmentVCLOTH::ReleaseSimSkin()
  380. {
  381.         if (m_pSimSkin)
  382.         {
  383.                 g_pCharacterManager->UnregisterInstanceVCloth(m_pSimSkin,this);
  384.                 ReleaseSimRemapTablePair();
  385.                 m_pSimSkin = 0;
  386.         }
  387. }
  388.  
  389. CAttachmentVCLOTH::~CAttachmentVCLOTH()
  390. {
  391.         const int nFrameID = gEnv->pRenderer ? gEnv->pRenderer->EF_GetSkinningPoolID() : 0;
  392.         const int nList = nFrameID % 3;
  393.         if(m_arrSkinningRendererData[nList].nFrameID == nFrameID && m_arrSkinningRendererData[nList].pSkinningData)
  394.         {                              
  395.                 if(m_arrSkinningRendererData[nList].pSkinningData->pAsyncJobs)
  396.                         gEnv->pJobManager->WaitForJob( *m_arrSkinningRendererData[nList].pSkinningData->pAsyncJobs );
  397.         }
  398.  
  399.         m_vertexAnimation.SetClothData(NULL);
  400.         ReleaseRenderSkin();
  401.         ReleaseSimSkin();
  402.  
  403.         CVertexAnimation::RemoveSoftwareRenderMesh(this);
  404.         for (uint32 j=0; j<2; ++j)
  405.                 m_pRenderMeshsSW[j] = NULL;
  406. }
  407.  
  408. void CAttachmentVCLOTH::Serialize(TSerialize ser)
  409. {
  410.         if (ser.GetSerializationTarget() != eST_Network)
  411.         {
  412.                 ser.BeginGroup("CAttachmentVCLOTH");
  413.  
  414.                 bool bHideInMainPass;
  415.  
  416.                 if (ser.IsWriting())
  417.                 {
  418.                         bHideInMainPass = ((m_AttFlags & FLAGS_ATTACH_HIDE_MAIN_PASS) == FLAGS_ATTACH_HIDE_MAIN_PASS);
  419.                 }
  420.  
  421.                 ser.Value("HideInMainPass", bHideInMainPass);
  422.  
  423.                 if (ser.IsReading())
  424.                 {
  425.                         HideAttachment(bHideInMainPass);
  426.                 }
  427.  
  428.                 ser.EndGroup();
  429.         }
  430. }
  431.  
  432. size_t CAttachmentVCLOTH::SizeOfThis() const
  433. {
  434.         size_t nSize = sizeof(CAttachmentVCLOTH) + sizeofVector(m_strSocketName);
  435.         nSize += m_arrRemapTable.get_alloc_size();
  436.         return nSize;
  437. }
  438.  
  439. void CAttachmentVCLOTH::GetMemoryUsage( ICrySizer *pSizer ) const
  440. {
  441.         pSizer->AddObject(this, sizeof(*this));
  442.         pSizer->AddObject( m_strSocketName );
  443.         pSizer->AddObject( m_arrRemapTable );  
  444. }
  445.  
  446. namespace VClothUtils
  447. {
  448. ILINE void DrawVertexDebug(
  449.         IRenderMesh* pRenderMesh, const QuatT& location,
  450.         const SVertexAnimationJob* pVertexAnimation,
  451.         const SVertexSkinData& vertexSkinData)
  452. {
  453.         static const ColorB SKINNING_COLORS[8] =
  454.         {
  455.                 ColorB(0x40, 0x40, 0xff, 0xff),
  456.                 ColorB(0x40, 0x80, 0xff, 0xff),
  457.                 ColorB(0x40, 0xff, 0x40, 0xff),
  458.                 ColorB(0x80, 0xff, 0x40, 0xff),
  459.  
  460.                 ColorB(0xff, 0x80, 0x40, 0xff),
  461.                 ColorB(0xff, 0x80, 0x80, 0xff),
  462.                 ColorB(0xff, 0xc0, 0xc0, 0xff),
  463.                 ColorB(0xff, 0xff, 0xff, 0xff),
  464.         };
  465.  
  466.         // wait till the SW-Skinning jobs have finished
  467.         while(*pVertexAnimation->pRenderMeshSyncVariable)                              
  468.                 CrySleep(1);                           
  469.  
  470.         IRenderMesh* pIRenderMesh = pRenderMesh;
  471.         strided_pointer<Vec3> parrDstPositions = pVertexAnimation->vertexData.pPositions;
  472.         strided_pointer<SPipTangents> parrDstTangents;
  473.         parrDstTangents.data = (SPipTangents*)pVertexAnimation->vertexData.pTangents.data;
  474.         parrDstTangents.iStride = sizeof(SPipTangents);
  475.  
  476.         uint32 numExtVertices = pIRenderMesh->GetVerticesCount();
  477.         if (parrDstPositions && parrDstTangents)
  478.         {
  479.                 static DynArray<Vec3>           arrDstPositions;
  480.                 static DynArray<ColorB> arrDstColors;
  481.                 uint32 numDstPositions=arrDstPositions.size();
  482.                 if (numDstPositions<numExtVertices)
  483.                 {
  484.                         arrDstPositions.resize(numExtVertices);
  485.                         arrDstColors.resize(numExtVertices);
  486.                 }
  487.  
  488.                 //transform vertices by world-matrix
  489.                 for (uint32 i=0; i<numExtVertices; ++i)
  490.                         arrDstPositions[i]      = location*parrDstPositions[i];
  491.  
  492.                 //render faces as wireframe
  493.                 if (Console::GetInst().ca_DebugSWSkinning == 1)
  494.                 {
  495.                         for (uint i=0; i<CRY_ARRAY_COUNT(SKINNING_COLORS); ++i)
  496.                                 g_pAuxGeom->Draw2dLabel(32.0f+float(i*16), 32.0f, 2.0f, ColorF(SKINNING_COLORS[i].r/255.0f, SKINNING_COLORS[i].g/255.0f, SKINNING_COLORS[i].b/255.0f, 1.0f), false, "%d", i+1);
  497.  
  498.                         for (uint32 e=0; e<numExtVertices; e++)
  499.                         {
  500.                                 uint32 w=0;
  501.                                 const SoftwareVertexBlendWeight* pBlendWeights = &vertexSkinData.pVertexTransformWeights[e];
  502.                                 for (uint c=0; c<vertexSkinData.vertexTransformCount; ++c)
  503.                                 {
  504.                                         if (pBlendWeights[c] > 0.0f)
  505.                                                 w++;
  506.                                 }
  507.  
  508.                                 if (w) --w;
  509.                                 arrDstColors[e] = w < 8 ? SKINNING_COLORS[w] : ColorB(0x00, 0x00, 0x00, 0xff);
  510.                         }
  511.  
  512.                         pIRenderMesh->LockForThreadAccess();
  513.                         uint32  numIndices = pIRenderMesh->GetIndicesCount();
  514.                         vtx_idx* pIndices = pIRenderMesh->GetIndexPtr(FSL_READ);
  515.  
  516.                         IRenderAuxGeom* pAuxGeom =      gEnv->pRenderer->GetIRenderAuxGeom();
  517.                         SAuxGeomRenderFlags renderFlags( e_Def3DPublicRenderflags );
  518.                         renderFlags.SetFillMode( e_FillModeWireframe );
  519.                         //              renderFlags.SetAlphaBlendMode(e_AlphaAdditive);
  520.                         renderFlags.SetDrawInFrontMode( e_DrawInFrontOn );
  521.                         pAuxGeom->SetRenderFlags( renderFlags );
  522.                         //      pAuxGeom->DrawTriangles(&arrDstPositions[0],numExtVertices, pIndices,numIndices,RGBA8(0x00,0x17,0x00,0x00));           
  523.                         pAuxGeom->DrawTriangles(&arrDstPositions[0],numExtVertices, pIndices,numIndices,&arrDstColors[0]);             
  524.  
  525.                         pIRenderMesh->UnLockForThreadAccess();
  526.                 }      
  527.  
  528.                 //render the Normals
  529.                 if (Console::GetInst().ca_DebugSWSkinning == 2)
  530.                 {
  531.                         IRenderAuxGeom* pAuxGeom =      gEnv->pRenderer->GetIRenderAuxGeom();
  532.                         static std::vector<ColorB> arrExtVColors;
  533.                         uint32 csize = arrExtVColors.size();
  534.                         if (csize<(numExtVertices*2)) arrExtVColors.resize( numExtVertices*2 );
  535.                         for(uint32 i=0; i<numExtVertices*2; i=i+2)     
  536.                         {
  537.                                 arrExtVColors[i+0] = RGBA8(0x00,0x00,0x3f,0x1f);
  538.                                 arrExtVColors[i+1] = RGBA8(0x7f,0x7f,0xff,0xff);
  539.                         }
  540.  
  541.                         Matrix33 WMat33 = Matrix33(location.q);
  542.                         static std::vector<Vec3> arrExtSkinnedStream;
  543.                         uint32 numExtSkinnedStream = arrExtSkinnedStream.size();
  544.                         if (numExtSkinnedStream<(numExtVertices*2)) arrExtSkinnedStream.resize( numExtVertices*2 );    
  545.                         for(uint32 i=0,t=0; i<numExtVertices; i++)     
  546.                         {
  547.                                 Vec3 vNormal = parrDstTangents[i].GetN().GetNormalized() * 0.03f;
  548.  
  549.                                 arrExtSkinnedStream[t+0] = arrDstPositions[i];
  550.                                 arrExtSkinnedStream[t+1] = WMat33*vNormal + arrExtSkinnedStream[t];
  551.                                 t=t+2;
  552.                         }
  553.                         SAuxGeomRenderFlags renderFlags( e_Def3DPublicRenderflags );
  554.                         pAuxGeom->SetRenderFlags( renderFlags );
  555.                         pAuxGeom->DrawLines( &arrExtSkinnedStream[0],numExtVertices*2, &arrExtVColors[0]);             
  556.                 }
  557.         }
  558. }
  559. }
  560. _smart_ptr<IRenderMesh> CAttachmentVCLOTH::CreateVertexAnimationRenderMesh(uint lod, uint id)
  561. {
  562.         m_pRenderMeshsSW[id] = NULL; // smart pointer release
  563.  
  564.         if (m_pRenderSkin == 0)
  565.                 return _smart_ptr<IRenderMesh>(NULL);
  566.  
  567.         uint32 numModelMeshes = m_pRenderSkin->m_arrModelMeshes.size();
  568.         if (lod >= numModelMeshes)
  569.                 return _smart_ptr<IRenderMesh>(NULL);
  570.  
  571.         _smart_ptr<IRenderMesh> pIStaticRenderMesh = m_pRenderSkin->m_arrModelMeshes[lod].m_pIRenderMesh;
  572.         if (pIStaticRenderMesh==0)
  573.                 return _smart_ptr<IRenderMesh>(NULL);
  574.         ;
  575.  
  576.         CModelMesh* pModelMesh = m_pRenderSkin->GetModelMesh(lod);
  577.         uint32 success = pModelMesh->InitSWSkinBuffer();
  578.         if (success==0)
  579.                 return _smart_ptr<IRenderMesh>(NULL);
  580.         ;
  581.  
  582.         if (m_sSoftwareMeshName.empty() && pIStaticRenderMesh->GetSourceName() != NULL)
  583.         {
  584.                 m_sSoftwareMeshName.reserve(strlen(pIStaticRenderMesh->GetSourceName()) + 3);
  585.                 m_sSoftwareMeshName = pIStaticRenderMesh->GetSourceName();
  586.                 m_sSoftwareMeshName += "_SW";
  587.         }
  588.  
  589.         m_pRenderMeshsSW[id] = g_pIRenderer->CreateRenderMeshInitialized(
  590.                 NULL
  591.                 , pIStaticRenderMesh->GetVerticesCount()
  592.                 , eVF_P3F_C4B_T2F
  593.                 , NULL
  594.                 , pIStaticRenderMesh->GetIndicesCount()
  595.                 , prtTriangleList
  596.                 , "Character"
  597.                 , m_sSoftwareMeshName.c_str()
  598.                 , eRMT_Transient);
  599.  
  600.         m_pRenderMeshsSW[id]->SetMeshLod(lod);
  601.  
  602.         TRenderChunkArray& chunks = pIStaticRenderMesh->GetChunks();
  603.         TRenderChunkArray  nchunks;
  604.         nchunks.resize(chunks.size());
  605.         for (size_t i=0; i<size_t(chunks.size()); ++i)
  606.         {
  607.                 nchunks[i].m_texelAreaDensity = chunks[i].m_texelAreaDensity;
  608.                 nchunks[i].nFirstIndexId = chunks[i].nFirstIndexId;
  609.                 nchunks[i].nNumIndices = chunks[i].nNumIndices;
  610.                 nchunks[i].nFirstVertId = chunks[i].nFirstVertId;
  611.                 nchunks[i].nNumVerts = chunks[i].nNumVerts;
  612. #ifdef SUBDIVISION_ACC_ENGINE
  613.                 nchunks[i].nFirstFaceId = chunks[i].nFirstFaceId;
  614.                 nchunks[i].nNumFaces = chunks[i].nNumFaces;
  615.                 nchunks[i].nPrimitiveType = chunks[i].nPrimitiveType;
  616. #endif
  617.                 nchunks[i].m_nMatFlags = chunks[i].m_nMatFlags;
  618.                 nchunks[i].m_nMatID = chunks[i].m_nMatID;
  619.                 nchunks[i].nSubObjectIndex = chunks[i].nSubObjectIndex;
  620.         }
  621.         m_pRenderMeshsSW[id]->SetRenderChunks(&nchunks[0], nchunks.size(), false);
  622.  
  623. #ifndef _RELEASE
  624.         m_vertexAnimation.m_vertexAnimationStats.sCharInstanceName = m_pAttachmentManager->m_pSkelInstance->GetFilePath();
  625.         m_vertexAnimation.m_vertexAnimationStats.sAttachmentName = "";//m_Name; TODO fix
  626.         m_vertexAnimation.m_vertexAnimationStats.pCharInstance = m_pAttachmentManager->m_pSkelInstance;
  627. #endif
  628.         return m_pRenderMeshsSW[id];
  629. }
  630.  
  631. void CAttachmentVCLOTH::DrawAttachment(SRendParams& RendParams, const SRenderingPassInfo &passInfo, const Matrix34& rWorldMat34, f32 fZoomFactor)
  632. {
  633.         //-----------------------------------------------------------------------------
  634.         //---              map logical LOD to render LOD                            ---
  635.         //-----------------------------------------------------------------------------
  636.         int32 numLODs = m_pRenderSkin->m_arrModelMeshes.size();
  637.         if (numLODs==0)
  638.                 return;
  639.         int nDesiredRenderLOD = RendParams.lodValue.LodA();
  640.         if (nDesiredRenderLOD == -1)
  641.                 nDesiredRenderLOD = RendParams.lodValue.LodB();
  642.         if(nDesiredRenderLOD>=numLODs)
  643.         {
  644.                 if (m_AttFlags&FLAGS_ATTACH_RENDER_ONLY_EXISTING_LOD)
  645.                         return;  //early exit, if LOD-file doesn't exist
  646.                 nDesiredRenderLOD = numLODs-1; //render the last existing LOD-file
  647.         }
  648.         int nRenderLOD = m_pRenderSkin->SelectNearestLoadedLOD(nDesiredRenderLOD);  //we can render only loaded LODs
  649.  
  650.         m_pRenderSkin->m_arrModelMeshes[nRenderLOD].m_stream.nFrameId = passInfo.GetMainFrameID();
  651.         m_pSimSkin->m_arrModelMeshes[nRenderLOD].m_stream.nFrameId = passInfo.GetMainFrameID();
  652.  
  653.         //      float fColor[4] = {1,0,1,1};
  654.         //      extern f32 g_YLine;
  655.         //      g_pAuxGeom->Draw2dLabel( 1,g_YLine, 1.3f, fColor, false,"CSkin:  numLODs: %d  nLodLevel: %d   nRenderLOD: %d   Model: %s",numLODs, RendParams.nLod, nRenderLOD, m_pModelSkin->GetModelFilePath() ); g_YLine+=0x10;
  656.  
  657.         Matrix34 FinalMat34 = rWorldMat34;
  658.         RendParams.pMatrix = &FinalMat34;
  659.         RendParams.pInstance = this;
  660.         RendParams.pMaterial = (IMaterial*)m_pIAttachmentObject->GetReplacementMaterial(nRenderLOD); //the Replacement-Material has priority
  661.         if (RendParams.pMaterial==0)
  662.                 RendParams.pMaterial = (IMaterial*)m_pRenderSkin->GetIMaterial(nRenderLOD); //as a fall back take the Base-Material from the model
  663.  
  664.         bool bNewFrame = false;
  665.         if (m_vertexAnimation.m_skinningPoolID != gEnv->pRenderer->EF_GetSkinningPoolID())
  666.         {
  667.                 m_vertexAnimation.m_skinningPoolID = gEnv->pRenderer->EF_GetSkinningPoolID();
  668.                 ++m_vertexAnimation.m_RenderMeshId;
  669.                 bNewFrame = true;
  670.         }
  671.  
  672.         if (bNewFrame && nRenderLOD < m_clothPiece.GetNumLods())
  673.         {
  674.                 bool visible = m_clothPiece.IsAlwaysVisible(); //||
  675.                 //                      g_pCharacterManager->GetClothManager()->QueryVisibility((uint64)m_pAttachmentManager, center, passInfo.IsGeneralPass());
  676.                 if (m_clothPiece.PrepareCloth(m_pAttachmentManager->m_pSkelInstance->m_SkeletonPose, rWorldMat34, visible, nRenderLOD))
  677.                 {
  678.                         m_AttFlags |= FLAGS_ATTACH_SW_SKINNING;
  679.                         m_vertexAnimation.SetClothData(&m_clothPiece);
  680.                 }
  681.                 else
  682.                 {
  683.                         m_AttFlags &= ~FLAGS_ATTACH_SW_SKINNING;
  684.                         m_vertexAnimation.SetClothData(NULL);
  685.  
  686.                         CryWarning(VALIDATOR_MODULE_ANIMATION, VALIDATOR_WARNING, "[Cloth] Character cloth buffer exceeds maximum (results in flickering between skinning & simulation). Increase buffer size with global 'ca_ClothMaxChars'.");
  687.                 }
  688.         }
  689.  
  690.         //---------------------------------------------------------------------------------------------
  691.         //---------------------------------------------------------------------------------------------
  692.         //---------------------------------------------------------------------------------------------
  693.         CRenderObject* pObj = g_pIRenderer->EF_GetObject_Temp(passInfo.ThreadID());
  694.         if (!pObj)
  695.                 return;
  696.  
  697.         pObj->m_pRenderNode = RendParams.pRenderNode;
  698.         uint64 uLocalObjFlags = pObj->m_ObjFlags;
  699.  
  700.         //check if it should be drawn close to the player
  701.         CCharInstance* pMaster  =       m_pAttachmentManager->m_pSkelInstance;
  702.         if (pMaster->m_rpFlags & CS_FLAG_DRAW_NEAR)
  703.         {
  704.                 uLocalObjFlags |= FOB_NEAREST;
  705.         }
  706.         else
  707.         {
  708.                 uLocalObjFlags &= ~FOB_NEAREST;
  709.         }
  710.  
  711.         pObj->m_fAlpha = RendParams.fAlpha;
  712.         pObj->m_fDistance =     RendParams.fDistance;
  713.         pObj->m_II.m_AmbColor = RendParams.AmbientColor;
  714.  
  715.         uLocalObjFlags |= RendParams.dwFObjFlags;
  716.  
  717.         SRenderObjData* pD = pObj->GetObjData();
  718.  
  719.         // copy the shaderparams into the render object data from the render params
  720.         if (RendParams.pShaderParams && RendParams.pShaderParams->size() > 0)
  721.         {
  722.                 pD->SetShaderParams(RendParams.pShaderParams);
  723.         }
  724.  
  725.         pD->m_uniqueObjectId = reinterpret_cast<uintptr_t>(RendParams.pInstance);
  726.  
  727.         bool bCheckMotion = pMaster->MotionBlurMotionCheck(pObj->m_ObjFlags);
  728.         if (bCheckMotion)
  729.                 uLocalObjFlags |= FOB_MOTION_BLUR;
  730.  
  731.         assert(RendParams.pMatrix);
  732.         Matrix34 RenderMat34 = (*RendParams.pMatrix);
  733.         pObj->m_II.m_Matrix = RenderMat34;
  734.         pObj->m_nClipVolumeStencilRef = RendParams.nClipVolumeStencilRef;
  735.         pObj->m_nTextureID = RendParams.nTextureID;
  736.  
  737.         pObj->m_nMaterialLayers = RendParams.nMaterialLayersBlend;
  738.  
  739.         pD->m_nVisionParams = RendParams.nVisionParams;
  740.         pD->m_nHUDSilhouetteParams = RendParams.nHUDSilhouettesParams;
  741.  
  742.         pD->m_nCustomData = RendParams.nCustomData;
  743.         pD->m_nCustomFlags = RendParams.nCustomFlags;
  744.         if(RendParams.nCustomFlags & COB_CLOAK_HIGHLIGHT)
  745.         {
  746.                 pD->m_fTempVars[5] = RendParams.fCustomData[0];
  747.         }
  748.         else if(RendParams.nCustomFlags & COB_POST_3D_RENDER)
  749.         {
  750.                 memcpy(&pD->m_fTempVars[5],&RendParams.fCustomData[0],sizeof(float)*4);
  751.                 pObj->m_fAlpha = 1.0f; // Use the alpha in the post effect instead of here
  752.                 pD->m_fTempVars[9] = RendParams.fAlpha;
  753.         }
  754.         pObj->m_DissolveRef = RendParams.nDissolveRef;
  755.  
  756.         pObj->m_ObjFlags = uLocalObjFlags | FOB_INSHADOW | FOB_TRANS_MASK;
  757.  
  758.         if (g_pI3DEngine->IsTessellationAllowed(pObj, passInfo))
  759.         {
  760.                 // Allow this RO to be tessellated, however actual tessellation will be applied if enabled in material
  761.                 pObj->m_ObjFlags |= FOB_ALLOW_TESSELLATION;
  762.         }
  763.  
  764.         pObj->m_nSort = fastround_positive(RendParams.fDistance * 2.0f);
  765.  
  766.         const float SORT_BIAS_AMOUNT = 1.f;
  767.         if(pMaster->m_rpFlags & CS_FLAG_BIAS_SKIN_SORT_DIST)
  768.         {
  769.                 pObj->m_fSort = SORT_BIAS_AMOUNT;
  770.         }
  771.  
  772.         // get skinning data           
  773.         const int numClothLods = m_clothPiece.GetNumLods();
  774.         const bool swSkin = (nRenderLOD == 0) && (Console::GetInst().ca_vaEnable != 0) && (nRenderLOD < numClothLods);
  775.  
  776.         IF (!swSkin, 1)
  777.                 pObj->m_ObjFlags |= FOB_SKINNED;
  778.  
  779.         pD->m_pSkinningData = GetVertexTransformationData(swSkin, nRenderLOD);
  780.         m_pRenderSkin->m_arrModelMeshes[nRenderLOD].m_stream.nFrameId = passInfo.GetMainFrameID();
  781.         m_pSimSkin->m_arrModelMeshes[nRenderLOD].m_stream.nFrameId = passInfo.GetMainFrameID();
  782.  
  783.         Vec3 skinOffset = m_pRenderSkin->m_arrModelMeshes[nRenderLOD].m_vRenderMeshOffset;
  784.         pD->m_pSkinningData->vecPrecisionOffset[0] = skinOffset.x;
  785.         pD->m_pSkinningData->vecPrecisionOffset[1] = skinOffset.y;
  786.         pD->m_pSkinningData->vecPrecisionOffset[2] = skinOffset.z;
  787.  
  788.         SVertexAnimationJob *pVertexAnimation = static_cast<SVertexAnimationJob*>(pD->m_pSkinningData->pCustomData);
  789.  
  790.         IRenderMesh* pRenderMesh = m_pRenderSkin->GetIRenderMesh(nRenderLOD);          
  791.         if(swSkin && pRenderMesh)
  792.         {
  793.                 uint iCurrentRenderMeshID = m_vertexAnimation.m_RenderMeshId & 1;
  794.  
  795.                 if (bNewFrame)
  796.                 {
  797.                         CreateVertexAnimationRenderMesh(nRenderLOD, iCurrentRenderMeshID);
  798.                         CVertexAnimation::RegisterSoftwareRenderMesh((CAttachmentVCLOTH*)this);
  799.                 }
  800.  
  801.                 pRenderMesh = m_pRenderMeshsSW[iCurrentRenderMeshID];
  802.  
  803.                 IF (pRenderMesh && bNewFrame, 1)
  804.                 {
  805.                         CModelMesh* pModelMesh = m_pRenderSkin->GetModelMesh(nRenderLOD);
  806.                         CSoftwareMesh& geometry = pModelMesh->m_softwareMesh;
  807.  
  808.                         SVertexSkinData vertexSkinData = SVertexSkinData();
  809.                         vertexSkinData.pTransformations = pD->m_pSkinningData->pBoneQuatsS;
  810.                         vertexSkinData.pTransformationRemapTable = pD->m_pSkinningData->pRemapTable;
  811.                         vertexSkinData.transformationCount = pD->m_pSkinningData->nNumBones;
  812.                         vertexSkinData.pVertexPositions = geometry.GetPositions();
  813.                         vertexSkinData.pVertexColors = geometry.GetColors();
  814.                         vertexSkinData.pVertexCoords = geometry.GetCoords();
  815.                         vertexSkinData.pVertexTransformIndices = geometry.GetBlendIndices();
  816.                         vertexSkinData.pVertexTransformWeights = geometry.GetBlendWeights();
  817.                         vertexSkinData.vertexTransformCount = geometry.GetBlendCount();
  818.                         vertexSkinData.pIndices = geometry.GetIndices();
  819.                         vertexSkinData.indexCount = geometry.GetIndexCount();
  820.                         CRY_ASSERT(pRenderMesh->GetVerticesCount() == geometry.GetVertexCount());
  821.  
  822.                         // also update tangents & vertexCount to fix problems in skinning
  823.                         vertexSkinData.pVertexQTangents = geometry.GetTangents();
  824.                         vertexSkinData.pTangentUpdateTriangles = geometry.GetTangentUpdateData();
  825.                         vertexSkinData.tangetUpdateTriCount = geometry.GetTangentUpdateDataCount();
  826.                         vertexSkinData.pTangentUpdateVertIds = geometry.GetTangentUpdateVertIds();
  827.                         vertexSkinData.tangetUpdateVertIdsCount = geometry.GetTangentUpdateTriIdsCount();
  828.                         vertexSkinData.vertexCount = geometry.GetVertexCount();
  829.  
  830. #if CRY_PLATFORM_DURANGO
  831.                         const uint fslCreate = FSL_VIDEO_CREATE;
  832.                         const uint fslRead = FSL_READ|FSL_VIDEO;
  833. #else
  834.                         const uint fslCreate = FSL_SYSTEM_CREATE;
  835.                         const uint fslRead = FSL_READ;
  836. #endif
  837.  
  838.                         vertexSkinData.pVertexPositionsPrevious = strided_pointer<const Vec3>(NULL);
  839.                         if (pD->m_pSkinningData->pPreviousSkinningRenderData)
  840.                                 gEnv->pJobManager->WaitForJob(*pD->m_pSkinningData->pPreviousSkinningRenderData->pAsyncJobs);
  841.                         _smart_ptr<IRenderMesh>& pRenderMeshPrevious = m_pRenderMeshsSW[1 - iCurrentRenderMeshID];
  842.                         if (pRenderMeshPrevious != NULL)
  843.                         {
  844.                                 pRenderMeshPrevious->LockForThreadAccess();
  845.                                 Vec3* pPrevPositions = (Vec3*)pRenderMeshPrevious->GetPosPtrNoCache(vertexSkinData.pVertexPositionsPrevious.iStride, fslRead);
  846.                                 if (pPrevPositions)
  847.                                 {
  848.                                         vertexSkinData.pVertexPositionsPrevious.data = pPrevPositions;
  849.                                         pVertexAnimation->m_previousRenderMesh = pRenderMeshPrevious;
  850.                                 }
  851.                                 else
  852.                                 {
  853.                                         pRenderMeshPrevious->UnlockStream(VSF_GENERAL);
  854.                                         pRenderMeshPrevious->UnLockForThreadAccess();
  855.                                 }
  856.                         }
  857.                         m_vertexAnimation.SetSkinData(vertexSkinData);
  858.  
  859.                         pVertexAnimation->vertexData.m_vertexCount = pRenderMesh->GetVerticesCount();
  860.  
  861.                         pRenderMesh->LockForThreadAccess();
  862.  
  863.                         SVF_P3F_C4B_T2F *pGeneral = (SVF_P3F_C4B_T2F*)pRenderMesh->GetPosPtrNoCache(pVertexAnimation->vertexData.pPositions.iStride, fslCreate);
  864.  
  865.                         pVertexAnimation->vertexData.pPositions.data    = (Vec3*)(&pGeneral[0].xyz);
  866.                         pVertexAnimation->vertexData.pPositions.iStride = sizeof(pGeneral[0]);
  867.                         pVertexAnimation->vertexData.pColors.data       = (uint32*)(&pGeneral[0].color);
  868.                         pVertexAnimation->vertexData.pColors.iStride    = sizeof(pGeneral[0]);
  869.                         pVertexAnimation->vertexData.pCoords.data       = (Vec2*)(&pGeneral[0].st);
  870.                         pVertexAnimation->vertexData.pCoords.iStride    = sizeof(pGeneral[0]);
  871.                         pVertexAnimation->vertexData.pVelocities.data = (Vec3*)pRenderMesh->GetVelocityPtr(pVertexAnimation->vertexData.pVelocities.iStride, fslCreate);
  872.                         pVertexAnimation->vertexData.pTangents.data = (SPipTangents*)pRenderMesh->GetTangentPtr(pVertexAnimation->vertexData.pTangents.iStride, fslCreate);
  873.                         pVertexAnimation->vertexData.pIndices = pRenderMesh->GetIndexPtr(fslCreate);
  874.                         pVertexAnimation->vertexData.m_indexCount = geometry.GetIndexCount();
  875.  
  876.                         if (!pVertexAnimation->vertexData.pPositions ||
  877.                                 !pVertexAnimation->vertexData.pVelocities ||
  878.                                 !pVertexAnimation->vertexData.pTangents)
  879.                         {
  880.                                 pRenderMesh->UnlockStream(VSF_GENERAL);
  881.                                 pRenderMesh->UnlockStream(VSF_TANGENTS);
  882.                                 pRenderMesh->UnlockStream(VSF_VERTEX_VELOCITY);
  883. #if ENABLE_NORMALSTREAM_SUPPORT
  884.                                 pRenderMesh->UnlockStream(VSF_NORMALS);
  885. #endif
  886.                                 pRenderMesh->UnLockForThreadAccess();
  887.                                 return;
  888.                         }
  889.  
  890.                         // If memory was pre-allocated for the command buffer, recompile into it.
  891.                         if (pVertexAnimation->commandBufferLength)
  892.                         {
  893.                                 CVertexCommandBufferAllocatorStatic commandBufferAllocator(
  894.                                         (uint8*)pD->m_pSkinningData->pCustomData + sizeof(SVertexAnimationJob),
  895.                                         pVertexAnimation->commandBufferLength);
  896.                                 pVertexAnimation->commandBuffer.Initialize(commandBufferAllocator);
  897.                                 m_vertexAnimation.CompileCommands(pVertexAnimation->commandBuffer);
  898.                         }
  899.  
  900.                         pVertexAnimation->pRenderMeshSyncVariable = pRenderMesh->SetAsyncUpdateState();
  901.  
  902.                         SSkinningData *pCurrentJobSkinningData = *pD->m_pSkinningData->pMasterSkinningDataList;
  903.                         if(pCurrentJobSkinningData == NULL)
  904.                         {
  905.                                 pVertexAnimation->Begin(pD->m_pSkinningData->pAsyncJobs);
  906.                         }
  907.                         else
  908.                         {
  909.                                 // try to append to list
  910.                                 pD->m_pSkinningData->pNextSkinningData = pCurrentJobSkinningData;
  911.                                 void *pUpdatedJobSkinningData = CryInterlockedCompareExchangePointer( alias_cast<void *volatile *>(pD->m_pSkinningData->pMasterSkinningDataList), pD->m_pSkinningData, pCurrentJobSkinningData );
  912.  
  913.                                 // in case we failed (job has finished in the meantime), we need to start the job from the main thread
  914.                                 if(pUpdatedJobSkinningData == NULL )
  915.                                 {
  916.                                         pVertexAnimation->Begin(pD->m_pSkinningData->pAsyncJobs);
  917.                                 }
  918.                         }
  919.  
  920.                         if (Console::GetInst().ca_DebugSWSkinning)
  921.                                 VClothUtils::DrawVertexDebug(pRenderMesh, QuatT(RenderMat34), pVertexAnimation, vertexSkinData);
  922.  
  923.                         pRenderMesh->UnLockForThreadAccess();
  924.                         if (m_clothPiece.NeedsDebugDraw())
  925.                                 m_clothPiece.DrawDebug(pVertexAnimation);
  926.                         if (!(Console::GetInst().ca_DrawCloth & 1))
  927.                                 return;
  928.                 }
  929.         }
  930.  
  931. //      CryFatalError("CryAnimation: pMaster is zero");
  932.         if(pRenderMesh)
  933.         {
  934.                 //g_pAuxGeom->Draw2dLabel( 1,g_YLine, 1.3f, ColorF(0,1,0,1), false,"VCloth name: %s",GetName()),g_YLine+=16.0f;
  935.  
  936.                 IMaterial* pMaterial = RendParams.pMaterial;
  937.                 if(pMaterial==0)
  938.                         pMaterial = m_pRenderSkin->GetIMaterial(0);
  939.                 pObj->m_pCurrMaterial = pMaterial;
  940. #ifndef _RELEASE
  941.                 CModelMesh* pModelMesh = m_pRenderSkin->GetModelMesh(nRenderLOD);
  942.                 static ICVar *p_e_debug_draw = gEnv->pConsole->GetCVar("e_DebugDraw");
  943.                 if(p_e_debug_draw && p_e_debug_draw->GetIVal() > 0)
  944.                         pModelMesh->DrawDebugInfo(pMaster->m_pDefaultSkeleton, nRenderLOD, RenderMat34, p_e_debug_draw->GetIVal(), pMaterial, pObj, RendParams, passInfo.IsGeneralPass(), (IRenderNode*)RendParams.pRenderNode, m_pAttachmentManager->m_pSkelInstance->m_SkeletonPose.GetAABB() );
  945. #endif
  946.                 pRenderMesh->Render(pObj, passInfo);
  947.  
  948.                 //------------------------------------------------------------------
  949.                 //---       render debug-output (only PC in CharEdit mode)       ---
  950.                 //------------------------------------------------------------------
  951. #if EDITOR_PCDEBUGCODE
  952.                 if (pMaster->m_CharEditMode&CA_CharacterTool)
  953.                 {
  954.                         const Console& rConsole = Console::GetInst();
  955.  
  956.                         uint32 tang = rConsole.ca_DrawTangents;
  957.                         uint32 bitang = rConsole.ca_DrawBinormals;
  958.                         uint32 norm = rConsole.ca_DrawNormals;
  959.                         uint32 wire = rConsole.ca_DrawWireframe;
  960.                         if (tang || bitang || norm || wire)
  961.                         {
  962.                                 CModelMesh* pModelMesh = m_pRenderSkin->GetModelMesh(nRenderLOD);
  963.                                 gEnv->pJobManager->WaitForJob( *pD->m_pSkinningData->pAsyncJobs );
  964.                                 //SoftwareSkinningDQ(pModelMesh, pObj->m_II.m_Matrix,   tang,bitang,norm,wire, pD->m_pSkinningData->pBoneQuatsS);
  965.                                 SoftwareSkinningDQ_VS_Emulator(pModelMesh, pObj->m_II.m_Matrix,   tang,bitang,norm,wire, pD->m_pSkinningData->pBoneQuatsS);
  966.                         }
  967.                 }
  968. #endif
  969.         }
  970.  
  971. }
  972.  
  973. //-----------------------------------------------------------------------------
  974. //---     trigger streaming of desired LODs (only need in CharEdit)         ---
  975. //-----------------------------------------------------------------------------
  976. void CAttachmentVCLOTH::TriggerMeshStreaming(uint32 nDesiredRenderLOD, const SRenderingPassInfo &passInfo)
  977. {
  978.         if (!m_pRenderSkin)
  979.                 return;
  980.  
  981.         uint32 numLODs = m_pRenderSkin->m_arrModelMeshes.size();
  982.         if (numLODs==0)
  983.                 return;
  984.         if (m_AttFlags&FLAGS_ATTACH_HIDE_ATTACHMENT)
  985.                 return;  //mesh not visible
  986.         if(nDesiredRenderLOD>=numLODs)
  987.         {
  988.                 if (m_AttFlags&FLAGS_ATTACH_RENDER_ONLY_EXISTING_LOD)
  989.                         return;  //early exit, if LOD-file doesn't exist
  990.                 nDesiredRenderLOD = numLODs-1; //render the last existing LOD-file
  991.         }
  992.         m_pRenderSkin->m_arrModelMeshes[nDesiredRenderLOD].m_stream.nFrameId = passInfo.GetMainFrameID();
  993.         m_pSimSkin->m_arrModelMeshes[nDesiredRenderLOD].m_stream.nFrameId = passInfo.GetMainFrameID();
  994. }
  995.  
  996. SSkinningData* CAttachmentVCLOTH::GetVertexTransformationData(bool bVertexAnimation, uint8 nRenderLOD)
  997. {
  998.         DEFINE_PROFILER_FUNCTION();
  999.         CCharInstance* pMaster = m_pAttachmentManager->m_pSkelInstance;
  1000.         if (pMaster==0)
  1001.         {
  1002.                 CryFatalError("CryAnimation: pMaster is zero");
  1003.                 return NULL;
  1004.         }
  1005.  
  1006.         uint32 skinningQuatCount = m_arrRemapTable.size();
  1007.         uint32 skinningQuatCountMax = pMaster->GetSkinningTransformationCount();
  1008.         uint32 nNumBones = min(skinningQuatCount, skinningQuatCountMax);       
  1009.  
  1010.         // get data to fill
  1011.         int nFrameID = gEnv->pRenderer->EF_GetSkinningPoolID();
  1012.         int nList = nFrameID % 3;
  1013.         int nPrevList = (nFrameID - 1 ) % 3;
  1014.         // before allocating new skinning date, check if we already have for this frame
  1015.         if(m_arrSkinningRendererData[nList].nFrameID == nFrameID && m_arrSkinningRendererData[nList].pSkinningData)
  1016.         {
  1017.                 return m_arrSkinningRendererData[nList].pSkinningData;
  1018.         }
  1019.  
  1020.         if(pMaster->arrSkinningRendererData[nList].nFrameID != nFrameID )
  1021.         {
  1022.                 pMaster->GetSkinningData(); // force master to compute skinning data if not available
  1023.         }
  1024.  
  1025.         uint32 nCustomDataSize = 0;
  1026.         uint commandBufferLength = 0;
  1027.         if (bVertexAnimation)
  1028.         {
  1029.                 // Make sure the software skinning command gets compiled.
  1030.                 SVertexSkinData vertexSkinData = SVertexSkinData();
  1031.                 vertexSkinData.transformationCount = 1;
  1032.                 vertexSkinData.vertexTransformCount = 4;
  1033.                 vertexSkinData.tangetUpdateTriCount = 1;
  1034.                 m_vertexAnimation.SetSkinData(vertexSkinData);
  1035.  
  1036.                 // Compile the command buffer without allocating the commands to
  1037.                 // compute the buffer length.
  1038.                 CVertexCommandBufferAllocationCounter commandBufferAllocationCounter;
  1039.                 CVertexCommandBuffer commandBuffer;
  1040.                 commandBuffer.Initialize(commandBufferAllocationCounter);
  1041.                 m_vertexAnimation.CompileCommands(commandBuffer);
  1042.                 commandBufferLength = commandBufferAllocationCounter.GetCount();
  1043.  
  1044.                 nCustomDataSize = sizeof(SVertexAnimationJob) + commandBufferLength;
  1045.         }
  1046.  
  1047.         SSkinningData *pSkinningData = gEnv->pRenderer->EF_CreateRemappedSkinningData(nNumBones, pMaster->arrSkinningRendererData[nList].pSkinningData, nCustomDataSize, pMaster->m_pDefaultSkeleton->GetGuid());      
  1048.         pSkinningData->pCustomTag = this;
  1049.         if (nCustomDataSize)
  1050.         {
  1051.                 SVertexAnimationJob *pVertexAnimation = new (pSkinningData->pCustomData) SVertexAnimationJob();
  1052.                 pVertexAnimation->commandBufferLength = commandBufferLength;
  1053.         }
  1054.         m_arrSkinningRendererData[nList].pSkinningData = pSkinningData;
  1055.         m_arrSkinningRendererData[nList].nFrameID = nFrameID;
  1056.         PREFAST_ASSUME(pSkinningData);
  1057.  
  1058.         // set data for motion blur    
  1059.         if(m_arrSkinningRendererData[nPrevList].nFrameID == (nFrameID - 1) && m_arrSkinningRendererData[nPrevList].pSkinningData)
  1060.         {              
  1061.                 pSkinningData->nHWSkinningFlags |= eHWS_MotionBlured;
  1062.                 pSkinningData->pPreviousSkinningRenderData = m_arrSkinningRendererData[nPrevList].pSkinningData;
  1063.                 if(pSkinningData->pPreviousSkinningRenderData->pAsyncJobs)
  1064.                         gEnv->pJobManager->WaitForJob( *pSkinningData->pPreviousSkinningRenderData->pAsyncJobs );
  1065.         }      
  1066.         else
  1067.         {
  1068.                 // if we don't have motion blur data, use the some as for the current frame
  1069.                 pSkinningData->pPreviousSkinningRenderData = pSkinningData;
  1070.         }
  1071.  
  1072.         pSkinningData->pRemapTable = &m_arrRemapTable[0];
  1073.  
  1074.         return pSkinningData;
  1075. }
  1076.  
  1077. SMeshLodInfo CAttachmentVCLOTH::ComputeGeometricMean() const
  1078. {
  1079.         SMeshLodInfo lodInfo;
  1080.         lodInfo.Clear();
  1081.  
  1082.         CModelMesh* pModelMesh = m_pRenderSkin->GetModelMesh(0);
  1083.         if (pModelMesh)
  1084.         {
  1085.                 lodInfo.fGeometricMean = pModelMesh->m_geometricMeanFaceArea;
  1086.                 lodInfo.nFaceCount = pModelMesh->m_faceCount;
  1087.         }
  1088.  
  1089.         return lodInfo;
  1090. }
  1091.  
  1092. #ifdef EDITOR_PCDEBUGCODE
  1093. //These functions are need only for the Editor on PC
  1094.  
  1095. void CAttachmentVCLOTH::DrawWireframeStatic( const Matrix34& m34, int nLOD, uint32 color)
  1096. {
  1097.         CModelMesh* pModelMesh = m_pRenderSkin->GetModelMesh(nLOD);
  1098.         if (pModelMesh)
  1099.                 pModelMesh->DrawWireframeStatic(m34,color);
  1100. }
  1101.  
  1102. //////////////////////////////////////////////////////////////////////////
  1103. // skinning of external Vertices and QTangents
  1104. //////////////////////////////////////////////////////////////////////////
  1105. void CAttachmentVCLOTH::SoftwareSkinningDQ_VS_Emulator( CModelMesh* pModelMesh, Matrix34 rRenderMat34, uint8 tang,uint8 binorm,uint8 norm,uint8 wire, const DualQuat* const pSkinningTransformations)
  1106. {
  1107. #ifdef DEFINE_PROFILER_FUNCTION
  1108.         DEFINE_PROFILER_FUNCTION();
  1109. #endif
  1110.  
  1111.         CRenderAuxGeomRenderFlagsRestore _renderFlagsRestore(g_pAuxGeom);
  1112.  
  1113.         if (pModelMesh->m_pIRenderMesh==0)
  1114.                 return;
  1115.  
  1116.         static DynArray<Vec3> g_arrExtSkinnedStream;
  1117.         static DynArray<Quat> g_arrQTangents;
  1118.         static DynArray<uint8> arrSkinned;
  1119.  
  1120.         uint32 numExtIndices    = pModelMesh->m_pIRenderMesh->GetIndicesCount();
  1121.         uint32 numExtVertices   = pModelMesh->m_pIRenderMesh->GetVerticesCount();
  1122.         assert(numExtVertices && numExtIndices);
  1123.  
  1124.         uint32 ssize=g_arrExtSkinnedStream.size();
  1125.         if (ssize<numExtVertices)
  1126.         {
  1127.                 g_arrExtSkinnedStream.resize(numExtVertices);
  1128.                 g_arrQTangents.resize(numExtVertices);
  1129.                 arrSkinned.resize(numExtVertices);
  1130.         }
  1131.         memset(&arrSkinned[0],0,numExtVertices);
  1132.  
  1133.         pModelMesh->m_pIRenderMesh->LockForThreadAccess();
  1134.         ++pModelMesh->m_iThreadMeshAccessCounter;
  1135.  
  1136.         vtx_idx* pIndices                               = pModelMesh->m_pIRenderMesh->GetIndexPtr(FSL_READ);
  1137.         if (pIndices==0)
  1138.                 return;
  1139.         int32           nPositionStride;
  1140.         uint8*  pPositions                      = pModelMesh->m_pIRenderMesh->GetPosPtr(nPositionStride, FSL_READ);
  1141.         if (pPositions==0)
  1142.                 return;
  1143.         int32           nQTangentStride;
  1144.         uint8*  pQTangents                      = pModelMesh->m_pIRenderMesh->GetQTangentPtr(nQTangentStride, FSL_READ);
  1145.         if (pQTangents==0)
  1146.                 return;
  1147.         int32           nSkinningStride;
  1148.         uint8 * pSkinningInfo                           = pModelMesh->m_pIRenderMesh->GetHWSkinPtr(nSkinningStride, FSL_READ); //pointer to weights and bone-id
  1149.         if (pSkinningInfo==0)
  1150.                 return;
  1151.  
  1152.         DualQuat arrRemapSkinQuat[MAX_JOINT_AMOUNT];    //dual quaternions for skinning
  1153.         for (size_t b = 0; b < m_arrRemapTable.size(); ++b)
  1154.         {
  1155.                 const uint16 sidx = m_arrRemapTable[b]; //is array can be different for every skin-attachment
  1156.                 arrRemapSkinQuat[b] = pSkinningTransformations[sidx];
  1157.         }
  1158.  
  1159.         const uint32 numSubsets = pModelMesh->m_arrRenderChunks.size();
  1160.         for (uint32 s=0; s<numSubsets; s++)
  1161.         {
  1162.                 float fColor[4] = {1,0,1,1};
  1163.                 extern f32 g_YLine;
  1164.                 //      g_pAuxGeom->Draw2dLabel( 1,g_YLine, 1.3f, fColor, false,"MODEL: %s",pDefaultSkeleton->GetFilePath()); g_YLine+=0x10;
  1165.                 uint32 startIndex               = pModelMesh->m_arrRenderChunks[s].m_nFirstIndexId;
  1166.                 uint32 endIndex                 = pModelMesh->m_arrRenderChunks[s].m_nFirstIndexId+pModelMesh->m_arrRenderChunks[s].m_nNumIndices;
  1167.                 g_pAuxGeom->Draw2dLabel(1, g_YLine, 1.3f, fColor, false, "subset: %d  startIndex: %d  endIndex: %d", s, startIndex, endIndex);
  1168.                 g_YLine += 0x10;
  1169.  
  1170.                 for (uint32 idx=startIndex; idx<endIndex; ++idx)
  1171.                 {
  1172.                         uint32 e = pIndices[idx];
  1173.                         if (arrSkinned[e])
  1174.                                 continue;
  1175.  
  1176.                         arrSkinned[e]=1;
  1177.                         Vec3            hwPosition      = *(Vec3*)(pPositions + e * nPositionStride) + pModelMesh->m_vRenderMeshOffset;
  1178.                         SPipQTangents   hwQTangent      = *(SPipQTangents*)(pQTangents + e * nQTangentStride);
  1179.                         uint16* hwIndices   = ((SVF_W4B_I4S*)(pSkinningInfo + e*nSkinningStride))->indices;
  1180.                         ColorB  hwWeights               = *(ColorB*)&((SVF_W4B_I4S*)(pSkinningInfo + e*nSkinningStride))->weights;
  1181.  
  1182.                         //---------------------------------------------------------------------
  1183.                         //---     this is CPU emulation of Dual-Quat skinning              ---
  1184.                         //---------------------------------------------------------------------
  1185.                         //get indices for bones (always 4 indices per vertex)
  1186.                         uint32 id0 = hwIndices[0];
  1187.                         assert(id0 < m_arrRemapTable.size());
  1188.                         uint32 id1 = hwIndices[1];
  1189.                         assert(id1 < m_arrRemapTable.size());
  1190.                         uint32 id2 = hwIndices[2];
  1191.                         assert(id2 < m_arrRemapTable.size());
  1192.                         uint32 id3 = hwIndices[3];
  1193.                         assert(id3 < m_arrRemapTable.size());
  1194.  
  1195.                         //get weights for vertices (always 4 weights per vertex)
  1196.                         f32 w0 = hwWeights[0]/255.0f;
  1197.                         f32 w1 = hwWeights[1]/255.0f;
  1198.                         f32 w2 = hwWeights[2]/255.0f;
  1199.                         f32 w3 = hwWeights[3]/255.0f;
  1200.                         assert(fabsf((w0+w1+w2+w3)-1.0f)<0.0001f);
  1201.  
  1202.                         const DualQuat& q0=arrRemapSkinQuat[id0];
  1203.                         const DualQuat& q1=arrRemapSkinQuat[id1];
  1204.                         const DualQuat& q2=arrRemapSkinQuat[id2];
  1205.                         const DualQuat& q3=arrRemapSkinQuat[id3];
  1206.                         DualQuat wquat          =       q0*w0 +  q1*w1 + q2*w2 +        q3*w3;
  1207.  
  1208.                         f32 l=1.0f/wquat.nq.GetLength();
  1209.                         wquat.nq*=l;
  1210.                         wquat.dq*=l;
  1211.                         g_arrExtSkinnedStream[e] = rRenderMat34*(wquat*hwPosition);  //transform position by dual-quaternion
  1212.  
  1213.                         Quat QTangent = hwQTangent.GetQ();
  1214.                         assert( QTangent.IsUnit() );
  1215.  
  1216.                         g_arrQTangents[e] = wquat.nq*QTangent;
  1217.                         if (g_arrQTangents[e].w<0.0f)
  1218.                                 g_arrQTangents[e]=-g_arrQTangents[e]; //make it positive
  1219.                         f32 flip = QTangent.w<0 ? -1.0f : 1.0f;
  1220.                         if (flip<0)
  1221.                                 g_arrQTangents[e]=-g_arrQTangents[e]; //make it negative
  1222.                 }
  1223.         }
  1224.         g_YLine+=0x10;
  1225.  
  1226.         pModelMesh->m_pIRenderMesh->UnLockForThreadAccess();
  1227.         --pModelMesh->m_iThreadMeshAccessCounter;
  1228.         if (pModelMesh->m_iThreadMeshAccessCounter==0)
  1229.         {
  1230.                 pModelMesh->m_pIRenderMesh->UnlockStream(VSF_GENERAL);
  1231.                 pModelMesh->m_pIRenderMesh->UnlockStream(VSF_TANGENTS);
  1232.                 pModelMesh->m_pIRenderMesh->UnlockStream(VSF_HWSKIN_INFO);
  1233.         }
  1234.  
  1235.         //---------------------------------------------------------------------------
  1236.         //---------------------------------------------------------------------------
  1237.         //---------------------------------------------------------------------------
  1238.  
  1239.         uint32 numBuffer        =       g_arrExtSkinnedStream.size();
  1240.         if (numBuffer<numExtVertices)
  1241.                 return;
  1242.         const f32 VLENGTH=0.03f;
  1243.  
  1244.         if (tang)
  1245.         {
  1246.                 static std::vector<ColorB> arrExtVColors;
  1247.                 uint32 csize = arrExtVColors.size();
  1248.                 if (csize<(numExtVertices*2)) arrExtVColors.resize( numExtVertices*2 );
  1249.                 for(uint32 i=0; i<numExtVertices*2; i=i+2)     
  1250.                 {
  1251.                         arrExtVColors[i+0] = RGBA8(0x3f,0x00,0x00,0x00);
  1252.                         arrExtVColors[i+1] = RGBA8(0xff,0x7f,0x7f,0x00);
  1253.                 }
  1254.  
  1255.                 Matrix33 WMat33 = Matrix33(rRenderMat34);
  1256.                 static std::vector<Vec3> arrExtSkinnedStream;
  1257.                 uint32 vsize = arrExtSkinnedStream.size();
  1258.                 if (vsize<(numExtVertices*2)) arrExtSkinnedStream.resize( numExtVertices*2 );  
  1259.                 for(uint32 i=0,t=0; i<numExtVertices; i++)     
  1260.                 {
  1261.                         Vec3 vTangent  = g_arrQTangents[i].GetColumn0()*VLENGTH;
  1262.                         arrExtSkinnedStream[t+0] = g_arrExtSkinnedStream[i];
  1263.                         arrExtSkinnedStream[t+1] = WMat33*vTangent+arrExtSkinnedStream[t];
  1264.                         t=t+2;
  1265.                 }
  1266.  
  1267.                 SAuxGeomRenderFlags renderFlags( e_Def3DPublicRenderflags );
  1268.                 g_pAuxGeom->SetRenderFlags( renderFlags );
  1269.                 g_pAuxGeom->DrawLines( &arrExtSkinnedStream[0],numExtVertices*2, &arrExtVColors[0]);           
  1270.         }
  1271.  
  1272.         if (binorm)
  1273.         {
  1274.                 static std::vector<ColorB> arrExtVColors;
  1275.                 uint32 csize = arrExtVColors.size();
  1276.                 if (csize<(numExtVertices*2)) arrExtVColors.resize( numExtVertices*2 );
  1277.                 for(uint32 i=0; i<numExtVertices*2; i=i+2)     
  1278.                 {
  1279.                         arrExtVColors[i+0] = RGBA8(0x00,0x3f,0x00,0x00);
  1280.                         arrExtVColors[i+1] = RGBA8(0x7f,0xff,0x7f,0x00);
  1281.                 }
  1282.  
  1283.                 Matrix33 WMat33 = Matrix33(rRenderMat34);
  1284.                 static std::vector<Vec3> arrExtSkinnedStream;
  1285.                 uint32 vsize = arrExtSkinnedStream.size();
  1286.                 if (vsize<(numExtVertices*2)) arrExtSkinnedStream.resize( numExtVertices*2 );  
  1287.                 for(uint32 i=0,t=0; i<numExtVertices; i++)     
  1288.                 {
  1289.                         Vec3 vBitangent = g_arrQTangents[i].GetColumn1()*VLENGTH;
  1290.                         arrExtSkinnedStream[t+0] = g_arrExtSkinnedStream[i];
  1291.                         arrExtSkinnedStream[t+1] = WMat33*vBitangent+arrExtSkinnedStream[t];
  1292.                         t=t+2;
  1293.                 }
  1294.  
  1295.                 SAuxGeomRenderFlags renderFlags( e_Def3DPublicRenderflags );
  1296.                 g_pAuxGeom->SetRenderFlags( renderFlags );
  1297.                 g_pAuxGeom->DrawLines( &arrExtSkinnedStream[0],numExtVertices*2, &arrExtVColors[0]);           
  1298.         }
  1299.  
  1300.         if (norm)
  1301.         {
  1302.                 static std::vector<ColorB> arrExtVColors;
  1303.                 uint32 csize = arrExtVColors.size();
  1304.                 if (csize<(numExtVertices*2)) arrExtVColors.resize( numExtVertices*2 );
  1305.                 for(uint32 i=0; i<numExtVertices*2; i=i+2)     
  1306.                 {
  1307.                         arrExtVColors[i+0] = RGBA8(0x00,0x00,0x3f,0x00);
  1308.                         arrExtVColors[i+1] = RGBA8(0x7f,0x7f,0xff,0x00);
  1309.                 }
  1310.  
  1311.                 Matrix33 WMat33 = Matrix33(rRenderMat34);
  1312.                 static std::vector<Vec3> arrExtSkinnedStream;
  1313.                 uint32 vsize = arrExtSkinnedStream.size();
  1314.                 if (vsize<(numExtVertices*2)) arrExtSkinnedStream.resize( numExtVertices*2 );  
  1315.                 for(uint32 i=0,t=0; i<numExtVertices; i++)     
  1316.                 {
  1317.                         f32 flip = (g_arrQTangents[i].w<0) ? -VLENGTH : VLENGTH;
  1318.                         Vec3 vNormal = g_arrQTangents[i].GetColumn2()*flip;
  1319.                         arrExtSkinnedStream[t+0] = g_arrExtSkinnedStream[i];
  1320.                         arrExtSkinnedStream[t+1] = WMat33*vNormal + arrExtSkinnedStream[t];
  1321.                         t=t+2;
  1322.                 }
  1323.                 SAuxGeomRenderFlags renderFlags( e_Def3DPublicRenderflags );
  1324.                 g_pAuxGeom->SetRenderFlags( renderFlags );
  1325.                 g_pAuxGeom->DrawLines( &arrExtSkinnedStream[0],numExtVertices*2, &arrExtVColors[0]);           
  1326.         }
  1327.  
  1328.         if (wire)
  1329.         {
  1330.                 uint32 color = RGBA8(0x00,0xff,0x00,0x00);
  1331.                 SAuxGeomRenderFlags renderFlags( e_Def3DPublicRenderflags );
  1332.                 renderFlags.SetFillMode( e_FillModeWireframe );
  1333.                 renderFlags.SetDrawInFrontMode( e_DrawInFrontOn );
  1334.                 renderFlags.SetAlphaBlendMode(e_AlphaAdditive);
  1335.                 g_pAuxGeom->SetRenderFlags( renderFlags );
  1336.                 g_pAuxGeom->DrawTriangles(&g_arrExtSkinnedStream[0],numExtVertices, pIndices,numExtIndices,color);             
  1337.         }
  1338. }
  1339. #endif
  1340.  
  1341. void CAttachmentVCLOTH::HideAttachment( uint32 x )
  1342. {
  1343.         m_pAttachmentManager->OnHideAttachment(this, FLAGS_ATTACH_HIDE_MAIN_PASS | FLAGS_ATTACH_HIDE_SHADOW_PASS | FLAGS_ATTACH_HIDE_RECURSION, x!=0);
  1344.  
  1345.         if(x)
  1346.                 m_AttFlags |=  (FLAGS_ATTACH_HIDE_MAIN_PASS | FLAGS_ATTACH_HIDE_SHADOW_PASS | FLAGS_ATTACH_HIDE_RECURSION);
  1347.         else
  1348.                 m_AttFlags &= ~(FLAGS_ATTACH_HIDE_MAIN_PASS | FLAGS_ATTACH_HIDE_SHADOW_PASS | FLAGS_ATTACH_HIDE_RECURSION);
  1349. }
  1350.  
  1351. void CAttachmentVCLOTH::HideInRecursion( uint32 x )
  1352. {
  1353.         m_pAttachmentManager->OnHideAttachment(this, FLAGS_ATTACH_HIDE_RECURSION, x!=0);
  1354.  
  1355.         if(x)
  1356.                 m_AttFlags |= FLAGS_ATTACH_HIDE_RECURSION;
  1357.         else
  1358.                 m_AttFlags &= ~FLAGS_ATTACH_HIDE_RECURSION;
  1359. }
  1360.  
  1361. void CAttachmentVCLOTH::HideInShadow( uint32 x )
  1362. {
  1363.         m_pAttachmentManager->OnHideAttachment(this, FLAGS_ATTACH_HIDE_SHADOW_PASS, x!=0);
  1364.  
  1365.         if(x)
  1366.                 m_AttFlags |= FLAGS_ATTACH_HIDE_SHADOW_PASS;
  1367.         else
  1368.                 m_AttFlags &= ~FLAGS_ATTACH_HIDE_SHADOW_PASS;
  1369. }
  1370.  
  1371. extern f32 g_YLine;
  1372.  
  1373. struct SEdgeInfo
  1374. {
  1375.         int m_iEdge;
  1376.         float m_cost;
  1377.         bool m_skip;
  1378.  
  1379.         SEdgeInfo() : m_iEdge(-1), m_cost(1e38f), m_skip(false) { }
  1380. };
  1381.  
  1382. bool CClothSimulator::AddGeometry(phys_geometry *pgeom)
  1383. {
  1384.         if (!pgeom || pgeom->pGeom->GetType() != GEOM_TRIMESH)
  1385.                 return false;
  1386.  
  1387.         mesh_data *pMesh = (mesh_data*)pgeom->pGeom->GetData();
  1388.  
  1389.         m_nVtx = pMesh->nVertices;
  1390.         m_particlesHot = new SParticleHot[m_nVtx];
  1391.         m_particlesCold = new SParticleCold[m_nVtx];
  1392.         for(int i = 0; i < m_nVtx; i++)
  1393.         {
  1394.                 m_particlesHot[i].pos = Vector4(pMesh->pVertices[i]);
  1395.                 m_particlesCold[i].prevPos = m_particlesHot[i].pos; // vel = 0
  1396.         }
  1397.  
  1398.         return true;
  1399. }
  1400.  
  1401. int CClothSimulator::SetParams(const SVClothParams& params, float* weights)
  1402. {
  1403.         m_config = params;
  1404.         m_config.weights = weights;
  1405.  
  1406.         for (int i = 0; i < m_nVtx && m_config.weights; i++)   
  1407.         {      
  1408.                 m_particlesHot[i].alpha = AttachmentVClothPreProcess::IsAttached(m_config.weights[i]) ? 1.0f : m_config.weights[i];
  1409.                 m_particlesHot[i].factorAttached = 1.0f - m_config.weights[i];
  1410.                 m_particlesCold[i].bAttached = AttachmentVClothPreProcess::IsAttached(m_particlesHot[i].alpha);
  1411.         }
  1412.         // refresh the edges for newly attached vertices
  1413.         for (int i = 0; i < m_nEdges; i++)
  1414.                 PrepareEdge(m_links[i]);
  1415.         for (size_t i = 0; i < m_shearLinks.size(); i++)
  1416.                 PrepareEdge(m_shearLinks[i]);
  1417.         for (size_t i = 0; i < m_bendLinks.size(); i++)
  1418.                 PrepareEdge(m_bendLinks[i]);
  1419.         return 1;
  1420. }
  1421.  
  1422. namespace VClothUtils
  1423. {
  1424. static inline float BendDetermineAngleAtRuntime(const Vec3& n0, const Vec3& n1, const Vec3 pRef0, const Vec3& pRef3)
  1425. {
  1426.         float nDotN = n0.dot(n1);
  1427.         if (nDotN > 1.0f) nDotN = 1.0f;
  1428.         if (nDotN < -1.0f) nDotN = -1.0f;
  1429.         float alpha = acos(nDotN);
  1430.         float sign = n0.dot(pRef3 - pRef0) > 0.0f ? -1.0f : 1.0f;
  1431.         alpha *= sign;
  1432.         return alpha;
  1433. }
  1434. }
  1435.  
  1436. void CClothSimulator::SetSkinnedPositions(const Vector4* points)
  1437. {
  1438.         if (!points)
  1439.                 return;
  1440.         for (int i = 0; i < m_nVtx; i++)
  1441.         {
  1442.                 m_particlesCold[i].skinnedPos = points[i];
  1443.         }
  1444. }
  1445.  
  1446. void CClothSimulator::GetVertices(Vector4* pWorldCoords) const
  1447. {
  1448.         // TODO: skip conversion, use Vector4 for skinning
  1449.         for (int i = 0; i < m_nVtx; i++)
  1450.         {
  1451.                 pWorldCoords[i] = m_particlesHot[i].pos;
  1452.         }
  1453. }
  1454.  
  1455. void CClothSimulator::GetVerticesFaded(Vector4* pWorldCoords)
  1456. {
  1457.         float t = m_fadeTimeActual / m_config.disableSimulationTimeRange;
  1458.  
  1459.         if (m_fadeInOutPhysicsDirection > 0) t = 1.0f - t; // ensure fading direction (in/out)
  1460.  
  1461.         for (int i = 0; i < m_nVtx; i++)
  1462.                 pWorldCoords[i] = m_particlesHot[i].pos;                                // copy positions
  1463.  
  1464.         //PushFadeInOutPhysics(); // store positions from simulation
  1465.         PositionsSetToSkinned(true, false); // set skinned positions, but not old positions
  1466.  
  1467.         // swap positions with pWorldCoords, to keep original positions in m_particlesHot
  1468.         Vector4 tmp;
  1469.         for (int i = 0; i < m_nVtx; i++)
  1470.         {
  1471.                 tmp = pWorldCoords[i];
  1472.                 pWorldCoords[i] = m_particlesHot[i].pos;
  1473.                 m_particlesHot[i].pos = tmp;
  1474.         }
  1475.  
  1476.         for (int i = 0; i < m_nVtx; i++)
  1477.         {
  1478.                 Vector4& A = pWorldCoords[i];
  1479.                 const Vector4& B = m_particlesHot[i].pos;
  1480.                 A = A + t * (B - A);
  1481.         }
  1482. }
  1483.  
  1484. void CClothSimulator::StartStep(float time_interval, const QuatT& location)
  1485. {
  1486.         m_location = location;
  1487.  
  1488.         m_time = time_interval - m_config.timeStep; // m_time = time_interval would mean simulating subStepTime01 = 0 - All Interpolations would be the same like the step before with subStepTime01 = 1.0
  1489.         if (m_time < 0) m_time = 0;
  1490.         m_timeInterval = time_interval;
  1491.         m_steps = 0;
  1492.         if (m_dtPrev < 0) m_dtPrev = m_config.timeStep;
  1493.  
  1494.         uint32 numClothProxie = 0;
  1495.         uint32 numProxies =  m_pAttachmentManager->GetProxyCount();
  1496.         for (uint32 i=0; i<numProxies; i++)
  1497.         {
  1498.                 if (m_pAttachmentManager->m_arrProxies[i].m_nPurpose == 1) // ==1: cloth
  1499.                         numClothProxie++;
  1500.         }
  1501. //      g_pAuxGeom->Draw2dLabel( 1,g_YLine, 1.3f, ColorF(0,1,0,1), false,"numProxies: %d",numClothProxie),g_YLine+=16.0f;
  1502.        
  1503.         uint32 numCollidables = m_permCollidables.size();
  1504.         if (numClothProxie != numCollidables)
  1505.                 m_permCollidables.resize(numClothProxie);
  1506.  
  1507.         Quat rotf = location.q;
  1508.         Quaternion ssequat(location.q);
  1509.         uint32 c=0;
  1510.         for (uint32 i=0; i<numProxies; i++)
  1511.         {
  1512.                 if (m_pAttachmentManager->m_arrProxies[i].m_nPurpose != 1) // ==1: cloth
  1513.                         continue;
  1514.                 m_permCollidables[c].oldOffset = m_permCollidables[c].offset;
  1515.                 m_permCollidables[c].oldR = m_permCollidables[c].R;
  1516.  
  1517.                 const CProxy* pProxy = &m_pAttachmentManager->m_arrProxies[i];
  1518.                 m_permCollidables[c].offset = ssequat * Vector4(pProxy->m_ProxyModelRelative.t);
  1519.                 m_permCollidables[c].R  = Matrix3(rotf * pProxy->m_ProxyModelRelative.q);
  1520.                 m_permCollidables[c].cr = pProxy->m_params.w;
  1521.                 m_permCollidables[c].cx = pProxy->m_params.x;
  1522.                 m_permCollidables[c].cy = pProxy->m_params.y;
  1523.                 m_permCollidables[c].cz = pProxy->m_params.z;
  1524.                 c++;
  1525.         }
  1526.  
  1527.         // determine external translational velocity - should be moved downwards to use numCollidables (instead of m_permCollidables.size())
  1528.         // not used at the moment, since translationBlend, externalBlend default to zero
  1529.         // determined by Joint 0 (root)
  1530.         if (numProxies > 0)
  1531.         {
  1532.                 //const Vec3& collidablePos = m_permCollidables[0].offset;
  1533.                 const Vec3& collidablePos = m_pAttachmentManager->GetSkelInstance()->GetISkeletonPose()->GetAbsJointByID(0).t;
  1534.  
  1535.                 m_externalDeltaTranslation = collidablePos - m_permCollidables0Old;
  1536.                 m_permCollidables0Old = collidablePos;
  1537.  
  1538.                 m_externalDeltaTranslation.z = 0; // no up/down movement
  1539.  
  1540.                 float thresh = 0.1f;
  1541.                 if (m_externalDeltaTranslation.len2() > thresh * thresh) m_externalDeltaTranslation = Vec3(ZERO);
  1542.         }
  1543.  
  1544.         for (int i = 0; i < m_nVtx; i++)
  1545.         {
  1546.                 m_particlesCold[i].oldPos = m_particlesHot[i].pos;
  1547.         }
  1548.  
  1549.         // blend world space with local space movement
  1550.         const float rotationBlend = m_config.rotationBlend; //max(m_angModulator, m_config.rotationBlend);
  1551.         if ((m_config.rotationBlend > 0.f || m_config.translationBlend > 0.f)  && !m_permCollidables.empty())
  1552.         {
  1553.                 Quaternion dq(IDENTITY);
  1554.                 if (m_config.rotationBlend > 0.f)
  1555.                 {
  1556.                         Quaternion qi(m_permCollidables[0].R);
  1557.                         Quaternion qf(m_permCollidables[0].oldR);
  1558.                         if (m_config.rotationBlend < 1.f)
  1559.                                 qi.SetNlerp(qf, qi, m_config.rotationBlend);
  1560.                         dq = qi * !qf;
  1561.                 }
  1562.                 Vector4 delta(ZERO);
  1563.                 if (m_config.translationBlend > 0.f && m_permCollidables.size())
  1564.                 {
  1565.                         delta = m_config.translationBlend * (m_permCollidables[0].offset - m_permCollidables[0].oldOffset);
  1566.                         delta += m_permCollidables[0].oldOffset - dq * m_permCollidables[0].oldOffset;
  1567.                 }
  1568.                 for(int i = 0; i < m_nVtx; i++)
  1569.                 {
  1570.                         if (!m_particlesCold[i].bAttached)
  1571.                         {
  1572.                                 m_particlesHot[i].pos = dq * m_particlesHot[i].pos + delta;
  1573.                                 m_particlesCold[i].prevPos = dq * m_particlesCold[i].prevPos + delta;
  1574.                         }
  1575.                 }
  1576.         }
  1577. }
  1578.  
  1579. struct SRay
  1580. {
  1581.         Vector4 origin, dir;
  1582. };
  1583.  
  1584. struct SIntersection
  1585. {
  1586.         Vector4 pt, n;
  1587. };
  1588.  
  1589. struct Quotient
  1590. {
  1591.         float x, y;
  1592.  
  1593.         Quotient(float ax, float ay) : x(ax), y(ay) { }
  1594.         float val() { return y != 0 ? x / y : 0; }
  1595.         Quotient& operator +=(float op) { x += op * y; return *this; }
  1596. };
  1597.  
  1598. namespace VClothUtils
  1599. {
  1600. inline float      GetMin(float) { return 1E-20f; }
  1601. static ILINE bool operator<(const Quotient&op1, const Quotient&op2)
  1602. {
  1603.         return op1.x * op2.y - op2.x * op1.y + GetMin(op1.x) * (op1.x - op2.x) < 0;
  1604. }
  1605.  
  1606. static ILINE bool PrimitiveRayCast(const f32 cr, const f32 ca, const SRay& ray, SIntersection& inters)
  1607. {
  1608.                        
  1609.         if (ca == 0)
  1610.         {
  1611.                 Vector4 delta = ray.origin;
  1612.                 float a = ray.dir.len2();
  1613.                 float b = ray.dir * delta;
  1614.                 float c = delta.len2() - sqr(cr);
  1615.                 float d = b * b - a * c;
  1616.                 if (d >= 0)
  1617.                 {
  1618.                         d = sqrt_tpl(d);
  1619.                         Quotient t(-b - d, a);
  1620.                         int bHit = isneg(fabs_tpl(t.x * 2 - t.y) - t.y);
  1621.                         t.x += d * (bHit ^ 1) * 2;
  1622.                         bHit = isneg(fabs_tpl(t.x *2 - t.y) - t.y);
  1623.                         if (!bHit)
  1624.                                 return 0;
  1625.  
  1626.                         inters.pt = ray.origin + ray.dir * t.val();
  1627.                         inters.n = (inters.pt).normalized();
  1628.                         //inters.iFeature[0][0]=inters.iFeature[1][0] = 0x40;
  1629.                         //inters.iFeature[0][1]=inters.iFeature[1][1] = 0x20;
  1630.                         return true;
  1631.                 }
  1632.         }
  1633.  
  1634.         if (ca)
  1635.         {
  1636.                 //lozenges
  1637.                 Vector4 axis;
  1638. #ifdef CLOTH_SSE
  1639.                 axis.x=1,axis.y=0,axis.z=0,axis.w=0;
  1640. #else
  1641.                 axis.x=1,axis.y=0,axis.z=0;
  1642. #endif
  1643.  
  1644.                 Quotient tmin(1, 1);
  1645.                 int iFeature = -1; // TODO: remove or change
  1646.                 float a = ray.dir.len2();
  1647.                 for (int icap = 0; icap < 2; icap++)
  1648.                 {
  1649.                         Vector4 vec0 = axis * (ca * (icap * 2 - 1));
  1650.                         Vector4 delta = ray.origin - vec0;
  1651.                         float b = ray.dir * delta;
  1652.                         float c = delta.len2() - sqr(cr);
  1653.                         float axcdiff = (ray.origin) * axis;
  1654.                         float axdir = ray.dir * axis;
  1655.                         float d = b * b - a * c;
  1656.                         if (d >= 0)
  1657.                         {
  1658.                                 d = sqrt_tpl(d);
  1659.                                 Quotient t(-b - d, a);
  1660.                                 int bHit = inrange(t.x * tmin.y, 0.f, t.y * tmin.x) & isneg(ca * t.y - fabs_tpl(axcdiff * t.y + axdir * t.x));
  1661.                                 tmin.x += (t.x - tmin.x) * bHit;
  1662.                                 tmin.y += (t.y - tmin.y) * bHit;
  1663.                                 iFeature = 0x41 + icap & -bHit | iFeature & ~-bHit;
  1664.                                 t.x += d * 2;
  1665.                                 bHit = inrange(t.x * tmin.y, 0.f, t.y * tmin.x) & isneg(ca * t.y - fabs_tpl(axcdiff * t.y + axdir * t.x));
  1666.                                 tmin.x += (t.x - tmin.x) * bHit;
  1667.                                 tmin.y += (t.y - tmin.y) * bHit;
  1668.                                 iFeature = 0x41 + icap & -bHit | iFeature & ~-bHit;
  1669.                         }
  1670.                 }
  1671.  
  1672.                 Vector4 vec0 = ray.origin;
  1673.                 Vector4 vec1 = ray.dir ^ axis;
  1674.                 a = vec1 * vec1;
  1675.                 float b = vec0 * vec1;
  1676.                 float c = vec0 * vec0 - sqr(cr);
  1677.                 float d = b * b - a * c;
  1678.                 if (d >= 0)
  1679.                 {
  1680.                         d = sqrt_tpl(d);
  1681.                         Quotient t(-b - d, a);
  1682.                         int bHit = inrange(t.x * tmin.y, 0.f, t.y * tmin.x) & isneg(fabs_tpl(((ray.origin) * t.y + ray.dir * t.x) * axis) - ca * t.y);
  1683.                         tmin.x += (t.x - tmin.x) * bHit;
  1684.                         tmin.y += (t.y - tmin.y) * bHit;
  1685.                         iFeature = 0x40 & -bHit | iFeature & ~-bHit;
  1686.                         t.x += d * 2;
  1687.                         bHit = inrange(t.x * tmin.y, 0.f, t.y * tmin.x) & isneg(fabs_tpl(((ray.origin) * t.y + ray.dir * t.x) * axis) - ca * t.y);
  1688.                         tmin.x += (t.x - tmin.x) * bHit;
  1689.                         tmin.y += (t.y - tmin.y) * bHit;
  1690.                         iFeature = 0x40 & -bHit | iFeature & ~-bHit;
  1691.                 }
  1692.  
  1693.                 if (iFeature<0)
  1694.                         return 0;
  1695.  
  1696.                 inters.pt = ray.origin + ray.dir * tmin.val();
  1697.                 if (iFeature == 0x40)
  1698.                 {
  1699.                         inters.n = inters.pt;
  1700.                         inters.n -= axis * (axis * inters.n);
  1701.                 }
  1702.                 else
  1703.                 {
  1704.                         inters.n = inters.pt - axis * (ca * ((iFeature - 0x41) * 2 - 1));
  1705.                 }
  1706.                 inters.n.normalize();
  1707.                 //inters.iFeature[0][0]=inters.iFeature[1][0] = iFeature;
  1708.                 //inters.iFeature[0][1]=inters.iFeature[1][1] = 0x20;
  1709.                 return true;
  1710.         }
  1711.  
  1712.         return false;
  1713. }
  1714. }
  1715.  
  1716. // Implemented according to the paper "Long Range Attachments", Mueller et al.
  1717. // but with much better distance constraints by using path finding algorithm and closest neighbors
  1718. void CClothSimulator::LongRangeAttachmentsSolve()
  1719. {
  1720.         if (m_bUseDijkstraForLRA)
  1721.         {
  1722.                 // Dijekstra / geodesic approach / distances along mesh
  1723.                 float allowedExtensionSqr = (1.0f + m_config.longRangeAttachmentsAllowedExtension);
  1724.                 allowedExtensionSqr *= allowedExtensionSqr;
  1725.                 for (auto it = m_lraNotAttachedOrderedIdx.begin(); it != m_lraNotAttachedOrderedIdx.end(); ++it)
  1726.                 {
  1727.                         // better would be to use real length along path for delta, not euklidean distance from initial pose...
  1728.                         const int i = *it;
  1729.                         const int& idx = m_particlesHot[i].lraIdx;
  1730.                         if (idx < 0) continue; // no lra found in initialization
  1731.                         // determine distance to LRA
  1732.                         Vector4 lraDistV = m_particlesHot[i].pos - m_particlesHot[idx].pos;
  1733.                         float lraDistSqr = lraDistV.dot(lraDistV);
  1734.  
  1735.                         if (lraDistSqr > m_particlesHot[i].lraDist * m_particlesHot[i].lraDist * allowedExtensionSqr)
  1736.                         {
  1737.                                 // force LRA constraint, by shifting particle in closest neighbor direction
  1738.                                 float delta = sqrt(lraDistSqr) - m_particlesHot[i].lraDist;
  1739.                                 int idxNextClosest = m_particlesHot[i].lraNextParent;
  1740.                                 Vector4 directionClosest = m_particlesHot[idxNextClosest].pos - m_particlesHot[i].pos;
  1741.                                 float distanceClosest = directionClosest.GetLengthFast();
  1742.                                 if (distanceClosest < 0.001f) continue;
  1743.                                 directionClosest = (directionClosest / distanceClosest); //directionClosest.GetNormalizedFast();
  1744.  
  1745.                                 const float moveMaxFactor = m_config.longRangeAttachmentsMaximumShiftFactor;
  1746.                                 const float movePosPrevFactor = m_config.longRangeAttachmentsShiftCollisionFactor; //true; // no velocity change
  1747.                                 if (distanceClosest * moveMaxFactor > delta)
  1748.                                 {
  1749.                                         // move delta in that direction
  1750.                                         m_particlesHot[i].pos += directionClosest * delta * m_particlesHot[i].factorAttached * m_dt;
  1751.                                         if (movePosPrevFactor) m_particlesCold[i].prevPos += directionClosest * delta * movePosPrevFactor * m_particlesHot[i].factorAttached * m_dt;
  1752.                                 }
  1753.                                 else
  1754.                                 {
  1755.                                         // move maximal moveMaxFactor in that direction
  1756.                                         m_particlesHot[i].pos += directionClosest * distanceClosest * moveMaxFactor * m_particlesHot[i].factorAttached * m_dt;
  1757.                                         if (movePosPrevFactor) m_particlesCold[i].prevPos += directionClosest * distanceClosest * moveMaxFactor * movePosPrevFactor * m_particlesHot[i].factorAttached * m_dt;
  1758.                                 }
  1759.                         }
  1760.                 }
  1761.         }
  1762.         else
  1763. {
  1764.                 // Euclidean distance in local space
  1765.         for (int i = 0; i < m_nVtx; i++)
  1766.         {
  1767.                         const int& idx = m_particlesHot[i].lraIdx;
  1768.                         if (idx < 0) continue; // no LRA for attached vtx
  1769.  
  1770.                         if (m_particlesCold[i].bAttached) continue; // no lra for attached particles
  1771.  
  1772.                         // determine distance to LRA
  1773.                         Vector4 d = m_particlesHot[i].pos - m_particlesHot[idx].pos;
  1774.                         float distSqr = d.dot(d);
  1775.  
  1776.                         if (distSqr > m_particlesHot[i].lraDist * m_particlesHot[i].lraDist)
  1777.                 {
  1778.                                 // force LRA constraint
  1779.                                 d = d.GetNormalizedFast();
  1780.                                 m_particlesHot[i].pos = m_particlesHot[idx].pos + m_particlesHot[i].lraDist * d * m_dt;
  1781.                         }
  1782.                 }
  1783.         }
  1784. }
  1785.  
  1786. void CClothSimulator::BendByTriangleAngleDetermineNormals()
  1787.                         {
  1788.         const SParticleHot* p = m_particlesHot;
  1789.  
  1790.         for (auto it = m_listBendTriangles.begin(); it != m_listBendTriangles.end(); it++)
  1791.         {
  1792.                 SBendTriangle& t = *it;
  1793.                 t.normal = ((p[t.p1].pos - p[t.p0].pos).cross(p[t.p2].pos - p[t.p0].pos)).GetNormalizedFast();
  1794.                         }
  1795.                 }              
  1796.  
  1797. void CClothSimulator::BendByTriangleAngleSolve(float kBend)
  1798.                 {
  1799.         BendByTriangleAngleDetermineNormals();
  1800.  
  1801.         const float k = kBend;
  1802.         SParticleHot* p = m_particlesHot;
  1803.         SParticleCold* pO = m_particlesCold;
  1804.  
  1805.         for (auto it = m_listBendTrianglePairs.begin(); it != m_listBendTrianglePairs.end(); it++)
  1806.                         {
  1807.                 Vec3& n0 = m_listBendTriangles[(*it).idxNormal0].normal;
  1808.                 Vec3& n1 = m_listBendTriangles[(*it).idxNormal1].normal;
  1809.  
  1810.                 float alpha = VClothUtils::BendDetermineAngleAtRuntime(n0, n1, p[it->p3].pos, p[it->p0].pos);
  1811.                 alpha += it->phi0; // add initial angle as offset to constraint this angle
  1812.  
  1813.                 float factor = k * alpha * 0.01f; // *0.001f; // scale into accurate floating point range
  1814.  
  1815.                 // add constraint to corner particles
  1816.                 p[it->p2].pos += n0 * factor * p[it->p2].factorAttached * m_dt;
  1817.                 p[it->p3].pos += n1 * factor * p[it->p3].factorAttached * m_dt;
  1818.  
  1819.                 // add inverse constraint to edge particles
  1820.                 Vec3 nHalf = (n0 + n1).GetNormalizedFast();
  1821.                 p[it->p0].pos -= nHalf * factor * p[it->p0].factorAttached * m_dt;
  1822.                 p[it->p1].pos -= nHalf * factor * p[it->p1].factorAttached * m_dt;
  1823.                         }
  1824. }
  1825.  
  1826. ///////////////////////////////////////////////////////////////////////////////
  1827.  
  1828. namespace VClothUtils
  1829.                         {
  1830.  
  1831. static ILINE f32 BoxGetSignedDistance(const Vec3& box, const Vec3& pos)     // signed distance of box
  1832.                                 {
  1833.         Vec3 d(abs(pos.x), abs(pos.y), abs(pos.z));
  1834.         d -= box;
  1835.  
  1836.         float minMax = min(max(d.x, max(d.y, d.z)), 0.0f);
  1837.  
  1838.         d.x = max(d.x, 0.0f);
  1839.         d.y = max(d.y, 0.0f);
  1840.         d.z = max(d.z, 0.0f);
  1841.  
  1842.         return minMax + d.len();
  1843.                                 }
  1844.  
  1845. static ILINE f32 ColliderDistance(const SCollidable& coll, const Vec3& pos)     // signed distance of lozenge
  1846. {
  1847.         const f32 cr = coll.cr;
  1848.         const Vec3 box(coll.cx, coll.cy, coll.cz);
  1849.  
  1850.         f32 boxDist = BoxGetSignedDistance(box, pos);
  1851.  
  1852.         return boxDist - cr;
  1853.                         }
  1854.  
  1855. static ILINE bool ColliderDistanceOutsideBoxCheck(const SCollidable& coll, const Vec3& pos)     // quick check, if outside lozenge bounding box
  1856. {
  1857.         const float& r = coll.cr;
  1858.         if (fabs(pos.z) > coll.cz + r) return true;
  1859.         if (fabs(pos.x) > coll.cx + r) return true;
  1860.         if (fabs(pos.y) > coll.cy + r) return true;
  1861.         return false;
  1862.                 }
  1863.  
  1864. static ILINE Vec3 ColliderDistanceDirectionNorm(const SCollidable& coll, const Vector4& pos, f32 distance)     // determine normalized direction to surface of lozenge, distance is distance to lozenge-surface at pos
  1865. {
  1866.         const f32 eps = 0.001f;
  1867.         const Vec3 epsX = Vec3(eps, 0.0f, 0.0f);
  1868.         const Vec3 epsY = Vec3(0.0f, eps, 0.0f);
  1869.         const Vec3 epsZ = Vec3(0.0f, 0.0f, eps);
  1870.  
  1871.         // derive forward
  1872.         Vec3 n(
  1873.           ColliderDistance(coll, pos + epsX) - distance,
  1874.           ColliderDistance(coll, pos + epsY) - distance,
  1875.           ColliderDistance(coll, pos + epsZ) - distance);
  1876.         return n.GetNormalizedFast();
  1877.         }
  1878.  
  1879. static ILINE bool ColliderProjectToSurface(const SCollidable& coll, Vector4& pos, Vector4* normal = nullptr, float factor = 1.0f)     // project pos on surface of lozenge; returns true, if pos is inside coll and has been projected; false otherwise
  1880. {
  1881.         if (ColliderDistanceOutsideBoxCheck(coll, pos)) return false;     // quick test, if outside box approximation of lozenge
  1882.         f32 distance = ColliderDistance(coll, pos);
  1883.         bool isInside = distance < 0;
  1884.         if (!isInside) return false;
  1885.  
  1886.         const f32 eps = 1.001f;
  1887.         if (normal != nullptr)
  1888.         {
  1889.                 *normal = ColliderDistanceDirectionNorm(coll, pos, distance);
  1890.                 pos -= eps * (*normal) * distance * factor;     // determine surface position
  1891. }
  1892.         else
  1893.         {
  1894.                 pos -= eps * ColliderDistanceDirectionNorm(coll, pos, distance) * distance * factor;     // determine surface position
  1895.         }
  1896.         return true;
  1897. }
  1898. }
  1899.  
  1900. void CClothSimulator::UpdateCollidablesLerp(f32 t01)
  1901. {
  1902.         std::vector<SCollidable>& collidables = m_permCollidables;
  1903.  
  1904.         // determine interpolated transformation matrices
  1905.         for (size_t k = 0; k < collidables.size(); k++)
  1906.         {
  1907.                 Quaternion qr(collidables[k].R);
  1908.                 Quaternion qrOld(collidables[k].oldR);
  1909.  
  1910.                 const float eps = 0.001f;
  1911.                 collidables[k].qLerp.q = t01 < 1.0f - eps ? Quaternion::CreateSlerp(qrOld, qr, t01) : qr;
  1912.                 collidables[k].qLerp.t = t01 < 1.0f - eps ? collidables[k].oldOffset + t01 * (collidables[k].offset - collidables[k].oldOffset) : collidables[k].offset;
  1913.  
  1914. #ifdef EDITOR_PCDEBUGCODE
  1915.                 // for debug rendering, only for editor on PC
  1916.                 if ((m_debugCollidableSubsteppingId == k)) { m_debugCollidableSubsteppingQuatT.push_back(collidables[k].qLerp); }
  1917. #endif
  1918.         }
  1919. }
  1920.  
  1921. void CClothSimulator::PositionsProjectToProxySurface(f32 t01)
  1922. {
  1923.         std::vector<SCollidable>& collidables = m_permCollidables;
  1924.         int colliderId[2];     // special handling for collision with two colliders at the same time, thus store id
  1925.  
  1926.         // check all particles
  1927.         // for multiple collisions the average of collision resolutions are used
  1928.         for (int i = 0; i < m_nVtx; i++)
  1929.         {
  1930.                 if (m_particlesCold[i].bAttached) continue; // discard attached particles
  1931.  
  1932.                 Vector4 collisionResolvePosition(ZERO);
  1933.                 int nCollisionsDetected = 0; // number of detected collisions
  1934.                 Vector4 collisionNormal;     // get normal for tangential damping
  1935.  
  1936.                 const bool instantResolve = true; // directly project onto proxy surface oder iteratively move in that direction
  1937.  
  1938.                 // check all collidables
  1939.                 int collId = 0;
  1940.                 for (auto it = collidables.begin(); it != collidables.end(); it++, collId++)
  1941.                 {
  1942.                         const SCollidable& coll = *it;
  1943.                         const Quaternion& M = coll.qLerp.q;
  1944.                         Vector4 ipos = (m_particlesHot[i].pos - coll.qLerp.t) * M; // particles position in collider space
  1945.  
  1946.                         if (instantResolve)
  1947.                         {
  1948.                                 // instant jump to valid position
  1949.                                 if (VClothUtils::ColliderProjectToSurface(coll, ipos, &collisionNormal))
  1950.                                 {
  1951.                                         if (nCollisionsDetected < 2) { colliderId[nCollisionsDetected] = collId; }
  1952.                                         nCollisionsDetected++;
  1953.                                         ipos = M * ipos + coll.qLerp.t;   // transform back to WS
  1954.                                         collisionResolvePosition += ipos; // set particles new position
  1955.         }
  1956.                         }
  1957.                         else
  1958.         {
  1959.                                 // slow approaching of final collision-resolve-position
  1960.                                 if (VClothUtils::ColliderProjectToSurface(coll, ipos, nullptr, 0.5f)) // approaching with factor 0.5
  1961.                                 {
  1962.                                         ipos = M * ipos + coll.qLerp.t;                           // transform back to WS
  1963.                                         collisionResolvePosition += ipos - m_particlesHot[i].pos; // store sum of delta
  1964.                                         nCollisionsDetected++;
  1965.         }
  1966.                         }
  1967.                 }
  1968.  
  1969.                 if (instantResolve)
  1970.         {
  1971.                         switch (nCollisionsDetected)
  1972.                         {
  1973.                         case 0:
  1974.                                 break; // no collisions
  1975.                         case 1:  // one collision
  1976.                                 m_particlesHot[i].pos = collisionResolvePosition;
  1977.                                 //m_particlesCold[i].oldPos = collisionResolvePosition;
  1978.  
  1979.                                 // for attached particles, smooth blending between collision resolve position and skinned position
  1980.                                 if (m_particlesHot[i].alpha) m_particlesHot[i].pos += (m_particlesCold[i].skinnedPos - m_particlesHot[i].pos) * m_particlesHot[i].alpha;
  1981.  
  1982.                                 if (m_config.collisionDampingTangential)
  1983.                                 {
  1984.                                         m_particlesHot[i].collisionExist = true;
  1985.                                         m_particlesHot[i].collisionNormal = collisionNormal;
  1986.         }
  1987.  
  1988.                                 break;
  1989.                         case 2:
  1990.                                 // 2 collisions at the same time: explicitly resolve by half distance into average direction
  1991.                                 if (m_config.collisionMultipleShiftFactor)
  1992.         {
  1993.                                         Vector4 collisionResolvePosition(ZERO);
  1994.                                         for (int j = 0; j < nCollisionsDetected; j++)
  1995.                                         {
  1996.                                                 const SCollidable& coll = collidables[colliderId[j]];
  1997.  
  1998.                                                 const Quaternion& M = coll.qLerp.q;
  1999.                                                 Vector4 ipos = (m_particlesHot[i].pos - coll.qLerp.t) * M; // particles position in collider space
  2000.                                                 if (VClothUtils::ColliderProjectToSurface(coll, ipos, nullptr, m_config.collisionMultipleShiftFactor))
  2001.                                                 {
  2002.                                                         ipos = M * ipos + coll.qLerp.t; // transform back to WS
  2003.                                                         collisionResolvePosition += ipos - m_particlesHot[i].pos;
  2004.         }
  2005.                                         }
  2006.                                         m_particlesHot[i].pos += collisionResolvePosition / 2.0f; // 2 collisions, thus '/ 2.0'f
  2007.                                 }
  2008.  
  2009.                                 // 2 collisions at the same time: collide with union of both colliders / disabled at the moment
  2010.                                 if (false)
  2011.         {
  2012.                                         const int id0 = colliderId[0];
  2013.                                         const Quaternion& m0 = collidables[id0].qLerp.q;                        // transformation matrix
  2014.                                         Vector4 ipos0 = (m_particlesHot[i].pos - collidables[id0].offset) * m0; // particles position in collider space
  2015.                                         const float dist0 = VClothUtils::ColliderDistance(collidables[id0], ipos0);
  2016.  
  2017.                                         const int id1 = colliderId[1];
  2018.                                         const Quaternion& m1 = collidables[id1].qLerp.q;                        // transformation matrix
  2019.                                         Vector4 ipos1 = (m_particlesHot[i].pos - collidables[id1].offset) * m1; // particles position in collider space
  2020.                                         const float dist1 = VClothUtils::ColliderDistance(collidables[id1], ipos1);
  2021.  
  2022.                                         if (dist0 < dist1)
  2023.                                         {
  2024.                                                 if (VClothUtils::ColliderProjectToSurface(collidables[id0], ipos0))
  2025.                                                 {
  2026.                                                         m_particlesHot[i].pos = m0 * ipos0 + collidables[id0].offset; // transform back to WS
  2027.                                                 }
  2028.                                         }
  2029.                                         else
  2030.                                         {
  2031.                                                 if (VClothUtils::ColliderProjectToSurface(collidables[id1], ipos1))
  2032.                                                 {
  2033.                                                         m_particlesHot[i].pos = m1 * ipos1 + collidables[id1].offset; // transform back to WS
  2034.                                                 }
  2035.                                         }
  2036.                                 }
  2037.                                 break;
  2038.                         default: // more than 2 collisions at the same time - at the moment: do nothing / no resolve
  2039.                                 // m_particlesHot[i].pos = collisionResolvePosition / (float)nCollisionsDetected; // set particles new position by average of possible collision resolutions
  2040.                                 break;
  2041.                         }
  2042.                 }
  2043.                 else
  2044.                 {
  2045.                         // slow approaching of final collision-resolve-position
  2046.                         m_particlesHot[i].pos += collisionResolvePosition / (float)nCollisionsDetected;
  2047.         }
  2048.  
  2049. }
  2050. }
  2051.  
  2052. ///////////////////////////////////////////////////////////////////////////////
  2053.  
  2054. void CClothSimulator::HandleCameraDistance()
  2055. {
  2056.         const f32 disableSimAtDist = m_config.disableSimulationAtDistance;
  2057.  
  2058.         if (CheckCameraDistanceLessThan(disableSimAtDist))
  2059.         {
  2060.                 if (!IsSimulationEnabled() || IsFadingOut())
  2061.                 {
  2062.                         if (!IsFadingOut()) { PositionsSetToSkinned(); /* m_doSkinningForNSteps = 3; */ } // only translate to constraints, if actually is not fading out, otherwise a position jump in cloth would occur in these cases
  2063.                         EnableSimulation();
  2064.                         EnableFadeInPhysics();
  2065.                 }
  2066.         }
  2067.         else
  2068.         {
  2069.                 //m_clothPiece.GetSimulator().EnableSimulation(false); // is done in step now, while handling fading
  2070.                 if (IsSimulationEnabled() && !IsFadingOut())
  2071.                 {
  2072.                         EnableFadeOutPhysics();
  2073.         }
  2074.         }
  2075. }
  2076.  
  2077. void CClothSimulator::InitFadeInOutPhysics()
  2078. {
  2079.         if (m_fadeTimeActual > 0.0f)
  2080.         {
  2081.                 // if fading is already running, everything is already set up
  2082.                 // only animation step has to be refined, since direction has been changed
  2083.                 m_fadeTimeActual = m_config.disableSimulationTimeRange - m_fadeTimeActual;
  2084.         }
  2085.         else
  2086.         {
  2087.                 // fading is not running, thus init step counter and copy initial vertices
  2088.                 m_fadeTimeActual = m_config.disableSimulationTimeRange;
  2089.         }
  2090. }
  2091.        
  2092. void CClothSimulator::EnableFadeOutPhysics()
  2093. {
  2094.         InitFadeInOutPhysics();
  2095.         m_fadeInOutPhysicsDirection = -1;
  2096. }
  2097.  
  2098. void CClothSimulator::EnableFadeInPhysics()
  2099. {
  2100.         InitFadeInOutPhysics();
  2101.         m_fadeInOutPhysicsDirection = 1;
  2102. }
  2103.  
  2104. void CClothSimulator::DecreaseFadeInOutTimer(float dt)
  2105. {
  2106.         m_fadeTimeActual -= dt;
  2107.  
  2108.         // handle end of fading
  2109.         if (m_fadeTimeActual <= 0)
  2110.         {
  2111.                 if (m_fadeInOutPhysicsDirection == -1) { EnableSimulation(false); } // disable simulation, if physics has been faded out
  2112.                 m_fadeInOutPhysicsDirection = 0;
  2113.                 m_fadeTimeActual = 0.0f;
  2114.         }
  2115. }
  2116.  
  2117. bool CClothSimulator::CheckCameraDistanceLessThan(float dist) const
  2118. {
  2119.         Vec3 distV = gEnv->p3DEngine->GetRenderingCamera().GetPosition() - m_pAttachmentManager->m_pSkelInstance->m_location.t; // distance vector to camera (animation pivot)
  2120.         distV -= m_pAttachmentManager->m_pSkelInstance->GetAABB().GetCenter();                                                  // use center of actual position (determined by BB), not of pivot
  2121.         float distSqr = distV.dot(distV);
  2122.         return distSqr < dist * dist;
  2123. }
  2124.  
  2125. bool CClothSimulator::CheckForceSkinningByFpsThreshold()
  2126. {
  2127.         bool forceSkinning = false;
  2128.         float fps = gEnv->pTimer->GetFrameRate();
  2129.         forceSkinning = fps < m_config.forceSkinningFpsThreshold;
  2130.  
  2131.         if (forceSkinning)
  2132.         {
  2133.                 // CryWarning(VALIDATOR_MODULE_ANIMATION, VALIDATOR_WARNING, "[Cloth] Force Skinning, Fps: %f [Thresh: %f Fps]", fps, m_config.forceSkinningFpsThreshold);
  2134.                 // g_pAuxGeom->Draw2dLabel( 100,140, 5.3f, ColorF(1,0,1,1), false, "[Cloth] FPS: %f",fps);
  2135.         }
  2136.  
  2137.         return forceSkinning;
  2138. }
  2139.  
  2140. bool CClothSimulator::CheckForceSkinning()
  2141. {
  2142.         bool forceSkinning = CheckForceSkinningByFpsThreshold(); // detect framerate; force skinning if needed
  2143.         forceSkinning |= m_doSkinningForNSteps > 0;
  2144.         forceSkinning |= !IsSimulationEnabled();
  2145.         forceSkinning |= (m_timeInterval / m_config.timeStep) > (float)m_config.timeStepsMax; // not possible to simulate the actual framerate with the provided max no of substeps
  2146.         forceSkinning |= m_config.forceSkinning;
  2147.         for (int i = min(m_nVtx, 5); i >= 0; --i)
  2148.                 forceSkinning |= (m_particlesHot[i].pos - m_particlesCold->prevPos).len2() > m_config.forceSkinningTranslateThreshold * m_config.forceSkinningTranslateThreshold;                                       // check translation distance
  2149.         return forceSkinning;
  2150. }
  2151.  
  2152. bool CClothSimulator::CheckAnimationRewind()
  2153. {
  2154.         bool animationRewindOccurred = false;
  2155.         float normalizedTime = m_pAttachmentManager->m_pSkelInstance->GetISkeletonAnim()->GetAnimationNormalizedTime(&m_pAttachmentManager->m_pSkelInstance->GetISkeletonAnim()->GetAnimFromFIFO(0, 0));
  2156.         int isAnimPlaying = m_pAttachmentManager->m_pSkelInstance->m_SkeletonAnim.m_IsAnimPlaying;
  2157.         if (isAnimPlaying && (normalizedTime < m_normalizedTimePrev)) // animation rewind has been occurred
  2158.         {
  2159.                 animationRewindOccurred = true;
  2160.         }
  2161.         m_normalizedTimePrev = normalizedTime;
  2162.         return animationRewindOccurred;
  2163. }
  2164.  
  2165. void CClothSimulator::DoForceSkinning()
  2166. {
  2167.         m_doSkinningForNSteps--;
  2168.         if (m_doSkinningForNSteps < 0) m_doSkinningForNSteps = 0;
  2169.  
  2170.         PositionsSetToSkinned(IsSimulationEnabled());
  2171.         UpdateCollidablesLerp();
  2172.         PositionsProjectToProxySurface(); // might be removed
  2173.         m_dtPrev = m_dt / m_dtNormalize;  // reset m_dtPrev
  2174.  
  2175.         for (int i = 0; i < m_nVtx; i++)
  2176.                 m_particlesHot[i].timer = 0;                                // reset timer -> start resetDamping
  2177. }
  2178.  
  2179. void CClothSimulator::DoAnimationRewind()
  2180. {
  2181.         // CryWarning(VALIDATOR_MODULE_ANIMATION, VALIDATOR_WARNING, "[Cloth] Animation rewind occured.");
  2182.         PositionsSetToSkinned();
  2183.         m_doSkinningForNSteps = 3; // fix poor animations with character default pose in 1st frame, which result in strong jump for 2nd frame
  2184.         //ProjectToProxySurface(); // deactivated for now, since normal/artist defined skinning should do fine
  2185.         m_dtPrev = m_dt / m_dtNormalize;
  2186.         for (int i = 0; i < m_nVtx; i++)
  2187.                 m_particlesHot[i].timer = 0; // reset timer -> start resetDamping
  2188. }
  2189.  
  2190. void CClothSimulator::DampTangential()
  2191.         {
  2192.         float k = m_config.collisionDampingTangential;
  2193.         for (int i = 0; i < m_nVtx; i++)
  2194.         {
  2195.                 if (m_particlesHot[i].collisionExist)
  2196.                 {
  2197.                         const Vector4& n = m_particlesHot[i].collisionNormal;
  2198.                         Vector4 vel = (m_particlesHot[i].pos - m_particlesCold[i].prevPos) / m_dtPrev;
  2199.  
  2200.                         Vector4 velN = n.dot(vel) * n;
  2201.                         vel -= velN;
  2202.                         vel *= 1.0f - k;
  2203.                         vel += velN;
  2204.  
  2205.                         m_particlesCold[i].prevPos = m_particlesHot[i].pos - vel * m_dt;
  2206.                 }
  2207.         }
  2208. }
  2209.  
  2210. void CClothSimulator::PositionsIntegrate()
  2211. {
  2212.         const Vector4 dg = (m_gravity * m_config.gravityFactor / 1000.0f) * m_dt; // scale to precise/good floating point domain
  2213.         const float resetDampingFactor = 1.0f - m_config.resetDampingFactor;
  2214.         const float kd = 1.0f - m_config.friction;
  2215.         for (int i = 0; i < m_nVtx; i++)
  2216.         {
  2217.                 Vector4 pos0 = m_particlesHot[i].pos;
  2218.                 Vector4 dv = (m_particlesHot[i].pos - m_particlesCold[i].prevPos) / m_dtPrev; // determine velocity, using the previous dt, since difference to prePos is used
  2219.  
  2220.                 if (m_particlesHot[i].timer > 0 && m_particlesHot[i].timer < m_config.resetDampingRange) // damping within resetDampingRange, to smooth hard cloth reset
  2221.                 {
  2222.                         dv *= resetDampingFactor;
  2223.                 }
  2224.  
  2225.                 dv *= kd;                                                         // simple damping
  2226.                 Vec3 dxExt = m_externalDeltaTranslation * m_config.externalBlend; // external influence
  2227.                 m_particlesHot[i].pos += dv * m_dt + dg * m_dt + dxExt;
  2228.                 m_particlesCold[i].prevPos = pos0;
  2229.                 m_particlesHot[i].timer++;
  2230.         }
  2231. }
  2232.  
  2233. void CClothSimulator::PositionsPullToSkinnedPositions()
  2234.         {
  2235.                 const float minDist = m_config.maxAnimDistance;
  2236.                 const float domain = 2 * minDist;
  2237.                 const Vector4 up(0, 0, 1);
  2238.                 for (int i = 0; i < m_nVtx; i++)
  2239.                 {
  2240.                 if ((m_particlesHot[i].alpha == 0.f && m_config.maxAnimDistance == 0.f) || m_particlesCold[i].bAttached)
  2241.                                 continue;
  2242.                         Vector4 target = m_particlesCold[i].skinnedPos;
  2243.                         Vector4 delta = target - m_particlesHot[i].pos;
  2244.                         float len = delta.len();
  2245.                 float alpha = 0.0f;
  2246.                 if (minDist && len > minDist && delta * up < 0.f)
  2247.                 {
  2248.                         alpha = min(1.f, max(0.0f, (len - minDist) / domain)); // interpolate in range minDist to 3*minDist from 0..1
  2249.                 }
  2250.                         float stiffness = max(alpha, m_config.pullStiffness * m_particlesHot[i].alpha);
  2251.                 m_particlesHot[i].pos += stiffness * delta * m_dt;
  2252.                 }
  2253.         }
  2254.  
  2255. void CClothSimulator::PositionsSetToSkinned(bool projectToProxySurface, bool setPosOld)
  2256.         {
  2257.         // set positions by skinned positions
  2258.         for (int n = 0; n < m_nVtx; ++n)
  2259.                 {
  2260.                 m_particlesHot[n].pos = m_particlesCold[n].skinnedPos;
  2261.                 }
  2262.         // one single collision step to move particles outside of collision object
  2263.         if (projectToProxySurface)
  2264.         {
  2265.                 UpdateCollidablesLerp();
  2266.                 PositionsProjectToProxySurface();
  2267.         }
  2268.         // set old positions by new (collided) positions
  2269.         if (setPosOld)
  2270.         {
  2271.                 for (int n = 0; n < m_nVtx; ++n)
  2272.                 {
  2273.                         m_particlesCold[n].prevPos = m_particlesHot[n].pos;
  2274.                         m_particlesCold[n].oldPos = m_particlesHot[n].pos;
  2275.                 }
  2276.         }
  2277. }
  2278.  
  2279. void CClothSimulator::PositionsSetAttachedToSkinnedInterpolated(float t01)
  2280.         {
  2281.         for (int i = 0; i < m_nVtx; i++)
  2282.                 {
  2283.                 if (m_particlesCold[i].bAttached)
  2284.                         {
  2285.                         m_particlesHot[i].pos = m_particlesCold[i].oldPos + t01 * (m_particlesCold[i].skinnedPos - m_particlesCold[i].oldPos); // interpolate substeps for smoother movements
  2286.                 }
  2287.                         }
  2288.                 }
  2289.  
  2290. int CClothSimulator::Step()
  2291.                 {
  2292.         // determine dt
  2293.         m_dt = m_config.timeStep;
  2294.         // m_time starts for substeps with m_timeInterval-m_config.timeStep (might be negative), and ends with 0, split last two timesteps to avoid very small timesteps
  2295.         if (m_timeInterval < m_config.timeStep) { m_dt = fmod(m_timeInterval, m_config.timeStep); } // SPF faster than substeps
  2296.         else if (m_time < m_config.timeStep)
  2297.                         {
  2298.                 m_dt = (fmod(m_timeInterval, m_config.timeStep) + m_config.timeStep) / 2.0f;
  2299.                 if (m_time > 0) m_time = m_dt;
  2300.         }   // split last two substeps into half
  2301.  
  2302.         float stepTime01 = 1.0f - m_time / m_timeInterval; // normalized time of substeps for this step, running from 0.0  to 1.0 [per frame]
  2303.         stepTime01 = clamp_tpl(stepTime01, 0.0f, 1.0f);
  2304.         m_dt *= m_dtNormalize; // normalize dt
  2305.  
  2306. #ifdef EDITOR_PCDEBUGCODE
  2307.         DebugOutput(stepTime01);
  2308. #endif
  2309.  
  2310.         // no vertices check, i.e. we are done here...
  2311.         if (m_nVtx <= 0)
  2312.         {
  2313.                 CryWarning(VALIDATOR_MODULE_ANIMATION, VALIDATOR_WARNING, "[Cloth] No of vertices <= 0");
  2314.                 return 1;
  2315.                         }
  2316.  
  2317.         // detect animation rewind
  2318.         if (m_config.checkAnimationRewind && CheckAnimationRewind()) { DoAnimationRewind(); return 1; }
  2319.  
  2320.         // check, if skinning should be forced
  2321.         if (CheckForceSkinning()) { DoForceSkinning(); return 1; }
  2322.  
  2323.         // always update attached vertices to skinned positions; even if not stepping
  2324.         PositionsSetAttachedToSkinnedInterpolated(stepTime01);
  2325.  
  2326.         // simulation
  2327.         m_dtPrev *= m_dtNormalize; // ensure normalization scale
  2328.         if (IsSimulationEnabled())
  2329.         {
  2330.                 // clever damping - following paper 'position based dynamics'
  2331.                 DampPositionBasedDynamics();
  2332.  
  2333.                 // damping of spring edges
  2334.                 const f32 springDamping = m_config.springDamping;
  2335.                 if (springDamping)
  2336.                 {
  2337.                         for (int i = 0; i < m_nEdges; i++)
  2338.                         {
  2339.                                 DampEdge(m_links[i], springDamping);
  2340.                         }                                                                          // stretch edges
  2341.                         for (auto it = m_bendLinks.begin(); it != m_bendLinks.end(); ++it)
  2342.                         {
  2343.                                 DampEdge(*it, springDamping);
  2344.                         }                                                                                                    // bend edges
  2345.                         for (auto it = m_shearLinks.begin(); it != m_shearLinks.end(); ++it)
  2346.                         {
  2347.                                 DampEdge(*it, springDamping);
  2348.                         }                                                                                                     // shear edges
  2349.                 }
  2350.  
  2351.                 // integrate / positions update
  2352.                 PositionsIntegrate(); // integrate positions here, to ensure collisions are handled correctly at the end of each substep
  2353.  
  2354.                 // pull towards skinned positions
  2355.                 if (m_config.pullStiffness || m_config.maxAnimDistance) { PositionsPullToSkinnedPositions(); }
  2356.  
  2357.                 // damping of colliding particles
  2358.                 // clear collisions for damping; so after the solver collisions/stiffness, the tangential collisions are handled
  2359.                 if (m_config.collisionDampingTangential)
  2360.                 {
  2361.                         for (int i = 0; i < m_nVtx; i++)
  2362.                                 m_particlesHot[i].collisionExist = false;
  2363.         }
  2364.  
  2365.                 // solver collisions/stiffness
  2366.                 float stretchStiffness = m_config.stretchStiffness;
  2367.                 float shearStiffness = m_config.shearStiffness;
  2368.                 float bendStiffness = m_config.bendStiffness;
  2369.                 float bendStiffnessByTrianglesAngle = -m_config.bendStiffnessByTrianglesAngle / 10.0f;
  2370.  
  2371.                 // interpolate transformation of collisionProxies
  2372.                 UpdateCollidablesLerp(stepTime01);
  2373.  
  2374.                 // constraint solver
  2375.                 for (int iter = 0; iter < m_config.numIterations; iter++)
  2376.                 {
  2377.                         // long range attachments
  2378.                         if (m_config.longRangeAttachments) LongRangeAttachmentsSolve();
  2379.  
  2380.                         // solve springs - stretching, bending & shearing
  2381.                         if (stretchStiffness)
  2382.                         {
  2383.                                 for (int i = 0; i < m_nEdges; i++)
  2384.                                 {
  2385.                                         SolveEdge(m_links[i], stretchStiffness);
  2386.                                 }
  2387.                         }
  2388.                         if (shearStiffness)
  2389.                         {
  2390.                                 for (auto it = m_shearLinks.begin(); it != m_shearLinks.end(); ++it)
  2391.                                 {
  2392.                                         SolveEdge(*it, shearStiffness);
  2393.                                 }
  2394.                         }
  2395.                         if (bendStiffness)
  2396.                         {
  2397.                                 for (auto it = m_bendLinks.begin(); it != m_bendLinks.end(); ++it)
  2398.                                 {
  2399.                                         SolveEdge(*it, bendStiffness);
  2400.                                 }
  2401.                         }
  2402.                         if (bendStiffnessByTrianglesAngle) { BendByTriangleAngleSolve(bendStiffnessByTrianglesAngle); }
  2403.                         if (m_config.springDampingPerSubstep && springDamping)
  2404.                         {
  2405.                                 // only damp  stretch links here, in the collision/stiffness loop
  2406.                                 for (int i = 0; i < m_nEdges; i++)
  2407.         {
  2408.                                         DampEdge(m_links[i], springDamping);
  2409.                                 }                                                                           // stretch edges
  2410.                                 //for (auto it = m_bendLinks.begin(); it != m_bendLinks.end(); ++it) { DampEdge(*it, springDamping); } // bend edges
  2411.                                 //for (auto it = m_shearLinks.begin(); it != m_shearLinks.end(); ++it) { DampEdge(*it, springDamping); } // shear edges
  2412.                         }
  2413.  
  2414.                         // collision handling - project particles lying inside collision proxies onto collision proxies surfaces
  2415.                         if (m_config.collideEveryNthStep)   // ==0 means no collision
  2416.                 {
  2417.                                 if ((iter % m_config.collideEveryNthStep == 0) || (iter == m_config.numIterations - 1)) { PositionsProjectToProxySurface(stepTime01); }
  2418.                 }
  2419.         }
  2420.        
  2421.                 // tangential damping in case of collisions
  2422.                 if (m_config.collisionDampingTangential) DampTangential();
  2423.  
  2424.         } // endif (IsSimulationEnabled())
  2425.  
  2426.         // time stepping
  2427.         m_dtPrev = m_dt / m_dtNormalize;
  2428.         if (m_time == 0) { return 1; } // stop, if frame-dt reached exactly
  2429.         m_time -= m_config.timeStep;
  2430.         if (m_time < 0) // ensure, that the actual frame-dt will be reached exactly in the next step
  2431.         {
  2432.                 m_time = 0;
  2433.                 return 0; // one more loop for m_time=0, eq. stepTime01=1 to reach exact frametime
  2434.         }
  2435.         m_steps++;
  2436.  
  2437.         return 0; // continue substepping
  2438. }
  2439.  
  2440. void CClothSimulator::LaplaceFilterPositions(Vector4* positions, float intensity)
  2441.         {
  2442.         Vector4*& pos = positions;
  2443.  
  2444.         m_listLaplacePosSum.clear();
  2445.         m_listLaplaceN.clear();
  2446.         m_listLaplacePosSum.resize(m_nVtx);
  2447.         m_listLaplaceN.resize(m_nVtx);
  2448.  
  2449.         // clear laplace-offset posSum & N
  2450.         for (auto it = m_listLaplacePosSum.begin(); it != m_listLaplacePosSum.end(); ++it)
  2451.                 {
  2452.                 it->zero();
  2453.                 }
  2454.         for (auto it = m_listLaplaceN.begin(); it != m_listLaplaceN.end(); ++it)
  2455.         {
  2456.                 *it = 0.0f;
  2457.         }
  2458.  
  2459.         // determine laplace-offset dx
  2460.         for (int i = 0; i < m_nEdges; i++)
  2461.         {
  2462.                 int idx0 = m_links[i].i1;
  2463.                 int idx1 = m_links[i].i2;
  2464.                 m_listLaplacePosSum[idx0] += pos[idx1];
  2465.                 m_listLaplaceN[idx0] += 1.0f;                                         // add neighbor position
  2466.                 m_listLaplacePosSum[idx1] += pos[idx0];
  2467.                 m_listLaplaceN[idx1] += 1.0f;                                         // add neighbor position
  2468. }
  2469.  
  2470.         // add laplace-offset dx
  2471.         for (int i = 0; i < m_nVtx; i++)
  2472. {
  2473.                 if (!m_particlesCold[i].bAttached) // don't smooth attached positions
  2474.                 {
  2475.                         Vec3 dxPos = intensity * (m_listLaplacePosSum[i] / m_listLaplaceN[i] - pos[i]);
  2476.                         pos[i] += dxPos;
  2477.                 }
  2478. }
  2479.  
  2480.         // UpdateCollidablesLerp(); ProjectToProxySurface(); // one step of collision projection
  2481. }
  2482.  
  2483. void CClothSimulator::DebugOutput(float stepTime01)
  2484. {
  2485.         switch (m_config.debugPrint)
  2486.         {
  2487.         case 1:
  2488.                 {
  2489.                         float offs = stepTime01 * 150;
  2490.                         g_pAuxGeom->Draw2dLabel(100, 80 + offs, 2.3f, ColorF(1, 0, 0, 1), false, "dt:%4.3f", m_dt / m_dtNormalize);
  2491.                         g_pAuxGeom->Draw2dLabel(300, 80 + offs, 2.3f, ColorF(1, 0, 0, 1), false, "dtP:%4.3f", m_dtPrev);
  2492.                         g_pAuxGeom->Draw2dLabel(500, 80 + offs, 2.3f, ColorF(0, 1, 0, 1), false, "stepTime01:  %4.3f", stepTime01);
  2493.                         if (stepTime01 > 0.9999f) g_pAuxGeom->Draw2dLabel(500, 80, 2.3f, ColorF(0, 1, 0, 1), false, "stepTime01:  0");
  2494.                         g_pAuxGeom->Draw2dLabel(10, 80 + offs, 2.3f, ColorF(0, 1, 0, 1), false, "No:%i", (int)(m_timeInterval / m_config.timeStep + 0.999f));
  2495.                 };
  2496.                 break;
  2497.         case 2:
  2498.                 m_dtPrev = m_dt / m_dtNormalize;
  2499.                 CryWarning(VALIDATOR_MODULE_3DENGINE, VALIDATOR_WARNING, "[Cloth] Force m_dtPrev = m_dt = %f", m_dt / m_dtNormalize);
  2500.                 break;
  2501.         case 3:
  2502.                 CryWarning(VALIDATOR_MODULE_3DENGINE, VALIDATOR_WARNING, "[Cloth] GlobalLocatorPos: %f, %f, %f", m_location.t.x, m_location.t.y, m_location.t.z); // global position of character (locator)
  2503.                 break;
  2504.         }
  2505. }
  2506.  
  2507. void CClothSimulator::DrawHelperInformation()
  2508. {
  2509.         if (m_nVtx <= 0) return;
  2510.         float sphereRadius = this->GetParams().debugDrawVerticesRadius;
  2511.         IRenderAuxGeom* pRendererAux = gEnv->pRenderer->GetIRenderAuxGeom();
  2512.         Vec3 offs = m_pAttachmentManager->m_pSkelInstance->m_location.t;
  2513.  
  2514.         ColorF colorRed(1.0f, 0, 0);