Newer
Older
Import / applications / HighwayDash / ports / Game / States / MotdState.cpp
//  BlockyFroggy
//  Copyright © 2017 John Ryland.
//  All rights reserved.
#include "MotdState.h"
#include "GameSim.h"
#include "Math.h"
#include "Dialog.h"
#include "Graphics.h"
#include "Debug.h"
#include "Sphere.h"
#include "Utilities.h"


//! Experiment - @todo just hacked it in to this state
// rtti and exceptions were enabled
#include "AugmentedReality.h"


REGISTER_GAME_STATE(MotdState)


//! @todo localization
const char* MessageOfTheDayList[] = {
  //! @todo make actual messages
  // example ideas for messages
  "    Unlock edit slots   \n"
  "  to customize the game   ",
  
  "    Collect coins to    \n"
  "    earn more points      ",
  
  "     Example test       \n"
  "         MOTD             ",
  
  "        Another         \n"
  "         MOTD             "
};


MotdState* currentObj = nullptr;

MotdState::MotdState()
  : m_camera(0)
{
  currentObj = this;
}

MotdState::~MotdState()
{
  currentObj = nullptr;
}

void MotdState::reset()
{
  accel[0] = 0.0;
  accel[1] = 0.0;
  accel[2] = 0.0;
  pos[0] = 0.0;
  pos[1] = 0.0;
  pos[2] = 0.0;
  vel[0] = 0.0;
  vel[1] = 0.0;
  vel[2] = 0.0;
  memset(m_accelXHistory, 0, sizeof(double)*640);
  memset(m_accelYHistory, 0, sizeof(double)*640);
  memset(m_accelZHistory, 0, sizeof(double)*640);
  memset(m_velXHistory, 0, sizeof(int)*640);
  memset(m_velYHistory, 0, sizeof(int)*640);
  memset(m_velZHistory, 0, sizeof(int)*640);
  memset(m_posXHistory, 0, sizeof(int)*640);
  memset(m_posYHistory, 0, sizeof(int)*640);
  memset(m_posZHistory, 0, sizeof(int)*640);
}

void resetMotd()
{
  if (currentObj)
  {
    currentObj->reset();
  }
}

const char* s_spriteVertexShader = R"(
  attribute vec4 posAndTex;
  varying lowp vec2 textureCoord;
  uniform vec2 invScreen;
  void main()
  {
    textureCoord = vec2(posAndTex.z,posAndTex.w) * vec2(1.0/512.0, 1.0/512.0);
    gl_Position = vec4(posAndTex.xy * invScreen + vec2(-1.0,1.0), 0.0, 1.0);
  }
)";

const char* s_spriteFragmentShader = R"(
  uniform sampler2D texture;
  varying lowp vec2 textureCoord;
  void main()
  {
    gl_FragColor = texture2D(texture, textureCoord);
  }
)";

const char* s_vertexColorsVertexShader =
R"(
  attribute vec3 pos;
  attribute vec4 col;
  varying lowp vec4 colorVarying;
  uniform mat4 modelViewProjectionMatrix;
  void main()
  {
    colorVarying = col;
    gl_Position = modelViewProjectionMatrix * vec4(pos, 1.0);
  }
)";

const char* s_vertexColorsFragmentShader =
R"(
  varying lowp vec4 colorVarying;
  void main()
  {
    gl_FragColor = colorVarying;
  }
)";

const char* s_lineVertexShader = R"(
  attribute vec4 pos;
  attribute vec4 col;
  varying lowp vec4 colorVarying;
  uniform vec2 invScreen;
  void main()
  {
    colorVarying = col;
    gl_Position = vec4(pos.xy * invScreen + vec2(-1.0,1.0), 0.0, 1.0);
  }
)";

const char* s_lineFragmentShader = R"(
  varying lowp vec4 colorVarying;
  void main()
  {
    gl_FragColor = colorVarying;
  }
)";


void MotdState::enter(GameGraphics& graphics)
{
  int messageCount = sizeof(MessageOfTheDayList) / sizeof(MessageOfTheDayList[0]);
  Math::RandomNumberGenerator gen;
  m_motdStr = MessageOfTheDayList[gen.generate(0,messageCount-1)];

  reset();

  // Setup m_spriteProgram program
  //m_deviceMotion.startTracking(1.0 / 30.0);
  const float trackingUpdateRate = 240.0;
  dt = 0.5 / trackingUpdateRate;
  m_deviceMotion.startTracking(1.0 / trackingUpdateRate, [this,trackingUpdateRate](double acceleration[3], float q[4], float a_rotationMatrix[9], float a_acceleration[3]){
    //Log(LL_Info, "Pos: %f  %f %f", x, y, z);
    //Log(LL_Info, "Accel: %f %f %f", acceleration[0], acceleration[1], acceleration[2]);
    //acceleration[0] += 1.0f;


    float baseModelRotation[16];
    Math::quatToMatrix4x4(baseModelRotation, qRot);
    
    /*
    baseModelRotation[0] = a_rotationMatrix[0];
    baseModelRotation[1] = a_rotationMatrix[1];
    baseModelRotation[2] = a_rotationMatrix[2];
    baseModelRotation[4] = a_rotationMatrix[3];
    baseModelRotation[5] = a_rotationMatrix[4];
    baseModelRotation[6] = a_rotationMatrix[5];
    baseModelRotation[8] = a_rotationMatrix[6];
    baseModelRotation[9] = a_rotationMatrix[7];
    baseModelRotation[10] = a_rotationMatrix[8];
    */


    acceleration[0] = a_acceleration[0]*baseModelRotation[0] + a_acceleration[1]*baseModelRotation[1] + a_acceleration[2]*baseModelRotation[2];
    acceleration[1] = a_acceleration[0]*baseModelRotation[4] + a_acceleration[1]*baseModelRotation[5] + a_acceleration[2]*baseModelRotation[6];
    acceleration[2] = a_acceleration[0]*baseModelRotation[8] + a_acceleration[1]*baseModelRotation[9] + a_acceleration[2]*baseModelRotation[10];

acceleration[0] = a_acceleration[0];
acceleration[1] = a_acceleration[1];
acceleration[2] = a_acceleration[2];

double smoothedAccelX = acceleration[0];
double smoothedAccelY = acceleration[1];
double smoothedAccelZ = acceleration[2];
for (int i = 0; i < 4; i++)
{
  smoothedAccelX += m_accelXHistory[i];
  smoothedAccelY += m_accelYHistory[i];
  smoothedAccelZ += m_accelZHistory[i];
}
smoothedAccelX /= 5.0;
smoothedAccelY /= 5.0;
smoothedAccelZ /= 5.0;

acceleration[0] = smoothedAccelX;
acceleration[1] = smoothedAccelY;
acceleration[2] = smoothedAccelZ;

    double sqrMag = acceleration[0]*acceleration[0] + acceleration[1]*acceleration[1] +acceleration[2]*acceleration[2];
    //setDebugValue("sqrMag", float(sqrMag));

    if (true)//sqrMag > 0.0005)
    {
      double newVel[3];
      double g = 1.0;//9.81;
      for (int i = 0; i < 3; i++)
      {
        // newVel[i] = vel[i] + g * dt * (acceleration[i] + accel[i]);
        newVel[i] = vel[i] + g * dt * (acceleration[i] + acceleration[i]);
        pos[i] += dt * (newVel[i] + vel[i]);
        vel[i] = 0.95 * newVel[i];
        accel[i] = acceleration[i];
      }
      dt = 0.5 * 1.0 / trackingUpdateRate;
    }
    else
    {
      float deaccel = 0.7f;
      
      vel[0] *= deaccel;
      vel[1] *= deaccel;
      vel[2] *= deaccel;

      //dt *= 2.0;
    }
    
    
    
acceleration[0] = a_acceleration[0];
acceleration[1] = a_acceleration[1];
acceleration[2] = a_acceleration[2];


    
#if 0
/*
    if (sqrMag > 0.10)
    {
      return;
    }
*/
    // if (sqrMag > 0.0003)
    if (sqrMag > 0.0005)
    {
      
      vel[0] += acceleration[0] * g * dt;
      vel[1] += acceleration[1] * g * dt;
      vel[2] += acceleration[2] * g * dt;

      pos[0] += vel[0] * dt;
      pos[1] += vel[1] * dt;
      pos[2] += vel[2] * dt;
/*
      accel[0] = acceleration[0];
      double accelX = accel[0] * 9.81;
      //acceleration[0] *= 100.0;
      velocityX += accelX * (1.0/60.0);
      posX += velocityX * (1.0/60.0);
      setDebugValue("VelX", float(velocityX));
      setDebugValue("PosX", float(posX));
*/

      float deaccel = 0.98f;
      
      vel[0] *= deaccel;
      vel[1] *= deaccel;
      vel[2] *= deaccel;
      
    } else {

      float deaccel = 0.95f;
      
      vel[0] *= deaccel;
      vel[1] *= deaccel;
      vel[2] *= deaccel;

      pos[0] += vel[0] * dt;
      pos[1] += vel[1] * dt;
      pos[2] += vel[2] * dt;
      
      //velocityX *= 0.95;
    }
#endif
    
    memcpy(&m_accelXHistory[1], &m_accelXHistory[0], sizeof(double)*639);
    memcpy(&m_accelYHistory[1], &m_accelYHistory[0], sizeof(double)*639);
    memcpy(&m_accelZHistory[1], &m_accelZHistory[0], sizeof(double)*639);

    m_accelXHistory[0] = acceleration[0];
    m_accelYHistory[0] = acceleration[1];
    m_accelZHistory[0] = acceleration[2];

    memcpy(&m_velXHistory[1], &m_velXHistory[0], sizeof(int)*639);
    memcpy(&m_velYHistory[1], &m_velYHistory[0], sizeof(int)*639);
    memcpy(&m_velZHistory[1], &m_velZHistory[0], sizeof(int)*639);

    m_velXHistory[0] = int(vel[0] * 300.0);
    m_velYHistory[0] = int(vel[1] * 300.0);
    m_velZHistory[0] = int(vel[2] * 300.0);
    
    memcpy(&m_posXHistory[1], &m_posXHistory[0], sizeof(int)*639);
    memcpy(&m_posYHistory[1], &m_posYHistory[0], sizeof(int)*639);
    memcpy(&m_posZHistory[1], &m_posZHistory[0], sizeof(int)*639);

    m_posXHistory[0] = int(pos[0] * 100.0);
    m_posYHistory[0] = int(pos[1] * 100.0);
    m_posZHistory[0] = int(pos[2] * 100.0);

    memcpy(qRot, q, sizeof(float)*4);
    //memcpy(pos, acceleration, sizeof(float)*3);


    float baseModelRotation2[16];
    baseModelRotation2[0] = a_rotationMatrix[0];
    baseModelRotation2[1] = a_rotationMatrix[1];
    baseModelRotation2[2] = -a_rotationMatrix[2];
    baseModelRotation2[3] = 0.0;
    baseModelRotation2[4] = a_rotationMatrix[3];
    baseModelRotation2[5] = a_rotationMatrix[4];
    baseModelRotation2[6] = -a_rotationMatrix[5];
    baseModelRotation2[7] = 0.0;
    baseModelRotation2[8] = -a_rotationMatrix[6];
    baseModelRotation2[9] = -a_rotationMatrix[7];
    baseModelRotation2[10] = a_rotationMatrix[8];
    baseModelRotation2[11] = 0.0;
    baseModelRotation2[12] = 0.0;
    baseModelRotation2[13] = 0.0;
    baseModelRotation2[14] = 0.0;
    baseModelRotation2[15] = 1.0;


  });
  OptionsType options;
  m_demoModelContext.setup(s_vertexColorsVertexShader, s_vertexColorsFragmentShader, Medium, options);
  m_linesContext.setup(s_lineVertexShader, s_lineFragmentShader, Medium, options, 0, Lines);
  m_linesContext.m_uniforms.m_invScreen.x = 2.0f / 640;
  m_linesContext.m_uniforms.m_invScreen.y = -2.0f / 960;
  m_cameraQuadContext.setup(s_spriteVertexShader, s_spriteFragmentShader, Medium, options, 1);
  m_cameraQuadContext.m_uniforms.m_texture = 0;
  m_cameraQuadContext.m_uniforms.m_invScreen.x = 2.0f / 640;
  m_cameraQuadContext.m_uniforms.m_invScreen.y = -2.0f / 960;
  
  m_demoModelContext.m_vertexArray.m_vertexData.clear();
  
  std::vector<vector3> sphereData;
  CreateIcoSphere(5, sphereData);
  for (int i = 0; i < sphereData.size(); i++)
  {
    m_demoModelContext.m_vertexArray.m_vertexData.push_back(VertexColorVertex{ sphereData[i].x, sphereData[i].y, sphereData[i].z, static_cast<uint8_t>(sphereData[i].x*255), static_cast<uint8_t>(sphereData[i].y*255), static_cast<uint8_t>(sphereData[i].z*255) } );
  }

/*
  m_demoModelContext.m_vertexArray.m_vertexData.push_back(VertexColorVertex{ 0.0, 0.0, 0.0, 255, 0, 0, 255 } );
  m_demoModelContext.m_vertexArray.m_vertexData.push_back(VertexColorVertex{ 1.0, 0.0, 0.0, 255, 0, 0, 255 } );
  m_demoModelContext.m_vertexArray.m_vertexData.push_back(VertexColorVertex{ 1.0, 1.0, 0.0, 255, 0, 0, 255 } );
  m_demoModelContext.m_vertexArray.m_vertexData.push_back(VertexColorVertex{ 1.0, 1.0, 0.0, 255, 0, 0, 255 } );
  m_demoModelContext.m_vertexArray.m_vertexData.push_back(VertexColorVertex{ 0.0, 1.0, 0.0, 255, 0, 0, 255 } );
  m_demoModelContext.m_vertexArray.m_vertexData.push_back(VertexColorVertex{ 0.0, 0.0, 0.0, 255, 0, 0, 255 } );

  m_demoModelContext.m_vertexArray.m_vertexData.push_back(VertexColorVertex{ 0.0, 0.0, 1.0, 255, 0, 0, 255 } );
  m_demoModelContext.m_vertexArray.m_vertexData.push_back(VertexColorVertex{ 1.0, 0.0, 1.0, 255, 0, 0, 255 } );
  m_demoModelContext.m_vertexArray.m_vertexData.push_back(VertexColorVertex{ 1.0, 1.0, 1.0, 255, 0, 0, 255 } );
  m_demoModelContext.m_vertexArray.m_vertexData.push_back(VertexColorVertex{ 1.0, 1.0, 1.0, 255, 0, 0, 255 } );
  m_demoModelContext.m_vertexArray.m_vertexData.push_back(VertexColorVertex{ 0.0, 1.0, 1.0, 255, 0, 0, 255 } );
  m_demoModelContext.m_vertexArray.m_vertexData.push_back(VertexColorVertex{ 0.0, 0.0, 1.0, 255, 0, 0, 255 } );


  m_demoModelContext.m_vertexArray.m_vertexData.push_back(VertexColorVertex{ 0.0, 0.0, 0.0, 0, 255, 0, 255 } );
  m_demoModelContext.m_vertexArray.m_vertexData.push_back(VertexColorVertex{ 0.0, 1.0, 0.0, 0, 255, 0, 255 } );
  m_demoModelContext.m_vertexArray.m_vertexData.push_back(VertexColorVertex{ 0.0, 1.0, 1.0, 0, 255, 0, 255 } );
  m_demoModelContext.m_vertexArray.m_vertexData.push_back(VertexColorVertex{ 0.0, 1.0, 1.0, 0, 255, 0, 255 } );
  m_demoModelContext.m_vertexArray.m_vertexData.push_back(VertexColorVertex{ 0.0, 0.0, 1.0, 0, 255, 0, 255 } );
  m_demoModelContext.m_vertexArray.m_vertexData.push_back(VertexColorVertex{ 0.0, 0.0, 0.0, 0, 255, 0, 255 } );
  
  m_demoModelContext.m_vertexArray.m_vertexData.push_back(VertexColorVertex{ 1.0, 0.0, 0.0, 0, 255, 0, 255 } );
  m_demoModelContext.m_vertexArray.m_vertexData.push_back(VertexColorVertex{ 1.0, 1.0, 0.0, 0, 255, 0, 255 } );
  m_demoModelContext.m_vertexArray.m_vertexData.push_back(VertexColorVertex{ 1.0, 1.0, 1.0, 0, 255, 0, 255 } );
  m_demoModelContext.m_vertexArray.m_vertexData.push_back(VertexColorVertex{ 1.0, 1.0, 1.0, 0, 255, 0, 255 } );
  m_demoModelContext.m_vertexArray.m_vertexData.push_back(VertexColorVertex{ 1.0, 0.0, 1.0, 0, 255, 0, 255 } );
  m_demoModelContext.m_vertexArray.m_vertexData.push_back(VertexColorVertex{ 1.0, 0.0, 0.0, 0, 255, 0, 255 } );


  m_demoModelContext.m_vertexArray.m_vertexData.push_back(VertexColorVertex{ 0.0, 0.0, 0.0, 0, 0, 255, 255 } );
  m_demoModelContext.m_vertexArray.m_vertexData.push_back(VertexColorVertex{ 0.0, 0.0, 1.0, 0, 0, 255, 255 } );
  m_demoModelContext.m_vertexArray.m_vertexData.push_back(VertexColorVertex{ 1.0, 0.0, 1.0, 0, 0, 255, 255 } );
  m_demoModelContext.m_vertexArray.m_vertexData.push_back(VertexColorVertex{ 1.0, 0.0, 1.0, 0, 0, 255, 255 } );
  m_demoModelContext.m_vertexArray.m_vertexData.push_back(VertexColorVertex{ 1.0, 0.0, 0.0, 0, 0, 255, 255 } );
  m_demoModelContext.m_vertexArray.m_vertexData.push_back(VertexColorVertex{ 0.0, 0.0, 0.0, 0, 0, 255, 255 } );
  
  m_demoModelContext.m_vertexArray.m_vertexData.push_back(VertexColorVertex{ 0.0, 1.0, 0.0, 0, 0, 255, 255 } );
  m_demoModelContext.m_vertexArray.m_vertexData.push_back(VertexColorVertex{ 0.0, 1.0, 1.0, 0, 0, 255, 255 } );
  m_demoModelContext.m_vertexArray.m_vertexData.push_back(VertexColorVertex{ 1.0, 1.0, 1.0, 0, 0, 255, 255 } );
  m_demoModelContext.m_vertexArray.m_vertexData.push_back(VertexColorVertex{ 1.0, 1.0, 1.0, 0, 0, 255, 255 } );
  m_demoModelContext.m_vertexArray.m_vertexData.push_back(VertexColorVertex{ 1.0, 1.0, 0.0, 0, 0, 255, 255 } );
  m_demoModelContext.m_vertexArray.m_vertexData.push_back(VertexColorVertex{ 0.0, 1.0, 0.0, 0, 0, 255, 255 } );
*/

  m_demoModelContext.update();
}


bool MotdState::update(GameUi::UpdateState& state, float elapsed)
{
  static float tm = 0.0f;
  static unsigned char* d = (unsigned char*)malloc(512*512*4);
  tm += elapsed;
  if (tm > 0.25)//(5.0/30.0))
  {
    tm -= 0.25;//(5.0/30.0);
    m_camera >> m_camFrame;
    int w = m_camFrame.cols;
    int h = m_camFrame.rows;
    unsigned char* data = (unsigned char*)m_camFrame.data;
    int w2 = std::min(w, 512);
    int h2 = std::min(h, 512);
    for (int j = 0; j < h2; j++)
      for (int i = 0; i < w2; i++)
      {
        d[(j*512 + i) * 3 + 0] = data[(j * w + i) * 3 + 2];
        d[(j*512 + i) * 3 + 1] = data[(j * w + i) * 3 + 1];
        d[(j*512 + i) * 3 + 2] = data[(j * w + i) * 3 + 0];
      }
    m_cameraQuadContext.setTextureData(0, d);
  }
  
  Camera camera;
  //static int tick = 0;
  //tick++;
  float x =   0.0f;// + 1.0f * sin(tick / 10.0f);
  float y =   0.0f;// + 1.0f * cos(tick / 10.0f);
  float z = -40.0f;
  float cameraRotate[3] = { 0.0, 0.0, 0.0 };
  float trans[3] = { x, y, z };

/*
  float modelRotate[4];// = { float((tick*5) % 360), float((tick*7) % 360), float((tick*9) % 360), 0.0f };
  float acceleration[3];
  
  //m_deviceMotion.getTrackingData(acceleration, modelRotate);
  
  //Log(LL_Info, "Pos: %f  %f %f", x, y, z);
  Log(LL_Info, "Accel: %f %f %f", acceleration[0], acceleration[1], acceleration[2]);
  
  //acceleration[0] += 1.0f;
  acceleration[0] *= 9.81;
  
  //acceleration[0] *= 100.0;
  static float velocityX = 0.0f;
  static float posX = 0.0f;
  
  velocityX += acceleration[0] * (elapsed/5.0);
  posX += velocityX * (elapsed/5.0);
  velocityX *= 0.95;

  setDebugValue("dt", elapsed*200.0f);
  setDebugValue("VelX", velocityX);
  setDebugValue("PosX", posX);

  setDebugValue("AccelX", acceleration[0]);
  float accelHi = 0.0;
  float accelLo = 0.0;
  if (acceleration[0] > accelHi)
    accelHi = acceleration[0];
  if (acceleration[0] < accelLo)
    accelLo = acceleration[0];
  setDebugValue("AccelXHi", accelHi);
  setDebugValue("AccelXLo", accelLo);
  accelHi *= 0.999;
  accelLo *= 0.999;
*/

  float scale = 200.0 * atof(state.m_variables["POS_SCALE"].c_str());
  float bounds = 100.0 * atof(state.m_variables["POS_BOUNDS"].c_str());

  setDebugValue("Scale", scale);
  setDebugValue("Bounds", bounds);

  trans[0] =   0 +  pos[0] * scale;
  trans[1] =   0 +  pos[1] * scale;  // +20
  trans[2] =   0 +  pos[2] * scale;

  for (int i = 0; i < 3; i++)
  {
    trans[i] = pos[i];
    if (trans[i] > bounds) {
      trans[i] = bounds;
      pos[i] = bounds;
    }
    if (trans[i] < -bounds) {
      trans[i] = -bounds;
      pos[i] = -bounds;
    }
    trans[i] *= scale;
  }

  //camera.build(45.0, 640.0/960.0, cameraRotate, 1.0, 0.0, 0.0, 0.0, false);//trans[0], trans[1], trans[2], false);
  camera.build(45.0, 640.0/960.0, cameraRotate, 1.0, trans[0], trans[1], trans[2], false);
  
  float baseModelViewMatrix[16];
  /*
  Math::makeIdentityMatrix4x4(baseModelViewMatrix);
  const float deg2rad = 1.0;//0.017453292f;
  Math::rotateMatrix4x4(baseModelViewMatrix, modelRotate[0] * deg2rad, 0.0f, 1.0f, 0.0f); // yaw
  Math::rotateMatrix4x4(baseModelViewMatrix, modelRotate[1] * deg2rad, 1.0f, 0.0f, 0.0f); // pitch - good
  Math::rotateMatrix4x4(baseModelViewMatrix, modelRotate[2] * deg2rad, 0.0f, 0.0f, 1.0f); // roll
  */

  float baseModelTranslation[16];
  Math::makeIdentityMatrix4x4(baseModelTranslation);
  Math::translateMatrix4x4(baseModelTranslation, 0, 30, 0); // trans[0], trans[1], trans[2]);
  float baseModelRotation[16];
  Math::quatToMatrix4x4(baseModelRotation, qRot);
  Math::multiplyMatrix4x4(baseModelViewMatrix, baseModelRotation, baseModelTranslation);
  Math::scaleMatrix4x4(baseModelViewMatrix, 5.0, 5.0, 5.0);
  Math::translateMatrix4x4(baseModelViewMatrix, -0.5f, -0.5f, -0.5f);
  
  float modelViewMatrix[16];
  Math::multiplyMatrix4x4(modelViewMatrix, camera.m_cameraMatrix, baseModelViewMatrix);
  Math::multiplyMatrix4x4(camera.m_modelViewProjectionMatrix, camera.m_projectionMatrix, modelViewMatrix);

  memcpy(m_demoModelContext.m_uniforms.m_modelViewProjectionMatrix.m, camera.m_modelViewProjectionMatrix, sizeof(float)*16);

  m_cameraQuadContext.m_vertexArray.m_vertexData.clear();
  GameUi::Rectangle r{0,0,640,960};
  int w = m_camFrame.cols;
  int h = m_camFrame.rows;
  GameUi::Rectangle tex{0,0,w,h};
  int t[2][6] = { { 0, 0, 1, 1, 1, 0 }, { 0, 1, 1, 1, 0, 0 } };
  for (int i = 0; i < 6; i++)
    m_cameraQuadContext.m_vertexArray.m_vertexData.push_back(ScreenVertex{int16_t(r.x+t[0][i]*r.w), int16_t(r.y+t[1][i]*r.h),int16_t(tex.x+t[0][i]*tex.w), int16_t(tex.y+t[1][i]*tex.h)});
  m_cameraQuadContext.update();

  m_linesContext.m_vertexArray.m_vertexData.clear();
  
  for (int16_t i = 0; i < 639; i++)
  {
    int16_t o = i + 1;
    m_linesContext.m_vertexArray.m_vertexData.push_back(LineVertex{ i, static_cast<int16_t>(m_accelXHistory[  i]*200.0 + 200), 255, 0, 0, 255 });
    m_linesContext.m_vertexArray.m_vertexData.push_back(LineVertex{ o, static_cast<int16_t>(m_accelXHistory[i+1]*200.0 + 200), 255, 0, 0, 255 });

    m_linesContext.m_vertexArray.m_vertexData.push_back(LineVertex{ i, static_cast<int16_t>(m_accelYHistory[  i]*200.0 + 400), 255, 0, 0, 255 });
    m_linesContext.m_vertexArray.m_vertexData.push_back(LineVertex{ o, static_cast<int16_t>(m_accelYHistory[i+1]*200.0 + 400), 255, 0, 0, 255 });

    m_linesContext.m_vertexArray.m_vertexData.push_back(LineVertex{ i, static_cast<int16_t>(m_accelZHistory[  i]*200.0 + 600), 255, 0, 0, 255 });
    m_linesContext.m_vertexArray.m_vertexData.push_back(LineVertex{ o, static_cast<int16_t>(m_accelZHistory[i+1]*200.0 + 600), 255, 0, 0, 255 });


    m_linesContext.m_vertexArray.m_vertexData.push_back(LineVertex{ i, static_cast<int16_t>(m_velXHistory[  i] + 200), 0, 255, 0, 255 });
    m_linesContext.m_vertexArray.m_vertexData.push_back(LineVertex{ o, static_cast<int16_t>(m_velXHistory[i+1] + 200), 0, 255, 0, 255 });

    m_linesContext.m_vertexArray.m_vertexData.push_back(LineVertex{ i, static_cast<int16_t>(m_velYHistory[  i] + 400), 0, 255, 0, 255 });
    m_linesContext.m_vertexArray.m_vertexData.push_back(LineVertex{ o, static_cast<int16_t>(m_velYHistory[i+1] + 400), 0, 255, 0, 255 });

    m_linesContext.m_vertexArray.m_vertexData.push_back(LineVertex{ i, static_cast<int16_t>(m_velZHistory[  i] + 600), 0, 255, 0, 255 });
    m_linesContext.m_vertexArray.m_vertexData.push_back(LineVertex{ o, static_cast<int16_t>(m_velZHistory[i+1] + 600), 0, 255, 0, 255 });


    m_linesContext.m_vertexArray.m_vertexData.push_back(LineVertex{ i, static_cast<int16_t>(m_posXHistory[  i] + 200), 0, 0, 255, 255 });
    m_linesContext.m_vertexArray.m_vertexData.push_back(LineVertex{ o, static_cast<int16_t>(m_posXHistory[i+1] + 200), 0, 0, 255, 255 });

    m_linesContext.m_vertexArray.m_vertexData.push_back(LineVertex{ i, static_cast<int16_t>(m_posYHistory[  i] + 400), 0, 0, 255, 255 });
    m_linesContext.m_vertexArray.m_vertexData.push_back(LineVertex{ o, static_cast<int16_t>(m_posYHistory[i+1] + 400), 0, 0, 255, 255 });

    m_linesContext.m_vertexArray.m_vertexData.push_back(LineVertex{ i, static_cast<int16_t>(m_posZHistory[  i] + 600), 0, 0, 255, 255 });
    m_linesContext.m_vertexArray.m_vertexData.push_back(LineVertex{ o, static_cast<int16_t>(m_posZHistory[i+1] + 600), 0, 0, 255, 255 });
  }
  m_linesContext.update();

  return true; // has to be exited via ui
}


void MotdState::draw(GameGraphics& graphics)
{
  // CMMotionManager
  // attitude

  graphics.prepareScreenContext();
  
  static GameUi::DrawItems items;
  items.m_items.resize(0);
  static std::vector<std::string> strings = Utilities::split(m_motdStr, '\n');
  static GameUi::Text txt;
  //static std::string line;
  for (int i = 0; i < strings.size(); i++) {
    txt = strings[i].c_str();
    items.addContrastString(80, 220+30*i++, txt);
  }
  
  graphics.drawAuxItems(items);


  // draw camera quad
  glDisable(GL_CULL_FACE);
  glDisable(GL_DEPTH_TEST);
  m_cameraQuadContext.draw();
  glEnable(GL_CULL_FACE);
  glEnable(GL_DEPTH_TEST);


  glClear(GL_DEPTH_BUFFER_BIT);
  //glDisable(GL_CULL_FACE);
  //glDisable(GL_DEPTH_TEST);
  m_demoModelContext.draw();
  //glEnable(GL_CULL_FACE);
  //glEnable(GL_DEPTH_TEST);


  glClear(GL_DEPTH_BUFFER_BIT);
  m_linesContext.draw();
}