ofDrawBitmapString(); doesn't rotate

I noticed one thing, that in vanderlin’s vimeo video of box2d.
there’s an example where random chars from an string is attached to a box2d
object and when it rotates the text rotates.

I’ve built that demo myself (the one with Custom Data) and on Linux/Ubuntu 12.10
the letters doesn’t rotate they just … goes in circular motion.

is this a linux bug?

i’ve done some tests myself with ofPopMatrix() and ofPushMatrix(), and ofRotateZ() and it rotates fine except the ofDrawBitmapString() text.

I am fairly new to c++ and openframeworks maybe someone else on linux could check this out.

1 Like

i don’t think this is related to linux but to how bitmap text is drawn. the origin for bitmap string characters is the baseline of the letter so if you want to make them rotate around their center you’ll need to translate a little bit higher to the center of the letter before using rotation then translate back to 0,0 before drawing

ok, but even if their individual centers are at baseline of a character. at some time that character must rotate upside down, mine doesn’t they just go round and round but always right way up.

can you post some code and a screenshot?

  
ofPushMatrix();  
	ofTranslate(300, 300, 0);  
	ofRotateZ(45);  
  
	ofDrawBitmapStringHighlight("BitmapString", 0, 0);  
  
	ofPopMatrix();  
  
	ofDrawBitmapStringHighlight("hello", 200, 200);  

mmh, ok that’s actually a different function, ofDrawBitmapString should work, i’m going to report an issue in github

yeah just to make it clear, it’s probably a bug on linux.

oh it’s on github, now I know :smiley: I can file reports myself in the future when I’m comfortable with oF.

is it working ok on other OS’s? that code should be platform independent

Hi all,

Any news on this? I couldn’t find the issue on Github. I’m really hoping to use this on a project in the very near future. I’ll try to investigate if you can point me in the right direction.

Thanks.

was just working with this, ofDrawBitmapString is actually rotation independent by default. you can use ofSetDrawBitmapMode(OF_BITMAPMODE_MODEL) to change it to be affected by transformations

Hmm… That fixed the rotation issue, but now the text renders upside down. Ideas? Looks like this has happened before…

EDIT: I figured out how to fix it.
It is similar to this issue here:
https://github.com/openframeworks/openFrameworks/issues/1474

I am not using ofFbo. Anyway, changing line 1115 https://github.com/openframeworks/openFrameworks/blob/master/libs/openFrameworks/gl/ofGLRenderer.cpp#L1115

to ofScale(1,1,0) seemed to do the trick.

I should file a bug report I guess?

thanks i’m fixing all this issues related to orientation, so will fix this too. instead, can you file a bug explaining that the default behaviour is confusing

thanks, arturo I see you’re from barcelona. That handle arturo I think I’ve seen before. Are you perhaps involved in development of offline render engines? like YAFRAY or YAFARAY?

Anyways thanks for fixing it, and thanks pushpop for a workaround!

Are you perhaps involved in development of offline render engines? like YAFRAY or YAFARAY?

no : )

Hi arturo,
I found it is interesting that ofDrawBitmapString() won’t rotate no matter how I use mouse to rotate the ofEasyCam, and it is exactly what I want to do!
However, I plan to use some Chinese characters, and found that ofDrawBitmapString() cannot support Chinese character, but ofTrueTypeFont can. But ofTrueTypeFont is affected by transformation.

Is there any way I can play with Chinese characters and won’t let it affected by transformation like ofDrawBitmapString() at the same time?

Many thanks!

this is the code that we use in the OF core to draw bitmap strings without being affected by transformations:

			auto rViewport = getCurrentViewport();
			
			auto mat = matrixStack.getProjectionMatrixNoOrientation()  * matrixStack.getModelViewMatrix();
			auto dScreen4 = mat * glm::vec4(x,y,z,1.0);
			auto dScreen = dScreen4.xyz() / dScreen4.w;
			dScreen += glm::vec3(1.0) ;
			dScreen *= 0.5;
			
			dScreen.x += rViewport.x;
			dScreen.x *= rViewport.width;

			dScreen.y += rViewport.y;
			dScreen.y *= rViewport.height;
			
			if (dScreen.z >= 1) return;


			ofMatrixMode(OF_MATRIX_PROJECTION);
			ofPushMatrix();
			ofLoadIdentityMatrix();

			ofMatrixMode(OF_MATRIX_MODELVIEW);
			ofPushMatrix();

			auto modelView = glm::translate(modelView, glm::vec3(-1,-1,0));
			modelView = glm::scale(modelView, glm::vec3(2/rViewport.width, 2/rViewport.height, 1));
			modelView = glm::translate(modelView, glm::vec3(dScreen.x, dScreen.y, 0));
			ofLoadMatrix(modelView);
			ofPopMatrix();


			ofMatrixMode(OF_MATRIX_PROJECTION);
			ofPopMatrix();
			ofMatrixMode(OF_MATRIX_MODELVIEW);

more or less it finds out the 2d projection of the 3d point where you are drawing the text and draws it in that 2d position;

if you are using a camera then it’s probably easier to just use camera.worldToScreen(pos) and draw the text at that 2d position (outside of camera begin/end)

1 Like

Hi arturo,

Thanks for the answer. I tried to combine the code you found with my project but failed. It shows Call to implicitly-deleted default constructor of 'ofApp' on the line “ofRunApp(new ofApp());” in the main.cpp page.

if I comment out the part (in the draw() function part ), the error would disappear.

what I want to achieve is: make the Chinese Character (ofTrueTypeFont) won’t affected by transformation, just like the “hello” and “welcome” (ofDrawBitmapString()) in the gif above

Many thanks!

ofApp.h

class ofApp : public ofBaseApp{
    
public:

....

//------- random postion vector
    vector <glm::vec3> randomPositions;
    float totalNum;
    float range;
    
    //------- font
    ofTrueTypeFont hongdao;
    
    //------- matrix
    ofMatrixStack matrixStack;
    const ofAppBaseWindow * window;
};

ofApp.cpp

(in setup() )

void ofApp::setup(){
totalNum = 5;
    range = 200;
    for(int i = 0; i < totalNum; i++){
        randomPositions.push_back(glm::vec3(ofRandom(-range,range), ofRandom(-range,range), ofRandom(-range,range)));
    }
    
    //------- fonts
    hongdao.load("hongdao.ttf", 30);
    
    ofTtfSettings settings("hongdao.ttf", 20);
    settings.antialiased = true;
    settings.addRange(ofUnicode::Latin1Supplement);
    settings.addRange(ofUnicode::Hiragana);
    settings.addRange(ofUnicode::Katakana);
    settings.addRange(ofUnicode::CJKUnified);
    settings.addRange(ofUnicode::Space);
    settings.addRange(ofUnicode::CJKLettersAndMonths);
    hongdao.load(settings);
 
    //-------- matrixStack
    matrixStack.setRenderSurface(*window);
}

(in draw() )

void ofApp::draw(){
    ofSetColor(255,255);
    
//    ofRectangle rViewport;
//    glm::mat4 modelView;
//    rViewport = ofGetCurrentViewport();
//    auto mat = matrixStack.getProjectionMatrixNoOrientation()  * matrixStack.getModelViewMatrix();
//    auto dScreen4 = mat * glm::vec4(randomPositions[0].x, randomPositions[0].y, randomPositions[0].z, 1.0);
//    auto dScreen = dScreen4.xyz() / dScreen4.w;
//    dScreen += glm::vec3(1.0) ;
//    dScreen *= 0.5;
//
//    dScreen.x += rViewport.x;
//    dScreen.x *= rViewport.width;
//
//    dScreen.y += rViewport.y;
//    dScreen.y *= rViewport.height;
//
//    if (dScreen.z >= 1) return;
//
//    ofMatrixMode(OF_MATRIX_PROJECTION);
//    ofPushMatrix();
//    ofLoadIdentityMatrix();
//
//    ofMatrixMode(OF_MATRIX_MODELVIEW);
//    ofPushMatrix();
//
//    modelView = glm::translate(modelView, glm::vec3(-1,-1,0));
//    modelView = glm::scale(modelView, glm::vec3(2/rViewport.width, 2/rViewport.height, 1));
//    modelView = glm::translate(modelView, glm::vec3(dScreen.x, dScreen.y, 0));
//    ofLoadMatrix(modelView);
//    
//    ofPopMatrix();
//    //ofMatrixMode(OF_MATRIX_PROJECTION); //error redefinition
//    ofPopMatrix();
//    //ofMatrixMode(OF_MATRIX_MODELVIEW);  //error redefinition


    
    ofPushMatrix();
    ofTranslate(randomPositions[0]);
    hongdao.drawString("操",0, 0);
    ofPopMatrix();

    ofPushMatrix();
    ofTranslate(randomPositions[1]);
    hongdao.drawString("你", 0,0);
    ofPopMatrix();

    ofPushMatrix();
    ofDrawBitmapString("hello", randomPositions[3]);
    ofPopMatrix();

    ofPushMatrix();
    ofDrawBitmapString("welcome", randomPositions[4]);
    ofPopMatrix();

    cam.end();
}