Help in applying texture to a circular ofMesh

Hello everyone,

Can anyone help me applying a texture to circular ofMesh?

Here is the code that I have so far:

ofApp.h:

class ofApp : public ofBaseApp{

public:
	void setup();
	void update();
	void draw();

	void keyPressed(int key);
	void keyReleased(int key);
	void mouseMoved(int x, int y );
	void mouseDragged(int x, int y, int button);
	void mousePressed(int x, int y, int button);
	void mouseReleased(int x, int y, int button);
	void windowResized(int w, int h);
	void dragEvent(ofDragInfo dragInfo);
	void gotMessage(ofMessage msg);

    //____________________________________

    ofImage texture;
    ofMesh mesh;
	
};

ofApp.cpp:

#include "ofApp.h"



void ofApp::setup(){
    
texture.loadImage("tex.png");
texture.getTextureReference().setTextureMinMagFilter(GL_NEAREST, GL_NEAREST);
texture.getTextureReference().setTextureWrap(GL_REPEAT, GL_REPEAT);

mesh.setMode(OF_PRIMITIVE_TRIANGLE_STRIP);

int nPts  = 20;
int r = 100;

ofVec2f center=ofVec2f(ofGetWidth()/2, ofGetHeight()/2);

float scale = r / (float)texture.getWidth();
for (int i=0; i<nPts; i++) {
    
    
    float n = ofMap(i, 0, nPts-1, 0.0, TWO_PI);
    float x = sin(n);
    float y = cos(n);

    mesh.addVertex(center);
    mesh.addVertex(ofPoint(center.x + (x * r), center.y + (y * r)));
    
    mesh.addTexCoord(ofPoint(0, 0));
    mesh.addTexCoord(ofPoint(x * scale, y * scale));
}



}

//--------------------------------------------------------------
void ofApp::draw(){
    
ofSetColor(255);
texture.bind();
mesh.draw();
texture.unbind();

ofSetColor(0);
mesh.drawWireframe();

}

here is the output I have so far, what am I doing wrong? I suspect it has to do with “mesh.addTexCoord()”

Thanks in advance,
J

In setup() before load the image put ofDisableArbTex();

Hope this help :smile:

Thanks @Dorald It did something, but still not the result that I expected, here is a screenshot

any ideas?

There are several problems / possible improvements with your code. To name a few:

  • After you call ofDisableArbTex(), you should use normalized (0 to 1) texture coordinates.
  • The texture coordinates of the center are not (0, 0), but rather (0.5, 0.5).
  • The calculated xy values are in the range (-1, 1) and should be remapped to the range (0, 1).
  • For this shape it’s more efficient to use an OF_PRIMITIVE_TRIANGLE_FAN.

Here is the adapted code:

ofApp.h:

#pragma once

#include "ofMain.h"

class ofApp : public ofBaseApp {

    public:
        void setup();
        void update();
        void draw();

        ofImage texture;
        ofMesh mesh;
        ofEasyCam cam;
};

ofApp.cpp:

#include "ofApp.h"

//--------------------------------------------------------------
void ofApp::setup(){
    ofEnableDepthTest();
    ofBackground(0);

    ofDisableArbTex();
    texture.loadImage("tex.png");
    texture.getTextureReference().setTextureMinMagFilter(GL_NEAREST, GL_NEAREST);
    texture.getTextureReference().setTextureWrap(GL_REPEAT, GL_REPEAT);

    int nPts = 20;
    int r = 200;

    mesh.setMode(OF_PRIMITIVE_TRIANGLE_FAN);

    mesh.addVertex(ofVec2f());
    mesh.addTexCoord(ofPoint(0.5, 0.5));
    int scale = 10;

    for(int i = 0; i < nPts; i++){
        float n = ofMap(i, 0, nPts - 1, 0.0, TWO_PI);
        float x = sin(n);
        float y = cos(n);
        mesh.addVertex(ofPoint(x * r, y * r));
        mesh.addTexCoord(ofPoint((x * scale + 1) / 2, (y * scale + 1) / 2));
    }

    cam.setVFlip(true);
}

//--------------------------------------------------------------
void ofApp::update(){

}

//--------------------------------------------------------------
void ofApp::draw(){
    cam.begin();

    ofSetColor(0);
    mesh.drawWireframe();

    ofSetColor(255);
    texture.bind();
    mesh.draw();
    texture.unbind();

    cam.end();
}

awesome @ammon, thanks a lot…

Hey @jftf

Can you share which command/correction renders the texture correctly?
I agree with @amnon suggestions, but if I use you code and just add ofDisableArbTex(), it’s enough to render it correctly. I would like to understand why you get that error.

Abraço.

Hey @hubris, In my first code I wasn’t adding the text coordinates correctly, the following suggestions from ammon, did the trick:

  • The texture coordinates of the center are not (0, 0), but rather (0.5, 0.5).
  • The calculated xy values are in the range (-1, 1) and should be remapped to the range (0, 1).

Yes, the mapping and range is offset. But even so, I get this result:

And you get everything scrambled…

It would be cool to know why, because this kind of things happen when you work in one computer but then deliver in another. Thanks for the reply. :slight_smile:

Interesting, I have a completely different result.
Now I’m curious why!?

Which Primitive are using in mesh.setMode() ?

Nice tile, btw :wink:

@hubris @jftf
The thing is that if you combine a) the wrong center texture coordinates with b) the wrong, unmapped texture coordinates for each vertex but c) you do use REPEAT, it might also give a result that appears correct visually.

However, if you remove the REPEAT in this scenario, you will probably notice that it all falls apart. The code I posted above, will behave correctly, even when REPEAT is removed (given a sufficiently visible scale). So while I am a supporter of the “whatever works” philosophy, I would not choose that route here, because it may lead to bugs later on.

Absolutely @amnon , thanks a lot for the help and clarifications.

I just came across with another problem. I would like to use a shape instead so I can use curveVertex do draw the shape! I just can’t figure out how to add the texture coordinates to the shape, Is this possible to map a texture to something like:

ofBeginShape();

ofCurveVertex(x,y);
...

ofEndShape();

Thanks,
J

I copy-pasted your code, and just added ofDisableArbTex(). Didn’t change anything, so OF_PRIMITIVE_TRIANGLE_STRIP.

I’m on Mac OS 10.10.2, OF 0.8.4 and my GPU is an AMD Radeon HD 6750M. (I know this GPU as some issues with point sprites.)

@amnon that’s exactly my point, I know how to do it properly but my question is: why does it work either way? Even if I set other wrap mode, it still works. Something related to this GPU that ignores/corrects negative values?

(I know the issue is solved, it’s just pure curiosity. :smiley:)

@jftf
You can’t add texture coordinates to code using of[Begin/End]Shape and ofCurveVertex. As a workaround however, you could draw such a complex shape to an ofFbo and use that ofFbo as a mask. You could implement this basic principle in several different ways manually or you could use one of the available mask ofxAddons.

@hubris
Ah right, that’s pretty strange. I guess a self-correcting GPU is a bit of a blessing in disguise. :grinning:

1 Like

you can also draw the shape using an ofPath, then get the generated mesh and apply the tex coordinates to it like:

//setup
ofPath path;
path.curveTo(...);
path.curveTo(...);
...

mesh = path.getTessellation();
for(auto & v: mesh.getVertices()){
    mesh.addTexCoord(tex.getCoordFromPoint(v.x,v.y));
}

//draw
mesh.draw()
3 Likes

Thanks a lot for the help guys, will try both solutions :slight_smile:

Hi @arturo, I’m trying to implement your method! I got the texture on the shape, But it works more like a mask over the texture. If i move the shape around I can see that the texture is fixed in the background!

What am I missing?

//--------------------------------------------------------------
void ofApp::setup(){
    
    ofBackground(0);
    
    ofDisableArbTex();
    texture.loadImage("tex.png");
    texture.getTextureReference().setTextureMinMagFilter(GL_NEAREST, GL_NEAREST);
    texture.getTextureReference().setTextureWrap(GL_REPEAT, GL_REPEAT);
    
}

//--------------------------------------------------------------
void ofApp::update(){
    
    int resolution = 20;
    int r = 200;
    ofPoint center;
    center.set(mouseX,mouseY);
    
    path.clear();
    mesh.clear();
    
    for(int i = 0; i < resolution; i++){
        
        float n = ofMap(i, 0, resolution - 1, 0.0, TWO_PI);
        float x = sin(n);
        float y = cos(n);
        path.curveTo(ofPoint((x * r)+center.x, (y * r)+center.y));
    }
    
    mesh = path.getTessellation();
    
    ofPoint textCoord;
    for(auto & v: mesh.getVertices()){
        
        textCoord.x=v.x/ofGetWidth();
        textCoord.y=v.y/ofGetHeight();
        
        mesh.addTexCoord(texture.getTextureReference().getCoordFromPoint(v.x,v.y));
    }
    
}

//--------------------------------------------------------------
void ofApp::draw(){
    
    ofPushStyle();
    ofSetColor(255);
    texture.bind();
    mesh.draw();
    texture.unbind();
    ofPopStyle();
}

thank you,
j

if you change the texture coordinate according to the movement of the shape they’ll move too. once you have the correct texture coordinates in the first frame i guess, you’ll need to copy them and reuse them every frame. or somehow reverse the transformation.

I am doing that in the update() with:

 mesh.addTexCoord(texture.getTextureReference().getCoordFromPoint(v.x,v.y));

right?

you would need to substract the translation from the texture coordinates, something like:

    ofPoint textCoord;
    for(auto & v: mesh.getVertices()){
        mesh.addTexCoord(texture.getTextureReference().getCoordFromPoint(v.x - trans.x, v.y - trans.y));
    }

I don’t know why you are doing that in update, in the long run you want to change the shape? Even so, you can either subtract the translation or do something like this… Set always the same center and then:

ofPushStyle();
ofSetColor(255);
ofPushMatrix();
ofTranslate(mouseX, mouseY);
texture.bind();
mesh.draw();
texture.unbind();
ofPopMatrix();
ofPopStyle();