void RPG_HighlightableComponentManager::RenderHighlightableEntities(VCompiledTechnique *shader, DynArray_cl<int> const& regs, RPG_HighlightableComponentCollection const& highlightables)
{
  for(int i = 0; i < highlightables.Count(); i++)
  {
    RPG_HighlightableComponent const *const comp = highlightables.GetAt(i);

    VisBaseEntity_cl *const ent = static_cast<VisBaseEntity_cl *>(comp->GetOwner());

    // KGC demo hack (?)
    if(!ent->GetAnimConfig() || ent->GetAnimConfig()->GetSkinningMeshBuffer() == NULL)
      continue;

    VColorRef color = comp->GetColor();
    hkvVec4 const color4 = color.getAsVec4(); //(0.15f, 0.15f, 0.15f, 1.0f);

    for(int j = 0; j < shader->GetShaderCount(); j++)
    {
      VCompiledShaderPass *const shaderPass = shader->GetShader(j);
      if(regs[j] >= 0)
      {
        shaderPass->GetConstantBuffer(VSS_VertexShader)->SetSingleRegisterF(regs[j], color4.data);
        shaderPass->m_bModified = true;
      }
    }

    Vision::RenderLoopHelper.RenderEntityWithShaders(ent, shader->GetShaderCount(), shader->GetShaderList());
  }
}
void VRendererNodeCommon::UpdateTimeOfDay()
{
  // Update the active sky.
  IVSky* pSky = m_spSky;
  if (pSky == NULL)
  {
    pSky = Vision::World.GetActiveSky();
  }
  if (pSky != NULL)
  {
    pSky->Tick(0);
  }

  // Update Time Of Day handler.
  IVTimeOfDay* pTimeOfDayInterface = Vision::Renderer.GetTimeOfDayHandler();
  if (pTimeOfDayInterface != NULL)
  {
    VASSERT_MSG(pTimeOfDayInterface->IsOfType(V_RUNTIME_CLASS(VTimeOfDay)),
      "Incompatible time of day handler installed - has to be VTimeOfDay or a subclass of it!");
    VTimeOfDay* pTimeOfDay = vstatic_cast<VTimeOfDay*>(pTimeOfDayInterface);
    pTimeOfDay->UpdateFogParameters();

    VColorRef vAmbientColor = pTimeOfDay->GetAmbientColor();
    Vision::Renderer.SetGlobalAmbientColor(vAmbientColor.ToFloat().getAsVec4(1.0f));
  }
  else
  {
    // Set the default global ambient color.
    Vision::Renderer.SetGlobalAmbientColor(Vision::Renderer.GetDefaultGlobalAmbientColor());
  }
}
void CRBX_ModelViewCtrl::SetBkgColor(UCHAR r, UCHAR g, UCHAR b)
{
  VisionRenderLoop_cl *pRL = (VisionRenderLoop_cl *)VisRenderContext_cl::GetMainRenderContext()->GetRenderLoop();
  VColorRef clearColor = Vision::Renderer.GetDefaultClearColor();
  clearColor.SetNoAlpha(VColorRef(r,g,b));
  Vision::Renderer.SetDefaultClearColor(clearColor);
}
  VColorRef* DownSample(int iSize, bool &bSuccess)
  {
    bSuccess = true;
    V_SAFE_DELETE_ARRAY(m_pDownSampled);
    m_pDownSampled = new VColorRef[iSize*iSize*iSize];
    VColorRef *pDst = m_pDownSampled;
    int iBlock = 256/iSize;
    for (int z=0;z<iSize;z++)
      for (int y=0;y<iSize;y++)
        for (int x=0;x<iSize;x++,pDst++)
        {
          // average block color:
          int r = 0, g = 0, b = 0;
          int iValid = 0;
          for (int zz=0;zz<iBlock;zz++)
            for (int yy=0;yy<iBlock;yy++)
              for (int xx=0;xx<iBlock;xx++)
              {
                VColorRef c = mapping[x*iBlock+xx][y*iBlock+yy][z*iBlock+zz];
                if (c.a==0) continue;
                iValid++;
                r += (int)c.r;
                g += (int)c.g;
                b += (int)c.b;
              }
          if (iValid>0)
            pDst->SetRGBA(r/iValid,g/iValid,b/iValid,255);
          else
            bSuccess = false;

        }
    return m_pDownSampled;
  }
hkResult vHavokAiNavMeshDebugDisplayHandler::displayLine(const hkVector4& start, const hkVector4& end, hkColor::Argb color, int id, int tag)
{
	VColorRef vcol; vcol.SetRGBA( hkColor::getRedAsChar(color), hkColor::getGreenAsChar(color), hkColor::getBlueAsChar(color), hkColor::getAlphaAsChar(color) );
	hkvVec3 s; vHavokConversionUtils::PhysVecToVisVecWorld(start,s);
	hkvVec3 e; vHavokConversionUtils::PhysVecToVisVecWorld(end,e);
	Vision::Game.DrawSingleLine( s, e, vcol );
	return HK_SUCCESS;
}
hkResult vHavokAiNavMeshDebugDisplayHandler::display3dText(const char* text, const hkVector4& pos, hkColor::Argb color, int id, int tag)
{
	VColorRef vcol; vcol.SetRGBA( hkColor::getRedAsChar(color), hkColor::getGreenAsChar(color), hkColor::getBlueAsChar(color), hkColor::getAlphaAsChar(color) );
	Vision::Message.SetTextColor(vcol);
	hkvVec3 vpos; vHavokConversionUtils::PhysVecToVisVecWorld(pos,vpos);
	Vision::Message.DrawMessage3D(text, vpos);
	Vision::Message.SetTextColor(V_RGBA_WHITE);
	return HK_SUCCESS;
}
hkResult vHavokAiNavMeshDebugDisplayHandler::displayTriangle(const hkVector4& a, const hkVector4& b, const hkVector4& c, hkColor::Argb color, int id, int tag)
{
	hkvVec3 va; vHavokConversionUtils::PhysVecToVisVecWorld(a,va); 
	hkvVec3 vb; vHavokConversionUtils::PhysVecToVisVecWorld(b,vb); 
	hkvVec3 vc; vHavokConversionUtils::PhysVecToVisVecWorld(c,vc); 
	VColorRef vcol; vcol.SetRGBA( hkColor::getRedAsChar(color), hkColor::getGreenAsChar(color), hkColor::getBlueAsChar(color), hkColor::getAlphaAsChar(color) );
	Vision::Game.DrawSingleTriangle( va, vb, vc, vcol );
	return HK_SUCCESS;
}
  void EngineInstanceDecorationGroup::UpdateLightgridColors()
  {
    VColorRef iAmbColor;
    iAmbColor.SetRGBA(m_iAmbientColor);

    hkvVec3 vPos(_x+_lgx,_y+_lgy,_z+_lgz);
    FOREACH_GROUP
      pGroup->SetUseLightgrid(m_bUseLightgrid);
      pGroup->SetLightgridSamplePosition(vPos);
      pGroup->SetAmbientColor(iAmbColor);
      pGroup->UpdateLightgridColors();
    }
 /// \brief
 ///   Helper function to read a color ref value
 inline BOOL ReadColorRef(VColorRef &color) 
 {
   // Read the color in the RGBA order (check if this works correct)
   char red,green,blue,alpha;
   BOOL success = 1;
   success &= ReadChar(red);
   success &= ReadChar(green);
   success &= ReadChar(blue);
   success &= ReadChar(alpha);
   color.SetRGBA(red,green,blue,alpha);
   return success;
 }
 // Set color for subtractive shadows
 inline void SetShadowColor(const VColorRef &shadowColor)
 {
   hkvVec3 vShadowColor = shadowColor.ToFloat();
   float pParams[4] = { vShadowColor.x, vShadowColor.y, vShadowColor.z, 1.0f };
   m_RegShadowColor.SetRegisterValueSafeF(this, pParams);
 }
void VVirtualThumbStick::Update(float fTimeDiff)
{
  if (!m_bActive)
    return;
  
  m_fTimeDiff = fTimeDiff;
  
  VColorRef color = V_RGBA_WHITE;
  int iTouchPointIndex = m_spTouchArea->GetTouchPointIndex();
  if (iTouchPointIndex >= 0)
  {
    const float fTouchPointX = m_spTouchArea->GetInputDevice().GetTouchPointValue(iTouchPointIndex, CT_TOUCH_ABS_X);
    const float fTouchPointY = m_spTouchArea->GetInputDevice().GetTouchPointValue(iTouchPointIndex, CT_TOUCH_ABS_Y);

    // If touch point was released before, reposition the thumb stick.
    if (m_iLastTouchPointIndex < 0) 
    {
      m_iCircleCenterX = static_cast<int>(fTouchPointX);
      m_iCircleCenterY = static_cast<int>(fTouchPointY);
      m_spRingMask->SetPos(
        static_cast<float>(m_iCircleCenterX - m_iRingWidth / 2), 
        static_cast<float>(m_iCircleCenterY - m_iRingHeight / 2));
    }
    
    m_fXValue = (fTouchPointX - m_iCircleCenterX) / (m_iRingWidth * 0.5f);
    m_fYValue = (fTouchPointY - m_iCircleCenterY) / (m_iRingHeight * 0.5f);
    
    float fLength = hkvMath::sqrt(m_fXValue * m_fXValue + m_fYValue * m_fYValue);
    if (fLength >= 1.0f)
    {
      m_fXValue /= fLength;
      m_fYValue /= fLength;
    }

    // Always place the touch area, so that it moves with the thumb. This does
    // prevent the virtual thumb stick to be released when the touch is outside the 
    // initial valid area and has not been released.
    float fHalfWidth, fHalfHeight;
    m_spRingMask->GetTargetSize(fHalfWidth, fHalfHeight);
    fHalfWidth *= 0.5f;
    fHalfHeight *= 0.5f;

    const VRectanglef rect(
      fTouchPointX - fHalfWidth, 
      fTouchPointY - fHalfHeight, 
      fTouchPointX + fHalfWidth, 
      fTouchPointY + fHalfHeight);
    m_spTouchArea->SetArea(rect);
  }
  else
  {
    m_fXValue = 0.0f;
    m_fYValue = 0.0f;
    color.SetRGBA(160, 160, 160, 160);

    // re-set to original area
    m_spTouchArea->SetArea(m_validArea);
  }
  m_iLastTouchPointIndex = iTouchPointIndex;
   
  // Set new circle position
  int iNewCircleX = m_iCircleCenterX + static_cast<int>(m_fXValue * (m_iCircleWidth * 0.5f));
  int iNewCircleY = m_iCircleCenterY + static_cast<int>(m_fYValue * (m_iCircleHeight * 0.5f));
  
  m_spCircleMask->SetPos(
    static_cast<float>(iNewCircleX - m_iCircleWidth / 2), 
    static_cast<float>(iNewCircleY - m_iCircleHeight / 2));

  m_spCircleMask->SetColor(color);
  m_spRingMask->SetColor(color);
}
void VTimeOfDayComponent::UpdateParent()
{
  IVTimeOfDay *pTimeOfDayInterface = Vision::Renderer.GetTimeOfDayHandler();
  if (pTimeOfDayInterface == NULL)
    return;

  VisObject3D_cl *pOwnerObject = (VisObject3D_cl *)m_pOwner;
  VASSERT(pOwnerObject);

  hkvVec3 vDirection(hkvNoInitialization);
  pTimeOfDayInterface->GetSunDirection(vDirection);
  vDirection.normalizeIfNotZero();

  if (AttachmentType == TIMEOFDAY_ATTACHMENT_MOONLIGHTSOURCE)
  {
    vDirection = -vDirection; 
  }
  else if(AttachmentType == TIMEOFDAY_ATTACHMENT_SUNBACKLIGHTSOURCE)
  {
    vDirection.x = -vDirection.x;
    vDirection.y = -vDirection.y;
  }
  
  if (AttachmentType != TIMEOFDAY_ATTACHMENT_ENABLEDATNIGHTLIGHTSOURCE)
  {
    pOwnerObject->SetDirection(vDirection);
  }

  if (AttachmentType == TIMEOFDAY_ATTACHMENT_CORONALIGHTSOURCE)
  {
    // TODO (multiple renderer nodes)
    IVRendererNode *pRenderer = Vision::Renderer.GetRendererNode(0);
    float fNear, fFar;
    pRenderer->GetReferenceContext()->GetClipPlanes(fNear, fFar);
    hkvVec3 vCamPos = pRenderer->GetReferenceContext()->GetCamera()->GetPosition();

    hkvVec3 vCoronaPos = -vDirection;
    vCoronaPos *= 0.95f * fFar;
    vCoronaPos += vCamPos;
    pOwnerObject->SetPosition(vCoronaPos);
  }

  if (m_bIsLightClass)
  {
    VisLightSource_cl *pLight = (VisLightSource_cl*)m_pOwner;
    VColorRef sunColor = pTimeOfDayInterface->GetSunColor();

    bool bSwitchable = (AttachmentType == TIMEOFDAY_ATTACHMENT_ENABLEDATNIGHTLIGHTSOURCE);
    float fBelowHorizonMultiplier = hkvMath::pow (hkvMath::Max(-vDirection.z+0.1f, 0.0f), bSwitchable ? 1.0f : 0.1f);
    fBelowHorizonMultiplier = hkvMath::Min(1.0f, fBelowHorizonMultiplier);

    if (bSwitchable && fBelowHorizonMultiplier < 1.0f && fBelowHorizonMultiplier > 0.f)
    {
      pLight->SetColor(m_iColor);
      pLight->SetMultiplier(Intensity * (1.0f - fBelowHorizonMultiplier));
    }
    else if (AttachmentType == TIMEOFDAY_ATTACHMENT_SUNLIGHTSOURCE)
    {
      pLight->SetColor(sunColor);
      pLight->SetMultiplier(Intensity * fBelowHorizonMultiplier);
    }
    else if ((AttachmentType == TIMEOFDAY_ATTACHMENT_MOONLIGHTSOURCE) ||
             (AttachmentType == TIMEOFDAY_ATTACHMENT_SUNBACKLIGHTSOURCE))
    {
      // TODO
      VColorRef negativeColor = V_RGBA_WHITE - sunColor;
      pLight->SetColor(negativeColor);
      pLight->SetMultiplier(Intensity * fBelowHorizonMultiplier * 0.333f);
    }  
    else if (AttachmentType == TIMEOFDAY_ATTACHMENT_CORONALIGHTSOURCE)
    {
      hkvVec3 vSunColorFloat = sunColor.ToFloat();
      float fLargestComponent = hkvMath::Max(hkvMath::Max(vSunColorFloat.x, vSunColorFloat.y), vSunColorFloat.z);
      if (fLargestComponent <= 0.0f)
        fLargestComponent = 1.0f;
      sunColor.FromFloat(vSunColorFloat * (1.0f / fLargestComponent));

      pLight->SetColor(sunColor * fBelowHorizonMultiplier);
      pLight->SetMultiplier(0.0f);
    }
  }
}
void VTimeOfDayComponent::UpdateParent()
{
  VTimeOfDay *pTimeOfDayInterface = (VTimeOfDay*)Vision::Renderer.GetTimeOfDayHandler();
  if (pTimeOfDayInterface == NULL)
    return;

  VisObject3D_cl *pOwnerObject = (VisObject3D_cl *)m_pOwner;
  VASSERT(pOwnerObject);

  hkvVec3 vDirection(hkvNoInitialization);
  pTimeOfDayInterface->GetSunDirection(vDirection);

  // The Moon and back light direction is calculated from the Sun direction
  if (AttachmentType == TIMEOFDAY_ATTACHMENT_MOONLIGHTSOURCE)
  {
    vDirection = -vDirection; 
  }
  else if(AttachmentType == TIMEOFDAY_ATTACHMENT_SUNBACKLIGHTSOURCE)
  {
    vDirection.x = -vDirection.x;
    vDirection.y = -vDirection.y;
  }
  
  if (AttachmentType != TIMEOFDAY_ATTACHMENT_ENABLEDATNIGHTLIGHTSOURCE)
  {
    pOwnerObject->SetDirection(vDirection);
  }

  if (AttachmentType == TIMEOFDAY_ATTACHMENT_CORONALIGHTSOURCE)
  {
    // TODO (multiple renderer nodes)
    IVRendererNode *pRenderer = Vision::Renderer.GetRendererNode(0);
    float fNear, fFar;
    pRenderer->GetReferenceContext()->GetClipPlanes(fNear, fFar);
    hkvVec3 vCamPos = pRenderer->GetReferenceContext()->GetCamera()->GetPosition();

    hkvVec3 vCoronaPos = -vDirection;
    vCoronaPos *= 0.95f * fFar;
    vCoronaPos += vCamPos;
    pOwnerObject->SetPosition(vCoronaPos);
  }

  // Set the color and intensity of the light
  if (m_bIsLightClass)
  {
    VisLightSource_cl *pLight = (VisLightSource_cl*)m_pOwner;
    VColorRef color;
    float intensity = 0.0f;

    switch (AttachmentType)
    {
    case TIMEOFDAY_ATTACHMENT_ENABLEDATNIGHTLIGHTSOURCE:
      {
        color = m_iColor;
        const float fMarginNearHorizon = 0.1f; //10% - Margin above the horizon to switch lights ON/OFF
        const float fBelowHorizonMultiplier = hkvMath::Max(-vDirection.z + fMarginNearHorizon, 0.0f);
        intensity = 1.0f - hkvMath::Min(1.0f, fBelowHorizonMultiplier);
        break;
      }
    case TIMEOFDAY_ATTACHMENT_CORONALIGHTSOURCE:
      {
        color = pTimeOfDayInterface->GetSunColor();
        hkvVec3 vSunColorFloat = color.ToFloat();
        float fLargestComponent = hkvMath::Max(hkvMath::Max(vSunColorFloat.x, vSunColorFloat.y), vSunColorFloat.z);
        if (fLargestComponent > 0.0f)
        {
          color.FromFloat(vSunColorFloat / fLargestComponent);
        }      
        intensity = 0.0f;
        break;
      }
    case TIMEOFDAY_ATTACHMENT_SUNLIGHTSOURCE:
      {
        color = pTimeOfDayInterface->GetSunColor();
        intensity = pTimeOfDayInterface->GetSunIntensity();
        break;
      }
    case TIMEOFDAY_ATTACHMENT_SUNBACKLIGHTSOURCE:
      {
        color = pTimeOfDayInterface->GetBackLightColor();
        intensity = pTimeOfDayInterface->GetBackLightIntensity();
        break;
      }
    case TIMEOFDAY_ATTACHMENT_MOONLIGHTSOURCE:
      {
        color = pTimeOfDayInterface->GetMoonColor();
        intensity = pTimeOfDayInterface->GetMoonIntensity();
        break;
      }
    default:
      VASSERT_MSG(0,"Unknown time of day attachment type");
    }

    pLight->SetColor(color);
    pLight->SetMultiplier(intensity * Intensity);    
  }
}