Beispiel #1
0
void GR_CocoaImage::cairoSetSource(cairo_t *cr)
{
	UT_return_if_fail(m_surface);
	double scaleX = (double)getDisplayWidth() / (double)cairo_image_surface_get_width(m_surface);
	double scaleY = (double)getDisplayHeight() / (double)cairo_image_surface_get_height(m_surface);
	cairo_scale(cr, scaleX, scaleY);
	cairo_set_source_surface(cr, m_surface, 0, 0);
}
Beispiel #2
0
void relocate_targets(){
	
    for (int i=0; i<max_targets; i++) {
        targets[i].x=rand_range(100,getDisplayWidth()-100);
        targets[i].y=rand_range(100,getDisplayHeight()-100);
    }

    reassign_flares();	
}
/**
 * Resize the buffer size (either normal or fullscreen)
 */
void ChameleonMScreen::setBufferSize(BufferSize newSize)
{    
       if (newSize == fullScreenSize) {
           qpixmap.resize(getDisplayFullWidth(), getDisplayFullHeight());
       } else {
           qpixmap.resize(getDisplayWidth(), getDisplayHeight());
       }

}
Beispiel #4
0
/*!
 * Scale our image to rectangle given by rec. The dimensions of rec
 * are calculated in logical units.
 */
void GR_UnixImage::scaleImageTo(GR_Graphics * pG, const UT_Rect & rec)
{
	UT_sint32 width = pG->tdu(rec.width);
	UT_sint32 height = pG->tdu(rec.height);
	if((width == getDisplayWidth()) && (height == getDisplayHeight()))
	{
		return;
	}
	scale(width,height);
	//	UT_ASSERT(G_OBJECT(m_image)->ref_count == 1);
}
Beispiel #5
0
/**
 * Resize the buffer size (either normal or fullscreen)
 */
void ChameleonMScreen::setBufferSize(BufferSize newSize)
{    
    if (newSize == fullScreenSize) {
        if (gc->isActive()) {
            gc->end();
        }
        qpixmap.resize(getDisplayFullWidth(), getDisplayFullHeight());
    } else {
        qpixmap.resize(getDisplayWidth(), getDisplayHeight());
    }
    
    // Whether current Displayable won't repaint the entire screen on
    // resize event, the artefacts from the old screen content can appear.
    // That's why the buffer content is not preserved.
    qpixmap.fill(Qt::black);
}
/*!
 * Generate an outline of an image with transparency. This is a collection
 * of (x,y) points marking the first non-transparent point from the left
 * and right side of the image.
 * This outline is used by GetOffsetFromLeft and facitates "tight" 
 * text wrapping
 * around objects.
 */
void GR_Image::GenerateOutline(void)
{
  DestroyOutline();
  UT_sint32 width = getDisplayWidth();
  UT_sint32 height = getDisplayHeight();
  UT_sint32 i,j=0;
  //
  // Generate from left
  //
  for(i=0; i< height;i++)
  {
    for(j =0; j< width;j++)
    {
      if(!isTransparentAt(j,i))
      {
	break;
      }
    }
    if( j < width)
    {
      GR_Image_Point * pXY = new GR_Image_Point();
      pXY->m_iX = j;
      pXY->m_iY = i;
      m_vecOutLine.addItem(pXY);
    }
  }
  //
  // Generate from Right
  //
  for(i=0; i< height;i++)
  {
    for(j =width-1; j>= 0;j--)
    {
      if(!isTransparentAt(j,i))
      {
	break;
      }
    }
    if( j >= 0)
    {
      GR_Image_Point * pXY = new GR_Image_Point();
      pXY->m_iX = j;
      pXY->m_iY = i;
      m_vecOutLine.addItem(pXY);
    }
  }
}
Beispiel #7
0
void Platform::setMouseCaptured(bool captured)
{
    if (captured != __mouseCaptured)
    {
        if (captured)
        {
            // Hide the cursor and warp it to the center of the screen
            __mouseCapturePoint.x = getDisplayWidth() / 2;
            __mouseCapturePoint.y = getDisplayHeight() / 2;

            ShowCursor(FALSE);
            WarpMouse(__mouseCapturePoint.x, __mouseCapturePoint.y);
        }
        else
        {
            // Restore cursor
            WarpMouse(__mouseCapturePoint.x, __mouseCapturePoint.y);
            ShowCursor(TRUE);
        }

        __mouseCaptured = captured;
    }
}
Beispiel #8
0
void init_graphic()
{
    memset(&ctx, 0, sizeof(DrawCtx));

    // alloc VSH Menu graphic buffers, generic based on canvas constants
    buf[0].addr = mem_alloc(CANVAS_W * CANVAS_H * sizeof(uint32_t));    // canvas buffer
    buf[1].addr = mem_alloc(CANVAS_W * CANVAS_H * sizeof(uint32_t));    // background buffer

    #ifdef HAVE_PNG_FONT
    // load font png
    Buffer font = load_png(PNG_FONT_PATH);
    ctx.font    = font.addr;
    #endif

    // set drawing context
    ctx.canvas   = buf[0].addr;
    ctx.bg       = buf[1].addr;
    ctx.bg_color = 0xFF000000;          // black, opaque
    ctx.fg_color = 0xFFFFFFFF;          // white, opaque

    // get current display values
    offset = *(uint32_t*)0x60201104;    // start offset of current framebuffer
    getDisplayPitch(&pitch, &unk1);     // framebuffer pitch size
    h = getDisplayHeight();             // display height
    w = getDisplayWidth();              // display width

    // get x/y start coordinates for our canvas, always center
    canvas_x = (w - CANVAS_W) /2;
    canvas_y = (h - CANVAS_H) /2;

    // dump background, for alpha blending
    dump_bg();

    // init first frame with background dump
    memcpy((uint8_t *)ctx.canvas, (uint8_t *)ctx.bg, CANVAS_W * CANVAS_H * sizeof(uint32_t));
}
// --------------------------------------------------
// This changes your app's window size to the correct output size
void ofxProjectorBlend::setWindowToDisplaySize()
{
	ofSetWindowShape(getDisplayWidth(), getDisplayHeight());
}
Beispiel #10
0
bool PageView::paintPage(cairo_t * cr, GdkRectangle * rect) {
	XOJ_CHECK_TYPE(PageView);

	double zoom = xournal->getZoom();

	g_mutex_lock(this->drawingMutex);

	int dispWidth = getDisplayWidth();
	int dispHeight = getDisplayHeight();

	if (this->crBuffer == NULL) {
		this->crBuffer = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, dispWidth, dispHeight);
		cairo_t * cr2 = cairo_create(this->crBuffer);
		cairo_set_source_rgb(cr2, 1, 1, 1);
		cairo_rectangle(cr2, 0, 0, dispWidth, dispHeight);
		cairo_fill(cr2);

		cairo_scale(cr2, zoom, zoom);

		const char * txtLoading = _("Loading...");

		cairo_text_extents_t ex;
		cairo_set_source_rgb(cr2, 0.5, 0.5, 0.5);
		cairo_select_font_face(cr2, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
		cairo_set_font_size(cr2, 32.0);
		cairo_text_extents(cr2, txtLoading, &ex);
		cairo_move_to(cr2, (page.getWidth() - ex.width) / 2 - ex.x_bearing, (page.getHeight() - ex.height) / 2 - ex.y_bearing);
		cairo_show_text(cr2, txtLoading);

		cairo_destroy(cr2);
		rerenderPage();
	}

	cairo_save(cr);

	double width = cairo_image_surface_get_width(this->crBuffer);
	if (width != dispWidth) {
		double scale = ((double) dispWidth) / ((double) width);

		// Scale current image to fit the zoom level
		cairo_scale(cr, scale, scale);
		cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_FAST);

		cairo_set_source_surface(cr, this->crBuffer, 0, 0);

		rerenderPage();

		rect = NULL;
	} else {
		cairo_set_source_surface(cr, this->crBuffer, 0, 0);
	}

	if (rect) {
		cairo_rectangle(cr, rect->x, rect->y, rect->width, rect->height);
		cairo_fill(cr);

#ifdef SHOW_PAINT_BOUNDS
		cairo_set_source_rgb(cr, 1.0, 0.5, 1.0);
		cairo_set_line_width(cr, 1. / zoom);
		cairo_rectangle(cr, rect->x, rect->y, rect->width, rect->height);
		cairo_stroke(cr);
#endif
	} else {
		cairo_paint(cr);
	}

	cairo_restore(cr);

	// don't paint this with scale, because it needs a 1:1 zoom
	if (this->verticalSpace) {
		this->verticalSpace->paint(cr, rect, zoom);
	}

	cairo_scale(cr, zoom, zoom);

	if (this->textEditor) {
		this->textEditor->paint(cr, rect, zoom);
	}
	if (this->selection) {
		this->selection->paint(cr, rect, zoom);
	}

	if (this->search) {
		this->search->paint(cr, rect, zoom, getSelectionColor());
	}
	this->inputHandler->draw(cr, zoom);
	g_mutex_unlock(this->drawingMutex);
	return true;
}
Beispiel #11
0
/*!
 * The idea is to create a
 * new image from the rectangular segment in device units defined by 
 * UT_Rect rec. The Image should be deleted by the calling routine.
 */
GR_Image * GR_Win32Image::createImageSegment(GR_Graphics * pG,const UT_Rect & rec)
{
	// this code assumes 24 bit RGB bitmaps ...
	UT_return_val_if_fail(pG && m_pDIB && m_pDIB->bmiHeader.biBitCount == 24, NULL);

	// the ration of x and y coords for the graphics class
	double fXYRatio = ((GR_Win32Graphics *)pG)->getXYRatio();

	// We have three different coordinate systems here:
	//   
	//   rec: the requested segment size, in layout units
	//   
	//   m_pDIB->bmiHeader.biHeight/Width(): physical size of the bitmap
	//
	//   getDisplayWidth()/Height() : size in device units for which this image was to be
	//                                rendered
	//
	// From these we need to work out the size/offset of the segment in the DIB
	// coordinaces

	// these are the DIB physical dimensions of the original
	UT_sint32 dH = m_pDIB->bmiHeader.biHeight;
	UT_sint32 dW = m_pDIB->bmiHeader.biWidth;

	// this is the internal scaling of the orginal DIB, which we need to workout
	// relationship between display units and DIB units; we need to use separate factors
	// for x and y axis, since the proportions of the DIB have no formal relationship to
	// the dimensions of the displayed rectangle (e.g., the display image could be
	// cropped).
	
	double fDibScaleFactorX = (double) dW / (double)getDisplayWidth();
	double fDibScaleFactorY = (double) dH / (double)getDisplayHeight();

	// these are the requested dimensions in device units
	UT_sint32 widthDU = (UT_sint32)((double)pG->tdu(rec.width) * fXYRatio);
	UT_sint32 heightDU = pG->tdu(rec.height);
	UT_sint32 xDU = (UT_sint32)((double)pG->tdu(rec.left) * fXYRatio);
	UT_sint32 yDU = pG->tdu(rec.top);

	// now convert the DUs into DIB units -- these are the values we need to work with
	// when copying the image segment
	UT_sint32 widthDIB = (UT_sint32)((double)widthDU * fDibScaleFactorX);
	UT_sint32 heightDIB = (UT_sint32)((double)heightDU * fDibScaleFactorY);
	UT_sint32 xDIB = (UT_sint32)((double)xDU * fDibScaleFactorX);
	UT_sint32 yDIB = (UT_sint32)((double)yDU * fDibScaleFactorY);
	
	if(xDIB < 0)
	{
		xDIB = 0;
	}
	if(yDIB < 0)
	{
		yDIB = 0;
	}

	if(heightDIB > dH)
	{
		heightDIB = dH;
	}
	if(widthDIB > dW)
	{
		widthDIB = dW;
	}
	if(xDIB + widthDIB > dW)
	{
		widthDIB = dW - xDIB;
	}
	if(yDIB + heightDIB > dH)
	{
		heightDIB = dH - yDIB;
	}
	if(widthDIB < 0)
	{
		xDIB = dW -1;
		widthDIB = 1;
	}
	if(heightDIB < 0)
	{
		yDIB = dH -1;
		heightDIB = 1;
	}
	
	UT_String sName("");
	getName(sName);
    UT_String sSub("");
	UT_String_sprintf(sSub,"_segment_%d_%d_%d_%d",xDIB,yDIB,widthDIB,heightDIB);
	sName += sSub;
	GR_Win32Image * pImage = new GR_Win32Image(sName.c_str());

	UT_return_val_if_fail( pImage, NULL );
	
	// now allocate memory -- mostly copied from convertFromBuffer()
	UT_uint32 iBytesInRow = widthDIB * 3;
	if (iBytesInRow % 4)
	{
		iBytesInRow += (4 - (iBytesInRow % 4));
	}

	pImage->m_pDIB = (BITMAPINFO*) g_try_malloc(sizeof(BITMAPINFOHEADER) + heightDIB * iBytesInRow);
	UT_return_val_if_fail( pImage->m_pDIB, NULL );

	// simply copy the whole header
	memcpy(pImage->m_pDIB, m_pDIB, sizeof(BITMAPINFOHEADER));

	// now set the image size ...
	pImage->setDisplaySize(widthDU, heightDU);
	pImage->m_pDIB->bmiHeader.biWidth = widthDIB;
	pImage->m_pDIB->bmiHeader.biHeight = heightDIB;
	pImage->m_pDIB->bmiHeader.biSizeImage = 0;

	// now copy the bitmap bits
	// the rows in both maps are/need to be padded to 4-bytes
	// NB: in the DIB lines are numbered from bottom up, while in our coord system y goes
	// from top to bottom

	// how wide is a row in the orignal ?
	UT_uint32 iOrigRowBytes = m_pDIB->bmiHeader.biWidth*3;
	if(iOrigRowBytes%4)
		iOrigRowBytes += (4 - iOrigRowBytes%4);

	// what are the coords in the orginal we want?
	UT_uint32 iByteWidth = widthDIB*3;
	UT_uint32 iLeft = xDIB*3;
	UT_uint32 iRight = iLeft + iByteWidth;
	UT_uint32 iTop = m_pDIB->bmiHeader.biHeight - yDIB;
	UT_uint32 iBottom = iTop - heightDIB;
	UT_uint32 iRightPadded = iRight + (iBytesInRow - iByteWidth);

	UT_Byte * pBits1 = ((UT_Byte*)m_pDIB) + sizeof(BITMAPINFOHEADER);
	UT_Byte * pBits2 = ((UT_Byte*)pImage->m_pDIB) + sizeof(BITMAPINFOHEADER);

	UT_uint32 iRow;
	
	for(iRow = iBottom; iRow < iTop; iRow++)
	{
		memcpy(pBits2, pBits1 + iRow * iOrigRowBytes + iLeft, iByteWidth);
		pBits2 += iByteWidth;
		
		// now the padding ...
		for(UT_uint32 iPad = iRight; iPad < iRightPadded; iPad++, pBits2++)
		{
			*pBits2 = 0;
		}
	}
	
	return static_cast<GR_Image *>(pImage);
}
Beispiel #12
0
int main()
{


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

    flareTex = loadPNG("resources/textures/cloud.png");
	
	
    width = getDisplayWidth();
    height = getDisplayHeight();

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

    // initialises glprint's matrix, shader and texture
    initGlPrint(getDisplayWidth(), getDisplayHeight());
    font1=createFont("resources/textures/font.png",0,256,16,16,16);
    initSprite(getDisplayWidth(), getDisplayHeight());
	

    fileid = 0;	
    loadfile();
    for (int i=0; i<max_flares; i++) {
        flares[i].x=rand_range(0,getDisplayWidth());
        flares[i].y=rand_range(0,getDisplayHeight());
        flares[i].vx=rand_range(0,10)-5;
        flares[i].vy=rand_range(0,10)-5;
    }
    /*for (int i=0; i<max_targets; i++) {
        targets[i].x=rand_range(0,getDisplayWidth());
        targets[i].y=rand_range(0,getDisplayHeight());
	targets[i].flares = 0;
    }*/

    /*for (int i=0; i<max_flares; i++) {
        flares[i].x=rand_range(0,getDisplayWidth());
        flares[i].y=rand_range(0,getDisplayHeight());
        flares[i].vx=rand_range(0,10)-5;
        flares[i].vy=rand_range(0,10)-5;
	flares[i].target = (int)rand_range(0,max_targets);
	targets[flares[i].target].flares ++;
    }*/


    // we don't want to draw the back of triangles
    // the blending is set up for glprint but disabled
    // while not in use
    glCullFace(GL_BACK);
    glEnable(GL_CULL_FACE);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_BLEND);
    glDisable(GL_DEPTH_TEST);
    glClearColor(0, 0.5, 1, 1);

    // count each frame
    int num_frames = 0;

    // set to true to leave main loop
    bool quit = false;
    
// get a pointer to the key down array
    keys = getKeys();
	int* mouse = getMouse();

    while (!quit) {		// the main loop

        doEvents();	// update mouse and key arrays

        if (keys[KEY_ESC])
            quit = true;	// exit if escape key pressed
        if (keys[KEY_SPACE])
            relocate_targets();	// exit if escape key pressed
        if (keys[KEY_RETURN])
            reassign_flares();	// exit if escape key pressed
        if (keys[KEY_S] && !lastkeys[KEY_S])
            save();	// exit if escape key pressed
        if (keys[KEY_CURSL] && !lastkeys[KEY_CURSL]){
            fileid--;
	    if (fileid <0) fileid = 0;
	    loadfile();	// exit if escape key pressed
	}
        if (keys[KEY_CURSR] && !lastkeys[KEY_CURSR]){
            fileid++;
	    loadfile();	// exit if escape key pressed
	}
        if (keys[KEY_C]){
            max_targets = 1;	// exit if escape key pressed
	    reassign_flares();    
	}
	lastkeys[KEY_S] = keys[KEY_S];
	lastkeys[KEY_CURSL] = keys[KEY_CURSL];
	lastkeys[KEY_CURSR] = keys[KEY_CURSR];
	
	mx = mouse[0];
	my = mouse[1];
	if(mouse[2] != 0){
		spawn_target(mx,my);
	}

	for (int i=0; i<RE_MULTIPLY; i++){
		random_events();
	}
	
	think();
        
        render();	// the render loop

        usleep(1600);	// no need to run cpu/gpu full tilt

    }

    closeContext();		// tidy up

    return 0;
}
Beispiel #13
0
    DisplayConfigPtr DisplayConfigFactory::create(OSVR_ClientContext ctx) {
        DisplayConfigPtr cfg(new DisplayConfig);
        try {
            auto const descriptorString = ctx->getStringParameter("/display");

            auto desc = display_schema_1::DisplayDescriptor(descriptorString);
            cfg->m_viewers.container().emplace_back(Viewer(ctx, HEAD_PATH));
            auto &viewer = cfg->m_viewers.container().front();
            auto eyesDesc = desc.getEyes();

            /// Set up stereo vs mono
            std::vector<uint8_t> eyeIndices;
            Eigen::Vector3d offset;
            if (eyesDesc.size() == 2) {
                // stereo
                offset = desc.getIPDMeters() / 2. * Eigen::Vector3d::UnitX();
                eyeIndices = {0, 1};
            } else {
                // if (eyesDesc.size() == 1)
                // mono
                offset = Eigen::Vector3d::Zero();
                eyeIndices = {0};
            }

            /// Handle radial distortion parameters
            boost::optional<OSVR_RadialDistortionParameters> distort;
            auto k1 = desc.getDistortion();
            if (k1.k1_red != 0 || k1.k1_green != 0 || k1.k1_blue != 0) {
                OSVR_RadialDistortionParameters params;
                params.k1.data[0] = k1.k1_red;
                params.k1.data[1] = k1.k1_green;
                params.k1.data[2] = k1.k1_blue;
                distort = params;
            }

            /// Compute angular offset about Y of the optical (view) axis
            util::Angle axisOffset = 0. * util::radians;
            {
                auto overlapPct = desc.getOverlapPercent();

                if (overlapPct < 1.) {
                    const auto hfov = desc.getHorizontalFOV();
                    const auto angularOverlap = hfov * overlapPct;
                    axisOffset = (hfov - angularOverlap) / 2.;
                }
            }

            /// Infer the number of display inputs and their association with
            /// eyes (actually surfaces) based on the descriptor.
            std::vector<OSVR_DisplayInputCount> displayInputIndices;
            if (eyesDesc.size() == 2 &&
                display_schema_1::DisplayDescriptor::FULL_SCREEN ==
                    desc.getDisplayMode()) {
                // two eyes, full screen - that means two screens.

                displayInputIndices = {0, 1};

                cfg->m_displayInputs.push_back(DisplayInput(
                    desc.getDisplayWidth(), desc.getDisplayHeight()));
                cfg->m_displayInputs.push_back(DisplayInput(
                    desc.getDisplayWidth(), desc.getDisplayHeight()));
            } else {
                // everything else, assume 1 screen.
                // Note that it's OK that displayInputIndices.size() >=
                // eyesDesc.size(), we'll just not end up using the second
                // entry.
                displayInputIndices = {0, 0};

                cfg->m_displayInputs.push_back(DisplayInput(
                    desc.getDisplayWidth(), desc.getDisplayHeight()));
            }
            BOOST_ASSERT_MSG(displayInputIndices.size() >= eyesDesc.size(),
                             "Must have at least as many indices as eyes");

            /// Create the actual eye (with implied surface) objects
            for (auto eye : eyeIndices) {
                // This little computation turns 0 into -1 and 1 into 1, used as
                // a coefficient to make the two eyes do opposite things.
                // Doesn't affect mono, which has a zero offset vector.
                double offsetFactor = (2. * eye) - 1.;

                // Set up per-eye distortion parameters, if needed
                boost::optional<OSVR_RadialDistortionParameters> distortEye(
                    distort);
                if (distortEye) {
                    distortEye->centerOfProjection.data[0] =
                        eyesDesc[eye].m_CenterProjX;
                    distortEye->centerOfProjection.data[1] =
                        eyesDesc[eye].m_CenterProjY;
                }

                // precompute translation offset for this eye
                auto xlateOffset = (offsetFactor * offset).eval();

                // precompute the optical axis rotation for this eye
                // here, the left eye should get a positive offset since it's a
                // positive rotation about y, hence the -1 factor.
                auto eyeAxisOffset = axisOffset * -1. * offsetFactor;

                // Look up the display index for this eye.
                auto displayInputIdx = displayInputIndices[eye];

                /// Create the ViewerEye[Surface] and add it to the container.
                viewer.container().emplace_back(ViewerEye(
                    ctx, xlateOffset, HEAD_PATH, computeViewport(eye, desc),
                    computeRect(desc), eyesDesc[eye].m_rotate180,
                    desc.getPitchTilt().value(), distortEye, displayInputIdx,
                    eyeAxisOffset));
            }

            OSVR_DEV_VERBOSE("Display: " << desc.getHumanReadableDescription());
            return cfg;
        } catch (std::exception const &e) {
            OSVR_DEV_VERBOSE(
                "Couldn't create a display config internally! Exception: "
                << e.what());
            return DisplayConfigPtr{};
        } catch (...) {
            OSVR_DEV_VERBOSE("Couldn't create a display config internally! "
                             "Unknown exception!");
            return DisplayConfigPtr{};
        }
    }
Beispiel #14
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;
}