Example #1
0
void setSize(int value)
{
    int prevGrid = grid;
    switch(value)
    {
    case SMALL :
        grid = MAXGRID/4;
        break;
    case MEDIUM:
        grid = MAXGRID/2;
        break;
    case LARGE :
        grid = MAXGRID/1.5;
        break;
    case XLARGE :
        grid = MAXGRID;
        break;
    }
    if (prevGrid > grid)
    {
        reset(resetMode);
    }
    zNear= grid/10.0;
    zFar= grid*3.0;
    sdepth = 5.0/4.0 * grid;
    getTexCoords();
    glutPostRedisplay();
}
Example #2
0
/////////////////////////////////////////////////////////
// setSize
//
/////////////////////////////////////////////////////////
void mesh_line :: setGrid( int valueX)
{
	if(valueX>=1) gridX = valueX;
	else gridX = 5;

    getTexCoords();
}
Example #3
0
//----------------------------------------------------------
void of3dPrimitive::normalizeAndApplySavedTexCoords() {
    ofVec4f tcoords = getTexCoords();
    // when a new mesh is created, it uses normalized tex coords, we need to reset them
    // but save the ones used previously //
    texCoords.set(0,0,1,1);
    mapTexCoords(tcoords.x, tcoords.y, tcoords.z, tcoords.w);
}
BaseSurface * GridWarpSurface::clone(){
	GridWarpSurface * s = new GridWarpSurface();
	s->setVertices(getVertices());
	s->setTexCoords(getTexCoords());
	s->setSource(getSource());
	return s;
}
Example #5
0
    void MapLevel::loadLevel(std::size_t level, sf::Image& levelData)
    {
        LOG_CALL("MapLevel::loadLevel");
        int imageX0 = level * LevelWidth;
        int imageY0 = 0;

        sf::Vector2u dataSize = levelData.getSize();
        LOG_DEBUG("LevelData size: %d, %d", dataSize.x, dataSize.y);

        mVertices.setPrimitiveType(sf::Quads);
        mVertices.resize(LevelWidth * LevelHeight * 4);


        for (std::size_t j = 0; j < LevelHeight; ++j) {
            for (std::size_t i = 0; i < LevelWidth; ++i) {
                int imageX = imageX0 + i;
                int imageY = imageY0 + j;

                Tile tile = getTileFromColor(levelData.getPixel(imageX, imageY));
                mWorld[i][j] = tile;

                if (tile == Tile::Wall) {
                    sf::Vector2i texCoords = getTexCoords(tile);
                    sf::Vertex* quad = &mVertices[(i + j * LevelWidth) * 4];
                    int tu = texCoords.x;
                    int tv = texCoords.y;

                    int left = WorldOffsetX + i * TileWidth;
                    int top = WorldOffsetY + j * TileHeight;
                    int right = WorldOffsetX + (i + 1) * TileWidth;
                    int bottom = WorldOffsetY + (j + 1) * TileHeight;

                    // Define 4 corners of vertice
                    quad[0].position = sf::Vector2f(left, top);
                    quad[1].position = sf::Vector2f(right, top);
                    quad[2].position = sf::Vector2f(right, bottom);
                    quad[3].position = sf::Vector2f(left, bottom);

                    quad[0].texCoords = sf::Vector2f(tu * TileWidth, tv * TileHeight);
                    quad[1].texCoords = sf::Vector2f((tu + 1) * TileWidth, tv * TileHeight);
                    quad[2].texCoords = sf::Vector2f((tu + 1) * TileWidth, (tv + 1) * TileHeight);
                    quad[3].texCoords = sf::Vector2f(tu * TileWidth, (tv + 1) * TileHeight);

                    // Register wall in Box2D
                    b2utils::createGround(mBoxWorld, (left + right) / 2, (top + bottom) / 2, TileWidth, TileHeight);

                } else if (tile == Tile::PlayerSpawn) {
                    mPlayerSpawnPos.x = i;
                    mPlayerSpawnPos.y = j;

                } else if (tile == Tile::DestinationSpawn) {
                    mDestinationList.push_back(Position(i, j));

                } else if (tile == Tile::SourceSpawn) {
                    mSourceList.push_back(Position(i, j));
                }
            }
        }
    }
Example #6
0
Mesh* ModelLoaderMD3::Surface::getObject(size_t frame) const {
	const vector<vec3> verticesArray = getVertices(vertices + frame*header.numVerts, header.numVerts);
	const vector<vec3> normalsArray = getNormals(vertices + frame*header.numVerts, header.numVerts);
	const vector<vec2> texcoordsArray = getTexCoords(texCoords, header.numVerts);
	const vector<Face> facesArray = getFaces(triangles, header.numTris);
	
	return new Mesh(verticesArray, normalsArray, texcoordsArray, facesArray);
}
BaseSurface * TriangleSurface::clone(){
	TriangleSurface * s = new TriangleSurface();
	s->setVertices(getVertices());
	s->setTexCoords(getTexCoords());
    BaseSource * src = getSource();
    src->referenceCount++;
	s->setSource(src);
	return s;
}
Example #8
0
/////////////////////////////////////////////////////////
// setSize
//
/////////////////////////////////////////////////////////
void newWave :: setSize( int valueX, int valueY )
{
    gridX = valueX;
    gridY = valueY;

    reset(resetMode);

    getTexCoords();
}
Example #9
0
Color Cylinder::getDifColor(const Vec3D& pnt, const CIsect& isect/* = CIsect()*/) const
{
	if (mMtrl->DifTexture)
	{
		Vec3D texCoords = getTexCoords(pnt, isect);
		return scale3D(mMtrl->DifTexture->sample(texCoords.x(), texCoords.y()), mMtrl->DifColor);
	}
	return mMtrl->DifColor;
}
Example #10
0
double Object::getKs(const Point &p)
{
	if (!specularTexture || specularTexture->size() == 0)
		// No texture, use material
		return material->ks;
	
	double u, v;
	getTexCoords(p, u, v);
	// Use the red channel of the texture image, ignore the green and blue channels
	return material->ks*specularTexture->colorAt(u, v).r;
}
Example #11
0
void TextRenderer::renderString(string text,float offset){
	glBindTexture(GL_TEXTURE_2D,charSheet);


	GLfloat texCoords[8*text.length()];
	GLfloat vertexCoords[12*text.length()];

	for(int x=0;x<text.length();x++){
		for(int y=0;y<12;y++)
			vertexCoords[x*12+y]=0;

		vertexCoords[x*12]=x*renderWidth;
		vertexCoords[x*12+1]=offset;
		vertexCoords[x*12+2]=-5;
		vertexCoords[x*12+3]=x*renderWidth;
		vertexCoords[x*12+4]=-renderHeight+offset;
		vertexCoords[x*12+5]=-5;
		vertexCoords[x*12+6]=(x+1)*renderWidth;
		vertexCoords[x*12+7]=-renderHeight+offset;
		vertexCoords[x*12+8]=-5;
		vertexCoords[x*12+9]=(x+1)*renderWidth;
		vertexCoords[x*12+10]=offset;
		vertexCoords[x*12+11]=-5;
		//setup texture coords
		getTexCoords(text[x],&texCoords[x*8]);
	}


	glGenVertexArrays(1,&vao);
	glBindVertexArray(vao);

	glGenBuffers(2,buff);
	glBindBuffer(GL_ARRAY_BUFFER, buff[0]);
	glBufferData(GL_ARRAY_BUFFER,sizeof(GLfloat)*12*text.length(),vertexCoords,GL_STREAM_DRAW);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);

	glBindBuffer(GL_ARRAY_BUFFER, buff[1]);
	glBufferData(GL_ARRAY_BUFFER,sizeof(GLfloat)*8*text.length(),texCoords,GL_STREAM_DRAW);
	glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);


	glEnableVertexAttribArray(0);
	glEnableVertexAttribArray(2);

	glDrawArrays(GL_QUADS,0,4*text.length());

	//glDisableVertexAttribArray(0);
	//glDisableVertexAttribArray(2);
	glBindVertexArray(0);

	glDeleteBuffers(2,buff);
	glDeleteVertexArrays(1,&vao);
	glBindTexture(GL_TEXTURE_2D,0);
}
Example #12
0
void Object::addPhoton(const Point &p, Color &color)
{
	if (photonmap)
	{
		double u, v;
		getTexCoords(p, u, v);
		Color newColor = color + photonmap->colorAt(u, v);
		newColor.clamp();
		photonmap->setColorAt(u, v, newColor);
	}
}
Example #13
0
Color Object::getColor(const Point &p)
{	
	if (!texture || texture->size() == 0)
		// No texture, use material
		return material->color;
	
	double u, v;
	getTexCoords(p, u, v);
	
	// u and v are in [0,1] so scale them to the texture dimensions
	return texture->colorAt(u, v);
}
Example #14
0
Color Object::getPhotons(const Point &p)
{
	if (!photonmap && !photonblurmap) return Color(0,0,0);
	
	double u, v;
	getTexCoords(p, u, v);
	
	if (photonblurmap)
		return photonblurmap->colorAt(u, v);
	else
		return photonmap->colorAt(u, v);
}
Example #15
0
//----------------------------------------------------------
void of3dPrimitive::mapTexCoords( float u1, float v1, float u2, float v2 ) {
    //setTexCoords( u1, v1, u2, v2 );
    ofVec4f prevTcoord = getTexCoords();
    
    for(int j = 0; j < getMesh().getNumTexCoords(); j++ ) {
        ofVec2f tcoord = getMesh().getTexCoord(j);
        tcoord.x = ofMap(tcoord.x, prevTcoord.x, prevTcoord.z, u1, u2);
        tcoord.y = ofMap(tcoord.y, prevTcoord.y, prevTcoord.w, v1, v2);
        
        getMesh().setTexCoord(j, tcoord);
    }
    
    texCoords.set(u1, v1, u2, v2);
}
Example #16
0
void
HW3b::initVertexBuffer()
{
    
    int i,j;
    
    for (i=0; i<grid-1; i++) {
        for (j=0; j<grid-1; j++){
            m_points.push_back(vec3(i/((float)grid-1)/1.0,j/((float)grid-1)/1.0,posit[i][j]/((float)grid-1)/1.0));
            m_points.push_back(vec3(i/((float)grid-1)/1.0,(j+1)/((float)grid-1)/1.0,posit[i][j+1]/((float)grid-1)/1.0));
            m_points.push_back(vec3((i+1)/((float)grid-1)/1.0,(j+1)/((float)grid-1)/1.0,posit[i+1][j+1]/((float)grid-1)/1.0));
            m_points.push_back(vec3((i+1)/((float)grid-1)/1.0,j/((float)grid-1)/1.0,posit[i+1][j]/((float)grid-1)/1.0));
        }
    }

    m_numPoints = m_points.size();	// save number of vertices

    static GLuint vertexBuffer = -1;
    glGenBuffers(1, &vertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
    
    glBufferData(GL_ARRAY_BUFFER, m_numPoints*sizeof(vec3), &m_points[0], GL_STATIC_DRAW);
    glVertexAttribPointer(ATTRIB_VERTEX, 3, GL_FLOAT, GL_FALSE, 0, NULL);
    glEnableVertexAttribArray(ATTRIB_VERTEX); 

    getTexCoords();
    
    for (i=0; i<grid-1; i++) {
        for (j=0; j<grid-1; j++){
            m_coords.push_back(vec2(texCoords[i][j][0],texCoords[i][j][1]));
            m_coords.push_back(vec2(texCoords[i][j+1][0],texCoords[i][j+1][1]));
            m_coords.push_back(vec2(texCoords[i+1][j+1][0],texCoords[i+1][j+1][1]));
            m_coords.push_back(vec2(texCoords[i+1][j][0],texCoords[i+1][j][1]));
            
            
        }
    }
    //Create texture coordinates buffer
    static GLuint texCoordBuffer = -1;
    glGenBuffers(1, &texCoordBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, texCoordBuffer);
    glBufferData(GL_ARRAY_BUFFER, m_numPoints*sizeof(vec2), &m_coords[0], GL_STATIC_DRAW);
    glVertexAttribPointer(ATTRIB_TEXTURE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, NULL);
    glEnableVertexAttribArray(ATTRIB_TEXTURE_POSITION);

    m_points.clear();
    m_coords.clear();

}
Example #17
0
//----------------------------------------------------------
void of3dPrimitive::mapTexCoordsFromTexture( ofTexture& inTexture ) {
    bool bNormalized = true;
#ifndef TARGET_OPENGLES
    bNormalized = (inTexture.getTextureData().textureTarget!=GL_TEXTURE_RECTANGLE_ARB);
#endif
    
    ofTextureData& tdata = inTexture.getTextureData();
    if(bNormalized)
        mapTexCoords( 0, 0, tdata.tex_t, tdata.tex_u );
    else
        mapTexCoords(0, 0, inTexture.getWidth(), inTexture.getHeight());
    
    ofVec4f tcoords = getTexCoords();
    mapTexCoords(tcoords.x, tcoords.y, tcoords.z, tcoords.w);
}
Example #18
0
Mesh* ModelLoaderMD2::buildKeyFrame(const Material &skin,
                                    const Header &header,
                                    TexCoord *texCoords,
                                    Triangle *triangles,
                                    const Frame &frame) {
	const vector<vec3> verticesArray = getVertices(frame.vertices, header.numOfVertices, frame.scale, frame.translate);
	const vector<vec3> normalsArray = getNormals(frame.vertices, header.numOfVertices);
	const vector<vec2> texcoordsArray = getTexCoords(texCoords, header.numOfSt, header.skinWidth, header.skinHeight);
	const vector<Face> facesArray = getFaces(triangles, header.numOfTris);
	
	Mesh *mesh = new Mesh(verticesArray, normalsArray, texcoordsArray, facesArray);
	
	mesh->material = skin;
	
	return mesh;
}
void VertexGenerator::Mesh2D::dumpInfo()
{
    LOG_INFO("<-Dumpping Mesh2D information->\n");
    LOG_INFO("Vertex Point Count: %d, Vertex Size: %d, TexCoords Size: %d, Byte Stride: %d\n",
             getVertexCount(), getVertexSize(), getTexCoordsSize(), getByteStride());
    for(size_t i = 0; i < getVertexCount(); ++i)
        {
            float* position = getPositions() + getStride() * i;
            LOG_INFO("VertexPosition[%d]: %f, %f\n", i, *position, *(position + 1));
        }
    for(size_t i = 0; i < getVertexCount(); ++i)
        {
            float* texCoords = getTexCoords() + getStride() * i;
            LOG_INFO("TexCoords[%d]: %f, %f\n", i, *texCoords, *(texCoords + 1));
        }
}
Example #20
0
void ofxMesh::fromMesh(const ofMesh & mesh){
    if (mesh.hasVertices()) {
        getVertices()=mesh.getVertices();
    }
    if (mesh.hasColors()) {
        getColors()=mesh.getColors();
    }
    if (mesh.hasNormals()) {
        getNormals()=mesh.getNormals();
    }
    if (mesh.hasTexCoords()) {
        getTexCoords()=mesh.getTexCoords();
    }
    if (mesh.hasIndices()) {
        getIndices()=mesh.getIndices();
    }
}
Example #21
0
void ofxMesh::toMesh(ofMesh & mesh){
    mesh.clear();
    if (hasVertices()) {
        mesh.getVertices()=getVertices();
    }
    if (hasColors()) {
        mesh.getColors()=getColors();
    }
    if (hasNormals()) {
        mesh.getNormals()=getNormals();
    }
    if (hasTexCoords()) {
        mesh.getTexCoords()=getTexCoords();
    }
    if (hasIndices()) {
        mesh.getIndices()=getIndices();
    }
}
Example #22
0
Vector Object::getBumpedNormal(const Vector &origNormal, const Point &p)
{
	if (!bumpmap || bumpmap->size() == 0)
		// No bump map, don't mess with normal
		return origNormal;
	
	double u, v;
	float dx, dy;
	getTexCoords(p, u, v);
	bumpmap->derivativeAt(u, v, &dx, &dy);
	
	// Get the vectors to (u,v) from the points corresponding to the texture pixels
	// immediately right and down from it
	Vector dxVec = p - getPointFromTexCoords(min(u+1.0/(bumpmap->width()-1), 1.0), v);
	Vector dyVec = p - getPointFromTexCoords(u, min(v+1.0/(bumpmap->height()-1), 1.0));

	return (origNormal + bumpfactor*(dx*dxVec + dy*dyVec)).normalized();
}
Example #23
0
/////////////////////////////////////////////////////////
// setSize
//
/////////////////////////////////////////////////////////
void mesh_square :: setSize( int valueX, int valueY )
{
	if(valueX>1) gridX = valueX;
	else gridX = 5;

	if(valueY>1) gridY = valueY;
	else gridY = gridX;
  texCoords.resize(gridX);
  for ( int i = 0; i < gridX; ++i){
    texCoords[i].resize(gridY);
    for ( int j = 0; j < gridY; ++j) {
      texCoords[i][j].resize(2);
      texCoords[i][j][0] = ((1.*i)/(gridX-1.));
      texCoords[i][j][1] = ((1.*j)/(gridY-1.));
    }
  }
  getTexCoords();
}
Example #24
0
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 * setSize:
 *
 * Set grid size (menu item).
 */
void setSize(int value)
{
	int prevGrid = Grid;

	switch(value) {
		case SMALL : Grid = MAXGRID/4;	 break;
		case MEDIUM: Grid = MAXGRID/2;	 break;
		case LARGE : Grid = MAXGRID/1.5; break;
		case XLARGE: Grid = MAXGRID;     break;
	}

	if(prevGrid > Grid) reset(ResetMode);

	ZNear = Grid/10.0;
	ZFar  = Grid*3.0;
	Sdepth = 5.0/4.0 * Grid;
	getTexCoords();
	glutPostRedisplay();
}
void TextureBackground::clear(DrawEnv  *pEnv)
{
#if !defined(OSG_OGL_COREONLY) || defined(OSG_CHECK_COREONLY)
    TextureBaseChunk *tex = getTexture();

    if(tex == NULL)
    {
        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        return;
    }

    glPushAttrib(GL_POLYGON_BIT | GL_DEPTH_BUFFER_BIT | 
                 GL_LIGHTING_BIT);

    glDisable(GL_LIGHTING);

#if 1
    // original mode
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
#else
    // for testing the grid
    glColor3f(1.0f, 1.0f, 1.0f);
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
#endif
    glClear(GL_DEPTH_BUFFER_BIT);

    glDisable(GL_DEPTH_TEST);
    glDepthFunc(GL_ALWAYS);
    glDepthMask(GL_FALSE);

    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    glLoadIdentity();

    glMatrixMode(GL_PROJECTION);
    glPushMatrix();

    glLoadIdentity();
    glOrtho(0, 1, 0, 1, 0, 1);

    glColor4fv(getColor().getValuesRGBA());

    tex->activate(pEnv);

    if(tex->isTransparent())
    {
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        glEnable(GL_BLEND);
    }
    if(osgAbs(getRadialDistortion()) < TypeTraits<Real32>::getDefaultEps())
    {
	    if(getMFTexCoords()->size() < 4)
	    {
	        // set some default texture coordinates.
	        glBegin(GL_QUADS);
                glTexCoord2f(0.0f, 0.0f);
                glVertex3f(0.0f, 0.0f, 0.0f);
                glTexCoord2f(1.0f, 0.0f);
                glVertex3f(1.0f, 0.0f, 0.0f);
                glTexCoord2f(1.0f, 1.0f);
                glVertex3f(1.0f, 1.0f, 0.0f);
                glTexCoord2f(0.0f, 1.0f);
                glVertex3f(0.0f, 1.0f, 0.0f);
	        glEnd();
	    }
	    else
	    {
	        glBegin(GL_QUADS);
            {
                glTexCoord2f(getTexCoords(0).getValues()[0],
                             getTexCoords(0).getValues()[1]);
                glVertex3f(0.0f, 0.0f, 0.0f);
                glTexCoord2f(getTexCoords(1).getValues()[0],
                             getTexCoords(1).getValues()[1]);
                glVertex3f(1.0f, 0.0f, 0.0f);
                glTexCoord2f(getTexCoords(2).getValues()[0],
                             getTexCoords(2).getValues()[1]);
                glVertex3f(1.0f, 1.0f, 0.0f);
                glTexCoord2f(getTexCoords(3).getValues()[0],
                             getTexCoords(3).getValues()[1]);
                glVertex3f(0.0f, 1.0f, 0.0f);
            }
	        glEnd();
	    }
    }
    else // map texture to distortion grid
    {
        updateGrid();
	    Int16 xxmax=getHor()+2,yymax=getVert()+2;

	    UInt32 gridCoords=xxmax*yymax;
	    UInt32 indexArraySize=xxmax*((getVert()+1)*2);

	    if(_vertexCoordArray.size()==gridCoords &&
	       _textureCoordArray.size()==gridCoords &&
	       _indexArray.size()==indexArraySize)
	    {
	        // clear background, because possibly the distortion grid 
            // could not cover th whole window
	        glClearColor(.5f, 0.5f, 0.5f, 1.0f);
	        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	        std::vector<UInt32>::iterator i;
	        UInt32 yMax=getVert()+1;
	        for(UInt32 y=0;y<yMax;y++)
	        {
		        glBegin(GL_TRIANGLE_STRIP);
		        std::vector<UInt32>::iterator begin=_indexArray.begin()+(y*2*xxmax);
		        std::vector<UInt32>::iterator end=begin+2*xxmax;
		        for(std::vector<UInt32>::iterator i=begin;i!=end;i++)
		        {
		            glTexCoord2fv(_textureCoordArray[*i].getValues());
		            glVertex2fv(_vertexCoordArray[*i].getValues());

		        }
		        glEnd();
	        }
	    }
    }
    if(tex->isTransparent())
    {
        glDisable(GL_BLEND);
    }

    tex->deactivate(pEnv);

    Int32 bit = getClearStencilBit();
    
    if (bit >= 0)
    {
        glClearStencil(bit);
        glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    }
    else
    {
        glClear(GL_DEPTH_BUFFER_BIT);
    }

    glPopMatrix();
    glMatrixMode(GL_MODELVIEW);
    glPopMatrix();

    glPopAttrib();

    glColor3f(1.0f, 1.0f, 1.0f);
#endif
}
Example #26
0
		void UpdateModelTexCoordsFromHeading(float* tex_array, bool activ, float currX, float currY, float desiredX, float desiredY) {
			seg9 = setHeadingAndSeg9(activ, currX, currY, desiredX, desiredY);
			float* textCoods = getTexCoords(seg9);
			memcpy(tex_array, textCoods, sizeof(float)*12);	
		}
Example #27
0
void Font::read(const void * data, size_t size) {
  std::istringstream in(std::string(static_cast<const char*>(data), size));
//  SignedDistanceFontFile sdff;
//  sdff.read(in);

  uint8_t header[4];
  readStream(in, header);
  if (memcmp(header, "SDFF", 4)) {
    FAIL("Bad font file");
  }

  uint16_t version;
  readStream(in, version);

  // read font name
  if (version > 0x0001) {
    char c;
    readStream(in, c);
    while (c) {
      mFamily += c;
      readStream(in, c);
    }
  }

  // read font data
  readStream(in, mLeading);
  readStream(in, mAscent);
  readStream(in, mDescent);
  readStream(in, mSpaceWidth);
  mFontSize = mAscent + mDescent;

  // read metrics data
  mMetrics.clear();

  uint16_t count;
  readStream(in, count);

  for (int i = 0; i < count; ++i) {
    uint16_t charcode;
    readStream(in, charcode);
    Metrics & m = mMetrics[charcode];
    readStream(in, m.ul.x);
    readStream(in, m.ul.y);
    readStream(in, m.size.x);
    readStream(in, m.size.y);
    readStream(in, m.offset.x);
    readStream(in, m.offset.y);
    readStream(in, m.d);
    m.lr = m.ul + m.size;
  }

  // read image data
  readPngToTexture((const char *) data + in.tellg(), size - in.tellg(),
      mTexture, mTextureSize);

  std::vector<TextureVertex> vertexData;
  std::vector<GLuint> indexData;
  float texH = 0, texW = 0, texA = 0;
  int characters = 0;
  std::for_each(mMetrics.begin(), mMetrics.end(),
      [&] ( MetricsData::reference & md ) {
        uint16_t id = md.first;
        Font::Metrics & m = md.second;
        ++characters;
        GLuint index = (GLuint)vertexData.size();
        rectf bounds = getBounds(m, mFontSize);
        rectf texBounds = getTexCoords(m);

        QuadBuilder qb(bounds, texBounds);
        for (int i = 0; i < 4; ++i) {
          vertexData.push_back(qb.vertices[i]);
        }

        m.indexOffset = indexData.size();
        indexData.push_back(index + 0);
        indexData.push_back(index + 1);
        indexData.push_back(index + 2);
        indexData.push_back(index + 0);
        indexData.push_back(index + 2);
        indexData.push_back(index + 3);
      });

  gl::VertexBufferPtr vertexBuffer(new gl::VertexBuffer(vertexData));
  gl::IndexBufferPtr indexBuffer(new gl::IndexBuffer(indexData));
  mGeometry = gl::GeometryPtr(
      new gl::Geometry(vertexBuffer, indexBuffer, characters * 2,
          gl::Geometry::Flag::HAS_TEXTURE));
  mGeometry->buildVertexArray();
}