Page MenuHome

Add a default UV map to our torus mesh primitive
Closed, ResolvedPublic


Torus primitive is generated from a python operator, unlike all others. So generating a default UV map for it should be added to that operator.

Event Timeline

this is my first time contributing to blender . hope it goes well

any more information . where to start

My first time too, I'm guessing

  1. Find that python operator
  2. rig up something to set the UV map - I'm not sure what the details of how the UV wrap will work, so I'm assuming just go for it and modify from the rough draft.
  3. put in a default true checkbox in the settings to create a UV.
  4. create a patch.
This comment was removed by Chau (BlenderNavi).
Chau (BlenderNavi) added a comment.EditedJun 23 2016, 4:42 AM

Can use this pattern for texture coordinate:

Chau (BlenderNavi) added a comment.EditedJun 23 2016, 11:59 AM

Pseudo code for create texCoord use diagram above. Sorry I program C/ObjectiveC but I think good Python programmer can understand this!

  1. major direction for u
  2. minor direction for v
  3. assume vertexArray have (numberMinorDivision+1)*(numberMajorDivision+1) elements
  4. and vertexes for each minor circle together

def function createTexCoord( integer numberMinorDivision, integer numberMajorDivision, Tuple vertexArray ) {

 integer majorIndex = 0;
# calculate u and v step size
 float uStep = 1.0/numberMajorDivision;
 float vStep = 1.0/numberMinorDivision;

 integer vertexArrayIndex = 0; 

# go around torus major axis
 float u = 0.0; # start at texture's left side
 while( majorIndex < numberMajorDivision + 1 ) {

    # go back to texture's bottom for each minor circle
   float v = 0.0;
   integer minorIndex = 0;
   # create coordinate for each vertex of minor circle
    while( minorIndex < numberMinorDivision + 1 ) {
       # save coordinate
       vertexArray[vertexIndex].u = u;
       vertexArray[vetexIndex].v = v;
       v += vStep;  # move up one step

    u += uStep; # move right one step


I add mesh coordinates for torus object. I try run it in Blender's text editor but it do nothing, also not appear in Object Menu. I use Blender 2.76. Please try it and tell me if it work.

@Chau (BlenderNavi) good start, looks like. Does anyone mind if I pick this up and give it a go?

Please finish it. I not know enough detail about how Blender mesh system work. I hope some one see this and help me finish it.

Well I am just learning too... Hopefully I can do something useful. :)

Here is what I did before I got busy with other things: I found relevant examples and documentation, and I created a workflow to modify and test the code for the operator. I added the property "Generate UVs" to the operator. I discovered that there must be some other way to access the UVs from Python, other than the first attempt made by @Chau (BlenderNavi).

My examples and references:

My in-progress modifications to the operator code, derived from @Chau (BlenderNavi)'s file:

My debugging environment/workflow:

  • Keep the above python file in some directory (need not be with Blender source code base).
  • Edit the file in an external editor.
  • Open a fresh instance of blender.
  • Open the above python file in a text block in a script editor.
  • Run the script.
  • Invoke the operator through the Mesh Add menu.

In a previous version, nothing happened when the script was run--the Blender code invokes the Python code some other way. Why does running the script have affect now? Thanks to the add-on tutorial, it has effect due to several lines I appended to the script (for debugging purposes only):

def menu_func(self, context):

def register():

if __name__ == "__main__":

Disclaimer: This is certainly not the only way to test the file.

However, you can speed up the above workflow by creating a fresh .blend file, loading the script into a text block, and saving the .blend file. Each time you want to run the script, open the .blend file, RE-load the script, and run it--WITHOUT overwriting the .blend file.

I truly hope this is helpful to someone! Cheers.

for a first python project I started working on this, most of the work was done anyways ;)
Here is the diff of my solution:

And here is the raw file:

I hope this helps finishing this project. I am happy about every tip i can get about my coding style or the development pipeline!

best regards,
Sebastian Witt

for a first python project I started working on this, most of the work was done anyways ;)
Here is the diff of my solution:
And here is the raw file:

I hope this helps finishing this project. I am happy about every tip i can get about my coding style or the development pipeline!
best regards,
Sebastian Witt

Thank you for contributing.

This is a summary of the python style required for scripts.

For python development currently is recommended using flake8 as a style checker. Set it up for your IDE/ editor of choice.

The default line width is 120 except in cases when there is a pep8-80-compliant comment at the top.

Common mistakes are not having spaces around operators, trailing space character or in empty ones, lines are too long, more or less than two spaces between functions, more than one line of gap between lines in functions, no space between # and text in comments, unused imports and variables, mixing tabs and spaces.

Some of the warnings are ignored due to the Blender specifics. You can check them in tests/python/ in source code (like E402 etc.).

Your solution seems to produce a good result just address the style issues first, before gets reviewed for functionality. :)

Here is an example of a cleanup for reference:

Here is the flake8 output with the style warnings in the raw file.

Thanks lijenstina,

thats exactly the type of feedback i need!
I've switched from xcode to atom for python coding and installed a flake8 Addon to get an instant stylecheck.

Here is the updated file:

I hope it is now fitting to the guidelines :)

Code review:

  • There's no need to convert to bmesh and back. You can do something like this:
uv_layer =

    loops = mesh.polygons[vertexIndex].loop_indices[loops[0]].uv = (u, v)
  • Use underscores rather than camel case for variable names. Maybe use minor_seg, major_seg names for consistency too.
  • Default UV map should be named "UVMap", not "default" for consistency, just leave out the name when calling new().
  • For other mesh primitives the Generate UVs button goes above View Align, and there's a col.separator() between them.

Thanks for the review,

I've tried to address all of the points you mentioned and will keep them in mind for the next project!
Here is the reworked code:

Committed, thanks for the patch!

I was trying to track down a strange discontinuity in a normal map generated from a torus, which led to discovering Blender was generating two UV islands - all but one single face were joined together. If you're interested, you can see the visual example (and what a user would do to fix it) here:

When I realized the torus generation was in a Python script, I took a look and cannot for the life of me work out why this section of code is included:

if minor_index == minor_seg - 1 and major_index == 0:
    uv_data[loops[1]].uv = u_prev, v_prev
    uv_data[loops[2]].uv = u_next, v_prev
    uv_data[loops[0]].uv = u_prev, v_next
    uv_data[loops[3]].uv = u_next, v_next
    uv_data[loops[0]].uv = u_prev, v_prev
    uv_data[loops[1]].uv = u_next, v_prev
    uv_data[loops[3]].uv = u_prev, v_next
    uv_data[loops[2]].uv = u_next, v_next

I tried removing that first special case and the UVs (and corresponding normal map render) looked as I expected. I tried a variety of odd & even segment values to see if it made any difference, and my "fix" appears to work fine. I admit math isn't my strong point so maybe I'm overlooking something, but perhaps this is just a legacy copy/paste issue? Anyway, I'm attaching the "fix".

I can confirm this is a bug.
The UV coords are flipped as to be expected by the code. I have no idea why this was in the code i wrote 2 years ago.

The provided fix should do it, just remove the first part of the condition.

@Sebastian Witt (witt): do you want to commit yourself? (I can do otherwise...)