hkpShape* vHavokShapeFactory::CreateConvexShapeFromStaticMeshInstances(const VisStaticMeshInstCollection &meshInstances, hkvMat4 &refTransform, bool shrinkByCvxRadius) { VVERIFY_OR_RET_VAL(meshInstances.GetLength()==1, NULL); // Get the collision mesh for the static mesh instance VisStaticMeshInstance_cl *pMeshInstance = meshInstances[0]; VisStaticMesh_cl *pMesh = pMeshInstance->GetMesh(); IVCollisionMesh *pColMesh = pMesh->GetCollisionMesh(true, true); VVERIFY_OR_RET_VAL(pColMesh!=NULL, NULL); // We transform each static mesh into the reference space. hkvMat4 mTransform = refTransform; mTransform = mTransform.multiply (pMeshInstance->GetTransform()); hkGeometry geom; int iNumColMeshes = hkvMath::Max(pColMesh->GetSubmeshCount(), 1); for (int i=0;i<iNumColMeshes;i++) BuildGeomFromCollisionMesh(pColMesh, i, mTransform, false, geom); // Set the build configuration to set planes equations and connectivity automatically hkpConvexVerticesShape::BuildConfig config; config.m_createConnectivity = true; config.m_shrinkByConvexRadius = shrinkByCvxRadius; hkStridedVertices stridedVerts; stridedVerts.m_numVertices = geom.m_vertices.getSize(); stridedVerts.m_striding = sizeof(hkVector4); stridedVerts.m_vertices = (const hkReal*)geom.m_vertices.begin(); // Create convex shape hkvConvexVerticesShape *pConvexShape = new hkvConvexVerticesShape(pColMesh->GetFileTime(), stridedVerts, config); return pConvexShape; }
bool VisionApp_cl::DeInitInput() { VVERIFY_OR_RET_VAL(m_bInputInitialized,false); VULPSTATUSMESSAGE_0("Deinitializing input"); VInputManager::DeInit(); m_bInputInitialized = false; return true; }
bool VisionApp_cl::InitInput() { VVERIFY_OR_RET_VAL(!m_bInputInitialized,false); #if defined(WIN32) && !defined(_VISION_WINRT) int eInputModeKeyboard = VGL_DIRECTINPUT; if ( (m_iInitFlags & VAPP_USE_DINPUT_KEYBOARD) ==0) eInputModeKeyboard = VGL_WINDOWSINPUT; int eInputModeMouse = VGL_DIRECTINPUT; if ( (m_iInitFlags & VAPP_USE_DINPUT_MOUSE) ==0) eInputModeMouse = VGL_WINDOWSINPUT; VInputManagerPC::Init(eInputModeKeyboard, eInputModeMouse, (m_iInitFlags&VAPP_MOUSE_HIDECURSOR)!=0, (m_iInitFlags&VAPP_MOUSE_NONEXCLUSIVE)==0, (m_iInitFlags&VAPP_KEYBOARD_NONEXCLUSIVE)==0); #else VInputManager::Init(); #endif m_bInputInitialized = true; return true; }
hkRefNew<hkpShape> vHavokShapeFactory::CreateConvexHullShapeFromMesh(VBaseMesh *pMesh, const hkvVec3& vScaleIn, const char **szShapeCacheId, int iCreationFlags) { VVERIFY_OR_RET_VAL(pMesh != NULL, NULL); const bool bAllowStaticMeshCaching = vHavokPhysicsModule_GetDefaultWorldRuntimeSettings().m_bEnableShapeCaching==TRUE; const bool bCacheShape = iCreationFlags & VShapeCreationFlags_CACHE_SHAPE; const vHavokPhysicsModule *pModule = vHavokPhysicsModule::GetInstance(); VASSERT(pModule != NULL); const bool bForceHktShapeCaching = pModule->IsHktShapeCachingEnforced(); const bool bShrinkShape = iCreationFlags & VShapeCreationFlags_SHRINK; char szShapeId[512]; if (bCacheShape) { VASSERT(szShapeCacheId != NULL); // Check whether shape has been already cached for this model with the respective scaling. vHavokShapeFactory::GetIDStringForConvexShape(szShapeId, pMesh->GetFilename(), vScaleIn, bShrinkShape); hkpShape *pCachedShape = FindShape(szShapeId, szShapeCacheId); if (pCachedShape) { pCachedShape->addReference(); return pCachedShape; } // Check if shape is already cached on disk if (bAllowStaticMeshCaching) { pCachedShape = vHavokCachedShape::LoadConvexShape(pMesh, vScaleIn, bShrinkShape); if (pCachedShape) { *szShapeCacheId = AddShape(szShapeId, pCachedShape); #ifdef HK_DEBUG_SLOW const hkClass* loadedClassType = hkVtableClassRegistry::getInstance().getClassFromVirtualInstance(pCachedShape); HK_ASSERT2(0x695cc897, loadedClassType && (hkString::strCmp( loadedClassType->getName(), "hkvConvexVerticesShape" ) == 0), "Serialized in a unexpected cached Havok shape type!"); #endif return pCachedShape; } else if(!Vision::Editor.IsInEditor() && !bForceHktShapeCaching) { Vision::Error.Warning("Cached HKT file for %s is missing. Please generate HKT file (see documentation for details).", pMesh->GetFilename()); } } } // Get the collision mesh for the specified mesh const IVCollisionMesh *pColMesh = (iCreationFlags & VShapeCreationFlags_USE_VCOLMESH) ? pMesh->GetCollisionMesh(true, true) : pMesh->GetTraceMesh(true, true); VASSERT(pColMesh != NULL); hkvMat4 tranform; tranform.setScalingMatrix(vScaleIn); hkGeometry geom; const int iNumColMeshes = hkvMath::Max(pColMesh->GetSubmeshCount(), 1); for (int i=0;i<iNumColMeshes;i++) BuildGeomFromCollisionMesh(pColMesh, i, tranform, true, geom); VVERIFY_OR_RET_VAL(geom.m_vertices.getSize() > 0, NULL); // Set the build configuration to set planes equations and connectivity automatically hkpConvexVerticesShape::BuildConfig config; config.m_createConnectivity = true; config.m_shrinkByConvexRadius = bShrinkShape; hkStridedVertices stridedVerts; stridedVerts.m_numVertices = geom.m_vertices.getSize(); stridedVerts.m_striding = sizeof(hkVector4); stridedVerts.m_vertices = (const hkReal*)geom.m_vertices.begin(); // Create convex shape hkvConvexVerticesShape *pConvexShape = new hkvConvexVerticesShape(pColMesh->GetFileTime(), stridedVerts, config); // Add shape to cache if (bCacheShape) *szShapeCacheId = AddShape(szShapeId, pConvexShape); // Only cache shape to HKT file when inside vForge or when enforced. if ((Vision::Editor.IsInEditor() && bAllowStaticMeshCaching && bCacheShape) || bForceHktShapeCaching) vHavokCachedShape::SaveConvexShape(pMesh, vScaleIn, bShrinkShape, pConvexShape); return pConvexShape; }
hkpShape* vHavokShapeFactory::CreateMeshShapeFromStaticMeshInstances(const VisStaticMeshInstCollection &meshInstances, hkvMat4 &refTransform, bool bAllowPerTriCollisionInfo, VisWeldingType_e eWeldingType) { int iCount = meshInstances.GetLength(); VVERIFY_OR_RET_VAL(iCount>0, NULL); hkGeometry geom; hkInt64 iFileTime = 0; // Iterate all the passed mesh instances hkvMeshMaterialCache materials; hkArray<hkUint8> collisionMask; int subPartIndex = 0; for (int i = 0; i < iCount; i++) { // Get the collision mesh for the static mesh instance const VisStaticMeshInstance_cl *pMeshInstance = meshInstances[i]; VisStaticMesh_cl *pMesh = pMeshInstance->GetMesh(); IVCollisionMesh *pColMesh = pMesh->GetCollisionMesh(true, true); if (pColMesh == NULL) { VASSERT(false); continue; } // Simply retrieve file time from last static mesh instance iFileTime = pColMesh->GetFileTime(); // Create the Havok triangle sub part { int startingNumTris = geom.m_triangles.getSize(); // We transform each static mesh into the reference space. hkvMat4 mTransform = refTransform; mTransform = mTransform.multiply (pMeshInstance->GetTransform()); int iNumColMeshes = hkvMath::Max(pColMesh->GetSubmeshCount(), 1); for (int i=0;i<iNumColMeshes;i++) { int startingNumVerts = geom.m_vertices.getSize(); BuildGeomFromCollisionMesh(pColMesh, i, mTransform, false, geom); int endNumVerts = geom.m_vertices.getSize(); int endNumTris = geom.m_triangles.getSize(); VASSERT( (endNumVerts - startingNumVerts) > 0 ); hkUint32 cdMask = 0; if (bAllowPerTriCollisionInfo && (pColMesh->GetSubmeshCount() > 0)) { const VPhysicsSubmesh& submesh = pColMesh->GetSubmeshes()[i]; cdMask = submesh.iGroupFilter & 0xff; // only lower 8 bits stored in compressed mesh. int numCD = endNumTris - collisionMask.getSize(); hkUint8* cdi = collisionMask.expandBy( numCD ); hkString::memSet(cdi, cdMask, numCD); } } // ColMesh can have Materials. Also need material to store the orig static mesh index (so if count > 1) if ( pColMesh->GetTriSrfIndices() ) { VColMeshMaterial *pColMaterials = pColMesh->GetMaterials(); VASSERT(pColMaterials); int iNumMats = pColMesh->GetMaterialCount(); int matIndexOffset = materials.getSize(); for(int ii=0;ii<iNumMats;ii++) { hkvMeshMaterial& mat = materials.expandOne(); // in Havok there is no StaticFriction, DynamicFriction, anisotropic StaticFriction/ DynamicFriction // instead there is only Friction available // so DynamicFriction is used for Havok Friction -> is there a better workaround? mat.m_fFriction = pColMaterials[ii].fDynamicFriction; mat.m_fRestitution = pColMaterials[ii].fRestitution; if (! pColMaterials[ii].szUserData.IsEmpty()) mat.m_userData = pColMaterials[ii].szUserData.GetChar(); mat.m_iOrignalSubMeshIndex = subPartIndex; } // reindex geom mat id if (matIndexOffset> 0) { for (int ti=startingNumTris; ti < geom.m_triangles.getSize(); ++ti) { VASSERT(geom.m_triangles[ti].m_material < iNumMats); VASSERT(geom.m_triangles[ti].m_material >= 0); geom.m_triangles[ti].m_material += matIndexOffset; } } } // per instance part ++subPartIndex; } } const bool bHaveTriCDData = collisionMask.getSize() > 0; vHavokCompressedInfoCinfo ci( &geom, bHaveTriCDData ? collisionMask.begin() : HK_NULL ); ci.m_weldingType = vHavokConversionUtils::VisToHkWeldingType(eWeldingType); ci.m_collisionFilterInfoMode = bHaveTriCDData ? hkpBvCompressedMeshShape::PER_PRIMITIVE_DATA_8_BIT : hkpBvCompressedMeshShape::PER_PRIMITIVE_DATA_NONE; hkvBvCompressedMeshShape *pCompressedMeshShape = HK_NULL; if ( materials.getSize() > 0 && materials.getSize() < 255) { ci.m_userDataMode = hkpBvCompressedMeshShape::PER_PRIMITIVE_DATA_8_BIT; pCompressedMeshShape = new hkvBvCompressedMeshShape(ci, materials, iFileTime); } else { ci.m_userDataMode = hkpBvCompressedMeshShape::PER_PRIMITIVE_DATA_NONE; pCompressedMeshShape = new hkvBvCompressedMeshShape(ci, iFileTime); } VASSERT_MSG(pCompressedMeshShape->getNumChildShapes() > 0, "hkvBvCompressedMeshShape could not be created for static model!"); pCompressedMeshShape->SetupMaterials(); return pCompressedMeshShape; }
hkRefNew<hkpShape> vHavokShapeFactory::CreateShapeFromStaticMeshInstances(const VisStaticMeshInstCollection &meshInstances, int iCreationFlags, const char **szShapeCacheId) { int iCount = meshInstances.GetLength(); VVERIFY_OR_RET_VAL(iCount>0 && szShapeCacheId!=NULL, NULL); // Actual mesh scale, which is only used for caching. hkvVec3 vScale(hkvNoInitialization); ExtractScaling(meshInstances[0]->GetTransform(), vScale); char szShapeId[512]; const bool bAllowStaticMeshCaching = vHavokPhysicsModule_GetDefaultWorldRuntimeSettings().m_bEnableShapeCaching==TRUE; const vHavokPhysicsModule *pModule = vHavokPhysicsModule::GetInstance(); VASSERT(pModule != NULL); const bool bForceHktShapeCaching = pModule->IsHktShapeCachingEnforced(); // For single mesh instances the per instance welding type is used. For merged mesh instances the global merged welding type is used. VisWeldingType_e eWeldingType = (iCount==1) ? meshInstances[0]->GetWeldingType() : (VisWeldingType_e)vHavokPhysicsModule_GetWorldSetupSettings().m_iMergedStaticWeldingType; const bool bAllowPerTriCollisionInfo = iCreationFlags & VShapeCreationFlags_ALLOW_PERTRICOLINFO; const bool bShrinkByCvxRadius = iCreationFlags & VShapeCreationFlags_SHRINK; // Check whether shape has been already cached for this mesh with the respective scaling. // We are just caching single static mesh instances and no static mesh collections. hkpShape *pCachedShape = HK_NULL; if (iCount == 1) { // first, find the convex version GetIDStringForConvexShape(szShapeId, meshInstances[0]->GetMesh()->GetFilename(), vScale, bShrinkByCvxRadius); pCachedShape = FindShape(szShapeId, szShapeCacheId); if (!pCachedShape) { // then find the mesh version GetIDStringForMeshShape(szShapeId, meshInstances[0]->GetMesh()->GetFilename(), vScale, meshInstances[0]->GetCollisionBehavior(), eWeldingType); pCachedShape = FindShape(szShapeId, szShapeCacheId); } if (pCachedShape) { pCachedShape->addReference(); return pCachedShape; } if (bAllowStaticMeshCaching) { // first, find the convex version pCachedShape = vHavokCachedShape::LoadConvexShape(meshInstances[0]->GetMesh(), vScale, bShrinkByCvxRadius); if (pCachedShape) { *szShapeCacheId = AddShape(szShapeId, pCachedShape); #ifdef HK_DEBUG_SLOW const hkClass* loadedClassType = hkVtableClassRegistry::getInstance().getClassFromVirtualInstance(pCachedShape); HK_ASSERT2(0x5432c902, loadedClassType && (hkString::strCmp( loadedClassType->getName(), "hkvConvexVerticesShape" ) == 0), "Serialized in a unexpected cached Havok shape type!"); #endif return pCachedShape; } else { // then find the mesh version pCachedShape = vHavokCachedShape::LoadMeshShape(meshInstances[0]->GetMesh(), vScale, meshInstances[0]->GetCollisionBehavior(), eWeldingType); } if (pCachedShape ) { *szShapeCacheId = AddShape(szShapeId, pCachedShape); #ifdef HK_DEBUG_SLOW const hkClass* loadedClassType = hkVtableClassRegistry::getInstance().getClassFromVirtualInstance(pCachedShape); HK_ASSERT2(0x5432c902, loadedClassType && (hkString::strCmp( loadedClassType->getName(), "hkvBvCompressedMeshShape" ) == 0), "Serialized in a unexpected cached Havok shape type!"); #endif hkvBvCompressedMeshShape *pCompressedMeshShape = reinterpret_cast<hkvBvCompressedMeshShape*>(pCachedShape); pCompressedMeshShape->SetupMaterials(); return pCachedShape; } else if(!Vision::Editor.IsInEditor() && !bForceHktShapeCaching) { Vision::Error.Warning("Cached HKT file for %s is missing. Please generate HKT file (see documentation for details).", meshInstances[0]->GetMesh()->GetFilename()); } } } // Get the reference transformation. We use the first static mesh as reference // transformation, and thus as the position of the corresponding rigid body. hkvMat4 referenceTransform = meshInstances[0]->GetTransform(); // Remove any scaling from the reference matrix. This one has to be applied to // the Havok shapes, and thus needs to be part of the mesh transforms. referenceTransform.setScalingFactors(hkvVec3 (1)); // We need the inverse referenceTransform to transform each instance into reference space referenceTransform.invert(); referenceTransform.setRow (3, hkvVec4 (0, 0, 0, 1)); // Determine collision type from first static mesh instance. const VisStaticMeshInstance_cl *pMeshInstance = meshInstances[0]; VisStaticMesh_cl *pMesh = pMeshInstance->GetMesh(); IVCollisionMesh *pColMesh = pMesh->GetCollisionMesh(true, true); const bool bIsConvex = pColMesh->GetType()==VIS_COLMESH_GEOTYPE_CONVEXHULL; // Only create a convex shape if a single mesh instance is used, since otherwise merging multiple mesh instances in one single convex hull // will provide in most cases not the desired behavior. Moreover we can only create either a convex hull or a concave mesh shape, therefore // mesh instances with different collision type can't be merged into one shape. hkpShape *pShape = (bIsConvex && iCount==1) ? CreateConvexShapeFromStaticMeshInstances(meshInstances, referenceTransform, bShrinkByCvxRadius) : CreateMeshShapeFromStaticMeshInstances(meshInstances, referenceTransform, bAllowPerTriCollisionInfo, eWeldingType); // We are just caching single static mesh instances and no static mesh collections. if (iCount == 1) { *szShapeCacheId = AddShape(szShapeId, pShape); // Only cache shape to HKT file when inside vForge or when enforced. if ((Vision::Editor.IsInEditor() && bAllowStaticMeshCaching) || bForceHktShapeCaching) { if (bIsConvex) vHavokCachedShape::SaveConvexShape(meshInstances[0]->GetMesh(), vScale, bShrinkByCvxRadius, (hkvConvexVerticesShape*)pShape); else vHavokCachedShape::SaveMeshShape(meshInstances[0]->GetMesh(), vScale, meshInstances[0]->GetCollisionBehavior(), eWeldingType, (hkvBvCompressedMeshShape*)pShape); } } return pShape; }
// -------------------------------------------------------------------------- // // Havok Shape - Mesh // // -------------------------------------------------------------------------- // hkRefNew<hkpShape> vHavokShapeFactory::CreateShapeFromMesh(VBaseMesh* pMesh, const hkvVec3& vScale, const char **szShapeCacheId, int iCreationFlags, VisWeldingType_e eWeldingType) { VVERIFY_OR_RET_VAL(pMesh != NULL, NULL); const bool bAllowStaticMeshCaching = vHavokPhysicsModule_GetDefaultWorldRuntimeSettings().m_bEnableShapeCaching==TRUE; const bool bCacheShape = iCreationFlags & VShapeCreationFlags_CACHE_SHAPE; const vHavokPhysicsModule *pModule = vHavokPhysicsModule::GetInstance(); VASSERT(pModule != NULL); const bool bForceHktShapeCaching = pModule->IsHktShapeCachingEnforced(); char szShapeId[512]; if (bCacheShape) { VASSERT(szShapeCacheId != NULL); // Check whether shape has been already cached for this model with the respective scaling vHavokShapeFactory::GetIDStringForMeshShape(szShapeId, pMesh->GetFilename(), vScale, VisStaticMeshInstance_cl::VIS_COLLISION_BEHAVIOR_CUSTOM, eWeldingType); hkpShape *pCachedShape = FindShape(szShapeId, szShapeCacheId); if (pCachedShape) { pCachedShape->addReference(); return pCachedShape; } // Check if shape is already cached on disk if (bAllowStaticMeshCaching ) { pCachedShape = vHavokCachedShape::LoadMeshShape(pMesh, vScale, VisStaticMeshInstance_cl::VIS_COLLISION_BEHAVIOR_CUSTOM, eWeldingType); if (pCachedShape) { *szShapeCacheId = AddShape(szShapeId, pCachedShape); #ifdef HK_DEBUG_SLOW const hkClass* loadedClassType = hkVtableClassRegistry::getInstance().getClassFromVirtualInstance(pCachedShape); HK_ASSERT2(0x695cc897, loadedClassType && (hkString::strCmp( loadedClassType->getName(), "hkvBvCompressedMeshShape" ) == 0), "Serialized in a unexpected cached Havok shape type!"); #endif hkvBvCompressedMeshShape* pCompressedMeshShape = reinterpret_cast<hkvBvCompressedMeshShape*>(pCachedShape); pCompressedMeshShape->SetupMaterials(); // just to be sure we don't try to access it as material ptr ever return pCompressedMeshShape; } else if(!Vision::Editor.IsInEditor() && !bForceHktShapeCaching) { Vision::Error.Warning("Cached HKT file for %s is missing. Please generate HKT file (see documentation for details).", pMesh->GetFilename()); } } } hkGeometry geom; // Get the collision mesh for the specified mesh IVCollisionMesh *pColMesh = (iCreationFlags & VShapeCreationFlags_USE_VCOLMESH) ? pMesh->GetCollisionMesh(true, true) : pMesh->GetTraceMesh(true, true); VASSERT(pColMesh != NULL); hkvMat4 tranform; tranform.setScalingMatrix(vScale); int iNumColMeshes = hkvMath::Max(pColMesh->GetSubmeshCount(), 1); for (int i=0;i<iNumColMeshes;i++) BuildGeomFromCollisionMesh(pColMesh, i, tranform, false, geom); VVERIFY_OR_RET_VAL(geom.m_vertices.getSize() > 0, NULL); ///XX A DynamicMesh can be animated. We are treating it as static here. hkpDefaultBvCompressedMeshShapeCinfo ci( &geom ); ci.m_collisionFilterInfoMode = hkpBvCompressedMeshShape::PER_PRIMITIVE_DATA_NONE; // Collision info ci.m_userDataMode = hkpBvCompressedMeshShape::PER_PRIMITIVE_DATA_NONE; // Materials ci.m_weldingType = vHavokConversionUtils::VisToHkWeldingType(eWeldingType); hkvBvCompressedMeshShape* pCompressedMeshShape = new hkvBvCompressedMeshShape(ci, pColMesh->GetFileTime()); if (pCompressedMeshShape->getNumChildShapes() <= 0) { pCompressedMeshShape->removeReference(); const char *szMeshFilename = (pMesh->GetFilename() != NULL) ? pMesh->GetFilename() : "UnnamedMesh"; Vision::Error.Warning("Physics Shape for [%s] is empty. Volume too small?", szMeshFilename); return NULL; } if (bCacheShape) *szShapeCacheId = AddShape(szShapeId, pCompressedMeshShape); // Only cache shape to HKT file when inside vForge or when enforced. if ((Vision::Editor.IsInEditor() && bAllowStaticMeshCaching && bCacheShape) || bForceHktShapeCaching) vHavokCachedShape::SaveMeshShape(pMesh, vScale, VisStaticMeshInstance_cl::VIS_COLLISION_BEHAVIOR_CUSTOM, eWeldingType, pCompressedMeshShape); return pCompressedMeshShape; }