# Is it possible to create vector fields based on a math equation?

If creating a vector field based on an equation is not possible, how create an equation-free 3-D vector field in blender?

The arrows should have color based on the magnitude of force they exert on objects. It would be great if the Vector field, can actually exert forces.

I understand that it's not possible to list everything in a single answer, but if someone can guide me in the right direction, it would be highly helpful.

Something like this

EDIT: Someone has actually done this, I precisely want to do something like this. https://www.reddit.com/r/blender/comments/8aqyns/vector_field/?utm_source=share&utm_medium=web2x

• Could you please elaborate. Does the result need to be renderable, animatable, and how many roundabouts? – batFINGER Oct 29 '19 at 6:58
• @batFINGER I exactly want something like the picture, I just have to look at the field from various angles. It would be nice, if it actually exerts a force on a object placed in the field. I primarily want to show arrows whose color is based on the magnitude obtained from a equation. – Aravindh Vasu Oct 29 '19 at 7:02
• The simplest of gizmos is an arrow. See text editor > templates > python > gizmo simple which displays an arrow gizmo to control the intensity of a spot lamp when selected. The color and orientation of the gizmo arrow can be set. This will display on 3d view as in image, but not be renderable, or animated using standard keyframing or drivers. A point cloud mesh (verts only) could be used for positions, and vertex color layer (rgba) for magnitude and direction of vector. – batFINGER Oct 29 '19 at 9:39
• @batFINGER thank you, I'm totally new so please bare with me. I'm having blender 2.79, there is no option named "gizmo simple" in the menu. – Aravindh Vasu Oct 29 '19 at 9:43
• Oh ok, gizmos are new in 2.8. Similarly in pre 2.8 could use bgl to draw arrows. Similarly to normals overlay – batFINGER Oct 29 '19 at 10:01

You could use mesh arrows to do it.

First, you need to create an arrow and the object that controls the field (in my case an empty named CTRL), then add a Track To constraint that points to the control.

Then you'll need to create your grid, which can do using this script:

import bpy
from bpy.app.handlers import persistent

dim = 10   #number of arrows on an edge og the cubic grid
spacing = 1
ctrl = bpy.data.objects["CTRL"]     #the control object
maxScale = 0.2
minScale = 0.01
distRange = 5

obj = bpy.context.selected_objects[0]

parent_coll = bpy.context.selected_objects[0].users_collection[0]
coll = bpy.data.collections.new("Grid")
for i in range(dim):
for j in range(dim):
for k in range(dim):
new_obj = obj.copy()
#new_obj.data = obj.data.copy()
new_obj.animation_data_clear()
new_obj.location = ((i-dim/2)*spacing, (j-dim/2)*spacing, (k-dim/2)*spacing)  #define arrows positions (here they are centered on the world origin)

for t in range(3):
driv.type = 'SCRIPTED'
driv.use_self = True

dist = driv.variables.new()
dist.name = "ctrlName"
dist.type = 'SINGLE_PROP'
dist.targets[0].id = ctrl
dist.targets[0].data_path = "name"

driv.expression = "getScale(ctrlName, self, "+str(maxScale)+","+str(minScale)+","+str(distRange)+")"

def getScale(ctrlName, obj, maxScale, minScale, distRange):
ctrl = bpy.data.objects[ctrlName]
dist = getDistance(ctrl, obj)
power = ctrl.scale[0]
scaleRange = maxScale - minScale
dist = dist/power   #distance is affected by the control size as well

if dist > distRange:
scale = minScale
else:
scale = scaleRange/(distRange**2)*(dist**2) - 2*scaleRange/distRange*dist + maxScale    #Here you define your scale function

return scale

def getDistance(ctrl, obj):
sum = 0
for i in range(3):
sum += (ctrl.location[i] - obj.location[i])**2
return sum**0.5

bpy.app.driver_namespace['getScale'] = getScale


The first part takes care of duplicating the arrows on the grid. As you can see, at the top there are some parameters you can change without going too much into the code.

The second part of the script creates and runs the drivers that control the scale of the arrows: it's a function that takes some of the parameters at the top of the script and calculates the scale of every single arrow. I strongly suggest you to check and modify the function to fit your needs, expecially if you are working on a scientific project.

The way I set it up is using a normal quadratic interpolation:

this is not very good looking, but you'll have the pick the interpolation you prefer. Also, note that in the script the size of the control affects the field as well.

For the color, there is just one material that calculates the distance between each arrow and the control (the control's position is gathered with 3 drivers) and feeds it in a ColorRamp