Created
August 15, 2022 23:10
-
-
Save armindocachada/5d6edbf7b3ad6cb2c22948c289e6af34 to your computer and use it in GitHub Desktop.
fully_connected_neural_network._blender_15_08_2022.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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