void GsMat::operator *= ( const GsMat& m )
 {
   GsMat* t = (this==&m)? new GsMat(GsMat::NoInit) : this;

   t->setl1 ( E11*m.E11 + E12*m.E21 + E13*m.E31 + E14*m.E41,
              E11*m.E12 + E12*m.E22 + E13*m.E32 + E14*m.E42,
              E11*m.E13 + E12*m.E23 + E13*m.E33 + E14*m.E43,
              E11*m.E14 + E12*m.E24 + E13*m.E34 + E14*m.E44 );

   t->setl2 ( E21*m.E11 + E22*m.E21 + E23*m.E31 + E24*m.E41,
              E21*m.E12 + E22*m.E22 + E23*m.E32 + E24*m.E42,
              E21*m.E13 + E22*m.E23 + E23*m.E33 + E24*m.E43,
              E21*m.E14 + E22*m.E24 + E23*m.E34 + E24*m.E44 );

   t->setl3 ( E31*m.E11 + E32*m.E21 + E33*m.E31 + E34*m.E41,
              E31*m.E12 + E32*m.E22 + E33*m.E32 + E34*m.E42,
              E31*m.E13 + E32*m.E23 + E33*m.E33 + E34*m.E43,
              E31*m.E14 + E32*m.E24 + E33*m.E34 + E34*m.E44 );

   t->setl4 ( E41*m.E11 + E42*m.E21 + E43*m.E31 + E44*m.E41,
              E41*m.E12 + E42*m.E22 + E43*m.E32 + E44*m.E42,
              E41*m.E13 + E42*m.E23 + E43*m.E33 + E44*m.E43,
              E41*m.E14 + E42*m.E24 + E43*m.E34 + E44*m.E44 );

   if ( t!=this ) { *this=*t; delete t; }
 }
void GsMat::mult ( const GsMat& m1, const GsMat& m2 )
 {
   GsMat* m = (this==&m1||this==&m2)? new GsMat(GsMat::NoInit) : this;

   m->setl1 ( m1.E11*m2.E11 + m1.E12*m2.E21 + m1.E13*m2.E31 + m1.E14*m2.E41,
              m1.E11*m2.E12 + m1.E12*m2.E22 + m1.E13*m2.E32 + m1.E14*m2.E42,
              m1.E11*m2.E13 + m1.E12*m2.E23 + m1.E13*m2.E33 + m1.E14*m2.E43,
              m1.E11*m2.E14 + m1.E12*m2.E24 + m1.E13*m2.E34 + m1.E14*m2.E44 );

   m->setl2 ( m1.E21*m2.E11 + m1.E22*m2.E21 + m1.E23*m2.E31 + m1.E24*m2.E41,
              m1.E21*m2.E12 + m1.E22*m2.E22 + m1.E23*m2.E32 + m1.E24*m2.E42,
              m1.E21*m2.E13 + m1.E22*m2.E23 + m1.E23*m2.E33 + m1.E24*m2.E43,
              m1.E21*m2.E14 + m1.E22*m2.E24 + m1.E23*m2.E34 + m1.E24*m2.E44 );

   m->setl3 ( m1.E31*m2.E11 + m1.E32*m2.E21 + m1.E33*m2.E31 + m1.E34*m2.E41,
              m1.E31*m2.E12 + m1.E32*m2.E22 + m1.E33*m2.E32 + m1.E34*m2.E42,
              m1.E31*m2.E13 + m1.E32*m2.E23 + m1.E33*m2.E33 + m1.E34*m2.E43,
              m1.E31*m2.E14 + m1.E32*m2.E24 + m1.E33*m2.E34 + m1.E34*m2.E44 );

   m->setl4 ( m1.E41*m2.E11 + m1.E42*m2.E21 + m1.E43*m2.E31 + m1.E44*m2.E41,
              m1.E41*m2.E12 + m1.E42*m2.E22 + m1.E43*m2.E32 + m1.E44*m2.E42,
              m1.E41*m2.E13 + m1.E42*m2.E23 + m1.E43*m2.E33 + m1.E44*m2.E43,
              m1.E41*m2.E14 + m1.E42*m2.E24 + m1.E43*m2.E34 + m1.E44*m2.E44 );

   if ( m!=this ) { *this=*m; delete m; }
 }
// here we will redraw the scene according to the current state of the application.
void AppWindow::glutDisplay()
{
	// Clear the rendering window
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	// Build a cross with some lines (if not built yet):
	if (_axis.changed) // needs update
	{
		_axis.build(1.0f); // axis has radius 1.0
	}

	// Define our scene transformation:
	GsMat rx, ry, stransf, spacex, spacey, spacexxx, spaceyyy, oogabooga,jetx,jety;
	rx.rotx(_rotx);
	ry.roty(_roty);
	spacex.translation(spacexx, spaceyy, spaceships);
	jetx.translation(jx, jy, jz);
	jety.translation(jx, jy, jz);
	stransf = rx*ry;
	spacey.roty(_rotynew);// set the scene transformation matrix
	spacexxx.roty(_rotxnew);
	spaceyyy.roty(_rotglobalx);
	oogabooga.translation(0, -15, 0);
	_light.pos = stransf * GsVec(0, 10, 0);
					 // Define our projection transformation:
					 // (see demo program in gltutors-projection.7z, we are replicating the same behavior here)
	GsMat camview, persp, sproj;
	if (cam_view) {
		GsVec eye(0, 0, 2), center(0, 0, 0), up(0, 1, 0);
		camview.lookat(eye, center, up); // set our 4x4 "camera" matrix
	}
	else {
		//GsVec eye(5, static_cast <int> (spacexx) , static_cast <int> (spaceships)), center(0, static_cast <int> (spacexx), static_cast <int> (spaceships)), up(0, 1, 0);
		//camview.lookat(eye, center, up); // set our 4x4 "camera" matrix

		GsMat cameraTransform, cameraRotation;
		cameraTransform.translation(0, 1, 2);
		cameraRotation.rotx(-3.14159f / 12.0f);
		GsMat viewMatrix = stransf * spacex * cameraTransform * cameraRotation;
		camview = viewMatrix.inverse();
	}
	//shadowMatrix(0,0,0.5,0.5);
	float aspect = (float)_w / (float) _h, znear = 0.1f, zfar = 500.0f;
	persp.perspective(_fovy, aspect, znear, zfar); // set our 4x4 perspective matrix

												   // Our matrices are in "line-major" format, so vertices should be multiplied on the 
												   // right side of a matrix multiplication, therefore in the expression below camview will
												   // affect the vertex before persp, because v' = (persp*camview)*v = (persp)*(camview*v).
	sproj = persp * camview; // set final scene projection

							 //  Note however that when the shader receives a matrix it will store it in column-major 
							 //  format, what will cause our values to be transposed, and we will then have in our 
							 //  shaders vectors on the left side of a multiplication to a matrix.

							 // Draw:
	if (_viewaxis) _axis.draw(stransf, sproj);
	_model.draw(stransf *spacex, sproj, _light);
	_floorball.draw(stransf*spacex*spaceyyy, sproj, _light);
	_ballleft.draw(stransf *jetx*spacexxx, sproj, _light);
	_ballright.draw(stransf *jety*spacex*spacey, sproj, _light);
	_world.draw(stransf, sproj, _light);


	_model.draw(stransf *spacex*shadowMatrix(0.0f, 0.5f, 0.5f), sproj, _light);
	_floorball.draw(stransf*spacex*spaceyyy*shadowMatrix(0.0f, 0.5f, 0.5f), sproj, _light);
	_ballleft.draw(stransf *spacex*spacexxx*shadowMatrix(0.0f, 0.5f, 0.5f), sproj, _light);
	_ballright.draw(stransf *spacex*spacey*shadowMatrix(0.0f, 0.5f, 0.5f), sproj, _light);
	ground.draw(stransf, sproj);

	
	// Swap buffers and draw:
	glFlush();         // flush the pipeline (usually not necessary)
	glutSwapBuffers(); // we were drawing to the back buffer, now bring it to the front
}
// here we will redraw the scene according to the current state of the application.
void AppWindow::glutDisplay ()
{
    // Frame time calculations
    high_resolution_clock::time_point currentTime = high_resolution_clock::now();
    duration<double> frameDelta = duration_cast<duration<double>>(currentTime - previousTime);
    previousTime = currentTime;
    
    if(!paused)
    {
        frameTime += frameDelta.count();
    }
    
    double subsecondsRotation = frameTime * (2.0 * M_PI);
    double secondsRotation = (frameTime / 60.0) * (2.0 * M_PI);
    subsecondsRotation = -subsecondsRotation;
    secondsRotation = -secondsRotation;
    
    // Clear the rendering window
    glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

    // Build a cross with some lines (if not built yet):
    if ( _axis.changed ) // needs update
    {
        _axis.build(1.0f); // axis has radius 1.0
    }
    if ( _border.changed )
    {
        _border.build(0.1f, 0.5f, 60);
    }
    if ( _seconds.changed )
    {
        _seconds.build(0.425f, 0.008333f, 0.008333f, 6);
    }
    if ( _subseconds.changed )
    {
        _subseconds.build(0.30f, 0.008333f, 0.008333f, 6);
    }

    // Define our scene transformation:
    GsMat rx, ry, stransf, nshadow;
    nshadow.identity();
    rx.rotx ( _rotx );
    ry.roty ( _roty );
    stransf = rx*ry; // set the scene transformation matrix

    // Define our projection transformation:
    // (see demo program in gltutors-projection.7z, we are replicating the same behavior here)
    GsMat camview, persp, sproj;

    GsVec eye(0,0,2), center(0,0,0), up(0,1,0);
    camview.lookat ( eye, center, up ); // set our 4x4 "camera" matrix

    float aspect=static_cast<float>(_w) / static_cast<float>(_h), znear=0.1f, zfar=500.0f;
    persp.perspective ( _fovy, aspect, znear, zfar ); // set our 4x4 perspective matrix

    // Our matrices are in "line-major" format, so vertices should be multiplied on the 
    // right side of a matrix multiplication, therefore in the expression below camview will
    // affect the vertex before persp, because v' = (persp*camview)*v = (persp)*(camview*v).
    sproj = persp * camview; // set final scene projection

    //  Note however that when the shader receives a matrix it will store it in column-major 
    //  format, what will cause our values to be transposed, and we will then have in our 
    //  shaders vectors on the left side of a multiplication to a matrix.

    // Draw the axes
    if ( _viewaxis )
    {
        _axis.draw ( stransf, sproj );
    }
    
    // Transform matrices
    GsMat transform;

    // Draw the border
    GsMat borderTranslation;
    borderTranslation.translation(0.0, 0.5, 0.0);
    transform = stransf * borderTranslation;
    _border.draw(transform, sproj, GsColor::white);
    
    GsMat derp;
    derp.translation(0.0f, 0.5f, 0.0f);

    // Compute the sub sections transformations
    GsMat subsecondsRot, subsecondsTranslation;
    subsecondsRot.rotz(subsecondsRotation);
    subsecondsTranslation.translation(0.0f, 0.15f, 0.0f);
    transform = stransf * derp * subsecondsRot * subsecondsTranslation;
    _subseconds.draw(transform, sproj, GsColor::white);
    
    // Compute the sub sections transformations
    GsMat secondsRot, secondsTranslation;
    secondsRot.rotz(secondsRotation);
    secondsTranslation.translation(0.0f, 0.2125f, 0.0f);
    transform = stransf * derp * secondsRot * secondsTranslation;
    _seconds.draw(transform, sproj, GsColor::white);

    // Draw the shadow  stuff
    if(lightEnabled)
    {
        // Draw an indicator of the lights position
        transform.translation(lightPosition);
        transform = stransf * transform;
        lightIndicator.draw(transform, sproj, GsColor::yellow);

        // Compute the shadow projection matrix
        GsMat shadowMatrix;
        float ground[4] = {0, 1, 0, 0};
        
        ComputeShadowMatrixDirectionalLight(shadowMatrix, lightPosition, &ground[0]);
        //ComputeShadowMatrixGroundPointLight(shadowMatrix, lightPosition);
        
        transform = stransf * shadowMatrix * borderTranslation;
        _border.draw(transform, sproj, GsColor::cyan);
        
        transform = stransf * shadowMatrix * derp * subsecondsRot * subsecondsTranslation;
        _subseconds.draw(transform, sproj, GsColor::cyan);

        transform = stransf * shadowMatrix * derp * secondsRot * secondsTranslation;
        _seconds.draw(transform, sproj, GsColor::cyan);
    }
    
    // Swap buffers and draw:
    glFlush();         // flush the pipeline (usually not necessary)
    glutSwapBuffers(); // we were drawing to the back buffer, now bring it to the front
}
// here we will redraw the scene according to the current state of the application.
void AppWindow::glutDisplay ()
 {
   // Clear the rendering window
   glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

   // Build a cross with some lines (if not built yet):
   if ( _axis.changed ) // needs update
    { _axis.build(1.0f); // axis has radius 1.0
    }
   if (sunanim) {
	   sunx = 2 * (cos(2 * M_PI*sunxc / 360) + sin(2 * M_PI*sunxc / 360)); suny = 20.0f; sunz = 2 * (-sin(2 * M_PI*sunxz / 360) + cos(2 * M_PI*sunxz / 360));
   }
   else {
	   sunx = 0.0; suny = 1; sunz = -.5;
   }

   // Define our scene transformation:
   GsMat rx, ry, stransf, barrelroll, leftright, transf, updown, rightwing, leftwing, offsety, centerrwing, centerlwing, rl, rr, backR, backL, centerbackl, centerbackr, br, bl;
   GsMat rfrot, lfrot, rbrot, lbrot, rollyawpitch, ShadowT;
   rx.rotx ( _rotx );
   ry.roty ( _roty );
   stransf = rx*ry; // set the scene transformation matrix

   offsety.translation(GsVec(0.0f, -5.7f, 0.0f));

   //Rotate many degrees
   barrelroll.rotz(2 * M_PI * rotate / 360);
   leftright.roty(2 * M_PI * _turnlr / 360);
   updown.rotx(2 * M_PI * _turnud / 360);

   rollyawpitch = leftright*updown*barrelroll;

   //Translate front wings to center
   centerrwing.translation(GsVec(-0.1f,-0.15f,0.0f)); centerlwing.translation(GsVec(0.1f, -0.15f, 0.0f));
   //Translate front wings back to airplane
   rr.translation(GsVec(0.1f, 0.15f, 0.0f)); rl.translation(GsVec(-0.1f, 0.15f, 0.0f));
   //Translate back wings to center
   centerbackl.translation(GsVec(-0.05f, -0.2f, 0.0f)); centerbackr.translation(GsVec(0.05f, -0.2f, 0.0f));
   //Translate back wings to airplane
   bl.translation(GsVec(0.05f, 0.2f, 0.0f)); br.translation(GsVec(-0.05f, 0.2f, 0.0f));
   //Rotate front wings
   rightwing.rotz(2 * M_PI * _wingsflyR / 360); leftwing.rotz(2 * M_PI * -_wingsflyL / 360);
   //Rotate back wings
   backR.rotz(2 * M_PI * _backR / 360); backL.rotz(2 * M_PI * -_backL / 360);
   //Clean up draw function
   rfrot = rr*rightwing*centerrwing;
   lfrot = rl*leftwing*centerlwing;
   rbrot = br*backR*centerbackr;
   lbrot = bl*backL*centerbackl;

	//speed is fast
	GsVec P = GsVec(0.0f, 0.0f, speed);
	GsVec bd = leftright*updown*barrelroll*P;
	R = R + bd;
	transf.setrans(R);

	GsVec sbd = leftright*P;
	SR = SR + sbd;
	ShadowT.setrans(SR);

   // Define our projection transformation:
   // (see demo program in gltutors-projection.7z, we are replicating the same behavior here)
   GsMat camview, camview2, _birdseye, persp, sproj;

   GsVec eye(0,0,0), center(0,0,0), up(0,1,0);
   GsVec eye2(0, 10, 0), center2(0, 0, 0), up2(0, 0, 1);
   eye += R + leftright*updown*barrelroll*GsVec(0,0,2);
   center += R + GsVec(0, 0, 0);

   _sun.build(1.0f, sunx, suny, sunz);
   float ground[4] = { 0, 1, 0, 4.99 };
   float light[4] = { sunx, suny, sunz, 0 };
   float  dot;
   GsMat shadowMat;

   dot = ground[0] * light[0] +
	   ground[1] * light[1] +
	   ground[2] * light[2] +
	   ground[3] * light[3];
    
   shadowMat.setl1(dot - light[0] * ground[0], 0.0 - light[0] * ground[1], 0.0 - light[0] * ground[2], 0.0 - light[0] * ground[3]);
   shadowMat.setl2(0.0 - light[1] * ground[0], dot - light[1] * ground[1], 0.0 - light[1] * ground[2], 0.0 - light[1] * ground[3]);
   shadowMat.setl3(0.0 - light[2] * ground[0], 0.0 - light[2] * ground[1], dot - light[2] * ground[2], 0.0 - light[2] * ground[3]);
   shadowMat.setl4(0.0 - light[3] * ground[0], 0.0 - light[3] * ground[1], 0.0 - light[3] * ground[2], dot - light[3] * ground[3]);
   
   //shadowMat = shadowMat*ry*rx;
   camview.lookat ( eye, center, up ); // set our 4x4 "camera" matrix
   camview2.lookat(eye2, center2, up2);

   float aspect=1.0f, znear=0.1f, zfar=5000.0f;
   persp.perspective ( _fovy, aspect, znear, zfar ); // set our 4x4 perspective matrix

   // Our matrices are in "line-major" format, so vertices should be multiplied on the 
   // right side of a matrix multiplication, therefore in the expression below camview will
   // affect the vertex before persp, because v' = (persp*camview)*v = (persp)*(camview*v).
   if (camera) {
	   sproj = persp * camview; // set final scene projection
   }
   else {
	   sproj = persp * camview2;
   }

   //  Note however that when the shader receives a matrix it will store it in column-major 
   //  format, what will cause our values to be transposed, and we will then have in our 
   //  shaders vectors on the left side of a multiplication to a matrix.
   float col = 1;
   // Draw:
   //if ( _viewaxis ) _axis.draw ( stransf, sproj );
	_model.draw(stransf*transf*rollyawpitch, sproj, _light, 0);
	_model2.draw(stransf*transf*rollyawpitch*rfrot, sproj, _light, 0);
	_model3.draw(stransf*transf*rollyawpitch*lfrot, sproj, _light, 0);
	_model4.draw(stransf*transf*rollyawpitch, sproj, _light, 0);
	_model5.draw(stransf*transf*rollyawpitch*rbrot, sproj, _light, 0);
	_model6.draw(stransf*transf*rollyawpitch*lbrot, sproj, _light, 0);
	_floor.draw(stransf, sproj, _light, textures);
	_city.draw(stransf*offsety, sproj, _light, 0);
	_city.draw(stransf*shadowMat*offsety, sproj, _shadow, 0);
	//Shadow
	_model.draw(stransf*ShadowT*shadowMat*rollyawpitch, sproj, _shadow, 1);
	_model2.draw(stransf*ShadowT*shadowMat*rollyawpitch, sproj, _shadow, 1);
	_model3.draw(stransf*ShadowT*shadowMat*rollyawpitch, sproj, _shadow, 1);
	_model4.draw(stransf*ShadowT*shadowMat*rollyawpitch, sproj, _shadow, 1);
	_model5.draw(stransf*ShadowT*shadowMat*rollyawpitch, sproj, _shadow, 1);
	_model6.draw(stransf*ShadowT*shadowMat*rollyawpitch, sproj, _shadow, 1);
	_side.draw(stransf, sproj, _light, col, textures);
	_sun.draw(stransf, sproj);


   // Swap buffers and draw:
   glFlush();         // flush the pipeline (usually not necessary)
   glutSwapBuffers(); // we were drawing to the back buffer, now bring it to the front
}