void VTerrainDecorationEntityModel::RenderBatchIR(VTerrainVisibilityCollectorComponent *pInfoComp, VTerrainDecorationInstance **pInstList, int iCount, RenderMode_e eRenderMode)
{
  // IR Rendering
  VTerrainDecorationModelManager* pManager = (VTerrainDecorationModelManager *)GetParentManager();
  VShaderEffectLib* pEffectLib = pManager->GetInfraredShaderLib();
  if (iCount > 0 && pManager->m_iInstancingBatchCount > 0 && pEffectLib != NULL)
  {
    int iMaxInstanceCount, iInstanceStreamMask;
    VisSurface_cl* pSurface = m_spMesh->GetSurface(0);

    if (m_spInstancingTechIRPrePass == NULL)
    {
      // lazy IR shader init
      RecreateIRShaders(pSurface, pEffectLib);
    }
    if (m_spInstancingTechIRPrePass == NULL || m_spInstancingTechIRMainPass == NULL)
      return;

    const int iPrimitiveCount = m_spModelMesh->GetCurrentPrimitiveCount();
    const int iVertexCount = m_spModelMesh->GetVertexCount();
    const VisMeshBuffer_cl::MB_PrimitiveType_e ePrimType = m_spModelMesh->GetPrimitiveType();

    bool bPrePass = (eRenderMode == RENDER_MODE_IR_PREPASS);
    VCompiledShaderPass* pShader = bPrePass? m_spInstancingTechIRPrePass->GetShader(0) : m_spInstancingTechIRMainPass->GetShader(0);
    
    const int iStreamMask = m_spModelMesh->GetStreamMask() & (pShader->GetStreamMask() | VERTEX_STREAM_INDEXBUFFER);
    VisMeshBuffer_cl* pInstanceMesh = pManager->GetInstanceBuffer(iMaxInstanceCount, iInstanceStreamMask);
    iInstanceStreamMask &= pShader->GetStreamMask();

    // perform the rendering
    Vision::RenderLoopHelper.BeginMeshRendering();

    Vision::RenderLoopHelper.BindDefaultStateGroups(pSurface, pShader);

    if (!bPrePass || pSurface->GetTransparencyType() != VIS_TRANSP_NONE)
      Vision::RenderLoopHelper.BindMeshTexture(pSurface->GetBaseTextureObject(), 0, NULL);

    while (iCount > 0)
    {
      int iRenderCount = hkvMath::Min(iCount, iMaxInstanceCount);

      // fill the instance buffer:
      {
        VISION_PROFILE_FUNCTION(VTerrainSectorManager::PROFILING_RENDERDECORARION_INSTANCE_SETUP);

        VModelInstanceData_t* pDest = (VModelInstanceData_t *)pInstanceMesh->LockVertices(VIS_LOCKFLAG_DISCARDABLE, 0, iRenderCount);
        for (int i = 0; i < iRenderCount; i++, pInstList++, pDest++)
          pDest->Set(*pInstList[0]);
        pInstanceMesh->UnLockVertices();
      }

      iCount -= iRenderCount;

      RENDER_INSTANCES(iRenderCount, iStreamMask);
    }

    Vision::RenderLoopHelper.EndMeshRendering();
  }
}
void VTerrainDecorationEntityModel::RenderBatchOTW(VTerrainVisibilityCollectorComponent *pInfoComp, VTerrainDecorationInstance **pInstList, int iCount)
{
  // OTW rendering
  VTerrainDecorationModelManager *pManager = (VTerrainDecorationModelManager *)GetParentManager();
  if (m_spInstancingTech!=NULL && iCount>4 && pManager->m_iInstancingBatchCount>0 /* && bAllowInstancing*/)
  {
    VCompiledShaderPass *pShader = m_spInstancingTech->GetShader(0);

    Vision::RenderLoopHelper.BeginMeshRendering();
    VisSurface_cl *pSurface = m_spMesh->GetSurface(0);
    Vision::RenderLoopHelper.BindSurfaceTextures(pSurface,pShader,NULL);
    Vision::RenderLoopHelper.BindDefaultStateGroups(pSurface,pShader);
    VisMeshBuffer_cl::MB_PrimitiveType_e ePrimType = m_spModelMesh->GetPrimitiveType();
    int iPrimitiveCount = m_spModelMesh->GetCurrentPrimitiveCount();
    int iVertexCount = m_spModelMesh->GetVertexCount();
    int iMaxInstanceCount, iInstanceStreamMask;
    VisMeshBuffer_cl *pInstanceMesh = ((VTerrainDecorationModelManager *)GetParentManager())->GetInstanceBuffer(iMaxInstanceCount,iInstanceStreamMask);

    // lightmap version
    if (m_iLightmapSampler>=0 && pInfoComp!=NULL)
    {
#ifdef HK_DEBUG
      const VStateGroupTexture *pStateGroupTexture = pShader->GetStateGroupTexture(VSS_PixelShader, m_iLightmapSampler);
      VASSERT(pStateGroupTexture!=NULL && pStateGroupTexture->m_cTextureType==TEXTURETYPE_LIGHTMAP);
#endif

      VStateGroupSampler *pLMSampler = pShader->GetStateGroupSampler(VSS_PixelShader, m_iLightmapSampler);
      VTerrainSector *pLastSector = NULL;
      VTextureObject *pTerrainLightmap = NULL;
      const VTerrainConfig& config(pInfoComp->m_pTerrain->m_Config);
      VTerrainSectorManager &sectormanager(pInfoComp->m_pTerrain->m_SectorManager);
      while (iCount>0)
      {
        int iWantedRenderCount = hkvMath::Min(iCount,iMaxInstanceCount);
        int iRenderCount = 0;

        // fill the instance buffer:
        {
          VISION_PROFILE_FUNCTION(VTerrainSectorManager::PROFILING_RENDERDECORARION_INSTANCE_SETUP);
          VModelInstanceData_t *pDest = (VModelInstanceData_t *)pInstanceMesh->LockVertices(VIS_LOCKFLAG_DISCARDABLE,0,iWantedRenderCount);
          // fill buffer up to lightmap change
          for (int i=0;i<iWantedRenderCount;i++,iRenderCount++,pDest++)
          {
            if (pLastSector!=pInstList[i]->m_pOwnerSector)
            {
              pLastSector = pInstList[i]->m_pOwnerSector;
              VTextureObject *pNewLightmap = pLastSector->m_pMeshPage[0].GetSurfaceSafe().m_spModelLightmaps[0];
              if (pNewLightmap!=pTerrainLightmap)
              {
                if (iRenderCount>0) // start a new batch so break here
                  break;
              }
            }
            pDest->Set(*pInstList[i]);
          }
          pInstanceMesh->UnLockVertices();
        }

        // bind sector specific properties
        VTerrainSector *pStateSetupSector = pInstList[0]->m_pOwnerSector; // this is where the batch starts
        hkvVec4 vWorld2Sector(false);
        // transforms worldspace to sector 0..1 range
        config.GetWorldSpaceToSectorTransform(pStateSetupSector->m_iIndexX,pStateSetupSector->m_iIndexY,vWorld2Sector);
        sectormanager.SetWorld2SectorTransform(vWorld2Sector);
          // standard range -> lightmap
        const hkvVec4 vSector2LM = pStateSetupSector->GetLightmapScaleOffset();
        VisRenderStates_cl::VSSetModelUVToLightmap(vSector2LM.data);
        Vision::RenderLoopHelper.BindMeshTexture(pStateSetupSector->m_pMeshPage[0].GetSurfaceSafe().m_spModelLightmaps[0],m_iLightmapSampler,pLMSampler);

        // advance by actual render counts
        pInstList += iRenderCount;
        iCount-=iRenderCount;
        RENDER_INSTANCES(iRenderCount, m_iModelStreams);
      }

    }
    else // non-lightmapped version
    {
      while (iCount>0)
      {
        int iRenderCount = hkvMath::Min(iCount,iMaxInstanceCount);

        // fill the instance buffer:
        {
          VISION_PROFILE_FUNCTION(VTerrainSectorManager::PROFILING_RENDERDECORARION_INSTANCE_SETUP);
          VModelInstanceData_t *pDest = (VModelInstanceData_t *)pInstanceMesh->LockVertices(VIS_LOCKFLAG_DISCARDABLE,0,iRenderCount);
          for (int i=0;i<iRenderCount;i++,pInstList++,pDest++)
            pDest->Set(*pInstList[0]);
          pInstanceMesh->UnLockVertices();
        }

        iCount-=iRenderCount;
        RENDER_INSTANCES(iRenderCount, m_iModelStreams);
      }
    }

    Vision::RenderLoopHelper.EndMeshRendering();
    return;
  }

  //////////////////////////////////////////////////////////
  // Non-instancing  version

  const VisDrawCallInfo_t *pSurfaceShaderList;
  VDynamicMesh *pMesh = m_spMesh;
  VASSERT(m_spVegetationShaders!=NULL);
  VisShaderSet_cl *pSet = m_spVegetationShaders;
  int iAsmCount = pSet->GetShaderAssignmentList(&pSurfaceShaderList);
  VColorRef iLastColor;

  #ifdef _VR_DX11
    VisRenderStates_cl::SetVSConstantBuffer(7,&m_PerInstanceData);
  #endif

  if (m_bNeedsLightmap && pInfoComp!=NULL)
  {
    VTerrainSector *pLastSector = NULL;
    VTextureObject *pTerrainLightmap = NULL;
    const VTerrainConfig& config(pInfoComp->m_pTerrain->m_Config);
    VTerrainSectorManager &sectormanager(pInfoComp->m_pTerrain->m_SectorManager);

    Vision::RenderLoopHelper.BeginEntityRendering();
    for (int i=0;i<iCount;i++,pInstList++)
    {
      if (pLastSector!=(*pInstList)->m_pOwnerSector)
      {
        pLastSector = (*pInstList)->m_pOwnerSector;
        VTextureObject *pNewLightmap = pLastSector->m_pMeshPage[0].GetSurfaceSafe().m_spModelLightmaps[0];
        if (pNewLightmap!=pTerrainLightmap)
        {
          // assign new model lightmaps
          const int iSrfCount = m_spMesh->GetSurfaceCount();
          for (int j=0;j<iSrfCount;j++)
            m_spMesh->GetSurface(j)->m_spModelLightmaps[0] = pNewLightmap;

          // and also force a shader re-binding
          for (int j=0;j<iAsmCount;j++)
            pSurfaceShaderList[j].GetShader()->m_bModified=true;

          pTerrainLightmap = pNewLightmap;
        }

        hkvVec4 vWorld2Sector(false);
        // transforms worldspace to sector 0..1 range
        config.GetWorldSpaceToSectorTransform(pLastSector->m_iIndexX,pLastSector->m_iIndexY,vWorld2Sector);
        sectormanager.SetWorld2SectorTransform(vWorld2Sector);
          // standard range -> lightmap
        const hkvVec4 vSector2LM = pLastSector->GetLightmapScaleOffset();
        VisRenderStates_cl::VSSetModelUVToLightmap(vSector2LM.data);
      }

      // per instance tint color
      if (i==0 || iLastColor!=(*pInstList)->m_InstanceColor)
      {
        iLastColor = (*pInstList)->m_InstanceColor;
        VPerInstanceData_t &data(m_PerInstanceData.BeginUpdate());
          VColorRef::RGBA_To_Float((*pInstList)->m_InstanceColor, data.vPerInstanceColor);
        m_PerInstanceData.EndUpdate();
      #ifndef _VR_DX11
        VisRenderStates_cl::SetVSConstantBuffer(7,&m_PerInstanceData);
      #endif
      }

      // finally render object
      hkvMat4 transform((*pInstList)->m_Orientation,(*pInstList)->m_vPosition);
      Vision::RenderLoopHelper.RenderModelWithSurfaceShaderList(m_spMesh,transform.getPointer (),iAsmCount,pSurfaceShaderList);
    }
    VisRenderStates_cl::SetVSConstantBuffer(7,NULL);
    Vision::RenderLoopHelper.EndEntityRendering();
  }
  else
  {
    Vision::RenderLoopHelper.BeginEntityRendering();

    // no lightmaps -> simple loop 
    for (int i=0;i<iCount;i++,pInstList++)
    {
      // per instance tint color
      if (i==0 || iLastColor!=(*pInstList)->m_InstanceColor)
      {
        iLastColor = (*pInstList)->m_InstanceColor;
        VPerInstanceData_t &data(m_PerInstanceData.BeginUpdate());
          VColorRef::RGBA_To_Float((*pInstList)->m_InstanceColor, data.vPerInstanceColor);
        m_PerInstanceData.EndUpdate();
      #ifndef _VR_DX11
        VisRenderStates_cl::SetVSConstantBuffer(7,&m_PerInstanceData);
      #endif
      }
      hkvMat4 transform((*pInstList)->m_Orientation,(*pInstList)->m_vPosition);
      Vision::RenderLoopHelper.RenderModelWithSurfaceShaderList(m_spMesh,transform.getPointer(),iAsmCount,pSurfaceShaderList);
    }

    VisRenderStates_cl::SetVSConstantBuffer(7,NULL);

    Vision::RenderLoopHelper.EndEntityRendering();
  }
}
void VTerrainDecorationEntityModel::RenderBatchDepthShadow(VTerrainVisibilityCollectorComponent *pInfoComp, VTerrainDecorationInstance **pInstList, int iCount)
{
  // depth shader rendering
  INSERT_PERF_MARKER_SCOPE("VTerrainDecorationEntityModel::RenderBatchDepthShadow");
  VTerrainDecorationModelManager *pManager = (VTerrainDecorationModelManager *)GetParentManager();

  if (m_spInstancingTechShadow!=NULL && iCount>4 && pManager->m_iInstancingBatchCount>0 /* && bAllowInstancing*/)
  {
    VCompiledShaderPass *pShader = m_spInstancingTechShadow->GetShader(0);

    Vision::RenderLoopHelper.BeginMeshRendering();
    VisSurface_cl *pSurface = m_spMesh->GetSurface(0);
    Vision::RenderLoopHelper.BindSurfaceTextures(pSurface,pShader,NULL);
    Vision::RenderLoopHelper.BindDefaultStateGroups(pSurface,pShader);
    VisMeshBuffer_cl::MB_PrimitiveType_e ePrimType = m_spModelMesh->GetPrimitiveType();
    int iPrimitiveCount = m_spModelMesh->GetCurrentPrimitiveCount();
    int iVertexCount = m_spModelMesh->GetVertexCount();
    int iMaxInstanceCount, iInstanceStreamMask;
    VisMeshBuffer_cl *pInstanceMesh = ((VTerrainDecorationModelManager *)GetParentManager())->GetInstanceBuffer(iMaxInstanceCount,iInstanceStreamMask);

    while (iCount>0)
    {
      int iRenderCount = hkvMath::Min(iCount,iMaxInstanceCount);

      // fill the instance buffer:
      {
        VISION_PROFILE_FUNCTION(VTerrainSectorManager::PROFILING_RENDERDECORARION_INSTANCE_SETUP);
        VModelInstanceData_t *pDest = (VModelInstanceData_t *)pInstanceMesh->LockVertices(VIS_LOCKFLAG_DISCARDABLE,0,iRenderCount);
        for (int i=0;i<iRenderCount;i++,pInstList++,pDest++)
          pDest->Set(*pInstList[0]);
        pInstanceMesh->UnLockVertices();
      }

      iCount-=iRenderCount;
      RENDER_INSTANCES(iRenderCount, m_iModelStreams);
    }
    Vision::RenderLoopHelper.EndMeshRendering();
  } 
  else
  {
    // non-instancing version
    VisDrawCallInfo_t surfaceShaderList[RLP_MAX_ENTITY_SURFACESHADERS];
    const int iNumSubmeshes = m_spMesh->GetSubmeshCount();
    int iAsmCount = 0;
    for (int i=0;i<iNumSubmeshes;i++)
    {
      VDynamicSubmesh *pSubmesh = m_spMesh->GetSubmesh(i);
      VisDrawCallInfo_t &assignment(surfaceShaderList[iAsmCount]);
      if (pSubmesh->GetSurface()->m_spShadowmapFill==NULL)
        continue;
      assignment.Set(pSubmesh, pSubmesh->GetSurface(), pSubmesh->GetSurface()->m_spShadowmapFill->GetShader(0));
      iAsmCount++;
    }
    Vision::RenderLoopHelper.BeginEntityRendering();
    for (int i=0;i<iCount;i++)
    {
      hkvMat4 transform(pInstList[i]->m_Orientation,pInstList[i]->m_vPosition);
      Vision::RenderLoopHelper.RenderModelWithSurfaceShaderList(m_spMesh, transform.getPointer (),iAsmCount,surfaceShaderList);
    }
    Vision::RenderLoopHelper.EndEntityRendering();
  }
}
vHavokDisplayGeometry::vHavokDisplayGeometry(hkDisplayGeometry* geometry, const hkTransform &transform, hkUlong id, int tag)
{
  // Set id
  m_ID = id;

  // Create mesh instance
  if (geometry->getGeometry() == NULL)
    geometry->buildGeometry();

  // Create mesh buffer
  VisMBVertexDescriptor_t desc;
  desc.m_iStride = sizeof(SimpleMesh_t);
  desc.m_iPosOfs = offsetof(SimpleMesh_t,pos);

  UINT iVertices = geometry->getGeometry()->m_vertices.getSize();
  UINT iTriangles = geometry->getGeometry()->m_triangles.getSize();
  VisMeshBuffer_cl *pMesh = new VisMeshBuffer_cl();

  // Copy vertices
  pMesh->AllocateVertices(desc, iVertices);
  SimpleMesh_t *pVertex = (SimpleMesh_t *)pMesh->LockVertices(VIS_LOCKFLAG_DISCARDABLE);
  for (UINT i = 0; i < iVertices; i++, pVertex++)
  {
	  hkVector4 vPos; 
	  vPos.setMul(geometry->getGeometry()->m_vertices[i], vHavokConversionUtils::GetHavok2VisionScaleSIMD());
	  vPos.store<3,HK_IO_NATIVE_ALIGNED>(&pVertex->pos[0]);
  }
  pMesh->UnLockVertices();

  // Copy indices
  pMesh->AllocateIndexList(iTriangles*3);
  unsigned short *pIndex = (unsigned short *)pMesh->LockIndices(VIS_LOCKFLAG_DISCARDABLE);

  for (UINT i = 0; i < iTriangles; i++, pIndex+=3)
  {
    pIndex[0] = geometry->getGeometry()->m_triangles[i].m_a;
    pIndex[1] = geometry->getGeometry()->m_triangles[i].m_b;
    pIndex[2] = geometry->getGeometry()->m_triangles[i].m_c;
  }
  pMesh->UnLockIndices();
  pMesh->SetPrimitiveType(VisMeshBuffer_cl::MB_PRIMTYPE_INDEXED_TRILIST );
  
  // Create mesh instance
  m_spMeshInstance = new VisMeshBufferObject_cl(pMesh);

  // Mesh instance created
  if (m_spMeshInstance == NULL)
    return;
 
  // Apply highlighting shader
  m_spMeshInstance->SetTechnique(CreateHighlightEffect(VColorRef(55, 255, 55)));

  // Set transform. Add the transform of the actual shape to the transform of the Vision mesh. 
  // This is needed for shapes that come from HKT files where they can have custom pivots.
  hkTransform finalTransform = transform;
  finalTransform.setMulEq(geometry->getTransform());
  vHavokConversionUtils::PhysTransformToVisMatVecWorld(finalTransform, m_vRot, m_vPos);
  m_spMeshInstance->SetUseEulerAngles(FALSE);
  m_spMeshInstance->SetPosition(m_vPos);
  m_spMeshInstance->SetRotationMatrix(m_vRot);
  m_spMeshInstance->SetVisible(false);
  m_spMeshInstance->SetObjectFlag(VObjectFlag_AutoDispose);
}