Posted: Thu May 31, 2012 8:00 am
Joined: 31 May 2012
Posts: 8
First off, I want to thank you for your time. A little overview: I play a game called League of Legends. Using a program called LOLReplay, I can have replay any match and record it with Frapps. The LOLReplay program doesn't save the positioning of my mouse and button presses though. So I wrote a program to save that information as I play. The output of that program looks something like this for the mouse positions: 254,12;254,14;269,23;. In the format x,y; x,y; My eventual goal is to load these positions into blender and render the mouse movement with something fancy like a glowing cloud cursor or something and then overlay that onto my video from Frapps. My problem is, I don't know how to load the "keyframes" for the cursor into Blender.
Posted: Thu May 31, 2012 3:21 pm
Joined: 05 Apr 2009
Posts: 695
so you want to:
- read cursor data from file
- keyframe an object with this data in blender
there are a lot import scripts, you should have a look at them
keyframing example:
http://www.blender.org/documentation/blender_python_api_2_63_7/info_quickstart.html#animation_________________
I'm sitting, waiting, wishing, building Blender in superstition...
Posted: Thu May 31, 2012 7:37 pm
Joined: 05 Apr 2009
Posts: 695
Here's some working code:
| Code: |
import bpy
def create_cursor(context, filepath):
if context.object and context.object.mode != 'OBJECT':
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
#for ob in bpy.data.objects:
# ob.select = False
bpy.ops.object.select_all(action='DESELECT')
# Add empty object
ob = bpy.data.objects.new("Cursor", None)
context.scene.objects.link(ob)
#ob.location.y = context.scene.cursor_location.y
context.scene.objects.active = ob
ob.select = True
f = open(filepath, 'r')
data = f.read()
f.close()
data = data.replace(" ", "").strip(",;")
#x, y = [pairs.split(",") for pairs in data.split(";")]
pairs = data.split(";")
for frame, pair in enumerate(pairs, context.scene.frame_current):
# Cast coords from string to int
pair = [int(pair) for pair in pair.split(",")]
# Keyframe xz locations to be viewed from front view
ob.location.x = pair[0]
ob.keyframe_insert("location", index=0, frame=frame)
ob.location.z = pair[1]
ob.keyframe_insert("location", index=2, frame=frame)
context.scene.update()
return {'FINISHED'}
# ImportHelper is a helper class, defines filename and
# invoke() function which calls the file selector.
from bpy_extras.io_utils import ImportHelper
from bpy.props import StringProperty
from bpy.types import Operator
class ImportCursor(Operator, ImportHelper):
'''Import X and Z values in the format: x1,y1;x2,y2; etc.'''
bl_idname = "import_anim.cursor"
bl_label = "Import Cursor animation"
# ImportHelper mixin class uses this
filename_ext = ".txt"
filter_glob = StringProperty(
default="*.txt",
options={'HIDDEN'},
)
def execute(self, context):
return create_cursor(context, self.filepath)
# Only needed if you want to add into a dynamic menu
def menu_func_import(self, context):
self.layout.operator(ImportCursor.bl_idname)
def register():
bpy.utils.register_class(ImportCursor)
bpy.types.INFO_MT_file_import.append(menu_func_import)
def unregister():
bpy.utils.unregister_class(ImportCursor)
bpy.types.INFO_MT_file_import.remove(menu_func_import)
if __name__ == "__main__":
register()
# test call
bpy.ops.import_anim.cursor('INVOKE_DEFAULT')
|
_________________
I'm sitting, waiting, wishing, building Blender in superstition...
Posted: Fri Jun 01, 2012 7:49 am
Joined: 31 May 2012
Posts: 8
I stayed up late last night fixing a few of the issues. I had found the link you just gave me and hacked up what I thought would work. Unfortunately there was an issue that needed to be addressed. My fix changes my mouse programs output. It used to just grab mouse position and save it each time there was a change in x or y coordinates. System performance would effect the "resolution" of my mouse position sampling and the output did not adhere to any kind of time structure.
So I rewrote the sampling loop. It now takes samples based on a limited "frame rate". Right now that number is set to 30 frames per second. So each second I get 30 mouse positions spaced evenly over that second. Also I keep a frame count. The new output structure looks like this:
| Code: |
| xPostion,yPosition,Frame; |
At the time I was unsure of how to interface a file with blender so I wrote a separate script to convert the output file into a blender readable script. Unfortunately this option loses viability with large file types as it has a 1:16 size ratio per each mouse sample.
| Code: |
listX = []
listY = []
listT = []
listZ = []
fps = 29.99
iterator = 0
for line in open("mousedump.csv", "r"):
listZ = line.split(",")
listX.append(int(listZ[0]))
listY.append(int(listZ[1]))
listT.append(float(listZ[2].strip(";\n")))
output = open("keyframe.py", "w")
output.write("import bpy\n")
output.write("obj = bpy.context.object\n")
print len(listX)
print len(listY)
print len(listT)
while(iterator < len(listX)):
output.write("obj.location[0]=")
output.write(str(listX[iterator]))
output.write("\n")
output.write("obj.location[1]=")
output.write(str(listY[iterator]))
output.write("\n")
output.write("obj.keyframe_insert(data_path=\"location\", frame=")
output.write((str(listT[iterator])))
output.write(", index=2)\n")
iterator += 1
output.close() |
When I ran the output from the above program in Blender with the default cube selected it would shoot of into space. This was a design oversight by me. How can I convert my mouse position data so that it stay on the grid? I will keep track of my screen resolution and set the render resolution to the same value, but I need the empty object to move around in front of the camera.
Once again, you helped is greatly appreciated.[/b][/list]
Posted: Fri Jun 01, 2012 8:32 am
Joined: 31 May 2012
Posts: 8
From what I can tell this does the trick.
| Code: |
# Keyframe xz locations to be viewed from front view
ob.location.x = pair[0]
ob.keyframe_insert("location", index=0, frame=[2])
ob.location.z = pair[1]
ob.keyframe_insert("location", index=2, frame=[2]) |
Posted: Fri Jun 01, 2012 8:43 am
Joined: 31 May 2012
Posts: 8
Your method works for me at a small scale; however, my files have upwards of 60,000 entries. When I run a sample file through it, containing 60,281 individual frames, my blender is just left hanging for a long time. I'm unsure if it is completing the operation slowly or it is out of memory. Keep in mind it is only really about 1MB worth of data.
Posted: Fri Jun 01, 2012 1:42 pm
Joined: 05 Apr 2009
Posts: 695
could you provide this 1mb file so i can test?
i don't really understand why you added a frame counter, isn't it just 1,2,3,4,... ?
_________________
I'm sitting, waiting, wishing, building Blender in superstition...
Posted: Fri Jun 01, 2012 7:07 pm
Joined: 31 May 2012
Posts: 8
I am a new to programming so sometimes I don't fully think things through. I didn't realize I could go without including the frames. Anyway, here is the file.
https://docs.google.com/open?id=0B5VXpPSW8occZ0FJOVJINm5zQ2c
Posted: Fri Jun 01, 2012 7:08 pm
Joined: 31 May 2012
Posts: 8
On my computer, chunks of 10,000 would stop it for a second, but they would load properly.
Posted: Sat Jun 02, 2012 3:14 am
Joined: 05 Apr 2009
Posts: 695
ya, same here. This loads 60k positions in less than 5 seconds
http://www.pasteall.org/32512/python
NOTE: this expects txt input like:
So each coord in a new line, x and y separated by a comma, no whitespace
you shouldn't go to Animation screen, lags like hell.
Set sync mode to frame dropping for playback.
I added a random x / 100 to limit the movements, you should be able to limit to actual bounds with some extra math
_________________
I'm sitting, waiting, wishing, building Blender in superstition...
Posted: Sat Jun 02, 2012 11:15 pm
Joined: 31 May 2012
Posts: 8
How long have you been scripting for blender? This works great by the way
Posted: Sun Jun 03, 2012 12:00 am
Joined: 31 May 2012
Posts: 8
Where was the bottleneck in that code?
Posted: Sun Jun 03, 2012 1:51 am
Joined: 05 Apr 2009
Posts: 695
I started to learn Python and Blender API 1 year ago.
Bottleneck is mostly operators, as they implicitly update scene or stuff, which means extra memory consumption and decreasing speed for each loop iteration:
run op, update object 1
run op, update object 1, 2
run op, update object 1, 2, 3
etc.
using "low-level" functions is way faster but more difficult
you could improve performance if you skipped subsequent duplicates, like x coord:
1, 2, 2, 2, 2, 3, 3
no need to store all two's, first and last would be just fine:
1, 2, skip frames, 2, 3, 3
should be done in your mouse recording script already to keep filesize down (required frame counter)
_________________
I'm sitting, waiting, wishing, building Blender in superstition...