collada-dae-parser
Advanced tools
Comparing version 0.4.0 to 0.5.0
@@ -9,3 +9,3 @@ var fs = require('fs') | ||
// TODO: Read using xhr request | ||
dae2json(fs.readFileSync('./demo/assets/p-c-c-c-test.dae'), function (err, parsedDae) { | ||
dae2json(fs.readFileSync('./demo/assets/animated-male-figure.dae'), function (err, parsedDae) { | ||
if (err) { callback(err) } | ||
@@ -12,0 +12,0 @@ |
@@ -15,3 +15,3 @@ var render = require('./render/render.js') | ||
currentlyPressedKeys: {}, | ||
orbit: {yRadians: 0, xRadians: 0} | ||
orbit: {yRadians: -0.65, xRadians: 0.9} | ||
}) | ||
@@ -18,0 +18,0 @@ var canvas = document.createElement('canvas') |
@@ -38,3 +38,3 @@ var matrixMultiply = require('./matrix-math/multiply.js') | ||
if (animationClock > animationDuration) { | ||
animationClock -= animationDuration | ||
animationClock %= animationDuration | ||
} | ||
@@ -60,15 +60,9 @@ // Find two closest keyframes | ||
var percentBetweenKeyframes = (lowestKeyframe + animationClock - min) / (max - min) | ||
var joint0 = createMatrix() | ||
var joint1 = createMatrix() | ||
var joint2 = createMatrix() | ||
var joint3 = createMatrix() | ||
var joint4 = createMatrix() | ||
interpolate(joint0, minJoints[0], maxJoints[0], percentBetweenKeyframes) | ||
interpolate(joint1, minJoints[1], maxJoints[1], percentBetweenKeyframes) | ||
// Quickly adding in support for two other matrices. The model that we're currently using doesn't have 4 bones | ||
// so we're passing in two fake matrices (they've been weighted to zero). This is for easy modification with | ||
// your own models. In a real shader you might not be so wasteful | ||
interpolate(joint2, minJoints[2] || createMatrix(), maxJoints[2] || createMatrix(), percentBetweenKeyframes) | ||
interpolate(joint3, minJoints[3] || createMatrix(), maxJoints[3] || createMatrix(), percentBetweenKeyframes) | ||
interpolate(joint4, minJoints[4] || createMatrix(), maxJoints[4] || createMatrix(), percentBetweenKeyframes) | ||
var interpolatedJoints = [] | ||
// TODO: get # joints from model | ||
var numJoints = 5 | ||
for (var i = 0; i < numJoints; i++) { | ||
interpolatedJoints[i] = createMatrix() | ||
interpolate(interpolatedJoints[i], minJoints[i] || createMatrix(), maxJoints[i] || createMatrix(), percentBetweenKeyframes) | ||
} | ||
@@ -81,3 +75,3 @@ gl.viewport(0, 0, viewport.width, viewport.height) | ||
var modelPosition = [0, 0, 0] | ||
var cameraMatrix = makeTranslation(0, 0, 20) | ||
var cameraMatrix = makeTranslation(0, 0, 3) | ||
cameraMatrix = matrixMultiply(cameraMatrix, makeXRotation(-state.orbit.xRadians)) | ||
@@ -125,7 +119,7 @@ cameraMatrix = matrixMultiply(cameraMatrix, makeYRotation(state.orbit.yRadians)) | ||
// Vertex weight | ||
gl.uniformMatrix4fv(shaderObject.boneMatrix0, false, joint0) | ||
gl.uniformMatrix4fv(shaderObject.boneMatrix1, false, joint1) | ||
gl.uniformMatrix4fv(shaderObject.boneMatrix2, false, joint2) | ||
gl.uniformMatrix4fv(shaderObject.boneMatrix3, false, joint3) | ||
gl.uniformMatrix4fv(shaderObject.boneMatrix4, false, joint4) | ||
gl.uniformMatrix4fv(shaderObject.boneMatrix0, false, interpolatedJoints[0]) | ||
gl.uniformMatrix4fv(shaderObject.boneMatrix1, false, interpolatedJoints[1]) | ||
gl.uniformMatrix4fv(shaderObject.boneMatrix2, false, interpolatedJoints[2]) | ||
gl.uniformMatrix4fv(shaderObject.boneMatrix3, false, interpolatedJoints[3]) | ||
gl.uniformMatrix4fv(shaderObject.boneMatrix4, false, interpolatedJoints[4]) | ||
@@ -132,0 +126,0 @@ gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, animatedModel.vertexPositionIndexBuffer) |
{ | ||
"name": "collada-dae-parser", | ||
"version": "0.4.0", | ||
"version": "0.5.0", | ||
"description": "Parse collada .dae 3d animation files into json", | ||
"main": "src/parse-collada.js", | ||
"bin": { | ||
"dae2json": "./bin/dae2json.js" | ||
}, | ||
"scripts": { | ||
@@ -7,0 +10,0 @@ "demo": "budo demo/browser.js --open --live --dir=demo/assets -- -t brfs", |
@@ -20,6 +20,14 @@ collada-dae-parser [![npm version](https://badge.fury.io/js/collada-dae-parser.svg)](http://badge.fury.io/js/collada-dae-parser) [![Build Status](https://travis-ci.org/chinedufn/collada-dae-parser.svg?branch=master)](https://travis-ci.org/chinedufn/collada-dae-parser) | ||
## Usage | ||
## CLI | ||
Output stringified JSON to stdout | ||
```sh | ||
# parse from stdin | ||
cat my-3d-model.dae | dae2json > parsed-model.json | ||
# parse from file | ||
dae2json my-3d-modal.dae > parsed-model.json | ||
``` | ||
## API | ||
@@ -56,3 +64,2 @@ | ||
vertexUVs: [...] | ||
// The rest is TODO | ||
} | ||
@@ -65,11 +72,28 @@ */ | ||
- [ ] basic cli (potentially pull into own repo, but start here) | ||
- [x] basic cli (potentially pull into own repo, but start here) | ||
- [ ] rounding values. Currently lots of .999999 and 1.000001 | ||
- [ ] fix normals in demo lighting | ||
- [ ] add a textured T-Rex demo model | ||
- [ ] add a textured complex demo model | ||
- [ ] allow zoom in, zoom out in demo | ||
- [x] Factor in bind shape matrix | ||
- [ ] Stop exporting bind shape matrix | ||
- [ ] toggle animation on and off | ||
- [ ] multiple animations in demo | ||
- [ ] full screen demo with controls overlayed | ||
- [ ] All of the TODO: statements in code | ||
- [ ] Allow file buffer to be passed in | ||
- [ ] Add a GIF of every test fixture animation | ||
- [ ] Documentation / references | ||
- [ ] Then v1.0.0 ! | ||
- We might want another module to export the raw useful data.. Then we can transform it / add opinions higher up. | ||
## References | ||
- waZim. (2010) ["Step by Step Skeletal Animation in C++ and OpenGL, Using COLLADA Part 1](http://www.wazim.com/Collada_Tutorial_1.htm) & [Part 2](http://www.wazim.com/Collada_Tutorial_2.htm)" | ||
- Heavily informed the initial parser | ||
- Markus Ruh. (2012) [Vertex Skinning](http://ruh.li/AnimationVertexSkinning.html) | ||
- Heavily informed the vertex skinning in the initial demo vertex shader | ||
- Jerimiah van Oosten. (2011) "[GPU Skinning of MD5 Models in OpenGL and Cg](http://www.3dgep.com/gpu-skinning-of-md5-models-in-opengl-and-cg/)" | ||
- Heavily informed the vertex skinning in the initial demo vertex shader | ||
## See Also | ||
@@ -76,0 +100,0 @@ |
var transpose = require('gl-mat4/transpose') | ||
var mat4Multiply = require('gl-mat4/multiply') | ||
@@ -30,7 +31,11 @@ module.exports = ParseLibraryControllers | ||
// All of our models joints | ||
// All of our model's joints | ||
var orderedJointNames = controller[0].skin[0].source[0].Name_array[0]._.split(' ') | ||
// Bind shape matrix (inverse bind matrix) | ||
var bindShapeMatrix = controller[0].skin[0].bind_shape_matrix[0].split(' ').map(Number) | ||
// Joint bind poses | ||
// TODO: Should we multiply in the bind shape matrix? | ||
// ^ yes, but wait until we have a test file for it | ||
var jointBindPoses = {} | ||
@@ -40,7 +45,6 @@ var bindPoses = controller[0].skin[0].source[1].float_array[0]._.split(' ').map(Number) | ||
var bindPose = bindPoses.slice(16 * index, 16 * index + 16) | ||
mat4Multiply(bindPose, bindShapeMatrix, bindPose) | ||
jointBindPoses[jointName] = bindPose | ||
}) | ||
// Bind shape matrix (inverse bind matrix) | ||
var bindShapeMatrix = controller[0].skin[0].bind_shape_matrix[0].split(' ').map(Number) | ||
transpose(bindShapeMatrix, bindShapeMatrix) | ||
@@ -47,0 +51,0 @@ } |
@@ -13,2 +13,4 @@ module.exports = ParseLibraryGeometries | ||
var vertexUVIndices = [] | ||
// TODO: This is currently dependent on a certain vertex data order | ||
// we should instead read this order from the .dae file | ||
polylistIndices.forEach(function (vertexIndex, positionInArray) { | ||
@@ -20,3 +22,3 @@ if (positionInArray % source.length === 0) { | ||
} | ||
if (source.length > 2 && positionInArray % source.length === 2) { | ||
if (positionInArray % source.length === 2) { | ||
vertexUVIndices.push(Number(vertexIndex)) | ||
@@ -23,0 +25,0 @@ } |
@@ -8,4 +8,3 @@ module.exports = ParseVisualScenes | ||
// TODO: Not sure if we're actually scaling the armature. It seems | ||
// like we need to apply these transformations to the top level joints | ||
// Some .dae files will export a shrunken model. Here's how to scale it | ||
var armatureScale = [] | ||
@@ -35,4 +34,2 @@ visualScene.node.forEach(function (node) { | ||
// Recursively parse child joints | ||
// TODO: factor in parent world matrix | ||
// TODO: Facilitate depth first traversal? | ||
function parseJoints (node, parentJointName, accumulator) { | ||
@@ -39,0 +36,0 @@ accumulator = accumulator || [] |
var parseXML = require('xml2js').parseString | ||
// TODO: better name | ||
var extractAnimation = require('./extract-animation.js') | ||
var parseLibraryGeometries = require('./library_geometries/parse-library-geometries.js') | ||
var parseLibraryVisualScenes = require('./library_visual_scenes/parse-visual-scenes.js') | ||
var parseLibraryControllers = require('./library_controllers/parse-library-controllers.js') | ||
var parseLibraryAnimations = require('./library_animations/parse-library-animations.js') | ||
var parseSkeletalAnimations = require('./library_animations/parse-skeletal-animations.js') | ||
var parseLocRotScaleAnim = require('./library_animations/parse-loc-rot-scale-anim.js') | ||
@@ -12,3 +11,2 @@ module.exports = ParseCollada | ||
// TODO: | ||
// Parse skeletal / skinning animations | ||
// Use input, accessor, and param attributes instead of hard coding lookups | ||
@@ -18,3 +16,3 @@ // Clean Up Code / less confusing var names | ||
parseXML(colladaXML, function (err, result) { | ||
if (err) { console.log(err) } | ||
if (err) { return callback(err) } | ||
@@ -24,3 +22,2 @@ var parsedObject = {} | ||
// TODO: rename | ||
var visualSceneData = parseLibraryVisualScenes(result.COLLADA.library_visual_scenes) | ||
@@ -30,8 +27,7 @@ | ||
if (result.COLLADA.library_controllers) { | ||
// TODO: rename | ||
var foo = parseLibraryControllers(result.COLLADA.library_controllers) | ||
if (foo.vertexJointWeights && Object.keys(foo.vertexJointWeights) .length > 0) { | ||
parsedObject.bindShapeMatrix = foo.bindShapeMatrix | ||
parsedObject.vertexJointWeights = foo.vertexJointWeights | ||
jointBindPoses = foo.jointBindPoses | ||
var controllerData = parseLibraryControllers(result.COLLADA.library_controllers) | ||
if (controllerData.vertexJointWeights && Object.keys(controllerData.vertexJointWeights) .length > 0) { | ||
parsedObject.bindShapeMatrix = controllerData.bindShapeMatrix | ||
parsedObject.vertexJointWeights = controllerData.vertexJointWeights | ||
jointBindPoses = controllerData.jointBindPoses | ||
} | ||
@@ -42,7 +38,7 @@ } | ||
if (result.COLLADA.library_animations) { | ||
parsedObject.keyframes = extractAnimation(result.COLLADA.library_animations[0].animation) | ||
parsedObject.keyframes = parseLocRotScaleAnim(result.COLLADA.library_animations[0].animation) | ||
if (Object.keys(parsedObject.keyframes).length === 0) { | ||
delete parsedObject.keyframes | ||
} | ||
var keyframes = parseLibraryAnimations(result.COLLADA.library_animations, jointBindPoses, visualSceneData) | ||
var keyframes = parseSkeletalAnimations(result.COLLADA.library_animations, jointBindPoses, visualSceneData) | ||
if (Object.keys(keyframes).length > 0) { | ||
@@ -49,0 +45,0 @@ parsedObject.keyframes = keyframes |
@@ -1,75 +0,2 @@ | ||
var fs = require('fs') | ||
var path = require('path') | ||
var test = require('tape') | ||
var colladaFilePath = path.resolve(__dirname, './fixture/textured-blender-default-cube.dae') | ||
var tbdcColladaXML = fs.readFileSync(colladaFilePath).toString() | ||
var expectedTBDC = require('./expected/textured-blender-default-cube.js') | ||
var blenderCubeAmimatedPath = path.resolve(__dirname, './fixture/animated-blender-cube.dae') | ||
var animatedColladaXML = fs.readFileSync(blenderCubeAmimatedPath).toString() | ||
var expectedAnimatedCube = require('./expected/animated-blender-cube.js') | ||
var skeletonSkinnedCubesPath = path.resolve(__dirname, './fixture/two-skinned-cubes.dae') | ||
var skeletonSkinnedCubesXML = fs.readFileSync(skeletonSkinnedCubesPath).toString() | ||
var expectedSkinnedCube = require('./expected/two-skinned-cube.js') | ||
var animatedLetterFPath = path.resolve(__dirname, './fixture/letter-f-animated.dae') | ||
var animatedLetterFXML = fs.readFileSync(animatedLetterFPath).toString() | ||
var expectedAnimatedLetterF = require('./expected/animated-letter-f.js') | ||
var parentChildChildLetterFPath = path.resolve(__dirname, './fixture/parent-child-child-letter-f.dae') | ||
var parentChildChildLetterFXML = fs.readFileSync(parentChildChildLetterFPath).toString() | ||
var expectedParentChildChildF = require('./expected/parent-child-child-letter-f.js') | ||
var parseCollada = require('../') | ||
test('Parse a default blender cube with an added texture', function (t) { | ||
t.plan(1) | ||
parseCollada(tbdcColladaXML, function (err, parsedCube) { | ||
if (err) { | ||
t.fail() | ||
} | ||
t.deepEqual(parsedCube, expectedTBDC) | ||
}) | ||
}) | ||
test('Parse a default blender cube with an animation', function (t) { | ||
t.plan(1) | ||
parseCollada(animatedColladaXML, function (err, parsedAnimatedCube) { | ||
if (err) { | ||
t.fail() | ||
} | ||
t.deepEqual(parsedAnimatedCube, expectedAnimatedCube) | ||
}) | ||
}) | ||
test('Parse two blender cubes animated with bones and skinning', function (t) { | ||
t.plan(1) | ||
parseCollada(skeletonSkinnedCubesXML, function (err, parsedSkeletonSkinnedCubes) { | ||
if (err) { | ||
t.fail() | ||
} | ||
t.deepEqual(parsedSkeletonSkinnedCubes, expectedSkinnedCube) | ||
t.end() | ||
}) | ||
}) | ||
test('Parse animated letter F with parent and child bone', function (t) { | ||
t.plan(1) | ||
parseCollada(animatedLetterFXML, function (err, parsedAnimatedLetterF) { | ||
if (err) { t.fail() } | ||
t.deepEqual(parsedAnimatedLetterF, expectedAnimatedLetterF) | ||
t.end() | ||
}) | ||
}) | ||
test('Parse with parent -> child -> child joint relationship', function (t) { | ||
t.plan(1) | ||
parseCollada(parentChildChildLetterFXML, function (err, parsedParentChildChildF) { | ||
if (err) { t.fail() } | ||
t.deepEqual(parsedParentChildChildF, expectedParentChildChildF) | ||
t.end() | ||
}) | ||
}) | ||
require('./api/api.js') | ||
require('./cli/cli.js') |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
3247075
49
1130
103
5
1