Skip to content
Snippets Groups Projects
  1. Jun 29, 2015
  2. Jun 18, 2015
    • Bastien Montagne's avatar
      Final step (hopefully) in unit/scale Hell. · 470e77c2
      Bastien Montagne authored
      So, it appears some importers (at least UE4) do not use UnitScaleFactor defined by FBX,
      which is assumed to be a way to say 'this FBX file uses units n times default FBX unit'
      (default FBX unit being centimeter - afaik, at least I saw some FBX from Max with a
      UnitScaleFactor of 2.54 - inches).
      
      Hence, we have to add yet another stupid option to apply that 'unit scaling' to objects
      instead (as part of global scaling)... Hurra.
    • Bastien Montagne's avatar
      Again forgot to raise version count... · 2fcc6e45
      Bastien Montagne authored
      2fcc6e45
    • Bastien Montagne's avatar
      Fix T45080: Scale of exported .fbx is wrong in 2.75. · 01b30931
      Bastien Montagne authored
      Man... this scaling issue becomes ridiculous!
      
      Tried to fix it again also regarding (what is supposed to be) FBX scale/units handling.
      Since we store Blender's unit system (with 1BU == 1m in case of none) as the UnitScaleFactor
      element, we actually *do not* have to also scale objects themselves... In theory.
      
      Since I have to wait hours here to get my UE4 repo updated and rebuild the monster,
      comitting this now, we'll see later for FBXSDK behavior.
      01b30931
  3. Jun 08, 2015
  4. Jun 05, 2015
  5. Jun 04, 2015
  6. Jun 03, 2015
  7. May 31, 2015
  8. May 29, 2015
  9. May 26, 2015
  10. May 24, 2015
  11. May 22, 2015
  12. May 20, 2015
  13. May 19, 2015
  14. May 18, 2015
  15. May 11, 2015
  16. May 06, 2015
    • Bastien Montagne's avatar
      Fix T44619: Top Face of a Step Pyramid has its normal inverted. · 234760a9
      Bastien Montagne authored
      Also, fixed wrong '2.75' blender version statement - no need to update that unless mandatory,
      this is minimal working version, not 'current' version...
      
      And please, always remove menus *before* unregistering, otherwise UI code may try
      to access removed classes (menus, shortcuts, operators, etc.).
      234760a9
  17. May 04, 2015
  18. May 03, 2015
  19. May 02, 2015
    • Greg Zaal's avatar
      Auto Tile Size: Fix minor bug · b5afec73
      Greg Zaal authored
      Tile size would be recalculated constantly (every scene update) when the calculated size was less than 8 pixels (blender's own hard limit)
      diff --git a/render_auto_tile_size.py b/render_auto_tile_size.py
      index a773281..00f848e 100644
      --- a/render_auto_tile_size.py
      +++ b/render_auto_tile_size.py
      @@ -20,7 +20,7 @@ bl_info = {
           "name": "Auto Tile Size",
           "description": "Estimate and set the tile size that will render the fastest",
           "author": "Greg Zaal",
      -    "version": (3, 0),
      +    "version": (3, 1),
           "blender": (2, 74, 0),
           "location": "Render Settings > Performance",
           "warning": "",
      @@ -300,6 +300,12 @@ def do_set_tile_size(context):
           else:
               settings.threads_error = False
      
      +    # Make sure tile sizes are within the internal limit
      +    tile_x = max(8, tile_x)
      +    tile_y = max(8, tile_y)
      +    tile_x = min(65536, tile_x)
      +    tile_y = min(65536, tile_y)
      +
           render.tile_x = tile_x
           render.tile_y = tile_y
      b5afec73
    • Greg Zaal's avatar
      Auto Tile Size: Various improvements... · 7faa91dd
      Greg Zaal authored
       - Let the user choose a specific number for the target tile size (not only limited to powers of 2).
       - If there are more render threads available than tiles, reduce the tile size until all threads will be utilized - this means you can do tiny border-renders and still utilize 100% of your CPU.
       - Number of tiles is now displayed in the UI.
       - Minor tweaks to tooltips and function names.
      
      NOTE: The math of calculating the maximum tile size possible while still using all the threads is a bit wonky - it's functional, but not nice. Occasionally when there are many CPU threads (e.g. 16), only 15 of them will be used. Math is not my forte, so some help in this area would be much appreciated.
      
      diff --git a/render_auto_tile_size.py b/render_auto_tile_size.py
      index 8ece451..a773281 100644
      --- a/render_auto_tile_size.py
      +++ b/render_auto_tile_size.py
      @@ -20,8 +20,8 @@ bl_info = {
           "name": "Auto Tile Size",
           "description": "Estimate and set the tile size that will render the fastest",
           "author": "Greg Zaal",
      -    "version": (2, 7),
      -    "blender": (2, 72, 0),
      +    "version": (3, 0),
      +    "blender": (2, 74, 0),
           "location": "Render Settings > Performance",
           "warning": "",
           "wiki_url": "http://wiki.blender.org/index.php?title=Extensions:2.6/Py/Scripts/Render/Auto_Tile_Size",
      @@ -31,7 +31,7 @@ bl_info = {
      
       import bpy
       from bpy.app.handlers import persistent
      -from math import ceil, floor
      +from math import ceil, floor, sqrt
      
       SUPPORTED_RENDER_ENGINES = {'CYCLES', 'BLENDER_RENDER'}
      @@ -55,16 +55,14 @@ class AutoTileSizeSettings(bpy.types.PropertyGroup):
               name="Target GPU Tile Size",
               items=TILE_SIZES,
               default='256',
      -        description="Square dimentions of tiles",
      +        description="Square dimentions of tiles for GPU rendering",
               update=_update_tile_size)
      -
           cpu_choice = bpy.props.EnumProperty(
               name="Target CPU Tile Size",
               items=TILE_SIZES,
               default='32',
      -        description="Square dimentions of tiles",
      +        description="Square dimentions of tiles for CPU rendering",
               update=_update_tile_size)
      -
           bi_choice = bpy.props.EnumProperty(
               name="Target CPU Tile Size",
               items=TILE_SIZES,
      @@ -72,6 +70,37 @@ class AutoTileSizeSettings(bpy.types.PropertyGroup):
               description="Square dimentions of tiles",
               update=_update_tile_size)
      
      +    gpu_custom = bpy.props.IntProperty(
      +        name="Target Size",
      +        default=256,
      +        min=8,  # same as blender's own limits
      +        max=65536,
      +        description="Custom target tile size for GPU rendering",
      +        update=_update_tile_size)
      +    cpu_custom = bpy.props.IntProperty(
      +        name="Target Size",
      +        default=32,
      +        min=8,  # same as blender's own limits
      +        max=65536,
      +        description="Custom target tile size for CPU rendering",
      +        update=_update_tile_size)
      +    bi_custom = bpy.props.IntProperty(
      +        name="Target Size",
      +        default=64,
      +        min=8,  # same as blender's own limits
      +        max=65536,
      +        description="Custom target tile size",
      +        update=_update_tile_size)
      +
      +    target_type = bpy.props.EnumProperty(
      +        name="Target tile size",
      +        items=(
      +            ('po2', "Po2", "A choice between powers of 2 (16, 32, 64...)"),
      +            ('custom', "Custom", "Choose any number as the tile size target")),
      +        default='po2',
      +        description="Method of choosing the target tile size",
      +        update=_update_tile_size)
      +
           use_optimal = bpy.props.BoolProperty(
               name="Optimal Tiles",
               default=True,
      @@ -89,9 +118,16 @@ class AutoTileSizeSettings(bpy.types.PropertyGroup):
               default=False,
               description="Show extra options for more control over the calculated tile size")
      
      +    thread_error_correct = bpy.props.BoolProperty(
      +        name="Fix",
      +        default=True,
      +        description="Reduce the tile size so that all your available threads are used.",
      +        update=_update_tile_size)
      +
           # Internally used props (not for GUI)
           first_run = bpy.props.BoolProperty(default=True, options={'HIDDEN'})
           threads_error = bpy.props.BoolProperty(options={'HIDDEN'})
      +    num_tiles = bpy.props.IntVectorProperty(default=(0, 0), size=2, options={'HIDDEN'})
           prev_choice = bpy.props.StringProperty(default='', options={'HIDDEN'})
           prev_engine = bpy.props.StringProperty(default='', options={'HIDDEN'})
           prev_device = bpy.props.StringProperty(default='', options={'HIDDEN'})
      @@ -109,16 +145,17 @@ def ats_poll(context):
           return True
      
      -def ats_get_engine_is_gpu(engine, device, userpref):
      +def engine_is_gpu(engine, device, userpref):
           return engine == 'CYCLES' and device == 'GPU' and userpref.system.compute_device_type != 'NONE'
      
      -def ats_get_tilesize_prop(engine, device, userpref):
      -    if ats_get_engine_is_gpu(engine, device, userpref):
      -        return "gpu_choice"
      +def get_tilesize_prop(engine, device, userpref):
      +    target_type = "_choice" if bpy.context.scene.ats_settings.target_type == 'po2' else "_custom"
      +    if engine_is_gpu(engine, device, userpref):
      +        return ("gpu" + target_type)
           elif engine == 'CYCLES':
      -        return "cpu_choice"
      -    return "bi_choice"
      +        return ("cpu" + target_type)
      +    return ("bi" + target_type)
      
       @persistent
      @@ -137,9 +174,9 @@ def on_scene_update(scene):
           # scene.cycles might not always exist (Cycles is an addon)...
           device = scene.cycles.device if engine == 'CYCLES' else settings.prev_device
           border = render.use_border
      -    threads = render.threads
      +    threads = get_threads(context, device)
      
      -    choice = getattr(settings, ats_get_tilesize_prop(engine, device, userpref))
      +    choice = getattr(settings, get_tilesize_prop(engine, device, userpref))
      
           res = get_actual_res(render)
           actual_ts = (render.tile_x, render.tile_y)
      @@ -150,7 +187,7 @@ def on_scene_update(scene):
                        device != settings.prev_device or
                        border != settings.prev_border or
                        threads != settings.prev_threads or
      -                 choice != settings.prev_choice or
      +                 str(choice) != settings.prev_choice or
                        res != settings.prev_res[:] or
                        border_res != settings.prev_border_res[:] or
                        actual_ts != settings.prev_actual_tile_size[:])
      @@ -163,6 +200,61 @@ def get_actual_res(render):
           # floor is implicitly done by int conversion...
           return (int(render.resolution_x * rend_percent), int(render.resolution_y * rend_percent))
      
      +def get_threads(context, device):
      +    render = context.scene.render
      +    engine = render.engine
      +    userpref = context.user_preferences
      +
      +    if engine_is_gpu(engine, device, userpref):
      +        gpu_device_str = userpref.system.compute_device
      +        if 'MULTI' in gpu_device_str:
      +            threads = int(gpu_device_str.split('_')[-1])
      +        else:
      +            threads = 1
      +    else:
      +        threads = render.threads
      +
      +    return threads
      +
      +def max_tile_size(threads, xres, yres):
      +    ''' Give the largest tile size that will still use all threads '''
      +
      +    render_area = xres * yres
      +    tile_area = render_area / threads
      +    tile_length = sqrt(tile_area)
      +
      +    # lists: num x tiles, num y tiles, squareness, total tiles
      +    perfect_attempts = []  # attempts with correct number of tiles
      +    attempts = []  # all attempts, even if incorrect number of tiles
      +
      +    axes = [xres, yres]
      +    funcs = [floor, ceil]
      +
      +    for axis in axes:
      +        sec_axis = yres if axis == xres else xres
      +        for func in funcs:
      +            primary = func(axis / tile_length)
      +            if primary > 0:
      +                secondary = threads / primary
      +                ts_p = axis/primary
      +                ts_s = sec_axis/secondary
      +                squareness = max(ts_p, ts_s) - min(ts_p, ts_s)
      +                attempt = [primary if axis == xres else secondary, primary if axis != xres else secondary, squareness, primary * secondary]
      +                if attempt not in attempts:
      +                    attempts.append(attempt)
      +                    if secondary.is_integer():  # will only be an integer if there are the right number of tiles
      +                        perfect_attempts.append(attempt)
      +
      +    if perfect_attempts:  # prefer to use attempt that has exactly the right number of tiles
      +        attempts = perfect_attempts
      +
      +    attempt = sorted(attempts, key=lambda k: k[2])[0]  # pick set with most square tiles
      +    numtiles_x = round(attempt[0])
      +    numtiles_y = round(attempt[1])
      +    tile_x = ceil(xres / numtiles_x)
      +    tile_y = ceil(yres / numtiles_y)
      +
      +    return (tile_x, tile_y)
      
       def do_set_tile_size(context):
           if not ats_poll(context):
      @@ -176,7 +268,6 @@ def do_set_tile_size(context):
           engine = render.engine
           device = scene.cycles.device if engine == 'CYCLES' else settings.prev_device
           border = render.use_border
      -    threads = render.threads
      
           realxres, realyres = xres, yres = res = get_actual_res(scene.render)
      
      @@ -184,11 +275,12 @@ def do_set_tile_size(context):
               xres = round(xres * (render.border_max_x - render.border_min_x))
               yres = round(yres * (render.border_max_y - render.border_min_y))
      
      -    choice = getattr(settings, ats_get_tilesize_prop(engine, device, userpref))
      +    choice = getattr(settings, get_tilesize_prop(engine, device, userpref))
           target = int(choice)
      
           numtiles_x = ceil(xres / target)
           numtiles_y = ceil(yres / target)
      +    settings.num_tiles = (numtiles_x, numtiles_y)
           if settings.use_optimal:
               tile_x = ceil(xres / numtiles_x)
               tile_y = ceil(yres / numtiles_y)
      @@ -198,20 +290,25 @@ def do_set_tile_size(context):
      
           print("Tile size: %dx%d (%dx%d tiles)" % (tile_x, tile_y, ceil(xres / tile_x), ceil(yres / tile_y)))
      
      -    render.tile_x = tile_x
      -    render.tile_y = tile_y
      -
           # Detect if there are fewer tiles than available threads
      -    if ((numtiles_x * numtiles_y) < threads) and not ats_get_engine_is_gpu(engine, device, userpref):
      +    threads = get_threads(context, device)
      +    if ((numtiles_x * numtiles_y) < threads):
               settings.threads_error = True
      +        if settings.thread_error_correct:
      +            tile_x, tile_y = max_tile_size(threads, xres, yres)
      +            settings.num_tiles = (ceil(xres/tile_x), ceil(yres/tile_y))
           else:
               settings.threads_error = False
      
      +    render.tile_x = tile_x
      +    render.tile_y = tile_y
      +
      +
           settings.prev_engine = engine
           settings.prev_device = device
           settings.prev_border = border
           settings.prev_threads = threads
      -    settings.prev_choice = choice
      +    settings.prev_choice = str(choice)
           settings.prev_res = res
           settings.prev_border_res = (render.border_min_x, render.border_min_y, render.border_max_x, render.border_max_y)
           settings.prev_actual_tile_size = (tile_x, tile_y)
      @@ -252,16 +349,21 @@ def ui_layout(engine, layout, context):
           row.prop(settings, "is_enabled", toggle=True)
           row.prop(settings, "use_advanced_ui", toggle=True, text="", icon='PREFERENCES')
      
      -    sub = col.column(align=True)
      +    sub = col.column(align=False)
           sub.enabled = settings.is_enabled
      
           if settings.use_advanced_ui:
      -        sub.label("Target tile size:")
      +        row = sub.row(align=True)
      +        row.label("Target tile size:")
      +        row.separator()
      +        row.prop(settings, "target_type", expand=True)
      
               row = sub.row(align=True)
      -        row.prop(settings, ats_get_tilesize_prop(engine, device, userpref), expand=True)
      +        row.prop(settings, get_tilesize_prop(engine, device, userpref), expand=True)
               sub.prop(settings, "use_optimal", text="Calculate Optimal Size")
      
      +        sub.label("Number of tiles: %s x %s (Total: %s)" % (settings.num_tiles[0], settings.num_tiles[1], settings.num_tiles[0] * settings.num_tiles[1]))
      +
           if settings.first_run:
               sub = layout.column(align=True)
               sub.operator("render.autotilesize_set", text="First-render fix", icon='ERROR')
      @@ -272,9 +374,11 @@ def ui_layout(engine, layout, context):
           if (render.tile_x / render.tile_y > 2) or (render.tile_x / render.tile_y < 0.5):  # if not very square tile
               sub.label(text="Warning: Tile size is not very square", icon='ERROR')
               sub.label(text="    Try a slightly different resolution")
      -        sub.label(text="    or choose \"Exact\" above")
           if settings.threads_error:
      -        sub.label(text="Warning: Fewer tiles than render threads", icon='ERROR')
      +        row = sub.row(align=True)
      +        row.alignment = 'CENTER'
      +        row.label(text="Warning: Fewer tiles than threads.", icon='ERROR')
      +        row.prop(settings, 'thread_error_correct')
      
       def menu_func_cycles(self, context):
      7faa91dd
  20. May 01, 2015
    • Howard Trickey's avatar
      Fix T44567, take 2. Sometimes faces repeated the same Vert. · 6d120f0d
      Howard Trickey authored
      This is really a different bug that the one that was reopened
      but I didn't know that when I reopened it.
      It shouldn't happen that vertices get repeated in a face, but
      when doing it happens in extreme cases, and for now am fixing by
      just removing those duplicates before calling the make-face routine.
      6d120f0d
    • Howard Trickey's avatar
      Fix T44567: inset polygon added crash · 44153e0c
      Howard Trickey authored
      Crash caused by some vertices in the input model being doubled.
      The code to test for the maximum inset deduped the vertices
      but the faces were not remapped. Fixed by having that test code
      not dedup the vertices.
      44153e0c
    • Greg Zaal's avatar
      Fix: T44564 · 922272e6
      Greg Zaal authored
      Adding an image sequence now works for Shader nodes too (not sure when this broke?)
      Also improved/fixed the logic of figuring out what image sequence the user is trying to add - sometimes they select only one frame, sometimes they select all the frames (Blender itself is inconsistent about this behavior)
      922272e6
Loading