Skip to content

Instantly share code, notes, and snippets.

@zeffii
Created December 13, 2011 16:00
Show Gist options
  • Save zeffii/1472674 to your computer and use it in GitHub Desktop.
Save zeffii/1472674 to your computer and use it in GitHub Desktop.
LIGGGGHTS parser for blender
import bpy
import time
from mathutils import Vector
# purposely coded verbosely in places. relax :)
'''
about the data being processed here:
we have 11 elements per line. Per particle snapshot they inform us about:
Element[0] = track num
Element[1] = timestamp = num * 0.35ms (from the start)
Element[2,3,4] = Position Px,Py,Pz
Element[5,6,7] = Velocity in Vx, Vy, Vz
Element[8,9,10] = Acceleration in Ax,Ay,Az
TODO[ ] turn into seperate splines
# while testing
break_token
322 is the first track
330 is first 2 tracks
649 is track 1, 2 and 3
671 = 1,2,3,4
'''
# setup reading location, and global variables
data_directory = '/home/zeffii/Downloads/Physics/'
datafile = 'test_data_trkflag_timestamp_1.txt'
# lpt_name = "LPT_REP" # name of object for scene
# optional, use these to look at a subset of the data
skip_value = 1 # default 1, is full set
use_tokens = True # True = set a cutoff point, False = entire dataset
start_token = 0 # start importing from this line, 0 for start
break_token = 27671 # don't import beyond this line or until dataset ends.
last_frame = 0.0
# spline setup
w = 1 # weight
minimtl = 22 # default 1, track segments minimally present before importing
def printTimeStamp():
# divider + timestamp
print("\n" + "="*19 + time.ctime() + "="*19)
def printListed(vec_list):
iter = 0
for item in vec_list:
print("track: ",iter, "="*12, "has", len(item), "data points")
for instance in item:
print(instance[0:5])
iter += 1
'''
def CreateMesh(num_param, data_set):
# debug prints, for flow control
debug_string = "num_param = " + str(num_param)
debug_string += " & data_set length = " + str(len(data_set))
print("Reaching CreateMesh with data: " + debug_string)
# make new mesh, add vertices using coordinates
Verts = []
for data_segment in data_set:
xfloat = float(data_segment[2])
yfloat = float(data_segment[3])
zfloat = float(data_segment[4])
unique_vertex = Vector((xfloat, yfloat, zfloat))
Verts.append(unique_vertex)
test_mesh = bpy.data.meshes.new("LPT_DATA")
test_mesh.from_pydata(Verts, [], [])
test_mesh.update()
new_object = bpy.data.objects.new(lpt_name, test_mesh)
new_object.data = test_mesh
scene = bpy.context.scene
scene.objects.link(new_object)
new_object.select = True
'''
def GenerateObjects(multi_list):
# printListed(multi_list)
maxlen = len(str(len(multi_list)))
def MakePolyline(pname, objname, rawList):
cList = []
for elem in rawList:
xfloat = float(elem[2])
yfloat = float(elem[3])
zfloat = float(elem[4])
unique_vertex = Vector((xfloat, yfloat, zfloat))
cList.append(unique_vertex)
# create path data and add it to a scene object, then link to scene.
curvedata = bpy.data.curves.new(name=pname, type='CURVE')
objectdata = bpy.data.objects.new(objname, curvedata)
objectdata.location = (0,0,0) #object origin
bpy.context.scene.objects.link(objectdata)
# trajectory settings
curvedata.dimensions = '3D'
curvedata.use_path = True
curvedata.use_path_follow = True
curvedata.path_duration = 100
# takes first and last timestamp for track.
first_vis_frame = float(rawList[0][1])
last_vis_frame = float(rawList[-1][1])
# animate path
curvedata.eval_time = 0
curvedata.keyframe_insert(data_path="eval_time", frame=first_vis_frame)
curvedata.eval_time = 100
curvedata.keyframe_insert(data_path="eval_time", frame=last_vis_frame)
# set to linear, hax!
action_name = pname+"Action"
this_keyframe_collection = bpy.data.actions[action_name].fcurves[0]
for keyframe in this_keyframe_collection.keyframe_points:
keyframe.interpolation = 'LINEAR'
# because we have so much exact data 'POLY' suffices.
polyline = curvedata.splines.new('POLY')
polyline.use_cyclic_u = False
polyline.use_endpoint_u = True
polyline.points.add(len(cList)-1)
for num in range(len(cList)):
x, y, z = cList[num]
polyline.points[num].co = (x, y, z, w)
# insert icosahedron, attach to curve object
bpy.ops.mesh.primitive_ico_sphere_add(subdivisions=2, size=0.0007)
particle = bpy.context.object
pconstraint = particle.constraints.new('FOLLOW_PATH')
pconstraint.target = objectdata
pconstraint.use_curve_follow = True
pconstraint.use_curve_radius = True # ?
pconstraint.use_fixed_location = False
pconstraint.forward_axis = 'FORWARD_Z' # ?
pconstraint.up_axis = 'UP_Y' #?
# deal with very last frame some other way.
time_and_state_settings = ( (0, True),
(first_vis_frame-1, True),
(first_vis_frame, False),
(last_vis_frame, False),
(last_vis_frame+1, True),
(last_frame, True))
for time_val in time_and_state_settings:
current_frame = time_val[0]
bpy.ops.anim.change_frame(frame=current_frame)
bpy.context.active_object.hide = time_val[1]
bpy.context.active_object.keyframe_insert( data_path="hide",
index=-1,
frame=current_frame)
# objname can be hidden.
bpy.context.scene.objects.active = bpy.data.objects[objname]
bpy.context.active_object.hide = True
return
iter = 0
for track in multi_list:
curvenum = str(iter).zfill(maxlen)
pname = "mycurve_" + curvenum
objname = "CurveName_" + curvenum
# to adjust the minimum track length to import, modify minimtl
# in the global variables above.
if len(track) > minimtl:
MakePolyline(pname, objname, track)
iter+=1
print("making:",iter,"tracks")
return
'''
# looks like i could refactor CreateMesh and CreateWireBounds
def CreateWireBounds(box_coordinates):
print("making wire bounding_box object")
# printList(box_coordinates)
# hardcode some edges
Edges = [ [0,1],[1,2],[2,3],[3,0],
[4,5],[5,6],[6,7],[7,4],
[0,4],[1,5],[2,6],[3,7]]
b_mesh = bpy.data.meshes.new("WIRE_BOX_DATA")
b_mesh.from_pydata(box_coordinates, Edges, [])
b_mesh.update()
box_object = bpy.data.objects.new("WIRE_BOX", b_mesh)
box_object.data = b_mesh
scene = bpy.context.scene
scene.objects.link(box_object)
box_object.select = True
def ConstructBoundingBox():
bpy.context.scene.update() # necessary sometimes
box_Vector = bpy.data.objects[lpt_name].dimensions
print(box_Vector)
# make bounding box 3dGrid
box_coordinates = bpy.data.objects[lpt_name].bound_box
CreateWireBounds(box_coordinates)
return
'''
def MakeHistogram(pnum, ldata):
print("Entering MakeHistogram function:")
print("--Total data points stored: ",len(ldata))
multi_list, temp_list = [],[]
# get first track num, this is a one off necessity
tracknum = ldata[0][0]
# start digging through the data
for i in range(len(ldata)):
tracknum_line = ldata[i][0]
if not tracknum_line == tracknum:
multi_list.append(temp_list) #no more items for this track
temp_list = [] # re-init storage list
temp_list.append(ldata[i])
tracknum = tracknum_line
# if last line, then add templist to multilist
if i == len(ldata)-1:
multi_list.append(temp_list)
return multi_list
def InitFunction():
global last_frame
def isBeyondToken(line_num):
if use_tokens == False: return True
if line_num <= break_token: return True
else:
return False
num_lines = 0
line_checking_list = [] # list to check for consistency
line_data_list = [] # list to append the various data values onto
dataset = open(data_directory + datafile)
# should be rewritten, it's not very pretty
for line in dataset:
if not isBeyondToken(num_lines):
break # stop importing if beyond
if num_lines % skip_value == 0:
if (num_lines >= start_token) or use_tokens == False:
items = line.split(",")
line_checking_list.append(len(items))
line_data_list.append(items)
print(items[1])
if float(items[1]) > last_frame:
last_frame = float(items[1])
print("current last frame:", last_frame)
num_lines += 1
dataset.close() # to be polite.
print("done reading data")
# use break token to set the end of the animation
print(last_frame)
bpy.context.scene.frame_end = last_frame
# detect anomalies first, before getting hopes up.
set_check = set(line_checking_list)
if len(set_check) == 1: # means no variation
printTimeStamp()
print("Number of lines in original dataset: ",num_lines)
if skip_value == 1: print("not skipping any lines")
else:
print("Skipping every",skip_value, "lines")
num_parameters = list(set_check)[0] # gives parameters per line
multi_list = MakeHistogram(num_parameters, line_data_list)
GenerateObjects(multi_list)
# CreateMesh(num_parameters, line_data_list)
# ConstructBoundingBox() # manually for grid drawing
else:
print("There exists variance in the data, won't proceed")
print("At least one line contains unexpected data")
return
return
InitFunction()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment