Circular texture


#1

hi,

had to make a texture wrap around a circle today and thought id share the code.

in the screengrab above you can see the straight strip of colored texture in the top left.
the example shows how to apply this texture around a circle as you can see in the center of the screen. also imagine it would work well for convex blobs too.

[attachment=0:uz95s3eb]circular_texture.zip[/attachment:uz95s3eb]

circular_texture.zip


#2

Coolio, thank you very much!


#3

FREAKIN’ AWESOME!!! TNX!! :smiley:


#4

Ha! So funny, I just needed this two days ago and created one as well :slight_smile: Though I’m not using normals and a vertex array… just plain old intermediate mode… I needed to draw a circular shape that is used as a progress bar.


#5

Julapy I’ve put your code to work on a circular transparency gradient, and it works a treat — thanks for posting!

I have a quick question, hope this makes sense. I’m looking through the code to see how I can scale the size of the texture dynamically.

The diagram below shows the relationship I’m looking to change. X is the height of the original png, which relates to the ‘thickness’ of the circle once rotated. I’d like to know how to stretch/compress the thickness of the circle, based on a sensor reading I’m passing to the object.

I’ve changed this section in the constructor, which seems to scale the whole png upon loading

  
	for( int i=0; i<circle.size(); i++ )  
	{  
		outerRim.push_back( circle[ i ] + normals[ i ] * 40 );  
		innerRim.push_back( circle[ i ] - normals[ i ] * 40 );  
	}  
  

and glScalef works well to change the radius of the circle

  
void testApp :: drawRing (float size)  
{  
  
	glPushMatrix();  
	  
	glScalef( size,size,1 );  
  
...  
  

Any ideas on how I might scale the vertical dimension of the texture, to make the circle thicker or thinner?

cheers!

J


#6

hi jason,

i haven’t got the code with me today but from memory, the way you’ve changed the values in the constructor is correct and will give you a different thickness in the donut… you just have change the thickness value on every frame and recalculate the inner and outer rim.

L.


#7

Hey Lukasz, that did the trick, cheers.

Is there a way to specify which edge of the png to scale from (top/bottom?)

J


#8

Hey @julapy,

Looks awesome.
Trying to accomplish something similar, do you still have the source code for this?


#9

I know this is a very old topic – but is there anybody doing anything else similar here?

I’ve been wracking my brain around different ways to get this done and getting stuck every time.

I’ve tried drawing a circle using ofPath or OfPolyLine and colouring the vertices that come out of those but the vertices look completely incorrect.

Hoping someone had saved this or can chime in on how it would be done.


#10

use an ofMesh. Make a ring. Should be something like

int num_slices = 20; // this are like the slices of a pizza
float innerRadius = 100, outerRadius = 150;
for(int i = 0; i < num_slices; i++){
float pct = i /(float)num_slices;
float angle = TWO_PI* pct;
float s = sin(angle);
float c = cos(angle);
mesh.addVertex( ofVec3f(s*innerRadius, c*innerRadius));
mesh.addVertex( ofVec3f(s*outerRadius, c*outerRadius));
mesh.addTexCoord(pct, 0);// for this you need normalized texCoords.
mesh.addTexCoord(pct, 1);
}

I coded this here without testing, but thats the main idea. you make a ring and then draw it using the texture.
you can also make this in a very similar fashion on a fragment shader converting cartesian coords to polar.

Hope this helps.
Best!


#11

Thanks a bunch!

That got me on the right track.

I have a couple of adjustments below (off-by-one for loop).

One thing I noticed was that it actually seems to take non-normalised coordinates in addTexCoord (I had to pass in the actual pixel values for the texture). Is that something I did incorrectly during set up?

Is it related to me putting them into an ofVec2f first?

  newMesh.setMode(OF_PRIMITIVE_TRIANGLE_STRIP);
  int num_slices = 20; // this are like the slices of a pizza
  float innerRadius = 100, outerRadius = 150;
  float startX = ofGetWidth()/2;
  float startY = ofGetHeight()/2;
  for(int i = 0; i <= num_slices; i++){
    float pct = i /(float)num_slices;
    float angle = TWO_PI* pct;
    float s = sin(angle);
    float c = cos(angle);
    newMesh.addVertex( ofVec3f(s*innerRadius + startX, c*innerRadius + startY));
    newMesh.addVertex( ofVec3f(s*outerRadius + startX, c*outerRadius + startY));
    newMesh.addTexCoord(ofVec2f(pct*200, 0));// for this you need normalized texCoords.
    newMesh.addTexCoord(ofVec2f(pct*200, 50));
  }

#12

Another question: How can I get multiple concentric circles with the same texture?

I’ve tried adding another loop on top and drawing more rings, but that just acts like a mask for the shader. I’m trying to get different ones for each ring.


#13

Hi, by default OF uses non normalized texture coordinates. What you did is correct. If you want to use normalized textures you need to call ofEnableNormalizedTexCoords()
it should look something like this

ofMesh mesh;
mesh.setMode(OF_PRIMITIVE_TRIANGLE_STRIP);
ofVec3f center(ofGetWidth()/2, ofGetHeight()/2);
for(int i = 0; i <= num_slices; i++){
	float pct = i /(float)num_slices;
	float angle = TWO_PI* pct;
	float s = sin(angle);
	float c = cos(angle);
	mesh.addVertex( ofVec3f(s*innerRadius, c*innerRadius) + center);
	mesh.addVertex( ofVec3f(s*outerRadius, c*outerRadius) + center);
	mesh.addTexCoord(ofVec2f(pct, 0));
	mesh.addTexCoord(ofVec2f(pct, 1));
}
ofEnableNormalizedTexCoords();
img.bind();
mesh.draw();
img.unbind();
ofDisableNormalizedTexCoords();

For more rings just draw the mesh once again. if you want it a different size call ofScale(...)

best


#14

Ah, that explains it!

I do hope it’s not annoying that I keep coming up with more questions.

Now I’ve veered into wanting to make this move. I tried moving everything into update() but my computer gets extremely slow…

I have a newish i5, so I am guessing that this is a very computationally expensive set of operations to do within update(). Would there be any performance improvements I can do?

Or is it better for me to re-do all of this within a shader?

int numCircles = 7;
  for( int h = numCircles; h > 0; --h){
    int num_slices = 20 ; // this are like the slices of a pizza
    int circleHeight = 10;
    int innerStart = 50;
    float spacing = 2.0;
    float innerRadius = innerStart + (circleHeight + spacing)*h;
    float outerRadius = innerRadius + circleHeight;
    float startX = ofGetWidth()/2;
    float startY = ofGetHeight()/2;
    
    for(int i = 0; i <= num_slices; i++){
      float pct = i /(float)num_slices;
      float angle = TWO_PI* pct;
      float s = sin(angle);
      float c = cos(angle);
      newMesh.addVertex( ofVec3f(s*innerRadius + startX, c*innerRadius + startY));
      newMesh.addVertex( ofVec3f(s*outerRadius + startX, c*outerRadius + startY));
      newMesh.addTexCoord(ofVec2f(abs(pct + (h*(1.0/num_slices) - floor(h*(1.0/num_slices))) - 1), 0));
      newMesh.addTexCoord(ofVec2f(abs(pct + (h*(1.0/num_slices) - floor(h*(1.0/num_slices))) - 1), 1));
    }
  }


#15

Hi,
that doesn’t look like something too intense.
Anyhow, there’s no need to update it every frame if you are not modifying any parameter. So just put all this code in the setup or some other function you create that you can call if you change any parameter.
cheers!


#16

Found the root – don’t put ofLog() in your update function if it is going to run a lot.

After removing that, and running mesh.clear(), I was set. Now to get my algorithm working how I want it.