Age | Commit message (Collapse) | Author |
|
Limited, because STL only stores face normals, so we can only fake this by setting
all clnors of a same face to that face normal... Guess use case are rather limited,
but does not hurt to have it either.
|
|
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
|
|
- 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):
|
|
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.
|
|
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.
|
|
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)
|
|
Tracker: https://developer.blender.org/T44561
New UI, New Addons, Better organization & removal of 'Lesser Object
Types'
Merged & removed "lesser" & 'larger" add mesh scripts.
Menu updates & re-organization & modernize.
New: Add Vert, Round Cube, Menger Cube, Brilliant Diamond, Parent to
Empty
Removed: Add Mesh: Sqorus, Trapezohedron, Wedge, Polysphere.
Merged add_mesh_symmetrical_empty from contrib
Documentation:
http://wiki.blender.org/index.php/Extensions:2.6/Py/Scripts/Add_Mesh/Add_Mesh_Extra_Objects
|
|
It would export animations from all compatible actions - even for objects that were
actually not animated at all! This would lead to undesired behavior esp. for
simple objects scenes with only one or two animated.
Now we only export all compatible actions for a given object if it is actually
animated.
|
|
MTL file.
Was a TODO actually, now we try to match better illum values with current mesh material.
Also, using mirror color as Ka instead of ambient one, when mirror is enabled in blen mat.
|
|
AnimAll
Patch D1210 by @Leon95
|
|
People do not read tooltips it seems...
Would not mind a big red flashing message even, but fear UI mafia would not be happy.
|
|
Rotation issues.
|
|
|
|
|
|
rotation_mode other than 'QUATERNION'. Thanks to Dmitry (MakKlaski) for highlighting this issue."
This reverts commit e66cdc9f40ef48fab506e801ec1e313db2487e0a.
|
|
rotation_mode other than 'QUATERNION'. Thanks to Dmitry (MakKlaski) for highlighting this issue.
|
|
|
|
- Increase line thickness slightly
- Draw in gray when source and target nodes are the same one (nothing will be done)
- Use DPI factor for line thickness
- Draw circles with 12 sides (32 was overkill for such tiny circles)
- Rename node outline draw callback accordingly
|
|
There's no real performance hit, so no reason not to use it all the time.
Also enable antialiasing for other draw functions.
|
|
The previous behaviour was flawed:
1. Repeatedly aligning the same selection of nodes would space them further and further apart each time
2. The user had to choose between "Horizontal" and "Vertical", which gave the opposite of intended behavior
The new behavior:
1. Nodes are spaced evenly and consistently apart
2. Whether the nodes are aligned vertically or horizontally is now determined automatically
|
|
mesh on import.
Issue here is that FBX assigns materials by objects, while in Blender it is by default assigned
to meshes (obdata). This becomes critical with tons of objects using the same mesh (as generated
e.g. by exporting from Blender's dupliobjects).
We may add an option later to assign materials to objects too, but meh... We already have tons
of options in FBX. :|
Also, added some timing/steps reporting in console, helps seeing io process going on,
and spotting stupid issues like this one!
|
|
disk.
Just abort when trying to (auto)save current file and it does not exists on disk yet.
|
|
|
|
|
|
|
|
|
|
Some report a size (facet number) of zero... To think even something as
simple as STL format cannot be respected universally... :'(
|
|
The tricky part here is that to read correctly df3 data, we need to have a unit box,
and can only transform it to match Blender's domain's bbox *after* df3 is read.
|
|
patch by Jefferson Rausseo
|
|
|
|
|
|
space_bar_menu addon is enabled.
That's great mystery - that addon was doing 'bad' `from bpy import *`.
Removing that fixes the issue, but... :/
|
|
Nothing broken here actually, just missing info (shape needs at least three levels
of branching to take effect).
To be backported to 2.74.
|
|
readonly properties.
|
|
|
|
Well, not exactly a fix, since the buggy behavior from FBXSDK side makes no sense to me.
So it's rather a hack to make that stupid piece of junk happy - now you can (optionally,
but ON by default) force exporting anim keys for all bones of an armature.
Should be safe for 2.74, just adds a new option, cannot see how it could break existing stuff.
|
|
rBAbfbabc0592b8.
Now using a class factory to allow customization of those defaults axes, still way less
verbose than previous code!
|
|
The minimum value for the 'scale' property has been decreased,
allowing even smaller scales (some C3D files use huge coordinates).
The effect of the 'from_inches' property has been changed to match its
description.
Reviewed by: dmbasso
Differential: D1195
|
|
with Cycles engine.
UseAlpha & co are image settings, they are not bound to any specific render engine.
To be backported to final 2.74.
|
|
|
|
In fact, it's the OBJ file which is utterly broken (thousands of faces reusing the same vertex...).
I think 'breakage' comes actually from change in bmesh (raising error when trying to get
an edge with same vert in both items of the key), afaiks this is not different from
old code in current importer.
Anyway, working around this is easy and cheap, so...
To be backported in final 2.74.
|
|
To be backported to final release.
|
|
|
|
invalid file.
Stupid libfbx crashes when there is no normals in 'main' mesh data, and some shape keys linked to that mesh.
Now, issue is, I removed always writing normals because iirc this was giving bugs
with some importers... Re-enabled it for now, let's hope everything works OK.
*do not backport this* to 2.74!
|
|
Pretty stupid, UV/VCols were passed as a copied list instead of direct blend data.
Not sure there was a reason for that, but now it was seriously conflicting with
new advanced behavior of that code (to allow complex per vert/face/loop normal import
into clnors)...
|
|
Needed to better handle a simultaneous edge / vertex event.
|
|
problems
when try to load factory settings. Fix was suggested by Severin, thanks a lot!
|
|
180 degree rotation of meshes.
Issue found, investigated and fixed by ib_rod (Rod Boyd), thanks a bunch!
And again, a special mention to the "quality" of FBX doc (even on official API level)...
|
|
|
|
Stupid mistake in own recent work on OBJ...
|