blender
This is an old revision of the document!
Table of Contents
Blender
cushion
source : https://www.youtube.com/watch?v=MLUnfE4FcOY
- Unordered List Itemcube
- s z
- loop cuts hor 30
- loop cut vert 1
- physics → cloth → change preset to silk
- collision → quality 4
- enable self collision
- field weights → gravity 0
- add a “force field” (make sure its placed in the center of the cube)
- strength 150
- start animation and stop when enough
- apply the cloth modifier
- remove the force field
dae cleaner
import bpy
def decimate():
for obj in bpy.data.objects:
if obj.type == 'MESH':
bpy.context.scene.objects.active = obj
bpy.ops.object.modifier_add(type="DECIMATE")
mod_name = bpy.context.object.modifiers[-1].name
bpy.context.object.modifiers[mod_name].decimate_type = 'DISSOLVE'
bpy.ops.object.modifier_apply(apply_as = 'DATA', modifier=mod_name)
def recenter_origin():
bpy.context.scene.cursor_location = (0.0,0.0,0.0)
for obj in bpy.data.objects:
if obj.type == 'MESH':
obj.select = True
#bpy.ops.object.origin_set(type='ORIGIN_CENTER_OF_MASS')
bpy.ops.object.origin_set(type='ORIGIN_CURSOR')
def set_layers():
for obj in bpy.data.objects:
if obj.type == 'MESH':
bpy.context.scene.objects.active = obj
if obj.parent.name == "group_0":
if obj.name[0:5] == "group":
bpy.context.object.layers[1] = True
elif obj.name[0:8] == "instance":
bpy.context.object.layers[2] = True
if obj.parent.name[0:8] == "instance":
bpy.context.object.layers[3] = True
if (obj.parent.name[0:5] == "group") and (obj.parent.name != "group_0"):
bpy.context.object.layers[4] = True
bpy.context.object.layers[0] = False
def unparent_all():
bpy.ops.object.select_all(action='DESELECT')
for obj in bpy.data.objects:
bpy.context.scene.objects.active = obj
if bpy.context.active_object.parent != None:
obj.select = True
bpy.ops.object.parent_clear(type='CLEAR_KEEP_TRANSFORM')
def select_all(status=True):
#bpy.ops.object.select_all(action='SELECT')
#bpy.ops.object.select_all(action='DESELECT')
for obj in bpy.data.objects:
obj.select = status
def hide_all(status=True):
for obj in bpy.data.objects:
bpy.context.scene.objects.active = obj
bpy.context.object.hide = status
def remove_duplicates():
unparent_all()
bpy.ops.object.select_all(action='DESELECT')
datas = {}
for obj in bpy.data.objects:
if obj.type == 'MESH':
bpy.context.scene.objects.active = obj
actual = bpy.context.scene.objects.active
if actual.data.name not in datas:
datas[actual.data.name] = [obj.name]
else:
datas[actual.data.name].append(obj.name)
#print(datas)
for values in datas:
length = len(datas[values])
if length > 1:
print(values, length, sep=':')
to_delete = sorted(datas[values])[1:length]
for value in to_delete:
bpy.data.objects[value].select = True
bpy.ops.object.delete()
#if length == 6:
# print(datas[values])
#print(values, datas[values][0].split('_')[1], sep=" : ")
#print(to_delete)
print("== Decimation Start ==")
print(bpy.data.scenes['Scene'].statistics())
remove_duplicates()
decimate()
recenter_origin()
print("== Decimation End ==")
print(bpy.data.scenes['Scene'].statistics())
shortcuts
Camera
| Shortcut | Function | Notes |
|---|---|---|
| ctrl+alt+0 | align camera to view | |
Interface
http://www.blendertips.com/hotkeys.html
| Shortcut | Function | Notes |
|---|---|---|
| ctrl + up/dow arrows | show / hide full screen panel | |
| keypad 1/3/7 | change view | |
Beziers
| Shortcut | Function | Notes |
|---|---|---|
| v | set handle type | |
| alt+c | close | |
Edit mode
| Shortcut | Function | Notes |
|---|---|---|
| a | select all / deselect all | |
| b | box select | |
| bb | brush select | |
| g | grab (translate) | |
| r | rotate | |
| s | scale | |
| x/y/z | using axis | |
| shift + x/y/z | use 2 axis except the one selected (ex : shift + z = use x+y) | |
| xx/yy/zz | use local axis | |
| ctrl + l | select linked elements | |
| p | separate items | |
| j | join item | |
| h | hide | |
| alt + h | show all | |
| f | create a face | |
Utils
| Shortcut | Function | Notes |
|---|---|---|
| ctrl + t | tracking mode to align camera to an object | |
| alt + g | clear coordinates | |
| shift + c | 3D Cursor to origin | |
Blender gmaps
sources
installation
renderdoc
- install renderdoc v1.10 : https://renderdoc.org/builds
- create a shortcut to chrome using “target” :
C:\Windows\System32\cmd.exe /c "SET RENDERDOC_HOOK_EGL=0 && START "" ^"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe^" --disable-gpu-sandbox --gpu-startup-dialog"
renderdoc blender addon
- install blender addon https://github.com/eliemichel/MapsModelsImporter
meshlab
- install meshlab https://www.meshlab.net/=download
procedure
capture
- run renderdoc
- go to “file/inject into process”
- run chrome using the shortcut and see the alert
- get the alert “process id” and use “refresh” in renderdoc to see the process and then push “inject” button (bottom right)
- click on the “ok” button on the chrome alert
- chrome should display numbers on the top left
- go to google maps and set to satellite and 3d
- explore the place with zooming and turn around the buildings
- go to renderdoc and use “capture after” 5 seconds
- go to chrome and move the 3d view and then it will hang shortly (it has been captured)
- go to renderdoc to see the capture
- right click and save the rdc file
- use import rdc file inside blender
optimizing mesh
- remove unuseful items
- select all the items and join them (ctrl+j)
- “edit mode” and “merge by distance”
optimize uv map
- duplicate the item and disable the first one
- remove the materials using this script :
import bpy
C = bpy.context
for i in range(0,len(C.object.material_slots)):
C.object.active_material_index = 1
bpy.ops.object.material_slot_remove()
bpy.ops.object.mode_set(mode = 'EDIT')
bpy.ops.mesh.select_all(action = 'SELECT')
bpy.ops.object.material_slot_assign()
bpy.ops.object.mode_set(mode = 'OBJECT')
- export selection as obj
- go to meshlab
- “file/import mesh”
- select mesh
- go to “filters / texture / parametrization : trivial per-triangle”
- set “texture dimension” to 8192 and click “apply”
- go to “render / show uv tex map” to see the result
- “file / export mesh”
- uncheck “vert / normal” and “face / color” so keep “wedge / texcoord”
- go back to blender
- delete the object
- import obj
bake the new texture
- select the imported mesh
- go to “shader editor”
- add a new material
- add an “image texture” node (do not connect it)
- create a new texture with 8192px size
- change renderer to “cycles” (set device to “cpu”)
- go to “bake” tab and select “bake type” as “diffuse”
- under “influence”, disable “direct” and “indirect”
- check “selected to active”
- “ray distance” to 0.1
- “output margin” 1px
- select image texture node in shader editor
- select disbled mesh and then select imported mesh (using ctrl to set the last one as active)
- click “bake”
- wait
- connect the image node
- rename the new texture and export it from the image editor
blender utils
blender 2.8 get names
import bpy
def getNames():
selection_names = bpy.context.selected_objects
for i in selection_names:
print(i.name)
getNames()
blender 2.8 custom join
import bpy
def customJoin():
# convert to single user
bpy.ops.object.make_single_user(type='SELECTED_OBJECTS', object=True, obdata=True, material=False, animation=False)
# get selection
selected_objects = bpy.context.selected_objects
# do the job
for o in selected_objects:
if o.type != 'EMPTY':
# set active
bpy.context.view_layer.objects.active = o
# convert to mesh
if o.type in ['CURVE', 'FONT']:
bpy.ops.object.convert(target='MESH')
# apply modifiers
for mod in o.modifiers:
bpy.ops.object.modifier_apply(modifier = mod.name)
# get the object's name
object_name = o.name
# get group
if object_name in o.vertex_groups:
group = o.vertex_groups[object_name]
else:
group = o.vertex_groups.new(name = object_name)
# get vertices
verts = []
for vert in o.data.vertices:
verts.append(vert.index)
# assign vertices to group
group.add(verts, 1.0, 'REPLACE')
# join to a single object
bpy.ops.object.join()
customJoin()
2.79 groups
import bpy
def giveGroup(groupname=""):
selected = bpy.context.selected_objects
for item in selected:
bpy.context.scene.objects.active = item
bpy.ops.object.group_link(group='veranda')
#giveGroup("veranda")
def giveMaterial(materialname=""):
selected = bpy.context.selected_objects
for item in selected:
bpy.context.scene.objects.active = item
bpy.context.object.active_material.name = materialname
giveMaterial("vitre")
addon template
import bpy
bl_info = {
"name": "my test addon",
"author": "jojo",
"version": (1,0),
"blender": (2,83,0),
"category": "Object",
"location": "Operator Search",
"description": "More monkeys!!",
"warning" : "",
"doc_url": "",
"tracker_url": ""
}
class MESH_OT_monkey_grid(bpy.types.Operator):
"""Let's spread some joy"""
bl_idname = "mesh.monkey_grid"
bl_label = "Monkey Grid"
bl_options = {'REGISTER', 'UNDO'}
count_x: bpy.props.IntProperty(
name="X",
description="Number of monkeys in the x direction",
default=3,
min=1,soft_max=10
)
count_y: bpy.props.IntProperty(
name="Y",
description="Number of monkeys in the y direction",
default=2,
min=1,soft_max=10
)
size: bpy.props.FloatProperty(
name="Size",
description="Size of each monkey",
min=0,max=1
)
@classmethod
def poll(cls, context):
if context.area.type == 'VIEW_3D':
return True
return False
def execute(self, context):
for idx in range(self.count_x * self.count_y):
x = idx % self.count_x
y = idx // self.count_x
bpy.ops.mesh.primitive_monkey_add(
size=self.size,
location=(x, y, 1))
return {'FINISHED'}
class VIEW3D_PT_monkey_grid(bpy.types.Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
bl_category = "Monkeys"
bl_label = "Grid"
def draw(self, context):
self.layout.operator('mesh.monkey_grid',
text='Default grid',
icon='MONKEY')
props = self.layout.operator('mesh.monkey_grid',
text='Big grid',
icon='MONKEY')
props.count_x = 10
props.count_y = 10
props.size = 0.8
def register():
bpy.utils.register_class(MESH_OT_monkey_grid)
bpy.utils.register_class(VIEW3D_PT_monkey_grid)
def unregister():
bpy.utils.unregister_class(MESH_OT_monkey_grid)
bpy.utils.unregister_class(VIEW3D_PT_monkey_grid)
Simple button
source : https://blenderartists.org/t/calling-a-function-from-a-button/616752/7
import bpy
class SimpleOperator(bpy.types.Operator):
"""Tooltip"""
bl_idname = "object.simple_operator"
bl_label = "Simple Object Operator"
@classmethod
def poll(cls, context):
return context.active_object is not None
def execute(self, context):
self.report({'INFO'}, "Button clicked!")
return {'FINISHED'}
def draw_func(self, context):
layout = self.layout
layout.operator("object.simple_operator")
def register():
bpy.utils.register_class(SimpleOperator)
bpy.types.VIEW3D_HT_header.prepend(draw_func)
def unregister():
bpy.utils.unregister_class(SimpleOperator)
bpy.types.VIEW3D_HT_header.remove(draw_func)
if __name__ == "__main__":
register()
bl_info = {
"name": "Exploded Bake",
"category": "Render",
}
import bpy
class ExplodedBake(bpy.types.Panel):
"""Creates a Panel in the Object properties window"""
bl_label = "Exploded Bake"
bl_idname = "OBJECT_PT_exploded_bake" # follow Blender convention for id names
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "object"
def draw(self, context):
layout = self.layout
obj = context.object
row = layout.row()
row.prop(obj, "name")
row = layout.row()
row.operator("button.explode")
class buttonExplode(bpy.types.Operator):
bl_idname = "button.explode" # translates to C-name BUTTON_OT_explode
bl_label = "Button text"
def execute(self, context):
#self.report({'INFO'}, "Hello world!")
print("hello")
return {'FINISHED'}
# (un-)register entire module, so you don't need to add every class here...
def register():
bpy.utils.register_module(__name__)
def unregister():
bpy.utils.unregister_module(__name__)
if __name__ == "__main__":
register()
import bpy
class SEBMAS_PROP_move_origins(bpy.types.PropertyGroup):
def update_function(self, context):
if self.move_origin_toggle:
bpy.context.scene.tool_settings.use_transform_data_origin = True
bpy.context.scene.tool_settings.snap_elements = {'VERTEX'}
else:
bpy.context.scene.tool_settings.use_transform_data_origin = False
bpy.context.scene.tool_settings.snap_elements = {'INCREMENT'}
return
bpy.types.WindowManager.move_origin_toggle = bpy.props.BoolProperty(
default = False,
update = update_function)
class SEBMAS_PT_tools_move_origin(bpy.types.Panel):
bl_category = "Tool"
bl_context = ".objectmode" # dot on purpose (access from topbar)
bl_label = "SebMas"
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
def draw(self, context):
self.layout.prop(context.window_manager,
'move_origin_toggle',
text="Move origin",
toggle=True,
icon='MONKEY')
classes = (
SEBMAS_PT_tools_move_origin,
)
def register():
for cls in classes:
bpy.utils.register_class(cls)
def unregister():
for cls in reversed(classes):
bpy.utils.unregister_class(cls)
if __name__ == "__main__":
register()
bounding box
Select an object and then :
import bpy; ob = bpy.data.scenes.active.objects.active; ob.getData(mesh=True).verts.extend(ob.getBoundBox(0))the object needs to dont have any “transformation”
blender.1635855250.txt.gz · Last modified: (external edit)
