bpy.ops.object.mode_set(mode="EDIT")
bpy.ops.mesh.subdivide(number_cuts=3)
bpy.ops.object.mode_set(mode="OBJECT")
Is a blog about python programming language. You can see my work with python programming language, tutorials and news.
Monday, May 30, 2022
Blender 3D and python scripting - part 008.
Thursday, May 26, 2022
Blender 3D and python scripting - part 007.
# this create a light by type ['POINT', 'SUN', 'SPOT', 'HEMI', 'AREA']
light_data = bpy.data.lights.new('light', type='POINT')
# set light object
light = bpy.data.objects.new('light', light_data)
# link light to collections
bpy.context.collection.objects.link(light)
light.location[0] = -1
light.location[1] = 3
light.location[2] = 3
light.data.color = (1.0, 0.0, 0.0)
light.data.energy=200.0
light.data.specular_factor = 0.5
# if you use another type like 'SUN'
# then you can change properties like: angle
#light.data.angle = pi * 10.0 / 180.0
# get the name of the object light
lamp = bpy.data.lights[light.name]
Wednesday, May 25, 2022
Blender 3D and python scripting - part 006.
import bpy
#define the pi global
pi = 3.1415926
# define the new camera named NewCamera
camera_data = bpy.data.cameras.new(name='NewCamera')
# set camera_data to object
camera_object = bpy.data.objects.new('ObjectCamera', camera_data)
# link camera object to scene
bpy.context.scene.collection.objects.link(camera_object)
# set active camera in the current scene by object
bpy.context.scene.camera = bpy.data.objects['ObjectCamera']
# set location
camera_object.location = [0,-5,1]
# set rotation mode
camera_object.rotation_mode = 'XYZ'
# set the rotate the camerea using rotation_euler
bpy.data.objects[camera_object.name_full].rotation_euler = (90*(pi/180),0,0)
scene = bpy.context.scene
#these settings will set the render output
bpy.context.scene.cycles.samples = 1
scene.render.resolution_x = 640
scene.render.resolution_y = 480
scene.render.resolution_percentage = 100
scene.render.use_border = False
scene.render.image_settings.file_format='PNG'
scene.render.filepath='C:/3D/box_640_480.png'
bpy.ops.render.render(write_still=1)
Tuesday, May 24, 2022
Blender 3D and python scripting - part 005.
obj = bpy.ops.mesh.primitive_plane_add(size=2,
calc_uvs=True,
enter_editmode=False,
align='CURSOR',
location=location,
rotation=(0, 0, 0),
scale=(0,0,0)
)
# rename the object
bpy.context.object.name = obj_name
# return the object reference
return bpy.context.object
import bpy
def create_plane_XYZ(loc, obj_name):
#define the pi
pi = 3.1415926
# this is a definition like a tuple
rot = (0,0,0)
# need to convert it to a list in order to add new values
rot_list = list(rot)
# this ang variable will rotate obj to the 90-degree angle
ang = -90*(pi/180)
ang_inc = 45*(pi/180)
if loc[0] < 0:
rot_list[1]=ang
if loc[0] > 0:
rot_list[1]=ang
if loc[1] < 0:
rot_list[0]=ang
if loc[1] > 0:
rot_list[0]=ang
# this check if the two value from position of plane is not zero
if loc[1] != loc[2] != 0:
rot_list[0]=ang_inc
# this convert a list back to tuple
rot=tuple(rot_list)
# this create the plane
obj = bpy.ops.mesh.primitive_plane_add(size=2,
calc_uvs=True,
enter_editmode=False,
align='CURSOR',
location=loc,
rotation= rot,
scale=(0,0,0)
)
# rename the object
bpy.context.object.name = obj_name
# return the object reference
return bpy.context.object
# this will create a plane on X and translate with -1 on Y
planeX001 = create_plane_XYZ((0,-1,0), "Plane-X")
# this will create a plane on X and translate with 1 on Y
planeX002 = create_plane_XYZ((0,1,0), "Plane+X")
# this will create a plane on Y and translate with -1 on X
planeY001 = create_plane_XYZ((-1,0,0), "Plane-Y")
# this will create a plane on X and translate with 1 on Y
planeY002 = create_plane_XYZ((1,0,0), "Plane+Y")
# this will create a plane with 45 degree because two value on tuple is not zero
planeZ001 = create_plane_XYZ((0,-0.25,1.66), "Plane-Y+Z")
Monday, May 23, 2022
Blender 3D and python scripting - part 004.
import bpy
import math
def DegToRad(angle):
"""convert to radians"""
return angle*(math.pi/180)
def RotOBJ(name, angles):
"""rotate obj to the specified angles"""
rotation = [DegToRad(angle) for angle in angles]
bpy.data.objects[name].rotation_euler = rotation
def create_plane_X(location, obj_name):
obj = bpy.ops.mesh.primitive_plane_add(size=2,
calc_uvs=True,
enter_editmode=False,
align='CURSOR',
location=location,
rotation=(0, 0, 0),
scale=(0,0,0)
)
# rename the object
bpy.context.object.name = obj_name
# return the object reference
return bpy.context.object
def create_plane_Y(location, obj_name):
obj = bpy.ops.mesh.primitive_plane_add(size=2,
calc_uvs=True,
enter_editmode=False,
align='CURSOR',
location=location,
rotation=(0, 0, 0),
scale=(0,0,0)
)
# rename the object
bpy.context.object.name = obj_name
# return the object reference
return bpy.context.object
def create_plane_Z(location, obj_name):
obj = bpy.ops.mesh.primitive_plane_add(size=2,
calc_uvs=True,
enter_editmode=False,
align='CURSOR',
location=location,
rotation=(0, 0, 0),
scale=(0,0,0)
)
# rename the object
bpy.context.object.name = obj_name
# return the object reference
return bpy.context.object
n = 1
planeX001 = create_plane_X((0,-1,0), "PlaneX-{:02d}".format(n))
RotOBJ(planeX001.name, [-90, 0, 0])
planeX002 = create_plane_X((0,1,0), "PlaneX-{:02d}".format(n))
RotOBJ(planeX002.name, [-90, -0, 0])
planeY001 = create_plane_Y((-1,0,0), "PlaneY-{:02d}".format(n))
RotOBJ(planeY001.name, [0, -90, 0])
planeY002 = create_plane_Y((1,0,0), "PlaneY-{:02d}".format(n))
RotOBJ(planeY002.name, [0, -90, 0])
planeZ001 = create_plane_Z((0,-0.25,1.66), "PlaneZ-{:02d}".format(n))
RotOBJ(planeZ001.name, [45, 0, 0])
Sunday, May 22, 2022
Blender 3D and python scripting - part 003.
import bpy
import random
#this is a for lines with N poins
N = 19
# this is default python script from the first tutorial
gpencil_data = bpy.data.grease_pencils.new("GPencil")
gpencil = bpy.data.objects.new(gpencil_data.name, gpencil_data)
bpy.context.collection.objects.link(gpencil)
gp_layer = gpencil_data.layers.new("lines")
gp_frame = gp_layer.frames.new(bpy.context.scene.frame_current)
gp_stroke = gp_frame.strokes.new()
gp_stroke.points.add(count=N)
# let's create a new material for pencil stroke
gp_material_001 = bpy.data.materials.new(name="Grease pencil material 001")
# if you want to use Nodes
gp_material_001.use_nodes = True
#this will add a diffuse color for this material
gp_material_001.diffuse_color = (0.0, 0.0, 0.0, 1)
# create a new material for this grease pencil
bpy.data.materials.create_gpencil_data(gp_material_001)
# add the material to the grese pencil defined like gpencil
gpencil.data.materials.append(gp_material_001)
for i in range (N):
rand1 = random.randint(-3, 3)
rand2 = random.randint(-3, 3)
rand_size = random.randint(70, 76)
gp_stroke.line_width = rand_size
gp_stroke.points[i].co = (rand1,rand2,rand1)
gp_stroke.points[i].co = (rand2,rand1,rand2)
#this will create a random pressure
rand_pressure = random.randint(-3, 3) * 3
#create random color for Red Green and Blue
rand_color_R = random.randint(0, 1)
rand_color_G = random.randint(0, 1)
rand_color_B = random.randint(0, 1)
# set the pressure
gp_stroke.points[i].pressure = rand_pressure
# set the color RGB with transparency 1
gp_stroke.points[i].vertex_color = (rand_color_R,rand_color_G,rand_color_B, 1)
Thursday, May 19, 2022
Blender 3D and python scripting - part 002.
import bpy
def create_sphere(radius, distance_to_center, obj_name):
obj = bpy.ops.mesh.primitive_uv_sphere_add(
radius=radius,
location=(distance_to_center, 0, 0),
scale=(1, 1, 1)
)
# rename the object
bpy.context.object.name = obj_name
# return the object reference
return bpy.context.object
def create_emission_shader(color, strength, mat_name):
# create a new material shader
mat = bpy.data.materials.new(mat_name)
# enable the node-graph edition mode
mat.use_nodes = True
# clear all starter nodes
nodes = mat.node_tree.nodes
nodes.clear()
# add the Emission node
node_emission = nodes.new(type="ShaderNodeEmission")
# (input[0] is the color)
node_emission.inputs[0].default_value = color
# (input[1] is the strength)
node_emission.inputs[1].default_value = strength
# add the Output node
node_output = nodes.new(type="ShaderNodeOutputMaterial")
# link the two nodes
links = mat.node_tree.links
link = links.new(node_emission.outputs[0], node_output.inputs[0])
# return the material reference
return mat
n = 1
r = 1.0
d = 1.5
sphere001 = create_sphere(r, d, "Sphere-{:02d}".format(n))
sphere001.data.materials.append(
create_emission_shader(
(1, 1, 1, 1), 100, "SphereMat001"
)
)
Wednesday, May 18, 2022
Blender 3D and python scripting - part 001.
import bpy
import random
rand1 = random.randint(-3, 3)
rand2 = random.randint(-3, 3)
rand_size = random.randint(70, 76)
gpencil_data = bpy.data.grease_pencils.new("GPencil")
gpencil = bpy.data.objects.new(gpencil_data.name, gpencil_data)
bpy.context.collection.objects.link(gpencil)
gp_layer = gpencil_data.layers.new("lines")
gp_frame = gp_layer.frames.new(bpy.context.scene.frame_current)
gp_stroke = gp_frame.strokes.new()
gp_stroke.line_width = rand_size
gp_stroke.points.add(count=4)
gp_stroke.points[0].co = (rand1,rand2,rand1)
gp_stroke.points[1].co = (rand2,rand1,rand2)
Tuesday, April 21, 2020
Python 3.7.4 : A simple addon for Blender 3D version 2.8 .
This software named Blender 3D come with python version 3.7.4 .
The version of this 3D tool is 2.82a .
This is a default addon with these python files: __init__.py , build.py, catafest_addon_start.py.
You can see a folder and images, but is not part of these tutorial.
The full source code of this addon can be found on my GitHub account on this project.
First python file named build.py will create the addon using this command:
python .\build.py
The source code for this python file is:
#!/usr/bin/env python
from os.path import abspath, dirname, join as pjoin
import zipfile
SRC_DIR = dirname(abspath(__file__))
with zipfile.ZipFile('catafest_addon_start.zip', 'w', zipfile.ZIP_DEFLATED) as arch:
for filename in [
'__init__.py',
'catafest_addon_start.py',
'textures/texture_001.png']:
arch.write(pjoin(SRC_DIR, filename), 'add_mesh_catafest_blender_start/'+filename)
print('created file: catafest_addon_start.zip')
The next file named __init__.py will install the addon:
bl_info = {
"name": "catafest addon start",
"author": "Catalin George Festila",
"license": "GPL",
"version": (1, 1, 1),
"blender": (2, 82, 0),
"location": "View3D > Add > Mesh",
"description": "Procedurally generate 3D catafest_addon_start from a random seed.",
"warning": "",
"wiki_url": "https://github.com/catafest/catafest_blender_start/blob/master/README.md",
"tracker_url": "https://github.com/catafest/catafest_blender_start/issues",
"category": "Add Mesh"
}
if "bpy" in locals():
# reload logic (magic)
import importlib
importlib.reload(catafest_addon_start)
else:
from . import catafest_addon_start
import bpy
from bpy.props import StringProperty, BoolProperty, IntProperty
from bpy.types import Operator
class Generate_catafest_mesh(Operator):
"""Procedurally generate a catafest 3D mesh from a random seed."""
bl_idname = "mesh.generate_mesh"
bl_label = "catafest_blender_start"
bl_options = {'REGISTER', 'UNDO'}
random_seed = StringProperty(default='', name='Seed')
def execute(self, context):
catafest_addon_start.generate_mesh(
self.random_seed)
return {'FINISHED'}
def menu_func(self, context):
self.layout.operator(Generate_catafest_mesh.bl_idname, text="catafest_blender_start", icon="INFO")
def register():
#bpy.utils.register_module(__name__)
bpy.utils.register_class(Generate_catafest_mesh)
#bpy.types.INFO_MT_mesh_add.append(menu_func)
bpy.types.VIEW3D_MT_mesh_add.append(menu_func)
def unregister():
#bpy.utils.unregister_module(__name__)
bpy.utils.unregister_class(Generate_catafest_mesh)
bpy.types.VIEW3D_MT_mesh_add.remove(menu_func)
if __name__ == "__main__":
register()
The last one come with the addon features, for example to create a mesh.This script will not create the mesh, but will show you how can be used, see generate_mesh.
You can change this generate_mesh to do your tasks.
# -*- coding:utf-8 -*-
#
# catafest_addon_start.py
#
# This is a Blender script that uses procedural generation to create
# a catafest 3D mesh from a random seed. Tested with Blender 2.77a.
#
# catalinfest@gmail.com
# https://github.com/catafest/catafest_blender_start
#
# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
# All rights reserved.
#
# ##### END GPL LICENSE BLOCK #####
#
#import all python modules
import sys
import os
import os.path
import bpy
import bmesh
import datetime
from math import sqrt, radians, pi, cos, sin
from mathutils import Vector, Matrix
from random import random, seed, uniform, randint, randrange
from enum import IntEnum
from colorsys import hls_to_rgb
DIR = os.path.dirname(os.path.abspath(__file__))
# get resource path
def resource_path(*path_components):
return os.path.join(DIR, *path_components)
# Deletes all existing catafest_addon_start and unused materials from the scene
def reset_scene():
for item in bpy.data.objects:
item.select = item.name.startswith('catafest_addon_start')
bpy.ops.object.delete()
for material in bpy.data.materials:
if not material.users:
bpy.data.materials.remove(material)
for texture in bpy.data.textures:
if not texture.users:
bpy.data.textures.remove(texture)
# Generate mesh
def generate_mesh(random_seed=''):
if random_seed:
seed(random_seed)
# Let's start with a unit BMesh cube scaled randomly
bm = bmesh.new()
bmesh.ops.create_cube(bm, size=1)
if __name__ == "__main__":
reset_scene()
for area in bpy.context.screen.areas:
if area.type == 'VIEW_3D':
ctx = bpy.context.copy()
ctx['area'] = area
ctx['region'] = area.regions[-1]
bpy.ops.view3d.view_selected(ctx)
scene = bpy.data.scenes["Scene"]
scene.render.resolution_x = res_x
scene.render.resolution_y = res_y
scene.camera.rotation_mode = 'XYZ'
scene.camera.data.angle = radians(fov)
frame = 0
timestamp = datetime.datetime.now().strftime('%Y%m%d_%H%M%S')
Saturday, May 26, 2018
Blender 3D and Roblox with Python .
However, you can download the player as a 3D object and use it as an avatar.
Here's an issue: The 3D object is hard to set with origins for animation but python and Blender 3D can easily solve this.
You can use BMesh.
As you know:
BMesh is the new Blender mesh system in 2.63, with full support for N-sided polygons instead of only triangles and quads.
The result of this download 3D object has a bad origin:
Let's see the source code:
import bpy
import bmesh
import mathutils
from mathutils import Vector
context = bpy.context
def origin_to_bottom(obj):
matrix_world = obj.matrix_world
local_verts = [Vector(v[:]) for v in obj.bound_box]
blender_mesh = blender_meshesh.new()
blender_mesh.from_mesh(obj.data)
x, y, z = 0, 0, 0
l = len(local_verts)
z = min([v.z for v in local_verts])
local_origin = Vector((0, 0, 0))
global_origin = matrix_world * local_origin
for v in blender_mesh.verts:
v.coord = v.coord - local_origin
blender_mesh.to_mesh(obj.data)
matrix_world.translation = global_origin
mesh_objs = [mesh_object for mesh_object in context.selected_objects if mesh_object.type == 'MESH']
bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY')
for my_objects in mesh_objs:
origin_to_bottom(my_objects)
The result is this:Friday, April 14, 2017
Blender 3D - ellipsoid.
The ellipsoid may be parameterized in several ways but I used the sin and cos functions:
x = sin(theta) * sin(phi)
y = cos(theta) * sin(phi)
z = cos(phi)
The steps I follow are:
- make points of ellipsoid - CoordsPoints
- define an ellipsoid vectors
- create a new mesh
- make rings for faces
- make an ellipsoid
- The verts_mesh and verts_mesh_face are used to make faces
- put all into the Blender 3D scene
import bpy
import bmesh
from math import degrees, radians, sin, cos, tan
from mathutils import Vector
class CoordsPoints:
@property
def xyz(self):
theta = self.theta
phi = self.phi
x = sin(theta) * sin(phi)
y = cos(theta) * sin(phi)
z = cos(phi)
R = self.R
return R * Vector((x,y,z))
def __init__(self, R, theta, phi):
self.R = R
self.theta = theta
self.phi = phi
#self.xyz = self.point(theta, phi)
def __repr__(self):
return "Coords(%.4f, %.4f)" % (degrees(self.theta),
degrees(self.phi))
# define the ellipsoid method.
def ellipsoid(a, b, c):
def ellipsoid(v):
x = a * (v.x)
y = b * (v.y)
z = c * (v.z)
return Vector((x, y, z))
return ellipsoid
# make the ellipsoid bmesh
bm = bmesh.new()
# TODO come up with a nicer way to do this.
rings = [[CoordsPoints(1, radians(theta), radians(phi))
for theta in range (0, 360, 2)]
for phi in range(0, 180, 2)]
h = ellipsoid(1.0, 1.0, 1.5)
verts_mesh = [bm.verts.new(h(p.xyz)) for p in rings[0]]
verts_mesh.append(verts_mesh[0])
for ring in range(1, len(rings)):
verts_mesh_face = [bm.verts.new(h(p.xyz)) for p in rings[ring]]
verts_mesh_face.append(verts_mesh_face[0])
faces = [
bm.faces.new((
verts_mesh[i], verts_mesh_face[i],
verts_mesh_face[i+1], verts_mesh[i+1]
))
for i in range(len(verts_mesh) - 1)
]
verts_mesh = verts_mesh_face
# create mesh link it to scene
mesh = bpy.data.meshes.new("ellipsoid")
bm.to_mesh(mesh)
obj = bpy.data.objects.new("ellipsoid", mesh)
scene = bpy.context.scene
scene.objects.link(obj)
scene.objects.active = obj
obj.select = True
obj.location = scene.cursor_location
Wednesday, May 15, 2013
Use python to render scene in Blender 3D.
The python script is very simple.
I used my scene with Mickey Mouse (my boy like this funny cartoon).
This is the python script.
import bpy
bpy.context.scene.render.use_border = False
bpy.context.scene.render.use_crop_to_border = False
bpy.ops.render.render()
R="Render Result"
bpy.data.images[R].save_render("/home/your_username/test_render.png")
See the output image:
The next source code it's used for border and crop.
Only if you want to use it.
bpy.context.scene.render.use_border = False
bpy.context.scene.render.use_crop_to_border = False
Also you can use this to set resolution percentage.
For example if you want to render just 10% of resolution use this:
bpy.context.scene.render.resolution_percentage =10
Saturday, March 23, 2013
Using fnmatch python module ...
The module fnmatch provides support for Unix shell-style wildcards, which are not the same as regular expressions.
Why , because the special characters used are : * , ? , [seq] , [!seq] .
This is default example from fnmach website.
>>> for file in os.listdir('.'):
... if fnmatch.fnmatch(file, '*.txt'):
... print file
...
tableta.txt
verf.txt
a.txt
python-modules.txt
untitled.txt
resetbios.txt
>>>
Now I want to show you another way to use this module.
Using Blender with multiple objects and python script can be very hard way.
For example if you have many objects or one matrix of objects create manually or with some scripts the named object is like in the next image:
Just use the fnmatch to sort this objects.
>>> import bpy
>>> import fnmatch
Now get all meshes objects.
>>> all_objects = bpy.data.objects
Put names of all meshes as a list of strings.
>>> list_all_objects= [all_objects[i].name for i in range(len(all_objects))]
Use the python module fnmatch to filter the name of objects.
>>> new_list_objects = fnmatch.filter(list_all_objects, 'Cube.*')]
Now you can use this new list to make some change. I use print to show test the list.
>>> print(new_list_objects)
['Cube.001', 'Cube.002', 'Cube.003'
The goal of fnmatch module in Blender 3D can be use one module to make list of objects and enables searching for files given a file name pattern.
It's two features in one module.
Also this python module can be used to get some
>>> regular_expression_txt = fnmatch.translate('*.txt')
>>> regular_expression_txt
'.*\\.txt\\Z(?ms)'
>>> print(regular_expression_txt)
.*\.txt\Z(?ms)
Just remove \Z(?ms) and use it.
I try to use some regular expression and seam working well.
Monday, April 30, 2012
Create tile image for your game using python script
Tile image is a method of storing a sequence of images placed in a single image file.
These images are then processed according to user needs.
Here's an example below:
How we can create these images?
We can use graphics editing software to create them separately.
I used Blender 3D to create separate images.
A tutorial how to do this can be found here on section Blender 3D.
After I rendered images separately and named: 0000.png , 0001.png , 0002.png , 0003.png
I created a python script to put in an tile image, see below:
import os
import PIL
from PIL import Image
from PIL import ImageDraw
o=Image.new("RGBA",(192,48))
d= ImageDraw.Draw(o)
for pic in range(0,4):
strpic=str(pic)
filnam="000"+strpic+".png"
x=pic*48
img=Image.open(filnam)
o.paste(img,(0+x,0))
o.save("out.png")
The script reads the image files of size 48 pixels and puts them into one image called out.png