void ofxTexture3d::allocate(int w, int h, int d, int internalGlDataType) { texData.tex_w = w; texData.tex_h = h; texData.tex_d = d; texData.tex_t = w; texData.tex_u = h; texData.tex_v = d; texData.textureTarget = GL_TEXTURE_3D; texData.glTypeInternal = internalGlDataType; // get the glType (format) and pixelType (type) corresponding to the glTypeInteral (internalFormat) texData.glType = ofGetGLFormatFromInternal(texData.glTypeInternal); texData.pixelType = ofGetGlTypeFromInternal(texData.glTypeInternal); // attempt to free the previous bound texture, if we can: clear(); glGenTextures(1, (GLuint *)&texData.textureID); retain(texData.textureID); glEnable(texData.textureTarget); glBindTexture(texData.textureTarget, (GLuint)texData.textureID); glTexImage3D(texData.textureTarget, 0, texData.glTypeInternal, (GLint)texData.tex_w, (GLint)texData.tex_h, (GLint)texData.tex_d, 0, texData.glType, texData.pixelType, 0); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_REPEAT); //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glDisable(texData.textureTarget); texData.width = w; texData.height = h; texData.depth = d; texData.bFlipTexture = false; texData.bAllocated = true; }
void ofTexture::allocate(const ofTextureData & textureData){ allocate(textureData,ofGetGLFormatFromInternal(textureData.glInternalFormat),ofGetGlTypeFromInternal(textureData.glInternalFormat)); }
//---------------------------------------------------------- void ofTexture::allocate(int w, int h, int glInternalFormat, bool bUseARBExtension){ allocate(w, h, glInternalFormat, bUseARBExtension, ofGetGLFormatFromInternal(glInternalFormat), ofGetGlTypeFromInternal(glInternalFormat)); }
//---------------------------------------------------------- void ofTexture::allocate(int w, int h, int glInternalFormat){ allocate(w, h, glInternalFormat, ofGetUsingArbTex(), ofGetGLFormatFromInternal(glInternalFormat), ofGetGlTypeFromInternal(glInternalFormat)); }
//---------------------------------------------------------- void ofTexture::copyTo(ofBufferObject & buffer) const{ ofSetPixelStoreiAlignment(GL_PACK_ALIGNMENT,getWidth(),ofGetBytesPerChannelFromGLType(ofGetGlTypeFromInternal(texData.glInternalFormat)),ofGetNumChannelsFromGLFormat(ofGetGLFormatFromInternal(texData.glInternalFormat))); buffer.bind(GL_PIXEL_PACK_BUFFER); glBindTexture(texData.textureTarget,texData.textureID); glGetTexImage(texData.textureTarget,0,ofGetGLFormatFromInternal(texData.glInternalFormat),ofGetGlTypeFromInternal(texData.glInternalFormat),0); glBindTexture(texData.textureTarget,0); buffer.unbind(GL_PIXEL_PACK_BUFFER); }
//---------------------------------------------------------- void ofTexture::allocate(int w, int h, int internalGlDataType, bool bUseARBExtention){ allocate(w, h, internalGlDataType, bUseARBExtention, ofGetGLFormatFromInternal(internalGlDataType), ofGetGlTypeFromInternal(internalGlDataType)); }
//---------------------------------------------------------- void ofTexture::allocate(int w, int h, int internalGlDataType){ allocate(w, h, internalGlDataType, ofGetUsingArbTex(), ofGetGLFormatFromInternal(internalGlDataType), ofGetGlTypeFromInternal(internalGlDataType)); }
//---------------------------------------------------------- void ofFbo::copyTo(ofBufferObject & buffer) const{ if(!bIsAllocated) return; bind(); buffer.bind(GL_PIXEL_PACK_BUFFER); glReadPixels(0, 0, settings.width, settings.height, ofGetGLFormatFromInternal(settings.internalformat), ofGetGlTypeFromInternal(settings.internalformat), NULL); buffer.unbind(GL_PIXEL_PACK_BUFFER); unbind(); }
//----------------------------------------------------------- bool ofxSosoTrueTypeFont::loadFont(string filename, int fontsize, bool _bAntiAliased, bool _bFullCharacterSet, bool makeContours, bool makeMipMaps, float simplifyAmt, int dpi){ //soso - added makeMipMaps (see below) bMakeContours = makeContours; //------------------------------------------------ if (bLoadedOk == true){ // we've already been loaded, try to clean up : unloadTextures(); } //------------------------------------------------ if( dpi == 0 ){ dpi = ttfGlobalDpi; } filename = ofToDataPath(filename); bLoadedOk = false; bAntiAliased = _bAntiAliased; bFullCharacterSet = _bFullCharacterSet; fontSize = fontsize; //--------------- load the library and typeface FT_Error err; FT_Library library; if (err = FT_Init_FreeType( &library )){ ofLog(OF_LOG_ERROR,"ofTrueTypeFont::loadFont - Error initializing freetype lib: FT_Error = %d", err); return false; } FT_Face face; if (err = FT_New_Face( library, filename.c_str(), 0, &face )) { // simple error table in lieu of full table (see fterrors.h) string errorString = "unknown freetype"; if(err == 1) errorString = "INVALID FILENAME"; ofLog(OF_LOG_ERROR,"ofTrueTypeFont::loadFont - %s: %s: FT_Error = %d", errorString.c_str(), filename.c_str(), err); return false; } //FT_Set_Char_Size( face, fontsize << 6, fontsize << 6, dpi, dpi); //of //FT_Set_Char_Size( face, 0, fontsize*dpi, 0, dpi); //soso FT_Set_Char_Size( face, 0, fontsize*64, 0, dpi); //soso lineHeight = fontsize * 1.43f; //------------------------------------------------------ //kerning would be great to support: //ofLog(OF_LOG_NOTICE,"FT_HAS_KERNING ? %i", FT_HAS_KERNING(face)); //------------------------------------------------------ //nCharacters = bFullCharacterSet ? 256 : 128 - NUM_CHARACTER_TO_START; nCharacters = bFullCharacterSet ? 512 : 128 - NUM_CHARACTER_TO_START; //--------------- initialize character info and textures cps.resize(nCharacters); if(bMakeContours){ charOutlines.clear(); charOutlines.assign(nCharacters, ofTTFCharacter()); } vector<ofPixels> expanded_data(nCharacters); long areaSum=0; //--------------------- load each char ----------------------- for (int i = 0 ; i < nCharacters; i++){ //------------------------------------------ anti aliased or not: //if(err = FT_Load_Glyph( face, FT_Get_Char_Index( face, (unsigned char)(i+NUM_CHARACTER_TO_START) ), FT_LOAD_DEFAULT )){ if(err = FT_Load_Glyph( face, getFTCharIndex( face, (unsigned char)(i+NUM_CHARACTER_TO_START) ), FT_LOAD_DEFAULT )){ //soso replaced FT_Get_Char_Index with our custom version ofLog(OF_LOG_ERROR,"ofTrueTypeFont::loadFont - Error with FT_Load_Glyph %i: FT_Error = %d", i, err); } if (bAntiAliased == true) FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL); else FT_Render_Glyph(face->glyph, FT_RENDER_MODE_MONO); //------------------------------------------ FT_Bitmap& bitmap= face->glyph->bitmap; // prepare the texture: //int width = ofNextPow2( bitmap.width + border*2 ); // int height = ofNextPow2( bitmap.rows + border*2 ); //// ------------------------- this is fixing a bug with small type //// ------------------------- appearantly, opengl has trouble with //// ------------------------- width or height textures of 1, so we //// ------------------------- we just set it to 2... //if (width == 1) width = 2; //if (height == 1) height = 2; if(bMakeContours){ if( printVectorInfo )printf("\n\ncharacter %c: \n", char( i+NUM_CHARACTER_TO_START ) ); //int character = i + NUM_CHARACTER_TO_START; charOutlines[i] = makeContoursForCharacter( face ); if(simplifyAmt>0) charOutlines[i].simplify(simplifyAmt); charOutlines[i].getTessellation(); } // ------------------------- // info about the character: cps[i].character = i; cps[i].height = face->glyph->bitmap_top; cps[i].width = face->glyph->bitmap.width; cps[i].setWidth = face->glyph->advance.x >> 6; cps[i].topExtent = face->glyph->bitmap.rows; cps[i].leftExtent = face->glyph->bitmap_left; int width = cps[i].width; int height = bitmap.rows; cps[i].tW = width; cps[i].tH = height; GLint fheight = cps[i].height; GLint bwidth = cps[i].width; GLint top = cps[i].topExtent - cps[i].height; GLint lextent = cps[i].leftExtent; GLfloat corr, stretch; //this accounts for the fact that we are showing 2*visibleBorder extra pixels //so we make the size of each char that many pixels bigger stretch = 0;//(float)(visibleBorder * 2); corr = (float)(( (fontSize - fheight) + top) - fontSize); cps[i].x1 = lextent + bwidth + stretch; cps[i].y1 = fheight + corr + stretch; cps[i].x2 = (float) lextent; cps[i].y2 = -top + corr; // Allocate Memory For The Texture Data. expanded_data[i].allocate(width, height, 2); //-------------------------------- clear data: expanded_data[i].set(0,255); // every luminance pixel = 255 expanded_data[i].set(1,0); if (bAntiAliased == true){ ofPixels bitmapPixels; bitmapPixels.setFromExternalPixels(bitmap.buffer,bitmap.width,bitmap.rows,1); expanded_data[i].setChannel(1,bitmapPixels); } else { //----------------------------------- // true type packs monochrome info in a // 1-bit format, hella funky // here we unpack it: unsigned char *src = bitmap.buffer; for(int j=0; j <bitmap.rows;j++) { unsigned char b=0; unsigned char *bptr = src; for(int k=0; k < bitmap.width ; k++){ expanded_data[i][2*(k+j*width)] = 255; if (k%8==0){ b = (*bptr++); } expanded_data[i][2*(k+j*width) + 1] = b&0x80 ? 255 : 0; b <<= 1; } src += bitmap.pitch; } //----------------------------------- } areaSum += (cps[i].width+border*2)*(cps[i].height+border*2); } vector<charProps> sortedCopy = cps; sort(sortedCopy.begin(),sortedCopy.end(),&compare_cps); // pack in a texture, algorithm to calculate min w/h from // http://upcommons.upc.edu/pfc/bitstream/2099.1/7720/1/TesiMasterJonas.pdf //cout << areaSum << endl; bool packed = false; float alpha = logf(areaSum)*1.44269; int w; int h; while(!packed){ w = pow(2,floor((alpha/2.f) + 0.5)); // there doesn't seem to be a round in cmath for windows. //w = pow(2,round(alpha/2.f)); h = w;//pow(2,round(alpha - round(alpha/2.f))); int x=0; int y=0; int maxRowHeight = sortedCopy[0].tH + border*2; for(int i=0;i<(int)cps.size();i++){ if(x+sortedCopy[i].tW + border*2>w){ x = 0; y += maxRowHeight; maxRowHeight = sortedCopy[i].tH + border*2; if(y + maxRowHeight > h){ alpha++; break; } } x+= sortedCopy[i].tW + border*2; if(i==(int)cps.size()-1) packed = true; } } ofPixels atlasPixels; atlasPixels.allocate(w,h,2); atlasPixels.set(0,255); atlasPixels.set(1,0); int x=0; int y=0; int maxRowHeight = sortedCopy[0].tH + border*2; for(int i=0;i<(int)cps.size();i++){ ofPixels & charPixels = expanded_data[sortedCopy[i].character]; if(x+sortedCopy[i].tW + border*2>w){ x = 0; y += maxRowHeight; maxRowHeight = sortedCopy[i].tH + border*2; } cps[sortedCopy[i].character].t2 = float(x + border)/float(w); cps[sortedCopy[i].character].v2 = float(y + border)/float(h); cps[sortedCopy[i].character].t1 = float(cps[sortedCopy[i].character].tW + x + border)/float(w); cps[sortedCopy[i].character].v1 = float(cps[sortedCopy[i].character].tH + y + border)/float(h); charPixels.pasteInto(atlasPixels,x+border,y+border); x+= sortedCopy[i].tW + border*2; } texAtlas.allocate(atlasPixels.getWidth(),atlasPixels.getHeight(),GL_LUMINANCE_ALPHA,false); if(bAntiAliased && fontsize>20){ if (makeMipMaps) { //soso //texAtlas.enableMipmaps(); //texAtlas.setTextureMinMagFilter(GL_LINEAR_MIPMAP_LINEAR,GL_LINEAR_MIPMAP_LINEAR); //soso } else //soso texAtlas.setTextureMinMagFilter(GL_LINEAR,GL_LINEAR); }else{ texAtlas.setTextureMinMagFilter(GL_NEAREST,GL_NEAREST); } texAtlas.loadData(atlasPixels.getPixels(),atlasPixels.getWidth(),atlasPixels.getHeight(),GL_LUMINANCE_ALPHA); ///////////////////////////////////////////////////////////////////////sosoAddon //until ofTexture fully supports mipmaps, we gotta do it manually here - AFTER loadData is called on the texture //it's a redo of what happens inside tex.loadData(), but instead we build the mipmaps if(makeMipMaps){ glEnable(texAtlas.getTextureData().textureTarget); glBindTexture(texAtlas.getTextureData().textureTarget, (GLuint) texAtlas.getTextureData().textureID); glTexParameteri(texAtlas.getTextureData().textureTarget, GL_GENERATE_MIPMAP_SGIS, true); glTexParameteri( texAtlas.getTextureData().textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri( texAtlas.getTextureData().textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri( texAtlas.getTextureData().textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri( texAtlas.getTextureData().textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR); gluBuild2DMipmaps(texAtlas.getTextureData().textureTarget, texAtlas.getTextureData().glTypeInternal, w, h, texAtlas.getTextureData().glTypeInternal, ofGetGlTypeFromInternal(texAtlas.getTextureData().glTypeInternal), atlasPixels.getPixels()); glDisable(texAtlas.getTextureData().textureTarget); } ////////////////////////////////////////////////////////////////////// //Sosolimited - load kerning pairs //initialize all pairs to 0 for (int i = 0; i < FONT_NUM_CHARS; i++) { for (int j = 0; j < FONT_NUM_CHARS; j++) { kerningPairs[i][j] = 0; } } //find out if the face has kerning FT_Bool use_kerning = (FT_Bool)FT_HAS_KERNING(face); if(!use_kerning) printf("ofxSosoTrueTypeFont::loadFont() - kerning is NOT supported for %s\n", (char*)filename.c_str()); FT_UInt glyph_index_r, glyph_index_l; for (int i = 0; i < FONT_NUM_CHARS; i++) { // convert character code to glyph index glyph_index_r = FT_Get_Char_Index(face, i + NUM_CHARACTER_TO_START); for (int j = 0; j < FONT_NUM_CHARS; j++) { // convert character code to glyph index glyph_index_l = FT_Get_Char_Index(face, j + NUM_CHARACTER_TO_START); // retrieve kerning distance if (use_kerning && glyph_index_l && glyph_index_r) { FT_Vector delta; FT_Get_Kerning( face, glyph_index_l, glyph_index_r, FT_KERNING_DEFAULT, &delta ); kerningPairs[i][j] = delta.x >> 6; //if(i<127) //if(fabs((float)kerningPairs[i][j]) > 0) printf("kerningPairs: %c%c = %d, delta = %d\n", i + NUM_CHARACTER_TO_START, j + NUM_CHARACTER_TO_START, kerningPairs[i][j], delta.x); } } }