blender-iks-to-fks
Advanced tools
Comparing version 2.0.0 to 2.0.1
{ | ||
"name": "blender-iks-to-fks", | ||
"version": "2.0.0", | ||
"version": "2.0.1", | ||
"description": "A Blender script that takes a mesh and armature that use IKs and other non-deformation bones and creates a new mesh and armature that uses only FK bones", | ||
@@ -5,0 +5,0 @@ "main": "bin/ik2fk.js", |
@@ -1,17 +0,29 @@ | ||
var test = require('tape') | ||
var cp = require('child_process') | ||
var path = require('path') | ||
var fs = require('fs') | ||
const test = require('tape') | ||
const cp = require('child_process') | ||
const path = require('path') | ||
const fs = require('fs') | ||
// A leg with IKs | ||
var legBlendFile = path.resolve(__dirname, './leg.blend') | ||
const legBlendFile = path.resolve(__dirname, './leg.blend') | ||
// A file with an unselected mesh and parent armature | ||
var unselectedBlendFile = path.resolve(__dirname, './unselected.blend') | ||
const unselectedBlendFile = path.resolve(__dirname, './unselected.blend') | ||
// We noticed that if there are bone hooks on a bezier curve that is being used to control a spline IK modifier | ||
// the ik-to-fk process would only work if those bone hooks had `Deform` set to true in Blender. | ||
// | ||
// However, these aren't actually deformation bones - so this file ensures that we've fixed this and that | ||
// things work when `Deform` is false. | ||
const bezierCurveBoneHooksDeformOff = path.resolve(__dirname, './bone-hooks.blend') | ||
var runAddon = path.resolve(__dirname, '../run-addon.py') | ||
const runAddon = path.resolve(__dirname, '../run-addon.py') | ||
test('Blender Ik to FK tests', t => { | ||
t.test('Creates a second armature', testCreatesSecondArmature) | ||
t.test('Old and new armature have same animations', testSameAnimations) | ||
t.test('Automatically selects mesh if none selected', testAutomaticSelection) | ||
}) | ||
// Our test blender file has 3 objects - a camera, mesh and armature | ||
// Here we ensure that after we run the script there are 5 objects, | ||
// since our script generates a new mesh and armature | ||
test('Create a second armature', function (t) { | ||
function testCreatesSecondArmature (t) { | ||
t.plan(1) | ||
@@ -24,13 +36,13 @@ | ||
cp.exec( | ||
`blender ${legBlendFile} --background --python ${runAddon} --python ${printNumObjectsScript}`, | ||
function (err, stdout, stderr) { | ||
if (err) { throw err } | ||
`blender ${legBlendFile} --background --python ${runAddon} --python ${printNumObjectsScript}`, | ||
function (err, stdout, stderr) { | ||
if (err) { throw err } | ||
t.ok( | ||
stdout.indexOf('The number of objects is: 5') > -1, 'New mesh and armature were created' | ||
) | ||
t.end() | ||
} | ||
t.ok( | ||
stdout.indexOf('The number of objects is: 5') > -1, 'New mesh and armature were created' | ||
) | ||
t.end() | ||
} | ||
) | ||
}) | ||
} | ||
@@ -41,10 +53,10 @@ // We render a frame of our mesh's animation from before and then after we've run our FK generation script | ||
// Which means that the two meshes share the same animation. | ||
test('Old and new armature have same animations', function (t) { | ||
// TODO: Combine these two arrays into an object {legBlendFile: 10} | ||
var filesToTest = [ | ||
legBlendFile | ||
function testSameAnimations (t) { | ||
const filesToTest = [ | ||
// In blender 2.79 this was <0.0002 .. In 2.80 we moved it up to <0.0036 .. | ||
// After looking at a few more complicated models the before and after still seem to be nearly identical. | ||
{file: legBlendFile, frameToRender: 10, maxError: 0.0036}, | ||
// Need to look into why there is so much error here | ||
{file: bezierCurveBoneHooksDeformOff, frameToRender: 19, maxError: 0.0179} | ||
] | ||
var framesToRender = [ | ||
10 | ||
] | ||
@@ -57,13 +69,15 @@ t.plan(filesToTest.length) | ||
filesToTest.forEach(function (testFile, testFileNum) { | ||
var beforeFile = path.resolve(__dirname, `./before_${testFileNum}_`) | ||
var afterFile = path.resolve(__dirname, `./after_${testFileNum}_`) | ||
filesToTest.forEach(function (testCase, testFileNum) { | ||
const testFile = testCase.file | ||
const beforeFile = path.resolve(__dirname, `./before_${testFileNum}_`) | ||
const afterFile = path.resolve(__dirname, `./after_${testFileNum}_`) | ||
// Render our model without converting it into FK | ||
cp.exec( | ||
`blender -b ${testFile} --render-output ${beforeFile} --render-frame ${framesToRender[testFileNum]} --render-format PNG -noaudio`, | ||
`blender -b ${testFile} --render-output ${beforeFile} --render-frame ${testCase.frameToRender} --render-format PNG -noaudio`, | ||
function (err, stdout, stderr) { | ||
if (err) { throw err } | ||
compareBeforeAndAfter(testFileNum) | ||
compareBeforeAndAfter(testCase, testFileNum) | ||
bothImagesRendered[testFileNum] = true | ||
@@ -75,7 +89,7 @@ } | ||
cp.exec( | ||
`blender -b ${testFile} --python ${runAddon} --render-output ${afterFile} --render-frame ${framesToRender[testFileNum]} --render-format PNG -noaudio`, | ||
`blender -b ${testFile} --python ${runAddon} --render-output ${afterFile} --render-frame ${testCase.frameToRender} --render-format PNG -noaudio`, | ||
function (err, stdout, stderr) { | ||
if (err) { throw err } | ||
compareBeforeAndAfter(testFileNum) | ||
compareBeforeAndAfter(testCase, testFileNum) | ||
bothImagesRendered[testFileNum] = true | ||
@@ -92,3 +106,3 @@ } | ||
*/ | ||
function compareBeforeAndAfter (testFileNum) { | ||
function compareBeforeAndAfter (testCase, testFileNum) { | ||
var beforeFile = path.resolve(__dirname, `./before_${testFileNum}_`) | ||
@@ -98,3 +112,3 @@ var afterFile = path.resolve(__dirname, `./after_${testFileNum}_`) | ||
if (bothImagesRendered[testFileNum]) { | ||
cp.exec(`compare -metric RMSE ${beforeFile}00${framesToRender[testFileNum]}.png ${afterFile}00${framesToRender[testFileNum]}.png /dev/null`, function (_, stdout, stderr) { | ||
cp.exec(`compare -metric RMSE ${beforeFile}00${testCase.frameToRender}.png ${afterFile}00${testCase.frameToRender}.png /dev/null`, function (_, stdout, stderr) { | ||
// Compare will write the comparison to stderr. We parse their | ||
@@ -108,12 +122,10 @@ // It looks like this: | ||
// Delete our test renderings | ||
fs.unlinkSync(`${beforeFile}00${framesToRender[testFileNum]}.png`) | ||
fs.unlinkSync(`${afterFile}00${framesToRender[testFileNum]}.png`) | ||
fs.unlinkSync(`${beforeFile}00${testCase.frameToRender}.png`) | ||
fs.unlinkSync(`${afterFile}00${testCase.frameToRender}.png`) | ||
// In blender 2.79 this was <0.0002 .. In 2.80 we moved it up to <0.0036 .. | ||
// After looking at a few more complicated models the before and after still seem to be nearly identical. | ||
t.ok(rootSquareMeanError < 0.0036, `Root square mean error between old and new armature ${rootSquareMeanError}.`) | ||
t.ok(rootSquareMeanError < testCase.maxError, `Root square mean error between old and new armature ${rootSquareMeanError}. ${testCase.file}`) | ||
}) | ||
} | ||
} | ||
}) | ||
} | ||
@@ -123,3 +135,3 @@ // If you have not selected a mesh that has an armature we will use the first mesh that we find that has an armature | ||
// TODO: We'll still need to figure out how to best handle files with multiple mesh's / armatures | ||
test('Automatically selects mesh if none selected', function (t) { | ||
function testAutomaticSelection (t) { | ||
t.plan(1) | ||
@@ -143,2 +155,2 @@ | ||
) | ||
}) | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
2566629
366