Oct 032013
 

[EDIT] Please check out the newest version of the FX Code (v0.51) with Android Bluetooth Control App and Chrome Control Extension.

[EDIT] Fixed a really dumb problem in the Arduino code, added a color picker to the python GUI, and uploaded a new video demo. The problem was I was using if (serial.available()) and should have been using while. That gummed up the works and made the LEDs flicker if you moved the sliders too fast. That’s fixed now. Should have waited and tested better but I was all excited to get this posted- live and learn, or more likely just repeat the same mistakes and correct myself as I go along.

Here’s another revision to the FastSPI2 effects demo code. Some code cleanups, a few new effects, and a python GUI (gtk). GUI can select effect by name and control brightness, delay, color-step, hue, and saturation of various effects.

Screenshot from 2013-10-03 19:52:46

Here’s the Arduino Code

Here’s the Python Code

 

If you find this really useful, please consider donating a little to the cause. Thanks!



I’m also grateful for bitcoin donations to: 1K5Yy77ejes2FZrHBG5fns3QAicnwZcduq

Apr 102013
 

I would like to introduce:

Stanley Tweedle – Captain of the Lexx.
Formerly Security Guard Class 4 for His Divine Shadow, and Assistant Deputy Backup Courier for the Austral B Heretics.

2013-04-05_16-43-58_5892013-03-16_16-51-29_671

I have a new project that will have to borrow time from my robot stuff for a bit, so I wanted to go ahead and post what
I’ve done so far, mostly for my own reference when I go to pick this up again.

PARTS:
(1) Arduino Nano
(2) 9g Continuous Rotation Hobby Servo
(1) Ultrasonic Rangefinder
(1) 6DOF Acc/Gyro
(1) USB 5V Battery
(3) WS2811 LEDs
(1) Bluetooth chip

Tweedle is complete hardware wise, but I have a little more coding to do before I’m satisfied with his brains. I ran out
of space in the Nano for anything other than input/output so all the control is done from a remote PC via python over
bluetooth/serial. I also made a wiimote script to control him manually. His brains is just basic obstacle avoidance right
now, still trying to see how much nav/odom info I can derive from a 6DOF sensor. Dead reckoning would result in massive
error accumulation, so for right now it just tells him orientation.
Anyway I’m pretty happy with how he’s turned out so far and he’s been a lot of fun. I’m usually not concerned with
aesthetics of these kind of things but I think he’s kinda cute.

This probably won’t help anyone because if you’re deep enough in your a project to understand my code- you’re deep enough
to write it yourself probably faster than it would take to adapt mine to your project… but here is is anyway.

Tweedle Arduino Sketch
Python Ncurses Control Program
Python WiiMote Teleop Program (NOT WORKING)
DOWNLOAD

And here’s some more pics of the wiring…

z2013-09-14_11-34-50_778 z2013-09-14_11-35-19_156 z2013-09-14_11-35-28_663 z2013-09-14_11-36-24_726 z2013-09-14_11-36-40_360

 

Aug 202012
 

I guess I’ve been using Blender for so much for so long that I tend to look for ‘Blender-like’ controls in a/v projects. So inevitably when I started working with LED strips I immediately tried to weasel out of having to think through functions and loops in arduino code to create effects I could do intuitively in Blender.

So after a few bad UI attempts I thought – hey, wish I could just design a light sequence in Blender and run it with ALT-A. So that’s what I did.

On the arduino side it’s using the FastSPI and CmdMessenger libraries for LED and serial communications.

The Blender script just reads the diffuse color in r-g-b from each LED objects material and spits it out to the USB port. Getting the pyserial library hooked up in Blender wasn’t a breeze but the “sys.path.append” line should help anyone having the same issues I did.

Here’s the arduino code and Blender file

(Using Arduino Duemilanove 328 and LED strip with WS2801 chips)

EDIT:

Blendernation article (Thanks Bart!)

I forgot to mention I’m using Ubuntu so the sys.path.append thing wont work for windows, you’ll have to find the pyserial library solution elsewhere (there’s plenty of reference out there)

Also – the script runs on each frame change. Here’s how that works (WARNING: kinda hacky) http://funkboxing.com/wordpress/?p=236

QUESTION: For any API guru’s out there – currently this script opens and closes the serial port on each framechange. I know this is radically inefficient. Any ideas on how to keep the serial port open persistently but to close it when blender closes?

 

 

 

 

Dec 272011
 

This is an attempt to merge Blenders Dynamic Paint feature with cellular automata. It started as a python script but then became even more of an educational experience when I realized python wasn’t going to be fast enough to run conway’s life on a 64x grid, let alone a 4Kx one, which was my initial goal. These ended up being 512x grids. I could have gone bigger but I’m using a little netbook for all this so I didn’t go nuts.

After figuring out that python wasn’t going to be fast enough I set out to make a c++ version, not in Blender, just in c++. Long story short it’s an atrocity of loops inside a main function. I didn’t even bother to pass any arguments, just recompiled every time I changed paths. Anyway it ended up being lots faster than the py scripts and I finally had an excuse to write a function I knew very well in a language I’ve been intimidated by for some time (and still very much am).

The c++ code uses the ImageMagick++ library, which made things much easier, but you’ll have to get this lib if you want to compile and use this. Hopefully this whole process has prepared me to get on porting the lighting generator to c++, which really needs to happen if if it’s ever going to be more than a gimmick.

So anyway, here’s the c++ code and here’s the Blender python script that I abandoned in favor of doing it in c++. For the record- this is bad, bad code. Very bad. Also here’s the command line to compile with g++ and imageMagick++, since that took awhile to get past.

conway_cpp_py.zip

user@pc:~$ g++ `Magick++-config –cxxflags –cppflags` conway.cpp -o conway `Magick++-config –ldflags –libs`

Here’s the process for using this to dynamic paint with conways life.

1) dynamically paint a canvas with a brush. This will paint ‘live’ cells onto the canvas
Turn on ‘dissolve’ and set to dissolve in 1-3 frames. Otherwise these become ‘immortal’ cells, which makes for a weird simulation.
I used red channel only for these demos.

2) compile and run the c++ code.
This will run the simulation on the dynamic paint cache images. It runs the simulation from the initial frame, but always includes the red cells from the next dynamic paint frame so they will be used in the next simulation step.

3) use this simulation output as a map in place of the dynamic paint output.
Sounds easy, and it kind of is, and kind of isn’t.
So if you want to do this yourself- if you know c++ it should be easy. If you don’t it will be very hard. If you’re just learning c++ it may be worthwile to try.

Not sure where I’m going with all this, as usual it was just something to do. Hope you dig it.

 

 

Dec 182011
 

Here’s a simple script that lets you ‘bookmark’ camera positions.

It’s a little redundant since the same thing can be accomplished a number of different ways but after a discussion with another BR BUG member I thought I’d take a swing. So here’s the script (right-clk>save as)

camera_marks

Just uncompress, then copy the script to your addons folder and then activate.

You get a panel in the 3DView>Toolbar that lets you add, delete, and change marks.

 

 

 

 

 

It saves the loc/rot/dofdist/lens to a textblock called CAMERAMARKS. I know this is a hacky implementation but I’m a hack and that’s just what I do. It’s super rudimentary now but it was only about 3 hours of coding and most of that was looking through old code to remember how to setup the UI, which I needed a refresher on anyway so this was a good little project. So tell me what you think, if it’s useful, what it needs to become useful, etc.

Jul 112011
 

BA Thread

What it Is – ProgrAnimals is an initial framework for variable morphology pose-controlled physics-based animation in Blender, whatever that means.

What it Does – In simplest terms this script creates a game-engine physics based ‘walking ragdoll’ from a user-defined armature, from humanoid biped to something much more bizarre. I think the game ‘Spore’ is probably the best analogy, where people can make creatures and they sort of walk or hobble based on how they’re built. This is the same notion, except much less automatic right now. The user has to define a little more about structure, muscles, and gait.

Why it Be – This is inspired first and foremost by my enduring love of doing horrible things to ragdolls, for which I make no excuses or apologies. The implementation is inspired especially by Cartwheel-3d, SIMBICON, and Philippe Beaudoin, and also by Ari Shapiro’s DANCE. The future goals of this are somewhere between Endorphin, Spore, and may also include possible robotics integration with Arduino. Ultimately I’d like to create a break-dancing robot army to help me stamp out tyranny, oppression, and tired dance moves.

This is the unexpected result of some of what I learned from the whole progranimation thing. I thought I would make a more complex pose-control system, but I ended up wanting to make a more generalized system that could work with arbitrary leg configurations. Originally I think it had something to do with making circuit components walk around on a circuit board but that’s another story, might still do that though. Anyway- this is actually a vastly simplified controller compared to Uno and Deuce in progranimation. No balance feedback, no uprightness vector, not even a collision sensor on the feet, it’s just proportional derivative controllers and a timed state-machine. It’s about the most bare-bones pose-controller I think you could make, but it’s still hilarious to watch it make stuff walk around. I hope to expand from here by giving the torso and legs considerable options as far as number of states, balance sensors, state-switching reactions, etc. First I wanted to get something functional and this is it.

I hope this will be useful and interesting, but it may take a little time to get a creature working. That said, it can be very fun and I hope I’ve made it easy enough to use that most Blender users can figure it out. Here are a couple of walk-throughs that demonstrate how the process works.

I. EDITING WALK STYLES – Changing the gait of a pre-made biped rig.

1) Download this file ProgrAnimals-I-biped.blend and open in Blender2.58a

2) Press ‘P’ to run game engine. Watch as very little happens. Press ‘ESC’ to stop game.

3) Select the iARMa-pg-0 armature (pose-goal armature). Switch to POSE MODE, and change the pose to something approximating this screenshot.

[Exact settings: BONE x|y|z rotation : THIGH0 -45|0|0 | SHIN0 90|0|0 : THIGH1 15|0|0]

4a) Run game again (P).

EXPLANATION: The left leg in the pose-goal armature is the ‘Swing Leg’, the right is the ‘Stance Leg’. They are the pose-goals that the leg will try to assume when in this state. Poses can also be stored in poseLib for convenience.

4b) while not bored: change settings; run game again (P).

5) Select the iARMa armature and switch to EDIT MODE.

6) Select each THIGH bone, change the bones Custom Property legstate = 0 on both.

7a) Switch to OBJECT MODE. Run game again (P).

EXPLANATION: legstate defines if the leg starts on swing or stance, setting both to the same makes the ragdoll jump.

7b) Change one thigh back to legstate = 1 (make the ragdoll walk again)

8} Select the iARMa-THIGHl-k empty (best to select from outliner). Look at the Scale values in the ‘N’ properties view. Change the ‘X’ scale to 10. Do the same on iARMa-THIGHr-k.

9) Run game again

EXPLANATION: The scale setting on these empties define the stiffness and damping parameters for their joints. See progranimation for a better explanation of PD controllers)

10) Edit the iARMa armature. Select the TORSO bone – change the bones Custom Properties: statetimer = .25; zgoal = ‘BALL’

11) Switch to OBJECT MODE. Run game again (P)

EXPLANATION: statetimer times the switch between states, zgoal defines the heading goal of the character. zgoal can be the name of an object or an angle in degrees using the prefix ‘a:’ ex. a:45

 

II. SETTING UP A NEW CREATURE

1) Download this file ProgrAnimals-II-quad.blend and open in Blender2.58a.

2) Select the iARMq armature.

3) In the script editor make sure the variable setupSEQ = 0. Run the script ALT-P. This script will add custom properties to the bones of this armature based on the names of the bones.

BONE SETUP/NAMES:
The script will use bone names as a starting point to setup constraints with axis and angle limits for standard joints. see code for values. THIGH, SHIN, FOOT, TOE, REVKNEE, just use these strings somewhere in the bone. The names aren’t necessary but they make setup much easier as they add the necessary Custom Properties to the bones.

CUSTOM PROPERTIES ADDED TO BONES:
TORSO
statetimer: time to switch states
zgoal: goal in degress ‘a:45′ or object name ‘Cube’
THIGHS
legstate: leg start state (0-swing/1-stance)
legtype: type of leg config (for multi leg setups)
ALL BONES:
usebone: create box for this bone
xyzmin/xyzmax: values to be used to create 6dof rigid body joints
*usebone and legtype are the only values that cannot be modified after this step

4) Select the armature, enter EDIT MODE. Make sure Custom Properties were added to bones. Select the THIGH bones. Change the value of legtype so the front legs are ‘0’ and the back legs are ‘1’. This will let the program distinguish between the different types of legs and will create pose-goal armatures for each leg type. You can have as many types of legs as you want, but for now they only have 2 states each: swing/stance.

5) Switch to OBJECT MODE. Select the armature. In the script editor set variable setupSEQ = 1. Run the script. This will create the boxes and empties for each bone. Boxes are game objects connected by rigid body constraints. Empties define stiffness/damp gains at each joint with their xyz scale values.

6) Select the armature. In the script editor set variable setupSEQ = 2. This will create pose goal armature(s) to be used to define swing/stance state pose goals for each leg type.

7) Adjust pose-goal armature poses as desired. Press ‘P’ to run game engine.

8} Design a crazy five-legged monster and make it chase some other crazy thing around.

9) Game> Record Animation. Rinse, Repeat.

NOTES FOR MAKING YOUR OWN CREATURE:
*Legs must at least have a thigh, the rest is optional. Feet are good to have though.
*Legs can be nearly any config as long as they do not branch (no double-footed legs or anything like that, a long tail is fine though).
*Use very short names on armature or bones, under 5 chars each (sorry).
*Do not use ‘-‘ (dashes) in the names of bones or armatures. I need those.
*The mass of each bone-box is determined by the length of the bone. This can make for very heavy limbs so you might want to adjust this. You may also want to change the shape of certain bone-boxes, that should work as long as you don’t change the origin.
*The settings created for THIGH, SHIN, FOOT, etc. are generic and can be changed to anything. The settings for each joint are combination of the rigid body constraint settings and the stiff/damp parameters. The initial setup of the rigid body constraint is defined by the xyzmin/xyzmax setting on the bone, you can change these Custom Properties before you create this bone-boxes, or you can adjust them in the constraint settings after they’re created.
*Characters should be created facing Y+ forwards.

 

III. TIMER OFFSET – Offsetting state switch timing.

This is a little cheat that offsets the state switch timing for a leg by a given amount. This allows sequential legs like the centipede guy, and galloping quadrupeds and whatnot. Setting it up can be a little tricky and depends on the creature design and the walk style you’re looking for.

Here is the .blend file with script with the timeroffset feature added. The example files for the previous tutorials do not have it. This file also contains all the creatures used in the demo video.

The timeroffset property is added to each leg bone in the armature when the first part of the setup is run (setupSEQ = 0). When the game objects are created the legs will use this bone property offset when that state is triggered.

That’s about it for the offset. It was a lot cheaper than breaking into more than two states and it works pretty well considering how simple it was to implement.

 

IV. BIG WARNING – BUGS and ERRORS and CRASHES! OH MY!

Creating the pose-goal armature in the setup (setupSEQ = 2) turned out to be a total fiasco. I had to con bpy.ops into making some bones for me and every once in awhile it just refuses. It’s a context thing but I never could figure out why it works sometimes and sometimes doesn’t. So enjoy that. If you have a problem with a rig, try it 3 more times, if it still wont work feel free to contact me, I’ll try to help you sort it out.


V. STUFF I HAVEN’T THOUGHT OF YET

I may add notes here in the future when I think of them.

Hey, here’s something- you can ‘deadleg’ a creature by turning all the usebone bone properties to False in a leg. I guess you could make a limping zombie character or something, though you’ll have to compensate the stiff/damp on the other leg so it’s strong enough to carry the weight and the poses will have to be offset so he stays sort of balanced.

Notes – Once you start playing with pose-goals you may notice that there is something horribly wrong with the joint torques. An extreme pose can lift the character off the ground and fly (not in a cool superman way, more like falling up). Clearly this is not physics. Working on that.

Also the feet didn’t stick to the ground like I’d expect so i added a hack where the obj.setLinVel.x.y = 0 on the last object in the chain of the stance leg, which ends up being the toe if you have one. So even in flight forward momentum is lost to this bs-friction-hack. Later I might try adding material friction to the feet or something.

In the future I’d really like to improve the whole implementation in Blender but I think the key will be porting it to the animation system once we get rigid body dynamics in the physics system. It would be great to have these rigs interact more cleanly with other dynamics. I love the game engine but the ‘Record Animation’ thing makes this a really weird workflow, glad it’s there though.

Why No UI? – mostly because the whole setup script is kind of sketchy as it is, it randomly crashes if  you keep remaking ragdolls from the same armature for some reason. Plus these are program driven animations so I think if you’re going to use this for anything you’re going to have to get into the code eventually anyway.

Personal Request – If you make a cool critter with this please show me! A render is worth a thousand comments. Hope you enjoy!

Jun 182011
 

To aid my never-ending quest to remember the things I learn about programming – I’ve decided to make this post as a place to leave little functions and crap that I always forget and are way too stupid to have to figure out more than once.

It’ll grow, I’m constantly learning things I forgot.

######################################
################ WARNING: ############
############## STUPID CODE ###########
######################################
#### PLEASE DO NOT LEARN ANYTHING ####
######################################

def sbh_within(x,y,d):
###---CHECK IF x-d <= y <= x+d
 if x-d <= y and x + d >= y:
 return True
 else: return False

def sbh_center2d(Ax, Ay, Bx, By):
###---GET CENTER BETWEEN TWO 2D POINTS
    Cx = Ax + (Bx - Ax)/2
    Cy = Ay + (By - Ay)/2
    return Cx, Cy

def sbh_dist2d(Ax, Ay, Bx, By):
###---GET DISTANCE BETWEEN TWO 2D POINTS
    Cx = Bx - Ax
    Cy = By - Ay
    return Cx, Cy

def sbh_hypot(a, b):
    c = sqrt(a*a+b*b)
    return c

def sbh_getAngle2d(A, B):
###---RETURNS HEADING FROM A TO B
    opp = B.y - A.y
    adj = B.x - A.x
    hyp = hypot(opp, adj)
    s = asin(opp/hyp)
    c = acos(adj/hyp)
    if B.x >= A.x and B.y >= A.y: r = s-pi/2
    if B.x <= A.x and B.y >= A.y: r = c-pi/2
    if B.x <= A.x and B.y <= A.y: r = (pi/2)-s
    if B.x >= A.x and B.y <= A.y: r = -(pi/2)-c
    return r

def sbh_si(num):
###---RETURNS SIGN OF A NUMBER
    if num>=0: return 1
    if num<0: return -1

def sbh_wrapAng(x):
###---WRAP EULER ANGLES (-pi <= a <= pi)
    p360 = pi*2
    f = x - (p360)*floor((x+pi)/p360)
    return f

—OTHER BLENDER PYTHON API NOTES—
Most of these are issues I’ve run into with and without solutions.

– Can not add game logic bricks via. python API. [SOLVED]
– Can not access poseLib data with bpy.data, only bpy.ops functions and none to read pose data.
– Voxel data files: .raw/.bvox – can’t use multi-frame data. Only 64x64x64 grid size works.

– active object – accessible with “bpy.context.scene.objects.active = ob”

 

May 272011
 

Trying to learn more about making controllers for actual robots, but the bge is cheaper than buying components. Thought I’d start simple so I made a little differential drive robot and some control stuff. Wanted to spice it up so I gave him a little scoop so he could pitch a ball up.

For now the drive control is completely retarded and the target (ball) sensor is arbitrary so it doesn’t mimic a real sensor like I meant it to. Working on the motor controls more right now.

.blend file (b2.57b)

The bot gets the ball, then goes to the ‘goal’, then pitches the ball up. No aiming yet, doesn’t even work real hard to point in the right direction. Sort of a spaz shot.

Actually this was an offshoot of some problems I was having while trying to make a 0G ‘satellite’ type bot. So I thought I’d limit myself to 2D for now.

May 102011
 

I don’t even know…

Okay, I guess I do know, I made it.
Why?
I don’t even know.
How?
bge and a simple gravity script of course.
wanna hear it? here is go!

import bge
from mathutils import Vector
co = bge.logic.getCurrentController()
scene = bge.logic.getCurrentScene()

obList = []
for o in scene.objects:
    if o.__class__ == bge.types.KX_GameObject:
        obList.append(o)

def calcGrav(obA, obB, G):
    m1 = obA.mass; m2 = obB.mass
    m = m1*m2
    loc1 = obA.worldPosition
    loc2 = obB.worldPosition
    v = loc1 - loc2
    r = v.length
    F = G * ( (m) / (r*r) )
    return -v * F

def loopGrav(obs, G):
    for obA in obs:
        fV = Vector((0,0,0))
        for obB in obs:
            if obA != obB:
                fV += calcGrav(obA, obB, G)
        obA.applyForce(fV, False)

loopGrav(obList, 1)

keyb = bge.logic.keyboard
if keyb.events[bge.events.ZKEY]>0:
    for ob in obList:
        ob.applyTorque(Vector((0,0,50)), False)

if keyb.events[bge.events.XKEY]>0:
    loopGrav(obList, -2.5)

if keyb.events[bge.events.CKEY]>0:
    loopGrav(obList, 15)


HOW TO:
– copy/paste script into blender text editor.
– setup an EMPTY object with logic nodes as shown.
– change ‘Engine’ from ‘Blender Render’ to ‘Blender Game’
– set World>Physics>Gravity to 0.0 (under Bullet)
– create some objects.
– hit ‘p’

This script will (should/might) make all meshes in the scene obey Newton.

Apr 132011
 

Blender.org Tracker –  BA Thread –  BlenderNation Article

UPDATE – 01.05.13 – v0.2.7
FIXES:
-Fixed the issue that prevented the addon from loading in Blender 2.63+. Also fixed a problem with the makeMeshCubes function.

UPDATE – 02.14.13 – v0.2.6
ISSUES:
-An API change has made the addon not load. It has something to do bpy.scene.context. I’ll look into it when I have a chance. Fortunately the script will still run as a regular script. If you want to use it, just use the .blend file below or just load it in the text editor and hit run.

UPDATE – 06.20.11 – v0.2.6
FIXES:
-Moderate speedup.
-Cubes output scale/loc corrected.
-Tooltips added.
NEW FEATURES:
-Container insulators: Arbitrary mesh shapes can be used as insulator/cloud objects. Still quite imperfect though. May slow down generation. Best for simple containers; bowl, cup, bottle. A spiral pipe would not work well. Must have rot=0, scale=1, and origin set to geometry.
-Mesh origin objects:. If the origin obj is a mesh, vert locations will be used as initial charges. However this will disable multi-mesh output. May slow down generation.

UPDATE – 05.08.11 – v.0.2.5
NEW STUFF:
-added ‘single mesh’ output option. use this mesh with build modifier to ‘grow’ lightning in animation.

If you find this really useful, please consider donating a little to the cause. Thanks!



I’m also grateful for bitcoin donations to: 1K5Yy77ejes2FZrHBG5fns3QAicnwZcduq

 

This is a partial implementation of the algorithm presented in the paper ‘Fast Simulation of Laplacian Growth’
and some concepts borrowed from Fast Animation of Lightning Using an Adaptive Mesh

It currently uses simplified spherical boundary conditions and calculates potential at candidate growth sites using FSLG-Eqn. 9
To be properly influenced by an environment map of charges and
allow artistic manipulation of growth patterns I will need to
implement FSLG-Eqn. 15, which I don’t fully understand yet.

As compared to the simulation times reported in the paper, there is no comparison. This is not fast. They report 2000 particles in 6 seconds. So far 1000 particles will take a few minutes.

A good chunk of the reason for the slowness is the weighted random choice function. Another big reason is it’s python not c. Probably the biggest reason is that I’m a hack and I barely cobbled this together so it’ll take time to get it optimized.

Anyway I think it’s better than making lightning by hand, or at least might give you a good base mesh to mess with. So it might be useful to someone. I’ll keep working on it.

DIRECTIONS:
you can use the example .blend file or load as an addon.

BLEND FILE:
-Download .blend* file, instructions in file. *right-click, save-as [works with Blender 2.5 – 2.62]
-Download .blend* file, instructions in file. *right-click, save-as [works with Blender 2.63+]

ADDON:
-Download script (object_laplace_lightningv026.rar) [this version of the addon only works with Blender 2.5 – 2.62]
-Download script (object_laplace_lightningv027.zip) [this version of the addon works with Blender 2.63+]
-Uncompress, Place in in Blender ‘addons’ folder:
Blender install folder/2.6x/scripts/addons/
-Enable addon
UI will be in >View3D>Tool Shelf>Laplacian Lightning (object mode)

-Hit ‘generate’ – try w/ defaults

-Play with the settings, try again.

iterations – how many times to run loop (number of particles) grid unit size – size of a ‘cell’ in BU
straighness – user variable to control branchiness/straighness
start charge – origin point
use ground charge plane – hacky method of simulating lightning strike. Terminate loop if lightning hits ‘ground’.
ground Z co – z coordinate of ground plane
ground charge – charge of ground plane
mesh, cube, voxel – visualization outputs
mesh – creates vert/edge mesh from data
cube – creates cube objects from data
voxel – creates a 64x64x64 voxel data file from data outputs to ‘FSLGvoxels.raw’ (experimental)

Hope you enjoy. Send me a link to some renders if you use it! Especially if you get >10,000 particles.