| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595 |
- include "ogre/lib/ogreSkeletonLib_usefulfns.ms"
- -----------------------------------------------------------------------------
- -- gets keyframes from the controllers animation
- -----------------------------------------------------------------------------
- function getTimeList obj firstframe lastframe samplerate IKsamplerate =
- (
- local list,rotContr,posContr,e ;
- list = #(firstframe) ;
- list2 = #() ; -- this is the list which will be returned.
-
- -- Biped Bones and the root: Bip01 for example don't have the same controller
-
- -- Root : Bip01
- if (isPelvis obj) then (
- -- vertical controller
- for e in obj.controller.vertical.controller.keys do (
- t =e.time ;
- if (t>firstFrame and t<=lastFrame) then (
- append list t ;
- --print t ;
- )
- )
- -- horizontal controller
- for e in obj.controller.horizontal.controller.keys do (
- t =e.time ;
- if (t>firstFrame and t<=lastFrame) then
- append list t ;
- )
- -- turn controller
- for e in obj.controller.turning.controller.keys do (
- t =e.time ;
- if (t>firstFrame and t<=lastFrame) then
- append list t ;
- )
- sort list ;
- )
- -- Biped Bones
- else if (isKindOf obj Biped_Object) then (
-
- for e in obj.controller.keys do (
- t =e.time ;
- if (t>firstFrame and t<=lastFrame) then
- append list t ;
- )
- )
- -- Standard Bones
- else
- (
- --print obj.name;
- --print (classof obj.controller) ;
- if (classof obj.controller == prs) then -- standard controller
- (
- rotContr = obj.rotation.controller ;
- posContr = obj.pos.controller ;
-
- for e in rotContr.keys do
- (
- t = e.time ;
- if (t>firstFrame and t<=lastFrame) then
- append list t ;
- )
- for e in posContr.keys do
- (
- t = e.time ;
- if (t>firstFrame and t<=lastFrame) then
- append list t ;
- )
- )
- else if ((classof obj.controller == IK_ControllerMatrix3Controller) or (classof obj.controller == IKControl)) then -- IK controller
- (
- local IKSR = IKsamplerate;
-
- if (IKSR == 0.0) then
- IKSR = 1.0;
-
- i=firstFrame as Float;
- while (i<=lastFrame) do
- (
- append list (i as Float);
- i = i + IKSR;
- )
- )
- )
- append list (firstFrame as Float); -- add a keyframe on the first frame
- append list (lastFrame as Float); -- add a keyframe on then last frame
- if (samplerate > 0) then -- sample the animation by adding keyframes on regular intervals
- (
- i=firstFrame as Float;
- while (i<=lastFrame) do
- (
- append list (i as Float);
- i = i + samplerate;
- )
- )
- sort list ;
-
- -- if several keyframes have the same value, we keep just one
- keepLoneValues list list2 ;
- list2 ;
- )
- -----------------------------------------------------------------------------
- -- write <track />
- -- Selected keys belongs to [firstframe,lastFrame]
- -- time = (key.time - firstFrame)*length/(lastFrame-firstFrame)
- -- (e.g. first key has time 0.)
- -----------------------------------------------------------------------------
- function writeTrack bone_name boneId firstframe lastframe samplerate IKsamplerate length scale flipYZ outFile=
- (
- local angle,timef,i,bname,d,mref,mparent ;
-
- -- displays information in the maxscript listener
- if (not g_MAX) then
- format "retrieving key information for % ...\n" (bone_name) ;
- -- gets bone acording to the parameter boneId
- bname = bone_name ;
- replaceSpaces bname ;
- d = getNodeByName bname ;
-
- -- gets keyframe list
- timelist = getTimeList d firstframe lastframe samplerate IKsamplerate;
-
- -- track header
- format("\t\t\t\t<track bone = \"%\">\n") bname to:outFile ;
- format("\t\t\t\t\t<keyframes>\n") to:outFile ;
-
- -- gets initial transform at frame 0f
- at time 0f (
- initTform = d.transform ;
- if (not isRootUniversal2 d) then (
- mparent = d.parent.transform ;
- initTform = initTform*inverse(mparent) ;
- )
- else if (flipYZ) then (
- if (not g_MAX) then
- format " - flipping root track..." ;
- -- we add the bip Transform
- --initTform = initTform * d.controller.rootNode.transform ;
- initTform = flipYZTransform initTform ;
- )
- )
-
- -- for each frame in the list
- for i in timelist do
- (
- -- moves slider time and compute OGRE time
- at time i (
- timef = ((float) (i-firstFrame)*length)/(lastframe - firstframe ) ;
-
- -- First, rotation which depends on initial transformation
- Tform = d.transform ;
- -- if this is the pelvis
- if (isRootUniversal2 d) then (
- mparent = matrix3 1 ;
- -- if flipYZ == true
- if (flipYZ) then
- Tform = flipYZTransform Tform ;
- )
- else
- mparent = d.parent.transform ;
-
- -- computes rotation
- mref = initTform*mparent ;
- Tform = Tform*inverse(mref) ;
-
- -- rotation part is saved.
- --rot = Tform.rotation as angleaxis ;
- --angle = - degToRad (rot.angle) ; -- don't know why there must be this minus :((((((
- rot = toAngleAxis Tform.rotation ;
- axis = rot.axis;
- angle = - rot.angle;
-
- -- Then, position which depends on parent
- Tform=d.transform ;
- Tform=Tform*inverse(mparent) ;
-
- -- if this is the root bone and flipYZ == true
- if (isRootUniversal2 d and flipYZ) then (
- Tform = flipYZTransform Tform ;
- )
-
- -- substracts position of the initial transform
- Tform.pos -= initTform.pos ;
- Tform.pos = Tform.pos * scale ;
-
- pos = Tform.pos ;
- -- writes them !
- if (abs(pos.x)<1e-5) then pos.x = 0 ;
- if (abs(pos.y)<1e-5) then pos.y = 0 ;
- if (abs(pos.z)<1e-5) then pos.z = 0 ;
-
- format("\t\t\t\t\t\t<keyframe time=\"%\">\n") timef to: outFile ;
- format("\t\t\t\t\t\t\t<translate x=\"%\" y=\"%\" z=\"%\" />\n") pos.x pos.y pos.z to: outFile ;
- format("\t\t\t\t\t\t\t<rotate angle=\"%\">\n") angle to:outFile ;
- format("\t\t\t\t\t\t\t\t<axis x=\"%\" y=\"%\" z=\"%\" />\n") (axis.x) (axis.y) (axis.z) to:outFile ;
- format("\t\t\t\t\t\t\t</rotate>\n") to:outFile ;
- format("\t\t\t\t\t\t</keyframe>\n") to:outFile ;
- )
- )
-
- -- track end
- format("\t\t\t\t\t</keyframes>\n") to:outFile ;
- format("\t\t\t\t</track>\n") to: outFile ;
- )
- -------------------------------------------------------------------------------------------------
- ------------------------------------------- WRITE SKELETON --------------------------------------
- -------------------------------------------------------------------------------------------------
- -------------------------------------
- -- List of bones in the hierarchy
- -------------------------------------
- global BonesList=#()
- global RootsList=#()
- -------------------------------------
- -- helper functions to build skeleton
- -------------------------------------
- -----------------------------------------------------------------
- -- recursive function to build the list of bones for the skeleton
- -----------------------------------------------------------------
- function computeBList b sk phy exportHelpers =
- (
- bname = b ;
- bone = getNodeByName bname ;
- if (findItem BonesList bname == 0) then
- if (isKindOf bone BoneGeometry or iskindOf bone Biped_Object or (exportHelpers and (isPartOfModifier bone sk phy)) ) then
- append BonesList bname ;
- childrenArray = bone.children ;
- for i=1 to childrenArray.count do
- (
- if (isKindOf bone BoneGeometry or iskindOf bone Biped_Object or (exportHelpers and (isPartOfModifier bone sk phy))) then
- computeBList (replaceSpaces childrenArray[i].name) sk phy exportHelpers;
- )
- )
- function addHelpersToHierarchy phy sk =
- (
- if (sk != undefined) then
- (
- for i=1 to (skinOps.GetNumberBones sk) do
- (
- bname = skinOps.GetBoneName sk i 1 ;
- replaceSpaces bname ;
- d = getNodeByName bname ;
- if (iskindof d helper) then
- append BonesList bname ;
- )
- )
- else if (phy != undefined) then
- (
- for i=1 to (physiqueOps.GetBoneCount $) do
- (
- bname = (physiqueOps.GetBones $)[i].name;
- replaceSpaces bname ;
- d = getNodeByName bname ;
-
- if (iskindof d helper) then
- append BonesList bname ;
- )
- )
- )
- -----------------------------------------------------------------
- -- find the root(s) of the rhierarchy
- -----------------------------------------------------------------
- function getHierarchyRoots phy sk exportHelpers =
- (
- local rootstab=#();
-
- if (sk != undefined) then
- (
- for i=1 to (skinOps.GetNumberBones sk) do
- (
- bname= skinOps.GetBoneName sk i 1 ;
- replaceSpaces bname ;
- d = getNodeByName bname ;
-
- while (d.parent!=undefined and (iskindof d.parent BoneGeometry or iskindOf d.parent Biped_Object or (exportHelpers and (isPartOfModifier d.parent sk phy)) )) do
- (
- d = d.parent
- )
- trouve = 0;
- --format("new potential root bone \"%\"\n") (replaceSpaces d.name) ;
- for j=1 to rootstab.count do
- (
- if (rootstab[j]!=undefined and (rootstab[j]==(replaceSpaces d.name)))then
- (
- trouve = 1;
- exit;
- )
- )
- if trouve==0 then
- (
- if (iskindof d BoneGeometry or iskindOf d Biped_Object or (exportHelpers and (isPartOfModifier d sk phy)) ) then
- (
- if (not g_MAX) then
- format("new root bone \"%\"\n") (replaceSpaces d.name) ;
- rootstab[rootstab.count+1] = (replaceSpaces d.name) ;
- )
- )
- )
- )
- else if (phy != undefined) then -- physique modifier
- (
- for i=1 to (physiqueOps.GetBoneCount $) do
- (
- bname = (physiqueOps.GetBones $)[i].name;
- replaceSpaces bname ;
- d = getNodeByName bname ;
-
- while (d.parent!=undefined and (iskindof d.parent BoneGeometry or iskindOf d.parent Biped_Object or (exportHelpers and (isPartOfModifier d.parent sk phy)) )) do
- (
- d = d.parent
- )
- trouve = 0;
- --format("new potential root bone \"%\"\n") (replaceSpaces d.name) ;
- for j=1 to rootstab.count do
- (
- if (rootstab[j]!=undefined and (rootstab[j]==(replaceSpaces d.name)))then
- (
- trouve = 1;
- exit;
- )
- )
- if trouve==0 then
- (
- if (iskindof d BoneGeometry or iskindOf d Biped_Object or (exportHelpers and (isPartOfModifier d sk phy))) then
- (
- if (not g_MAX) then
- format("new root bone \"%\"\n") (replaceSpaces d.name) ;
- rootstab[rootstab.count+1] = (replaceSpaces d.name) ;
- )
- )
- )
- )
-
- rootstab;
- )
- -----------------------------------------------------------------
- -- function to build the list of bones for the skeleton
- -----------------------------------------------------------------
- function computeBonesList phy sk exportHelpers =
- (
- RootsList = getHierarchyRoots phy sk exportHelpers; -- find the roots of the current hierarchy
- print RootsList;
- for b in RootsList do
- (
- computeBList b sk phy exportHelpers;
- )
-
- -- add the nodes that are parts of the skin (or physique) modifier but are neither biped_object nor standard bones
- -- only helpers (Point, Dummy) at the moment...
- -- addHelpersToHierarchy phy sk ;
- )
- ------------------
- -- write <bones />
- ------------------
- function writeB bone_name id scale flipYZ outFile =
- (
- -- gets bone acording to the parameter boneId
- bname = bone_name ;
- replaceSpaces bname;
- d = getNodeByName bname ;
-
- -- gets initial transform at frame 0f
- format("\t\t<bone id=\"%\" name=\"%\">\n") (id-1) bname to:outFile ;
- slidertime = 0f ;
- Tform = d.transform ;
- if (not isRootUniversal2 d) then (
- mparent = d.parent.transform ;
- Tform = Tform*inverse(mparent) ;
- )
-
- Tform.pos = Tform.pos * scale ;
-
- if ((isRootUniversal2 d) and flipYZ) then (
- if (not g_MAX) then
- format "- Flipping root... \n" ;
- Tform = flipYZTransform Tform ;
- )
-
- pos = Tform.pos ;
- --rot = Tform.rotation as angleaxis ;
- --angle = - degToRad (rot.angle) ; -- don't know why there must be this minus :((((((
- rot = toAngleAxis Tform.rotation ;
- angle = - rot.angle ;
-
- -- if (abs(pos.x)<1e-5) then pos.x = 0 ;
- -- if (abs(pos.y)<1e-5) then pos.y = 0 ;
- -- if (abs(pos.z)<1e-5) then pos.z = 0 ;
-
- -- Only object.transform was taken into account, but when mirror is applied
- -- object.scale is modified and become [-1,-1,-1] that's why we do what follows:
- if ((d.parent != undefined) and (hasproperty d.parent "scale")) then (
- pos = pos * d.parent.scale ;
- )
-
- format("\t\t\t<position x=\"%\" y=\"%\" z=\"%\" />\n") pos.x pos.y pos.z to:outFile ;
- format("\t\t\t<rotation angle=\"%\">\n") angle to:outFile ;
- format("\t\t\t\t<axis x=\"%\" y=\"%\" z=\"%\" />\n") rot.axis.x rot.axis.y rot.axis.z to:outFile ;
- format("\t\t\t</rotation>\n") to:outFile ;
- format("\t\t</bone>\n") to:outFile ;
- )
- -----------------------------
- -- write Bones (using writeB)
- -----------------------------
- function writeBones phy sk scale flipYZ exportHelpers outFile =
- (
- local i ;
-
- OgreExportObject.exportProgress.value = 0;
- if (BonesList.count == 0) then
- computeBonesList phy sk exportHelpers;
-
- format("\t<bones>\n") to:outFile;
-
- i = 0 ;
-
- for i=1 to BonesList.count do
- (
- OgreExportObject.exportProgress.value = (100.0*i/BonesList.count);
- writeB BonesList[i] i scale flipYZ outFile ;
- )
-
- format("\t</bones>\n") to:outFile;
-
- OgreExportObject.exportProgress.value = 100;
- )
- --------------------------
- -- write <bonehierarchy />
- --------------------------
- function writeH b outFile =
- (
- if (not isRootUniversal2 b) then
- (
- p = b.parent ;
- format("\t\t<boneparent bone=\"%\" parent=\"%\" />\n") (replaceSpaces b.name) (replaceSpaces p.name) to:outFile ;
- )
- )
- function writeHierarchy outFile =
- (
- OgreExportObject.exportProgress.value = 0;
- local bname,pelvis
- format("\t<bonehierarchy>\n") to:outFile ;
- for i=1 to BonesList.count do
- (
- OgreExportObject.exportProgress.value = (100.0*i/BonesList.count);
- b = getNodeByName BonesList[i] ;
- writeH b outFile ;
- )
- format("\t</bonehierarchy>\n") to:outFile ;
-
- OgreExportObject.exportProgress.value = 100;
- )
- -----------------------
- -- write <animations />
- -----------------------
- function writeAnim Anims samplerate IKsamplerate scale flipYZ outFile =
- (
- local i,n ;
-
- OgreExportObject.exportProgress.value = 0;
-
- format("\t<animations>\n") to: outFile ;
-
- for anm=1 to Anims.names.count do
- (
- format("\t\t<animation name=\"%\" length=\"%\">\n") Anims.names[anm] Anims.lengths[anm] to:outFile ;
- format("\t\t\t<tracks>\n") to:outFile
-
- n = BonesList.count ;
- for i = 1 to n do
- (
- OgreExportObject.exportProgress.value = (100.0*i/BonesList.count)/Anims.names.count;
- writeTrack BonesList[i] i Anims.startframes[anm] Anims.endframes[anm] samplerate IKsamplerate Anims.lengths[anm] scale flipYZ outFile ;
- )
-
- format("\t\t\t</tracks>\n") to:outFile
- format("\t\t</animation>\n") to: outFile ;
- )
-
- format("\t</animations>\n") to: outFile ;
- OgreExportObject.exportProgress.value = 100;
- )
- -------------------------------------------------------------
- -- write <skeleton /> main function
- -- write the animation in the file out_name + ".skeleton.xml"
- -- between the frame firstFrame and lastFrame
- -- and scale time according to length
- -------------------------------------------------------------
- function writeSkeleton pmesh exportOptions Anims out_name =
- (
- local sk,n,keys,initialKeys,messages,phy ;
-
- sk = getSkin pmesh ;
- phy = getPhysique pmesh ;
-
- if (sk == undefined and phy == undefined) then
- (
- MessageBox "There is no skin or physique modifier for this object" ;
- return false;
- )
- else
- (
- -- in order to perform, skin should be opened
- max modify mode ;
- if (sk != undefined) then
- modPanel.setCurrentObject pmesh.modifiers[#Skin] ;
- else -- physique
- modPanel.setCurrentObject pmesh.modifiers[#Physique] ;
- if (not g_MAX) then
- (
- format "------------------------------------------\n"
- format "------ OGRE skeleton Exporter Log ------\n"
- format "------------------------------------------\n"
-
- format "Exporter options :\n"
- for i=1 to Anims.names.count do
- format "Anim % - firstFrame: % - lastFrame: %\n" Anims.names[i] Anims.startframes[i] Anims.endframes[i] ;
- -- creates the output file
- outFile = createfile (out_name + ".skeleton.xml") ;
- )
- else
- (
- if (g_MAX_use_listener) then
- format("<ogrestartfile>%</ogrestartfile><ogrestartdata>\n") (outName + ".skeleton.xml");
- outFile = listener;
- )
-
- -- writes header
- format("<skeleton>\n") to:outFile ;
-
- if (not g_MAX) then
- format "Writing bones :\n" ;
- writeBones phy sk exportOptions.scale exportOptions.flipYZ exportOptions.exportHelpers outFile ;
- if (not g_MAX) then
- format "Writing bone hierarchy.\n" ;
- writeHierarchy outFile ;
- if (not g_MAX) then
- format "Writing bone tracks.\n" ;
- writeAnim Anims exportOptions.sampleRate exportOptions.ikSampleRate exportOptions.scale exportOptions.flipYZ outFile ;
- -- ecriture, fin des balises
- format("</skeleton>\n") to: outFile ;
-
- if (not g_MAX) then
- (
- format "------------------------------------------\n"
- format "---------- END ---------\n"
- format "------------------------------------------\n"
-
- close outFile ;
- )
- else
- (
- if (g_MAX_use_listener) then
- format("</ogrestartdata>\n") to: outFile;
- )
-
- messageBox "Exporting skeleton successful !"
- return true;
- )
- )
|