void vHavokStaticMesh::Init(VisStaticMeshInstCollection &meshInstances)
{
  // Init may only be called once
  VVERIFY_OR_RET(m_bInitialized == false);

  // Add the static mesh instances
  int iCount = meshInstances.GetLength();
  for (int i = 0; i < iCount; i++)
  {
    m_staticMeshes.Append(meshInstances[i]);
    meshInstances[i]->SetPhysicsObject(this);
    m_iNumValidStaticMeshes++;
  }

  m_bInitialized = true;

  CreateHkRigidBody();
}
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;
}