Skip to content

Instantly share code, notes, and snippets.

@2no
Created April 1, 2012 06:40
Show Gist options
  • Save 2no/2272034 to your computer and use it in GitHub Desktop.
Save 2no/2272034 to your computer and use it in GitHub Desktop.
BVH データ読み込み JS
var aachan = new Bvh();
var nocchi = new Bvh();
var kashiyuka = new Bvh();
aachan.load({
src: "./bvh/aachan.bvh",
complete: function(xhr) {
console.log("あーちゃんの BVH データ読み込み完了");
nocchi.load({
src: "./bvh/nocchi.bvh",
complete: function(xhr) {
console.log("のっちの BVH データ読み込み完了");
kashiyuka.load({
src: "./bvh/kashiyuka.bvh",
complete: function(xhr) {
console.log("かしゆかの BVH データ読み込み完了");
completeHandler(xhr);
},
error: errorHandler
});
},
error: errorHandler
});
},
error: errorHandler
});
function errorHandler(xhr)
{
console.log('error');
}
function completeHandler(xhr)
{
console.log('complete');
}
// https://github.com/perfume-dev/example-flash/tree/master/src/com/perfume/utils/bvh からの簡単移植
var Bvh = window.Bvh || (function() {
function Bvh(str)
{
this.init(str);
}
Bvh.prototype = {
_loop: false,
setLoop: function(b)
{
this._loop = !!b;
return this;
},
isLoop: function() { return this._loop; },
_root: null,
setRoot: function(bone)
{
if (bone instanceof Bvh.Bone) {
this._root = bone;
}
return this;
},
_frames: [],
// TODO: 値をチェックするか
addFrame: function(frame)
{
if (frame instanceof Array) {
this._frames.push(frame);
}
},
setFrames: function(frames)
{
this._frames = [];
for (var i = 0, length = frames.length; i < length; i++) {
this.addFrame(frames[i]);
}
return this;
},
getFrames: function() { return this._frames; },
_numFrames: 0,
getNumFrames: function() { return this._numFrames; },
setNumFramesInternal: function(num) {
if (!isNaN(num)) {
this._numFrames = Number(num);
}
return this;
},
_frameTime: 0,
getFrameTime: function() { return this._frameTime; },
setFrameTimeInternal: function(num)
{
if (!isNaN(num)) {
this._frameTime = Number(num);
}
return this;
},
_bones: [],
getBones: function() { return this._bones; },
init: function(str)
{
this._bones = [];
this._frames = [];
this._root = null;
if (typeof str === "string") {
new Bvh.Parser(this, str);
}
return this;
},
gotoFrame: function(frame)
{
if (isNaN(frame)) {
return;
}
if (!this._loop) {
if (frame >= this._numFrames) {
frame = this._numFrames - 1;
}
}
else {
while (frame >= this._numFrames) {
frame -= this._numFrames;
}
}
frame = this._frames[frame];
var numFrame = frame.length;
var count = 0;
var bone;
var channel;
for (var key in this._bones) {
bone = this._bones[key];
channel = bone.getChannels();
for (var i = 0, l = bone.getNumChannels(), v; i < l; i++) {
if (count < numFrame) {
v = frame[count++];
switch (channel[i]) {
case "Xposition":
bone.setPositionX(v);
break;
case "Yposition":
bone.setPositionY(v);
break;
case "Zposition":
bone.setPositionZ(v);
break;
case "Xrotation":
bone.setRotationX(v);
break;
case "Yrotation":
bone.setRotationY(v);
break;
case "Zrotation":
bone.setRotationZ(v);
break;
}
}
}
}
return this;
},
load: function(settings)
{
if (typeof settings.src !== "string") {
return;
}
var xhr = null;
if (window.ActiveXObject) {
try {
xhr = new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e) {
try {
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
catch (e) {
if (typeof settings.error === "function") {
settings.error.apply(this, [null]);
}
}
}
}
else if (window.XMLHttpRequest) {
xhr = new XMLHttpRequest();
}
var self = this;
xhr.onreadystatechange = function() {
if (this.readyState === 4) {
if (this.status === 200) {
self.init(xhr.responseText);
if (typeof settings.complete === "function") {
settings.complete.apply(self, [xhr]);
}
}
else if (typeof settings.error === "function") {
settings.error.apply(self, [xhr]);
}
}
};
xhr.open("GET", settings.src, true);
try {
xhr.send();
}
catch (e) {
if (typeof settings.error === "function") {
settings.error.apply(this, [xhr]);
}
}
return this;
}
};
return Bvh;
})();
Bvh.Bone = window.Bvh.Bone || (function() {
function Bone(parent)
{
this.setParent(parent);
}
Bone.prototype = {
_name: "",
_offsetX: 0,
_offsetY: 0,
_offsetZ: 0,
_endOffsetX: 0,
_endOffsetY: 0,
_endOffsetZ: 0,
_positionX: 0,
_positionY: 0,
_positionZ: 0,
_rotationX: 0,
_rotationY: 0,
_rotationZ: 0,
_numChannels: 0,
_channels: [],
_parent: null,
_children: [],
_end: false,
setName: function(name)
{
if (typeof name === "string") {
this._name = name;
}
return this;
},
getName: function() { return this._name; },
setParent: function(bone)
{
if (bone instanceof Bone || bone === null) {
this._parent = bone;
}
return this;
},
getParent: function()
{
return this._parent;
},
addChild: function(child)
{
if (child instanceof Bone) {
child.setParent(this);
this._children.push(child);
}
return this;
},
getChild: function(index) { return this._children[index]; },
getChildren: function() { return this._children; },
setNumChannels: function(num)
{
if (!isNaN(num)) {
this._numChannels = Number(num);
}
return this;
},
getNumChannels: function() { return this._numChannels; },
setChannels: function(channels)
{
this._channels = channels instanceof Array ? channels : [channels];
return this;
},
getChannels: function() { return this._channels; },
setOffset: function(offset)
{
if (typeof offset.x !== 'undefined') {
this.setOffsetX(offset.x);
}
if (typeof offset.y !== 'undefined') {
this.setOffsetY(offset.y);
}
if (typeof offset.z !== 'undefined') {
this.setOffsetZ(offset.z);
}
return this;
},
setOffsetX: function(x)
{
if (!isNaN(x)) {
this._offsetX = Number(x);
}
return this;
},
setOffsetY: function(y)
{
if (!isNaN(y)) {
this._offsetY = Number(y);
}
return this;
},
setOffsetZ: function(z)
{
if (!isNaN(z)) {
this._offsetZ = Number(z);
}
return this;
},
getOffset: function()
{
return {
x: this._offsetX,
y: this._offsetY,
z: this._offsetZ
};
},
getOffsetX: function() { return this._offsetX; },
getOffsetY: function() { return this._offsetY; },
getOffsetZ: function() { return this._offsetZ; },
setEndOffset: function(offset)
{
if (typeof offset.x !== 'undefined') {
this.setEndOffsetX(offset.x);
}
if (typeof offset.y !== 'undefined') {
this.setEndOffsetY(offset.y);
}
if (typeof offset.z !== 'undefined') {
this.setEndOffsetZ(offset.z);
}
return this;
},
setEndOffsetX: function(x)
{
if (!isNaN(x)) {
this._endOffsetX = Number(x);
}
return this;
},
setEndOffsetY: function(y)
{
if (!isNaN(y)) {
this._endOffsetY = Number(y);
}
return this;
},
setEndOffsetZ: function(z)
{
if (!isNaN(z)) {
this._endOffsetZ = Number(z);
}
return this;
},
getEndOffset: function()
{
return {
x: this._endOffsetX,
y: this._endOffsetY,
z: this._endOffsetZ
};
},
getEndOffsetX: function() { return this._endOffsetX; },
getEndOffsetY: function() { return this._endOffsetY; },
getEndOffsetZ: function() { return this._endOffsetZ; },
setPosition: function(position)
{
if (typeof position.x !== "undefined") {
this.setPositionX(position.x);
}
if (typeof position.y !== "undefined") {
this.setPositionY(position.y);
}
if (typeof position.z !== "undefined") {
this.setPositionZ(position.z);
}
return this;
},
setPositionX: function(x)
{
if (!isNaN(x)) {
this._positionX = Number(x);
}
return this;
},
setPositionY: function(y)
{
if (!isNaN(y)) {
this._positionY = Number(y);
}
return this;
},
setPositionZ: function(z)
{
if (!isNaN(z)) {
this._positionZ = Number(z);
}
return this;
},
getPosition: function()
{
return {
x: this._positionX,
y: this._positionY,
z: this._positionZ
};
},
getPositionX: function() { return this._positionX; },
getPositionY: function() { return this._positionY; },
getPositionZ: function() { return this._positionZ; },
setRotation: function(rotation)
{
if (typeof rotation.x !== "undefined") {
this.setRotationX(rotation.x);
}
if (typeof rotation.y !== "undefined") {
this.setRotationY(rotation.y);
}
if (typeof rotation.z !== "undefined") {
this.setRotationZ(rotation.z);
}
return this;
},
setRotationX: function(x)
{
if (!isNaN(x)) {
this._rotationX = Number(x);
}
return this;
},
setRotationY: function(y)
{
if (!isNaN(y)) {
this._rotationY = Number(y);
}
return this;
},
setRotationZ: function(z)
{
if (!isNaN(z)) {
this._rotationZ = Number(z);
}
return this;
},
getRotation: function()
{
return {
x: this._rotationX,
y: this._rotationY,
z: this._rotationZ
};
},
getRotationX: function() { return this._rotationX; },
getRotationY: function() { return this._rotationY; },
getRotationZ: function() { return this._rotationZ; },
isRoot: function() { return this._parent === null; },
isEnd: function() { return this._end; },
setEnd: function(b)
{
this._end = !!b;
return this;
},
init: function()
{
this._parent = null;
this._channels = [];
this._children = [];
return this;
}
};
return Bone;
})();
Bvh.Parser = window.Bvh.Parser || (function() {
function Parser(bvh, str)
{
var lineArr = str.split("\n");
this._lines = [];
for (var key in lineArr) {
this._lines.push(new Bvh.Line(lineArr[key]));
}
this._currentLine = 1;
bvh.rootBone = this._parseBone(bvh.getBones());
var length = this._lines.length;
for (var currentLine = 0; currentLine < length; currentLine++) {
if (this._lines[currentLine].getLineType() === "MOTION") {
break;
}
}
var numFrames = this._lines[++currentLine].getNumFrames();
bvh.setNumFramesInternal(numFrames);
bvh.setFrameTimeInternal(this._lines[++currentLine].getFrameTime());
var frames = [];
var length = this._lines.length;
for (var i = ++currentLine; i < length; i++) {
frames.push(this._lines[i].getFrames());
}
bvh.setFrames(frames);
bvh.setNumFramesInternal(frames.length);
}
Parser.prototype = {
_lines: [],
_currentLine: 0,
_currentBone: null,
_parseBone: function(bones)
{
var bone = new Bvh.Bone(this._currentBone);
bones.push(bone);
bone.setName(this._lines[this._currentLine++].getBoneName());
bone.setOffset(this._lines[++this._currentLine].getOffset());
var line = this._lines[++this._currentLine];
bone.setNumChannels(line.getNumChannels());
bone.setChannels(line.getChannelsProps());
this._currentLine++;
while (this._currentLine < this._lines.length) {
switch (this._lines[this._currentLine].getLineType()) {
case "ROOT":
case "JOINT":
var child = this._parseBone(bones);
bone.addChild(child);
break;
case "End":
this._currentLine++;
this._currentLine++;
bone.setEnd(true);
var line = this._lines[this._currentLine];
bone.setOffset(line.getOffset());
this._currentLine++;
this._currentLine++;
case "}":
return bone;
}
this._currentLine++;
}
return bone;
}
};
return Parser;
})();
Bvh.Line = window.Bvh.Line || (function() {
function Line(str)
{
this._parse(str);
}
Line.prototype = {
_lineType: "",
_boneType: "",
_boneName: "",
_offsetX: 0,
_offsetY: 0,
_offsetZ: 0,
_numChannels: 0,
_channelsProps: [],
_numFrames: 0,
_frameTime: 0,
_frames: [],
_parse: function(str)
{
var lineStr = this._trim(str);
var words = lineStr.split(" ");
if (String(words[0]).indexOf("Frames:") !== -1) {
words[0] = "Frames:";
words.push(lineStr.split(":")[1]);
}
if (words[0] === "Frame" && words.length === 2) {
words[1] = "Time:";
words[2] = lineStr.split(":")[1];
}
this._lineType = !isNaN(Number(words[0])) ? "FRAME" : words[0];
switch (this._lineType) {
case "HIERARCHY":
break;
case "ROOT":
case "JOINT":
this._boneType = words[0] === "ROOT" ? "ROOT" : "JOINT";
this._boneName = words[1];
break;
case "OFFSET":
this._offsetX = Number(words[1]);
this._offsetY = Number(words[2]);
this._offsetZ = Number(words[3]);
break;
case "CHANNELS":
this._numChannels = Number(words[1]);
this._channelsProps = [];
for (var i = 0; i < this._numChannels; i++) {
this._channelsProps.push(words[i + 2]);
}
break;
case "Frames:":
this._numFrames = Number(words[1]);
break;
case "Frame":
this._frameTime = Number(words[2]);
break;
case "End":
case "{":
case "}":
case "MOTION":
break;
case "FRAME":
this._frames = [];
for (var key in words) {
this._addFrame(words[key]);
}
break;
}
},
_trim: function(str)
{
var startIndex = 0;
while (this._isWhitespace(str.charAt(startIndex))) {
++startIndex;
}
var endIndex = str.length - 1;
while (this._isWhitespace(str.charAt(endIndex))) {
--endIndex;
}
return endIndex >= startIndex
? str.slice(startIndex, endIndex + 1) : "";
},
_isWhitespace: function(character)
{
return character.match(/\s|\t|\r|\n|\f/);
},
_addFrame: function(frame)
{
if (!isNaN(frame)) {
this._frames.push(Number(frame));
}
},
getFrames: function() { return this._frames; },
getFrameTime: function() { return this._frameTime; },
getNumFrames: function() { return this._numFrames; },
getChannelsProps: function() { return this._channelsProps; },
getNumChannels: function() { return this._numChannels; },
getOffset: function() {
return {
x: this._offsetX,
y: this._offsetY,
z: this._offsetZ
}
},
getOffsetZ: function() { return this._offsetZ; },
getOffsetY: function() { return this._offsetY; },
getOffsetX: function() { return this._offsetX; },
getBoneName: function() { return this._boneName; },
getBoneType: function() { return this._boneType; },
getLineType: function() { return this._lineType; }
};
return Line;
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment