Created
December 13, 2011 16:00
-
-
Save zeffii/1472674 to your computer and use it in GitHub Desktop.
LIGGGGHTS parser for blender
This file contains hidden or 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 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