Ejemplo n.º 1
0
/**
 * Calculates the inverse of pM and stores the result in
 * pOut.
 * @Return Returns NULL if there is no inverse, else pOut
 */
kmMat4* const kmMat4Inverse(kmMat4* pOut, const kmMat4* pM)
{
    kmMat4 inv;
    kmMat4Assign(&inv, pM);

    kmMat4 tmp;
    kmMat4Identity(&tmp);

    if(gaussj(&inv, &tmp) == KM_FALSE) {
        return NULL;
    }

    kmMat4Assign(pOut, &inv);
    return pOut;
}
void kmGLPushMatrix(void)
{
	kmMat4 top;

	lazyInitialize(); //Initialize the stacks if they haven't been already

	//Duplicate the top of the stack (i.e the current matrix)
	kmMat4Assign(&top, current_stack->top);
	km_mat4_stack_push(current_stack, &top);
}
Ejemplo n.º 3
0
void kmGLPushMatrix(void)
{
	kmMat4 top;

	km_mat4_stack_context *current_context = lazyInitializeCurrentContext();

	/*Duplicate the top of the stack (i.e the current matrix)	*/
	kmMat4Assign(&top, current_context->current_stack->top);
	km_mat4_stack_push(current_context->current_stack, &top);
}
void kmGLGetMatrix(kmGLEnum mode, kmMat4* pOut)
{
	lazyInitialize();

	switch(mode)
	{
		case KM_GL_MODELVIEW:
			kmMat4Assign(pOut, modelview_matrix_stack.top);
		break;
		case KM_GL_PROJECTION:
			kmMat4Assign(pOut, projection_matrix_stack.top);
		break;
		case KM_GL_TEXTURE:
			kmMat4Assign(pOut, texture_matrix_stack.top);
		break;
		default:
			assert(1 && "Invalid matrix mode specified"); //TODO: Proper error handling
		break;
	}
}
Ejemplo n.º 5
0
void kmGLGetMatrix(kmGLEnum mode, kmMat4* pOut)
{
	km_mat4_stack_context *current_context = lazyInitializeCurrentContext();

	switch(mode)
	{
		case KM_GL_MODELVIEW:
			kmMat4Assign(pOut, current_context->modelview_matrix_stack.top);
		break;
		case KM_GL_PROJECTION:
			kmMat4Assign(pOut, current_context->projection_matrix_stack.top);
		break;
		case KM_GL_TEXTURE:
			kmMat4Assign(pOut, current_context->texture_matrix_stack.top);
		break;
		default:
			assert(1 && "Invalid matrix mode specified"); /*TODO: Proper error handling*/
		break;
	}
}
Ejemplo n.º 6
0
void km_mat4_stack_push(km_mat4_stack* stack, const kmMat4* item)
{
    stack->top = &stack->stack[stack->item_count];
    kmMat4Assign(stack->top, item);
    stack->item_count++;

    if(stack->item_count >= stack->capacity){
        stack->capacity += INCREMENT;
        stack->stack = (kmMat4*)realloc(stack->stack,stack->capacity*sizeof(kmMat4));
        stack->top = &stack->stack[stack->item_count - 1];
    }
}
Ejemplo n.º 7
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);

}
Ejemplo n.º 8
0
void km_mat4_stack_push(km_mat4_stack* stack, const kmMat4* item)
{
    stack->top = &stack->stack[stack->item_count];
    kmMat4Assign(stack->top, item);
    stack->item_count++;

    if(stack->item_count >= stack->capacity)
    {
		kmMat4* temp = NULL;
        stack->capacity += INCREMENT;
        temp = stack->stack;
        stack->stack = (kmMat4*) malloc(stack->capacity*sizeof(kmMat4));
        memcpy(stack->stack, temp, sizeof(kmMat4)*(stack->capacity - INCREMENT));
        free(temp);
        stack->top = &stack->stack[stack->item_count - 1];
    }
}
Ejemplo n.º 9
0
    kmMat4 *nodeToWorldTransform()
    {
        
        kmMat4 *transform = get_transform();
        kmMat4Assign(_nodeToWorldTransform, transform); //获取nodeToWorld矩阵
        auto p = m_parent;
        if (nullptr != p)
        {
            if (p->hasComponent<KKTransform2DComponent>())
            {
                kmMat4Multiply(_nodeToWorldTransform, p->getComponent<KKTransform2DComponent>()->nodeToWorldTransform(), _nodeToWorldTransform);//矩阵相乘
                p = p->getComponent<KKTransform2DComponent>()->get_parent();
            }
        }
        else
        {
            KKASSERT(mEntity, "compnent not activated");
            KKSceneManager *sceneMgr = mEntity->getEntityManager()->getSceneManager();
            kmMat4Multiply(_nodeToWorldTransform, _nodeToWorldTransform, sceneMgr->currentCameraMatrix());
        }
        
//        kmMat4* transform = get_transform();
//        kmMat4Assign(_nodeToWorldTransform, transform);
//        
//        KKEntity* parent = m_parent;
//        if (parent != NULL)
//        {
//            if (parent->hasComponent<KKTransform2DComponent>())
//            {
//                kmMat4Multiply(_nodeToWorldTransform, parent->getComponent<KKTransform2DComponent>()->nodeToWorldTransform(),_nodeToWorldTransform);
//                parent = parent->getComponent<KKTransform2DComponent>()->get_parent();
//            }
//        }
//        else
//        {
//            KKSceneManager* sceneMgr = mEntity->getEntityManager()->getSceneManager();
//            kmMat4Multiply(_nodeToWorldTransform, _nodeToWorldTransform, sceneMgr->currentCameraMatrix());
//        }
        
        return _nodeToWorldTransform;
    }
Ejemplo n.º 10
0
void BaseRenderer::render(Scene& scene) {
    on_start_render(scene);

    //FIXME: This is ugly and inconsistent
    scene.active_camera().apply(&modelview().top());
    kmMat4Assign(&projection().top(), &scene.active_camera().projection_matrix());

    for(Scene::iterator it = scene.begin(); it != scene.end(); ++it) {
        Object& object = static_cast<Object&>(*it);
        if(pre_visit(object)) {
            (*this)(object);
            post_visit(object);
        }
    }

    //Reset the modelview and projection for the overlay
    kmMat4Identity(&modelview().top());
    kmMat4Identity(&projection().top());

    /*
      Once the entire scene has been rendered, it's time to handle the
      overlays.
    */
    for(uint32_t i = 0; i < scene.overlay_count(); ++i) {
        Overlay& overlay = scene.overlay_ordered_by_zindex(i);
        projection().push();

        for(Scene::iterator it = overlay.begin(); it != overlay.end(); ++it) {
            Object& object = static_cast<Object&>(*it);
            if(pre_visit(object)) {
                (*this)(object);
                post_visit(object);
            }
        }
        projection().pop();
    }

    on_finish_render(scene);
}
Ejemplo n.º 11
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);

}
Ejemplo n.º 12
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;
}
void kmGLLoadMatrix(const kmMat4* pIn)
{
	lazyInitialize();
	kmMat4Assign(current_stack->top, pIn);
}
Ejemplo n.º 14
0
void kmGLLoadMatrix(const kmMat4* pIn)
{
	km_mat4_stack_context *current_context = lazyInitializeCurrentContext();
	kmMat4Assign(current_context->current_stack->top, pIn);
}
Ejemplo n.º 15
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;
}