Пример #1
0
void Transform::flush()
{
    if (m_needFlush)
    {
        m_needFlush=false;
        kmMat4Identity(&m_matrix);
        kmMat4 t_mat;
        
        //position
        kmMat4Identity(&t_mat);
        kmMat4Translation(&t_mat,m_x,m_y,0);
        kmMat4Multiply(&m_matrix, &m_matrix, &t_mat);
        
        //rotation
        kmMat4Identity(&t_mat);
        kmMat4RotationZ(&t_mat, m_rotationZ*PI/180.0f);
        kmMat4Multiply(&m_matrix, &m_matrix, &t_mat);
        
        //scale
        kmMat4Identity(&t_mat);
        kmMat4Scaling(&t_mat, m_scaleX, m_scaleY, 1);
        kmMat4Multiply(&m_matrix, &m_matrix, &t_mat);
        
        //anchorPoint
        kmMat4Identity(&t_mat);
        kmMat4Translation(&t_mat,(-m_anchorX*m_width),(-m_anchorY*m_height),0);
        kmMat4Multiply(&m_matrix, &m_matrix, &t_mat);
        
    }
}
Пример #2
0
void glPrintf(float x, float y, const char *fmt, ...)
{
    char text[256];
    va_list ap;
    va_start(ap, fmt);
    vsprintf(text, fmt, ap);
    va_end(ap);

    glUseProgram(__glp.printProg);
    kmMat4Assign(&__glp.otm, &__glp.opm);
    kmMat4Translation(&__glp.t, x, y, -1);
    kmMat4Multiply(&__glp.otm, &__glp.otm, &__glp.t);

    glEnable(GL_BLEND);
    glDisable(GL_DEPTH_TEST);

    glBindTexture(GL_TEXTURE_2D, __glp.fonttex);

    glEnableVertexAttribArray(__glp.vert_attrib);
    glBindBuffer(GL_ARRAY_BUFFER, __glp.quadvbo);
    glVertexAttribPointer(__glp.vert_attrib, 3, GL_FLOAT, GL_FALSE, 0, 0);

    glEnableVertexAttribArray(__glp.uv_attrib);
    glBindBuffer(GL_ARRAY_BUFFER, __glp.texvbo);
    glVertexAttribPointer(__glp.uv_attrib, 2, GL_FLOAT, GL_FALSE, 0, 0);

    glUniform1i(__glp.texture_uniform, 0);

    for (int n = 0; n < strlen(text); n++) {

        int c = (int)text[n];
        float cx = c % 16;
        float cy = (int)(c / 16.0);
        cy = cy * (1. / 16);
        cx = cx * (1. / 16);

        glUniformMatrix4fv(__glp.opm_uniform, 1, GL_FALSE, (GLfloat *) & __glp.otm);
        glUniform1f(__glp.cx_uniform, cx);
        glUniform1f(__glp.cy_uniform, cy);

        glDrawArrays(GL_TRIANGLES, 0, 6);

        kmMat4Translation(&__glp.t, 16, 0, 0);
        kmMat4Multiply(&__glp.otm, &__glp.otm, &__glp.t);
    }

    glDisable(GL_BLEND);
    glEnable(GL_DEPTH_TEST);
    glDisableVertexAttribArray(__glp.uv_attrib);
    glDisableVertexAttribArray(__glp.vert_attrib);

}
Пример #3
0
static void dlUpdateMatrix( dlObject *object )
{
   kmMat4 translation,
          rotation,
          scale,
          temp;

   CALL("%p", object);

   /* translation */
   kmMat4Translation( &translation,
                      object->translation.x,
                      object->translation.y,
                      object->translation.z  );

   /* rotation */
   kmMat4RotationX( &rotation, kmDegreesToRadians(object->rotation.x) );
   kmMat4Multiply(  &rotation, &rotation,
                    kmMat4RotationY( &temp, kmDegreesToRadians(object->rotation.y) ) );
   kmMat4Multiply(  &rotation, &rotation,
                    kmMat4RotationZ( &temp, kmDegreesToRadians(object->rotation.z) ) );

   /* scale */
   kmMat4Scaling( &scale,
                  object->scale.x,
                  object->scale.y,
                  object->scale.z  );

   /* build matrix */
   kmMat4Multiply( &translation, &translation, &rotation );
   kmMat4Multiply( &object->matrix, &translation, &scale );
   object->transform_changed = 0;
}
Пример #4
0
/* \brief transform V3B object */
static void _glhckSkinBoneTransformObjectV3B(glhckObject *object)
{
   unsigned int i, w;
   kmMat4 bias, biasinv, scale, scaleinv;
   static glhckVector3b zero = {0,0,0};

   kmMat4Translation(&bias, object->geometry->bias.x, object->geometry->bias.y, object->geometry->bias.z);
   kmMat4Scaling(&scale, object->geometry->scale.x, object->geometry->scale.y, object->geometry->scale.z);
   kmMat4Inverse(&biasinv, &bias);
   kmMat4Inverse(&scaleinv, &scale);

   for (i = 0; i != object->numSkinBones; ++i) {
      glhckSkinBone *skinBone = object->skinBones[i];
      for (w = 0; w != skinBone->numWeights; ++w) {
         glhckVertexWeight *weight = &skinBone->weights[w];

         if (weight->vertexIndex >= (glhckIndexi)object->geometry->vertexCount)
            continue;

         memcpy(&object->geometry->vertices.v3b[weight->vertexIndex].vertex, &zero, sizeof(glhckVector3s));
         memcpy(&object->geometry->vertices.v3b[weight->vertexIndex].normal, &zero, sizeof(glhckVector3s));
      }
   }

   for (i = 0; i != object->numSkinBones; ++i) {
      kmMat3 transformedNormal;
      kmMat4 transformedVertex, transformedMatrix, offsetMatrix;
      glhckSkinBone *skinBone = object->skinBones[i];
      if (!skinBone->bone) continue;

      kmMat4Multiply(&transformedMatrix, &biasinv, &skinBone->bone->transformedMatrix);
      kmMat4Multiply(&transformedMatrix, &scaleinv, &transformedMatrix);
      kmMat4Multiply(&offsetMatrix, &skinBone->offsetMatrix, &bias);
      kmMat4Multiply(&offsetMatrix, &offsetMatrix, &scale);
      kmMat4Multiply(&transformedVertex, &transformedMatrix, &offsetMatrix);
      kmMat3AssignMat4(&transformedNormal, &transformedVertex);

      for (w = 0; w != skinBone->numWeights; ++w) {
         glhckVector3f bindVertex, bindNormal;
         glhckVertexWeight *weight = &skinBone->weights[w];

         if (weight->vertexIndex >= (glhckIndexi)object->geometry->vertexCount)
            continue;

         glhckSetV3(&bindVertex, &object->bindGeometry->vertices.v3b[weight->vertexIndex].vertex);
         glhckSetV3(&bindNormal, &object->bindGeometry->vertices.v3b[weight->vertexIndex].normal);
         kmVec3MultiplyMat4((kmVec3*)&bindVertex, (kmVec3*)&bindVertex, &transformedVertex);
         kmVec3MultiplyMat3((kmVec3*)&bindNormal, (kmVec3*)&bindNormal, &transformedNormal);

         object->geometry->vertices.v3b[weight->vertexIndex].vertex.x += bindVertex.x * weight->weight;
         object->geometry->vertices.v3b[weight->vertexIndex].vertex.y += bindVertex.y * weight->weight;
         object->geometry->vertices.v3b[weight->vertexIndex].vertex.z += bindVertex.z * weight->weight;
         object->geometry->vertices.v3b[weight->vertexIndex].normal.x += bindNormal.x * weight->weight;
         object->geometry->vertices.v3b[weight->vertexIndex].normal.y += bindNormal.y * weight->weight;
         object->geometry->vertices.v3b[weight->vertexIndex].normal.z += bindNormal.z * weight->weight;
      }
   }
}
void kmGLTranslatef(float x, float y, float z)
{
	kmMat4 translation;

	//Create a rotation matrix using the axis and the angle
	kmMat4Translation(&translation,x,y,z);

	//Multiply the rotation matrix by the current matrix
	kmMat4Multiply(current_stack->top, current_stack->top, &translation);
}
Пример #6
0
bool BaseRenderer::pre_visit(Object& obj) {
    modelview().push();

    kmMat4 trans;
    kmMat4Identity(&trans);
    kmMat4Translation(&trans, obj.absolute_position().x, obj.absolute_position().y, obj.absolute_position().z);
    kmMat4Multiply(&modelview().top(), &modelview().top(), &trans);

    return true;
}
Пример #7
0
uint8_t lite3d_scene_node_update(lite3d_scene_node *node)
{
    uint8_t updated = LITE3D_FALSE;
    SDL_assert(node);

    if (node->recalc)
    {
        kmMat4 transMat;
        kmMat4 scaleMat;
        kmQuaternionNormalize(&node->rotation,
            &node->rotation);

        kmMat4RotationQuaternion(&node->localView, &node->rotation);
        kmMat4Translation(&transMat,
            node->isCamera ? -node->position.x : node->position.x,
            node->isCamera ? -node->position.y : node->position.y,
            node->isCamera ? -node->position.z : node->position.z);

        if (node->scale.x != 1.0f ||
            node->scale.y != 1.0f ||
            node->scale.z != 1.0f)
        {
            kmMat4Scaling(&scaleMat, node->scale.x,
                node->scale.y,
                node->scale.z);

            kmMat4Multiply(&transMat, &transMat, &scaleMat);
        }

        if (node->rotationCentered)
            kmMat4Multiply(&node->localView,
            &transMat, &node->localView);
        else
            kmMat4Multiply(&node->localView,
            &node->localView, &transMat);

        if (node->baseNode)
        {
            kmMat4Multiply(&node->worldView,
                &node->baseNode->worldView, &node->localView);
        }
        else
        {
            node->worldView = node->localView;
        }
        
        kmMat3NormalMatrix(&node->normalModel, &node->worldView);

        node->recalc = LITE3D_FALSE;
        node->invalidated = LITE3D_TRUE;
        updated = LITE3D_TRUE;
    }

    return updated;
}
Пример #8
0
void kmGLTranslatef(float x, float y, float z)
{
    km_mat4_stack_context *current_context = (km_mat4_stack_context *)pthread_getspecific(current_context_key);

	kmMat4 translation;

	/*Create a rotation matrix using the axis and the angle*/
	kmMat4Translation(&translation,x,y,z);

	/*Multiply the rotation matrix by the current matrix*/
	kmMat4Multiply(current_context->current_stack->top, current_context->current_stack->top, &translation);
}
Пример #9
0
void drawSprite(float x, float y, float w, float h, float a, int tex)
{


    glUseProgram(__spr.spriteProg);
    kmMat4Assign(&__spr.otm, &__spr.opm);
    kmMat4Translation(&__spr.t, x, y, -1); // support z layers?
    kmMat4RotationZ(&__spr.r,a);
    kmMat4Multiply(&__spr.t,&__spr.t,&__spr.r);
    kmMat4Multiply(&__spr.otm, &__spr.otm, &__spr.t);

    glEnable(GL_BLEND);
    glDisable(GL_DEPTH_TEST);

    glBindTexture(GL_TEXTURE_2D, tex);

    glEnableVertexAttribArray(__spr.vert_attrib);
    glBindBuffer(GL_ARRAY_BUFFER, __spr.quadvbo);
    glVertexAttribPointer(__spr.vert_attrib, 3, GL_FLOAT, GL_FALSE, 0, 0);

    glEnableVertexAttribArray(__spr.uv_attrib);
    glBindBuffer(GL_ARRAY_BUFFER, __spr.texvbo);
    glVertexAttribPointer(__spr.uv_attrib, 2, GL_FLOAT, GL_FALSE, 0, 0);

    glUniform1i(__spr.texture_uniform, 0);
    glUniform2f(__spr.u_size, w,h);


    glUniformMatrix4fv(__spr.opm_uniform, 1, GL_FALSE, (GLfloat *) & __spr.otm);

    glDrawArrays(GL_TRIANGLES, 0, 6);


    glDisable(GL_BLEND);
    glEnable(GL_DEPTH_TEST);
    glDisableVertexAttribArray(__glp.uv_attrib);
    glDisableVertexAttribArray(__glp.vert_attrib);

}
Пример #10
0
/**
 * Builds a translation matrix in the same way as gluLookAt()
 * the resulting matrix is stored in pOut. pOut is returned.
 */
kmMat4* const kmMat4LookAt(kmMat4* pOut, const kmVec3* pEye,
                     const kmVec3* pCenter, const kmVec3* pUp)
{
    kmVec3 f, up, s, u;
    kmMat4 translate;

    kmVec3Subtract(&f, pCenter, pEye);
    kmVec3Normalize(&f, &f);

    kmVec3Assign(&up, pUp);
    kmVec3Normalize(&up, &up);

    kmVec3Cross(&s, &f, &up);
    kmVec3Normalize(&s, &s);

    kmVec3Cross(&u, &s, &f);
    kmVec3Normalize(&s, &s);

    kmMat4Identity(pOut);

    pOut->mat[0] = s.x;
    pOut->mat[4] = s.y;
    pOut->mat[8] = s.z;

    pOut->mat[1] = u.x;
    pOut->mat[5] = u.y;
    pOut->mat[9] = u.z;

    pOut->mat[2] = -f.x;
    pOut->mat[6] = -f.y;
    pOut->mat[10] = -f.z;

    kmMat4Translation(&translate, -pEye->x, -pEye->y, -pEye->z);
    kmMat4Multiply(pOut, pOut, &translate);

    return pOut;
}
Пример #11
0
int main()
{

    lightDir.x=0.5;
    lightDir.y=.7;
    lightDir.z=-0.5;
    kmVec3Normalize(&lightDir,&lightDir);

    // creates a window and GLES context
    // create a window and GLES context
	if (!glfwInit())
		exit(EXIT_FAILURE);

	window = glfwCreateWindow(width, height, "I N V A D E R S ! ! !", NULL, NULL);
	if (!window) {
		glfwTerminate();
		exit(EXIT_FAILURE);
	}
	glfwSetWindowSizeCallback(window,window_size_callback);	
	glfwMakeContextCurrent(window);



    // all the shaders have at least texture unit 0 active so
    // activate it now and leave it active
    glActiveTexture(GL_TEXTURE0);

    // The obj shapes and their textures are loaded
    cubeTex = loadPNG("resources/textures/dice.png");
    loadObj(&cubeObj, "resources/models/cube.gbo",
            "resources/shaders/textured.vert", "resources/shaders/textured.frag");


    shipTex = loadPNG("resources/textures/shipv2.png");
    loadObjCopyShader(&shipObj,"resources/models/ship.gbo",&cubeObj);

    alienTex = loadPNG("resources/textures/alien.png");
    loadObjCopyShader(&alienObj, "resources/models/alien.gbo", &cubeObj);

    shotTex = loadPNG("resources/textures/shot.png");
    loadObjCopyShader(&shotObj, "resources/models/shot.gbo", &cubeObj);

    expTex = loadPNG("resources/textures/explosion.png");


    playerPos.x = 0;
    playerPos.y = 0;
    playerPos.z = 0;

    kmMat4Identity(&view);

    pEye.x = 0;
    pEye.y = 2;
    pEye.z = 4;
    pCenter.x = 0;
    pCenter.y = 0;
    pCenter.z = -5;
    pUp.x = 0;
    pUp.y = 1;
    pUp.z = 0;

    kmMat4LookAt(&view, &pEye, &pCenter, &pUp);

    // projection matrix, as distance increases
    // the way the model is drawn is effected
    kmMat4Identity(&projection);
    kmMat4PerspectiveProjection(&projection, 45,
                                (float)width/ height, 0.1, 1000);

    glViewport(0, 0, width,height);

    // these two matrices are pre combined for use with each model render
    kmMat4Assign(&vp, &projection);
    kmMat4Multiply(&vp, &vp, &view);

    // initialises glprint's matrix shader and texture
    initGlPrint(width,height);

	font1=createFont("resources/textures/font.png",0,256,16,16,16);
	font2=createFont("resources/textures/bigfont.png",32,512,9.5,32,48);

    glCullFace(GL_BACK);
    glEnable(GL_CULL_FACE);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glDisable(GL_BLEND);	// only used by glprintf
    glEnable(GL_DEPTH_TEST);


    int num_frames = 0;

    bool quit = false;

    resetAliens();

    for (int n = 0; n < MAX_PLAYER_SHOTS; n++) {
        playerShots[n].alive = false;
    }


    initPointClouds("resources/shaders/particle.vert",
                    "resources/shaders/particle.frag",(float)width/24.0);



    for (int n = 0; n < MAX_ALIENS; n++) {
        aliens[n].explosion=createPointCloud(40);
        resetExposion(aliens[n].explosion); // sets initials positions
    }

	glClearColor(0, .5, 1, 1);

    while (!quit) {		// the main loop

        clock_gettime(0,&ts);  // note the time BEFORE we start to render the current frame
		glfwPollEvents();


        if (glfwGetKey(window,GLFW_KEY_ESCAPE)==GLFW_PRESS || glfwWindowShouldClose(window))
            quit = true;

        float rad;		// radians rotation based on frame counter

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        frame++;
        rad = frame * (0.0175f * 2);

        //kmMat4Identity(&model);
        kmMat4Translation(&model, playerPos.x, playerPos.y, playerPos.z);
        playerCroll +=
            (PIDcal(playerRoll, playerCroll, &playerPre_error, &playerIntegral)
             / 2);
//        kmMat4RotationPitchYawRoll(&model, 0, 3.1416, playerCroll * 3);	//
		kmMat4RotationYawPitchRoll(&rot,0,3.1416,-playerCroll*3);
        kmMat4Multiply(&model, &model, &rot);
        
        kmMat4Assign(&mvp, &vp);
        kmMat4Multiply(&mvp, &mvp, &model);

        kmMat4Assign(&mv, &view);
        kmMat4Multiply(&mv, &mv, &model);

        glBindTexture(GL_TEXTURE_2D, shipTex);
        drawObj(&shipObj, &mvp, &mv, lightDir, viewDir);

        glPrintf(50 + sinf(rad) * 16, 240 + cosf(rad) * 16,
                 font2,"frame=%i", frame);

        kmVec3 tmp;

        playerFireCount--;

        if (glfwGetKey(window,GLFW_KEY_LEFT_CONTROL)==GLFW_PRESS && playerFireCount < 0) {

            struct playerShot_t *freeShot;
            freeShot = getFreeShot();
            if (freeShot != 0) {
                playerFireCount = 15;
                freeShot->alive = true;
                kmVec3Assign(&freeShot->pos, &playerPos);
            }
        }

        for (int n = 0; n < MAX_PLAYER_SHOTS; n++) {
            if (playerShots[n].alive) {
                playerShots[n].pos.z -= .08;
                if (playerShots[n].pos.z < -10)
                    playerShots[n].alive = false;

                //kmMat4Identity(&model);
                kmMat4Translation(&model, playerShots[n].pos.x,
                                  playerShots[n].pos.y,
                                  playerShots[n].pos.z);
                //kmMat4RotationPitchYawRoll(&model, rad * 4, 0,
                //                           -rad * 4);
				kmMat4RotationYawPitchRoll(&rot,rad*4,0,-rad*4);
				kmMat4Multiply(&model,&model,&rot);
                kmMat4Assign(&mvp, &vp);
                kmMat4Multiply(&mvp, &mvp, &model);

                kmMat4Assign(&mv, &view);
                kmMat4Multiply(&mv, &mv, &model);

                glBindTexture(GL_TEXTURE_2D, shotTex);
                drawObj(&shotObj, &mvp, &mv, lightDir, viewDir);
            }
        }

        playerRoll = 0;
        if (glfwGetKey(window,GLFW_KEY_LEFT)==GLFW_PRESS && playerPos.x > -10) {
            playerPos.x -= 0.1;
            playerRoll = .2;
        }
        if (glfwGetKey(window,GLFW_KEY_RIGHT)==GLFW_PRESS && playerPos.x < 10) {
            playerPos.x += 0.1;
            playerRoll = -.2;
        }
        pEye.x = playerPos.x * 1.25;

        pCenter.x = playerPos.x;
        pCenter.y = playerPos.y + 1;
        pCenter.z = playerPos.z;

        int deadAliens;

        deadAliens = 0;

        for (int n = 0; n < MAX_ALIENS; n++) {
            if (aliens[n].alive == true) {

                //kmMat4Identity(&model);
                kmMat4Translation(&model, aliens[n].pos.x,
                                  aliens[n].pos.y, aliens[n].pos.z);
                //kmMat4RotationPitchYawRoll(&model, -.4, 0, 0);
				kmMat4RotationYawPitchRoll(&rot,.2,0,0);
				kmMat4Multiply(&model,&model,&rot);

                kmMat4Assign(&mvp, &vp);
                kmMat4Multiply(&mvp, &mvp, &model);

                kmMat4Assign(&mv, &view);
                kmMat4Multiply(&mv, &mv, &model);

                glBindTexture(GL_TEXTURE_2D, alienTex);
                drawObj(&alienObj, &mvp, &mv, lightDir, viewDir);

                kmVec3 d;
                for (int i = 0; i < MAX_PLAYER_SHOTS; i++) {
                    kmVec3Subtract(&d, &aliens[n].pos,
                                   &playerShots[i].pos);
                    if (kmVec3Length(&d) < .7
                            && playerShots[i].alive) {
                        aliens[n].alive = false;
                        playerShots[i].alive = false;
                        aliens[n].exploding = true;
                        resetExposion(aliens[n].explosion);
                    }
                }
            } 

            if (aliens[n].alive != true && aliens[n].exploding != true) {
                    deadAliens++;
                
            }
        }

        if (deadAliens == MAX_ALIENS) {
            resetAliens();
        }

		// draw explosions after ALL aliens
        for (int n = 0; n < MAX_ALIENS; n++) {
			if (aliens[n].exploding==true) {
				kmMat4Identity(&model);
				kmMat4Translation(&model, aliens[n].pos.x,
								  aliens[n].pos.y, aliens[n].pos.z);

				kmMat4Assign(&mvp, &vp);
				kmMat4Multiply(&mvp, &mvp, &model);
				glBindTexture(GL_TEXTURE_2D, expTex);
				drawPointCloud(aliens[n].explosion, &mvp);
				aliens[n].explosion->tick=aliens[n].explosion->tick+0.05;
				if (aliens[n].explosion->tick>1.25) {
					aliens[n].exploding=false;                   	
				} else {
					// update the explosion
					
					for (int i=0; i<aliens[n].explosion->totalPoints; i++) {
				
						float t;
						t=aliens[n].explosion->tick;
						if (i>aliens[n].explosion->totalPoints/2) t=t/2.0;
						aliens[n].explosion->pos[i*3]=aliens[n].explosion->vel[i*3] * t;
						aliens[n].explosion->pos[i*3+1]=aliens[n].explosion->vel[i*3+1] * t;
						aliens[n].explosion->pos[i*3+2]=aliens[n].explosion->vel[i*3+2] * t;
				
					}
				}
			}
		}

        // move camera
        kmMat4LookAt(&view, &pEye, &pCenter, &pUp);

        kmMat4Assign(&vp, &projection);
        kmMat4Multiply(&vp, &vp, &view);

        kmVec3Subtract(&viewDir,&pEye,&pCenter);
        kmVec3Normalize(&viewDir,&viewDir);

        // dump values
        glPrintf(100, 280, font1,"eye    %3.2f %3.2f %3.2f ", pEye.x, pEye.y, pEye.z);
        glPrintf(100, 296, font1,"centre %3.2f %3.2f %3.2f ", pCenter.x, pCenter.y,
                 pCenter.z);
        glPrintf(100, 340, font1,"frame %i %i ", frame, frame % 20);



        glfwSwapBuffers(window);

        ts.tv_nsec+=20000000;  // 1000000000 / 50 = 50hz less time to render the frame
        //thrd_sleep(&ts,NULL); // tinycthread
        usleep(20000); // while I work out why tinycthread that was working isnt.... :/

    }

	glfwDestroyWindow(window);
	glfwTerminate();

    return 0;
}
Пример #12
0
int main()
{




    lightDir.x=0.5;
    lightDir.y=.7;
    lightDir.z=-0.5;
    kmVec3Normalize(&lightDir,&lightDir);

    // creates a window and GLES context
    if (makeContext() != 0)
        exit(-1);

    // all the shaders have at least texture unit 0 active so
    // activate it now and leave it active
    glActiveTexture(GL_TEXTURE0);

    // The obj shapes and their textures are loaded
    cubeTex = loadPNG("resources/textures/dice.png");
    loadObj(&cubeObj, "resources/models/cube.gbo",
            "resources/shaders/textured.vert", "resources/shaders/textured.frag");


    shipTex = loadPNG("resources/textures/shipv2.png");
    loadObjCopyShader(&shipObj,"resources/models/ship.gbo",&cubeObj);

    alienTex = loadPNG("resources/textures/alien.png");
    loadObjCopyShader(&alienObj, "resources/models/alien.gbo", &cubeObj);

    shotTex = loadPNG("resources/textures/shot.png");
    loadObjCopyShader(&shotObj, "resources/models/shot.gbo", &cubeObj);

    expTex = loadPNG("resources/textures/explosion.png");





    playerPos.x = 0;
    playerPos.y = 0;
    playerPos.z = 0;

    kmMat4Identity(&view);

    pEye.x = 0;
    pEye.y = 2;
    pEye.z = 4;
    pCenter.x = 0;
    pCenter.y = 0;
    pCenter.z = -5;
    pUp.x = 0;
    pUp.y = 1;
    pUp.z = 0;

    kmMat4LookAt(&view, &pEye, &pCenter, &pUp);

    // projection matrix, as distance increases
    // the way the model is drawn is effected
    kmMat4Identity(&projection);
    kmMat4PerspectiveProjection(&projection, 45,
                                (float)getDisplayWidth() / getDisplayHeight(), 0.1, 100);

    glViewport(0, 0, getDisplayWidth(), getDisplayHeight());

    // these two matrices are pre combined for use with each model render
    kmMat4Assign(&vp, &projection);
    kmMat4Multiply(&vp, &vp, &view);

    // initialises glprint's matrix shader and texture
    initGlPrint(getDisplayWidth(), getDisplayHeight());

	font1=createFont("resources/textures/font.png",0,256,16,16,16);
	font2=createFont("resources/textures/bigfont.png",32,512,9.5,32,48);

    glCullFace(GL_BACK);
    glEnable(GL_CULL_FACE);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glDisable(GL_BLEND);	// only used by glprintf
    glEnable(GL_DEPTH_TEST);

    struct timeval t, ta, t1, t2;	// fps stuff
    gettimeofday(&t1, NULL);
    int num_frames = 0;

    bool quit = false;

    mouse = getMouse();
    keys = getKeys();

    resetAliens();

    for (int n = 0; n < MAX_PLAYER_SHOTS; n++) {
        playerShots[n].alive = false;
    }


    initPointClouds("resources/shaders/particle.vert",
                    "resources/shaders/particle.frag",(float)getDisplayWidth()/24.0);


    for (int n = 0; n < MAX_ALIENS; n++) {
        aliens[n].explosion=createPointCloud(40);
        resetExposion(aliens[n].explosion); // sets initials positions
    }



    while (!quit) {		// the main loop

        doEvents();	// update mouse and key arrays

        // mask of 4 is right mouse
        if (keys[KEY_ESC])
            quit = true;

        glClearColor(0, .5, 1, 1);

        // render between two gettimeofday calls so
        // we can sleep long enough to roughly sync
        // to ~60fps but not on the pi!

        // TODO find something a tad more elegent

        long i;
        gettimeofday(&t, NULL);
        i = t.tv_sec * 1e6 + t.tv_usec;

//        render();
        float rad;		// radians rotation based on frame counter

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        frame++;
        rad = frame * (0.0175f * 2);

        kmMat4Identity(&model);
        kmMat4Translation(&model, playerPos.x, playerPos.y, playerPos.z);

        playerCroll +=
            (PIDcal(playerRoll, playerCroll, &playerPre_error, &playerIntegral)
             / 2);
        kmMat4RotationPitchYawRoll(&model, 0, 3.1416, playerCroll * 3);	//

        kmMat4Assign(&mvp, &vp);
        kmMat4Multiply(&mvp, &mvp, &model);

        kmMat4Assign(&mv, &view);
        kmMat4Multiply(&mv, &mv, &model);

        glBindTexture(GL_TEXTURE_2D, shipTex);
        drawObj(&shipObj, &mvp, &mv, lightDir, viewDir);

        glPrintf(50 + sinf(rad) * 16, 240 + cosf(rad) * 16,
                 font2,"frame=%i fps=%3.2f", frame, lfps);

        kmVec3 tmp;

        playerFireCount--;

        if (keys[KEY_LCTRL] && playerFireCount < 0) {

            struct playerShot_t *freeShot;
            freeShot = getFreeShot();
            if (freeShot != 0) {
                playerFireCount = 15;
                freeShot->alive = true;
                kmVec3Assign(&freeShot->pos, &playerPos);
            }
        }

        for (int n = 0; n < MAX_PLAYER_SHOTS; n++) {
            if (playerShots[n].alive) {
                playerShots[n].pos.z -= .08;
                if (playerShots[n].pos.z < -10)
                    playerShots[n].alive = false;

                kmMat4Identity(&model);
                kmMat4Translation(&model, playerShots[n].pos.x,
                                  playerShots[n].pos.y,
                                  playerShots[n].pos.z);
                kmMat4RotationPitchYawRoll(&model, rad * 4, 0,
                                           -rad * 4);

                kmMat4Assign(&mvp, &vp);
                kmMat4Multiply(&mvp, &mvp, &model);

                kmMat4Assign(&mv, &view);
                kmMat4Multiply(&mv, &mv, &model);

                glBindTexture(GL_TEXTURE_2D, shotTex);
                drawObj(&shotObj, &mvp, &mv, lightDir, viewDir);
            }
        }

        playerRoll = 0;
        if (keys[KEY_CURSL] && playerPos.x > -10) {
            playerPos.x -= 0.1;
            playerRoll = .2;
        }
        if (keys[KEY_CURSR] && playerPos.x < 10) {
            playerPos.x += 0.1;
            playerRoll = -.2;
        }
        pEye.x = playerPos.x * 1.25;

        pCenter.x = playerPos.x;
        pCenter.y = playerPos.y + 1;
        pCenter.z = playerPos.z;

        int deadAliens;

        deadAliens = 0;

        for (int n = 0; n < MAX_ALIENS; n++) {
            if (aliens[n].alive == true) {

                kmMat4Identity(&model);
                kmMat4Translation(&model, aliens[n].pos.x,
                                  aliens[n].pos.y, aliens[n].pos.z);
                kmMat4RotationPitchYawRoll(&model, -.4, 0, 0);

                kmMat4Assign(&mvp, &vp);
                kmMat4Multiply(&mvp, &mvp, &model);

                kmMat4Assign(&mv, &view);
                kmMat4Multiply(&mv, &mv, &model);

                glBindTexture(GL_TEXTURE_2D, alienTex);
                drawObj(&alienObj, &mvp, &mv, lightDir, viewDir);

                kmVec3 d;
                for (int i = 0; i < MAX_PLAYER_SHOTS; i++) {
                    kmVec3Subtract(&d, &aliens[n].pos,
                                   &playerShots[i].pos);
                    if (kmVec3Length(&d) < .7
                            && playerShots[i].alive) {
                        aliens[n].alive = false;
                        playerShots[i].alive = false;
                        aliens[n].exploding = true;
                        resetExposion(aliens[n].explosion);
                    }
                }
            } 

            if (aliens[n].alive != true && aliens[n].exploding != true) {
                    deadAliens++;
                
            }
        }

        if (deadAliens == MAX_ALIENS) {
            resetAliens();
        }

		// draw explosions after ALL aliens
        for (int n = 0; n < MAX_ALIENS; n++) {
			if (aliens[n].exploding==true) {
				kmMat4Identity(&model);
				kmMat4Translation(&model, aliens[n].pos.x,
								  aliens[n].pos.y, aliens[n].pos.z);

				kmMat4Assign(&mvp, &vp);
				kmMat4Multiply(&mvp, &mvp, &model);
				glBindTexture(GL_TEXTURE_2D, expTex);
				drawPointCloud(aliens[n].explosion, &mvp);
				aliens[n].explosion->tick=aliens[n].explosion->tick+0.05;
				if (aliens[n].explosion->tick>1.25) {
					aliens[n].exploding=false;                   	
				} else {
					// update the explosion
					
					for (int i=0; i<aliens[n].explosion->totalPoints; i++) {
				
						float t;
						t=aliens[n].explosion->tick;
						if (i>aliens[n].explosion->totalPoints/2) t=t/2.0;
						aliens[n].explosion->pos[i*3]=aliens[n].explosion->vel[i*3] * t;
						aliens[n].explosion->pos[i*3+1]=aliens[n].explosion->vel[i*3+1] * t;
						aliens[n].explosion->pos[i*3+2]=aliens[n].explosion->vel[i*3+2] * t;
				
					}
				}
			}
		}

        // move camera
        kmMat4LookAt(&view, &pEye, &pCenter, &pUp);

        kmMat4Assign(&vp, &projection);
        kmMat4Multiply(&vp, &vp, &view);

        kmVec3Subtract(&viewDir,&pEye,&pCenter);
        kmVec3Normalize(&viewDir,&viewDir);

        // dump values
        glPrintf(100, 280, font1,"eye    %3.2f %3.2f %3.2f ", pEye.x, pEye.y, pEye.z);
        glPrintf(100, 296, font1,"centre %3.2f %3.2f %3.2f ", pCenter.x, pCenter.y,
                 pCenter.z);
        glPrintf(100, 320, font1,"mouse %i,%i %i ", mouse[0], mouse[1], mouse[2]);
        glPrintf(100, 340, font1,"frame %i %i ", frame, frame % 20);



        swapBuffers();

        gettimeofday(&ta, NULL);
        long j = (ta.tv_sec * 1e6 + ta.tv_usec);

        i = j - i;
        if (i < 0)
            i = 1000000;	// pass through - slower that 60fps
        if (i < 16000)
            usleep(16000 - i);

        // every 10 frames average the time taken and store
        // fps value for later printing with glprintf
        if (++num_frames % 10 == 0) {
            gettimeofday(&t2, NULL);
            float dtf =
                t2.tv_sec - t1.tv_sec + (t2.tv_usec -
                                         t1.tv_usec) * 1e-6;
            lfps = num_frames / dtf;
            num_frames = 0;
            t1 = t2;
        }
    }

    closeContext();

    return 0;
}