Skip to content

Commit

Permalink
Added SplinePositionInterpolator.js to the Interpolation Component.
Browse files Browse the repository at this point in the history
  • Loading branch information
xperien committed Sep 22, 2014
1 parent 7370f21 commit 8a04847
Show file tree
Hide file tree
Showing 2 changed files with 247 additions and 1 deletion.
245 changes: 245 additions & 0 deletions src/nodes/Interpolation/SplinePositionInterpolator.js
@@ -0,0 +1,245 @@
/** @namespace x3dom.nodeTypes */
/*
* Based on code originally provided by
* http://www.x3dom.org
*
* (C)2014 Toshiba Corporation, Japan.
* Dual licensed under the MIT and GPL
*/

// ### SplinePositionInterpolator ###
x3dom.registerNodeType(
"SplinePositionInterpolator",
"Interpolation",
defineClass(x3dom.nodeTypes.X3DInterpolatorNode,

/**
* Constructor for SplinePositionInterpolator
* @constructs x3dom.nodeTypes.SplinePositionInterpolator
* @x3d 3.3
* @component Interpolation
* @status experimental
* @extends x3dom.nodeTypes.X3DInterpolatorNode
* @param {Object} [ctx=null] - context object, containing initial settings like namespace
* @classdesc The SplinePositionInterpolator node non-linearly interpolates among a list of 3D vectors to produce an SFVec3f value_changed event. The keyValue, keyVelocity, and key fields shall each have the same number of values.
*/
function (ctx) {
x3dom.nodeTypes.SplinePositionInterpolator.superClass.call(this, ctx);

/**
* Defines the set of data points, that are used for interpolation.
* @var {x3dom.fields.MFVec3f} keyValue
* @memberof x3dom.nodeTypes.SplinePositionInterpolator
* @initvalue []
* @field x3d
* @instance
*/
this.addField_MFVec3f(ctx, 'keyValue', []);

/**
* Defines the set of velocity vectors, that are used for interpolation.
* @var {x3dom.fields.MFVec3f} keyVelocity
* @memberof x3dom.nodeTypes.SplinePositionInterpolator
* @initvalue []
* @field x3d
* @instance
*/
this.addField_MFVec3f(ctx, 'keyVelocity', []);

/**
* Specifies whether the interpolator should provide a closed loop, with continuous velocity vectors as the interpolator transitions from the last key to the first key.
* @var {x3dom.fields.SFBool} closed
* @memberof x3dom.nodeTypes.SplinePositionInterpolator
* @initvalue false
* @field x3d
* @instance
*/
this.addField_SFBool(ctx, 'closed', false);

/**
* Specifies whether the velocity vectors are to be transformed into normalized tangency vectors.
* @var {x3dom.fields.SFBool} normalizeVelocity
* @memberof x3dom.nodeTypes.SplinePositionInterpolator
* @initvalue false
* @field x3d
* @instance
*/
this.addField_SFBool(ctx, 'normalizeVelocity', false);

/******** Private variables and functions ***********/

/* dtot is the sum of the distance between all adjacent keys.
* dtot = SUM{i=0, i < n-1}(|vi - vi+1|)
*/
this.dtot = 0.0;

/* Non-uniform interval adjusted velocity vectors
*/
this.T0 = [];
this.T1 = [];

/* Checks sanity. Node is sane if (|key| == |key_value|) and (|key| == |key_velocity| or |key_velocity| == 0 or (|key_velocity| == 2 and |key| >= 2))
*/
this.checkSanity = function() {
var sane = (this._vf.key.length == this._vf.keyValue.length) &&
((this._vf.key.length == this._vf.keyVelocity.length) || (this._vf.keyVelocity.length == 2 && this._vf.key.length >= 2) || (this._vf.keyVelocity.length == 0));
if(!sane)
x3dom.debug.logWarning("SplinePositionInterpolator Node: 'key' , 'keyValue' and/or 'keyVelocity' fields have inappropriate sizes");
};

/* Calculate dtot (sum of distances between all adjacent keys)
*/
this.calcDtot = function()
{
this.dtot = 0.0;
for(var i = 0; i < this._vf.key.length-1; i++)
{
this.dtot += Math.abs(this._vf.key[i] - this._vf.key[i+1]);
}
};

/* Calculate non-uniform interval adjusted velocity vectors
*/
this.calcAdjustedKeyVelocity = function()
{
var i, Ti, F_plus_i, F_minus_i;
var N = this._vf.key.length;

// If velocities are defined at all the control points, ignore 'closed' field
if(this._vf.keyVelocity.length == N)
{
for(i = 0; i < N; i++)
{
Ti = this._vf.keyVelocity[i];

if(this._vf.normalizeVelocity)
Ti = Ti.multiply(this.dtot / Ti.length());

F_plus_i = (i == 0 || i == N-1) ? 1.0 : 2.0 * (this._vf.key[i] - this._vf.key[i-1]) / (this._vf.key[i+1] - this._vf.key[i-1]);
F_minus_i= (i == 0 || i == N-1) ? 1.0 : 2.0 * (this._vf.key[i+1] - this._vf.key[i]) / (this._vf.key[i+1] - this._vf.key[i-1]);

this.T0[i] = Ti.multiply(F_plus_i);
this.T1[i] = Ti.multiply(F_minus_i);
}
}
// if only first and last velocities are specified, ignore 'closed' field
else if(this._vf.keyVelocity.length == 2 && N > 2)
{
for(i = 0; i < N; i++)
{
if(i == 0)
Ti = this._vf.keyVelocity[0];
else if(i == N-1)
Ti = this._vf.keyVelocity[1];
else
Ti = this._vf.keyValue[i+1].subtract(this._vf.keyValue[i-1]).multiply(0.5);

if(this._vf.normalizeVelocity)
Ti = Ti.multiply(this.dtot / Ti.length());

F_plus_i = (i == 0 || i == N-1) ? 1.0 : 2.0 * (this._vf.key[i] - this._vf.key[i-1]) / (this._vf.key[i+1] - this._vf.key[i-1]);
F_minus_i= (i == 0 || i == N-1) ? 1.0 : 2.0 * (this._vf.key[i+1] - this._vf.key[i]) / (this._vf.key[i+1] - this._vf.key[i-1]);

this.T0[i] = Ti.multiply(F_plus_i);
this.T1[i] = Ti.multiply(F_minus_i);
}
}
// velocities are unspecified
else
{
// ignore closed if first and last keyValues are not equal
var closed = this._vf.closed && this._vf.keyValue[0].equals(this._vf.keyValue[N-1], 0.00001);

for(i = 0; i < N; i++)
{
if((i == 0 || i == N-1) && !closed)
{
this.T0[i] = new x3dom.fields.SFVec3f(0, 0, 0);
this.T1[i] = new x3dom.fields.SFVec3f(0, 0, 0);
continue;
}
else if((i == 0 || i == N-1) && closed)
{
Ti = this._vf.keyValue[1].subtract(this._vf.keyValue[N-2]).multiply(0.5);
if(i == 0) {
F_plus_i = 2.0 * (this._vf.key[0] - this._vf.key[N-2]) / (this._vf.key[1] - this._vf.key[N-2]);
F_minus_i= 2.0 * (this._vf.key[1] - this._vf.key[0]) / (this._vf.key[1] - this._vf.key[N-2]);
}
else {
F_plus_i = 2.0 * (this._vf.key[N-1] - this._vf.key[N-2]) / (this._vf.key[1] - this._vf.key[N-2]);
F_minus_i= 2.0 * (this._vf.key[1] - this._vf.key[N-1]) / (this._vf.key[1] - this._vf.key[N-2]);
}
F_plus_i = 2.0 * (this._vf.key[N-1] - this._vf.key[N-2]) / (this._vf.key[N-2] - this._vf.key[1]);
F_minus_i= 2.0 * (this._vf.key[1] - this._vf.key[0]) / (this._vf.key[N-2] - this._vf.key[1]);
}
else
{
Ti = this._vf.keyValue[i+1].subtract(this._vf.keyValue[i-1]).multiply(0.5);
F_plus_i = 2.0 * (this._vf.key[i] - this._vf.key[i-1]) / (this._vf.key[i+1] - this._vf.key[i-1]);
F_minus_i= 2.0 * (this._vf.key[i+1] - this._vf.key[i]) / (this._vf.key[i+1] - this._vf.key[i-1]);
}

this.T0[i] = Ti.multiply(F_plus_i);
this.T1[i] = Ti.multiply(F_minus_i);
}
}
};

this.checkSanity();
this.calcDtot();
this.calcAdjustedKeyVelocity();
},
{
fieldChanged: function(fieldName)
{
switch(fieldName)
{
case 'key':
case 'keyValue':
case 'keyVelocity':
{
this.checkSanity();
this.calcDtot();
this.calcAdjustedKeyVelocity();
break;
}
case 'closed':
case 'normalizeVelocity':
{
this.calcAdjustedKeyVelocity();
break;
}
case 'set_fraction':
{
var value;

if(this._vf.key.length > 0.0) {
if (this._vf.set_fraction <= this._vf.key[0])
value = x3dom.fields.SFVec3f.copy(this._vf.keyValue[0]);

else if (this._vf.set_fraction >= this._vf.key[this._vf.key.length-1])
value = x3dom.fields.SFVec3f.copy(this._vf.keyValue[this._vf.key.length-1]);
}

for(var i = 0; i < this._vf.key.length-1; i++) {
if ((this._vf.key[i] < this._vf.set_fraction) && (this._vf.set_fraction <= this._vf.key[i+1])) {
var s = (this._vf.set_fraction - this._vf.key[i]) / (this._vf.key[i+1]-this._vf.key[i]);

var S_H = new x3dom.fields.SFVec4f(2.0*s*s*s - 3.0*s*s + 1.0, -2.0*s*s*s + 3.0*s*s, s*s*s - 2.0*s*s + s, s*s*s - s*s);
value = new x3dom.fields.SFVec3f(S_H.x * this._vf.keyValue[i].x + S_H.y * this._vf.keyValue[i+1].x + S_H.z * this.T0[i].x + S_H.w * this.T1[i+1].x,
S_H.x * this._vf.keyValue[i].y + S_H.y * this._vf.keyValue[i+1].y + S_H.z * this.T0[i].y + S_H.w * this.T1[i+1].y,
S_H.x * this._vf.keyValue[i].z + S_H.y * this._vf.keyValue[i+1].z + S_H.z * this.T0[i].z + S_H.w * this.T1[i+1].z);
break;
}
}

if(value !== undefined)
this.postMessage('value_changed', value);
else
x3dom.debug.logWarning("SplinePositionInterpolator Node: value_changed is undefined!");
}
}
}
}
)
);
3 changes: 2 additions & 1 deletion tools/packages.json
Expand Up @@ -153,7 +153,8 @@
{"file": "NormalInterpolator.js"},
{"file": "ColorInterpolator.js"},
{"file": "ScalarInterpolator.js"},
{"file": "CoordinateInterpolator.js"}
{"file": "CoordinateInterpolator.js"},
{"file": "SplinePositionInterpolator.js"}
]},
{"name": "Time", "filePrefix": "nodes/Time/", "files":[
{"file": "TimeSensor.js"},
Expand Down

0 comments on commit 8a04847

Please sign in to comment.