VCustomVolumeObject* VCustomVolumeManager::SearchInstance(const char* szObjectKey) const
{
  int iCount = m_instances.GetLength();
  for (int i=0;i<iCount;i++)
  {
    VCustomVolumeObject* pCustomVolumeObject = m_instances.GetAt(i);
    if(pCustomVolumeObject != NULL && pCustomVolumeObject->HasObjectKey(szObjectKey))
      return pCustomVolumeObject;
  }

  return NULL;
}
bool VLightClippingVolumeRenderer::RenderLightClippingVolumeHelper(VisLightSource_cl *pLight,VStateGroupDepthStencil& sg)
{
  VLightClippingVolumeComponent* pComponent = pLight->Components().GetComponentOfBaseType<VLightClippingVolumeComponent>();
  if(pComponent != NULL && pComponent->GetVolume() != NULL && m_spLightClippingVolumeStencilFill)
  {
    INSERT_PERF_MARKER_SCOPE("VLightClippingVolumeRenderer::RenderLightClippingVolume");

    VisRenderStates_cl::SetDepthStencilState(sg);

    VCustomVolumeObject* pVolume = pComponent->GetVolume();

    VisStaticMesh_cl* pStaticMesh = pVolume->GetStaticMesh();
    if(!pStaticMesh)
      return false;

    VisMeshBuffer_cl* pMeshBuffer = pStaticMesh->GetMeshBuffer();
    if(!pMeshBuffer || pMeshBuffer->GetIndexCount() <= 0)
      return false;

    Vision::RenderLoopHelper.BeginMeshRendering();
    Vision::RenderLoopHelper.ResetMeshStreams();
    Vision::RenderLoopHelper.AddMeshStreams(pMeshBuffer, m_spLightClippingVolumeStencilFill->GetShader(0)->GetStreamMask() | VERTEX_STREAM_INDEXBUFFER);

    hkvMat4 transform;
    transform.setIdentity ();
    transform.setRotationalPart(pVolume->GetRotationMatrix());
    transform.setTranslation(pVolume->GetPosition());
    transform.setScalingFactors(pVolume->GetScale());

    Vision::RenderLoopHelper.SetMeshTransformationMatrix(transform);

    Vision::RenderLoopHelper.RenderMeshes(m_spLightClippingVolumeStencilFill->GetShader(0), pMeshBuffer->GetPrimitiveType(), 0, pMeshBuffer->GetIndexCount() / 3, pMeshBuffer->GetVertexCount());
    Vision::RenderLoopHelper.EndMeshRendering();

    return true;
  }
  return false;
}
void vHavokTriggerVolume::CommonInit()
{
  // Do not initialize the component in case our module is not active
  if (!m_pModule)
  {
    hkvLog::Warning("Failed to initialize vHavokTriggerVolume since a non Havok physics module is currently active");
    return;
  }

  // Get owner custom volume object
  VCustomVolumeObject *pCustomVolume = GetOwnerCustomVolume();
  VVERIFY_OR_RET(pCustomVolume != NULL); 

  // Get the static mesh from the custom volume object
  VisStaticMesh_cl *pMesh = pCustomVolume->GetStaticMesh();
  if (pMesh == NULL)
    return;
  pMesh->EnsureLoaded();

  if ((!pMesh->IsLoaded()) || (pMesh->GetNumOfTriangles() < 1))
    return;
 
  // Get scaling vector from custom volume object
  const hkvVec3 vScale = pCustomVolume->GetScale();

  // Check whether the static mesh has valid size
  const hkvAlignedBBox& bbox = pMesh->GetBoundingBox();
  hkVector4 bbox_min; vHavokConversionUtils::VisVecToPhysVec_noscale(bbox.m_vMin, bbox_min);
  hkVector4 bbox_max; vHavokConversionUtils::VisVecToPhysVec_noscale(bbox.m_vMax, bbox_max);
  hkVector4 bbox_scale; vHavokConversionUtils::VisVecToPhysVec_noscale(vScale, bbox_scale);

  bbox_scale.mul(vHavokConversionUtils::GetVision2HavokScaleSIMD());

  hkVector4 bbox_extent; bbox_extent.setSub(bbox_max,bbox_min); bbox_extent.mul(bbox_scale);

  hkVector4 meshTol; meshTol.setAll(hkReal((Havok_ShapeType==VHavokTriggerVolumeShapeType_CONVEX) ? HKVIS_CONVEX_SHAPE_TOLERANCE : HKVIS_MESH_SHAPE_TOLERANCE));
  hkVector4Comparison notLargeEnough = bbox_extent.less(meshTol);
  if (notLargeEnough.anyIsSet<hkVector4ComparisonMask::MASK_XYZ>())
  {
    const char *szMeshFilename = (pMesh->GetFilename()!=NULL) ? pMesh->GetFilename() : "Unnamed";
    hkvLog::Warning("Initializing vHavokTriggerVolume with a static mesh [%s] with undersized extents (%.4f, %4f, %.4f)", 
      szMeshFilename, bbox_extent(0), bbox_extent(1), bbox_extent(2));
    return;
  }

  // Create shape, thereby the shape is not cached to file. It would not be a good idea, to cache the shape every time, when the user has modified 
  // the custom volume or has switched the custom static mesh. Instead the final shape will be cached at serialization. Only try using a collision 
  // mesh for creation if custom static mesh is used, since otherwise the static mesh is not physically present on disk.
  int iCreationFlags = (!Vision::Editor.IsInEditor()) ? vHavokShapeFactory::VShapeCreationFlags_CACHE_SHAPE : 0;
  iCreationFlags |= pCustomVolume->GetCustomStaticMesh() ? vHavokShapeFactory::VShapeCreationFlags_USE_VCOLMESH : 0;
  
  // Create Havok trigger volume 
  bool bResult = CreateHkTriggerVolume(pMesh, vScale, iCreationFlags);
  VASSERT_MSG(bResult, "Failed to create Havok Trigger Volume");

  // Set debug visibility 
  SetDebugRendering(Debug_Render);

  // Note, that the trigger components are only created here inside vForge. Serialization reads these components from the archive.
  if (!m_spOnObjectEnter)
  {
    m_spOnObjectEnter = new VisTriggerSourceComponent_cl(VHAVOKTRIGGERVOLUME_ONOBJECTENTER, VIS_OBJECTCOMPONENTFLAG_NONE);
    AddComponent(m_spOnObjectEnter);
  }
  if (!m_spOnObjectLeave)
  {
    m_spOnObjectLeave = new VisTriggerSourceComponent_cl(VHAVOKTRIGGERVOLUME_ONOBJECTLEAVE, VIS_OBJECTCOMPONENTFLAG_NONE);
    AddComponent(m_spOnObjectLeave);
  }
  if (!m_spOnCharacterEnter)
  {
    m_spOnCharacterEnter = new VisTriggerSourceComponent_cl(VHAVOKTRIGGERVOLUME_ONCHARACTERENTER, VIS_OBJECTCOMPONENTFLAG_NONE);
    AddComponent(m_spOnCharacterEnter);
  }
  if (!m_spOnCharacterLeave)
  {
    m_spOnCharacterLeave = new VisTriggerSourceComponent_cl(VHAVOKTRIGGERVOLUME_ONCHARACTERLEAVE, VIS_OBJECTCOMPONENTFLAG_NONE);
    AddComponent(m_spOnCharacterLeave);
  }
}