[Help] Problem mapping texture to 3d mesh cylinder

Hi,
I’m trying to map 2d Textures to distorted 3d spheres drawn using ofMesh, but it didn’t work so this is a more stripped down version using a cylindrical shape. some segments draw the shape properly but others don’t. I’m not sure if it’s to do with some depth issue. I can’t seem to upload images which is not helpful but if anyone could help that would be greatly appreciated.

Also if anyone has any ideas as to why mapping the sphere also does not work that would be appreciated.

//.h file
ofImage image;
ofSpherePrimitive sphere;

ofMesh mesh;


 // cpp file
 void ofApp::setup(){
 image.loadImage("moon.jpg");

sphere.set(200, 20);
sphere.setPosition(0, 0, 0);

mesh.clear();
mesh.setMode(OF_PRIMITIVE_TRIANGLES);



int numJ = 6;
int numI = 10;
float r = 100;

    for (int i = 0; i < numI; i++) {
        
         for (int j = 0; j < numJ; j++) {
             
             
             double theta = 360*i/numI;
             theta = ofDegToRad(theta);
             
             

        double x = r * sin(theta);
            // int x = r*i;
        int y = j*100;
         double z = r * cos(theta);
        
        mesh.addVertex(ofVec3f(x,y,z));
        mesh.addTexCoord(ofVec2f(x,y));
             
        
             
     
 
            
    }
}





for (int i = 0; i < numI-1; i++) {
        for (int j = 0; j < numJ-1; j++) {
            
            int n = i * numJ + j;
            
     mesh.addIndex(n);  mesh.addIndex(n+numJ);
     mesh.addIndex(n+1);
            
                                       mesh.addIndex(n+numJ);
    mesh.addIndex(n+1); mesh.addIndex(n+numJ+1);
       
    }
}




  ofEnableDepthTest();
ofDisableAlphaBlending();
ofEnableArbTex();
}
indent preformatted text by 4 spaces

void ofApp::draw(){

ofTranslate(300, 0);
ofRotateY(50*ofGetElapsedTimef());
ofBackground(0);
glPointSize(5);
image.getTextureReference().bind();
//mesh.drawWireframe();
//mesh.drawVertices();

mesh.draw();
image.unbind();

//image.draw(0,0);


}

ofMesh can return a textured sphere mesh.

https://github.com/openframeworks/openFrameworks/blob/master/libs/openFrameworks/3d/ofMesh.cpp#L1587

The texture coordinates will be from 0-1 so you can either call ofDisableArbTex() before loading your texture or you can remap all of the tex coords to match your texture dimensions.
for example:

float imageWidth = image.getWidth();
float imageHeight = image.getHeight();
vector< ofVec2f >& tcoords = mymesh.getTexCoords();
for( int i = 0; i < tcoords.size(); i++ ) {
   tcoords[i].x = ofMap( tcoords[i].x, 0, 1, 0, imageWidth, true );
   tcoords[i].y = ofMap( tcoords[i].y, 0, 1, 0, imageHeight, true );
}

You should also make sure to call ofSetColor( 255, 255, 255 ) before binding your image.

Thanks, but I wanted to generate my own mesh to have more control over vertices, and also just to see if a texture could be mapped on a distorted sphere. Also , I did call ofDisableArbTex() even though it says enable in the example. Also, the sphere doesn’t work either it just gives a uniform colour. It’s only on 3D obj that the mapping does not work properly, on 2d it is fine even the z co-ord is used.

You can manipulate the vertices from the sphere so you don’t have to figure out all of the texture coords yourself.

vector< ofVec3f >& verts = mysphere.getVertices();
for( int i = 0; i < vertis.size(); i++ ) {
     verts[i].x += ofRandom( -10, 10);
     verts[i].z += ofRandom( -10, 10 );
}

The sphere is probably just giving a solid color because there are no lights in the scene.
The 3dPrimitives example (the 4th mode) shows ways to manipulate the vertices with textures.

I’m not sure if I’m doing something wrong with the ofMesh sphere, but it does not draw anything. The ofSpherePrimitive does though and is textured correctly.

And I can post images now so on a cube the front face is ok but the sides only the values from (x,y, 0) all away along, and also the back face uses the pixel info from x, y ,0 also making it a reflection.

on the cylinder

I would just be interested to know the mechanics of why this happens.

Can you post the code you are using?

This is the most stripped down version of mesh mapping I could think of.

//.h

 ofMesh mesh;
ofImage img;
int w,h,d;

ofMesh sphere;

//.cpp

void ofApp::setup(){

w=2;
h=2;
d = 2;

ofVec3f pnts[8];

mesh.setMode(OF_PRIMITIVE_TRIANGLES);

//set verts and texcoords
for (int z = 0; z <2; z++)  {
    for (int i = 0; i < w; i++) {
        for (int j = 0; j < h ; j++) {
        
            int n = i * h  + j + (z * w*h);
        
            pnts[n].x = i*300;
            pnts[n].y = j*300;
            pnts[n].z = z*300;
            
            mesh.addVertex(ofVec3f(pnts[n].x,pnts[n].y,pnts[n].z));
            mesh.addTexCoord(ofVec2f(pnts[n].x,pnts[n].y));
            
        mesh.addColor(ofFloatColor::white);
    }
}
}

// just drew this up quickly so didn't work out a formula for indices but they should 
// be ok
mesh.addIndex(0);mesh.addIndex(1);mesh.addIndex(1);
mesh.addIndex(1);mesh.addIndex(2);mesh.addIndex(3);

mesh.addIndex(2);mesh.addIndex(6);mesh.addIndex(3);
mesh.addIndex(3);mesh.addIndex(6);mesh.addIndex(7);

mesh.addIndex(4);mesh.addIndex(5);mesh.addIndex(6);
mesh.addIndex(6);mesh.addIndex(5);mesh.addIndex(7);

mesh.addIndex(0);mesh.addIndex(4);mesh.addIndex(1);
mesh.addIndex(1);mesh.addIndex(4);mesh.addIndex(5);

mesh.addIndex(0);mesh.addIndex(4);mesh.addIndex(2);
mesh.addIndex(2);mesh.addIndex(4);mesh.addIndex(6);

mesh.addIndex(1);mesh.addIndex(3);mesh.addIndex(5);
mesh.addIndex(3);mesh.addIndex(5);mesh.addIndex(7);


img.loadImage("moon.jpg");

ofDisableArbTex();
ofDisableAlphaBlending();
ofEnableDepthTest();


}

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

}

//--------------------------------------------------------------
void ofApp::draw(){
ofBackground(0, 0, 0);

ofTranslate(300, 300);
ofRotate(10*ofGetElapsedTimef(), 0.5, 1, 0);

img.getTextureReference().bind();
//mesh.drawWireframe();
mesh.draw();
img.getTextureReference().unbind();

}

You must call ofDisableArbTex() before loading the image if you want it to apply to the image. In the code above, it is not affecting the image. But it seems like you don’t want to in this case, since you are setting the tex coords to be from 0 - 300.
I tried both the ofMesh::box and ofMesh::sphere code and they worked as expected with an image that is 1024x1024. Maybe since their tex coords are from 0-1, they weren’t showing up?
Setup function:
ofDisableArbTex();
img.loadImage(“moon.jpg”);
mesh.clear();
mesh = ofMesh::box( 300, 300, 300 );

and

ofDisableArbTex();
img.loadImage("moon.jpg");
mesh.clear();
mesh = ofMesh::sphere( 150 );

the draw function should have a push and pop matrix around the transforms
ofBackground(0, 0, 0);

void ofApp::draw() {
    ofBackground(0, 0, 0);
    
    ofPushMatrix(); {
        ofTranslate(512, 512);
        ofRotate(10*ofGetElapsedTimef(), 0.5, 1, 0);
        ofSetColor( 255, 255, 255 );
        img.getTextureReference().bind();
        //mesh.drawWireframe();
        mesh.draw();
        img.getTextureReference().unbind();
    } ofPopMatrix();
}

Regarding the ‘stretching’ of the textures on the sides. That is because the sides are sharing the same tex coord for each edge connected to the faces that are mapped properly. You can see the color connecting the two sides. There needs to be a plane for each face to properly view the texture on all of the faces. So 24 verts instead of 8.

Thanks I drew it again with 4 vertices for each face and mapped a different part of the texture to each face and it works.

.h

  ofMesh mesh;
  ofImage img;

.cpp

void ofApp::setup(){





float verts[] = {
    
    //front
    0,0,0, //0
    300,0,0, //1
    0,300,0, //2
    300,300,0, //3
    
    //right
    300,0,0, //4
    300,0,-300,//5
    300,300,0,//6
    300,300,-300,//7
    
    //back
    300,0,-300,//8
    0,0,-300,//9
    300,300,-300,//10
    0,300,-300,//11
    
    //left
    0,0,-300,//12
    0,0,0,//13
    0,300,-300,//14
    0,300, 0,//15
    
    //top
    0,0,-300,//16
    300,0,-300,//17
    0,0,0,//18
    300,0,0,//19
    
    //bottom
    0,300,-300,//20
    300,300,-300,//21
    0,300,0,//22
    300,300,0//23
    
    
};

int indicies[] = {
    0,1,2,
    1,2,3,
    
    4,5,6,
    5,6,7,
    
    8,9,10,
    10,11,12,
    
    12,13,14,
    13,14,15,
    
    16,17,18,
    17,18,19,
    
    20,21,22,
    21,22,23
};

mesh.clear();

ofVec3f points[24];

mesh.setMode(OF_PRIMITIVE_TRIANGLES);

for (int i = 0; i < 24; i++) {

    
    points[i].x = verts[i*3];
    points[i].y = verts[i*3+1];
    points[i].z = verts[i*3+2];
    
    mesh.addVertex(points[i]);
    //mesh.addTexCoord(ofVec2f(points[i].x,points[i].y));
    mesh.addColor(ofFloatColor::white);
}

   float tcoords [] =  {
       //front
       0,0,
       0.33,0,
       0,0.5,
       0.33,0.5,
       
       //right
       0.33,0,
       0.67,0,
       0.33,0.5,
       0.67,0.5,
       
       //back
       0.67,0,
       1.0,0,
       0.67,0.5,
       1.0,0.5,
       
       //left
       0,0.5,
       0.33,0.5,
       0,1.0,
       0.33,1.0,
       
       //top
       0.33,0.5,
       0.67,0.5,
       0.33,1.0,
       0.67,1.0,
       
       //bottom
       0.67,0.5,
       1.0,0.5,
       0.67,1.0,
       1.0,1.0
   };

ofVec2f tcrds[24];

for (int i = 0; i < 24; i++) {

    
    tcrds[i].x = tcoords[i*2];
    tcrds[i].y = tcoords[i*2+1];
    mesh.addTexCoord(tcrds[i]);
}


for (int i = 0; i < 6; i++) {
    int fI = 4*i;
    
    mesh.addIndex(fI);  mesh.addIndex(fI+1);
    mesh.addIndex(fI+2);
    mesh.addIndex(fI+1);mesh.addIndex(fI+2);
                        mesh.addIndex(fI+3);
    
}




ofDisableArbTex();
img.loadImage("moon.jpg");

ofDisableBlendMode();
ofEnableDepthTest();



}

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


}

//--------------------------------------------------------------
void ofApp::draw(){
    ofBackground(0);

ofTranslate(300,200);
ofRotateY(90*ofGetElapsedTimef());
 // mesh.drawWireframe();
ofSetColor(255,255,255,255);
img.getTextureReference().bind();
mesh.draw();
img.getTextureReference().unbind();

}

using cube mapping principles with an image that is not really suitable