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