Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save armindocachada/5d6edbf7b3ad6cb2c22948c289e6af34 to your computer and use it in GitHub Desktop.
Save armindocachada/5d6edbf7b3ad6cb2c22948c289e6af34 to your computer and use it in GitHub Desktop.
fully_connected_neural_network._blender_15_08_2022.py
import bpy
import bmesh
import math
import numpy as np
def createMaterialForSynapses():
mat = bpy.data.materials.new(name='Material Synapses')
#object.data.materials.append(mat)
mat.use_nodes=True
# let's create a variable to store our list of nodes
mat_nodes = mat.node_tree.nodes
# let's set the metallic to 1.0
mat_nodes['Principled BSDF'].inputs['Metallic'].default_value=1.0
mat_nodes['Principled BSDF'].inputs['Roughness'].default_value=0.0
mat_nodes['Principled BSDF'].inputs['Base Color'].default_value=(0.013, 1, 0.830, 1.0)
mat_nodes['Principled BSDF'].inputs['Roughness'].default_value=0.167
return mat
def createMaterialForNeurons():
mat = bpy.data.materials.new(name='Material Neurons')
#object.data.materials.append(mat)
mat.use_nodes=True
# let's create a variable to store our list of nodes
mat_nodes = mat.node_tree.nodes
# let's set the metallic to 1.0
mat_nodes['Principled BSDF'].inputs['Metallic'].default_value=1.0
mat_nodes['Principled BSDF'].inputs['Roughness'].default_value=0.0
mat_nodes['Principled BSDF'].inputs['Base Color'].default_value=(0.047, 0.383, 1, 1.0)
mat_nodes['Principled BSDF'].inputs['Roughness'].default_value=0.167
return mat
MAT_NEURONS = createMaterialForNeurons()
MAT_SYNAPSES = createMaterialForSynapses()
def getGeometryCenter(obj):
vcos = [ obj.matrix_world @ v.co for v in obj.data.vertices ]
findCenter = lambda l: ( max(l) + min(l) ) / 2
x,y,z = [ [ v[i] for v in vcos ] for i in range(3) ]
center = [ findCenter(axis) for axis in [x,y,z] ]
print(center)
return center
def setOrigin(obj):
oldLoc = obj.location
newLoc = getGeometryCenter(obj)
for vert in obj.data.vertices:
vert.co[0] -= newLoc[0] - oldLoc[0]
vert.co[1] -= newLoc[1] - oldLoc[1]
vert.co[2] -= newLoc[2] - oldLoc[2]
obj.location = newLoc
def calculateNeuronGrid(numberOfNodes, origin, neuron_size, gap=(1, 0, 1)):
(gap_x, gap_y, gap_z) = gap
(rows, cols) = numberOfNodes
height = rows * (neuron_size + gap_z) - gap_z
width = cols * (neuron_size + gap_x) - gap_x
(origin_x, origin_y, origin_z) = origin
top_z = origin_z - (height / 2)
left_x = origin_x - (width / 2)
start_x = left_x + (neuron_size / 2)
start_y = origin_y
start_z = top_z + (neuron_size / 2)
row_height = neuron_size
col_width = neuron_size
neuron_coordinate_y = 0
neurons_grid = np.zeros((rows, cols, 3))
for row_index in range(0, rows):
neuron_coordinate_z = start_z + row_index * (row_height + gap_z)
for col_index in range(0, cols):
neuron_coordinate_x = start_x + col_index * (col_width + gap_x)
neurons_grid[row_index, col_index] = (neuron_coordinate_x,
start_y,
neuron_coordinate_z)
return neurons_grid.reshape( (rows * cols, 3))
def neuronsLayer(numberOfNodes=(10,10), origin=(0,0,0), neuron_size = 0.1, gap= (1,0, 1)):
(gap_x, _, gap_z) = gap
# Create an empty mesh and the object.
mesh = bpy.data.meshes.new('Basic_Sphere')
neuron_layer = bpy.data.objects.new("Neuron Layer", mesh)
neuron_layer.location= origin
# Add the object into the scene.
bpy.context.collection.objects.link(neuron_layer)
# Select the newly created object
bpy.context.view_layer.objects.active = neuron_layer
neuron_layer.select_set(True)
(nrows, ncols) = numberOfNodes
# Construct the bmesh sphere and assign it to the blender mesh.
bm = bmesh.new()
bmesh.ops.create_uvsphere(bm, u_segments=32, v_segments=16, radius=neuron_size/2)
bm.to_mesh(mesh)
bm.free()
mod = neuron_layer.modifiers.new('Array', 'ARRAY')
mod.use_relative_offset = True
mod.relative_offset_displace[0] = 1
mod.relative_offset_displace[1] = 0
mod.use_constant_offset = True
mod.constant_offset_displace[0] = gap_x
mod.constant_offset_displace[1] = 0.0
mod.count = nrows
bpy.ops.object.modifier_apply(modifier='Array')
mod = neuron_layer.modifiers.new('Array', 'ARRAY')
#print(type(mod))
#print(mod.items())
# mod.relative_offset_displace[0] = 0
# mod.relative_offset_displace[1] = 0
# mod.relative_offset_displace[2] = 1
mod.use_relative_offset = True
mod.relative_offset_displace[0] = 0
mod.relative_offset_displace[2] = 1
mod.use_constant_offset = True
mod.constant_offset_displace[0] = 0.0
mod.constant_offset_displace[2] = gap_z
mod.count = ncols
bpy.ops.object.modifier_apply(modifier='Array')
print(f"sphere.dimensions={neuron_layer.dimensions}")
setOrigin(neuron_layer)
neuron_layer.location=origin
neuron_layer.data.materials.append(MAT_NEURONS)
neuron_grid = calculateNeuronGrid(numberOfNodes, origin, neuron_size, gap=gap )
return (neuron_layer, neuron_grid)
def connectLayers(layer1, layer2):
index = 0
for neuron_layer1 in layer1:
#if index == 1:
for neuron_layer2 in layer2:
connectNeurons(neuron_layer1 ,neuron_layer2)
#if index == 3:
# break
index+=1
def midpoint(location_1, location_2):
(x1, y1, z1) = location_1
(x2, y2, z2) = location_2
x12 = (x1 +x2) / 2
y12 = (y1+ y2) /2
z12 = (z1 + z2)/ 2
return (x12, y12, z12)
def distance(location_1, location_2):
(x1, y1, z1) = location_1
(x2, y2, z2) = location_2
distance = math.sqrt( (x2- x1)**2 + (y2- y1)**2 + (z2- z1)**2)
return distance
def determine_angle(vectora, vectorb):
(xa, ya, za) = vectora
(xb, yb, zb) = vectorb
dot_product= (xa * xb + ya * yb + za * zb)
sqrt_vectora = math.sqrt((xa ** 2 + ya**2 + za**2))
sqrt_vectorb = math.sqrt((xb ** 2 + yb**2 + zb**2))
product_sqrt = sqrt_vectora * sqrt_vectorb
angle = math.acos(dot_product / product_sqrt)
return angle
def createCube(height, location, width=0.01):
vertices=[(1,1,-1),(1,-1,-1),(-1,-1,-1),(-1,1,-1),(1,1,1),(1,-1,1),(-1,-1,1),(-1,1,1)]
edges=[]
faces=[(0,1,2,3),(4,5,6,7),(0,4,7,3),(0,1,5,4),(1,2,6,5),(7,6,2,3)]
new_mesh=bpy.data.meshes.new("new_mesh")
new_mesh.from_pydata(vertices, edges, faces)
new_mesh.update()
#make object from the mesh
new_object = bpy.data.objects.new("new_object", new_mesh)
new_object.location = location
new_object.name="Aname"
new_object.scale=(width/2, width/2,height/2)
view_layer=bpy.context.view_layer
view_layer.active_layer_collection.collection.objects.link(new_object)
return new_object
def connectNeurons( location_start, location_end):
x = location_end[0] - location_start[0]
y = location_end[1] - location_start[1]
z = location_end[2] - location_start[2]
dist = distance(location_end, location_start)
mag = math.sqrt(x**2 + y**2 )
print(f"x={x} y={y} z={z}")
if x == 0:
beta = math.pi/2
else:
beta = math.atan(y/x)
if (x < 0 and y >= 0) or (x < 0 and y <= 0):
print(f"beta={beta} before adding math.pi")
beta = math.pi + beta
print("adding math.pi to beta")
#beta = math.pi + beta
if mag == 0:
theta = pi/2
else:
theta = math.atan(z/mag)
cube_loc = location_start + (location_end - location_start)/2
cube = createCube(dist,cube_loc)
gap = mag
cube.rotation_euler.z = beta
cube.rotation_euler.y = -theta + math.pi/2
cube.data.materials.append(MAT_SYNAPSES)
(neuron_layer1, neuron_grid1) = neuronsLayer(numberOfNodes=(25,25), origin=(0,0,0))
(neuron_layer2, neuron_grid2) = neuronsLayer(numberOfNodes=(4,4), origin=(0,10,0))
connectLayers(neuron_grid1, neuron_grid2)
#cube = createCube(1, (0,0,0), width=1)
#mat = bpy.data.materials.new(name='Material')
#cube.data.materials.append(mat)
#mat.use_nodes=True
## let's create a variable to store our list of nodes
#mat_nodes = mat.node_tree.nodes
## let's set the metallic to 1.0
#mat_nodes['Principled BSDF'].inputs['Metallic'].default_value=1.0
#mat_nodes['Principled BSDF'].inputs['Roughness'].default_value=0.0
#mat_nodes['Principled BSDF'].inputs['Base Color'].default_value=(0.047, 0.383, 1, 1.0)
#mat_nodes['Principled BSDF'].inputs['Roughness'].default_value=0.167
#print(f"neuron_grid1: {neuron_grid1}")
#print(f"neuron_grid2: {neuron_grid2}")
#print(midpoint((0,0,0), (1, 1, 1)))
#print(distance((0,0,0), (1, 1, 1)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment