Exemple #1
0
// Helper for OnRunGameLoop
// The update loop is responsible for deleting "dead" entities and updating the core engine's variables
void VisionApp_cl::RunUpdateLoop()
{
  VISION_PROFILE_FUNCTION( VIS_PROFILE_GAMELOOP_UPDATELOOP );

  // Delete "dead" entities from previous frame
  Vision::Game.FreeRemovedEntities();

  const VisEntityCollection_cl &updatedEntities = Vision::Game.GetUpdatedEntities();
  const int iNumEntities = updatedEntities.GetNumEntries();
  int &i = updatedEntities.m_iIterator; // use this iterator to keep counter in-sync if collection changes during loop
  for (i=0; i<iNumEntities; i++)
  {
    VisBaseEntity_cl *pEntity = updatedEntities.GetEntry(i);
    if (!pEntity)
      continue;

    VISION_PROFILE_FUNCTION(VIS_PROFILE_GAMELOOP_MODULESYSHANDLE);

    // send notifications to module system (e.g. all children like bound entities, lights, particles, ...)
    pEntity->Handle();

    // update visibility bounding box
    pEntity->UpdateVisBoundingBox();

    // update core engine variables
    if ( pEntity->IsCoreUpdateRequired() )
      pEntity->UpdateEntityChangedStatus();

    // reset the status flags
    pEntity->ResetStatusFlags();
  } 
}
VParticleWallmark* VWallmarkManager::CreateWallmark(
    VTextureObject *pTexture, VIS_TransparencyType eBlending,
    const hkvVec3& vCenter, const hkvMat3 &alignment,
    VColorRef color, float fLifetime, float fFadeOutTime, bool bApplyDeferredLighting)
{
  VISION_PROFILE_FUNCTION(PROFILING_WALLMARK_CREATION);
  VParticleWallmark* p = CreateParticle(pTexture,eBlending,bApplyDeferredLighting,vCenter,true);
  p->pos[0] = vCenter.x;
  p->pos[1] = vCenter.y;
  p->pos[2] = vCenter.z;
  p->color = color;
  
  hkvVec3 normal = alignment.getAxis(0);
  hkvVec3 right = alignment.getAxis(1);
  hkvVec3 up = alignment.getAxis(2);
  p->size = up.getLength()*2.f;
  normal.normalizeIfNotZero();
  p->normal[0] = normal.x;
  p->normal[1] = normal.y;
  p->normal[2] = normal.z;
  p->distortion[0] = right.x*2.f;
  p->distortion[1] = right.y*2.f;
  p->distortion[2] = right.z*2.f;

  p->velocity[0] = fLifetime + fFadeOutTime;
  p->velocity[1] = fFadeOutTime;
  p->velocity[2] = (float)color.a; // original alpha (255 based)
  return p;
}
Exemple #3
0
// Helper for OnRunGameLoop
// Run the physics simulation
void VisionApp_cl::RunPhysics(float fElapsedTime)
{
  VISION_PROFILE_FUNCTION( VIS_PROFILE_PHYSICS_RUNSIMULATION );
  IVisPhysicsModule_cl *pPhysicsModule = Vision::GetApplication()->GetPhysicsModule();
  if ( pPhysicsModule )
    pPhysicsModule->OnRunPhysics( fElapsedTime );
}
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();
  }
}
Exemple #5
0
// Helper for OnRunGameLoop
// Fetch the physics results
void VisionApp_cl::FetchPhysicsResults()
{
  VISION_PROFILE_FUNCTION( VIS_PROFILE_PHYSICS_FETCHRESULTS );
  IVisPhysicsModule_cl *pPhysicsModule = Vision::GetApplication()->GetPhysicsModule();
  if ( pPhysicsModule )
    pPhysicsModule->FetchPhysicsResults();

  OnUpdatePhysicsFinished.TriggerCallbacks();
}
//Implement VisTypedEngineObject_cl::MessageFunction
void VScriptComponent::MessageFunction(int iID, INT_PTR iParamA, INT_PTR iParamB)
{
  VISION_PROFILE_FUNCTION(PROFILING_SCRIPTING);  //TODO: Different category?
  
  // Return immediately when this component has no script instance
  if (!m_spInstance)
    return;

  if (iID == VIS_MSG_TRIGGER)
  {
    if (m_iFunctions&VSCRIPT_FUNC_ONTRIGGER)
    {
      VisTriggerSourceComponent_cl *pTriggerSrc = (VisTriggerSourceComponent_cl *)iParamA;
      VisTriggerTargetComponent_cl *pTriggerTgt = (VisTriggerTargetComponent_cl *)iParamB;
      m_spInstance->ExecuteFunctionArg("OnTrigger", "*ss",pTriggerSrc->GetComponentName(), pTriggerTgt->GetComponentName());
    }

    return;
  }

  if (iID == VIS_MSG_TRANSITIONSTATEMACHINE)
  {
    if (m_iFunctions&VSCRIPT_FUNC_ONTRANSITIONEVENT)
    {
      
      m_spInstance->ExecuteFunctionArg("OnTransitionEvent", "*i", iParamA);
    }
    return;
  }

  if (iID == VIS_MSG_EVENT) // aka animation event
  {
    if (m_iFunctions&VSCRIPT_FUNC_ONANIMATIONEVENT)
    {
      VisAnimControl_cl *pSender = (VisAnimControl_cl *)iParamB;
      
      //do not call Lua function if the animation has been paused
      if(!pSender->IsPlaying() && m_pLastSenderAnimControl == pSender) return;
      m_pLastSenderAnimControl = pSender;

      //get the name of the animation sequence
      const char * szAnimSequence = pSender->GetAnimSequence() ? pSender->GetAnimSequence()->GetName() : NULL;

      if(Vision::Animations.IsStringEvent((int)iParamA))
      {
        const char * szAnimationEventName = Vision::Animations.GetEventString((int)iParamA);
        m_spInstance->ExecuteFunctionArg("OnAnimationEvent", "*ss", szAnimationEventName, szAnimSequence);
      }
      else
      {
        m_spInstance->ExecuteFunctionArg("OnAnimationEvent", "*is", iParamA, szAnimSequence);
      }
    }
    return;
  }

}
Exemple #7
0
// Helper for OnRunGameLoop
// Pre-physics loop: statistics, prethink, events & animations
void VisionApp_cl::RunPreThink(float fElapsedTime)
{
  {
    VISION_PROFILE_FUNCTION(VIS_PROFILE_GAMELOOP_PRETHINKFUNCTION);

    const VisEntityCollection_cl &relevantEntities = Vision::Game.GetPreThinkingEntities();
    int &i = relevantEntities.m_iIterator; // use this iterator to keep counter in-sync if collection changes during loop
    for (i=0; i<relevantEntities.GetNumEntries(); i++)
    {
      VisBaseEntity_cl *pEntity = relevantEntities.GetEntry( i );
      VASSERT(pEntity->GetPreThinkFunctionStatus());

      // entity code prethink
      pEntity->PreThinkFunction();
    }
  }

  OnUpdateAnimatonBegin.TriggerCallbacks();

  // run animated entities
  {
    VISION_PROFILE_FUNCTION(VIS_PROFILE_ANIMSYS_OVERALL);
    VISION_PROFILE_FUNCTION(VIS_PROFILE_GAMELOOP_ANIMATION);

    const VisEntityCollection_cl &relevantEntities = Vision::Game.GetAnimatedEntities();
    int &i = relevantEntities.m_iIterator; // use this iterator to keep counter in-sync if collection changes during loop
    for (i=0; i<relevantEntities.GetNumEntries(); i++)
    {
      VisBaseEntity_cl *pEntity = relevantEntities.GetEntry( i );
      VASSERT(pEntity->GetAnimConfig()!=NULL);

      //Process the skeletal and muscle animations
      //(Do animation before physics so the motion deltas are available for physics)
      pEntity->HandleAnimations(fElapsedTime);
    }
  }

  OnUpdateAnimatonFinished.TriggerCallbacks();
}
//Implement IVisCallbackHandler_cl
void VScriptComponent::OnHandleCallback(IVisCallbackDataObject_cl *pData)
{
  VISION_PROFILE_FUNCTION(PROFILING_SCRIPTING);  //TODO: Different category?
  VASSERT(m_spInstance);
  if (!m_spInstance || !Vision::Editor.IsAnimatingOrPlaying())
    return;
    
  if (pData->m_pSender==&Vision::Callbacks.OnUpdateSceneBegin)
  {
    if (m_iFunctions & VSCRIPT_FUNC_ONUPDATESCENEBEGIN)
      m_spInstance->ExecuteFunctionArg("OnUpdateSceneBegin", "*");
    return;
  }

  if (pData->m_pSender==&Vision::Callbacks.OnScriptThink)
  {
    if ((m_iFunctions & VSCRIPT_FUNC_ONTHINK) && !Vision::GetScriptManager()->IsPaused() && m_bScriptThinkEnabled)
    {
      m_spInstance->ExecuteFunctionArg("OnThink", "*");
    }
    return;
  }
  
  if (pData->m_pSender==&Vision::Callbacks.OnUpdateSceneFinished)
  {
    if (m_iFunctions & VSCRIPT_FUNC_ONUPDATESCENEFINISHED)
      m_spInstance->ExecuteFunctionArg("OnUpdateSceneFinished", "*");
    return;
  }

  if (pData->m_pSender==&Vision::Callbacks.OnAfterSceneLoaded)
  {
    if (m_iFunctions & VSCRIPT_FUNC_ONAFTERSCENELOADED)
      m_spInstance->ExecuteFunctionArg("OnAfterSceneLoaded", "*");
    return;
  }

  if (pData->m_pSender==&Vision::Callbacks.OnBeforeSceneUnloaded)
  {
    if (m_iFunctions & VSCRIPT_FUNC_ONBEFORESCENEUNLOADED)
      m_spInstance->ExecuteFunctionArg("OnBeforeSceneUnloaded", "*");
    return;
  }

  if (pData->m_pSender==&Vision::Callbacks.OnVideoChanged)
  {
    if (m_iFunctions & VSCRIPT_FUNC_ONVIDEOCHANGED)
      m_spInstance->ExecuteFunctionArg("OnVideoChanged", "*");
    return;
  }
}
Exemple #9
0
// Helper for OnRunGameLoop
// Post-physics loop: posthink & modulesystem-notifications
void VisionApp_cl::RunThink(float fElapsedTime)
{
  const VisEntityCollection_cl &relevantEntities = Vision::Game.GetThinkingEntities();

  VISION_PROFILE_FUNCTION(VIS_PROFILE_GAMELOOP_THINKFUNCTION);

  int &i = relevantEntities.m_iIterator; // use this iterator to keep counter in-sync if collection changes during loop
  for (i=0; i<relevantEntities.GetNumEntries(); i++)
  {
    VisBaseEntity_cl *pEntity = relevantEntities.GetEntry(relevantEntities.m_iIterator);
    VASSERT(pEntity->GetThinkFunctionStatus());

    // entity code postthink
    pEntity->ThinkFunction();
  }
}
BOOL VWallmarkManager::TryAlignWallmark(
    const hkvVec3& vCenter,
    const hkvVec3& vNormal,
    float fSize, float fRotation,
    hkvVec3& vNewCenter,
    hkvMat3 &alignment,
    float fEpsilon
    )
{
  VISION_PROFILE_FUNCTION(PROFILING_WALLMARK_CREATION);

  hkvVec3 vNewNormal(hkvNoInitialization);
  float fTraceRad = fSize;
  if (!IsTracePointOnPlane(vCenter,vNormal,fTraceRad,fEpsilon,vNewNormal))
    return false;

  hkvVec3 vRight(hkvNoInitialization),vUp(hkvNoInitialization),vRotRight(hkvNoInitialization),vRotUp(hkvNoInitialization), vDummy(hkvNoInitialization);
  if (hkvMath::Abs (vNewNormal.x)>0.5f)
    vRight.set(0.f,1.f,0.f);
  else
    vRight.set(1.f,0.f,0.f);
  vUp = vNewNormal.cross(vRight);
  vRight = vNewNormal.cross(vUp);

  float fSin = hkvMath::sinDeg (fRotation);
  float fCos = hkvMath::cosDeg (fRotation);

  vRotRight = vRight *  fCos + vUp * fSin;
  vRotUp    = vRight * -fSin + vUp * fCos;

  vRotRight.setLength(fSize*0.5f);
  vRotUp.setLength(fSize*0.5f);
  alignment.setAxisXYZ (vNewNormal,vRotRight,vRotUp);
  vNewCenter = vCenter + vNewNormal*fEpsilon;

  // check corners:
  if (!IsTracePointOnPlane(vCenter+vRotRight+vRotUp,vNewNormal,fTraceRad,fEpsilon,vDummy))
    return false;
  if (!IsTracePointOnPlane(vCenter+vRotRight-vRotUp,vNewNormal,fTraceRad,fEpsilon,vDummy))
    return false;
  if (!IsTracePointOnPlane(vCenter-vRotRight+vRotUp,vNewNormal,fTraceRad,fEpsilon,vDummy))
    return false;
  if (!IsTracePointOnPlane(vCenter-vRotRight-vRotUp,vNewNormal,fTraceRad,fEpsilon,vDummy))
    return false;

  return TRUE;
}
VDialog *VDialogResource::CreateInstance(IVGUIContext *pContext, VDialog *pParent, int iFlags)
{
  VISION_PROFILE_FUNCTION(VGUIManager::PROFILING_BUILD);
  EnsureLoaded();

  if (!m_pXMLNode || !IsLoaded()) // couldn't load XML file?
  {
    VASSERT(!"VDialogResource::CreateInstance failed because dialog resource is invalid");
    return NULL;
  }

  char szPath[FS_MAX_PATH];
  GetFilePath(szPath);

  const char *szClass = XMLHelper::Exchange_String(m_pXMLNode,"class",NULL,false);
  if (!szClass || !szClass[0])
    szClass = "VDialog";

  VType *pType = Vision::GetTypeManager()->GetType(szClass);
  if (!pType)
  {
    VASSERT(!"VDialogResource::CreateInstance failed because dialog class does not exist in type manager");
    return NULL;
  }
  VDialog *pDlg = (VDialog *)pType->CreateInstance();
  
  // sanity check
  if (!pDlg->IsOfType(Vision::GetTypeManager()->GetType("VDialog")))
    Vision::Error.FatalError("class '%s' is not derived from base class VDialog",szClass);

  VASSERT(pParent==NULL || pParent->m_pContext==pContext);

  pDlg->InitDialog(pContext, this, pParent, iFlags);
  if (!pDlg->Build(m_pXMLNode, szPath,false))
  {
    VASSERT(!"VDialogResource::CreateInstance failed because Build from XML node failed");
    return NULL;
  }
  pDlg->OnBuildFinished();
  pDlg->OnInitDialog();

  return pDlg;
}
bool VisClothDeformer_cl::UpdateDeformerResult(VisVertexAnimResult_cl* pVertexAnimResult)
{
  VISION_PROFILE_FUNCTION(VIS_PROFILE_ANIMSYS_RESULT_VERTEX_ANIM);
   
  if(m_spMesh == NULL)
    return false;

  //// fill vertexanimresult with the mesh data
  // destination buffer
  float *pDestVertexPosition;
  const int  iDestVertexPositionStride = pVertexAnimResult->GetDestVertexPosition(pDestVertexPosition);
  float *pDestVertexNormal;
  const int  iDestVertexNormalStride = pVertexAnimResult->GetDestVertexNormal(pDestVertexNormal);

  int iVertexCount = m_spMesh->GetVertexCount();
  VDynamicMesh *pMesh = pVertexAnimResult->GetMesh();
  VASSERT(pMesh->GetNumOfVertices() == m_spMesh->GetVertexCount());
  VisObjectVertexDelta_t *pVertexDelta = m_spMesh->GetVertexDeltaList();

  // copy mesh vertices into vertexanim result
  hkvVec3 tempNormal(hkvNoInitialization);
  hkvVec3 vTranslate;
  if (m_pParentObject)
    vTranslate = m_pParentObject->GetPosition();

  for(int i=0; i<iVertexCount; i++, pVertexDelta++, ADVANCE_VERTEXPOINTERS)
  {
    pDestVertexPosition[0] = pVertexDelta->delta[0] - vTranslate.x;
    pDestVertexPosition[1] = pVertexDelta->delta[1] - vTranslate.y;
    pDestVertexPosition[2] = pVertexDelta->delta[2] - vTranslate.z;
    tempNormal.set(pVertexDelta->normal[0], pVertexDelta->normal[1], pVertexDelta->normal[2]);
    tempNormal.normalizeIfNotZero();
    pDestVertexNormal[0] = tempNormal.x;
    pDestVertexNormal[1] = tempNormal.y;
    pDestVertexNormal[2] = tempNormal.z;
  }

  return true;
}
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();
  }
}
void VFmodManager::RunTick(float fTimeDelta)
{
  if (!IsInitialized())
    return;

  VISION_PROFILE_FUNCTION(PROFILING_FMOD_OVERALL);

  // profiling scope
  {
    VISION_PROFILE_FUNCTION(PROFILING_FMOD_PUREUPDATE);

    VASSERT(m_pEventSystem!=NULL);
    
    // update Fmod listener attributes
    VisObject3D_cl *pListener = m_pListenerObject ? m_pListenerObject : Vision::Camera.GetMainCamera();
    if (!pListener)
      return;

    hkvVec3 vCamPos = pListener->GetPosition();
    hkvVec3 vDir(pListener->GetObjDir()),
            vRight(pListener->GetObjDir_Right()),
            vUp(pListener->GetObjDir_Up());

    vUp = -vUp; // compensate for coordinate system
    m_pEventSystem->set3DListenerAttributes(0, (FMOD_VECTOR *)&vCamPos, NULL, (FMOD_VECTOR *)&vDir, (FMOD_VECTOR *)&vUp); // no speed (yet)
    
    
    // update all sound objects 
    SoundInstances().Update();

    // update all events 
    Events().Update();

    // update Fmod event system
    m_fTimeLeftOver += fTimeDelta;
    if (m_fTimeLeftOver > m_config.fTimeStep)
    { 
      m_pEventSystem->update();
#ifdef VFMOD_SUPPORTS_NETWORK
      if (m_config.bUseNetworkSystem)
        FMOD::NetEventSystem_Update();
#endif
      m_fTimeLeftOver = hkvMath::mod (m_fTimeLeftOver, m_config.fTimeStep);
    }
  } 
  
  // do not purge sounds/ events in vForge, in order to allow toggling playback via hotspot button
  if (Vision::Editor.IsInEditor())
    return;  

  if (m_bAnyStopped)
  {
    VISION_PROFILE_FUNCTION(PROFILING_FMOD_PURGE);

    // all sounds/ events that have finished playing are removed from handling
    SoundInstances().PurgeNotPlaying();
    Events().PurgeNotPlaying();

    m_bAnyStopped = false; // reset any stopped flag
  }
}
void VFmodManager::RunTick(float fTimeDelta)
{
  VISION_PROFILE_FUNCTION(PROFILING_FMOD_OVERALL);

  if (!IsInitialized())
  {
    if (!IsOutputDevicePresent())
      InitDevice();

    return; 
  }

  // profiling scope
  {
    VISION_PROFILE_FUNCTION(PROFILING_FMOD_PUREUPDATE);

    VASSERT(m_pEventSystem!=NULL);

    // update Fmod listener attributes
    VisObject3D_cl *pListener = m_pListenerObject;
    if (pListener == NULL)
    {
      // The listener is the main camera. Check for teleportation since the last Fmod update, in
      // which case we won't use the position difference to calculate the listener speed.
      VisContextCamera_cl* pCamera = Vision::Camera.GetMainCamera();
      VisRenderContext_cl* pContext = VisRenderContext_cl::GetMainRenderContext();
      if (pCamera != NULL && pContext != NULL)
      {
        if (m_bLastListenerPositionValid && pCamera->GetLastTeleported() > m_iFrameOfLastUpdate)
          m_bLastListenerPositionValid = false;

        m_iFrameOfLastUpdate = pContext->GetLastRenderedFrame();
        pListener = pCamera;
      }
    }

    if (!pListener)
      return;

    hkvVec3 vCamPos = pListener->GetPosition();
    hkvVec3 vDir(pListener->GetObjDir()),
            vRight(pListener->GetObjDir_Right()),
            vUp(pListener->GetObjDir_Up());

    // Determine the camera velocity based on the previous known position
    hkvVec3 vCamVel(m_bLastListenerPositionValid && (fTimeDelta > 0.f) ? (vCamPos - m_vLastListenerPosition) * (1.f / fTimeDelta) : hkvVec3::ZeroVector());
    m_vLastListenerPosition = vCamPos;
    m_bLastListenerPositionValid = true;

    vUp = -vUp; // compensate for coordinate system
    m_pEventSystem->set3DListenerAttributes(0, (FMOD_VECTOR *)&vCamPos, (FMOD_VECTOR *)&vCamVel, (FMOD_VECTOR *)&vDir, (FMOD_VECTOR *)&vUp);

    // update all sound objects 
    SoundInstances().Update(fTimeDelta);

    // update all events 
    Events().Update(fTimeDelta);

    // update Fmod event system
    m_fTimeLeftOver += fTimeDelta;
    if (m_fTimeLeftOver > m_config.fTimeStep)
    { 
      m_pEventSystem->update();

#ifdef VFMOD_SUPPORTS_NETWORK
      if (m_config.bUseNetworkSystem)
        FMOD::NetEventSystem_Update();
#endif
      m_fTimeLeftOver = hkvMath::mod (m_fTimeLeftOver, m_config.fTimeStep);
    }
  }

  // do not purge sounds/ events in vForge, in order to allow toggling playback via hotspot button
  if (Vision::Editor.IsInEditor())
    return;  

  if (m_bAnyStopped)
  {
    VISION_PROFILE_FUNCTION(PROFILING_FMOD_PURGE);

    // all sounds/ events that have finished playing are removed from handling
    SoundInstances().PurgeNotPlaying();
    Events().PurgeNotPlaying();

    m_bAnyStopped = false; // reset any stopped flag
  }
}
void VCoronaManager::RenderAllVisibleCoronas()
{
#ifdef SUPPORTS_CORONAS
  VisRenderContext_cl* pContext = VisRenderContext_cl::GetCurrentContext();

  // Determine relevant render context and visibility collector
  IVisVisibilityCollector_cl *pVisCollector = pContext->GetVisibilityCollector();
  if (!pVisCollector)
    return;
  VisRenderContext_cl *pOQContext = pVisCollector->GetOcclusionQueryRenderContext();
  if (pOQContext != NULL)
    pContext = pOQContext;


  if ((pContext->GetRenderFlags() & VIS_RENDERCONTEXT_FLAG_USE_PIXELCOUNTER) == 0)
    return;

  if ((pContext->GetRenderFlags() & VIS_RENDERCONTEXT_FLAG_RENDER_CORONAS) == 0)
    return;

  INSERT_PERF_MARKER_SCOPE("VCoronaManager::RenderAllVisibleCoronas");
  VISION_PROFILE_FUNCTION(PROFILING_CORONA_RENDER);

  // Force for the queries to finish so they are available in this frame.
  if (m_bTeleportedLastFrame && m_bForceQueryOnTeleport)
  {
    UpdateCoronas(VCUF_UPDATE | VCUF_FORCE_FETCH | VCUF_USE_OC_CONTEXT);
  }

  // Ensure size of corona state structure.
  int iContextIndex = pContext->GetNumber();
  if (iContextIndex + 1 > m_State.GetSize())
    m_State.SetSize(iContextIndex + 1, -1);
  VCoronaRenderContextState& state = m_State[iContextIndex];
  int iCapacity = m_Instances.GetCapacity();
  state.EnsureSize(iCapacity);

  const int iCoronasToRender = state.m_Candidates.GetSize();

  // Sort candidates by texture?
  
  VTextureObject* pTexture = NULL;

  // Render all corona components
  Vision::RenderLoopHelper.BeginMeshRendering();
  Vision::RenderLoopHelper.AddMeshStreams(m_spBillboardMesh,VERTEX_STREAM_POSITION);

  for (int i=0; i < iCoronasToRender; ++i)
  {
    VCoronaCandidate& coronaCandidate = state.m_Candidates.ElementAt(i);
    if (coronaCandidate.m_fCurrentVisibility > 0.0f)
    {
      RenderCorona (coronaCandidate, pTexture);
    }
  }

  Vision::RenderLoopHelper.EndMeshRendering();

  m_bTeleportedLastFrame = (pContext->GetCamera()->GetLastTeleported() >= pContext->GetLastRenderedFrame());
#endif
}
void VCoronaManager::UpdateCoronas(int iCoronaUpdateFlags)
{
#ifdef SUPPORTS_CORONAS

  VisRenderContext_cl* pContext = VisRenderContext_cl::GetCurrentContext();

  if ((iCoronaUpdateFlags & VCUF_USE_OC_CONTEXT) > 0)
  {
    // Determine relevant render context and visibility collector
    IVisVisibilityCollector_cl *pVisCollector = pContext->GetVisibilityCollector();
    if (!pVisCollector)
      return;
    VisRenderContext_cl *pOQContext = pVisCollector->GetOcclusionQueryRenderContext();
    if (pOQContext != NULL)
      pContext = pOQContext;
  }

  if (pContext == NULL)
    return;

  if ((pContext->GetRenderFlags() & VIS_RENDERCONTEXT_FLAG_USE_PIXELCOUNTER) == 0)
    return;

  if ((pContext->GetRenderFlags() & VIS_RENDERCONTEXT_FLAG_RENDER_CORONAS) == 0)
    return;

  // Get bitmask for this context.
  unsigned int iRenderFilterMask = pContext->GetRenderFilterMask();

  // get the collection of visible lights.
  IVisVisibilityCollector_cl* pVisCollector = VisRenderContext_cl::GetCurrentContext()->GetVisibilityCollector();
  if (pVisCollector == NULL)
    return;

  VISION_PROFILE_FUNCTION(PROFILING_CORONA_UPDATE);

  // Get multi-sampling mode
  unsigned int iTexelsPerPixel = 1;
  VTextureObject* pDepthTex = pContext->GetDepthStencilTarget();
  if(pDepthTex == NULL)
  {
    // If no depth stencil target is available, we might work without a renderer node and we're in the main context
    if(Vision::Renderer.GetCurrentRendererNode() == NULL && pContext == VisRenderContext_cl::GetMainRenderContext())
    {
      // In this case get the multi-sampling type from the video config as it's used to set the actual backbuffer settings
      // where the main context will render to
      iTexelsPerPixel = hkvMath::Max(1, 1 << ((int)Vision::Video.GetCurrentConfig()->m_eMultiSample));     
    }  
  }
  else if (pDepthTex->GetTextureType() == VTextureLoader::Texture2D)
  {
    iTexelsPerPixel = hkvMath::Max(1u, ((VisRenderableTexture_cl*)pDepthTex)->GetConfig()->m_iMultiSampling);
  }
  
  const VisLightSrcCollection_cl* pVisibleLights = pVisCollector->GetVisibleLights();
  int iCandidates = 0;
  if (pVisibleLights != NULL)
    iCandidates = pVisibleLights->GetNumEntries();

  // Ensure size of coronas state structure.
  int iContextIndex = pContext->GetNumber();
  if (iContextIndex + 1 > m_State.GetSize())
    m_State.SetSize(iContextIndex + 1, -1);
  VCoronaRenderContextState& state = m_State[iContextIndex];
  int iCapacity = m_Instances.GetCapacity();
  state.EnsureSize(iCapacity);

  // Add visible lights with a lens flare component to the candidate list for this frame
  if ((iCoronaUpdateFlags & VCUF_ADD) > 0)
  {
    for (int iCandidate = 0; iCandidate < iCandidates; ++iCandidate)
    {
      VisLightSource_cl* pLight = pVisibleLights->GetEntry(iCandidate);
      if (pLight)
      {
        VCoronaComponent *pComponent = pLight->Components().GetComponentOfBaseType<VCoronaComponent>();
        if (pComponent != NULL && pComponent->IsEnabled() && !state.IsBitSet(pComponent->m_iIndex))
        {
          // The component is not in m_Candidates yet, so we check whether it is a valid candidate
          bool bIsLightOnScreen = pComponent->IsValidCandidate(pContext);

          if (bIsLightOnScreen)
          {
            state.SetBit(pComponent->m_iIndex);
            pContext->SetPixelCounterResult(pComponent->m_CoronaPixelCounter.GetNumber(), 0);
            state.m_Candidates.Append(pComponent);
          }
        }
      }
    }
  }
  

  // Forces the retrieval all pending queries.
  pContext->FetchPixelCounterTestResults( (iCoronaUpdateFlags & VCUF_FORCE_FETCH) > 0 );
   
  
  // Retrieve Queries and update status of lens flares
  if ((iCoronaUpdateFlags & VCUF_UPDATE) > 0)
  {
    for (int i=0; i < state.m_Candidates.GetSize(); ++i)
    {
      VCoronaCandidate& coronaCandidate = state.m_Candidates.ElementAt(i);
      VCoronaComponent* pCorona = coronaCandidate.m_pCorona;
      if (!pCorona || !pCorona->IsEnabled())
        continue;

      if (pCorona->GetOwner())
      {
        // Retrieve occlusion results of the last query
        unsigned int iElementIndex = pCorona->m_CoronaPixelCounter.GetNumber();
        bool bRes = !pContext->IsPixelCounterQueryInProgress(iElementIndex);

        // Reschedule query if the old on could be retrieved or if a teleport forces us to re-query everything.
        if (bRes | ((iCoronaUpdateFlags & VCUF_FORCE_SCHEDULE) > 0) )
          pContext->SchedulePixelCounterTest(iElementIndex);

        unsigned int iDrawnPixels = pContext->GetPixelCounterResult(iElementIndex) / iTexelsPerPixel;

        float fVisibility = (float)iDrawnPixels / ((int)pCorona->QueryRadius * (int)pCorona->QueryRadius * 4);

        // ATI fix for random insanely high return values.
        if (iDrawnPixels > ((unsigned int)pCorona->QueryRadius * 2 + 1) * ((unsigned int)pCorona->QueryRadius * 2 + 1))
        {
          fVisibility = coronaCandidate.m_fLastVisibilityQuery;
        }

        if ((iCoronaUpdateFlags & VCUF_FORCE_FETCH) > 0)
        {
          // Force lens flare visibility to the current query value.
          coronaCandidate.m_fCurrentVisibility = fVisibility;
          coronaCandidate.m_fLastVisibilityQuery = fVisibility;
          pCorona->UpdateVisibility(coronaCandidate.m_fLastVisibilityQuery, coronaCandidate.m_fCurrentVisibility);
        }
        else if (!m_bTeleportedLastFrame)
        {
          coronaCandidate.m_fLastVisibilityQuery = fVisibility;
          pCorona->UpdateVisibility(coronaCandidate.m_fLastVisibilityQuery, coronaCandidate.m_fCurrentVisibility);
        }
        else
        {
          // if we were teleported, the last frame's query results must be invalidated
          coronaCandidate.m_fCurrentVisibility = 0.0f;
          coronaCandidate.m_fLastVisibilityQuery = 0.0f;
        }
      }
    }
  }
  
  // Removes coronas that are outside the frustum and no longer visible.
  if ((iCoronaUpdateFlags & VCUF_REMOVE) > 0)
  {
    for (int i=0; i < state.m_Candidates.GetSize();)
    {
      VCoronaCandidate& coronaCandidate = state.m_Candidates.ElementAt(i);
      VCoronaComponent* pCorona = coronaCandidate.m_pCorona;

      unsigned int iElementIndex = pCorona->m_CoronaPixelCounter.GetNumber();
      // If the visibility reached zero and the corona is no longer potentially visible it is removed from the list
      if (!pCorona->IsEnabled() || !pCorona->GetOwner()
        || (pCorona->GetVisibleBitmask() & iRenderFilterMask) == 0
        || (((VisLightSource_cl*)pCorona->GetOwner())->GetVisibleBitmask() & iRenderFilterMask) == 0
        || ( coronaCandidate.m_fCurrentVisibility == 0.0f && !pCorona->IsValidCandidate(pContext) ) )
      {
        state.RemoveBit(pCorona->m_iIndex);
        state.m_Candidates.SetAt(i, state.m_Candidates.GetAt(state.m_Candidates.GetSize()-1) );
        state.m_Candidates.RemoveAt(state.m_Candidates.GetSize() -1);
        // Reset cache to zero, so we don't see the lens flare once it enters the frustum again.
        pContext->SetPixelCounterResult(iElementIndex, 0);
      }
      else
      {
        ++i;
      }
    }
  }

#endif
}
void VWallmarkManager::OnHandleCallback(IVisCallbackDataObject_cl *pData)
{
  if (pData->m_pSender==&Vision::Callbacks.OnRenderHook)
  {
    VISION_PROFILE_FUNCTION(PROFILING_WALLMARK_RENDERING);
    // render projected wallmarks
    int iEntry = ((VisRenderHookDataObject_cl *)pData)->m_iEntryConst;
    if (iEntry == m_iPrimaryOpaquePassRenderOrder && ((m_eProjectedWMPassTypes & VPT_PrimaryOpaquePass) != 0))
      RenderProjectedWallmarks(VPT_PrimaryOpaquePass);
    else if(iEntry == m_iSecondaryOpaquePassRenderOrder && ((m_eProjectedWMPassTypes & VPT_SecondaryOpaquePass) != 0))
      RenderProjectedWallmarks(VPT_SecondaryOpaquePass);
    else if (iEntry == m_iTransparentPassRenderOrder && ((m_eProjectedWMPassTypes & VPT_TransparentPass)!=0))
      RenderProjectedWallmarks(VPT_TransparentPass);
    return;
  }
  if (pData->m_pSender==&Vision::Callbacks.OnUpdateSceneFinished)
  {
    VISION_PROFILE_FUNCTION(PROFILING_WALLMARK_SIMULATION);
    // simulate particle wallmarks
    int iCount = m_AllWallmarkGroups.Count();
    for (int i=0;i<iCount;i++)
      m_AllWallmarkGroups.GetAt(i)->TickFunction(Vision::GetTimer()->GetTimeDifference());

    // simulate projected wallmarks
    iCount = m_FadingProjectedWallmarks.Count();
    for (int i=0;i<iCount;i++)
      if (m_FadingProjectedWallmarks.GetAt(i)->TickFunction(Vision::GetTimer()->GetTimeDifference()))
      {
        m_FadingProjectedWallmarks.GetAt(i)->DisposeObject();
        i--;iCount--;
      }      
    return;
  }
  // respond to some zone streaming events (clean/rebuild wallmark primitive references) 
  if (pData->m_pSender==&VisZoneResourceManager_cl::GlobalManager().OnResourceChanged)
  {
    VISION_PROFILE_FUNCTION(PROFILING_WALLMARK_CLEANUP);
    VisResourceInfoDataObject_cl *pResData = (VisResourceInfoDataObject_cl *)pData;
    if (pResData->m_iAction==VRESOURCECHANGEDFLAG_LOADEDRESOURCE)
      OnZoneLoaded((VisZoneResource_cl *)pResData->m_pResource);
    else if (pResData->m_iAction==VRESOURCECHANGEDFLAG_UNLOADINGRESOURCE)
      OnZoneUnloading((VisZoneResource_cl *)pResData->m_pResource);
    return;
  }
  // respond to deletion of static geometry instances (that are not part of zones)
  if (pData->m_pSender==&VisStaticGeometryInstance_cl::OnStaticGeometryInstanceDestroyed)
  {
    VISION_PROFILE_FUNCTION(PROFILING_WALLMARK_CLEANUP);
    VisStaticGeometryInstance_cl *pInst =((VisStaticGeometryInstanceObject_cl *)pData)->m_pInstance;
    if ((m_iGeomRefHashMask & GetGeomHashMask(pInst))!=0) // effective early out
      OnStaticGeometryDeleted(pInst);
    return;
  }
  // OnReassignShaders
  if (pData->m_pSender==&Vision::Callbacks.OnReassignShaders)
  {
    // Shaders will be re-created the next time they're used.
    DeleteWallmarkShaders();

    // Re-create shaders for wallmarks with custom effects.
    const int iWallmarkCount = m_AllProjectedWallmarks.Count();
    for (int i = 0; i < iWallmarkCount; i++)
    {
      VProjectedWallmark *pProjWallmark = m_AllProjectedWallmarks.GetAt(i);
      VCompiledEffectPtr spEffect = pProjWallmark->m_spCustomEffect;

      if (spEffect != NULL && spEffect->GetSourceEffect() != NULL)
      {
        const char *szFXName  = spEffect->GetSourceEffect()->GetName();
        const char *szParam   = spEffect->m_sParamStr;
        int iFlags            = spEffect->m_iCreationFlags;

        VCompiledEffect *pFX = Vision::Shaders.CreateEffect(szFXName,szParam,iFlags);

        pProjWallmark->SetCustomShaderEffect(pFX);
      }
    }
    return;
  }
  if (pData->m_pSender == &Vision::Callbacks.OnWorldDeInit)
  {
    // clean-up
    DeleteWallmarkShaders();

    m_AllWallmarkGroups.Clear();
    m_AllProjectedWallmarks.Clear();
    m_FadingProjectedWallmarks.Clear();
    m_iGeomRefHashMask = 0;
    m_eProjectedWMPassTypes = VPT_Undefined;
    return;
  }
}
/////////////////////////////////////////////////////////////////////////////
// RenderAllShadows : render all shadow instances
/////////////////////////////////////////////////////////////////////////////
void VBlobShadowManager::RenderAllShadows()
{
    // if enabled, a 2D bounding box is additionally used for clipping, which saves a lot of fillrate!

    // TODO: PSP2 - fix 2d clipping
#if defined(_VISION_PSP2)
    static bool bClipScissor = false;
#else
    static bool bClipScissor = true;
#endif
    VisFrustum_cl viewFrustum;
    IVisVisibilityCollector_cl *pVisColl = VisRenderContext_cl::GetCurrentContext()->GetVisibilityCollector();
    if (pVisColl==NULL || pVisColl->GetBaseFrustum()==NULL)
        return;
    viewFrustum.CopyFrom((VisFrustum_cl&)*pVisColl->GetBaseFrustum());

    // render all shadows
    VISION_PROFILE_FUNCTION(PROFILING_BS_OVERALL);

    // get the collection of visible (opaque) primitives. For each shadow instance determine
    // the primitives in this list, which intersect with the shadow box
    // (we do not want to render primitives that are not visible)
    const VisStaticGeometryInstanceCollection_cl *pVisibleGeom = pVisColl->GetVisibleStaticGeometryInstancesForPass(VPT_PrimaryOpaquePass);

    VRectanglef clipRect(false);
    VRectanglef screenRect(0.f,0.f,(float)Vision::Video.GetXRes(),(float)Vision::Video.GetYRes());
    hkvVec3 vBoxCorner[8];
    hkvVec2 vCorner2D(false);

    // now render the shadows:
    FOR_ALL_SHADOWS

    if (pShadow->GetOwner())
        pShadow->SetBoundingBoxFromOwnerProperties();

    // shadow box visible?
    if (!viewFrustum.Overlaps(pShadow->m_ShadowBox))
        continue;

    // build 2D bounding box for scissor clipping
    if (bClipScissor)
    {
        VISION_PROFILE_FUNCTION(PROFILING_BS_SCISSORRECT);
        clipRect.Reset();
        pShadow->m_ShadowBox.getCorners(vBoxCorner);
        for (int i=0; i<8; i++)
        {
            // if one vertex is behind camera, do not use clipping
            if (!Vision::Contexts.GetCurrentContext()->Project2D(vBoxCorner[i],vCorner2D.x,vCorner2D.y))
            {
                Vision::RenderLoopHelper.SetScissorRect(NULL);
                goto render_shadow;
            }
            clipRect.Add(vCorner2D);
        }
        VASSERT(clipRect.IsValid());
        clipRect = clipRect.GetIntersection(screenRect);
        if (!clipRect.IsValid())
            continue; // do not render shadows at all if rect is outside the screen
        Vision::RenderLoopHelper.SetScissorRect(&clipRect);
    }

render_shadow:

    // get the visible primitives in the shadow bounding box
    {
        VISION_PROFILE_FUNCTION(PROFILING_BS_DETERMINE_PRIMS);
        // affected static geometry:
        shadowGeom.Clear();
        pVisibleGeom->DetermineEntriesTouchingBox(pShadow->m_ShadowBox,shadowGeom);
    }

    // split into geometry types:
    if (!shadowGeom.GetNumEntries())
        continue;

    const VisStaticGeometryType_e relevantTypes[2] = {STATIC_GEOMETRY_TYPE_MESHINSTANCE,STATIC_GEOMETRY_TYPE_TERRAIN};

    // two relevant geometry types:
    for (int iType=0; iType<2; iType++)
    {
        shadowGeomOfType.Clear();
        shadowGeom.GetEntriesOfType(shadowGeomOfType,relevantTypes[iType]);
        VCompiledTechnique *pFX = GetDefaultTechnique(relevantTypes[iType]);
        if (shadowGeomOfType.GetNumEntries()==0 || pFX==NULL)
            continue;

        // for all the shader in the projection effect (usually 1 shader), render the primitive collection
        const int iShaderCount = pFX->GetShaderCount();

        for (int j=0; j<iShaderCount; j++)
        {
            VBlobShadowShader *pShader = (VBlobShadowShader *)pFX->GetShader(j);

            {   // code block for easier profiling
                VISION_PROFILE_FUNCTION(PROFILING_BS_PREPARE_SHADER);
                // prepare the shader, i.e. setup shadow specific projection planes, colors etc.
                pShader->UpdateShadow(pShadow);
            }
            {   // code block for easier profiling
                VISION_PROFILE_FUNCTION(PROFILING_BS_RENDER_PRIMS);
                Vision::RenderLoopHelper.RenderStaticGeometryWithShader(shadowGeomOfType,*pShader);
            }
        }
    }


}
Exemple #21
0
// Game loop that updates the scene
void VisionApp_cl::OnUpdateScene()
{
  VISION_PROFILE_FUNCTION(VIS_PROFILE_GAMELOOP);

  IVisSceneManager_cl *pSceneManager = Vision::GetSceneManager();
  VASSERT(pSceneManager);

  // Check whether we should use async physics
  IVisPhysicsModule_cl *pPhysicsModule = Vision::GetApplication()->GetPhysicsModule();
  bool bAsyncPhysics;
  if (pPhysicsModule != NULL && pPhysicsModule->GetUseAsynchronousPhysics())
    bAsyncPhysics = true;
  else
    bAsyncPhysics = false; 

  //Timer is not longer updated here, because it needs to be updated right after the frame flip
  float fElapsedTime = Vision::GetTimer()->GetTimeDifference();

  // Advance the scene update counter
  Vision::Game.SetUpdateSceneCount( Vision::Game.GetUpdateSceneCount() + 1 );

  Vision::Callbacks.OnUpdateSceneBegin.TriggerCallbacks();


  //Send any queued messages before we remove entities
  Vision::Game.ProcessMessageQueue();

  // Delete "dead" entities from previous frame
  {
    VISION_PROFILE_FUNCTION( VIS_PROFILE_GAMELOOP_UPDATELOOP );
    Vision::Game.FreeRemovedEntities();
  }

  // Run the pre-physics loop: statistics, prethink, events & animations
  if ( Vision::Editor.IsPlaying() )
    RunPreThink(fElapsedTime);

  //Process animation messages after processing animations
  Vision::Game.ProcessMessageQueue();

  // Run the physics simulation (if physics simulation is set to synchronous)
  if ( Vision::Editor.IsPlaying() && !bAsyncPhysics)
  {
    RunPhysics(fElapsedTime);
    FetchPhysicsResults();
  }

  // Run the post-physics loop: posthink
  if ( Vision::Editor.IsPlaying() )
    RunThink(fElapsedTime);

  // for the editor, we call the EditorThinkFunction function in every mode for every entity:
  if (Vision::Editor.IsInEditor())
  {
    const int iCount = VisBaseEntity_cl::ElementManagerGetSize();
    for (int i=0;i<iCount;i++)
    {
      VisBaseEntity_cl *pEntity = VisBaseEntity_cl::ElementManagerGet(i);
      if (pEntity)
        pEntity->EditorThinkFunction();
    }
  }

  // handle the lightsources (e.g. color animation)
  if (Vision::Editor.IsAnimatingOrPlaying())
    VisLightSource_cl::HandleAllLightSources(fElapsedTime);

  // update the core engine and module system
  RunUpdateLoop();
  Vision::Game.ResetUpdatedEntitiesList();

  // Kick off asynchronous physics simulation
  if ( Vision::Editor.IsPlaying() && bAsyncPhysics )
  {
    RunPhysics(fElapsedTime);
  }

  // Handle portal/visibility zone transitions
  VisObject3DVisData_cl::HandleAllNodeTransitions();

  //Handle render contexts
  VisRenderContext_cl::HandleAllRenderContexts(fElapsedTime);

  //Animate textures (in animate mode)
  VisTextureAnimInstance_cl::HandleAllAnims(Vision::Editor.IsAnimatingOrPlaying() ? fElapsedTime : 0.f);

  // scroll sky only when animating scene
  IVSky *pSky = Vision::World.GetActiveSky();
  if (pSky != NULL && Vision::Editor.IsAnimatingOrPlaying())
    pSky->Tick(fElapsedTime);

  Vision::Callbacks.OnUpdateSceneFinished.TriggerCallbacks();
}