Page 5 of 10
Re: Animations - Creating a Curve2IPO wizard
Posted: Tue Jul 15, 2008 3:51 am
by Grogyan
Found some interesting data, that if some could verify for me
[[BezTriple
[-22.731007, -0.970000, 0.000000]
[1.000000, -0.970000, 0.000000]
[24.731007, -70000, 0.000000],
I've reformatted this slightly from how its shown but its the same, its just easier to read like this
Anyway the first line is for the first handle
the second is for the knot
the third is for the second handle
I don't know what the 3rd value in the matrix is for its just plain zero
The first float in each array in the matrix corresponds to time
the second responds to I think the extent on that axis relative to the objects centre
the second float is the frame number followed by its extent on the axis
The third array is the same as the first but with different extents it has
so now that I think I have the value of that curve, must remember that I cannot feed this back into the append function as its layout is completely different from what it expects
Re: Animations - Creating a Curve2IPO wizard
Posted: Tue Jul 15, 2008 12:26 pm
by Christian Walther
Grogyan wrote:Found some interesting data, that if some could verify for me
I'm not sure what your question is, due to lack of question marks in your post, but I assume it's this:
I don't know what the 3rd value in the matrix is for its just plain zero
That's the third dimension. For a curve in 3D space it would be the Z coordinate. Since Ipo curves live in a 2-dimensional space, it's unused here. As you observed, the first dimension is time, and the second is whatever quantity the curve describes.
(At least that's what I assume, based on my experimentation. I don't have this on any authority.)
Re: Animations - Creating a Curve2IPO wizard
Posted: Wed Jul 16, 2008 2:32 pm
by Nadnerb
Yes, this is how the bezier handles are stored (or at least returned in the python interface) I would have assumed you knew this following all the work you've done so far, but then I haven't been following this very closely.
A bezTriple has multiple methods of accessing the same data. You can get only the points on the curve (or "knots") from bezTriple.pt, which returns [time, value], or you can get the entire handle via bezTriple.vec
bezTriple.vec[0] and [2] return the outer handles, which are in the same coordinate space as the points on the curve, and are returned as [time, value, 0]
bezTriple.vec[1] is the same as bezTriple.pt (except with an extra zero at the end, since it's returning lists of 3 floats)
Some rather old documentation
Re: Animations - Creating a Curve2IPO wizard
Posted: Thu Jul 17, 2008 2:42 am
by Grogyan
Ah, ok I was quite confused as to why I keep reading similar scripts and they have only 1 float, cause the compiler complains that its not a tuple -> usually something i've done wrong

Its pretty late tonight to work on it, will see what happens tomorrow or the weekend
Will feeding data for that handle actually show up in the Ipo, the API isn't too clear on that?
Re: Animations - Creating a Curve2IPO wizard
Posted: Thu Jul 24, 2008 9:58 pm
by Grogyan
Back to work now on this script, and I have been getting some help from BlenderArtists, and I reckon the script is getting better with each little thing I learn about it.
I do think I have nailed that BezTriple problem down, thanks to FunkyWrym, just gonna try some revisions to the code
Re: Animations - Creating a Curve2IPO wizard
Posted: Thu Jul 24, 2008 10:09 pm
by Grogyan
Woohoo, Grogyan does a happy dance, it works, it works!!!

Code that did it is
Code: Select all
# Store all bezier points
H1_X = nCurvePoints.vec[0][0]
H1_Y = nCurvePoints.vec[0][0]
H1_Z = nCurvePoints.vec[0][2]
P_X = nCurvePoints.vec[1][0]
P_Y = nCurvePoints.vec[1][1]
P_Z = nCurvePoints.vec[1][2]
H2_X = nCurvePoints.vec[2][0]
H2_Y = nCurvePoints.vec[2][1]
H2_Z = nCurvePoints.vec[2][2]
# make 3 BezTriples, and mke sure their handles are FREE
# pass eacch of these 3 new BezTriples for X, Y and Z
# to theirrelevant IPO's
myIPOCurveX = Blender.BezTriple.New(myCurrentPathLen - 5, H1_X, 0, myCurrentPathLen, P_X, 0, myCurrentPathLen + 5, H2_X, 0)
myIPOCurveY = Blender.BezTriple.New(myCurrentPathLen - 5, H1_Y, 0, myCurrentPathLen, P_Y, 0, myCurrentPathLen + 5, H2_Y, 0)
myIPOCurveX.handleTypes = (Blender.BezTriple.HandleTypes.FREE, Blender.BezTriple.HandleTypes.FREE)
myIPOCurveY.handleTypes = (Blender.BezTriple.HandleTypes.FREE, Blender.BezTriple.HandleTypes.FREE)
myIPOCurveLoc_X.append(myIPOCurveX)
myIPOCurveLoc_Y.append(myIPOCurveY)
This is one battle that is nearly over, in the above example I have forced the time base for the handles, as I now have that problem on my hands, but at least this is a victory, thanks all
Re: Animations - Creating a Curve2IPO wizard
Posted: Sun Jul 27, 2008 12:34 am
by Grogyan
Done a little more refinement, I suppose I should upload my example code, till I can migrate it over to the trunk
Location of an object mostly follows the drawn curve, ie it follows the X and Z axes but not the Y axis, and i'm not sure why
Re: Animations - Creating a Curve2IPO wizard
Posted: Mon Aug 04, 2008 1:43 am
by Grogyan
I havn't made much progress in a while now because of this weird anomaly of the Y axis.
I was hoping to have this sorted before taking on complex algorithms. Even so I can't even visualize why its happening, let alon how to fix it.
Here is the code that kinda works, if you aren't downloading it already from the SVN
Code: Select all
#!BPY
# A script to convert a curve to an IPO curve which can be used by an object to simulate the path it is flying
# Specifically designed to help with GoW_PyPrp plugin
"""
Name: 'Curve2IPO'
Blender: 246
Group: 'Wizards'
Tooltip: 'Make IPO curves from path'
"""
# ==============================================
#
# ToDo
#
# 1) Move the else statement
# to the end so that that section is skipped
# when the condition isn't true
# -> DONE
#
# 2) Put in a check object type in before the
# first if statement, the else goes at the end
# -> DONE
#
# 3) Put in a check for if its cyclic or not,
# if it is true then save copy of the first
# BezTriple and apply it after the for loop
#
# 4) Apply the BezTriple of locations to the IPO
# window
#
# 5) Add to the IPO window the folowing blocks
# dRotX, dRotY, dRotZ and Time where time is
# the slow down or speed up at certain sections
# though this is probably redundant and just
# maintain a constand speed
#
# 6) Work out an algorithm for the above
# but don't for get that rotation is divided
# by 10, eg 90 degres becomes 9 degrees
# but test it out first.
#
# 7) Set the curves' datablock name as the
# objects'
# -> DONE
#
# ==============================================
import Blender
import math
from math import *
print"\n\n\n#################################################"
print" Attempting to run script"
print"##############################################\n"
# Get the currently selected object
myCurve = Blender.Object.GetSelected()[0]
# Create variable and get the type of object
myObjectType = myCurve.getType()
if myObjectType == 'Curve':
print" -> Object is a %s" % myObjectType
myCurveData = Blender.Curve.Get()[0]
myCurveFlag1 = myCurveData.getFlag()
# Standard bit mask for bit 3
if myCurveFlag1 and 0x08: # Is "CurvePath" flag set
print" -> Curve flag bit 3 at 0x00001000 is set, value is: %x " % (myCurveFlag1 and 0x08)
# Get the object name of the curve
myCurveName = myCurve.getName()
#myCurveBez = Blender.Object.Get(myCurve) # Get data of curve
# Initialize what will be the name of the IPO's
myIPOCurveSet = myCurve.getName()
# Get the length of the curve in frames
myPathLength = myCurveData.getPathLen()
# Create variables myPathIter, myCurrentPathLen
# and initialize them to a known value
myPathIter = myCurrentPathLen = myPathLength
#myIPOCurves = myIPOCurves.LOC[x]
myIPOCurveSet = Blender.Ipo.New('Object', myCurveName) # Attmpting to get the Curve name same as IPO curve set
#####################################
#handleTypes = (Blender.BezTriple.HandleTypes.FREE, Blender.BezTriple.HandleTypes.FREE)
#####################################
# Get the name of the data block
myCurveData = myCurve.data
myCyclicTest = myCurveData.isCyclic()
if myCyclicTest == True:
print" -> Curve is cyclic"
else:
print" -> Curve is not cyclic"
# Set the name of the data block as the
# objects' name
myCurveData.setName(myCurveName)
# Create the variable and intialize it to 0
myCurvePoints = 0
# Old way -> myCurvePoints = myCurveData.__getitem__(myCurvePoints)
myCurvePoints = myCurveData[myCurvePoints]
# can't be bothered how to figure out how
# use get curve length function in the API
# its just as easy to write a loop to calculate it
myNumberOfPoints = 0
for iNumberOfPoints in myCurvePoints:
myNumberOfPoints = myNumberOfPoints + 1.0
myPathIter = myPathLength / myNumberOfPoints
myHandleIter = myPathIter / (myNumberOfPoints * 2.0)
myHandleIter = ceil (myHandleIter)
print "\n##############################################"
print "Curve name: %s " % myCurveName
print "Curve data: %s " % myCurveData
print "Ipo curves: %s " % myIPOCurveSet
print "Ipo length: %s " % myPathLength
print "Path iteration constant: %s" % myPathIter
print "##############################################\n"
# Create LocX, LocY, and LocZ Ipo curves in our new Curve Object
# and store them so we can access them later
myIPOCurveLoc_X = myIPOCurveSet.addCurve('dLocX')
myIPOCurveLoc_Y = myIPOCurveSet.addCurve('dLocY')
myIPOCurveLoc_Z = myIPOCurveSet.addCurve('dLocZ')
myIPOCurveRot_X = myIPOCurveSet.addCurve('dRotX')
myIPOCurveRot_Y = myIPOCurveSet.addCurve('dRotY')
myIPOCurveRot_Z = myIPOCurveSet.addCurve('dRotZ')
#myIPOCurveSpeed = myIPOCurveSet.addCurve('Time')
myBezPointNumber = 1
myCurrentPathLen = 1
for nCurvePoints in myCurvePoints:
# Copy the first set of co-ordinates
# ready for a isCyclic condtion
if myBezPointNumber == 0:
myFirstCoods = nCurvePoints
# Apparently BezTriple outputs 9 floats for each handle/knot in 3D space
# so print out each float value
print"\n##############################################"
print"Bezier point number: %s" % myBezPointNumber
print"Out of a total: %s" % myNumberOfPoints
print"Current iteration at frame: %s\n" % myCurrentPathLen
print"H1x: %s " % nCurvePoints.vec[0][0]
print"H1y: %s " % nCurvePoints.vec[0][1]
print"H1z: %s " % nCurvePoints.vec[0][2]
print"\n"
print"Px: %s " % nCurvePoints.vec[1][0]
print"Py: %s " % nCurvePoints.vec[1][1]
print"Pz: %s " % nCurvePoints.vec[1][2]
print"\n"
print"H2x: %s " % nCurvePoints.vec[2][0]
print"H2y: %s " % nCurvePoints.vec[2][1]
print"H2z: %s " % nCurvePoints.vec[2][2]
print"##############################################\n"
# Store all bezier points
H1_X = nCurvePoints.vec[0][0]
H1_Y = nCurvePoints.vec[0][0]
H1_Z = nCurvePoints.vec[0][2]
P_X = nCurvePoints.vec[1][0]
P_Y = nCurvePoints.vec[1][1]
P_Z = nCurvePoints.vec[1][2]
H2_X = nCurvePoints.vec[2][0]
H2_Y = nCurvePoints.vec[2][1]
H2_Z = nCurvePoints.vec[2][2]
# make 3 BezTriples, and mke sure their handles are FREE
# pass eacch of these 3 new BezTriples for X, Y and Z
# to their relevant IPO's
myIPOCurveX = Blender.BezTriple.New(myCurrentPathLen - myHandleIter, H1_X, 0, myCurrentPathLen, P_X, 0, myCurrentPathLen + myHandleIter, H2_X, 0)
myIPOCurveY = Blender.BezTriple.New(myCurrentPathLen - myHandleIter, H1_Y, 0, myCurrentPathLen, P_Y, 0, myCurrentPathLen + myHandleIter, H2_Y, 0)
myIPOCurveZ = Blender.BezTriple.New(myCurrentPathLen - myHandleIter, H1_Z, 0, myCurrentPathLen, P_Z, 0, myCurrentPathLen + myHandleIter, H2_Z, 0)
myIPOCurveX.handleTypes = (Blender.BezTriple.HandleTypes.FREE, Blender.BezTriple.HandleTypes.FREE)
myIPOCurveY.handleTypes = (Blender.BezTriple.HandleTypes.FREE, Blender.BezTriple.HandleTypes.FREE)
myIPOCurveZ.handleTypes = (Blender.BezTriple.HandleTypes.FREE, Blender.BezTriple.HandleTypes.FREE)
myIPOCurveLoc_X.append(myIPOCurveX)
myIPOCurveLoc_Y.append(myIPOCurveY)
myIPOCurveLoc_Z.append(myIPOCurveZ)
#myIPOCurveSpeed.append((myCurrentPathLen, 30))
# Must be done last in the for loop
myBezPointNumber = myBezPointNumber + 1
myCurrentPathLen = myPathIter * myBezPointNumber
myIPOCurveLoc_X.recalc()
myIPOCurveLoc_Y.recalc()
myIPOCurveLoc_Z.recalc()
else:
Blender.Draw.PupMenu("Curve is not a Path")
print" -> Curve flag bit 3 at 0x00001000 is NOT set, value is: %x " % (myCurveFlag1 and 0x08)
else:
Blender.Draw.PupMenu("Object is not a curve")
print" -> Object is a %s" % myObjectType
Re: Animations - Creating a Curve2IPO wizard
Posted: Thu Aug 07, 2008 10:22 pm
by Grogyan
I have found the problem, and its not with my code, phew!
The problem lies withing the API when appending a BexTriple to the IPO widow, for some reason it would use the value of the X coordinate as the Y coordinate of the
FIRST handle of each curve in the curve object
Confusing I know, and I really only found it today
Now I just have to wait for a fix then download the automated build of Blender when the fix is done
So now I stand on the edge of a very deep crevice, bezier rotation curves, uuuugh

Re: Animations - Creating a Curve2IPO wizard
Posted: Sat Aug 16, 2008 1:43 am
by Grogyan
I've fixed the problem - small typo in my code been there for so long that I had completely missed hundreds of times
So while the script now animates objects EXACTLY round a path, there is one small problem, that i'm hoping Lontahv will be able to help me with.
PyPrp is coded with IPO curves for global world space, where as the script I have written outputs IPO curves based on the local space of the original curve object.
After that, i'll proceed with the rotation curves, though I don't know how hard that will be.
I'm thinking that I an do it by standard Trig on the current and next points in a segment.
It will be by far the hardest, no matter which way i'll do it