Started replacing OSGJS with three.js

pull/78/head
Piero Toffanin 2017-01-02 18:08:09 -05:00
rodzic 9fc005d8aa
commit f9f4f9f869
263 zmienionych plików z 62 dodań i 63802 usunięć

Wyświetl plik

@ -1,10 +1,15 @@
import React from 'react';
import './css/ModelView.scss';
import {osgDB, osgGA, osgViewer, osg, CADManipulator} from './vendor/osgjs/OSG';
import $ from 'jquery';
const THREE = require('three'); // import does not work :/
require('./vendor/OBJLoader');
THREE.OrbitControls = require('three-orbit-controls')(THREE);
THREE.MTLLoader = require('three-mtl-loader');
class ModelView extends React.Component {
static defaultProps = {
test: 0
test: 1
};
static propTypes = {
@ -19,29 +24,64 @@ class ModelView extends React.Component {
}
componentDidMount() {
this.viewer = new osgViewer.Viewer(this.canvas);
this.viewer.init();
const node = new osg.MatrixTransform();
var container;
var camera, controls, scene, renderer;
var lighting, ambient, keyLight, fillLight, backLight;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;
this.viewer.setSceneData( node );
this.viewer.setupManipulator(new osgGA.CADManipulator());
this.viewer.getManipulator().computeHomePosition();
this.viewer.run();
const init = () => {
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.z = 3;
let request = osgDB.readNodeURL( '/static/app/test/test.osgjs' );
request.then( function ( model ) {
node.addChild(model);
this.viewer.getManipulator().computeHomePosition();
}.bind( this ) );
scene = new THREE.Scene();
ambient = new THREE.AmbientLight(0xFFFFFF, 1.0);
scene.add(ambient);
var mtlLoader = new THREE.MTLLoader();
mtlLoader.setTexturePath('/static/app/test/');
mtlLoader.setPath('/static/app/test/');
mtlLoader.load('odm_textured_model.mtl', function (materials) {
materials.preload();
const objLoader = new THREE.OBJLoader();
objLoader.setMaterials(materials);
objLoader.load('/static/app/test/odm_textured_model.obj', function (object) {
scene.add(object);
console.log(object);
});
});
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize($(this.canvas).width(), $(this.canvas).height());
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.2;
controls.enableZoom = true;
this.canvas.appendChild(renderer.domElement);
};
function render() {
requestAnimationFrame(render);
controls.update();
renderer.render(scene, camera);
}
init();
render();
}
// React render
render(){
return (<div className="model-view">
<canvas
<div
ref={(domNode) => { this.canvas = domNode; }}
style={{height: "100%", width: "100%"}}
onContextMenu={(e) => {e.preventDefault();}}></canvas>
onContextMenu={(e) => {e.preventDefault();}}></div>
</div>);
}
}

Plik diff jest za duży Load Diff

Plik diff jest za duży Load Diff

File diff suppressed because one or more lines are too long

Plik diff jest za duży Load Diff

Wyświetl plik

@ -1,13 +0,0 @@
// This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment.
require('../../js/transition.js')
require('../../js/alert.js')
require('../../js/button.js')
require('../../js/carousel.js')
require('../../js/collapse.js')
require('../../js/dropdown.js')
require('../../js/modal.js')
require('../../js/tooltip.js')
require('../../js/popover.js')
require('../../js/scrollspy.js')
require('../../js/tab.js')
require('../../js/affix.js')

Wyświetl plik

@ -1,40 +0,0 @@
'use strict';
var osgNameSpace = require( 'osgNameSpace' );
var osg = require( 'osg/osg' );
var osgAnimation = require( 'osgAnimation/osgAnimation' );
var osgDB = require( 'osgDB/osgDB' );
var osgGA = require( 'osgGA/osgGA' );
var osgUtil = require( 'osgUtil/osgUtil' );
var osgViewer = require( 'osgViewer/osgViewer' );
var osgShader = require( 'osgShader/osgShader' );
var osgShadow = require( 'osgShadow/osgShadow' );
var osgText = require( 'osgText/osgText' );
var osgWrappers = require( 'osgWrappers/osgWrappers' );
var osgPlugins = require( 'osgPlugins/osgPlugins' );
var openSceneGraph = osgNameSpace;
openSceneGraph.osg = osg;
openSceneGraph.osgAnimation = osgAnimation;
openSceneGraph.osgDB = osgDB;
openSceneGraph.osgGA = osgGA;
openSceneGraph.osgUtil = osgUtil;
openSceneGraph.osgViewer = osgViewer;
openSceneGraph.osgShader = osgShader;
openSceneGraph.osgShadow = osgShadow;
openSceneGraph.osgText = osgText;
openSceneGraph.osgWrappers = osgWrappers;
openSceneGraph.osgPlugins = osgPlugins;
var namespaces = [ 'osg', 'osgAnimation', 'osgDB', 'osgGA', 'osgUtil', 'osgViewer', 'osgShader', 'osgShadow', 'osgText', 'osgWrappers', 'osgPlugins' ];
// for backward compatibility
openSceneGraph.globalify = function () {
namespaces.forEach( function ( namespace ) {
window[ namespace ] = openSceneGraph[ namespace ];
} );
};
module.exports = openSceneGraph;

Wyświetl plik

@ -1,5 +0,0 @@
'use strict';
module.exports = {
ArrayType: Float64Array
};

Wyświetl plik

@ -1,332 +0,0 @@
'use strict';
var MACROUTILS = require( 'osg/Utils' );
var Transform = require( 'osg/Transform' );
var vec3 = require( 'osg/glMatrix' ).vec3;
var vec4 = require( 'osg/glMatrix' ).vec4;
var quat = require( 'osg/glMatrix' ).quat;
var mat4 = require( 'osg/glMatrix' ).mat4;
var NodeVisitor = require( 'osg/NodeVisitor' );
var TransformEnums = require( 'osg/transformEnums' );
var Node = require( 'osg/Node' );
/** AutoTransform is a derived form of Transform that automatically
* scales or rotates to keep its children aligned with screen coordinates.
* W.r.t. AutorotateModes only rotate to screen is supported right now.
* More AutorotateModes modes should be addressed in the future.
* @class AutoTransform
*/
var AutoTransform = function () {
Transform.call( this );
this._matrix = mat4.create();
this._position = vec3.create();
this._matrixDirty = true;
this._scale = vec3.fromValues( 1.0, 1.0, 1.0 );
this._minimumScale = 0;
this._maximumScale = Number.MAX_VALUE;
this._rotation = quat.create();
this._pivotPoint = vec3.create();
this._autoScaleToScreen = false;
this._autoRotateToScreen = false;
this._cachedMatrix = mat4.create();
this._firstTimeToInitEyePoint = true;
this._autoScaleTransitionWidthRatio = 0.25;
this._billboardAttribute = undefined;
this._previousWidth = 0.0;
this._previousHeight = 0.0;
this._previousProjection = mat4.create();
this._previousModelView = mat4.create();
this._previousPosition = vec3.create();
};
/** @lends Autotransform.prototype */
AutoTransform.prototype = MACROUTILS.objectLibraryClass( MACROUTILS.objectInherit( Transform.prototype, {
getMatrix: function () {
return this._matrix;
},
setMatrix: function ( m ) {
this._matrix = m;
this.dirtyBound();
},
setPosition: function ( pos ) {
this._position = pos;
this._matrixDirty = true;
this.dirtyBound();
},
getPosition: function () {
return this._position;
},
setRotation: function ( q ) {
this._rotation = q;
this._matrixDirty = true;
this.dirtyBound();
},
getRotation: function () {
return this._rotation;
},
setScale: function ( scale ) {
this.setScaleFromvec3( vec3.fromValues( scale, scale, scale ) );
},
setScaleFromvec3: function ( scaleVec ) {
this._scale = scaleVec;
this._matrixDirty = true;
this.dirtyBound();
},
getScale: function () {
return this._scale;
},
setMinimumScale: function ( minimumScale ) {
this._minimumScale = minimumScale;
},
getMinimumScale: function () {
return this._minimumScale;
},
setMaximumScale: function ( maximumScale ) {
this._maximumScale = maximumScale;
},
getMaximumScale: function () {
return this._maximumScale;
},
setAutoScaleToScreen: function ( autoScaleToScreen ) {
this._autoScaleToScreen = autoScaleToScreen;
this._matrixDirty = true;
},
getAutoScaleToScreen: function () {
return this._autoScaleToScreen;
},
setAutoRotateToScreen: function ( value ) {
this._autoRotateToScreen = value;
},
getAutoRotateToScreen: function () {
return this._autoRotateToScreen;
},
setAutoScaleTransitionWidthRatio: function ( autoScaleTransitionWidthRatio ) {
this._autoScaleTransitionWidthRatio = autoScaleTransitionWidthRatio;
},
getAutoScaleTransitionWidthRatio: function () {
return this._autoScaleTransitionWidthRatio;
},
// local to "local world" (not Global World)
computeLocalToWorldMatrix: function ( matrix /*, nodeVisitor */ ) {
if ( this._matrixDirty ) this.computeMatrix();
if ( this.referenceFrame === TransformEnums.RELATIVE_RF ) {
mat4.mul( matrix, matrix, this._matrix );
} else {
mat4.copy( matrix, this._matrix );
}
},
computeMatrix: ( function () {
var neg = vec3.create();
var tmpMat = mat4.create();
return function () {
if ( !this._matrixDirty ) return;
mat4.fromQuat( this._matrix, this._rotation );
mat4.fromTranslation( tmpMat, this._position );
mat4.mul( this._matrix, tmpMat, this._matrix );
mat4.scale( this._matrix, this._matrix, this._scale );
mat4.translate( this._matrix, this._matrix, vec3.neg( neg, this._pivotPoint ) );
this._matrixDirty = false;
};
} )(),
computeWorldToLocalMatrix: ( function () {
var neg = vec3.create();
var rotInverse = quat.create();
var scaleInverse = vec3.create();
var tmpMat = mat4.create();
return function ( matrix /*, nodeVisitor */ ) {
if ( this.scale[ 0 ] === 0.0 && this.scale[ 1 ] === 0.0 && this.scale[ 2 ] === 0.0 ) {
return false;
}
scaleInverse[ 0 ] = 1.0 / this._scale[ 0 ];
scaleInverse[ 1 ] = 1.0 / this._scale[ 1 ];
scaleInverse[ 2 ] = 1.0 / this._scale[ 2 ];
if ( this.referenceFrame === TransformEnums.RELATIVE_RF ) {
mat4.fromTranslation( tmpMat, vec3.neg( neg, this._position ) );
mat4.mul( matrix, tmpMat, matrix );
if ( !quat.zeroRotation( this._rotation ) ) {
mat4.fromQuat( tmpMat, quat.invert( rotInverse, this._rotation ) );
mat4.mul( matrix, tmpMat, matrix );
}
mat4.fromScaling( tmpMat, scaleInverse );
mat4.mul( matrix, tmpMat, matrix );
mat4.fromTranslation( tmpMat, this._pivotPoint );
mat4.mul( matrix, tmpMat, matrix );
} else { // absolute
mat4.fromQuat( this._matrix, quat.invert( rotInverse, this._rotation ) );
mat4.translate( matrix, matrix, vec3.neg( neg, this._position ) );
mat4.fromScaling( tmpMat, scaleInverse );
mat4.mul( matrix, tmpMat, matrix );
mat4.fromTranslation( tmpMat, this._pivotPoint );
mat4.mul( matrix, tmpMat, matrix );
}
return true;
};
} )(),
computeBound: ( function () {
var matrix = mat4.create();
return function ( bSphere ) {
if ( this._autoScaleToScreen && this._firstTimeToInitEyePoint )
return bSphere;
Node.prototype.computeBound.call( this, bSphere );
if ( !bSphere.valid() ) {
return bSphere;
}
mat4.identity( matrix );
// local to local world (not Global World)
this.computeLocalToWorldMatrix( matrix );
//Matrix.transformBoundingSphere( matrix, bSphere, bSphere );
bSphere.transformMat4( bSphere, matrix );
return bSphere;
};
} )(),
accept: ( function () {
return function ( visitor ) {
if ( visitor.getVisitorType() === NodeVisitor.CULL_VISITOR ) {
var width = visitor.getViewport().width();
var height = visitor.getViewport().height();
var projMat = visitor.getCurrentProjectionMatrix();
var modelViewMat = visitor.getCurrentModelViewMatrix();
var position = this._position;
var doUpdate = this._firstTimeToInitEyePoint;
if ( !this._firstTimeToInitEyePoint ) {
if ( width !== this._previousWidth || height !== this._previousHeight ) {
doUpdate = true;
} else if ( !mat4.exactEquals( projMat, this._previousProjection ) ) {
doUpdate = true;
} else if ( !mat4.exactEquals( modelViewMat, this._previousModelView ) ) {
doUpdate = true;
} else if ( !vec3.exactEquals( position, this._previousPosition ) ) {
doUpdate = true;
}
}
this._firstTimeToInitEyePoint = false;
if ( doUpdate ) {
if ( this._autoScaleToScreen ) {
var viewport = visitor.getViewport();
var psvector = this.computePixelSizeVector( viewport, projMat, modelViewMat );
var v = vec4.fromValues( this._position[ 0 ], this._position[ 1 ], this._position[ 2 ], 1.0 );
var pixelSize = vec4.dot( v, psvector );
pixelSize = 0.48 / pixelSize;
var size = 1.0 / pixelSize;
if ( this._autoScaleTransitionWidthRatio > 0.0 ) {
var c, b, a;
if ( this._minimumScale > 0.0 ) {
var j = this._minimumScale;
var i = ( this._maximumScale < Number.MAX_VALUE ) ?
this._minimumScale + ( this._maximumScale - this._minimumScale ) * this._autoScaleTransitionWidthRatio :
this._minimumScale * ( 1.0 + this._autoScaleTransitionWidthRatio );
c = 1.0 / ( 4.0 * ( i - j ) );
b = 1.0 - 2.0 * c * i;
a = j + b * b / ( 4.0 * c );
var k = -b / ( 2.0 * c );
if ( size < k ) size = this._minimumScale;
else if ( size < i ) size = a + b * size + c * ( size * size );
}
if ( this._maximumScale < Number.MAX_VALUE ) {
var n = this._maximumScale;
var m = ( this._minimumScale > 0.0 ) ?
this._maximumScale + ( this._minimumScale - this._maximumScale ) * this._autoScaleTransitionWidthRatio :
this._maximumScale * ( 1.0 - this._autoScaleTransitionWidthRatio );
c = 1.0 / ( 4.0 * ( m - n ) );
b = 1.0 - 2.0 * c * m;
a = n + b * b / ( 4.0 * c );
var p = -b / ( 2.0 * c );
if ( size > p ) size = this._maximumScale;
else if ( size > m ) size = a + b * size + c * ( size * size );
}
}
this.setScale( size );
}
if ( this._autoRotateToScreen ) {
var rotation = quat.create();
mat4.getRotation( rotation, modelViewMat );
this.setRotation( quat.invert( rotation, rotation ) );
}
this._previousWidth = width;
this._previousHeight = height;
vec3.copy( this._previousPosition, position );
mat4.copy( this._previousProjection, projMat );
mat4.copy( this._previousModelView, modelViewMat );
}
}
Node.prototype.accept.call( this, visitor );
};
} )(),
computePixelSizeVector: ( function () {
var scale00 = vec3.create();
var scale10 = vec3.create();
return function ( W, P, M ) {
// Where W = viewport, P = ProjectionMatrix, M = ModelViewMatrix
// Comment from OSG:
// pre adjust P00,P20,P23,P33 by multiplying them by the viewport window matrix.
// here we do it in short hand with the knowledge of how the window matrix is formed
// note P23,P33 are multiplied by an implicit 1 which would come from the window matrix.
// scaling for horizontal pixels
var P00 = P[ 0 ] * W.width() * 0.5;
var P20_00 = P[ 8 ] * W.width() * 0.5 + P[ 11 ] * W.width() * 0.5;
vec3.set( scale00, M[ 0 ] * P00 + M[ 2 ] * P20_00,
M[ 4 ] * P00 + M[ 6 ] * P20_00,
M[ 8 ] * P00 + M[ 10 ] * P20_00 );
// scaling for vertical pixels
var P10 = P[ 5 ] * W.height() * 0.5;
var P20_10 = P[ 9 ] * W.height() * 0.5 + P[ 11 ] * W.height() * 0.5;
vec3.set( scale10, M[ 1 ] * P10 + M[ 2 ] * P20_10,
M[ 5 ] * P10 + M[ 6 ] * P20_10,
M[ 9 ] * P10 + M[ 10 ] * P20_10 );
var P23 = P[ 11 ];
var P33 = P[ 15 ];
var pixelSizeVector = vec4.fromValues( M[ 2 ] * P23, M[ 6 ] * P23, M[ 10 ] * P23, M[ 14 ] * P23 + M[ 15 ] * P33 );
var scaleRatio = 0.7071067811 / Math.sqrt( vec3.sqrLen( scale00 ) + vec3.sqrLen( scale10 ) );
vec4.scale( pixelSizeVector, pixelSizeVector, scaleRatio );
return pixelSizeVector;
};
} )()
} ), 'osg', 'AutoTransform' );
MACROUTILS.setTypeID( AutoTransform );
module.exports = AutoTransform;

Wyświetl plik

@ -1,31 +0,0 @@
'use strict';
var MACROUTILS = require( 'osg/Utils' );
var StateAttribute = require( 'osg/StateAttribute' );
var BillboardAttribute = function () {
StateAttribute.call( this );
this._attributeEnable = false;
};
BillboardAttribute.prototype = MACROUTILS.objectLibraryClass( MACROUTILS.objectInherit( StateAttribute.prototype, {
attributeType: 'Billboard',
cloneType: function () {
return new BillboardAttribute();
},
setEnabled: function ( state ) {
this._attributeEnable = state;
},
isEnabled: function () {
return this._attributeEnable;
},
apply: function () {}
} ), 'osg', 'Billboard' );
module.exports = BillboardAttribute;

Wyświetl plik

@ -1,49 +0,0 @@
'use strict';
var MACROUTILS = require( 'osg/Utils' );
var StateAttribute = require( 'osg/StateAttribute' );
var vec4 = require( 'osg/glMatrix' ).vec4;
/**
* Manage BlendColor attribute
* @class
* @memberOf osg
* @extends StateAttribute
*/
var BlendColor = function ( color ) {
StateAttribute.call( this );
this._constantColor = vec4.create();
vec4.set( this._constantColor, 1.0, 1.0, 1.0, 1.0 );
if ( color !== undefined ) {
this.setConstantColor( color );
}
};
/**
* @lends BlendColor.prototype
*/
BlendColor.prototype = MACROUTILS.objectLibraryClass( MACROUTILS.objectInherit( StateAttribute.prototype, {
attributeType: 'BlendColor',
cloneType: function () {
return new BlendColor();
},
/**
*
* @param {} color
*/
setConstantColor: function ( color ) {
vec4.copy( this._constantColor, color );
},
getConstantColor: function () {
return this._constantColor;
},
apply: function ( state ) {
var gl = state.getGraphicContext();
gl.blendColor( this._constantColor[ 0 ],
this._constantColor[ 1 ],
this._constantColor[ 2 ],
this._constantColor[ 3 ] );
}
} ), 'osg', 'BlendColor' );
module.exports = BlendColor;

Wyświetl plik

@ -1,155 +0,0 @@
'use strict';
var MACROUTILS = require( 'osg/Utils' );
var StateAttribute = require( 'osg/StateAttribute' );
/**
* Manage Blending mode
* @class BlendFunc
*/
var BlendFunc = function ( sourceRGB, destinationRGB, sourceAlpha, destinationAlpha ) {
StateAttribute.call( this );
this._sourceFactor = BlendFunc.DISABLE;
this._destinationFactor = BlendFunc.DISABLE;
this._sourceFactorAlpha = this._sourceFactor;
this._destinationFactorAlpha = this._destinationFactor;
this._separate = false;
if ( sourceRGB !== undefined ) {
this.setSource( sourceRGB );
}
if ( destinationRGB !== undefined ) {
this.setDestination( destinationRGB );
}
if ( sourceAlpha !== undefined ) {
this.setSourceAlpha( sourceAlpha );
}
if ( destinationAlpha !== undefined ) {
this.setDestinationAlpha( destinationAlpha );
}
};
BlendFunc.DISABLE = -1;
BlendFunc.ZERO = 0;
BlendFunc.ONE = 1;
BlendFunc.SRC_COLOR = 0x0300;
BlendFunc.ONE_MINUS_SRC_COLOR = 0x0301;
BlendFunc.SRC_ALPHA = 0x0302;
BlendFunc.ONE_MINUS_SRC_ALPHA = 0x0303;
BlendFunc.DST_ALPHA = 0x0304;
BlendFunc.ONE_MINUS_DST_ALPHA = 0x0305;
BlendFunc.DST_COLOR = 0x0306;
BlendFunc.ONE_MINUS_DST_COLOR = 0x0307;
BlendFunc.SRC_ALPHA_SATURATE = 0x0308;
/* Separate Blend Functions */
BlendFunc.BLEND_DST_RGB = 0x80C8;
BlendFunc.BLEND_SRC_RGB = 0x80C9;
BlendFunc.BLEND_DST_ALPHA = 0x80CA;
BlendFunc.BLEND_SRC_ALPHA = 0x80CB;
BlendFunc.CONSTANT_COLOR = 0x8001;
BlendFunc.ONE_MINUS_CONSTANT_COLOR = 0x8002;
BlendFunc.CONSTANT_ALPHA = 0x8003;
BlendFunc.ONE_MINUS_CONSTANT_ALPHA = 0x8004;
BlendFunc.BLEND_COLOR = 0x8005;
/** @lends BlendFunc.prototype */
BlendFunc.prototype = MACROUTILS.objectLibraryClass( MACROUTILS.objectInherit( StateAttribute.prototype, {
/**
StateAttribute type of BlendFunc
@type String
*/
attributeType: 'BlendFunc',
/**
Create an instance of this StateAttribute
*/
cloneType: function () /**BlendFunc*/ {
return new BlendFunc();
},
setSource: function ( f ) {
this.setSourceRGB( f );
this.setSourceAlpha( f );
},
getSource: function () {
return this._sourceFactor;
},
setDestination: function ( f ) {
this.setDestinationRGB( f );
this.setDestinationAlpha( f );
},
getDestination: function () {
return this._destinationFactor;
},
getSeparate: function () {
return this._separate;
},
checkSeparate: function () {
return ( this._sourceFactor !== this._sourceFactorAlpha ||
this._destinationFactor !== this._destinationFactorAlpha );
},
setSourceRGB: function ( f ) {
if ( typeof f === 'string' ) {
this._sourceFactor = BlendFunc[ f ];
} else {
this._sourceFactor = f;
}
this._separate = this.checkSeparate();
},
getSourceRGB: function () {
return this._sourceFactor;
},
setSourceAlpha: function ( f ) {
if ( typeof f === 'string' ) {
this._sourceFactorAlpha = BlendFunc[ f ];
} else {
this._sourceFactorAlpha = f;
}
this._separate = this.checkSeparate();
},
getSourceAlpha: function () {
return this._sourceFactorAlpha;
},
setDestinationRGB: function ( f ) {
if ( typeof f === 'string' ) {
this._destinationFactor = BlendFunc[ f ];
} else {
this._destinationFactor = f;
}
this._separate = this.checkSeparate();
},
getDestinationRGB: function () {
return this._destinationFactor;
},
setDestinationAlpha: function ( f ) {
if ( typeof f === 'string' ) {
this._destinationFactorAlpha = BlendFunc[ f ];
} else {
this._destinationFactorAlpha = f;
}
this._separate = this.checkSeparate();
},
getDestinationAlpha: function () {
return this._destinationFactorAlpha;
},
/**
Apply the mode, must be called in the draw traversal
@param state
*/
apply: function ( state ) {
var gl = state.getGraphicContext();
if ( this._sourceFactor === BlendFunc.DISABLE || this._destinationFactor === BlendFunc.DISABLE ) {
gl.disable( gl.BLEND );
} else {
gl.enable( gl.BLEND );
if ( this._separate ) {
gl.blendFuncSeparate( this._sourceFactor, this._destinationFactor,
this._sourceFactorAlpha, this._destinationFactorAlpha );
} else {
gl.blendFunc( this._sourceFactor, this._destinationFactor );
}
}
}
} ), 'osg', 'BlendFunc' );
module.exports = BlendFunc;

Wyświetl plik

@ -1,228 +0,0 @@
'use strict';
var Notify = require( 'osg/notify' );
var MACROUTILS = require( 'osg/Utils' );
var vec3 = require( 'osg/glMatrix' ).vec3;
var mat4 = require( 'osg/glMatrix' ).mat4;
var BoundingBox = function () {
this._min = vec3.create();
this._max = vec3.create();
this.init();
};
BoundingBox.prototype = MACROUTILS.objectLibraryClass( {
init: function () {
vec3.copy( this._min, vec3.INFINITY );
vec3.copy( this._max, vec3.NEGATIVE_INFINITY );
},
copy: function ( bbox ) {
var min = this._min;
var bmin = bbox._min;
min[ 0 ] = bmin[ 0 ];
min[ 1 ] = bmin[ 1 ];
min[ 2 ] = bmin[ 2 ];
var max = this._max;
var bmax = bbox._max;
max[ 0 ] = bmax[ 0 ];
max[ 1 ] = bmax[ 1 ];
max[ 2 ] = bmax[ 2 ];
},
valid: function () {
return ( this._max[ 0 ] >= this._min[ 0 ] && this._max[ 1 ] >= this._min[ 1 ] && this._max[ 2 ] >= this._min[ 2 ] );
},
expandByBoundingSphere: function ( bs ) {
if ( !bs.valid() ) {
return;
}
var max = this._max;
var min = this._min;
var radius = bs._radius;
var x = bs._center[ 0 ];
var y = bs._center[ 1 ];
var z = bs._center[ 2 ];
min[ 0 ] = Math.min( min[ 0 ], x - radius );
min[ 1 ] = Math.min( min[ 1 ], y - radius );
min[ 2 ] = Math.min( min[ 2 ], z - radius );
max[ 0 ] = Math.max( max[ 0 ], x + radius );
max[ 1 ] = Math.max( max[ 1 ], y + radius );
max[ 2 ] = Math.max( max[ 2 ], z + radius );
},
expandBySphere: function ( bs ) {
Notify.log( 'BoundingBox.expandBySphere is deprecated, use instead BoundBox.expandByBoundingSphere' );
return this.expandByBoundingSphere( bs );
},
expandByvec3: function ( v ) {
var min = this._min;
var max = this._max;
min[ 0 ] = Math.min( min[ 0 ], v[ 0 ] );
min[ 1 ] = Math.min( min[ 1 ], v[ 1 ] );
min[ 2 ] = Math.min( min[ 2 ], v[ 2 ] );
max[ 0 ] = Math.max( max[ 0 ], v[ 0 ] );
max[ 1 ] = Math.max( max[ 1 ], v[ 1 ] );
max[ 2 ] = Math.max( max[ 2 ], v[ 2 ] );
},
expandByBoundingBox: function ( bb ) {
if ( !bb.valid() )
return;
var min = this._min;
var max = this._max;
var bbmin = bb._min;
var bbmax = bb._max;
if ( bbmin[ 0 ] < min[ 0 ] ) min[ 0 ] = bbmin[ 0 ];
if ( bbmax[ 0 ] > max[ 0 ] ) max[ 0 ] = bbmax[ 0 ];
if ( bbmin[ 1 ] < min[ 1 ] ) min[ 1 ] = bbmin[ 1 ];
if ( bbmax[ 1 ] > max[ 1 ] ) max[ 1 ] = bbmax[ 1 ];
if ( bbmin[ 2 ] < min[ 2 ] ) min[ 2 ] = bbmin[ 2 ];
if ( bbmax[ 2 ] > max[ 2 ] ) max[ 2 ] = bbmax[ 2 ];
},
center: function ( result ) {
var min = this._min;
var max = this._max;
result[ 0 ] = ( min[ 0 ] + max[ 0 ] ) * 0.5;
result[ 1 ] = ( min[ 1 ] + max[ 1 ] ) * 0.5;
result[ 2 ] = ( min[ 2 ] + max[ 2 ] ) * 0.5;
return result;
},
radius: function () {
return Math.sqrt( this.radius2() );
},
radius2: function () {
var min = this._min;
var max = this._max;
var dx = max[ 0 ] - min[ 0 ];
var dy = max[ 1 ] - min[ 1 ];
var dz = max[ 2 ] - min[ 2 ];
return 0.25 * ( dx * dx + dy * dy + dz * dz );
},
getMin: function () {
return this._min;
},
getMax: function () {
return this._max;
},
setMin: function ( min ) {
vec3.copy( this._min, min );
return this;
},
setMax: function ( max ) {
vec3.copy( this._max, max );
return this;
},
xMax: function () {
return this._max[ 0 ];
},
yMax: function () {
return this._max[ 1 ];
},
zMax: function () {
return this._max[ 2 ];
},
xMin: function () {
return this._min[ 0 ];
},
yMin: function () {
return this._min[ 1 ];
},
zMin: function () {
return this._min[ 2 ];
},
corner: function ( pos, ret ) {
/*jshint bitwise: false */
if ( pos & 1 ) {
ret[ 0 ] = this._max[ 0 ];
} else {
ret[ 0 ] = this._min[ 0 ];
}
if ( pos & 2 ) {
ret[ 1 ] = this._max[ 1 ];
} else {
ret[ 1 ] = this._min[ 1 ];
}
if ( pos & 4 ) {
ret[ 2 ] = this._max[ 2 ];
} else {
ret[ 2 ] = this._min[ 2 ];
}
return ret;
/*jshint bitwise: true */
},
// http://dev.theomader.com/transform-bounding-boxes/
// https://github.com/erich666/GraphicsGems/blob/master/gems/TransBox.c
transformMat4: ( function () {
var tmpMin = vec3.create();
var tmpMax = vec3.create();
return function ( out, m ) {
var inMin = this.getMin();
var inMax = this.getMax();
/* Take care of translation by beginning at T. */
mat4.getTranslation( tmpMin, m );
vec3.copy( tmpMax, tmpMin );
/* Now find the extreme points by considering the product of the */
/* min and max with each component of M. */
for ( var i = 0; i < 3; ++i ) {
var i4 = i * 4;
var mini = inMin[ i ];
var maxi = inMax[ i ];
for ( var j = 0; j < 3; ++j ) {
var cm = m[ i4 + j ];
var a = cm * maxi;
var b = cm * mini;
if ( a < b ) {
tmpMin[ j ] += a;
tmpMax[ j ] += b;
} else {
tmpMin[ j ] += b;
tmpMax[ j ] += a;
}
}
}
var outMax = out.getMax();
var outMin = out.getMin();
outMax[ 0 ] = tmpMax[ 0 ];
outMax[ 1 ] = tmpMax[ 1 ];
outMax[ 2 ] = tmpMax[ 2 ];
outMin[ 0 ] = tmpMin[ 0 ];
outMin[ 1 ] = tmpMin[ 1 ];
outMin[ 2 ] = tmpMin[ 2 ];
return out;
};
} )()
}, 'osg', 'BoundingBox' );
module.exports = BoundingBox;

Wyświetl plik

@ -1,195 +0,0 @@
'use strict';
var BoundingBox = require( 'osg/BoundingBox' );
var Notify = require( 'osg/notify' );
var vec3 = require( 'osg/glMatrix' ).vec3;
var mat4 = require( 'osg/glMatrix' ).mat4;
var BoundingSphere = function () {
this._center = vec3.create();
this._radius = -1.0;
};
BoundingSphere.prototype = {
init: function () {
vec3.init( this._center );
this._radius = -1.0;
},
valid: function () {
return this._radius >= 0.0;
},
set: function ( center, radius ) {
this._center = center;
this._radius = radius;
},
center: function () {
return this._center;
},
radius: function () {
return this._radius;
},
radius2: function () {
return this._radius * this._radius;
},
expandByBoundingBox: ( function () {
var v = vec3.create();
var newbb = new BoundingBox();
return function ( bb ) {
if ( !bb.valid() )
return;
if ( this.valid() ) {
vec3.copy( newbb._min, bb._min );
vec3.copy( newbb._max, bb._max );
for ( var i = 0; i < 8; i++ ) {
vec3.sub( v, bb.corner( i, v ), this._center ); // get the direction vector from corner
vec3.normalize( v, v ); // normalise it.
vec3.scaleAndAdd( v, this._center, v, -this._radius ); // move the vector in the opposite direction distance radius.
newbb.expandByvec3( v ); // add it into the new bounding box.
}
newbb.center( this._center );
this._radius = newbb.radius();
} else {
bb.center( this._center );
this._radius = bb.radius();
}
};
} )(),
expandByBox: function ( bb ) {
Notify.log( 'BoundingSphere.expandByBox is deprecated, use instead BoundingSphere.expandByBoundingBox' );
return this.expandByBoundingBox( bb );
},
expandByvec3: ( function () {
var dv = vec3.create();
return function ( v ) {
if ( this.valid() ) {
vec3.sub( dv, v, this.center( dv ) );
var r = vec3.length( dv );
if ( r > this.radius() ) {
var dr = ( r - this.radius() ) * 0.5;
this._center[ 0 ] += dv[ 0 ] * ( dr / r );
this._center[ 1 ] += dv[ 1 ] * ( dr / r );
this._center[ 2 ] += dv[ 2 ] * ( dr / r );
this._radius += dr;
}
} else {
this._center[ 0 ] = v[ 0 ];
this._center[ 1 ] = v[ 1 ];
this._center[ 2 ] = v[ 2 ];
this._radius = 0.0;
}
};
} )(),
expandRadiusBySphere: function ( sh ) {
if ( sh.valid() ) {
if ( this.valid() ) {
var r = vec3.distance( this._center, sh._center ) + sh._radius;
if ( r > this._radius ) {
this._radius = r;
}
// else do nothing as vertex is within sphere.
} else {
vec3.copy( this._center, sh._center );
this._radius = sh._radius;
}
}
},
expandBy: function ( bs ) {
Notify.log( 'BoundingSphere.expandBy is deprecated, use instead BoundingSphere.expandByBoundingSphere' );
this.expandByBoundingSphere( bs );
},
expandByBoundingSphere: function ( sh ) {
// ignore operation if incomming BoundingSphere is invalid.
if ( !sh.valid() ) {
return;
}
// This sphere is not set so use the inbound sphere
if ( !this.valid() ) {
this._center[ 0 ] = sh._center[ 0 ];
this._center[ 1 ] = sh._center[ 1 ];
this._center[ 2 ] = sh._center[ 2 ];
this._radius = sh.radius();
return;
}
// Calculate d == The distance between the sphere centers
var d = vec3.distance( sh.center(), this.center() );
// New sphere is already inside this one
if ( d + sh.radius() <= this.radius() ) {
return;
}
// New sphere completely contains this one
if ( d + this.radius() <= sh.radius() ) {
this._center[ 0 ] = sh._center[ 0 ];
this._center[ 1 ] = sh._center[ 1 ];
this._center[ 2 ] = sh._center[ 2 ];
this._radius = sh._radius;
return;
}
// Build a new sphere that completely contains the other two:
//
// The center point lies halfway along the line between the furthest
// points on the edges of the two spheres.
//
// Computing those two points is ugly - so we'll use similar triangles
var newRadius = ( this.radius() + d + sh.radius() ) * 0.5;
var ratio = ( newRadius - this.radius() ) / d;
this._center[ 0 ] += ( sh._center[ 0 ] - this._center[ 0 ] ) * ratio;
this._center[ 1 ] += ( sh._center[ 1 ] - this._center[ 1 ] ) * ratio;
this._center[ 2 ] += ( sh._center[ 2 ] - this._center[ 2 ] ) * ratio;
this._radius = newRadius;
},
contains: function ( v ) {
if ( !this.valid() )
return false;
return vec3.sqrDist( this.center(), v ) <= this.radius2();
},
intersects: function ( bs ) {
if ( !this.valid() || !bs.valid() )
return false;
var r = this.radius() + bs.radius();
return vec3.sqrDist( bs.center(), this.center() ) <= r * r;
},
transformMat4: ( function () {
var scaleVec = vec3.create();
return function ( out, matrix ) {
if ( !this.valid() ) return out;
if ( out._center !== this._center ) {
vec3.copy( out._center, this._center );
out._radius = this._radius;
}
var sphCenter = out._center;
var sphRadius = out._radius;
mat4.getSqrScale( scaleVec, matrix );
var scale = Math.sqrt( Math.max( Math.max( scaleVec[ 0 ], scaleVec[ 1 ] ), scaleVec[ 2 ] ) );
sphRadius = sphRadius * scale;
out._radius = sphRadius;
vec3.transformMat4( sphCenter, sphCenter, matrix );
return out;
};
} )()
};
module.exports = BoundingSphere;

Wyświetl plik

@ -1,179 +0,0 @@
'use strict';
var MACROUTILS = require( 'osg/Utils' );
var Notify = require( 'osg/notify' );
var Object = require( 'osg/Object' );
var GLObject = require( 'osg/GLObject' );
var Timer = require( 'osg/Timer' );
var getAttributeType = function ( array ) {
var type;
if ( array instanceof MACROUTILS.Float32Array ) type = 0x1406;
if ( array instanceof MACROUTILS.Uint32Array ) type = 0x1405;
if ( array instanceof MACROUTILS.Uint16Array ) type = 0x1403;
if ( array instanceof MACROUTILS.Uint8Array ) type = 0x1401;
return type;
};
/**
* BufferArray manage vertex / normal / ... array used by webgl.
* osgjs automatically converts array buffers to Float32Array and
* element array buffers to Uint16Array if not said explicitly with
* preserveArrayType variable in constructor.
* @class BufferArray
*/
var BufferArray = function ( target, elements, itemSize, preserveArrayType ) {
GLObject.call( this );
// maybe could inherit from Object
this._instanceID = Object.getInstanceID();
this.dirty();
this._itemSize = itemSize;
this._target = typeof target === 'string' ? BufferArray[ target ] : target;
// initialized by setElements
this._type = undefined;
this._normalize = false;
if ( elements !== undefined ) {
var typedArray = elements;
if ( !preserveArrayType ) {
if ( this._target === BufferArray.ELEMENT_ARRAY_BUFFER ) {
typedArray = elements instanceof MACROUTILS.Uint16Array ? elements : new MACROUTILS.Uint16Array( elements );
} else {
typedArray = elements instanceof MACROUTILS.Float32Array ? elements : new MACROUTILS.Float32Array( elements );
}
}
this.setElements( typedArray );
}
};
BufferArray.ELEMENT_ARRAY_BUFFER = 0x8893;
BufferArray.ARRAY_BUFFER = 0x8892;
// static cache of glBuffers flagged for deletion, which will actually
// be deleted in the correct GL context.
BufferArray._sDeletedGLBufferArrayCache = new window.Map();
// static method to delete Program
BufferArray.deleteGLBufferArray = function ( gl, buffer ) {
if ( !BufferArray._sDeletedGLBufferArrayCache.has( gl ) )
BufferArray._sDeletedGLBufferArrayCache.set( gl, [] );
BufferArray._sDeletedGLBufferArrayCache.get( gl ).push( buffer );
};
// static method to flush all the cached glPrograms which need to be deleted in the GL context specified
BufferArray.flushDeletedGLBufferArrays = function ( gl, availableTime ) {
// if no time available don't try to flush objects.
if ( availableTime <= 0.0 ) return availableTime;
if ( !BufferArray._sDeletedGLBufferArrayCache.has( gl ) ) return availableTime;
var elapsedTime = 0.0;
var beginTime = Timer.instance().tick();
var deleteList = BufferArray._sDeletedGLBufferArrayCache.get( gl );
var numBuffers = deleteList.length;
for ( var i = numBuffers - 1; i >= 0 && elapsedTime < availableTime; i-- ) {
gl.deleteBuffer( deleteList[ i ] );
deleteList.splice( i, 1 );
elapsedTime = Timer.instance().deltaS( beginTime, Timer.instance().tick() );
}
return availableTime - elapsedTime;
};
BufferArray.flushAllDeletedGLBufferArrays = function ( gl ) {
if ( !BufferArray._sDeletedGLBufferArrayCache.has( gl ) ) return;
var deleteList = BufferArray._sDeletedGLBufferArrayCache.get( gl );
var numBuffers = deleteList.length;
for ( var i = numBuffers - 1; i >= 0; i-- ) {
gl.deleteBuffer( deleteList[ i ] );
deleteList.splice( i, 1 );
}
};
/** @lends BufferArray.prototype */
BufferArray.prototype = MACROUTILS.objectInherit( GLObject.prototype, {
getInstanceID: function () {
return this._instanceID;
},
setItemSize: function ( size ) {
this._itemSize = size;
},
isValid: function () {
if ( this._buffer !== undefined ||
this._elements !== undefined ) {
return true;
}
return false;
},
releaseGLObjects: function () {
if ( this._buffer !== undefined && this._buffer !== null && this._gl !== undefined ) {
BufferArray.deleteGLBufferArray( this._gl, this._buffer );
}
this._buffer = undefined;
},
setNormalize: function ( normalize ) {
this._normalize = normalize;
},
getNormalize: function () {
return this._normalize;
},
bind: function ( gl ) {
if ( !this._gl ) this.setGraphicContext( gl );
var target = this._target;
var buffer = this._buffer;
if ( buffer ) {
gl.bindBuffer( target, buffer );
return;
}
if ( !buffer && this._elements.length > 0 ) {
this._buffer = gl.createBuffer();
this._numItems = this._elements.length / this._itemSize;
gl.bindBuffer( target, this._buffer );
}
},
getItemSize: function () {
return this._itemSize;
},
dirty: function () {
this._dirty = true;
},
isDirty: function () {
return this._dirty;
},
compile: function ( gl ) {
if ( this._dirty ) {
MACROUTILS.timeStamp( 'osgjs.metrics:bufferData' );
gl.bufferData( this._target, this._elements, gl.STATIC_DRAW );
this._dirty = false;
}
},
getElements: function () {
return this._elements;
},
setElements: function ( elements ) {
this._elements = elements;
this._type = getAttributeType( elements );
this._dirty = true;
},
getType: function () {
return this._type;
}
} );
BufferArray.create = function ( type, elements, itemSize ) {
Notify.log( 'BufferArray.create is deprecated, use new BufferArray with same arguments instead' );
return new BufferArray( type, elements, itemSize );
};
module.exports = BufferArray;

Wyświetl plik

@ -1,40 +0,0 @@
'use strict';
var BufferArray = require( 'osg/BufferArray' );
var BufferArrayProxy = function ( bufferArray ) {
this._initialBufferArray = undefined;
this._bufferArray = undefined;
if ( bufferArray ) {
this.setBufferArray( bufferArray );
this.setInitialBufferArray( bufferArray );
}
};
var prototype = {
setInitialBufferArray: function ( bufferArray ) {
this._initialBufferArray = bufferArray;
},
getInitialBufferArray: function () {
return this._initialBufferArray;
},
setBufferArray: function ( bufferArray ) {
this._bufferArray = bufferArray.getBufferArray ? bufferArray.getBufferArray() : bufferArray;
},
getBufferArray: function () {
return this._bufferArray;
}
};
// adds original method of BufferArray prototype for the proxy for convenient usage
var keys = window.Object.keys( BufferArray.prototype );
keys.forEach( function ( methodName ) {
prototype[ methodName ] = function () {
return BufferArray.prototype[ methodName ].apply( this._bufferArray, arguments );
};
} );
BufferArrayProxy.prototype = prototype;
module.exports = BufferArrayProxy;

Wyświetl plik

@ -1,252 +0,0 @@
'use strict';
var MACROUTILS = require( 'osg/Utils' );
var Transform = require( 'osg/Transform' );
var CullSettings = require( 'osg/CullSettings' );
var mat4 = require( 'osg/glMatrix' ).mat4;
var Texture = require( 'osg/Texture' );
var TransformEnums = require( 'osg/transformEnums' );
var vec4 = require( 'osg/glMatrix' ).vec4;
/**
* Camera - is a subclass of Transform which represents encapsulates the settings of a Camera.
* @class Camera
* @inherits Transform CullSettings
*/
var Camera = function () {
Transform.call( this );
CullSettings.call( this );
this.viewport = undefined;
this._graphicContext = undefined;
this.setClearColor( vec4.fromValues( 0, 0, 0, 1.0 ) );
this.setClearDepth( 1.0 );
/*jshint bitwise: false */
this.setClearMask( Camera.COLOR_BUFFER_BIT | Camera.DEPTH_BUFFER_BIT );
/*jshint bitwise: true */
this.setViewMatrix( mat4.create() );
this.setProjectionMatrix( mat4.create() );
this.renderOrder = Camera.NESTED_RENDER;
this.renderOrderNum = 0;
this._view = undefined;
this._renderer = undefined;
this._attachments = {};
};
Camera.PRE_RENDER = 0;
Camera.NESTED_RENDER = 1;
Camera.POST_RENDER = 2;
Camera.COLOR_BUFFER_BIT = 0x00004000;
Camera.DEPTH_BUFFER_BIT = 0x00000100;
Camera.STENCIL_BUFFER_BIT = 0x00000400;
/** @lends Camera.prototype */
Camera.prototype = MACROUTILS.objectLibraryClass( MACROUTILS.objectInherit(
CullSettings.prototype,
MACROUTILS.objectInherit( Transform.prototype, {
// at which view this camera is attached
getView: function () {
return this._view;
},
setView: function ( view ) {
this._view = view;
},
getRenderer: function () {
return this._renderer;
},
setRenderer: function ( renderer ) {
this._renderer = renderer;
},
// Set the final draw callback for custom operations
// to be done after the drawing of
// the camera's subgraph and pre render stages.
setFinalDrawCallback: function ( cb ) {
this._finalDrawCallback = cb;
},
getFinalDrawCallback: function () {
return this._finalDrawCallback;
},
// Set the initial draw callback for custom operations
// to be done before the drawing of
// the camera's subgraph and pre render stages.
setInitialDrawCallback: function ( cb ) {
this._initialDrawCallback = cb;
},
getInitialDrawCallback: function () {
return this._initialDrawCallback;
},
getAttachments: function () {
return this._attachments;
},
setGraphicContext: function ( gc ) {
this._graphicContext = gc;
},
getGraphicContext: function () {
return this._graphicContext;
},
setClearDepth: function ( depth ) {
this.clearDepth = depth;
},
getClearDepth: function () {
return this.clearDepth;
},
setClearMask: function ( mask ) {
this.clearMask = mask;
},
getClearMask: function () {
return this.clearMask;
},
setClearColor: function ( color ) {
this.clearColor = color;
},
getClearColor: function () {
return this.clearColor;
},
setViewport: function ( vp ) {
this.viewport = vp;
this.getOrCreateStateSet().setAttributeAndModes( vp );
},
getViewport: function () {
return this.viewport;
},
setViewMatrix: function ( matrix ) {
this.modelviewMatrix = matrix;
},
setViewMatrixAsLookAt: function ( eye, center, up ) {
mat4.lookAt( this.getViewMatrix(), eye, center, up );
},
setProjectionMatrix: function ( matrix ) {
this.projectionMatrix = matrix;
},
/** Set to an orthographic projection. See OpenGL glOrtho for documentation further details.*/
setProjectionMatrixAsOrtho: function ( left, right,
bottom, top,
zNear, zFar ) {
mat4.ortho( this.getProjectionMatrix(), left, right, bottom, top, zNear, zFar );
},
isRenderToTextureCamera: function () {
return window.Object.keys( this._attachments ).length > 0;
},
getViewMatrix: function () {
return this.modelviewMatrix;
},
getProjectionMatrix: function () {
return this.projectionMatrix;
},
getRenderOrder: function () {
return this.renderOrder;
},
setRenderOrder: function ( order, orderNum ) {
this.renderOrder = order;
this.renderOrderNum = orderNum;
},
detachAll: function () {
this._attachments = {};
if ( this.frameBufferObject ) {
this.frameBufferObject.dirty();
}
},
// TODO: fix in case of shared fbo
// TODO: fix adding a resize case
resetAttachments: function () {
if ( this.frameBufferObject ) {
this.frameBufferObject.reset();
// remove framebuffer
this.frameBufferObject = 0;
}
// removes camera attachement
this._attachments = {};
},
attachTexture: function ( bufferComponent, texture, textureTarget ) {
if ( this.frameBufferObject ) {
this.frameBufferObject.dirty();
}
// because before the argument was level and the spec says
// it must always be 0 ! is valid for 0 or undefined
if ( !textureTarget ) {
textureTarget = Texture.TEXTURE_2D;
}
this._attachments[ bufferComponent ] = {
'attachment': bufferComponent,
'texture': texture,
'textureTarget': textureTarget
};
},
attachRenderBuffer: function ( bufferComponent, internalFormat ) {
if ( this.frameBufferObject ) {
this.frameBufferObject.dirty();
}
this._attachments[ bufferComponent ] = {
'format': internalFormat,
'attachment': bufferComponent
};
},
computeLocalToWorldMatrix: function ( matrix /*,nodeVisitor*/ ) {
if ( this.referenceFrame === TransformEnums.RELATIVE_RF ) {
mat4.mul( matrix, matrix, this.modelviewMatrix );
} else { // absolute
mat4.copy( matrix, this.modelviewMatrix );
}
return true;
},
computeWorldToLocalMatrix: ( function () {
var minverse = mat4.create();
return function ( matrix /*, nodeVisitor */ ) {
mat4.invert( minverse, this.modelviewMatrix );
if ( this.referenceFrame === TransformEnums.RELATIVE_RF ) {
mat4.mul( matrix, minverse, matrix );
} else {
mat4.copy( matrix, minverse );
}
return true;
};
} )()
} ) ), 'osg', 'Camera' );
MACROUTILS.setTypeID( Camera );
module.exports = Camera;

Wyświetl plik

@ -1,44 +0,0 @@
'use strict';
var MACROUTILS = require( 'osg/Utils' );
var StateAttribute = require( 'osg/StateAttribute' );
var ColorMask = function ( red, green, blue, alpha ) {
StateAttribute.call( this );
this._colorMask = [ true, true, true, true ];
this.setMask( red, green, blue, alpha );
};
ColorMask.prototype = MACROUTILS.objectLibraryClass( MACROUTILS.objectInherit( StateAttribute.prototype, {
attributeType: 'ColorMask',
cloneType: function () {
return new ColorMask();
},
setMask: function ( red, green, blue, alpha ) {
if ( red !== undefined &&
green !== undefined &&
blue !== undefined &&
alpha !== undefined ) {
this._colorMask[ 0 ] = red;
this._colorMask[ 1 ] = green;
this._colorMask[ 2 ] = blue;
this._colorMask[ 3 ] = alpha;
}
},
apply: function ( state ) {
var gl = state.getGraphicContext();
var colorMask = this._colorMask;
gl.colorMask( colorMask[ 0 ], colorMask[ 1 ], colorMask[ 2 ], colorMask[ 3 ] );
}
} ), 'osg', 'ColorMask' );
module.exports = ColorMask;

Wyświetl plik

@ -1,109 +0,0 @@
'use strict';
var BoundingBox = require( 'osg/BoundingBox' );
var Geometry = require( 'osg/Geometry' );
var mat4 = require( 'osg/glMatrix' ).mat4;
var MatrixMemoryPool = require( 'osg/MatrixMemoryPool' );
var Transform = require( 'osg/Transform' );
var NodeVisitor = require( 'osg/NodeVisitor' );
var MACROUTILS = require( 'osg/Utils' );
var ComputeBoundsVisitor = function ( traversalMode ) {
NodeVisitor.call( this, traversalMode );
// keep a matrix in memory to avoid to create matrix
this._reservedMatrixStack = new MatrixMemoryPool();
// Matrix stack along path traversal
this._matrixStack = [];
this._bb = new BoundingBox();
};
ComputeBoundsVisitor.prototype = MACROUTILS.objectLibraryClass( MACROUTILS.objectInherit( NodeVisitor.prototype, {
reset: function () {
this._reservedMatrixStack.reset();
this._matrixStack.length = 0;
this._bb.init();
},
getBoundingBox: function () {
return this._bb;
},
// not implemented
//void getPolytope(osg::Polytope& polytope, float margin=0.1) const;
//void getBase(osg::Polytope& polytope, float margin=0.1) const;
//applyDrawable: function ( drawable ) {},
applyTransform: function ( transform ) {
var matrix = this._reservedMatrixStack.get();
var stackLength = this._matrixStack.length;
if ( stackLength )
mat4.copy( matrix, this._matrixStack[ stackLength - 1 ] );
else
mat4.identity( matrix );
transform.computeLocalToWorldMatrix( matrix, this );
this.pushMatrix( matrix );
this.traverse( transform );
this.popMatrix();
},
apply: function ( node ) {
if ( node instanceof Transform ) {
this.applyTransform( node );
return;
} else if ( node instanceof Geometry ) {
this.applyBoundingBox( node.getBoundingBox() );
return;
}
this.traverse( node );
},
pushMatrix: function ( matrix ) {
this._matrixStack.push( matrix );
},
popMatrix: function () {
this._matrixStack.pop();
},
applyBoundingBox: ( function () {
var bbOut = new BoundingBox();
return function ( bbox ) {
var stackLength = this._matrixStack.length;
if ( !stackLength )
this._bb.expandByBoundingBox( bbox );
else if ( bbox.valid() ) {
var matrix = this._matrixStack[ stackLength - 1 ];
//Matrix.transformBoundingBox( matrix, bbox, bbOut );
bbox.transformMat4( bbOut, matrix );
this._bb.expandByBoundingBox( bbOut );
}
};
} )(),
getMatrixStack: function () {
return this._matrixStack;
}
} ), 'osg', 'ComputeBoundsVisitor' );
module.exports = ComputeBoundsVisitor;

Wyświetl plik

@ -1,51 +0,0 @@
'use strict';
var MACROUTILS = require( 'osg/Utils' );
var StateAttribute = require( 'osg/StateAttribute' );
/**
* Manage CullFace attribute
* @class CullFace
*/
var CullFace = function ( mode ) {
StateAttribute.call( this );
this.setMode( mode !== undefined ? mode : CullFace.BACK );
};
CullFace.DISABLE = 0x0;
CullFace.FRONT = 0x0404;
CullFace.BACK = 0x0405;
CullFace.FRONT_AND_BACK = 0x0408;
/** @lends CullFace.prototype */
CullFace.prototype = MACROUTILS.objectLibraryClass( MACROUTILS.objectInherit( StateAttribute.prototype, {
attributeType: 'CullFace',
cloneType: function () {
return new CullFace();
},
setMode: function ( mode ) {
var value = mode;
if ( typeof value === 'string' ) value = CullFace[ value ];
this._mode = value;
},
getMode: function () {
return this._mode;
},
apply: function ( state ) {
var gl = state.getGraphicContext();
if ( this._mode === CullFace.DISABLE ) {
gl.disable( gl.CULL_FACE );
} else {
gl.enable( gl.CULL_FACE );
gl.cullFace( this._mode );
}
}
} ), 'osg', 'CullFace' );
module.exports = CullFace;

Wyświetl plik

@ -1,95 +0,0 @@
'use strict';
var CullSettings = function () {
// Not doing a this.reset()
// because of multiple inheritance
// it will call the wrong reset
// cullstack reset for isntance()
CullSettings.prototype.reset.call( this );
};
CullSettings.prototype = {
reset: function () {
this._computeNearFar = true;
this._nearFarRatio = 0.005;
// Magic numbers 3 & 4
this.bbCornerFar = 3;
this.bbCornerNear = 4;
// see code below for for the
// Code simplification origin
// var vec3 = require( 'osg/glMatrix' ).vec3;
// var lookVector = vec3.fromValues( 0.0, 0.0, -1.0 );
// /*jshint bitwise: false */
// this.bbCornerFar = ( lookVector[ 0 ] >= 0 ? 1 : 0 ) | ( lookVector[ 1 ] >= 0 ? 2 : 0 ) | ( lookVector[ 2 ] >= 0 ? 4 : 0 );
// this.bbCornerNear = ( ~this.bbCornerFar ) & 7;
// /*jshint bitwise: true */
// is equivalent to
this._enableFrustumCulling = false;
// who sets the parameter
// if it's cullvisitor
// it's an OVERRIDER for enableFrustumCulling
// allowing for global EnableFrustimCulling
this._settingsSourceOverrider = this;
//LOD bias for the CullVisitor to use
this._LODScale = 1.0;
// Custom clampProjectionMatrix
this._clampProjectionMatrixCallback = undefined;
},
setCullSettings: function ( settings ) {
this._computeNearFar = settings._computeNearFar;
this._nearFarRatio = settings._nearFarRatio;
this._enableFrustumCulling = settings._enableFrustumCulling;
this._settingsSourceOverrider = settings._settingsSourceOverrider;
this._clampProjectionMatrixCallback = settings._clampProjectionMatrixCallback;
},
setNearFarRatio: function ( ratio ) {
this._nearFarRatio = ratio;
},
getNearFarRatio: function () {
return this._nearFarRatio;
},
setComputeNearFar: function ( value ) {
this._computeNearFar = value;
},
getComputeNearFar: function () {
return this._computeNearFar;
},
setEnableFrustumCulling: function ( value ) {
this._enableFrustumCulling = value;
},
getEnableFrustumCulling: function () {
return this._enableFrustumCulling;
},
getSettingSourceOverrider: function () {
return this._settingsSourceOverrider;
},
setClampProjectionMatrixCallback: function ( callback ) {
this._clampProjectionMatrixCallback = callback;
},
getClampProjectionMatrixCallback: function () {
return this._clampProjectionMatrixCallback;
},
setLODScale: function ( scale ) {
this._LODScale = scale;
},
getLODScale: function () {
return this._LODScale;
}
};
module.exports = CullSettings;

Wyświetl plik

@ -1,394 +0,0 @@
'use strict';
var MACROUTILS = require( 'osg/Utils' );
var BoundingSphere = require( 'osg/BoundingSphere' );
var Camera = require( 'osg/Camera' );
var ComputeMatrixFromNodePath = require( 'osg/computeMatrixFromNodePath' );
var CullSettings = require( 'osg/CullSettings' );
var CullingSet = require( 'osg/CullingSet' );
var mat4 = require( 'osg/glMatrix' ).mat4;
var Plane = require( 'osg/Plane' );
var MatrixMemoryPool = require( 'osg/MatrixMemoryPool' );
var Transform = require( 'osg/Transform' );
var Notify = require( 'osg/notify' );
var TransformEnums = require( 'osg/transformEnums' );
var vec3 = require( 'osg/glMatrix' ).vec3;
var CullStack = function () {
this._modelViewMatrixStack = [];
this._projectionMatrixStack = [];
this._viewportStack = [];
this._cullingSetStack = [];
this._frustumVolume = -1.0;
this._bbCornerFar = 0;
this._bbCornerNear = 0;
// keep a matrix in memory to avoid to create matrix
this._reservedMatrixStack = new MatrixMemoryPool();
this._reserveCullingSetStack = [
new CullingSet()
];
this._reserveCullingSetStack.current = 0;
// data for caching camera matrix inverse for computation of world/view
// contains index of the camera node in the nodepath
this._cameraIndexStack = [];
// contains index of the camera modelview matrix in the modelViewMatrixStack
this._cameraModelViewIndexStack = [];
// contains the id has a key to computed Inverse Matrix
this._cameraMatrixInverse = [];
this._cameraMatrixInverseRoot = undefined;
};
CullStack.prototype = MACROUTILS.objectInherit( CullSettings.prototype, {
_getReservedCullingSet: function () {
var m = this._reserveCullingSetStack[ this._reserveCullingSetStack.current++ ];
if ( this._reserveCullingSetStack.current === this._reserveCullingSetStack.length ) {
this._reserveCullingSetStack.push( new CullingSet() );
}
return m;
},
reset: function () {
this._modelViewMatrixStack.length = 0;
this._projectionMatrixStack.length = 0;
this._cullingSetStack.length = 0;
this._reservedMatrixStack.reset();
this._reserveCullingSetStack.current = 0;
this._cameraModelViewIndexStack.length = 0;
this._cameraIndexStack.length = 0;
this._cameraMatrixInverse.length = 0;
this._cameraMatrixInverseRoot = undefined;
},
getProjectionMatrixStack: function () {
return this._projectionMatrixStack;
},
getCurrentProjectionMatrix: function () {
return this._projectionMatrixStack[ this._projectionMatrixStack.length - 1 ];
},
getCurrentModelViewMatrix: function () {
return this._modelViewMatrixStack[ this._modelViewMatrixStack.length - 1 ];
},
getCurrentModelviewMatrix: function () {
Notify.warn( 'deprecated switch to getCurrentModelViewMatrix' );
return this.getCurrentModelViewMatrix();
},
getCameraInverseMatrix: function () {
// Return or compute and cache the MatrixInverse of the last
// active camera in absolute reference
// if no index the camera inverse is the root with an fake id
if ( !this._cameraIndexStack.length )
return this._cameraMatrixInverseRoot;
var idx = this._cameraIndexStack[ this._cameraIndexStack.length - 1 ];
// get the camera node
var camera = this.getNodePath()[ idx ];
var id = camera.getInstanceID();
if ( this._cameraMatrixInverse[ id ] === undefined ) {
var indexInModelViewMatrixStack = this._cameraModelViewIndexStack[ this._cameraModelViewIndexStack.length - 1 ];
var mat = this._modelViewMatrixStack[ indexInModelViewMatrixStack ];
var matInverse = this._reservedMatrixStack.get();
mat4.invert( matInverse, mat );
this._cameraMatrixInverse[ id ] = matInverse;
}
return this._cameraMatrixInverse[ id ];
},
getCurrentModelMatrix: function () {
// Improvment could be to cache more things
// and / or use this method only if the shader use it
var invMatrix = this.getCameraInverseMatrix();
var m = this._reservedMatrixStack.get();
var world = mat4.mul( m, invMatrix, this.getCurrentModelViewMatrix() );
return world;
},
getCurrentViewMatrix: function () {
// Improvment could be to cache more things
// and / or use this method only if the shader use it
if ( !this._cameraIndexStack.length )
return this._modelViewMatrixStack[ 0 ];
// also we could keep the index of the current to avoid lenght-1 at each access
// it's implemented in osg like that:
// https://github.com/openscenegraph/osg/blob/master/include/osg/fast_back_stack
var idx = this._cameraModelViewIndexStack[ this._cameraModelViewIndexStack.length - 1 ];
return this._modelViewMatrixStack[ idx ];
},
getViewport: function () {
if ( this._viewportStack.length === 0 ) {
return undefined;
}
return this._viewportStack[ this._viewportStack.length - 1 ];
},
getLookVectorLocal: function ( outLookVector ) {
var lookVectorLocal = this.getCurrentModelViewMatrix();
return vec3.set( outLookVector, -lookVectorLocal[ 2 ], -lookVectorLocal[ 6 ], -lookVectorLocal[ 10 ] );
},
pushViewport: function ( vp ) {
this._viewportStack.push( vp );
},
popViewport: function () {
this._viewportStack.pop();
},
getFrustumPlanes: ( function () {
var mvp = mat4.create();
return function ( out, projection, view, withNearFar ) {
mat4.mul( mvp, projection, view );
var computeNearFar = !!withNearFar;
// Right clipping plane.
var right = out[ 0 ];
right[ 0 ] = mvp[ 3 ] - mvp[ 0 ];
right[ 1 ] = mvp[ 7 ] - mvp[ 4 ];
right[ 2 ] = mvp[ 11 ] - mvp[ 8 ];
right[ 3 ] = mvp[ 15 ] - mvp[ 12 ];
// Left clipping plane.
var left = out[ 1 ];
left[ 0 ] = mvp[ 3 ] + mvp[ 0 ];
left[ 1 ] = mvp[ 7 ] + mvp[ 4 ];
left[ 2 ] = mvp[ 11 ] + mvp[ 8 ];
left[ 3 ] = mvp[ 15 ] + mvp[ 12 ];
// Bottom clipping plane.
var bottom = out[ 2 ];
bottom[ 0 ] = mvp[ 3 ] + mvp[ 1 ];
bottom[ 1 ] = mvp[ 7 ] + mvp[ 5 ];
bottom[ 2 ] = mvp[ 11 ] + mvp[ 9 ];
bottom[ 3 ] = mvp[ 15 ] + mvp[ 13 ];
// Top clipping plane.
var top = out[ 3 ];
top[ 0 ] = mvp[ 3 ] - mvp[ 1 ];
top[ 1 ] = mvp[ 7 ] - mvp[ 5 ];
top[ 2 ] = mvp[ 11 ] - mvp[ 9 ];
top[ 3 ] = mvp[ 15 ] - mvp[ 13 ];
if ( computeNearFar ) {
// Far clipping plane.
var far = out[ 4 ];
far[ 0 ] = mvp[ 3 ] - mvp[ 2 ];
far[ 1 ] = mvp[ 7 ] - mvp[ 6 ];
far[ 2 ] = mvp[ 11 ] - mvp[ 10 ];
far[ 3 ] = mvp[ 15 ] - mvp[ 14 ];
// Near clipping plane.
var near = out[ 5 ];
near[ 0 ] = mvp[ 3 ] + mvp[ 2 ];
near[ 1 ] = mvp[ 7 ] + mvp[ 6 ];
near[ 2 ] = mvp[ 11 ] + mvp[ 10 ];
near[ 3 ] = mvp[ 15 ] + mvp[ 14 ];
}
//Normalize the planes
var j = withNearFar ? 6 : 4;
for ( var i = 0; i < j; i++ ) {
Plane.normalizeEquation( out[ i ] );
}
};
} )(),
pushCullingSet: function () {
var cs = this._getReservedCullingSet();
if ( this._enableFrustumCulling ) {
mat4.getFrustumPlanes( cs.getFrustum().getPlanes(), this.getCurrentProjectionMatrix(), this.getCurrentModelViewMatrix(), false );
// TODO: no far no near.
// should check if we have them
// should add at least a near 0 clip if not
cs.getFrustum().setupMask( 4 );
}
this._cullingSetStack.push( cs );
},
popCullingSet: function () {
return this._cullingSetStack.pop();
},
getCurrentCullingSet: function () {
return this._cullingSetStack[ this._cullingSetStack.length - 1 ];
},
pushCurrentMask: function () {
var cs = this.getCurrentCullingSet();
if ( cs ) cs.pushCurrentMask();
},
popCurrentMask: function () {
var cs = this.getCurrentCullingSet();
if ( cs ) cs.popCurrentMask();
},
isVerticesCulled: function ( vertices ) {
if ( !this._enableFrustumCulling )
return false;
return this.getCurrentCullingSet().isVerticesCulled( vertices );
},
isBoundingBoxCulled: function ( bb ) {
if ( !this._enableFrustumCulling )
return false;
return bb.valid() && this.getCurrentCullingSet().isBoundingBoxCulled( bb );
},
isBoundingSphereCulled: function ( bs ) {
if ( !this._enableFrustumCulling )
return false;
return bs.valid() && this.getCurrentCullingSet().isBoundingSphereCulled( bs );
},
isCulled: ( function () {
var bsWorld = new BoundingSphere();
return function ( node, nodePath ) {
if ( !this._enableFrustumCulling )
return false;
if ( node.isCullingActive() ) {
if ( this.getCurrentCullingSet().getCurrentResultMask() === 0 )
return false; // father bounding sphere totally inside
var matrix = this._reservedMatrixStack.get();
mat4.identity( matrix );
// TODO: Perf just get World Matrix at each node transform
// store it in a World Transform Node Path (only world matrix change)
// so that it's computed once and reused for each further node getCurrentModel
// otherwise, it's 1 mult for each node, each matrix node, and each geometry
//matrix = this.getCurrentModelMatrix();
// tricky: change push be before isculled, and pop in case of culling
// strange bug for now on frustum culling sample with that
if ( node instanceof Transform ) {
// tricky: MatrixTransform getBound is already transformed to
// its local space whereas nodepath also have its matrix ...
// so to get world space, you HAVE to remove that matrix from nodePATH
// TODO: GC Perf of array slice creating new array
matrix = ComputeMatrixFromNodePath.computeLocalToWorld( nodePath.slice( 0, nodePath.length - 1 ), true, matrix );
} else {
matrix = ComputeMatrixFromNodePath.computeLocalToWorld( nodePath, true, matrix );
}
// Matrix.transformBoundingSphere( matrix, node.getBound(), bsWorld );
node.getBound().transformMat4( bsWorld, matrix );
return this.getCurrentCullingSet().isBoundingSphereCulled( bsWorld );
} else {
this.getCurrentCullingSet().resetCullingMask();
return false;
}
};
} )(),
pushModelViewMatrix: ( function () {
var lookVector = vec3.create();
return function ( matrix ) {
// When pushing a matrix, it can be a transform or camera. To compute
// differents matrix type in shader ( ViewMatrix/ModelMatrix/ModelViewMatrix )
// we track camera node when using pushModelViewMatrix
// To detect a camera, we check on the nodepath the type of the node and if the
// camera is relatif or absolute.
// When we detect an absolute camera we keep it's index to get it when needed to
// compute the World/View matrix
// Th ere is an exception for the root camera, the root camera is not pushed on the
// CullVisitor but only its matrixes, so to handle this we compute the inverse camera
// when the nodepath has a lenght of 0
// To avoid to compute too much inverse matrix, we keep a cache of them during the
// traverse and store the result under the instanceID key, except for the root
var np = this.getNodePath();
var length = np.length;
if ( !length ) { // root
var matInverse = this._reservedMatrixStack.get();
mat4.invert( matInverse, matrix );
this._cameraMatrixInverseRoot = matInverse;
} else {
var index = length - 1;
if ( np[ index ].getTypeID() === Camera.getTypeID() && np[ index ].getReferenceFrame() === TransformEnums.ABSOLUTE_RF ) {
this._cameraIndexStack.push( index );
this._cameraModelViewIndexStack.push( this._modelViewMatrixStack.length );
}
}
this._modelViewMatrixStack.push( matrix );
this.getLookVectorLocal( lookVector );
/*jshint bitwise: false */
this._bbCornerFar = ( lookVector[ 0 ] >= 0 ? 1 : 0 ) | ( lookVector[ 1 ] >= 0 ? 2 : 0 ) | ( lookVector[ 2 ] >= 0 ? 4 : 0 );
this._bbCornerNear = ( ~this._bbCornerFar ) & 7;
/*jshint bitwise: true */
};
} )(),
popModelViewMatrix: ( function () {
var lookVector = vec3.create();
return function () {
// if same index it's a camera and we have to pop it
var np = this.getNodePath();
var index = np.length - 1;
if ( this._cameraIndexStack.length && index === this._cameraIndexStack[ this._cameraIndexStack.length - 1 ] ) {
this._cameraIndexStack.pop();
this._cameraModelViewIndexStack.pop();
}
this._modelViewMatrixStack.pop();
if ( this._modelViewMatrixStack.length !== 0 ) {
this.getLookVectorLocal( lookVector );
} else {
vec3.set( lookVector, 0.0, 0.0, -1.0 );
}
/*jshint bitwise: false */
this._bbCornerFar = ( lookVector[ 0 ] >= 0.0 ? 1.0 : 0.0 ) | ( lookVector[ 1 ] >= 0 ? 2.0 : 0.0 ) | ( lookVector[ 2 ] >= 0 ? 4.0 : 0.0 );
this._bbCornerNear = ( ~this._bbCornerFar ) & 7;
/*jshint bitwise: true */
};
} )(),
pushProjectionMatrix: function ( matrix ) {
this._projectionMatrixStack.push( matrix );
// need to recompute frustum volume.
this._frustumVolume = -1.0;
this.pushCullingSet();
},
popProjectionMatrix: function () {
this._projectionMatrixStack.pop();
// need to recompute frustum volume.
this._frustumVolume = -1.0;
this.popCullingSet();
}
} );
module.exports = CullStack;

Wyświetl plik

@ -1,761 +0,0 @@
'use strict';
var Notify = require( 'osg/notify' );
var MACROUTILS = require( 'osg/Utils' );
var osgMath = require( 'osg/math' );
var NodeVisitor = require( 'osg/NodeVisitor' );
var CullSettings = require( 'osg/CullSettings' );
var CullStack = require( 'osg/CullStack' );
var mat4 = require( 'osg/glMatrix' ).mat4;
var MatrixTransform = require( 'osg/MatrixTransform' );
var AutoTransform = require( 'osg/AutoTransform' );
var Projection = require( 'osg/Projection' );
var LightSource = require( 'osg/LightSource' );
var osgPool = require( 'osgUtil/osgPool' );
var Geometry = require( 'osg/Geometry' );
var RenderLeaf = require( 'osg/RenderLeaf' );
var RenderBin = require( 'osg/RenderBin' );
var RenderStage = require( 'osg/RenderStage' );
var Node = require( 'osg/Node' );
var Lod = require( 'osg/Lod' );
var PagedLOD = require( 'osg/PagedLOD' );
var Camera = require( 'osg/Camera' );
var TransformEnums = require( 'osg/transformEnums' );
var vec3 = require( 'osg/glMatrix' ).vec3;
var Skeleton = require( 'osgAnimation/Skeleton' );
var RigGeometry = require( 'osgAnimation/RigGeometry' );
var Bone = require( 'osgAnimation/Bone' );
var MorphGeometry = require( 'osgAnimation/MorphGeometry' );
/**
* CullVisitor traverse the tree and collect Matrix/State for the rendering traverse
* @class CullVisitor
*/
var CullVisitor = function () {
NodeVisitor.call( this, NodeVisitor.TRAVERSE_ACTIVE_CHILDREN );
CullSettings.call( this );
CullStack.call( this );
this._rootStateGraph = undefined;
this._currentStateGraph = undefined;
this._currentRenderBin = undefined;
this._currentRenderStage = undefined;
this._rootRenderStage = undefined;
this._computedNear = Number.POSITIVE_INFINITY;
this._computedFar = Number.NEGATIVE_INFINITY;
var lookVector = vec3.fromValues( 0.0, 0.0, -1.0 );
this._camera = undefined;
/*jshint bitwise: false */
this._bbCornerFar = ( lookVector[ 0 ] >= 0 ? 1 : 0 ) | ( lookVector[ 1 ] >= 0 ? 2 : 0 ) | ( lookVector[ 2 ] >= 0 ? 4 : 0 );
this._bbCornerNear = ( ~this._bbCornerFar ) & 7;
/*jshint bitwise: true */
this._reserveLeafStack = [ new RenderLeaf() ];
this._reserveLeafStackCurrent = 0;
this._reserveRenderStageStacks = {};
this._reserveCullSettingsStack = [ new CullSettings() ];
this._reserveCullSettingsStackCurrent = 0;
this._renderBinStack = [];
this.visitorType = NodeVisitor.CULL_VISITOR;
this._identityMatrix = mat4.create();
this._renderer = undefined;
this._renderStageType = RenderStage;
this._numCamera = 0;
this._numMatrixTransform = 0;
this._numProjection = 0;
this._numNode = 0;
this._numLightSource = 0;
this._numGeometry = 0;
};
/** @lends CullVisitor.prototype */
CullVisitor.prototype = MACROUTILS.objectInherit( CullStack.prototype, MACROUTILS.objectInherit( NodeVisitor.prototype, {
distance: function ( coord, matrix ) {
return -( coord[ 0 ] * matrix[ 2 ] + coord[ 1 ] * matrix[ 6 ] + coord[ 2 ] * matrix[ 10 ] + matrix[ 14 ] );
},
getComputedNear: function () {
return this._computedNear;
},
getComputedFar: function () {
return this._computedFar;
},
resetStats: function () {
this._numCamera = 0;
this._numMatrixTransform = 0;
this._numProjection = 0;
this._numNode = 0;
this._numLightSource = 0;
this._numGeometry = 0;
},
handleCullCallbacksAndTraverse: function ( node ) {
var ccb = node.getCullCallback();
if ( ccb && !ccb.cull( node, this ) )
return;
this.traverse( node );
},
getCurrentCamera: function () {
return this._currentRenderBin.getStage().getCamera();
},
updateCalculatedNearFar: ( function () {
var nearVec = vec3.create();
var farVec = vec3.create();
return function ( matrix, drawable ) {
var bb = drawable.getBoundingBox();
var dNear, dFar;
// efficient computation of near and far, only taking into account the nearest and furthest
// corners of the bounding box.
dNear = this.distance( bb.corner( this._bbCornerNear, nearVec ), matrix );
dFar = this.distance( bb.corner( this._bbCornerFar, farVec ), matrix );
if ( dNear > dFar ) {
var tmp = dNear;
dNear = dFar;
dFar = tmp;
}
if ( dFar < 0.0 ) {
// whole object behind the eye point so discard
return false;
}
if ( dNear < this._computedNear ) {
this._computedNear = dNear;
}
if ( dFar > this._computedFar ) {
this._computedFar = dFar;
}
return true;
};
} )(),
setStateGraph: function ( sg ) {
this._rootStateGraph = sg;
this._currentStateGraph = sg;
},
setRenderStage: function ( rg ) {
this._rootRenderStage = rg;
this._currentRenderBin = rg;
},
setRenderer: function ( renderer ) {
this._renderer = renderer;
},
getRenderer: function () {
return this._renderer;
},
reset: function () {
CullStack.prototype.reset.call( this );
// Reset the stack before reseting the current leaf index.
// Reseting elements and refilling them later is faster than create new elements
// That's the reason to have a leafStack, see http://jsperf.com/refill/2
this.resetRenderLeafStack();
this._reserveLeafStackCurrent = 0;
this.resetCullSettingsStack();
this._reserveCullSettingsStackCurrent = 0;
// renderstage / renderbin pools
var resetStages = window.Object.keys( this._reserveRenderStageStacks );
for ( var i = 0, l = resetStages.length; i < l; i++ ) {
var key = resetStages[ i ];
this._reserveRenderStageStacks[ key ].reset();
}
RenderBin.resetStack();
this._computedNear = Number.POSITIVE_INFINITY;
this._computedFar = Number.NEGATIVE_INFINITY;
},
getCurrentRenderBin: function () {
return this._currentRenderBin;
},
setCurrentRenderBin: function ( rb ) {
this._currentRenderBin = rb;
},
// mimic the osg implementation
// in osg you can push 0, in this case an identity matrix will be loaded
addPositionedAttribute: function ( matrix, attribute ) {
var m = matrix ? matrix : this._identityMatrix;
this._currentRenderBin.getStage().positionedAttribute.push( [ m, attribute ] );
},
pushStateSet: function ( stateset ) {
this._currentStateGraph = this._currentStateGraph.findOrInsert( stateset );
if ( stateset.getBinName() !== undefined ) {
var renderBinStack = this._renderBinStack;
var currentRenderBin = this._currentRenderBin;
renderBinStack.push( currentRenderBin );
this._currentRenderBin = currentRenderBin.getStage().findOrInsert( stateset.getBinNumber(), stateset.getBinName() );
}
},
/** Pop the top state set and hence associated state group.
* Move the current state group to the parent of the popped
* state group.
*/
popStateSet: function () {
var currentStateGraph = this._currentStateGraph;
var stateset = currentStateGraph.getStateSet();
this._currentStateGraph = currentStateGraph.parent;
if ( stateset.getBinName() !== undefined ) {
var renderBinStack = this._renderBinStack;
if ( renderBinStack.length === 0 ) {
this._currentRenderBin = this._currentRenderBin.getStage();
} else {
this._currentRenderBin = renderBinStack.pop();
}
}
},
popProjectionMatrix: function () {
if ( this._computeNearFar === true && this._computedFar >= this._computedNear ) {
var m = this.getCurrentProjectionMatrix();
if ( this._clampProjectionMatrixCallback !== undefined ) {
this._clampProjectionMatrixCallback( m, this._computedNear, this._computedFar, this._nearFarRatio );
} else {
this.clampProjectionMatrix( m, this._computedNear, this._computedFar, this._nearFarRatio );
}
}
CullStack.prototype.popProjectionMatrix.call( this );
},
clampProjectionMatrix: function ( projection, znear, zfar, nearFarRatio, resultNearFar ) {
var epsilon = 1e-6;
if ( zfar < znear - epsilon ) {
Notify.log( 'clampProjectionMatrix not applied, invalid depth range, znear = ' + znear + ' zfar = ' + zfar, false, true );
return false;
}
var desiredZnear, desiredZfar;
if ( zfar < znear + epsilon ) {
// znear and zfar are too close together and could cause divide by zero problems
// late on in the clamping code, so move the znear and zfar apart.
var average = ( znear + zfar ) * 0.5;
znear = average - epsilon;
zfar = average + epsilon;
// OSG_INFO << '_clampProjectionMatrix widening znear and zfar to '<<znear<<' '<<zfar<<std::endl;
}
if ( Math.abs( projection[ 3 ] ) < epsilon &&
Math.abs( projection[ 7 ] ) < epsilon &&
Math.abs( projection[ 11 ] ) < epsilon ) {
// OSG_INFO << 'Orthographic matrix before clamping'<<projection<<std::endl;
var deltaSpan = ( zfar - znear ) * 0.02;
if ( deltaSpan < 1.0 ) {
deltaSpan = 1.0;
}
desiredZnear = znear - deltaSpan;
desiredZfar = zfar + deltaSpan;
// assign the clamped values back to the computed values.
znear = desiredZnear;
zfar = desiredZfar;
projection[ 10 ] = -2.0 / ( desiredZfar - desiredZnear );
projection[ 14 ] = -( desiredZfar + desiredZnear ) / ( desiredZfar - desiredZnear );
// OSG_INFO << 'Orthographic matrix after clamping '<<projection<<std::endl;
} else {
// OSG_INFO << 'Persepective matrix before clamping'<<projection<<std::endl;
//std::cout << '_computed_znear'<<_computed_znear<<std::endl;
//std::cout << '_computed_zfar'<<_computed_zfar<<std::endl;
var zfarPushRatio = 1.02;
var znearPullRatio = 0.98;
//znearPullRatio = 0.99;
desiredZnear = znear * znearPullRatio;
desiredZfar = zfar * zfarPushRatio;
// near plane clamping.
var minNearPlane = zfar * nearFarRatio;
if ( desiredZnear < minNearPlane ) {
desiredZnear = minNearPlane;
}
// assign the clamped values back to the computed values.
znear = desiredZnear;
zfar = desiredZfar;
var m22 = projection[ 10 ];
var m32 = projection[ 14 ];
var m23 = projection[ 11 ];
var m33 = projection[ 15 ];
var transNearPlane = ( -desiredZnear * m22 + m32 ) / ( -desiredZnear * m23 + m33 );
var transFarPlane = ( -desiredZfar * m22 + m32 ) / ( -desiredZfar * m23 + m33 );
var ratio = Math.abs( 2.0 / ( transNearPlane - transFarPlane ) );
var center = -( transNearPlane + transFarPlane ) / 2.0;
var centerRatio = center * ratio;
projection[ 2 ] = projection[ 2 ] * ratio + projection[ 3 ] * centerRatio;
projection[ 6 ] = projection[ 6 ] * ratio + projection[ 7 ] * centerRatio;
projection[ 10 ] = m22 * ratio + m23 * centerRatio;
projection[ 14 ] = m32 * ratio + m33 * centerRatio;
// same as
// var matrix = [ 1.0, 0.0, 0.0, 0.0,
// 0.0, 1.0, 0.0, 0.0,
// 0.0, 0.0, ratio, 0.0,
// 0.0, 0.0, center * ratio, 1.0
// ];
// mat4.mul( projection , matrix, projection );
// OSG_INFO << 'Persepective matrix after clamping'<<projection<<std::endl;
}
if ( resultNearFar !== undefined ) {
resultNearFar[ 0 ] = znear;
resultNearFar[ 1 ] = zfar;
}
return true;
},
popCameraModelViewProjectionMatrix: function () {
this.popModelViewMatrix();
this.popProjectionMatrix();
},
pushCameraModelViewProjectionMatrix: function ( camera, modelview, projection ) {
this.pushModelViewMatrix( modelview );
this.pushProjectionMatrix( projection );
},
apply: function ( node ) {
this[ node.typeID ]( node );
},
createOrReuseRenderStage: function ( classInstance ) {
var type = !classInstance ? 'RenderStage' : classInstance.className();
var classCtor = !classInstance ? RenderStage : classInstance.constructor;
var stack;
if ( this._reserveRenderStageStacks[ type ] ) {
stack = this._reserveRenderStageStacks[ type ];
} else {
stack = new osgPool.OsgObjectMemoryStack( classCtor );
this._reserveRenderStageStacks[ type ] = stack;
}
return stack.get().init();
},
createOrReuseRenderLeaf: function () {
var l = this._reserveLeafStack[ this._reserveLeafStackCurrent++ ];
if ( this._reserveLeafStackCurrent === this._reserveLeafStack.length ) {
this._reserveLeafStack.push( new RenderLeaf() );
}
return l;
},
resetRenderLeafStack: function () {
for ( var i = 0, j = this._reserveLeafStackCurrent; i <= j; i++ ) {
this._reserveLeafStack[ i ].reset();
}
},
createOrReuseCullSettings: function () {
var l = this._reserveCullSettingsStack[ this._reserveCullSettingsStackCurrent++ ];
if ( this._reserveCullSettingsStackCurrent === this._reserveCullSettingsStack.length ) {
this._reserveCullSettingsStack.push( new CullSettings() );
}
return l;
},
resetCullSettingsStack: function () {
for ( var i = 0, j = this._reserveCullSettingsStackCurrent; i <= j; i++ ) {
this._reserveCullSettingsStack[ i ].reset();
}
},
// function call after the push state in the geometry apply function
// the idea is to avoid heavy copy-paste for the rigGeometry apply
// since the only difference is that we want to push an additional state
// Maybe it will be useful when we'll add morph target geometry or something...
postPushGeometry: function ( cull, node ) {
var sourceGeometry;
var geometryStateSetAnimation;
if ( node instanceof RigGeometry ) {
geometryStateSetAnimation = node.getStateSetAnimation();
if ( geometryStateSetAnimation ) cull.pushStateSet( geometryStateSetAnimation );
sourceGeometry = node.getSourceGeometry();
if ( sourceGeometry instanceof MorphGeometry ) {
geometryStateSetAnimation = sourceGeometry.getStateSetAnimation();
if ( geometryStateSetAnimation ) cull.pushStateSet( geometryStateSetAnimation );
}
} else if ( node instanceof MorphGeometry ) {
geometryStateSetAnimation = node.getStateSetAnimation();
if ( geometryStateSetAnimation ) cull.pushStateSet( geometryStateSetAnimation );
}
},
// same comment as above (postPushGeometry)
prePopGeometry: function ( cull, node ) {
if ( node instanceof RigGeometry ) {
var sourceGeometry = node.getSourceGeometry();
if ( sourceGeometry instanceof MorphGeometry ) {
if ( sourceGeometry.getStateSetAnimation() ) cull.popStateSet();
}
if ( node.getStateSetAnimation() ) cull.popStateSet();
} else if ( node instanceof MorphGeometry && node.getStateSetAnimation() ) {
cull.popStateSet();
}
},
pushLeaf: function ( node, depth ) {
var leafs = this._currentStateGraph.leafs;
if ( leafs.length === 0 ) {
this._currentRenderBin.addStateGraph( this._currentStateGraph );
}
var leaf = this.createOrReuseRenderLeaf();
leaf.init( this._currentStateGraph,
node,
this.getCurrentProjectionMatrix(),
this.getCurrentViewMatrix(),
this.getCurrentModelViewMatrix(),
this.getCurrentModelMatrix(),
depth );
leafs.push( leaf );
}
} ) );
// Camera cull visitor call
// ANY CHANGE, any change : double check in rendere Camera code
// for the first camera
CullVisitor.prototype[ Camera.typeID ] = function ( camera ) {
this._numCamera++;
var stateset = camera.getStateSet();
if ( stateset ) this.pushStateSet( stateset );
var modelview = this._reservedMatrixStack.get();
var projection = this._reservedMatrixStack.get();
if ( camera.getReferenceFrame() === TransformEnums.RELATIVE_RF ) {
var lastProjectionMatrix = this.getCurrentProjectionMatrix();
mat4.mul( projection, lastProjectionMatrix, camera.getProjectionMatrix() );
var lastViewMatrix = this.getCurrentModelViewMatrix();
mat4.mul( modelview, lastViewMatrix, camera.getViewMatrix() );
} else {
// absolute
mat4.copy( modelview, camera.getViewMatrix() );
mat4.copy( projection, camera.getProjectionMatrix() );
}
// save current state of the camera
var previousZnear = this._computedNear;
var previousZfar = this._computedFar;
// save cullSettings
// TODO Perf: why it's not a stack
// and is pollutin GC ?
var previousCullsettings = this.createOrReuseCullSettings();
previousCullsettings.setCullSettings( this );
this._computedNear = Number.POSITIVE_INFINITY;
this._computedFar = Number.NEGATIVE_INFINITY;
//
this.setCullSettings( camera );
// global override
// upon who setted the parameter
// if it's cullvisitor
// it's an OVERRIDER for enableFrustumCulling
// allowing for global EnableFrustimCulling
if ( previousCullsettings.getSettingSourceOverrider() === this && previousCullsettings.getEnableFrustumCulling() ) {
this.setEnableFrustumCulling( true );
}
this.pushCameraModelViewProjectionMatrix( camera, modelview, projection );
if ( camera.getViewport() ) {
this.pushViewport( camera.getViewport() );
}
// nested camera
if ( camera.getRenderOrder() === Camera.NESTED_RENDER ) {
this.handleCullCallbacksAndTraverse( camera );
} else {
// not tested
var renderBin = this.getCurrentRenderBin();
var previousStage = renderBin.getStage();
// use render to texture stage
var rtts = this.createOrReuseRenderStage( this._rootRenderStage );
rtts.setCamera( camera );
rtts.setClearDepth( camera.getClearDepth() );
rtts.setClearColor( camera.getClearColor() );
rtts.setClearMask( camera.getClearMask() );
var vp;
if ( camera.getViewport() === undefined ) {
vp = previousStage.getViewport();
} else {
vp = camera.getViewport();
}
rtts.setViewport( vp );
// skip positional state for now
// ...
this.setCurrentRenderBin( rtts );
this.handleCullCallbacksAndTraverse( camera );
this.setCurrentRenderBin( renderBin );
if ( camera.getRenderOrder() === Camera.PRE_RENDER ) {
this.getCurrentRenderBin().getStage().addPreRenderStage( rtts, camera.renderOrderNum );
} else {
this.getCurrentRenderBin().getStage().addPostRenderStage( rtts, camera.renderOrderNum );
}
}
this.popCameraModelViewProjectionMatrix( camera );
if ( camera.getViewport() ) {
this.popViewport();
}
// restore previous state of the camera
this.setCullSettings( previousCullsettings );
this._computedNear = previousZnear;
this._computedFar = previousZfar;
if ( stateset ) this.popStateSet();
};
CullVisitor.prototype[ MatrixTransform.typeID ] = function ( node ) {
this._numMatrixTransform++;
// Camera and lights must enlarge node parent bounding boxes for this not to cull
if ( this.isCulled( node, this.nodePath ) ) {
return;
}
// push the culling mode.
this.pushCurrentMask();
var matrix = this._reservedMatrixStack.get();
var lastMatrixStack = this.getCurrentModelViewMatrix();
mat4.copy( matrix, lastMatrixStack );
node.computeLocalToWorldMatrix( matrix );
this.pushModelViewMatrix( matrix );
var stateset = node.getStateSet();
if ( stateset ) this.pushStateSet( stateset );
this.handleCullCallbacksAndTraverse( node );
if ( stateset ) this.popStateSet();
this.popModelViewMatrix();
// pop the culling mode.
this.popCurrentMask();
};
CullVisitor.prototype[ Projection.typeID ] = function ( node ) {
this._numProjection++;
var lastMatrixStack = this.getCurrentProjectionMatrix();
var matrix = this._reservedMatrixStack.get();
mat4.mul( matrix, lastMatrixStack, node.getProjectionMatrix() );
this.pushProjectionMatrix( matrix );
var stateset = node.getStateSet();
if ( stateset ) this.pushStateSet( stateset );
this.handleCullCallbacksAndTraverse( node );
if ( stateset ) this.popStateSet();
this.popProjectionMatrix();
};
// here it's treated as a group node for culling
// as there's isn't any in osgjs
// so frustumCulling is done here
CullVisitor.prototype[ Node.typeID ] = function ( node ) {
this._numNode++;
// Camera and lights must enlarge node parent bounding boxes for this not to cull
if ( this.isCulled( node, this.nodePath ) ) {
return;
}
// push the culling mode.
this.pushCurrentMask();
var stateset = node.getStateSet();
if ( stateset ) this.pushStateSet( stateset );
this.handleCullCallbacksAndTraverse( node );
if ( stateset ) this.popStateSet();
// pop the culling mode.
this.popCurrentMask();
};
// same code like MatrixTransform
CullVisitor.prototype[ AutoTransform.typeID ] = CullVisitor.prototype[ MatrixTransform.typeID ];
// same code like Node
CullVisitor.prototype[ Lod.typeID ] = CullVisitor.prototype[ Node.typeID ];
// same code like Node
CullVisitor.prototype[ PagedLOD.typeID ] = CullVisitor.prototype[ Node.typeID ];
CullVisitor.prototype[ LightSource.typeID ] = function ( node ) {
this._numLightSource++;
var stateset = node.getStateSet();
if ( stateset ) this.pushStateSet( stateset );
var light = node.getLight();
if ( light ) {
if ( node.getReferenceFrame() === TransformEnums.RELATIVE_RF )
this.addPositionedAttribute( this.getCurrentModelViewMatrix(), light );
else
this.addPositionedAttribute( null, light );
}
this.handleCullCallbacksAndTraverse( node );
if ( stateset ) this.popStateSet();
};
CullVisitor.prototype[ Geometry.typeID ] = ( function () {
var tempVec = vec3.create();
var loggedOnce = false;
return function geometryApply( node ) {
this._numGeometry++;
var modelview = this.getCurrentModelViewMatrix();
var bb = node.getBoundingBox();
if ( this._computeNearFar && bb.valid() ) {
if ( !this.updateCalculatedNearFar( modelview, node ) ) {
return;
}
}
// using modelview is not a pb because geometry
// is a leaf node, else traversing the graph would be an
// issue because we use modelview after
var ccb = node.getCullCallback();
if ( ccb && !ccb.cull( node, this ) )
return;
var stateset = node.getStateSet();
if ( stateset ) this.pushStateSet( stateset );
this.postPushGeometry( this, node );
var depth = 0;
if ( bb.valid() ) {
depth = this.distance( bb.center( tempVec ), modelview );
}
if ( osgMath.isNaN( depth ) ) {
if ( !loggedOnce ) {
Notify.warn( 'warning geometry has a NaN depth, ' + modelview + ' center ' + tempVec );
loggedOnce = true;
}
} else {
this.pushLeaf( node, depth );
}
this.prePopGeometry( this, node );
if ( stateset ) this.popStateSet();
};
} )();
CullVisitor.prototype[ Skeleton.typeID ] = CullVisitor.prototype[ MatrixTransform.typeID ];
CullVisitor.prototype[ RigGeometry.typeID ] = CullVisitor.prototype[ Geometry.typeID ];
CullVisitor.prototype[ MorphGeometry.typeID ] = CullVisitor.prototype[ Geometry.typeID ];
CullVisitor.prototype[ Bone.typeID ] = CullVisitor.prototype[ MatrixTransform.typeID ];
module.exports = CullVisitor;

Wyświetl plik

@ -1,81 +0,0 @@
'use strict';
var Polytope = require( 'osg/Polytope' );
var CullingSet = function () {
this._mask = CullingSet.DEFAULT_CULLING;
this._frustum = new Polytope();
};
CullingSet.prototype = {
reset: function () {
this._mask = CullingSet.DEFAULT_CULLING;
this._frustum.clear();
},
setCullingMask: function ( mask ) {
this._mask = mask;
},
getCullingMask: function () {
return this._mask;
},
setFrustum: function ( frustum ) {
this._frustum = frustum;
},
getFrustum: function () {
return this._frustum;
},
getCurrentResultMask: function () {
return this._frustum.getCurrentMask();
},
pushCurrentMask: function () {
this._frustum.pushCurrentMask();
},
popCurrentMask: function () {
this._frustum.popCurrentMask();
},
resetCullingMask: function () {
this._frustum.setResultMask( this._frustum.getCurrentMask() );
},
isBoundingBoxCulled: function ( bbox ) {
if ( this._mask & CullingSet.VIEW_FRUSTUM_CULLING ) {
// is it outside the view frustum...
if ( !this._frustum.containsBoundingBox( bbox ) ) return true;
}
return false;
},
isBoundingSphereCulled: function ( bs ) {
if ( this._mask & CullingSet.VIEW_FRUSTUM_CULLING ) {
// is it outside the view frustum...
if ( !this._frustum.containsBoundingSphere( bs ) ) return true;
}
return false;
},
isVerticesCulled: function ( vertices ) {
if ( this._mask & CullingSet.VIEW_FRUSTUM_CULLING ) {
// is it outside the view frustum...
if ( !this._frustum.containsVertices( vertices ) ) return true;
}
return false;
}
};
CullingSet.NO_CULLING = 0x0;
CullingSet.VIEW_FRUSTUM_LEFT_CULLING = 0x1;
CullingSet.VIEW_FRUSTUM_RIGHT_CULLING = 0x2;
CullingSet.VIEW_FRUSTUM_TOP_CULLING = 0x3;
CullingSet.VIEW_FRUSTUM_BOTTOM_CULLING = 0x4;
CullingSet.NEAR_PLANE_CULLING = 0x5;
CullingSet.FAR_PLANE_CULLING = 0x6;
CullingSet.VIEW_FRUSTUM_SIDES_CULLING = CullingSet.VIEW_FRUSTUM_LEFT_CULLING | CullingSet.VIEW_FRUSTUM_RIGHT_CULLING | CullingSet.VIEW_FRUSTUM_BOTTOM_CULLING | CullingSet.VIEW_FRUSTUM_TOP_CULLING;
CullingSet.VIEW_FRUSTUM_CULLING = CullingSet.VIEW_FRUSTUM_SIDES_CULLING | CullingSet.NEAR_PLANE_CULLING | CullingSet.FAR_PLANE_CULLING;
CullingSet.DEFAULT_CULLING = CullingSet.VIEW_FRUSTUM_SIDES_CULLING;
CullingSet.ENABLE_ALL_CULLING = CullingSet.VIEW_FRUSTUM_CULLING;
module.exports = CullingSet;

Wyświetl plik

@ -1,72 +0,0 @@
'use strict';
var MACROUTILS = require( 'osg/Utils' );
var StateAttribute = require( 'osg/StateAttribute' );
var Depth = function ( func, near, far, writeMask ) {
StateAttribute.call( this );
this._func = Depth.LESS;
this._near = 0.0;
this._far = 1.0;
this._writeMask = true;
if ( func !== undefined ) {
if ( typeof ( func ) === 'string' ) {
this._func = Depth[ func ];
} else {
this._func = func;
}
}
if ( near !== undefined ) {
this._near = near;
}
if ( far !== undefined ) {
this._far = far;
}
if ( writeMask !== undefined ) {
this._writeMask = writeMask;
}
};
Depth.DISABLE = 0x0000;
Depth.NEVER = 0x0200;
Depth.LESS = 0x0201;
Depth.EQUAL = 0x0202;
Depth.LEQUAL = 0x0203;
Depth.GREATER = 0x0204;
Depth.NOTEQUAL = 0x0205;
Depth.GEQUAL = 0x0206;
Depth.ALWAYS = 0x0207;
Depth.prototype = MACROUTILS.objectLibraryClass( MACROUTILS.objectInherit( StateAttribute.prototype, {
attributeType: 'Depth',
cloneType: function () {
return new Depth();
},
setRange: function ( near, far ) {
this._near = near;
this._far = far;
},
setWriteMask: function ( mask ) {
this._writeMask = mask;
},
getWriteMask: function () {
return this._writeMask;
},
getFunc: function () {
return this._func;
},
apply: function ( state ) {
var gl = state.getGraphicContext();
if ( this._func === 0 ) {
gl.disable( gl.DEPTH_TEST );
} else {
gl.enable( gl.DEPTH_TEST );
gl.depthFunc( this._func );
gl.depthMask( this._writeMask );
gl.depthRange( this._near, this._far );
}
}
} ), 'osg', 'Depth' );
module.exports = Depth;

Wyświetl plik

@ -1,51 +0,0 @@
'use strict';
/**
* DrawArrayLengths manage rendering primitives
* @class DrawArrayLengths
*/
var DrawArrayLengths = function ( mode, first, array ) {
this._mode = mode;
this._first = first;
this._arrayLengths = array.slice( 0 );
};
/** @lends DrawArrayLengths.prototype */
DrawArrayLengths.prototype = {
draw: function ( state ) {
var gl = state.getGraphicContext();
var mode = this._mode;
var first = this._first;
var array = this._arrayLengths;
for ( var i = 0, l = array.length; i < l; i++ ) {
var count = array[ i ];
gl.drawArrays( mode, first, count );
first += count;
}
},
getMode: function () {
return this._mode;
},
getNumIndices: function () {
var count = 0;
var array = this._arrayLengths;
for ( var i = 0, l = array.length; i < l; i++ ) {
count += array[ i ];
}
return count;
},
getCount: function () {
return this.getNumIndices();
},
getArrayLengths: function () {
return this._arrayLengths;
},
getFirst: function () {
return this._first;
},
setFirst: function ( first ) {
this._first = first;
}
};
module.exports = DrawArrayLengths;

Wyświetl plik

@ -1,59 +0,0 @@
'use strict';
var Notify = require( 'osg/notify' );
var PrimitiveSet = require( 'osg/primitiveSet' );
/**
* DrawArrays manage rendering primitives
* @class DrawArrays
*/
var DrawArrays = function ( mode, first, count ) {
this.mode = mode;
if ( mode !== undefined ) {
if ( typeof ( mode ) === 'string' ) {
mode = PrimitiveSet[ mode ];
}
this.mode = mode;
}
this.first = first;
this.count = count;
};
/** @lends DrawArrays.prototype */
DrawArrays.prototype = {
draw: function ( state ) {
if ( this.count === 0 )
return;
var gl = state.getGraphicContext();
gl.drawArrays( this.mode, this.first, this.count );
},
getMode: function () {
return this.mode;
},
setCount: function ( count ) {
this.count = count;
},
getCount: function () {
return this.count;
},
setFirst: function ( first ) {
this.first = first;
},
getFirst: function () {
return this.first;
},
getNumIndices: function () {
return this.count;
},
index: function ( i ) {
return this.first + i;
}
};
DrawArrays.create = function ( mode, first, count ) {
Notify.log( 'DrawArrays.create is deprecated, use new DrawArrays with same arguments' );
var d = new DrawArrays( mode, first, count );
return d;
};
module.exports = DrawArrays;

Wyświetl plik

@ -1,86 +0,0 @@
'use strict';
var Notify = require( 'osg/notify' );
var PrimitiveSet = require( 'osg/primitiveSet' );
/**
* DrawElements manage rendering of indexed primitives
* @class DrawElements
*/
var DrawElements = function ( mode, indices ) {
this.mode = PrimitiveSet.POINTS;
if ( mode !== undefined ) {
if ( typeof ( mode ) === 'string' ) {
mode = PrimitiveSet[ mode ];
}
this.mode = mode;
}
this.count = 0;
this.offset = 0;
this.indices = indices;
this.uType = DrawElements.UNSIGNED_SHORT;
if ( indices !== undefined ) {
this.setIndices( indices );
}
};
DrawElements.UNSIGNED_BYTE = 0x1401;
DrawElements.UNSIGNED_SHORT = 0x1403;
DrawElements.UNSIGNED_INT = 0x1405;
/** @lends DrawElements.prototype */
DrawElements.prototype = {
getMode: function () {
return this.mode;
},
draw: function ( state ) {
if ( this.count === 0 )
return;
state.setIndexArray( this.indices );
this.drawElements( state );
},
drawElements: function ( state ) {
var gl = state.getGraphicContext();
gl.drawElements( this.mode, this.count, this.uType, this.offset );
},
setIndices: function ( indices ) {
this.indices = indices;
var elts = indices.getElements();
this.count = elts.length;
var nbBytes = elts.BYTES_PER_ELEMENT;
if ( nbBytes === 1 ) this.uType = DrawElements.UNSIGNED_BYTE;
else if ( nbBytes === 2 ) this.uType = DrawElements.UNSIGNED_SHORT;
else if ( nbBytes === 4 ) this.uType = DrawElements.UNSIGNED_INT;
},
getIndices: function () {
return this.indices;
},
setFirst: function ( val ) {
this.offset = val;
},
getFirst: function () {
return this.offset;
},
setCount: function ( val ) {
this.count = val;
},
getCount: function () {
return this.count;
},
getNumIndices: function () {
return this.indices.getElements().length;
},
index: function ( i ) {
return this.indices.getElements()[ i ];
}
};
DrawElements.create = function ( mode, indices ) {
Notify.log( 'DrawElements.create is deprecated, use new DrawElements with same arguments' );
return new DrawElements( mode, indices );
};
module.exports = DrawElements;

Wyświetl plik

@ -1,140 +0,0 @@
'use strict';
var Notify = require( 'osg/notify' );
var mat4 = require( 'osg/glMatrix' ).mat4;
var vec3 = require( 'osg/glMatrix' ).vec3;
var EllipsoidModel = function () {
this._radiusEquator = EllipsoidModel.WGS_84_RADIUS_EQUATOR;
this._radiusPolar = EllipsoidModel.WGS_84_RADIUS_POLAR;
this.computeCoefficients();
};
EllipsoidModel.WGS_84_RADIUS_EQUATOR = 6378137.0;
EllipsoidModel.WGS_84_RADIUS_POLAR = 6356752.3142;
EllipsoidModel.prototype = {
setRadiusEquator: function ( radius ) {
this._radiusEquator = radius;
this.computeCoefficients();
},
getRadiusEquator: function () {
return this._radiusEquator;
},
setRadiusPolar: function ( radius ) {
this._radiusPolar = radius;
this.computeCoefficients();
},
getRadiusPolar: function () {
return this._radiusPolar;
},
convertLatLongHeightToXYZ: function ( latitude, longitude, height, result ) {
if ( result === undefined ) {
Notify.warn( 'deprecated, use this signature convertLatLongHeightToXYZ( latitude, longitude, height, result )' );
result = vec3.create();
}
var sinLatitude = Math.sin( latitude );
var cosLatitude = Math.cos( latitude );
var N = this._radiusEquator / Math.sqrt( 1.0 - this._eccentricitySquared * sinLatitude * sinLatitude );
var X = ( N + height ) * cosLatitude * Math.cos( longitude );
var Y = ( N + height ) * cosLatitude * Math.sin( longitude );
var Z = ( N * ( 1.0 - this._eccentricitySquared ) + height ) * sinLatitude;
result[ 0 ] = X;
result[ 1 ] = Y;
result[ 2 ] = Z;
return result;
},
convertXYZToLatLongHeight: function ( X, Y, Z, result ) {
if ( result === undefined ) {
Notify.warn( 'deprecated, use this signature convertXYZToLatLongHeight( X, Y, Z , result)' );
result = vec3.create();
}
// http://www.colorado.edu/geography/gcraft/notes/datum/gif/xyzllh.gif
var p = Math.sqrt( X * X + Y * Y );
var theta = Math.atan2( Z * this._radiusEquator, ( p * this._radiusPolar ) );
var eDashSquared = ( this._radiusEquator * this._radiusEquator - this._radiusPolar * this._radiusPolar ) / ( this._radiusPolar * this._radiusPolar );
var sinTheta = Math.sin( theta );
var cosTheta = Math.cos( theta );
var latitude = Math.atan( ( Z + eDashSquared * this._radiusPolar * sinTheta * sinTheta * sinTheta ) /
( p - this._eccentricitySquared * this._radiusEquator * cosTheta * cosTheta * cosTheta ) );
var longitude = Math.atan2( Y, X );
var sinLatitude = Math.sin( latitude );
var N = this._radiusEquator / Math.sqrt( 1.0 - this._eccentricitySquared * sinLatitude * sinLatitude );
var cosLat = Math.cos( latitude );
if ( cosLat === 0 ) cosLat = 1;
var height = p / cosLat - N;
result[ 0 ] = latitude;
result[ 1 ] = longitude;
result[ 2 ] = height;
return result;
},
computeLocalUpVector: function ( X, Y, Z ) {
// Note latitude is angle between normal to ellipsoid surface and XY-plane
var latitude, longitude, altitude;
var coord = this.convertXYZToLatLongHeight( X, Y, Z, latitude, longitude, altitude );
latitude = coord[ 0 ];
longitude = coord[ 1 ];
altitude = coord[ 2 ];
// Compute up vector
return [ Math.cos( longitude ) * Math.cos( latitude ),
Math.sin( longitude ) * Math.cos( latitude ),
Math.sin( latitude )
];
},
isWGS84: function () {
return ( this._radiusEquator === EllipsoidModel.WGS_84_RADIUS_EQUATOR && this._radiusPolar === EllipsoidModel.WGS_84_RADIUS_POLAR );
},
computeCoefficients: function () {
var flattening = ( this._radiusEquator - this._radiusPolar ) / this._radiusEquator;
this._eccentricitySquared = 2.0 * flattening - flattening * flattening;
},
computeLocalToWorldTransformFromLatLongHeight: function ( latitude, longitude, height, result ) {
if ( result === undefined ) {
Notify.warn( 'deprecated, use this signature computeLocalToWorldTransformFromLatLongHeight(latitude, longitude, height, result)' );
result = mat4.create();
}
var pos = this.convertLatLongHeightToXYZ( latitude, longitude, height, result );
mat4.fromTranslation( result, pos );
this.computeCoordinateFrame( latitude, longitude, result );
return result;
},
computeLocalToWorldTransformFromXYZ: function ( X, Y, Z ) {
var lla = this.convertXYZToLatLongHeight( X, Y, Z );
var m = mat4.fromTranslation( mat4.create(), vec3.fromValues( X, Y, Z ) );
this.computeCoordinateFrame( lla[ 0 ], lla[ 1 ], m );
return m;
},
computeCoordinateFrame: ( function () {
var up = vec3.create();
var east = vec3.create();
var north = vec3.create();
return function ( latitude, longitude, localToWorld ) {
// Compute up vector
up[ 0 ] = Math.cos( longitude ) * Math.cos( latitude );
up[ 1 ] = Math.sin( longitude ) * Math.cos( latitude );
up[ 2 ] = Math.sin( latitude );
// Compute east vector
east[ 0 ] = -Math.sin( longitude );
east[ 1 ] = -Math.cos( longitude );
// Compute north vector = outer product up x east
vec3.cross( north, up, east );
// set matrix
mat4.set( localToWorld,
east[ 0 ], east[ 1 ], east[ 2 ], 0,
north[ 0 ], north[ 1 ], north[ 2 ], 0,
up[ 0 ], up[ 1 ], up[ 2 ], 0,
0, 0, 0, 1 );
};
} )()
};
module.exports = EllipsoidModel;

Wyświetl plik

@ -1,351 +0,0 @@
'use strict';
var Notify = require( 'osg/notify' );
var MACROUTILS = require( 'osg/Utils' );
var GLObject = require( 'osg/GLObject' );
var StateAttribute = require( 'osg/StateAttribute' );
var Timer = require( 'osg/Timer' );
var WebglCaps = require( 'osg/WebGLCaps' );
/**
* FrameBufferObject manage fbo / rtt
* @class FrameBufferObject
*/
var FrameBufferObject = function () {
GLObject.call( this );
StateAttribute.call( this );
this._fbo = undefined;
this._rbo = undefined;
this._attachments = [];
this._dirty = true;
};
FrameBufferObject.COLOR_ATTACHMENT0 = 0x8CE0;
FrameBufferObject.DEPTH_ATTACHMENT = 0x8D00;
FrameBufferObject.DEPTH_COMPONENT16 = 0x81A5;
// static cache of glFrameBuffer flagged for deletion, which will actually
// be deleted in the correct GL context.
FrameBufferObject._sDeletedGLFrameBufferCache = new window.Map();
// static method to delete FrameBuffers
FrameBufferObject.deleteGLFrameBuffer = function ( gl, fb ) {
if ( !FrameBufferObject._sDeletedGLFrameBufferCache.has( gl ) )
FrameBufferObject._sDeletedGLFrameBufferCache.set( gl, [] );
FrameBufferObject._sDeletedGLFrameBufferCache.get( gl ).push( fb );
};
// static method to flush all the cached glFrameBuffers which need to be deleted in the GL context specified
FrameBufferObject.flushDeletedGLFrameBuffers = function ( gl, availableTime ) {
// if no time available don't try to flush objects.
if ( availableTime <= 0.0 ) return availableTime;
if ( !FrameBufferObject._sDeletedGLFrameBufferCache.has( gl ) ) return availableTime;
var elapsedTime = 0.0;
var beginTime = Timer.instance().tick();
var deleteList = FrameBufferObject._sDeletedGLFrameBufferCache.get( gl );
var numBuffers = deleteList.length;
for ( var i = numBuffers - 1; i >= 0 && elapsedTime < availableTime; i-- ) {
gl.deleteFramebuffer( deleteList[ i ] );
deleteList.splice( i, 1 );
elapsedTime = Timer.instance().deltaS( beginTime, Timer.instance().tick() );
}
return availableTime - elapsedTime;
};
FrameBufferObject.flushAllDeletedGLFrameBuffers = function ( gl ) {
if ( !FrameBufferObject._sDeletedGLFrameBufferCache.has( gl ) ) return;
var deleteList = FrameBufferObject._sDeletedGLFrameBufferCache.get( gl );
var numBuffers = deleteList.length;
for ( var i = numBuffers - 1; i >= 0; i-- ) {
gl.deleteFramebuffer( deleteList[ i ] );
deleteList.splice( i, 1 );
}
};
// static cache of glRenderBuffer flagged for deletion, which will actually
// be deleted in the correct GL context.
FrameBufferObject._sDeletedGLRenderBufferCache = new window.Map();
// static method to delete RenderBuffers
FrameBufferObject.deleteGLRenderBuffer = function ( gl, fb ) {
if ( !FrameBufferObject._sDeletedGLRenderBufferCache.has( gl ) )
FrameBufferObject._sDeletedGLRenderBufferCache.set( gl, [] );
FrameBufferObject._sDeletedGLRenderBufferCache.get( gl ).push( fb );
};
// static method to flush all the cached glRenderBuffers which need to be deleted in the GL context specified
FrameBufferObject.flushDeletedGLRenderBuffers = function ( gl, availableTime ) {
// if no time available don't try to flush objects.
if ( availableTime <= 0.0 ) return availableTime;
if ( !FrameBufferObject._sDeletedGLRenderBufferCache.has( gl ) ) return availableTime;
var elapsedTime = 0.0;
var beginTime = Timer.instance().tick();
var deleteList = FrameBufferObject._sDeletedGLRenderBufferCache.get( gl );
var numBuffers = deleteList.length;
for ( var i = numBuffers - 1; i >= 0 && elapsedTime < availableTime; i-- ) {
gl.deleteRenderbuffer( deleteList[ i ] );
deleteList.splice( i, 1 );
elapsedTime = Timer.instance().deltaS( beginTime, Timer.instance().tick() );
}
return availableTime - elapsedTime;
};
FrameBufferObject.flushAllDeletedGLRenderBuffers = function ( gl ) {
if ( !FrameBufferObject._sDeletedGLRenderBufferCache.has( gl ) ) return;
var deleteList = FrameBufferObject._sDeletedGLRenderBufferCache.get( gl );
var numBuffers = deleteList.length;
for ( var i = numBuffers - 1; i >= 0; i-- ) {
gl.deleteRenderbuffer( deleteList[ i ] );
deleteList.splice( i, 1 );
}
};
/** @lends FrameBufferObject.prototype */
FrameBufferObject.prototype = MACROUTILS.objectInherit( GLObject.prototype, MACROUTILS.objectInherit( StateAttribute.prototype, {
attributeType: 'FrameBufferObject',
cloneType: function () {
return new FrameBufferObject();
},
dirty: function () {
this._dirty = true;
},
isDirty: function () {
return this._dirty;
},
setAttachment: function ( attachment ) {
this._attachments.push( attachment );
},
releaseGLObjects: function () {
if ( this._fbo !== undefined && this._gl !== undefined ) {
FrameBufferObject.deleteGLFrameBuffer( this._gl, this._fbo );
}
this._fbo = undefined;
if ( this._rbo !== undefined && this._gl !== undefined ) {
FrameBufferObject.deleteGLRenderBuffer( this._gl, this._rbo );
}
this._rbo = undefined;
},
_reportFrameBufferError: function ( code ) {
switch ( code ) {
case 0x8CD6:
Notify.debug( 'FRAMEBUFFER_INCOMPLETE_ATTACHMENT' );
break;
case 0x8CD7:
Notify.debug( 'FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT' );
break;
case 0x8CD9:
Notify.debug( 'FRAMEBUFFER_INCOMPLETE_DIMENSIONS' );
break;
case 0x8CDD:
Notify.debug( 'FRAMEBUFFER_UNSUPPORTED' );
break;
default:
Notify.debug( 'FRAMEBUFFER unknown error ' + code.toString( 16 ) );
}
},
reset: function () {
this.releaseGLObjects();
this._attachments = [];
},
getFrameBufferObject: function () {
return this._fbo;
},
createFrameBufferObject: function ( state ) {
this.setGraphicContext( state.getGraphicContext() );
this._fbo = this._gl.createFramebuffer();
},
createRenderBuffer: function ( format, width, height ) {
var gl = this._gl;
var renderBuffer = gl.createRenderbuffer();
gl.bindRenderbuffer( gl.RENDERBUFFER, renderBuffer );
gl.renderbufferStorage( gl.RENDERBUFFER, format, width, height );
return renderBuffer;
},
framebufferRenderBuffer: function ( attachment, renderBuffer ) {
var gl = this._gl;
gl.bindRenderbuffer( gl.RENDERBUFFER, renderBuffer );
gl.framebufferRenderbuffer( gl.FRAMEBUFFER, attachment, gl.RENDERBUFFER, renderBuffer );
/* develblock:start */
// only visible with webgl-insector enabled
if ( gl.rawgl !== undefined ) {
Notify.log( 'FBO: renderBuffer: ' + this._fbo.trackedObject.defaultName );
}
/* develblock:end */
},
framebufferTexture2D: function ( state, attachment, textureTarget, texture ) {
var gl = this._gl;
// apply on unit 1 to init it
// make sure we do bind it whatever state stack
// texture is cached
state.applyTextureAttribute( 1, texture );
if ( texture.isDirty() || !texture.getTextureObject() ) {
// image wasn't ready, texture not allocated due to lack of gpu MEM
return false;
}
gl.framebufferTexture2D( gl.FRAMEBUFFER, attachment, textureTarget, texture.getTextureObject().id(), 0 );
/* develblock:start */
// only visible with webgl-insector enabled
// allow trace debug (fb<->texture link)
if ( gl.rawgl !== undefined ) {
Notify.log( 'FBO: texture: ' + texture.getName() + ' : ' + texture.getTextureObject().id().trackedObject.defaultName + ' fbo: ' + this._fbo.trackedObject.defaultName );
}
/* develblock:end */
return true;
},
bindFrameBufferObject: function () {
var gl = this._gl;
gl.bindFramebuffer( gl.FRAMEBUFFER, this._fbo );
},
checkStatus: function () {
var gl = this._gl;
var status = gl.checkFramebufferStatus( gl.FRAMEBUFFER );
if ( status !== 0x8CD5 ) {
this._reportFrameBufferError( status );
}
},
_checkAllowedSize: function ( w, h ) {
var maxSize = WebglCaps.instance().getWebGLParameter( 'MAX_RENDERBUFFER_SIZE' );
if ( w === 0 || h === 0 || h > maxSize || w > maxSize ) {
Notify.error( 'width (' + w + ') or height (' + w + ') makes frame buffer not bindable. Max RenderBuffer is "' + maxSize + '"' );
return false;
}
return true;
},
apply: function ( state ) {
if ( !this._gl ) this.setGraphicContext( state.getGraphicContext() );
var gl = this._gl;
var attachments = this._attachments;
// if the fbo is created manually, we want to just bind it
if ( attachments.length > 0 || this._fbo ) {
if ( this.isDirty() ) {
if ( !this._fbo )
this.createFrameBufferObject( state );
this.bindFrameBufferObject();
var hasRenderBuffer = false;
for ( var i = 0, l = attachments.length; i < l; ++i ) {
var attachment = attachments[ i ];
// render buffer
if ( !attachment.texture ) {
if ( !this._checkAllowedSize( attachment.width, attachment.height ) ) {
this.releaseGLObjects();
return;
}
this._rbo = this.createRenderBuffer( attachment.format, attachment.width, attachment.height );
this.framebufferRenderBuffer( attachment.attachment, this._rbo );
hasRenderBuffer = true;
} else {
// use texture
var texture = attachment.texture;
if ( !this._checkAllowedSize( texture.getWidth(), texture.getHeight() ) ) {
this.releaseGLObjects();
return;
}
if ( !this.framebufferTexture2D( state, attachment.attachment, attachment.textureTarget, texture ) ) {
this.releaseGLObjects();
return;
}
}
}
this.checkStatus();
// set it to null only if used renderbuffer
if ( hasRenderBuffer )
gl.bindRenderbuffer( gl.RENDERBUFFER, null );
this._dirty = false;
} else {
gl.bindFramebuffer( gl.FRAMEBUFFER, this._fbo );
if ( Notify.reportWebGLError === true )
this.checkStatus();
}
} else {
gl.bindFramebuffer( gl.FRAMEBUFFER, null );
}
}
} ) );
module.exports = FrameBufferObject;

Wyświetl plik

@ -1,37 +0,0 @@
'use strict';
var FrameStamp = function () {
this._frame = 0;
this._startSimulation = 0.0;
this._currentSimulation = 0.0;
this._deltaTime = 0.0; // last time elapsed since the next traversal
};
FrameStamp.prototype = {
setReferenceTime: function ( s ) {
this._startSimulation = s;
},
getReferenceTime: function () {
return this._startSimulation;
},
setSimulationTime: function ( s ) {
this._currentSimulation = s;
},
getSimulationTime: function () {
return this._currentSimulation;
},
setDeltaTime: function ( d ) {
this._deltaTime = d;
},
getDeltaTime: function () {
return this._deltaTime;
},
setFrameNumber: function ( n ) {
this._frame = n;
},
getFrameNumber: function () {
return this._frame;
}
};
module.exports = FrameStamp;

Wyświetl plik

@ -1,19 +0,0 @@
'use strict';
// Base class for GLResources: Textures, Buffers, Programs, Shaders, FrameBuffers and RenderBuffers
// It holds a reference to the graphic context that is needed for resource deletion
var GLObject = function () {
this._gl = undefined;
};
GLObject.prototype = {
setGraphicContext: function ( gl ) {
this._gl = gl;
},
getGraphicContext: function () {
return this._gl;
}
};
module.exports = GLObject;

Wyświetl plik

@ -1,474 +0,0 @@
'use strict';
var MACROUTILS = require( 'osg/Utils' );
var Node = require( 'osg/Node' );
var Notify = require( 'osg/notify' );
var WebGLCaps = require( 'osg/WebGLCaps' );
var DrawElements = require( 'osg/DrawElements' );
var BufferArrayProxy = require( 'osg/BufferArrayProxy' );
/**
* Geometry manage array and primitives to draw a geometry.
* @class Geometry
*/
var Geometry = function () {
Node.call( this );
// Use proxy to detect change in vertex attributes
// you should use setVertexAttribute but if you dont
if ( window.Proxy ) {
var self = this;
this._attributes = {};
this._primitives = [];
this.attributes = new Proxy( this._attributes, {
set: function ( obj, prop, value ) {
var old = obj[ prop ];
if ( old !== value ) {
obj[ prop ] = value;
self.dirty();
}
return true;
}
} );
var push = function () {
this.push.apply( this, arguments );
self.dirty();
}.bind( this._primitives );
var pop = function () {
this.pop();
self.dirty();
}.bind( this._primitives );
this.primitives = new Proxy( this._primitives, {
get: function ( obj, key ) {
if ( key === 'push' ) return push;
if ( key === 'pop' ) return pop;
return obj[ key ];
}
} );
} else {
this.attributes = {};
this.primitives = [];
this._primitives = this.primitives;
this._attributes = this.attributes;
}
// function is generated for each Shader Program ID
// which generates a a special "draw"
// TODO: could be upon hash of combination of attributes
// (as multiple shader Programs can use same combination of attributes)
this._cacheDrawCall = {};
// VAO cached data, per combination of vertex buffer
// program id also the cache key
this._extVAO = undefined;
this._vao = {};
this._cacheVertexAttributeBufferList = {};
// null means the kdTree builder will skip the kdTree creation
this._shape = undefined;
};
/**
* enableVAO flag
* We rely on Proxy to detect changes in vertextes attributes list or in primitives
* list. If you dont have Proxy and you still want to use the VAO code path, replace
* OSG.osg.Geometry.enableVAO = true at the begining of your application, but be sure to
* not change vertexes attributes without calling dirty after.
*/
Geometry.enableVAO = Boolean( window.Proxy );
if ( Geometry.enableVAO ) Notify.info( 'enable VAO' );
/** @lends Geometry.prototype */
Geometry.prototype = MACROUTILS.objectLibraryClass( MACROUTILS.objectInherit( Node.prototype, {
releaseGLObjects: function () {
if ( this.stateset !== undefined ) this.stateset.releaseGLObjects();
var keys = window.Object.keys( this._attributes );
var value;
var i, l;
for ( i = 0, l = keys.length; i < l; i++ ) {
value = this._attributes[ keys[ i ] ];
value.releaseGLObjects();
}
for ( var j = 0, h = this._primitives.length; j < h; j++ ) {
var prim = this._primitives[ j ];
if ( prim.getIndices !== undefined ) {
if ( prim.getIndices() !== undefined && prim.getIndices() !== null ) {
prim.indices.releaseGLObjects();
}
}
}
this.releaseVAO();
},
releaseVAO: function () {
if ( !this._extVAO ) return;
var keys = window.Object.keys( this._vao );
for ( var i = 0, l = keys.length; i < l; i++ ) {
var prgID = keys[ i ];
if ( this._vao[ prgID ] ) {
var vao = this._vao[ prgID ];
this._extVAO.deleteVertexArrayOES( vao );
this._vao[ prgID ] = undefined;
}
}
},
dirty: function () {
this._cacheDrawCall = {};
this.releaseVAO();
},
getPrimitives: function () {
// Notify.warn( 'deprecated use instead getPrimitiveSetList' );
return this.getPrimitiveSetList();
},
getAttributes: function () {
// Notify.warn( 'deprecated use instead getVertexAttributeList' );
return this.getVertexAttributeList();
},
getShape: function () {
return this._shape;
},
setShape: function ( shape ) {
this._shape = shape;
},
getVertexAttributeList: function () {
return this.attributes;
},
/**
* Return the primitiveset list
* If you modify something inside this array
* you must call dirty() on the Geometry
*/
getPrimitiveSetList: function () {
return this.primitives;
},
/**
* Set the buffer array on the attribute name key
* key is often something like Vertex, Normal, Color, ...
* for classic geometry
*
* if you change a buffer a dirty will be automatically
* called to rebuild the VAO if needed.
*/
setVertexAttribArray: function ( key, array ) {
if ( this._attributes[ key ] !== array ) {
this._attributes[ key ] = array;
this.dirty();
}
},
_generateVertexSetup: function ( validAttributeKeyList, validAttributeIndexList, includeFirstIndexBuffer ) {
// generate setup for vertex attribute
// will be used as setup for vao or as is without vao
var vertexAttributeSetup = [ '//generated by Geometry::implementation',
'state.lazyDisablingOfVertexAttributes();',
'var attr;'
];
for ( var i = 0, l = validAttributeKeyList.length; i < l; i++ ) {
vertexAttributeSetup.push( 'attr = this._attributes[\'' + validAttributeKeyList[ i ] + '\'];' );
vertexAttributeSetup.push( 'if ( attr.BufferArrayProxy ) attr = attr.getBufferArray();' );
vertexAttributeSetup.push( 'if ( !attr.isValid() ) return;' );
vertexAttributeSetup.push( 'state.setVertexAttribArray(' + validAttributeIndexList[ i ] + ', attr, attr.getNormalize() );' );
}
vertexAttributeSetup.push( 'state.applyDisablingOfVertexAttributes();' );
if ( includeFirstIndexBuffer )
vertexAttributeSetup.push( 'state.setIndexArray( this._primitives[ 0 ].getIndices() );' );
return vertexAttributeSetup;
},
_generatePrimitive: function ( primitives, hasVertexColor, optimizeVAO ) {
var primitiveSetup = [
hasVertexColor ? 'state.enableVertexColor();' : 'state.disableVertexColor();'
];
if ( optimizeVAO ) {
return primitiveSetup.concat( [
'var primitive = this._primitives[ 0 ];',
'var indexes = primitive.getIndices();',
'if ( indexes.isDirty() ) {;',
' indexes.bind( gl );',
' indexes.compile( gl );',
'};',
'primitive.drawElements( state );'
] );
}
primitiveSetup.push( 'var primitives = this._primitives;' );
for ( var j = 0, m = primitives.length; j < m; j++ )
primitiveSetup.push( 'primitives[' + j + '].draw(state);' );
return primitiveSetup;
},
/**
* Generate a function specific to the Geometry/Program
* two version one using VAO and a regular one
*/
generateDrawCommand: ( function () {
var validAttributeList = [];
var validAttributeKeyList = [];
return function ( state, program, prgID ) {
var attributesCacheKeys = program._attributesCache.getKeys();
var attributesCacheMap = program._attributesCache;
var geometryVertexAttributes = this.getVertexAttributeList();
validAttributeKeyList.length = 0;
validAttributeList.length = 0;
// 1 - register valid vertex attributes and color flag
var attribute, i, l, j, m, key, attr;
var extVAO = this._extVAO;
var listVABuff = extVAO ? [] : undefined;
var hasVertexColor = false;
for ( i = 0, l = attributesCacheKeys.length; i < l; i++ ) {
key = attributesCacheKeys[ i ];
attribute = attributesCacheMap[ key ];
attr = geometryVertexAttributes[ key ];
if ( attr === undefined ) continue;
var attributeBuffer = this._attributes[ key ];
// dont use VAO if we have BufferArrayProxy
// typically used for morphing
if ( attributeBuffer instanceof BufferArrayProxy ) {
attributeBuffer = attributeBuffer.getBufferArray();
extVAO = false;
}
if ( !attributeBuffer.isValid() ) return undefined;
// store for later usage at draw time/update
if ( extVAO ) listVABuff.push( attributeBuffer );
if ( !hasVertexColor && key === 'Color' )
hasVertexColor = true;
validAttributeKeyList.push( key );
validAttributeList.push( attribute );
}
var autogeneratedFunction;
var functionName;
// generate specific function using VAO or standard
if ( extVAO ) {
this._cacheVertexAttributeBufferList[ prgID ] = listVABuff;
// if there is only one drawElement we can put the index buffer
// in the vao
var optimizeIndexBufferVAO = ( this._primitives.length === 1 && this._primitives[ 0 ] instanceof DrawElements );
var vertexAttributeSetup = this._generateVertexSetup( validAttributeKeyList, validAttributeList, optimizeIndexBufferVAO );
state.clearVertexAttribCache();
var vao = this._extVAO.createVertexArrayOES();
state.setVertexArrayObject( vao );
this._vao[ prgID ] = vao;
// evaluate the vertexAttribute setup to register into the vao
/*jshint evil: true */
var vertexSetupCommand = new Function( 'state', vertexAttributeSetup.join( '\n' ) );
/*jshint evil: false */
vertexSetupCommand.call( this, state );
// setup the program
var vaoSetup = [
'var gl = state.getGraphicContext();',
'var vao = this._vao[ ' + prgID + ' ] ',
'var hasChanged = state.setVertexArrayObject( vao );',
'if ( hasChanged ) {',
' var vaList = this._cacheVertexAttributeBufferList[ ' + prgID + ' ];',
' var va;'
];
for ( j = 0, m = listVABuff.length; j < m; j++ ) {
vaoSetup.push( ' va = vaList[ ' + j + '];' );
vaoSetup.push( ' if ( va.isDirty() ) {;' );
vaoSetup.push( ' va.bind( gl );' );
vaoSetup.push( ' va.compile( gl );' );
vaoSetup.push( ' };' );
}
vaoSetup.push( '}' );
autogeneratedFunction = vaoSetup.concat( this._generatePrimitive( this._primitives, hasVertexColor, optimizeIndexBufferVAO ) ).join( '\n' );
functionName = 'GeometryDrawImplementationCacheVAO';
} else {
autogeneratedFunction = this._generateVertexSetup( validAttributeKeyList, validAttributeList, false ).concat( this._generatePrimitive( this._primitives, hasVertexColor, false ) ).join( '\n' );
functionName = 'GeometryDrawImplementationCache';
}
/*jshint evil: true */
// name the function
// http://stackoverflow.com/questions/5905492/dynamic-function-name-in-javascript
var drawCommand = ( new Function( 'state', 'return function ' + functionName + '( state ) { ' + autogeneratedFunction + '}' ) )();
/*jshint evil: false */
this._cacheDrawCall[ prgID ] = drawCommand;
return drawCommand;
};
} )(),
drawImplementation: function ( state ) {
var program = state.getLastProgramApplied();
var prgID = program.getInstanceID();
var cachedDraw = this._cacheDrawCall[ prgID ];
// most of the time we should use vao
if ( this._extVAO && !this._vao[ prgID ] ) state.setVertexArrayObject( null );
if ( cachedDraw === undefined ) {
if ( !this._primitives.length ) return;
// no cache for this combination of vertex attributes
// compute new Draw Call
if ( this._extVAO === undefined && Geometry.enableVAO ) { // will be null if not supported
var extVAO = WebGLCaps.instance( state.getGraphicContext() ).getWebGLExtension( 'OES_vertex_array_object' );
this._extVAO = extVAO;
}
cachedDraw = this.generateDrawCommand( state, program, prgID );
}
cachedDraw.call( this, state );
},
setBound: function ( bb ) {
this._boundingBox = bb;
this._boundingBoxComputed = true;
},
computeBoundingBox: function ( boundingBox ) {
boundingBox.init();
var vertexArray = this.getVertexAttributeList().Vertex;
if ( vertexArray && vertexArray.getElements() && vertexArray.getItemSize() > 2 ) {
var vertexes = vertexArray.getElements();
var itemSize = vertexArray.getItemSize();
var min = boundingBox.getMin();
var max = boundingBox.getMax();
var minx = min[ 0 ];
var miny = min[ 1 ];
var minz = min[ 2 ];
var maxx = max[ 0 ];
var maxy = max[ 1 ];
var maxz = max[ 2 ];
// if the box is un-initialized min=Inf and max=-Inf
// we can't simply write if(x > min) [...] else (x < max) [...]
// most of the time the else condition is run so it's a kinda useless
// optimization anyway
for ( var idx = 0, l = vertexes.length; idx < l; idx += itemSize ) {
var v1 = vertexes[ idx ];
var v2 = vertexes[ idx + 1 ];
var v3 = vertexes[ idx + 2 ];
if ( v1 < minx ) minx = v1;
if ( v1 > maxx ) maxx = v1;
if ( v2 < miny ) miny = v2;
if ( v2 > maxy ) maxy = v2;
if ( v3 < minz ) minz = v3;
if ( v3 > maxz ) maxz = v3;
}
min[ 0 ] = minx;
min[ 1 ] = miny;
min[ 2 ] = minz;
max[ 0 ] = maxx;
max[ 1 ] = maxy;
max[ 2 ] = maxz;
}
return boundingBox;
},
computeBoundingSphere: function ( boundingSphere ) {
boundingSphere.init();
var bb = this.getBoundingBox();
boundingSphere.expandByBoundingBox( bb );
return boundingSphere;
}
} ), 'osg', 'Geometry' );
Geometry.appendVertexAttributeToList = function ( from, to, postfix ) {
var keys = window.Object.keys( from );
var key, keyPostFix;
for ( var i = 0, l = keys.length; i < l; i++ ) {
key = keys[ i ];
keyPostFix = key;
if ( postfix !== undefined )
keyPostFix += '_' + postfix;
to[ keyPostFix ] = from[ key ];
}
};
MACROUTILS.setTypeID( Geometry );
module.exports = Geometry;

Wyświetl plik

@ -1,241 +0,0 @@
'use strict';
var Notify = require( 'osg/notify' );
var MACROUTILS = require( 'osg/Utils' );
var Object = require( 'osg/Object' );
var ImageBitmap = window.ImageBitmap || function () {};
var ImageObject = function ( image ) {
Object.call( this );
this._imageObject = undefined;
this._url = undefined;
this._width = undefined;
this._height = undefined;
this._dirty = true;
this._mipmap = [];
if ( image ) {
this.setImage( image );
}
this._isGreyscale = undefined;
};
ImageObject.prototype = MACROUTILS.objectLibraryClass( MACROUTILS.objectInherit( Object.prototype, {
dirty: function () {
this._isGreyscale = undefined;
this._dirty = true;
},
isDirty: function () {
return this._dirty;
},
setDirty: function ( bool ) {
this._dirty = bool;
},
getImage: function () {
return ( this._imageObject instanceof ImageObject ) ? this._imageObject.getImage() : this._imageObject;
},
getURL: function () {
return this._url;
},
setURL: function ( url ) {
this._url = url;
},
useOrCreateImage: function ( img ) {
return ( img instanceof( ImageObject ) === false ) ? new ImageObject( img ) : img;
},
setImage: function ( img ) {
if ( !this._url && img && ( img.src || img.currentSrc ) ) {
// TODO what is currentSrc ?
this._url = img.src || img.currentSrc;
}
this._mipmap.length = 0;
// img can be an image or an array of image if specify the
// all mipmap levels
if ( Array.isArray( img ) ) {
for ( var i = 0, nbImg = img.length; i < nbImg; i++ ) {
this._mipmap.push( this.useOrCreateImage( img[ i ] ) );
}
this.setWidth( this._mipmap[ 0 ].getWidth() );
this.setHeight( this._mipmap[ 0 ].getHeight() );
} else {
this._mipmap.push( img );
}
this._imageObject = this._mipmap[ 0 ];
this.dirty();
},
isCanvas: function () {
return this.getImage() instanceof window.HTMLCanvasElement;
},
isBitmap: function () {
return this.getImage() instanceof ImageBitmap;
},
isVideo: function () {
return this.getImage() instanceof window.HTMLVideoElement;
},
isImage: function () {
return this.getImage() instanceof window.Image;
},
isTypedArray: function () {
var img = this.getImage();
return img instanceof Uint8Array || img instanceof Float32Array || img instanceof Uint16Array;
},
setWidth: function ( w ) {
this._width = w;
},
setHeight: function ( h ) {
this._height = h;
},
getWidth: function () {
var img = this.getImage();
if ( this.isImage() ) {
return img.naturalWidth;
} else if ( this.isVideo() ) {
return img.videoWidth;
} else if ( this.isCanvas() || this.isBitmap() ) {
return img.width;
}
return this._width;
},
getHeight: function () {
var img = this.getImage();
if ( this.isImage() ) {
return img.naturalHeight;
} else if ( this.isVideo() ) {
return img.videoHeight;
} else if ( this.isCanvas() || this.isBitmap() ) {
return img.height;
}
return this._height;
},
isGreyscale: function ( nbSamples ) {
if ( this._isGreyscale !== undefined )
return this._isGreyscale;
if ( this._imageObject !== undefined && this.isReady() && this._isGreyscale === undefined ) {
var canvas = this._imageObject;
if ( !this.isCanvas() ) {
canvas = document.createElement( 'canvas' );
}
var ctx = canvas.getContext( '2d' );
canvas.width = this._imageObject.width;
canvas.height = this._imageObject.height;
ctx.drawImage( this._imageObject, 0, 0 );
var sampleX, sampleY;
// cap sample if needed
if ( !nbSamples ) {
sampleX = canvas.width;
sampleY = canvas.height;
}
if ( nbSamples > 0 ) {
nbSamples = Math.min( Math.min( canvas.width, canvas.height ), nbSamples );
sampleX = sampleY = nbSamples;
}
var isGreyscale = true;
var xFactor = canvas.width / ( sampleX );
var yFactor = canvas.height / ( sampleY );
for ( var i = 0; i < sampleX; i++ ) {
for ( var j = 0; j < sampleY; j++ ) {
var x = Math.floor( xFactor * ( i + 0.5 ) ),
y = Math.floor( yFactor * ( j + 0.5 ) );
var data = ctx.getImageData( x, y, 1, 1 ).data;
if ( !( data[ 0 ] === data[ 1 ] && data[ 0 ] === data[ 2 ] ) ) {
isGreyscale = false;
break;
}
}
}
this._isGreyscale = isGreyscale;
}
return this._isGreyscale;
},
isReady: function () {
// image is a osgImage
if ( this._imageObject && this._imageObject instanceof ImageObject ) {
return this._imageObject.isReady();
}
// image are ready for static data
if ( this.isCanvas() || this.isTypedArray() || this.isBitmap() ) {
return true;
}
if ( this.isImage() ) {
var image = this.getImage();
if ( image.complete ) {
if ( image.naturalWidth !== undefined && image.naturalWidth === 0 ) {
return false;
}
return true;
}
}
if ( this.isVideo() ) {
if ( this.getWidth() !== 0 ) return true;
}
// here means we have something but we don't know what
// Check if the object is not a image
// by "feature" detect it
var imageTry = this.getImage();
if ( imageTry.complete ) {
if ( imageTry.naturalWidth !== undefined && imageTry.naturalWidth === 0 ) {
return false;
}
return true;
}
// It's not something we recognise
/*develblock:start*/
Notify.warn( 'Warning can\'t detect image object ' );
/*develblock:end*/
return false;
},
getMipmap: function () {
return this._mipmap;
},
hasMipmap: function () {
return this._mipmap.length > 1;
},
release: function () {
this._mipmap.length = 0;
this._imageObject = undefined;
}
} ), 'osg', 'Image' );
MACROUTILS.setTypeID( ImageObject );
module.exports = ImageObject;

Wyświetl plik

@ -1,68 +0,0 @@
'use strict';
var P = require( 'bluebird' );
var MACROUTILS = require( 'osg/Utils' );
var Image = require( 'osg/Image' );
var ImageStream = function ( video ) {
Image.call( this, video );
this._canPlayDefered = undefined;
};
ImageStream.PAUSE = 0;
ImageStream.PLAYING = 1;
ImageStream.prototype = MACROUTILS.objectLibraryClass( MACROUTILS.objectInherit( Image.prototype, {
isDirty: function () {
return this._status === ImageStream.PLAYING; // video is dirty if playing
},
setImage: function ( video ) {
Image.prototype.setImage.call( this, video );
this._status = ImageStream.STOP;
// event at the end of the stream
video.addEventListener( 'ended', function () {
if ( !this._imageObject.loop )
this.stop();
}.bind( this ), true );
this.dirty();
},
setLooping: function ( bool ) {
this._imageObject.loop = bool;
},
play: function () {
this._imageObject.play();
this._status = ImageStream.PLAYING;
},
stop: function () {
this._imageObject.pause();
this._status = ImageStream.PAUSE;
},
whenReady: function () {
if ( !this._imageObject ) {
return P.reject();
}
if ( !this._canPlayDefered ) {
this._canPlayDefered = P.defer();
this._imageObject.addEventListener( 'canplaythrough', this._canPlayDefered.resolve.bind( this._canPlayDefered, this ), true );
}
return this._canPlayDefered.promise;
}
} ), 'osg', 'ImageStream' );
MACROUTILS.setTypeID( ImageStream );
module.exports = ImageStream;

Wyświetl plik

@ -1,432 +0,0 @@
'use strict';
var MACROUTILS = require( 'osg/Utils' );
var vec3 = require( 'osg/glMatrix' ).vec3;
var BoundingBox = require( 'osg/BoundingBox' );
var TriangleIndexFunctor = require( 'osg/TriangleIndexFunctor' );
var PrimitiveSet = require( 'osg/primitiveSet' );
var KdTreeRayIntersector = require( 'osg/KdTreeRayIntersector' );
var KdTreeSphereIntersector = require( 'osg/KdTreeSphereIntersector' );
// **** GENERAL INFO ON KDTREE ****
// A KdTree is a Spatial Partitionning Tree (http://en.wikipedia.org/wiki/Space_partitioning)
// The type of tree is sort of defined by the splitting axis method:
// - Per Axis split (octree/ kdtree)
// - Arbritrary direction split (bsp)
// The algorithm used for splitting, the name for finding best split is 'Surface Area Heuristic (SAH)'
// Octree divide the space in 8 subspace (one box -> 8 sub boxes)
// whereas kdtree does it by splitting population number in two equal group
// Kd Tree http://en.wikipedia.org/wiki/K-d_tree
// a given set of points is sorted along one Axis (e.g. X).
// The sorted list is split at the median.
// The result are two sets, one for each half-space (left and right).
// Then, for the current node, the splitting-plane position (or the median-point) and depth is saved.
// Finally, if the point-set has more than n point and the tree depth is below m
// (with n,m chosen by the user, as build options), two child-nodes (L/R one for each point-set)
// are created which themselfs repeat the pocedure.
// The split-axis gets alternated at each depth, the split order is computed by checking the main
// bounding box the length of its axis
// **** GENERAL INFO ON KDTREE ****
// The KdTree implemented here is flattened, ie, a node and its children all lie in the same array
// The most important thing is the understanding of the variables first and second for each node
// Their semantic depend if the node is a leaf or not
// if it's a leaf :
// first and second defines a range in the triangles array (triangles in the cell)
// if it's not a leaf :
// - first and second respectively represents the left and right sub children
// We know that a node is a leaf if first is negative, in that case the range will be defined by
// [ -first - 1, -first-1 + second ]
var KdNode = function ( first, second ) {
this._bb = new BoundingBox();
this._first = first;
this._second = second;
// These variables represent the local clipped ray (for intersection test)
// They are mostly temporary because they are recomputed for each intersection test
this._nodeRayStart = vec3.create();
this._nodeRayEnd = vec3.create();
};
var BuildKdTree = function ( kdTree ) {
this._kdTree = kdTree;
this._bb = new BoundingBox();
this._primitiveIndices = null; // Uint32Array
this._centers = null; // Float32Array
this._axisOrder = vec3.create();
this._stackLength = 0;
};
BuildKdTree.prototype = {
build: function ( options, geom ) {
var targetTris = options._targetNumTrianglesPerLeaf;
var vertexAttrib = geom.getVertexAttributeList().Vertex;
if ( !vertexAttrib )
return false;
var vertices = vertexAttrib.getElements();
if ( !vertices )
return false;
var nbVertices = vertices.length / 3;
if ( nbVertices < targetTris )
return false;
this._bb.copy( geom.getBoundingBox() );
this._kdTree.setVertices( vertices );
this.computeDivisions( options );
options._numVerticesProcessed += nbVertices;
this.computeTriangles( geom );
var node = new KdNode( -1, this._primitiveIndices.length );
node._bb.copy( this._bb );
var nodeNum = this._kdTree.addNode( node );
var bb = new BoundingBox();
bb.copy( this._bb );
nodeNum = this.divide( options, bb, nodeNum, 0 );
// Here we re-order the triangle list so that we can have a flat tree
// _primitiveIndices is the ordered array of the triangle indices
var triangles = this._kdTree.getTriangles();
var primitives = this._primitiveIndices;
var nbPrimitives = primitives.length;
var triangleOrdered = new MACROUTILS.Uint32Array( triangles.length );
for ( var i = 0, j = 0; i < nbPrimitives; ++i, j += 3 ) {
var id = primitives[ i ] * 3;
triangleOrdered[ j ] = triangles[ id ];
triangleOrdered[ j + 1 ] = triangles[ id + 1 ];
triangleOrdered[ j + 2 ] = triangles[ id + 2 ];
}
this._kdTree.setTriangles( triangleOrdered );
return this._kdTree.getNodes().length > 0;
},
// The function first gather all the triangles of the geometry
// It then computes the centroid for each triangle and initialize
// of triangles indices that will refer to the main triangles array
computeTriangles: function ( geom ) {
var kdTree = this._kdTree;
var totalLenArray = 0;
var geomPrimitives = geom.primitives;
var nbPrimitives = geomPrimitives.length;
var i = 0;
for ( i = 0; i < nbPrimitives; i++ ) {
var prim = geomPrimitives[ i ];
var mode = prim.getMode();
// ignore points and line stuffs
if ( mode === PrimitiveSet.TRIANGLES )
totalLenArray += prim.getCount();
else if ( mode === PrimitiveSet.TRIANGLE_STRIP || mode === PrimitiveSet.TRIANGLE_FAN )
totalLenArray += ( prim.getCount() - 2 ) * 3;
}
var indices = new MACROUTILS.Uint32Array( totalLenArray );
var next = 0;
var cb = function ( i1, i2, i3 ) {
if ( i1 === i2 || i1 === i3 || i2 === i3 )
return;
indices[ next ] = i1;
indices[ next + 1 ] = i2;
indices[ next + 2 ] = i3;
next += 3;
};
var tif = new TriangleIndexFunctor();
tif.init( geom, cb );
tif.apply();
indices = indices.subarray( 0, next );
var nbTriangles = indices.length;
kdTree.setTriangles( indices );
var vertices = kdTree.getVertices();
this._centers = new MACROUTILS.Float32Array( nbTriangles );
var centers = this._centers;
this._primitiveIndices = new MACROUTILS.Uint32Array( nbTriangles / 3 );
var primitives = this._primitiveIndices;
var j = 0;
for ( i = 0, j = 0; i < nbTriangles; i += 3, ++j ) {
var iv0 = indices[ i ];
var iv1 = indices[ i + 1 ];
var iv2 = indices[ i + 2 ];
// discard degenerate points
if ( iv0 === iv1 || iv1 === iv2 || iv0 === iv2 )
return;
iv0 *= 3;
iv1 *= 3;
iv2 *= 3;
var v0x = vertices[ iv0 ];
var v0y = vertices[ iv0 + 1 ];
var v0z = vertices[ iv0 + 2 ];
var v1x = vertices[ iv1 ];
var v1y = vertices[ iv1 + 1 ];
var v1z = vertices[ iv1 + 2 ];
var v2x = vertices[ iv2 ];
var v2y = vertices[ iv2 + 1 ];
var v2z = vertices[ iv2 + 2 ];
var minx = Math.min( v0x, Math.min( v1x, v2x ) );
var miny = Math.min( v0y, Math.min( v1y, v2y ) );
var minz = Math.min( v0z, Math.min( v1z, v2z ) );
var maxx = Math.max( v0x, Math.max( v1x, v2x ) );
var maxy = Math.max( v0y, Math.max( v1y, v2y ) );
var maxz = Math.max( v0z, Math.max( v1z, v2z ) );
centers[ i ] = ( minx + maxx ) * 0.5;
centers[ i + 1 ] = ( miny + maxy ) * 0.5;
centers[ i + 2 ] = ( minz + maxz ) * 0.5;
primitives[ j ] = j;
}
},
computeDivisions: function ( options ) {
this._stackLength = options._maxNumLevels;
var max = this._bb._max;
var min = this._bb._min;
var dx = max[ 0 ] - min[ 0 ];
var dy = max[ 1 ] - min[ 1 ];
var dz = max[ 2 ] - min[ 2 ];
var axisOrder = this._axisOrder;
// We set the cutting order (longest edge aabb first)
axisOrder[ 0 ] = ( dx >= dy && dx >= dz ) ? 0 : ( dy >= dz ) ? 1 : 2;
axisOrder[ 2 ] = ( dx < dy && dx < dz ) ? 0 : ( dy < dz ) ? 1 : 2;
var sum = axisOrder[ 0 ] + axisOrder[ 2 ];
axisOrder[ 1 ] = sum === 3 ? 0 : sum === 2 ? 1 : 2;
},
// The core function of the kdtree building
// It checks if the node need to be subdivide or not
// If it decides it's a leaf, it computes the final bounding box of the node
// and it ends here
// If it's a node, then it puts the splitting axis position on the median population
// On the same time it reorder the triangle index array
divide: function ( options, bb, nodeIndex, level ) {
var kdTree = this._kdTree;
var primitives = this._primitiveIndices;
var nodes = kdTree.getNodes();
var node = nodes[ nodeIndex ];
var first = node._first;
var second = node._second;
var needToDivide = level < this._stackLength && first < 0 && second > options._targetNumTrianglesPerLeaf;
var istart = -first - 1;
var iend = istart + second - 1;
if ( !needToDivide ) {
if ( first < 0 ) {
// leaf is done, now compute bound on it.
this.computeNodeBox( node, istart, iend );
}
return nodeIndex;
}
if ( first >= 0 )
return nodeIndex;
// leaf node as first < 0, so look at dividing it.
var axis = this._axisOrder[ level % 3 ];
var originalMin = bb._min[ axis ];
var originalMax = bb._max[ axis ];
var mid = ( originalMin + originalMax ) * 0.5;
var originalLeftChildIndex = 0;
var originalRightChildIndex = 0;
var insitueDivision = false;
var left = istart;
var right = iend;
var centers = this._centers;
while ( left < right ) {
while ( left < right && ( centers[ primitives[ left ] * 3 + axis ] <= mid ) ) {
++left;
}
while ( left < right && ( centers[ primitives[ right ] * 3 + axis ] > mid ) ) {
--right;
}
if ( left < right ) {
var tmp = primitives[ left ];
primitives[ left ] = primitives[ right ];
primitives[ right ] = tmp;
++left;
--right;
}
}
if ( left === right ) {
if ( centers[ primitives[ left ] * 3 + axis ] <= mid ) ++left;
else --right;
}
if ( ( right - istart ) <= -1 ) {
originalLeftChildIndex = 0;
originalRightChildIndex = nodeIndex;
insitueDivision = true;
} else if ( ( iend - left ) <= -1 ) {
originalLeftChildIndex = nodeIndex;
originalRightChildIndex = 0;
insitueDivision = true;
} else {
originalLeftChildIndex = kdTree.addNode( new KdNode( -istart - 1, ( right - istart ) + 1 ) );
originalRightChildIndex = kdTree.addNode( new KdNode( -left - 1, ( iend - left ) + 1 ) );
}
var restore = bb._max[ axis ];
bb._max[ axis ] = mid;
var leftChildIndex = originalLeftChildIndex !== 0 ? this.divide( options, bb, originalLeftChildIndex, level + 1 ) : 0;
bb._max[ axis ] = restore;
restore = bb._min[ axis ];
bb._min[ axis ] = mid;
var rightChildIndex = originalRightChildIndex !== 0 ? this.divide( options, bb, originalRightChildIndex, level + 1 ) : 0;
bb._min[ axis ] = restore;
if ( !insitueDivision ) {
node._first = leftChildIndex;
node._second = rightChildIndex;
insitueDivision = true;
var bnode = node._bb;
bnode.init();
if ( leftChildIndex !== 0 ) bnode.expandByBoundingBox( nodes[ leftChildIndex ]._bb );
if ( rightChildIndex !== 0 ) bnode.expandByBoundingBox( nodes[ rightChildIndex ]._bb );
}
return nodeIndex;
},
// It computes the bounding box of the node so that the box contains all the triangles
// of the cell
computeNodeBox: function ( node, istart, iend ) {
var minx = Infinity,
miny = Infinity,
minz = Infinity,
maxx = -Infinity,
maxy = -Infinity,
maxz = -Infinity;
var triangles = this._kdTree.getTriangles();
var vertices = this._kdTree.getVertices();
var primitives = this._primitiveIndices;
for ( var i = istart; i <= iend; ++i ) {
var id = primitives[ i ] * 3;
var iv0 = triangles[ id ] * 3;
var iv1 = triangles[ id + 1 ] * 3;
var iv2 = triangles[ id + 2 ] * 3;
var v0x = vertices[ iv0 ];
var v0y = vertices[ iv0 + 1 ];
var v0z = vertices[ iv0 + 2 ];
var v1x = vertices[ iv1 ];
var v1y = vertices[ iv1 + 1 ];
var v1z = vertices[ iv1 + 2 ];
var v2x = vertices[ iv2 ];
var v2y = vertices[ iv2 + 1 ];
var v2z = vertices[ iv2 + 2 ];
minx = Math.min( minx, Math.min( v0x, Math.min( v1x, v2x ) ) );
miny = Math.min( miny, Math.min( v0y, Math.min( v1y, v2y ) ) );
minz = Math.min( minz, Math.min( v0z, Math.min( v1z, v2z ) ) );
maxx = Math.max( maxx, Math.max( v0x, Math.max( v1x, v2x ) ) );
maxy = Math.max( maxy, Math.max( v0y, Math.max( v1y, v2y ) ) );
maxz = Math.max( maxz, Math.max( v0z, Math.max( v1z, v2z ) ) );
}
var epsilon = 1E-6;
var bnode = node._bb;
var bmin = bnode._min;
var bmax = bnode._max;
bmin[ 0 ] = minx - epsilon;
bmin[ 1 ] = miny - epsilon;
bmin[ 2 ] = minz - epsilon;
bmax[ 0 ] = maxx + epsilon;
bmax[ 1 ] = maxy + epsilon;
bmax[ 2 ] = maxz + epsilon;
}
};
var KdTree = function () {
this._vertices = null;
this._kdNodes = [];
this._triangles = null; // Float32Array
};
KdTree.prototype = MACROUTILS.objectLibraryClass( {
getVertices: function () {
return this._vertices;
},
setVertices: function ( vertices ) {
this._vertices = vertices;
},
getNodes: function () {
return this._kdNodes;
},
getTriangles: function () {
return this._triangles;
},
setTriangles: function ( triangles ) {
this._triangles = triangles;
},
addNode: function ( node ) {
this._kdNodes.push( node );
return this._kdNodes.length - 1;
},
build: function ( options, geom ) {
var buildTree = new BuildKdTree( this );
return buildTree.build( options, geom );
},
intersectRay: function ( start, end, intersections, nodePath ) {
if ( this._kdNodes.length === 0 ) {
return false;
}
var numIntersectionsBefore = intersections.length;
if ( !this._rayIntersector ) {
this._rayIntersector = new KdTreeRayIntersector();
this._rayIntersector.setKdtree( this._vertices, this._kdNodes, this._triangles );
}
this._rayIntersector.init( intersections, start, end, nodePath );
this._rayIntersector.intersect( this.getNodes()[ 0 ], start, end );
return numIntersectionsBefore !== intersections.length;
},
intersectSphere: function ( center, radius, intersections, nodePath ) {
if ( this._kdNodes.length === 0 ) {
return false;
}
var numIntersectionsBefore = intersections.length;
if ( !this._sphereIntersector ) {
this._sphereIntersector = new KdTreeSphereIntersector();
this._sphereIntersector.setKdtree( this._vertices, this._kdNodes, this._triangles );
}
this._sphereIntersector.init( intersections, center, radius, nodePath );
this._sphereIntersector.intersect( this.getNodes()[ 0 ] );
return numIntersectionsBefore !== intersections.length;
}
}, 'osg', 'KdTree' );
module.exports = KdTree;

Wyświetl plik

@ -1,32 +0,0 @@
'use strict';
var MACROUTILS = require( 'osg/Utils' );
var NodeVisitor = require( 'osg/NodeVisitor' );
var KdTree = require( 'osg/KdTree' );
var KdTreeBuilder = function ( options ) {
NodeVisitor.call( this );
this._buildOptions = options !== undefined ? options : {
_numVerticesProcessed: 0,
_targetNumTrianglesPerLeaf: 50,
_maxNumLevels: 20
};
};
KdTreeBuilder.prototype = MACROUTILS.objectInherit( NodeVisitor.prototype, {
apply: function ( node ) {
if ( node.getShape ) {
var shape = node.getShape();
// we test if the kdTree is already built and if we can build it (null means we skip it)
if ( shape === undefined ) {
var kdTree = new KdTree();
if ( kdTree.build( this._buildOptions, node ) ) {
node.setShape( kdTree );
}
}
}
this.traverse( node );
}
} );
module.exports = KdTreeBuilder;

Wyświetl plik

@ -1,231 +0,0 @@
'use strict';
var vec3 = require( 'osg/glMatrix' ).vec3;
var TriangleIntersector = require( 'osgUtil/TriangleIntersector' );
var Notify = require( 'osg/notify' );
var KdTreeRayIntersector = function () {
if ( arguments && arguments.length ) {
Notify.warn( 'using ctor as initialiser is deprecated, use init(intersections, start, end, nodePath) and/or setKdtree: function ( vertices, nodes, triangles )' );
}
this._intersector = new TriangleIntersector();
this._dInvX = vec3.create();
this._dInvY = vec3.create();
this._dInvZ = vec3.create();
};
KdTreeRayIntersector.prototype = {
setKdtree: function ( vertices, nodes, triangles ) {
this._vertices = vertices;
this._kdNodes = nodes;
this._triangles = triangles;
},
init: ( function () {
var dir = vec3.create();
return function ( intersections, start, end, nodePath ) {
var d = vec3.sub( dir, end, start );
var len = vec3.length( d );
var invLen = 0.0;
if ( len !== 0.0 )
invLen = 1.0 / len;
vec3.scale( d, d, invLen );
if ( d[ 0 ] !== 0.0 ) vec3.scale( this._dInvX, d, 1.0 / d[ 0 ] );
if ( d[ 1 ] !== 0.0 ) vec3.scale( this._dInvY, d, 1.0 / d[ 1 ] );
if ( d[ 2 ] !== 0.0 ) vec3.scale( this._dInvZ, d, 1.0 / d[ 2 ] );
this._intersector._intersections = intersections;
this._intersector.setNodePath( nodePath );
this._intersector.set( start, end );
};
} )(),
// Classic ray intersection test
// If it's a leaf it does ray-triangles intersection with the triangles in the cell
// If it's not a leaf, it descend in the tree in a recursive way as long as the ray
// intersects the boundinbox of the nodes
intersect: ( function () {
var v0 = vec3.create();
var v1 = vec3.create();
var v2 = vec3.create();
return function ( node, ls, le ) {
var first = node._first;
var second = node._second;
var triangles = this._triangles;
var vertices = this._vertices;
if ( first < 0 ) {
// treat as a leaf
var istart = -first - 1;
var iend = istart + second;
var intersector = this._intersector;
intersector.index = istart;
for ( var i = istart; i < iend; ++i ) {
var id = i * 3;
var iv0 = triangles[ id ];
var iv1 = triangles[ id + 1 ];
var iv2 = triangles[ id + 2 ];
var j = iv0 * 3;
v0[ 0 ] = vertices[ j ];
v0[ 1 ] = vertices[ j + 1 ];
v0[ 2 ] = vertices[ j + 2 ];
j = iv1 * 3;
v1[ 0 ] = vertices[ j ];
v1[ 1 ] = vertices[ j + 1 ];
v1[ 2 ] = vertices[ j + 2 ];
j = iv2 * 3;
v2[ 0 ] = vertices[ j ];
v2[ 1 ] = vertices[ j + 1 ];
v2[ 2 ] = vertices[ j + 2 ];
intersector.intersect( v0, v1, v2, iv0, iv1, iv2 );
}
} else {
var s = node._nodeRayStart;
var e = node._nodeRayEnd;
var kNodes = this._kdNodes;
var kNode;
vec3.copy( s, ls );
vec3.copy( e, le );
if ( first > 0 ) {
kNode = kNodes[ first ];
if ( this.intersectAndClip( s, e, kNode._bb ) ) {
this.intersect( kNode, s, e );
}
}
if ( second > 0 ) {
vec3.copy( s, ls );
vec3.copy( e, le );
kNode = kNodes[ second ];
if ( this.intersectAndClip( s, e, kNode._bb ) ) {
this.intersect( kNode, s, e );
}
}
}
};
} )(),
// This method do 2 things
// It test if the ray intersects the node
// If so... it clip the ray so that the start and end point of the ray are
// snapped to the bounding box of the nodes
intersectAndClip: ( function () {
return function ( s, e, bb ) {
var min = bb._min;
var xmin = min[ 0 ];
var ymin = min[ 1 ];
var zmin = min[ 2 ];
var max = bb._max;
var xmax = max[ 0 ];
var ymax = max[ 1 ];
var zmax = max[ 2 ];
var invX = this._dInvX;
var invY = this._dInvY;
var invZ = this._dInvZ;
if ( s[ 0 ] <= e[ 0 ] ) {
// trivial reject of segment wholely outside.
if ( e[ 0 ] < xmin ) return false;
if ( s[ 0 ] > xmax ) return false;
if ( s[ 0 ] < xmin ) {
// clip s to xMin.
vec3.scaleAndAdd( s, s, invX, xmin - s[ 0 ] );
}
if ( e[ 0 ] > xmax ) {
// clip e to xMax.
vec3.scaleAndAdd( e, s, invX, xmax - s[ 0 ] );
}
} else {
if ( s[ 0 ] < xmin ) return false;
if ( e[ 0 ] > xmax ) return false;
if ( e[ 0 ] < xmin ) {
// clip s to xMin.
vec3.scaleAndAdd( e, s, invX, xmin - s[ 0 ] );
}
if ( s[ 0 ] > xmax ) {
// clip e to xMax.
vec3.scaleAndAdd( s, s, invX, xmax - s[ 0 ] );
}
}
// compate s and e against the yMin to yMax range of bb.
if ( s[ 1 ] <= e[ 1 ] ) {
// trivial reject of segment wholely outside.
if ( e[ 1 ] < ymin ) return false;
if ( s[ 1 ] > ymax ) return false;
if ( s[ 1 ] < ymin ) {
// clip s to yMin.
vec3.scaleAndAdd( s, s, invY, ymin - s[ 1 ] );
}
if ( e[ 1 ] > ymax ) {
// clip e to yMax.
vec3.scaleAndAdd( e, s, invY, ymax - s[ 1 ] );
}
} else {
if ( s[ 1 ] < ymin ) return false;
if ( e[ 1 ] > ymax ) return false;
if ( e[ 1 ] < ymin ) {
// clip s to yMin.
vec3.scaleAndAdd( e, s, invY, ymin - s[ 1 ] );
}
if ( s[ 1 ] > ymax ) {
// clip e to yMax.
vec3.scaleAndAdd( s, s, invY, ymax - s[ 1 ] );
}
}
// compate s and e against the zMin to zMax range of bb.
if ( s[ 2 ] <= e[ 2 ] ) {
// trivial reject of segment wholely outside.
if ( e[ 2 ] < zmin ) return false;
if ( s[ 2 ] > zmax ) return false;
if ( s[ 2 ] < zmin ) {
// clip s to zMin.
vec3.scaleAndAdd( s, s, invZ, zmin - s[ 2 ] );
}
if ( e[ 2 ] > zmax ) {
// clip e to zMax.
vec3.scaleAndAdd( e, s, invZ, zmax - s[ 2 ] );
}
} else {
if ( s[ 2 ] < zmin ) return false;
if ( e[ 2 ] > zmax ) return false;
if ( e[ 2 ] < zmin ) {
// clip s to zMin.
vec3.scaleAndAdd( e, s, invZ, zmin - s[ 2 ] );
}
if ( s[ 2 ] > zmax ) {
// clip e to zMax.
vec3.scaleAndAdd( s, s, invZ, zmax - s[ 2 ] );
}
}
return true;
};
} )()
};
module.exports = KdTreeRayIntersector;

Wyświetl plik

@ -1,91 +0,0 @@
'use strict';
var MACROUTILS = require( 'osg/Utils' );
var vec3 = require( 'osg/glMatrix' ).vec3;
var KdTreeRayIntersector = require( 'osg/KdTreeRayIntersector' );
var TriangleSphereIntersector = require( 'osgUtil/TriangleSphereIntersector' );
var KdTreeSphereIntersector = function () {
this._intersector = new TriangleSphereIntersector();
};
KdTreeSphereIntersector.prototype = MACROUTILS.objectInherit( KdTreeRayIntersector.prototype, {
init: function ( intersections, center, radius, nodePath ) {
this._intersector._intersections = intersections;
this._intersector.setNodePath( nodePath );
this._intersector.set( center, radius );
this._center = center;
this._radius = radius;
},
intersect: ( function () {
var v0 = vec3.create();
var v1 = vec3.create();
var v2 = vec3.create();
return function ( node ) {
var first = node._first;
var second = node._second;
var triangles = this._triangles;
var vertices = this._vertices;
if ( first < 0 ) {
// treat as a leaf
var istart = -first - 1;
var iend = istart + second;
var intersector = this._intersector;
intersector.index = istart;
for ( var i = istart; i < iend; ++i ) {
var id = i * 3;
var iv0 = triangles[ id ];
var iv1 = triangles[ id + 1 ];
var iv2 = triangles[ id + 2 ];
var j = iv0 * 3;
v0[ 0 ] = vertices[ j ];
v0[ 1 ] = vertices[ j + 1 ];
v0[ 2 ] = vertices[ j + 2 ];
j = iv1 * 3;
v1[ 0 ] = vertices[ j ];
v1[ 1 ] = vertices[ j + 1 ];
v1[ 2 ] = vertices[ j + 2 ];
j = iv2 * 3;
v2[ 0 ] = vertices[ j ];
v2[ 1 ] = vertices[ j + 1 ];
v2[ 2 ] = vertices[ j + 2 ];
intersector.intersect( v0, v1, v2, iv0, iv1, iv2 );
}
} else {
if ( first > 0 ) {
if ( this.intersectSphere( this._kdNodes[ first ]._bb ) ) {
this.intersect( this._kdNodes[ first ] );
}
}
if ( second > 0 ) {
if ( this.intersectSphere( this._kdNodes[ second ]._bb ) ) {
this.intersect( this._kdNodes[ second ] );
}
}
}
};
} )(),
intersectSphere: ( function () {
var tmp = vec3.create();
return function ( bb ) {
var r = this._radius + bb.radius();
return vec3.sqrDist( bb.center( tmp ), this._center ) <= r * r;
};
} )()
} );
module.exports = KdTreeSphereIntersector;

Wyświetl plik

@ -1,335 +0,0 @@
'use strict';
var MACROUTILS = require( 'osg/Utils' );
var StateAttribute = require( 'osg/StateAttribute' );
var Uniform = require( 'osg/Uniform' );
var mat4 = require( 'osg/glMatrix' ).mat4;
var vec3 = require( 'osg/glMatrix' ).vec3;
var vec4 = require( 'osg/glMatrix' ).vec4;
var Map = require( 'osg/Map' );
var Notify = require( 'osg/notify' );
// use the same kind of opengl lights
// see http://www.glprogramming.com/red/chapter05.html
var Light = function ( lightNum, disable ) {
StateAttribute.call( this );
var lightNumber = lightNum !== undefined ? lightNum : 0;
this._ambient = vec4.fromValues( 0.2, 0.2, 0.2, 1.0 );
this._diffuse = vec4.fromValues( 0.8, 0.8, 0.8, 1.0 );
this._specular = vec4.fromValues( 0.2, 0.2, 0.2, 1.0 );
// Default is directional as postion[3] is 0
this._position = vec4.fromValues( 0.0, 0.0, 1.0, 0.0 );
this._direction = vec3.fromValues( 0.0, 0.0, -1.0 );
// TODO : refactor lights management w=1.0 (isHemi), w=-1.0
// (isNotHemi) _ground contains the color but w says if it's
// an hemi or not
this._ground = vec4.fromValues( 0.2, 0.2, 0.2, -1.0 );
this._spotCutoff = 180.0;
this._spotBlend = 0.01;
// the array contains constant, linear, quadratic factor
this._attenuation = vec4.fromValues( 1.0, 0.0, 0.0, 0.0 );
this._lightUnit = lightNumber;
this._invMatrix = mat4.create();
this._enable = !disable;
};
Light.DIRECTION = 'DIRECTION';
Light.SPOT = 'SPOT';
Light.POINT = 'POINT';
Light.HEMI = 'HEMI';
Light.uniforms = {};
Light.prototype = MACROUTILS.objectLibraryClass( MACROUTILS.objectInherit( StateAttribute.prototype, {
attributeType: 'Light',
cloneType: function () {
return new Light( this._lightUnit, true );
},
getTypeMember: function () {
return this.attributeType + this._lightUnit;
},
getUniformName: function ( name ) {
var prefix = this.getType() + this._lightUnit.toString();
return 'u' + prefix + '_' + name;
},
getHash: function () {
return this.getTypeMember() + this.getLightType() + this.isEnabled().toString();
},
getOrCreateUniforms: function () {
var obj = Light;
var typeMember = this.getTypeMember();
if ( obj.uniforms[ typeMember ] ) return obj.uniforms[ typeMember ];
var uniforms = {
ambient: Uniform.createFloat4( this.getUniformName( 'ambient' ) ),
diffuse: Uniform.createFloat4( this.getUniformName( 'diffuse' ) ),
specular: Uniform.createFloat4( this.getUniformName( 'specular' ) ),
attenuation: Uniform.createFloat4( this.getUniformName( 'attenuation' ) ),
position: Uniform.createFloat4( this.getUniformName( 'position' ) ),
direction: Uniform.createFloat3( this.getUniformName( 'direction' ) ),
spotCutOff: Uniform.createFloat1( this.getUniformName( 'spotCutOff' ) ),
spotBlend: Uniform.createFloat1( this.getUniformName( 'spotBlend' ) ),
ground: Uniform.createFloat4( this.getUniformName( 'ground' ) ),
matrix: Uniform.createMatrix4( this.getUniformName( 'matrix' ) ),
invMatrix: Uniform.createMatrix4( this.getUniformName( 'invMatrix' ) )
};
obj.uniforms[ typeMember ] = new Map( uniforms );
return obj.uniforms[ typeMember ];
},
// enable / disable is not implemented in uniform
// we should add it
isEnabled: function () {
return this._enable;
},
setEnabled: function ( bool ) {
this._enable = bool;
},
// Deprecated methods, should be removed in the future
isEnable: function () {
Notify.log( 'Light.isEnable() is deprecated, use isEnabled instead' );
return this.isEnabled();
},
setEnable: function ( bool ) {
Notify.log( 'Light.setEnable() is deprecated, use setEnabled instead' );
this.setEnabled( bool );
},
// colors
setAmbient: function ( a ) {
vec4.copy( this._ambient, a );
},
getAmbient: function () {
return this._ambient;
},
setDiffuse: function ( a ) {
vec4.copy( this._diffuse, a );
},
getDiffuse: function () {
return this._diffuse;
},
setSpecular: function ( a ) {
vec4.copy( this._specular, a );
},
getSpecular: function () {
return this._specular;
},
// position, also used for directional light
// position[3] === 0 means directional
// see creating lightsources http://www.glprogramming.com/red/chapter05.html
setPosition: function ( a ) {
vec4.copy( this._position, a );
},
getPosition: function () {
return this._position;
},
// unused for directional
setDirection: function ( a ) {
vec3.copy( this._direction, a );
},
getDirection: function () {
return this._direction;
},
setSpotCutoff: function ( a ) {
this._spotCutoff = a;
},
getSpotCutoff: function () {
return this._spotCutoff;
},
setSpotBlend: function ( a ) {
this._spotBlend = a;
},
getSpotBlend: function () {
return this._spotBlend;
},
// set/get the color of the ground
setGround: function ( a ) {
vec3.copy( this._ground, a );
},
getGround: function () {
return this._ground;
},
// attenuation coeff
setConstantAttenuation: function ( value ) {
this._attenuation[ 0 ] = value;
},
getConstantAttenuation: function () {
return this._attenuation[ 0 ];
},
setLinearAttenuation: function ( value ) {
this._attenuation[ 1 ] = value;
},
getLinearAttenuation: function () {
return this._attenuation[ 1 ];
},
setQuadraticAttenuation: function ( value ) {
this._attenuation[ 2 ] = value;
},
getQuadraticAttenuation: function () {
return this._attenuation[ 2 ];
},
setLightType: function ( type ) {
if ( type === Light.DIRECTION )
return this.setLightAsDirection();
else if ( type === Light.SPOT )
return this.setLightAsSpot();
else if ( type === Light.HEMI )
return this.setLightAsHemi();
return this.setLightAsPoint();
},
getLightType: function () {
if ( this.isDirectionLight() )
return Light.DIRECTION;
else if ( this.isSpotLight() )
return Light.SPOT;
else if ( this.isHemiLight() )
return Light.HEMI;
return Light.POINT;
},
setLightAsSpot: function () {
vec4.set( this._position, 0.0, 0.0, 0.0, 1.0 );
vec3.set( this._direction, 0.0, 0.0, -1.0 );
this._ground[ 3 ] = -1.0;
this._spotCutoff = 90;
},
setLightAsPoint: function () {
vec4.set( this._position, 0.0, 0.0, 0.0, 1.0 );
vec3.set( this._direction, 0.0, 0.0, -1.0 );
this._ground[ 3 ] = -1.0;
},
setLightAsDirection: function () {
vec4.set( this._position, 0.0, 0.0, 1.0, 0.0 );
this._spotCutoff = 180;
this._ground[ 3 ] = -1.0;
},
setLightAsHemi: function () {
vec4.set( this._position, 0.0, 0.0, 1.0, 0.0 );
this._spotCutoff = 180;
this._ground[ 3 ] = 1.0;
},
setLightNumber: function ( unit ) {
this._lightUnit = unit;
},
getLightNumber: function () {
return this._lightUnit;
},
// internal helper
isSpotLight: function () {
return this._spotCutoff < 180.0;
},
isDirectionLight: function () {
return this._position[ 3 ] === 0.0 && this._ground[ 3 ] === -1.0;
},
isHemiLight: function () {
return this._ground[ 3 ] === 1.0;
},
// matrix is current model view, which can mean:
// world (node refAbsolute)
// world+camera (camera is refAbsolute)
// world+camera+camera+... (camera relative...)
applyPositionedUniform: function ( matrix ) {
var uniformMap = this.getOrCreateUniforms();
var matrixArray = uniformMap.matrix.getInternalArray();
var invMatrixArray = uniformMap.invMatrix.getInternalArray();
mat4.copy( matrixArray, matrix );
mat4.copy( invMatrixArray, matrix );
invMatrixArray[ 12 ] = 0.0;
invMatrixArray[ 13 ] = 0.0;
invMatrixArray[ 14 ] = 0.0;
mat4.invert( invMatrixArray, invMatrixArray );
mat4.transpose( invMatrixArray, invMatrixArray );
},
apply: function () {
if ( !this._enable ) return;
var uniformMap = this.getOrCreateUniforms();
uniformMap.position.setFloat4( this._position );
if ( this.isSpotLight() ) {
var spotsize = Math.cos( this._spotCutoff * Math.PI / 180.0 );
uniformMap.spotCutOff.setFloat( spotsize );
uniformMap.spotBlend.setFloat( ( 1.0 - spotsize ) * this._spotBlend );
uniformMap.direction.setFloat3( this._direction );
}
if ( this.isHemiLight() )
uniformMap.ground.setFloat4( this._ground );
uniformMap.attenuation.setFloat4( this._attenuation );
uniformMap.diffuse.setFloat4( this._diffuse );
uniformMap.specular.setFloat4( this._specular );
uniformMap.ambient.setFloat4( this._ambient );
}
} ), 'osg', 'Light' );
MACROUTILS.setTypeID( Light );
module.exports = Light;

Wyświetl plik

@ -1,53 +0,0 @@
'use strict';
var MACROUTILS = require( 'osg/Utils' );
var Node = require( 'osg/Node' );
var TransformEnums = require( 'osg/transformEnums' );
var vec3 = require( 'osg/glMatrix' ).vec3;
/**
* LightSource is a positioned node to use with StateAttribute Light
* @class LightSource
*/
var LightSource = function () {
Node.call( this );
this._light = undefined;
this._referenceFrame = TransformEnums.RELATIVE_RF;
};
/** @lends LightSource.prototype */
LightSource.prototype = MACROUTILS.objectLibraryClass( MACROUTILS.objectInherit( Node.prototype, {
getLight: function () {
return this._light;
},
setLight: function ( light ) {
this._light = light;
},
setReferenceFrame: function ( value ) {
this._referenceFrame = value;
},
getReferenceFrame: function () {
return this._referenceFrame;
},
computeBoundingSphere: ( function () {
var tmp = vec3.create();
return function ( bsphere ) {
Node.prototype.computeBoundingSphere.call( this, bsphere );
if ( this._light !== undefined && this._referenceFrame === TransformEnums.RELATIVE_RF ) {
var position = this._light.getPosition();
if ( position[ 3 ] !== 0.0 ) {
bsphere.expandByvec3( vec3.scale( tmp, position, 1.0 / position[ 3 ] ) );
}
}
return bsphere;
};
} )()
} ), 'osg', 'LightSource' );
MACROUTILS.setTypeID( LightSource );
module.exports = LightSource;

Wyświetl plik

@ -1,22 +0,0 @@
'use strict';
var MACROUTILS = require( 'osg/Utils' );
var StateAttribute = require( 'osg/StateAttribute' );
var LineWidth = function ( lineWidth ) {
StateAttribute.call( this );
this.lineWidth = 1.0;
if ( lineWidth !== undefined ) {
this.lineWidth = lineWidth;
}
};
LineWidth.prototype = MACROUTILS.objectLibraryClass( MACROUTILS.objectInherit( StateAttribute.prototype, {
attributeType: 'LineWidth',
cloneType: function () {
return new LineWidth();
},
apply: function ( state ) {
state.getGraphicContext().lineWidth( this.lineWidth );
}
} ), 'osg', 'LineWidth' );
module.exports = LineWidth;

Wyświetl plik

@ -1,177 +0,0 @@
'use strict';
var MACROUTILS = require( 'osg/Utils' );
var Node = require( 'osg/Node' );
var NodeVisitor = require( 'osg/NodeVisitor' );
var mat4 = require( 'osg/glMatrix' ).mat4;
var vec2 = require( 'osg/glMatrix' ).vec2;
var vec3 = require( 'osg/glMatrix' ).vec3;
var BoundingSphere = require( 'osg/BoundingSphere' );
/**
* Lod that can contains child node
* @class Lod
*/
var Lod = function () {
Node.call( this );
this._radius = -1;
this._range = [];
this._rangeMode = Lod.DISTANCE_FROM_EYE_POINT;
this._userDefinedCenter = [];
this._centerMode = Lod.USE_BOUNDING_SPHERE_CENTER;
};
Lod.DISTANCE_FROM_EYE_POINT = 0;
Lod.PIXEL_SIZE_ON_SCREEN = 1;
Lod.USE_BOUNDING_SPHERE_CENTER = 0;
Lod.USER_DEFINED_CENTER = 1;
Lod.UNION_OF_BOUNDING_SPHERE_AND_USER_DEFINED = 2;
/** @lends Lod.prototype */
Lod.prototype = MACROUTILS.objectLibraryClass( MACROUTILS.objectInherit( Node.prototype, {
// Functions here
getRadius: function () {
return this._radius;
},
/** Set the object-space reference radius of the volume enclosed by the LOD.
* Used to determine the bounding sphere of the LOD in the absence of any children.*/
setRadius: function ( radius ) {
this._radius = radius;
},
setCenter: function ( center ) {
if ( this._centerMode !== Lod.UNION_OF_BOUNDING_SPHERE_AND_USER_DEFINED )
this._centerMode = Lod.USER_DEFINED_CENTER;
this._userDefinedCenter = center;
},
getCenter: function () {
if ( ( this._centerMode === Lod.USER_DEFINED_CENTER ) || ( this._centerMode === Lod.UNION_OF_BOUNDING_SPHERE_AND_USER_DEFINED ) )
return this._userDefinedCenter;
else return this.getBound().center();
},
setCenterMode: function ( centerMode ) {
this._centerMode = centerMode;
},
computeBoundingSphere: function ( bsphere ) {
if ( this._centerMode === Lod.USER_DEFINED_CENTER && this._radius >= 0.0 ) {
bsphere.set( this._userDefinedCenter, this._radius );
return bsphere;
} else if ( this._centerMode === Lod.UNION_OF_BOUNDING_SPHERE_AND_USER_DEFINED && this._radius >= 0.0 ) {
bsphere.set( this._userDefinedCenter, this._radius );
var bs = new BoundingSphere();
bsphere.expandByBoundingSphere( Node.prototype.computeBoundingSphere.call( this, bs ) );
return bsphere;
} else {
Node.prototype.computeBoundingSphere.call( this, bsphere );
return bsphere;
}
},
projectBoundingSphere: ( function () {
// from http://www.iquilezles.org/www/articles/sphereproj/sphereproj.htm
// Sample code at http://www.shadertoy.com/view/XdBGzd?
var o = vec3.create();
return function ( sph, camMatrix, fle ) {
vec3.transformMat4( o, sph.center(), camMatrix );
var r2 = sph.radius2();
var z2 = o[ 2 ] * o[ 2 ];
var l2 = vec3.sqrLen( o );
var area = -Math.PI * fle * fle * r2 * Math.sqrt( Math.abs( ( l2 - r2 ) / ( r2 - z2 ) ) ) / ( r2 - z2 );
return area;
};
} )(),
setRangeMode: function ( mode ) {
//TODO: check if mode is correct
this._rangeMode = mode;
},
addChildNode: function ( node ) {
Node.prototype.addChild.call( this, node );
if ( this.children.length > this._range.length ) {
var r = [];
var max = 0.0;
if ( this._range.lenght > 0 )
max = this._range[ this._range.length - 1 ][ 1 ];
r.push( vec2.fromValues( max, max ) );
this._range.push( r );
}
return true;
},
addChild: function ( node, min, max ) {
Node.prototype.addChild.call( this, node );
if ( this.children.length > this._range.length ) {
var r = [];
r.push( vec2.fromValues( min, min ) );
this._range.push( r );
}
this._range[ this.children.length - 1 ][ 0 ] = min;
this._range[ this.children.length - 1 ][ 1 ] = max;
return true;
},
traverse: ( function () {
// avoid to generate variable on the heap to limit garbage collection
// instead create variable and use the same each time
var zeroVector = vec3.create();
var eye = vec3.create();
var viewModel = mat4.create();
return function ( visitor ) {
var traversalMode = visitor.traversalMode;
switch ( traversalMode ) {
case NodeVisitor.TRAVERSE_ALL_CHILDREN:
for ( var index = 0; index < this.children.length; index++ ) {
this.children[ index ].accept( visitor );
}
break;
case ( NodeVisitor.TRAVERSE_ACTIVE_CHILDREN ):
var requiredRange = 0;
var matrix = visitor.getCurrentModelViewMatrix();
mat4.invert( viewModel, matrix );
// Calculate distance from viewpoint
if ( this._rangeMode === Lod.DISTANCE_FROM_EYE_POINT ) {
vec3.transformMat4( eye, zeroVector, viewModel );
var d = vec3.distance( this.getBound().center(), eye );
requiredRange = d * visitor.getLODScale();
} else {
// Let's calculate pixels on screen
var projmatrix = visitor.getCurrentProjectionMatrix();
// focal lenght is the value stored in projmatrix[0]
requiredRange = this.projectBoundingSphere( this.getBound(), matrix, projmatrix[ 0 ] );
// Multiply by a factor to get the real area value
requiredRange = ( ( requiredRange * visitor.getViewport().width() * visitor.getViewport().width() ) * 0.25 ) / visitor.getLODScale();
}
var numChildren = this.children.length;
if ( this._range.length < numChildren ) numChildren = this._range.length;
for ( var j = 0; j < numChildren; ++j ) {
if ( this._range[ j ][ 0 ] <= requiredRange && requiredRange < this._range[ j ][ 1 ] ) {
this.children[ j ].accept( visitor );
}
}
break;
default:
break;
}
};
} )()
} ), 'osg', 'Lod' );
MACROUTILS.setTypeID( Lod );
module.exports = Lod;

Wyświetl plik

@ -1,67 +0,0 @@
'use strict';
var Map = function ( obj ) {
window.Object.defineProperty( this, '_dirty', {
configurable: true,
enumerable: false,
writable: true,
value: true
} );
window.Object.defineProperty( this, '_keys', {
configurable: true,
enumerable: false,
writable: true,
value: undefined
} );
if ( obj ) this.setMap( obj );
};
Map.prototype = {
getKeys: function () {
if ( this._dirty ) {
this._keys = window.Object.keys( this );
this._dirty = false;
}
return this._keys;
},
dirty: function () {
this._dirty = true;
},
remove: function ( key ) {
//this[ key ] = undefined;
delete this[ key ];
this.dirty();
this.getKeys();
},
setMap: function ( map ) {
var i, l;
// remove all
var keys = window.Object.keys( this );
if ( keys.length > 0 ) {
for ( i = 0, l = keys.length; i < l; i++ )
delete this[ keys[ i ] ];
}
// add new
keys = window.Object.keys( map );
if ( keys.length > 0 ) {
for ( i = 0, l = keys.length; i < l; i++ ) {
var key = keys[ i ];
this[ key ] = map[ key ];
}
}
this.dirty();
}
};
module.exports = Map;

Wyświetl plik

@ -1,108 +0,0 @@
'use strict';
var MACROUTILS = require( 'osg/Utils' );
var StateAttribute = require( 'osg/StateAttribute' );
var vec4 = require( 'osg/glMatrix' ).vec4;
var Uniform = require( 'osg/Uniform' );
var Map = require( 'osg/Map' );
// Define a material attribute
var Material = function () {
StateAttribute.call( this );
this._ambient = vec4.fromValues( 0.2, 0.2, 0.2, 1.0 );
this._diffuse = vec4.fromValues( 0.8, 0.8, 0.8, 1.0 );
this._specular = vec4.fromValues( 0.0, 0.0, 0.0, 1.0 );
this._emission = vec4.fromValues( 0.0, 0.0, 0.0, 1.0 );
this._shininess = 12.5;
};
Material.prototype = MACROUTILS.objectLibraryClass( MACROUTILS.objectInherit( StateAttribute.prototype, {
attributeType: 'Material',
cloneType: function () {
return new Material();
},
getParameterName: function ( name ) {
return 'u' + this.getType() + '_' + name;
},
getOrCreateUniforms: function () {
var obj = Material;
if ( obj.uniforms ) return obj.uniforms;
var uniformList = {
ambient: Uniform.createFloat4( 'uMaterialAmbient' ),
diffuse: Uniform.createFloat4( 'uMaterialDiffuse' ),
specular: Uniform.createFloat4( 'uMaterialSpecular' ),
emission: Uniform.createFloat4( 'uMaterialEmission' ),
shininess: Uniform.createFloat1( 'uMaterialShininess' )
};
obj.uniforms = new Map( uniformList );
return obj.uniforms;
},
setEmission: function ( a ) {
vec4.copy( this._emission, a );
},
getEmission: function () {
return this._emission;
},
setAmbient: function ( a ) {
vec4.copy( this._ambient, a );
},
getAmbient: function () {
return this._ambient;
},
setSpecular: function ( a ) {
vec4.copy( this._specular, a );
},
getSpecular: function () {
return this._specular;
},
setDiffuse: function ( a ) {
vec4.copy( this._diffuse, a );
},
getDiffuse: function () {
return this._diffuse;
},
setShininess: function ( a ) {
this._shininess = a;
},
getShininess: function () {
return this._shininess;
},
setTransparency: function ( a ) {
this._diffuse[ 3 ] = 1.0 - a;
},
getTransparency: function () {
return this._diffuse[ 3 ];
},
apply: function () {
var uniforms = this.getOrCreateUniforms();
uniforms.ambient.setFloat4( this._ambient );
uniforms.diffuse.setFloat4( this._diffuse );
uniforms.specular.setFloat4( this._specular );
uniforms.emission.setFloat4( this._emission );
uniforms.shininess.setFloat( this._shininess );
}
} ), 'osg', 'Material' );
module.exports = Material;

Wyświetl plik

@ -1 +0,0 @@
module.exports = require( 'osg/deprecated-MatrixVector/Matrix' );

Wyświetl plik

@ -1,45 +0,0 @@
'use strict';
var mat4 = require( 'osg/glMatrix' ).mat4;
/**
* Prevents Memory fragmentation, GC heavy usage
* using pre-allocated memory segment
* allowing reuse of memory
* @class MatrixMemoryPool
*/
var MatrixMemoryPool = function () {
this._stack = [ mat4.create() ];
this._current = 0;
};
/** @lends MatrixMemoryPool.prototype */
MatrixMemoryPool.prototype = {
// start reuse the stack
reset: function () {
this._current = 0;
},
get: function () {
var m = this._stack[ this._current++ ];
if ( this._current === this._stack.length ) {
this._stack.push( mat4.create() );
}
return m;
}
};
module.exports = MatrixMemoryPool;

Wyświetl plik

@ -1,56 +0,0 @@
'use strict';
var MACROUTILS = require( 'osg/Utils' );
var mat4 = require( 'osg/glMatrix' ).mat4;
var Transform = require( 'osg/Transform' );
var TransformEnums = require( 'osg/transformEnums' );
/**
* MatrixTransform is a Transform Node that can be customized with user matrix
* @class MatrixTransform
*/
var MatrixTransform = function () {
Transform.call( this );
this.matrix = mat4.create();
};
/** @lends MatrixTransform.prototype */
MatrixTransform.prototype = MACROUTILS.objectLibraryClass( MACROUTILS.objectInherit( Transform.prototype, {
getMatrix: function () {
return this.matrix;
},
setMatrix: function ( m ) {
this.matrix = m;
this.dirtyBound();
},
// local to "local world" (not Global World)
computeLocalToWorldMatrix: function ( matrix /*, nodeVisitor */ ) {
if ( this.referenceFrame === TransformEnums.RELATIVE_RF ) {
mat4.mul( matrix, matrix, this.matrix );
} else {
mat4.copy( matrix, this.matrix );
}
return true;
},
computeWorldToLocalMatrix: ( function () {
var minverse = mat4.create();
return function ( matrix /*, nodeVisitor */ ) {
mat4.invert( minverse, this.matrix );
if ( this.referenceFrame === TransformEnums.RELATIVE_RF ) {
mat4.mul( matrix, minverse, matrix );
} else { // absolute
mat4.copy( matrix, minverse );
}
return true;
};
} )()
} ), 'osg', 'MatrixTransform' );
MACROUTILS.setTypeID( MatrixTransform );
module.exports = MatrixTransform;

Wyświetl plik

@ -1,544 +0,0 @@
'use strict';
var MACROUTILS = require( 'osg/Utils' );
var Object = require( 'osg/Object' );
var BoundingBox = require( 'osg/BoundingBox' );
var BoundingSphere = require( 'osg/BoundingSphere' );
var StateSet = require( 'osg/StateSet' );
var NodeVisitor = require( 'osg/NodeVisitor' );
var Notify = require( 'osg/notify' );
var mat4 = require( 'osg/glMatrix' ).mat4;
var MatrixMemoryPool = require( 'osg/MatrixMemoryPool' );
var ComputeMatrixFromNodePath = require( 'osg/computeMatrixFromNodePath' );
var TransformEnums = require( 'osg/transformEnums' );
/**
* Node that can contains child node
* @class Node
*/
var Node = function () {
Object.call( this );
this.children = [];
this._parents = [];
/*jshint bitwise: false */
this.nodeMask = ~0;
/*jshint bitwise: true */
this._boundingSphere = new BoundingSphere();
this._boundingSphereComputed = false;
this._boundingBox = new BoundingBox();
this._boundingBoxComputed = false;
this._updateCallbacks = [];
this._cullCallback = undefined;
this._cullingActive = true;
this._numChildrenWithCullingDisabled = 0;
this._numChildrenRequiringUpdateTraversal = 0;
// it's a tmp object for internal use, do not use
this._tmpBox = new BoundingBox();
};
Node._reservedMatrixStack = new MatrixMemoryPool();
var nodeGetMat = function () {
var mat = Node._reservedMatrixStack.get.bind( Node._reservedMatrixStack );
return mat4.identity( mat );
};
/** @lends Node.prototype */
Node.prototype = MACROUTILS.objectLibraryClass( MACROUTILS.objectInherit( Object.prototype, {
/**
Return StateSet and create it if it does not exist yet
@type StateSet
*/
getOrCreateStateSet: function () {
if ( !this.stateset ) this.setStateSet( new StateSet() );
return this.stateset;
},
getStateSet: function () {
return this.stateset;
},
accept: function ( nv ) {
if ( nv.validNodeMask( this ) ) {
nv.pushOntoNodePath( this );
nv.apply( this );
nv.popFromNodePath();
}
},
dirtyBound: function () {
if ( this._boundingSphereComputed === true || this._boundingBoxComputed === true ) {
this._boundingSphereComputed = false;
this._boundingBoxComputed = false;
var parents = this._parents;
for ( var i = 0, l = parents.length; i < l; i++ ) {
parents[ i ].dirtyBound();
}
}
},
setNodeMask: function ( mask ) {
this.nodeMask = mask;
},
getNodeMask: function () {
return this.nodeMask;
},
setStateSet: function ( stateSet ) {
if ( this.stateset === stateSet ) return;
var deltaUpdate = 0;
if ( this.stateset ) {
if ( this.stateset.requiresUpdateTraversal() ) deltaUpdate--;
this.stateset.removeParent( this );
}
if ( stateSet ) {
stateSet.addParent( this );
if ( stateSet.requiresUpdateTraversal() ) ++deltaUpdate;
}
if ( deltaUpdate !== 0 )
this.setNumChildrenRequiringUpdateTraversal( this.getNumChildrenRequiringUpdateTraversal() + deltaUpdate );
this.stateset = stateSet;
},
_updateNumChildrenRequeringUpdateTraversal: function ( delta ) {
if ( this._numChildrenRequiringUpdateTraversal === 0 && this._parents.length ) {
// the number of callbacks has changed, need to pass this
// on to parents so they know whether app traversal is
// required on this subgraph.
for ( var i = 0, l = this._parents.length; i < l; i++ ) {
var parent = this._parents[ i ];
var num = parent.getNumChildrenRequiringUpdateTraversal();
parent.setNumChildrenRequiringUpdateTraversal( num + delta );
}
}
},
setNumChildrenRequiringUpdateTraversal: function ( num ) {
// if no changes just return.
if ( this._numChildrenRequiringUpdateTraversal === num ) return;
// note, if _updateCallback is set then the
// parents won't be affected by any changes to
// _numChildrenRequiringUpdateTraversal so no need to inform them.
if ( !this._updateCallbacks.length && this._parents.length ) {
// need to pass on changes to parents.
var delta = 0;
if ( this._numChildrenRequiringUpdateTraversal > 0 ) --delta;
if ( num > 0 ) ++delta;
if ( delta !== 0 ) {
// the number of callbacks has changed, need to pass this
// on to parents so they know whether app traversal is
// required on this subgraph.
var parents = this._parents;
for ( var i = 0, l = parents.length; i < l; i++ ) {
var parent = parents[ i ];
var parentNum = parent.getNumChildrenRequiringUpdateTraversal();
parent.setNumChildrenRequiringUpdateTraversal( parentNum + delta );
}
}
}
// finally update this objects value.
this._numChildrenRequiringUpdateTraversal = num;
},
getNumChildrenRequiringUpdateTraversal: function () {
return this._numChildrenRequiringUpdateTraversal;
},
/**
<p>
Set update node callback, called during update traversal.
The Object must have the following method
update(node, nodeVisitor) {}
note, callback is responsible for scenegraph traversal so
they must call traverse(node,nv) to ensure that the
scene graph subtree (and associated callbacks) are traversed.
</p>
<p>
Here a dummy UpdateCallback example
</p>
@example
var DummyUpdateCallback = function() {};
DummyUpdateCallback.prototype = {
update: function(node, nodeVisitor) {
return true;
}
};
@param Oject callback
*/
setUpdateCallback: function ( cb ) {
Notify.warn( 'deprecated use instead addUpdateCallback/removeUpdateCallback' );
if ( cb === this._updateCallbacks[ 0 ] || !cb ) return;
var hasExistingCallback = Boolean( this._updateCallbacks.length );
if ( !this._updateCallbacks.length )
this.addUpdateCallback( cb );
else
this._updateCallbacks[ 0 ] = cb;
if ( !hasExistingCallback )
this._updateNumChildrenRequeringUpdateTraversal( 1 );
},
/** Get update node callback, called during update traversal.
@type Oject
*/
getUpdateCallback: function () {
return this._updateCallbacks[ 0 ];
},
addUpdateCallback: function ( cb ) {
var hasExistingCallback = Boolean( this._updateCallbacks.length );
this._updateCallbacks.push( cb );
// send the signal on first add
if ( !hasExistingCallback )
this._updateNumChildrenRequeringUpdateTraversal( 1 );
},
removeUpdateCallback: function ( cb ) {
var arrayIdx = this._updateCallbacks.indexOf( cb );
if ( arrayIdx === -1 ) return;
this._updateCallbacks.splice( arrayIdx, 1 );
// send the signal when no more callback
if ( !this._updateCallbacks.length )
this._updateNumChildrenRequeringUpdateTraversal( -1 );
},
getUpdateCallbackList: function () {
return this._updateCallbacks;
},
/**
<p>
Set cull node callback, called during cull traversal.
The Object must have the following method
cull(node, nodeVisitor) {}
note, callback is responsible for scenegraph traversal so
they must return true to traverse.
</p>
<p>
Here a dummy CullCallback example
</p>
@example
var DummyCullCallback = function() {};
DummyCullCallback.prototype = {
cull: function(node, nodeVisitor) {
return true;
}
};
@param Oject callback
*/
setCullCallback: function ( cb ) {
this._cullCallback = cb;
},
getCullCallback: function () {
return this._cullCallback;
},
hasChild: function ( child ) {
for ( var i = 0, l = this.children.length; i < l; i++ ) {
if ( this.children[ i ] === child ) {
return true;
}
}
return false;
},
addChild: function ( child ) {
if ( this.children.indexOf( child ) !== -1 ) return undefined;
this.children.push( child );
child.addParent( this );
this.dirtyBound();
// could now require app traversal thanks to the new subgraph,
// so need to check and update if required.
if ( child.getNumChildrenRequiringUpdateTraversal() > 0 ||
child.getUpdateCallbackList().length ) {
this.setNumChildrenRequiringUpdateTraversal(
this.getNumChildrenRequiringUpdateTraversal() + 1
);
}
return child;
},
getChildren: function () {
return this.children;
},
getNumChildren: function () {
return this.children.length;
},
getChild: function ( num ) {
return this.children[ num ];
},
getParents: function () {
return this._parents;
},
addParent: function ( parent ) {
this._parents.push( parent );
},
removeParent: function ( parent ) {
var idx = this._parents.indexOf( parent );
if ( idx === -1 ) return;
this._parents.splice( idx, 1 );
},
removeChildren: function () {
var children = this.children;
var nbChildren = children.length;
if ( !nbChildren ) return;
var updateCallbackRemoved = 0;
for ( var i = 0; i < nbChildren; i++ ) {
var child = children[ i ];
child.removeParent( this );
if ( child.getNumChildrenRequiringUpdateTraversal() > 0 || child.getUpdateCallbackList().length ) ++updateCallbackRemoved;
}
children.length = 0;
if ( updateCallbackRemoved )
this.setNumChildrenRequiringUpdateTraversal( this.getNumChildrenRequiringUpdateTraversal() - updateCallbackRemoved );
this.dirtyBound();
},
// preserve order
removeChild: function ( child ) {
var children = this.children;
var id = children.indexOf( child );
if ( id === -1 ) return;
child.removeParent( this );
children.splice( id, 1 );
if ( child.getNumChildrenRequiringUpdateTraversal() > 0 || child.getUpdateCallbackList().length )
this.setNumChildrenRequiringUpdateTraversal( this.getNumChildrenRequiringUpdateTraversal() - 1 );
},
traverse: function ( visitor ) {
var children = this.children;
for ( var i = 0, l = children.length; i < l; i++ ) {
var child = children[ i ];
child.accept( visitor );
}
},
ascend: function ( visitor ) {
var parents = this._parents;
for ( var i = 0, l = parents.length; i < l; i++ ) {
var parent = parents[ i ];
parent.accept( visitor );
}
},
getBoundingBox: function () {
if ( !this._boundingBoxComputed ) {
this.computeBoundingBox( this._boundingBox );
this._boundingBoxComputed = true;
}
return this._boundingBox;
},
computeBoundingBox: function ( bbox ) {
// circular dependency... not sure if the global visitor instance should be instancied here
var ComputeBoundsVisitor = require( 'osg/ComputeBoundsVisitor' );
var cbv = ComputeBoundsVisitor.instance = ComputeBoundsVisitor.instance || new ComputeBoundsVisitor();
cbv.setNodeMaskOverride( ~0x0 ); // traverse everything to be consistent with computeBoundingSphere
cbv.reset();
cbv.apply( this );
bbox.copy( cbv.getBoundingBox() );
return bbox;
},
getBoundingSphere: function () {
return this.getBound();
},
getBound: function () {
if ( !this._boundingSphereComputed ) {
this.computeBoundingSphere( this._boundingSphere );
this._boundingSphereComputed = true;
}
return this._boundingSphere;
},
computeBoundingSphere: function ( bSphere ) {
var children = this.children;
var l = children.length;
bSphere.init();
if ( l === 0 ) return bSphere;
var cc, i;
var bb = this._tmpBox;
bb.init();
for ( i = 0; i < l; i++ ) {
cc = children[ i ];
if ( cc.referenceFrame !== TransformEnums.ABSOLUTE_RF ) {
bb.expandByBoundingSphere( cc.getBound() );
}
}
if ( !bb.valid() ) return bSphere;
bSphere.set( bb.center( bSphere.center() ), 0.0 );
for ( i = 0; i < l; i++ ) {
cc = children[ i ];
if ( cc.referenceFrame !== TransformEnums.ABSOLUTE_RF ) {
bSphere.expandRadiusBySphere( cc.getBound() );
}
}
return bSphere;
},
// matrixCreate allow user handling of garbage collection of matrices
getWorldMatrices: ( function () {
var CollectParentPaths = function () {
this.nodePaths = [];
this.halt = undefined;
NodeVisitor.call( this, NodeVisitor.TRAVERSE_PARENTS );
};
CollectParentPaths.prototype = MACROUTILS.objectInherit( NodeVisitor.prototype, {
reset: function () {
this.nodePath.length = 0;
this.nodePaths.length = 0;
},
apply: function ( node ) {
if ( node._parents.length === 0 || node === this.halt || node.referenceFrame === TransformEnums.ABSOLUTE_RF ) {
// copy
this.nodePaths.push( this.nodePath.slice( 0 ) );
} else {
this.traverse( node );
}
}
} );
var collected = new CollectParentPaths();
collected.setNodeMaskOverride( ~0x0 ); // traverse everything
return function computeLocalToWorldList( halt, matrixCreate ) {
collected.reset();
collected.halt = halt;
this.accept( collected );
var matrixList = [];
var matrixGenerator = matrixCreate || mat4.create;
for ( var i = 0, l = collected.nodePaths.length; i < l; i++ ) {
var np = collected.nodePaths[ i ];
var m = matrixGenerator();
if ( np.length !== 0 ) {
ComputeMatrixFromNodePath.computeLocalToWorld( np, true, m );
}
matrixList.push( m );
}
return matrixList;
};
} )(),
// same as getWorldMatrices GC: Perf WIN
getWorldMatrix: function ( halt, matrix ) {
// pass allocator on master
var matrixList = this.getWorldMatrices( halt, nodeGetMat );
if ( matrixList.length === 0 ) {
mat4.identity( matrix );
} else {
mat4.copy( matrix, matrixList[ 0 ] );
}
Node._reservedMatrixStack.reset();
return matrix;
},
setCullingActive: function ( value ) {
if ( this._cullingActive === value ) return;
if ( this._numChildrenWithCullingDisabled === 0 && this._parents.length > 0 ) {
var delta = 0;
if ( !this._cullingActive ) --delta;
if ( !value ) ++delta;
if ( delta !== 0 ) {
for ( var i = 0, k = this._parents.length; i < k; i++ ) {
this._parents[ i ].setNumChildrenWithCullingDisabled( this._parents[ i ].getNumChildrenWithCullingDisabled() + delta );
}
}
}
this._cullingActive = value;
},
getCullingActive: function () {
return this._cullingActive;
},
isCullingActive: function () {
return this._numChildrenWithCullingDisabled === 0 && this._cullingActive && this.getBound().valid();
},
setNumChildrenWithCullingDisabled: function ( num ) {
if ( this._numChildrenWithCullingDisabled === num ) return;
if ( this._cullingActive && this._parents.length > 0 ) {
var delta = 0;
if ( this._numChildrenWithCullingDisabled > 0 ) --delta;
if ( num > 0 ) ++delta;
if ( delta !== 0 ) {
for ( var i = 0, k = this._parents.length; i < k; i++ ) {
this._parents[ i ].setNumChildrenWithCullingDisabled( this._parents[ i ].getNumChildrenWithCullingDisabled() + delta );
}
}
}
this._numChildrenWithCullingDisabled = num;
},
getNumChildrenWithCullingDisabled: function () {
return this._numChildrenWithCullingDisabled;
},
releaseGLObjects: function () {
if ( this.stateset !== undefined ) this.stateset.releaseGLObjects();
}
} ), 'osg', 'Node' );
MACROUTILS.setTypeID( Node );
module.exports = Node;

Wyświetl plik

@ -1,144 +0,0 @@
'use strict';
var NodeVisitor = function ( traversalMode ) {
/*jshint bitwise: false */
this.traversalMask = ~0x0;
/*jshint bitwise: true */
this.nodeMaskOverride = 0;
this.traversalMode = traversalMode;
if ( traversalMode === undefined ) {
this.traversalMode = NodeVisitor.TRAVERSE_ALL_CHILDREN;
}
this.nodePath = [];
this.visitorType = NodeVisitor.NODE_VISITOR;
this._databaseRequestHandler = undefined;
this._frameStamp = undefined;
this.traverse = NodeVisitor._traversalFunctions[ this.traversalMode ];
this.pushOntoNodePath = NodeVisitor._pushOntoNodePath[ this.traversalMode ];
this.popFromNodePath = NodeVisitor._popFromNodePath[ this.traversalMode ];
};
//NodeVisitor.TRAVERSE_NONE = 0;
NodeVisitor.TRAVERSE_PARENTS = 1;
NodeVisitor.TRAVERSE_ALL_CHILDREN = 2;
NodeVisitor.TRAVERSE_ACTIVE_CHILDREN = 3;
NodeVisitor.NODE_VISITOR = 0;
NodeVisitor.UPDATE_VISITOR = 1;
NodeVisitor.CULL_VISITOR = 2;
// =================== Traversal functions ===============
var traverseParents = function traverseParents( node ) {
node.ascend( this );
};
var traverseChildren = function traverseAllChildren( node ) {
node.traverse( this );
};
// must be sync with TRAVERSE_ENUMS
NodeVisitor._traversalFunctions = [
undefined,
traverseParents,
traverseChildren,
traverseChildren
];
// =================== PushOntoNodePath functions ===============
var pushOntoNodePathParents = function ( node ) {
this.nodePath.unshift( node );
};
var pushOntoNodePathChildren = function ( node ) {
this.nodePath.push( node );
};
NodeVisitor._pushOntoNodePath = [
undefined,
pushOntoNodePathParents,
pushOntoNodePathChildren,
pushOntoNodePathChildren
];
// =================== PopOntoNodePath functions ===============
var popFromNodePathParents = function () {
return this.nodePath.shift();
};
var popFromNodePathChildren = function () {
this.nodePath.pop();
};
NodeVisitor._popFromNodePath = [
undefined,
popFromNodePathParents,
popFromNodePathChildren,
popFromNodePathChildren
];
NodeVisitor.prototype = {
reset: function () {
// to be used when you want to re-use a nv
this.nodePath.length = 0;
},
setFrameStamp: function ( frameStamp ) {
this._frameStamp = frameStamp;
},
getFrameStamp: function () {
return this._frameStamp;
},
setNodeMaskOverride: function ( m ) {
this.nodeMaskOverride = m;
},
getNodeMaskOverride: function () {
return this.nodeMaskOverride;
},
setTraversalMask: function ( m ) {
this.traversalMask = m;
},
getTraversalMask: function () {
return this.traversalMask;
},
getNodePath: function () {
return this.nodePath;
},
pushOntoNodePath: function ( node ) {
NodeVisitor._pushOntoNodePath[ this.traversalMode ].call( this, node );
},
popFromNodePath: function () {
NodeVisitor._popFromNodePath[ this.traversalMode ].call( this );
},
validNodeMask: function ( node ) {
var nm = node.getNodeMask();
/*jshint bitwise: false */
return ( ( this.traversalMask & ( this.nodeMaskOverride | nm ) ) !== 0 );
/*jshint bitwise: true */
},
apply: function ( node ) {
this.traverse( node );
},
traverse: function ( node ) {
NodeVisitor._traversalFunctions[ this.traversalMode ].call( this, node );
},
getVisitorType: function () {
return this.visitorType;
},
setDatabaseRequestHandler: function ( dbpager ) {
this._databaseRequestHandler = dbpager;
},
getDatabaseRequestHandler: function () {
return this._databaseRequestHandler;
}
};
module.exports = NodeVisitor;

Wyświetl plik

@ -1,53 +0,0 @@
'use strict';
var MACROUTILS = require( 'osg/Utils' );
/**
* Object class
* @class Object
*/
var Object = function () {
this._name = undefined;
this._userdata = undefined;
this._instanceID = Object.getInstanceID();
};
/** @lends Object.prototype */
Object.prototype = MACROUTILS.objectLibraryClass( {
// this method works only if constructor is set correctly
// see issue https://github.com/cedricpinson/osgjs/issues/494
cloneType: function () {
var Constructor = this.constructor;
return new Constructor();
},
getInstanceID: function () {
return this._instanceID;
},
setName: function ( name ) {
this._name = name;
},
getName: function () {
return this._name;
},
setUserData: function ( data ) {
this._userdata = data;
},
getUserData: function () {
return this._userdata;
}
}, 'osg', 'Object' );
// get an instanceID for each object
var instanceID = 0;
Object.getInstanceID = function () {
instanceID += 1;
return instanceID;
};
module.exports = Object;

Wyświetl plik

@ -1,54 +0,0 @@
'use strict';
var MACROUTILS = require( 'osg/Utils' );
var OptionsDefault = {
'antialias': true, // activate MSAA
//'overrideDevicePixelRatio': 1, // if specified override the device pixel ratio
'fullscreen': true,
'enableFrustumCulling': false,
'stats': false, // display canvas with stats for the viewer
'scrollwheel': true,
'webgl2': false
};
var Options = function () {
window.Object.keys( OptionsDefault ).forEach( function ( key ) {
this[ key ] = OptionsDefault[ key ];
}.bind( this ) );
};
Options.prototype = {
extend: function ( options ) {
MACROUTILS.objectMix( this, options );
return this;
},
get: function ( key ) {
return this[ key ];
},
getBoolean: function ( key ) {
var val = this.getString( key );
if ( val ) return ( val !== 'false' && val !== '0' );
return undefined;
},
getNumber: function ( key ) {
var val = this[ key ];
if ( val ) return Number( val );
return undefined;
},
getString: function ( key ) {
var val = this[ key ];
if ( val !== undefined ) return this[ key ].toString();
return undefined;
}
};
module.exports = Options;

Wyświetl plik

@ -1,244 +0,0 @@
'use strict';
var MACROUTILS = require( 'osg/Utils' );
var Lod = require( 'osg/Lod' );
var NodeVisitor = require( 'osg/NodeVisitor' );
var mat4 = require( 'osg/glMatrix' ).mat4;
var vec3 = require( 'osg/glMatrix' ).vec3;
/**
* PagedLOD that can contains paged child nodes
* @class PagedLod
*/
var PagedLOD = function () {
Lod.call( this );
this._perRangeDataList = [];
this._loading = false;
this._expiryTime = 0.0;
this._expiryFrame = 0;
this._centerMode = Lod.USER_DEFINED_CENTER;
this._frameNumberOfLastTraversal = 0;
this._databasePath = '';
this._numChildrenThatCannotBeExpired = 0;
};
/**
* PerRangeData utility structure to store per range values
* @class PerRangeData
*/
var PerRangeData = function () {
this.filename = '';
this.function = undefined;
this.loaded = false;
this.timeStamp = 0.0;
this.frameNumber = 0;
this.frameNumberOfLastTraversal = 0;
this.dbrequest = undefined;
};
/** @lends PagedLOD.prototype */
PagedLOD.prototype = MACROUTILS.objectLibraryClass( MACROUTILS.objectInherit( Lod.prototype, {
// Functions here
setRange: function ( childNo, min, max ) {
if ( childNo >= this._range.length ) {
var r = [];
r.push( [ min, min ] );
this._range.push( r );
}
this._range[ childNo ][ 0 ] = min;
this._range[ childNo ][ 1 ] = max;
},
setExpiryTime: function ( expiryTime ) {
this._expiryTime = expiryTime;
},
setDatabasePath: function ( path ) {
this._databasePath = path;
},
getDatabasePath: function () {
return this._databasePath;
},
setFileName: function ( childNo, filename ) {
// May we should expand the vector first?
if ( childNo >= this._perRangeDataList.length ) {
var rd = new PerRangeData();
rd.filename = filename;
this._perRangeDataList.push( rd );
} else {
this._perRangeDataList[ childNo ].filename = filename;
}
},
setFunction: function ( childNo, func ) {
if ( childNo >= this._perRangeDataList.length ) {
var rd = new PerRangeData();
rd.function = func;
this._perRangeDataList.push( rd );
} else {
this._perRangeDataList[ childNo ].function = func;
}
},
addChild: function ( node, min, max ) {
Lod.prototype.addChild.call( this, node, min, max );
this._perRangeDataList.push( new PerRangeData() );
},
addChildNode: function ( node ) {
Lod.prototype.addChildNode.call( this, node );
},
setFrameNumberOfLastTraversal: function ( frameNumber ) {
this._frameNumberOfLastTraversal = frameNumber;
},
getFrameNumberOfLastTraversal: function () {
return this._frameNumberOfLastTraversal;
},
setTimeStamp: function ( childNo, timeStamp ) {
this._perRangeDataList[ childNo ].timeStamp = timeStamp;
},
setFrameNumber: function ( childNo, frameNumber ) {
this._perRangeDataList[ childNo ].frameNumber = frameNumber;
},
setNumChildrenThatCannotBeExpired: function ( num ) {
this._numChildrenThatCannotBeExpired = num;
},
getNumChildrenThatCannotBeExpired: function () {
return this._numChildrenThatCannotBeExpired;
},
getDatabaseRequest: function ( childNo ) {
return this._perRangeDataList[ childNo ].dbrequest;
},
removeExpiredChildren: function ( expiryTime, expiryFrame, removedChildren ) {
if ( this.children.length <= this._numChildrenThatCannotBeExpired ) return;
var i = this.children.length - 1;
var timed, framed;
timed = this._perRangeDataList[ i ].timeStamp + this._expiryTime;
framed = this._perRangeDataList[ i ].frameNumber + this._expiryFrame;
if ( timed < expiryTime && framed < expiryFrame && ( this._perRangeDataList[ i ].filename.length > 0 ||
this._perRangeDataList[ i ].function !== undefined ) ) {
removedChildren.push( this.children[ i ] );
this.removeChild( this.children[ i ] );
this._perRangeDataList[ i ].loaded = false;
if ( this._perRangeDataList[ i ].dbrequest !== undefined ) {
this._perRangeDataList[ i ].dbrequest._groupExpired = true;
}
}
},
traverse: ( function () {
// avoid to generate variable on the heap to limit garbage collection
// instead create variable and use the same each time
var zeroVector = vec3.create();
var eye = vec3.create();
var viewModel = mat4.create();
return function ( visitor ) {
var traversalMode = visitor.traversalMode;
var updateTimeStamp = false;
if ( visitor.getVisitorType() === NodeVisitor.CULL_VISITOR ) {
this._frameNumberOfLastTraversal = visitor.getFrameStamp().getFrameNumber();
updateTimeStamp = true;
}
switch ( traversalMode ) {
case NodeVisitor.TRAVERSE_ALL_CHILDREN:
for ( var index = 0; index < this.children.length; index++ ) {
this.children[ index ].accept( visitor );
}
break;
case ( NodeVisitor.TRAVERSE_ACTIVE_CHILDREN ):
var requiredRange = 0;
// Calculate distance from viewpoint
var matrix = visitor.getCurrentModelViewMatrix();
mat4.invert( viewModel, matrix );
if ( this._rangeMode === Lod.DISTANCE_FROM_EYE_POINT ) {
vec3.transformMat4( eye, zeroVector, viewModel );
var d = vec3.distance( this.getBound().center(), eye );
requiredRange = d * visitor.getLODScale();
} else {
// Calculate pixels on screen
var projmatrix = visitor.getCurrentProjectionMatrix();
// focal lenght is the value stored in projmatrix[0]
requiredRange = this.projectBoundingSphere( this.getBound(), matrix, projmatrix[ 0 ] );
// Get the real area value and apply LODScale
requiredRange = ( ( requiredRange * visitor.getViewport().width() * visitor.getViewport().width() ) * 0.25 ) / visitor.getLODScale();
if ( requiredRange < 0 ) requiredRange = this._range[ this._range.length - 1 ][ 0 ];
}
var needToLoadChild = false;
var lastChildTraversed = -1;
for ( var j = 0; j < this._range.length; ++j ) {
if ( this._range[ j ][ 0 ] <= requiredRange && requiredRange < this._range[ j ][ 1 ] ) {
if ( j < this.children.length ) {
if ( updateTimeStamp ) {
this._perRangeDataList[ j ].timeStamp = visitor.getFrameStamp().getSimulationTime();
this._perRangeDataList[ j ].frameNumber = visitor.getFrameStamp().getFrameNumber();
}
this.children[ j ].accept( visitor );
lastChildTraversed = j;
} else {
needToLoadChild = true;
}
}
}
if ( needToLoadChild ) {
var numChildren = this.children.length;
if ( numChildren > 0 && ( ( numChildren - 1 ) !== lastChildTraversed ) ) {
if ( updateTimeStamp ) {
this._perRangeDataList[ numChildren - 1 ].timeStamp = visitor.getFrameStamp().getSimulationTime();
this._perRangeDataList[ numChildren - 1 ].frameNumber = visitor.getFrameStamp().getFrameNumber();
}
this.children[ numChildren - 1 ].accept( visitor );
}
// now request the loading of the next unloaded child.
if ( numChildren < this._perRangeDataList.length ) {
// compute priority from where abouts in the required range the distance falls.
var priority = ( this._range[ numChildren ][ 0 ] - requiredRange ) / ( this._range[ numChildren ][ 1 ] - this._range[ numChildren ][ 0 ] );
if ( this._rangeMode === Lod.PIXEL_SIZE_ON_SCREEN ) {
priority = -priority;
}
// Here we do the request
var group = visitor.nodePath[ visitor.nodePath.length - 1 ];
if ( this._perRangeDataList[ numChildren ].loaded === false ) {
this._perRangeDataList[ numChildren ].loaded = true;
var dbhandler = visitor.getDatabaseRequestHandler();
this._perRangeDataList[ numChildren ].dbrequest = dbhandler.requestNodeFile( this._perRangeDataList[ numChildren ].function, this._databasePath + this._perRangeDataList[ numChildren ].filename, group, visitor.getFrameStamp().getSimulationTime(), priority );
} else {
// Update timestamp of the request.
if ( this._perRangeDataList[ numChildren ].dbrequest !== undefined ) {
this._perRangeDataList[ numChildren ].dbrequest._timeStamp = visitor.getFrameStamp().getSimulationTime();
this._perRangeDataList[ numChildren ].dbrequest._priority = priority;
} else {
// The DB request is undefined, so the DBPager was not accepting requests, we need to ask for the child again.
this._perRangeDataList[ numChildren ].loaded = false;
}
}
}
}
break;
default:
break;
}
};
} )()
} ), 'osg', 'PagedLOD' );
MACROUTILS.setTypeID( PagedLOD );
module.exports = PagedLOD;

Wyświetl plik

@ -1,143 +0,0 @@
'use strict';
var MACROUTILS = require( 'osg/Utils' );
var vec4 = require( 'osg/glMatrix' ).vec4;
var vec3 = require( 'osg/glMatrix' ).vec3;
/** @class Plane Operations */
var Plane = MACROUTILS.objectInherit( vec4, {
// Many case (frustum, convexity)
// needs to know where from a plane it stands,
// not just boolean intersection
INSIDE: 1,
INTERSECT: 2,
OUTSIDE: 3,
/* Transform the plane */
transformProvidingInverse: function () {
var iplane = Plane.create();
return function ( p, m ) {
//Matrix.transformVec4PostMult( matrix, plane, iplane );
var x = p[ 0 ];
var y = p[ 1 ];
var z = p[ 2 ];
var w = p[ 3 ];
iplane[ 0 ] = m[ 0 ] * x + m[ 1 ] * y + m[ 2 ] * z + m[ 3 ] * w;
iplane[ 1 ] = m[ 4 ] * x + m[ 5 ] * y + m[ 6 ] * z + m[ 7 ] * w;
iplane[ 2 ] = m[ 8 ] * x + m[ 9 ] * y + m[ 10 ] * z + m[ 11 ] * w;
iplane[ 3 ] = m[ 12 ] * x + m[ 13 ] * y + m[ 14 ] * z + m[ 15 ] * w;
Plane.normalizeEquation( iplane );
Plane.copy( iplane, p );
return p;
};
},
normalizeEquation: function ( plane ) {
// multiply the coefficients of the plane equation with a constant factor so that the equation a^2+b^2+c^2 = 1 holds.
var inv = 1.0 / Math.sqrt( plane[ 0 ] * plane[ 0 ] + plane[ 1 ] * plane[ 1 ] + plane[ 2 ] * plane[ 2 ] );
plane[ 0 ] *= inv;
plane[ 1 ] *= inv;
plane[ 2 ] *= inv;
plane[ 3 ] *= inv;
},
/*only the normal Component*/
getNormal: function ( plane, result ) {
result[ 0 ] = plane[ 0 ];
result[ 1 ] = plane[ 1 ];
result[ 2 ] = plane[ 2 ];
return result;
},
setNormal: function ( plane, normal ) {
plane[ 0 ] = normal[ 0 ];
plane[ 1 ] = normal[ 1 ];
plane[ 2 ] = normal[ 2 ];
},
/* only the distance getter*/
getDistance: function ( plane ) {
return plane[ 3 ];
},
setDistance: function ( plane, distance ) {
plane[ 3 ] = distance;
},
/* using the plane equation, compute distance to plane of a point*/
distanceToPlane: function ( plane, position ) {
return plane[ 0 ] * position[ 0 ] + plane[ 1 ] * position[ 1 ] + plane[ 2 ] * position[ 2 ] + plane[ 3 ];
},
intersectsOrContainsBoundingSphere: function ( plane, bSphere ) {
if ( !bSphere.valid() ) return Plane.OUTSIDE;
var position = bSphere.center();
var radius = bSphere.radius();
var d = this.distanceToPlane( plane, position );
if ( d < -radius ) {
return Plane.OUTSIDE;
} else if ( d <= radius ) {
return Plane.INTERSECT;
}
return Plane.INSIDE;
},
instersectsBoundingSphere: function ( plane, bSphere ) {
return this.intersectsOrContainsBoundingSphere( plane, bSphere ) === Plane.INTERSECT;
},
// absPlane optional paramter is an optimisation for the
// DOD case: on plane, many bounding boxes
intersectsOrContainsBoundingBox: function () {
var center = vec3.create();
var extent = vec3.create();
var absTemp = vec3.create();
return function ( plane, bbox, absPlane ) {
vec3.add( center, bbox.getMax(), bbox.getMin() );
vec3.scale( center, center, 0.5 );
vec3.sub( center, bbox.getMax(), bbox.getMin() );
vec3.scale( extent, extent, 0.5 );
var d = vec3.dot( center, plane );
if ( !absPlane ) {
absPlane = absTemp;
absPlane[ 0 ] = Math.abs( plane[ 0 ] );
absPlane[ 1 ] = Math.abs( plane[ 1 ] );
absPlane[ 2 ] = Math.abs( plane[ 2 ] );
}
var r = vec3.dot( extent, absPlane );
if ( d + r > 0 ) return Plane.INTERSECT; // partially inside
if ( d - r >= 0 ) return Plane.INSIDE; // fully inside
return Plane.OUTSIDE;
};
},
intersectsBoundingBox: function ( plane, bbox, absPlane ) {
return this.intersectsOrContainsBoundingBox( plane, bbox, absPlane ) === Plane.INTERSECT;
},
intersectOrContainsVertices: function ( plane, vertices ) {
var side = -1;
// all points must be on one side only
for ( var i = 0; i < vertices.length; i++ ) {
var d = this.distanceToPlane( plane, vertices[ i ] );
if ( d < 0.0 ) {
if ( side === 1 ) return Plane.INTERSECT;
side = 2;
} else if ( d > 0.0 ) {
if ( side === 2 ) return Plane.INTERSECT;
side = 1;
} else { //if ( d === 0.0 )
return Plane.INTERSECT;
}
}
return ( side > 0 ) ? Plane.INSIDE : Plane.OUTSIDE;
},
intersectVertices: function ( plane, vertices ) {
return this.intersectOrContainsVertices( plane, vertices ) === Plane.INTERSECT;
}
} );
module.exports = Plane;

Wyświetl plik

@ -1,349 +0,0 @@
'use strict';
var Object = require( 'osg/Object' );
var Plane = require( 'osg/Plane' );
var MACROUTILS = require( 'osg/Utils' );
var vec4 = require( 'osg/glMatrix' ).vec4;
/*jshint bitwise: false */
/**
* Polytope class for representing convex clipping volumes made up of a set of planes.
* When adding planes, their normals should point inwards (into the volume)
* @class Polytope
*/
var Polytope = function () {
this._clippingMask = 0x0;
this._planeList = [ Plane.create(), Plane.create(), Plane.create(), Plane.create(), Plane.create(), Plane.create() ];
this._vertexList = [];
// stack of clipping masks
this._maskStack = [];
// init with a clear mask
this._resultMask = 0;
this._maskStack.push( this._resultMask );
};
Polytope.prototype = MACROUTILS.objectInherit( Object.prototype, {
getPlanes: function () {
return this._planeList;
},
setPlanes: function ( pl ) {
this._planeList = pl;
this.setupMask();
},
clear: function () {
this._clippingMask = 0x0;
if ( this._planeList ) {
for ( var i = 0, l = this._planeList.length; i < l; ++i ) {
Plane.init( this._planeList[ i ] );
}
}
this._vertexList = [];
this.setupMask();
},
/** Create a Polytope which is a cube, centered at 0,0,0, with sides of 2 units.*/
setToUnitFrustum: function ( withNear, withFar ) {
if ( withNear === undefined ) withNear = true;
if ( withFar === undefined ) withFar = true;
this._planeList.length = 0;
this._planeList.push( vec4.set( Plane.create(), 1.0, 0.0, 0.0, 1.0 ) ); // left plane.
this._planeList.push( vec4.set( Plane.create(), -1.0, 0.0, 0.0, 1.0 ) ); // right plane.
this._planeList.push( vec4.set( Plane.create(), 0.0, 1.0, 0.0, 1.0 ) ); // bottom plane.
this._planeList.push( vec4.set( Plane.create(), 0.0, -1.0, 0.0, 1.0 ) ); // top plane.
if ( withNear ) this._planeList.push( vec4.set( Plane.create(), 0.0, 0.0, 1.0, 1.0 ) ); // near plane
if ( withFar ) this._planeList.push( vec4.set( Plane.create(), 0.0, 0.0, -1.0, 1.0 ) ); // far plane
this.setupMask();
},
/** Create a Polytope which is a equivalent to BoundingBox.*/
setToBoundingBox: function ( bb ) {
this._planeList.length = 0;
this._planeList.push( vec4.set( Plane.create(), 1.0, 0.0, 0.0, -bb.getMin()[ 0 ] ) ); // left plane.
this._planeList.push( vec4.set( Plane.create(), -1.0, 0.0, 0.0, bb.getMax()[ 0 ] ) ); // right plane.
this._planeList.push( vec4.set( Plane.create(), 0.0, 1.0, 0.0, -bb.getMin()[ 1 ] ) ); // bottom plane.
this._planeList.push( vec4.set( Plane.create(), 0.0, -1.0, 0.0, bb.getMax()[ 1 ] ) ); // top plane.
this._planeList.push( vec4.set( Plane.create(), 0.0, 0.0, 1.0, -bb.getMin()[ 2 ] ) ); // near plane
this._planeList.push( vec4.set( Plane.create(), 0.0, 0.0, -1.0, bb.getMax()[ 2 ] ) ); // far plane
this.setupMask();
},
setAndTransformProvidingInverse: function ( pt, matrix ) {
this._referenceVertexList = pt._referenceVertexList;
var resultMask = pt._maskStack[ this._maskStack.length - 1 ];
if ( resultMask === 0 ) {
this._maskStack[ this._maskStack.length - 1 ] = 0;
this._resultMask = 0;
this._planeList.length = 0;
return;
}
var selectorMask = 0x1;
var numActivePlanes = 0;
// count number of active planes.
var i;
for ( i = 0; i !== pt._planeList.length; ++i ) {
if ( resultMask & selectorMask ) ++numActivePlanes;
selectorMask <<= 1;
}
this._planeList.length = numActivePlanes;
this._resultMask = 0;
selectorMask = 0x1;
var index = 0;
for ( i = 0; i !== pt._planeList.length; ++i ) {
if ( resultMask & selectorMask ) {
this._planeList[ index ] = pt._planeList[ i ];
Plane.transformProvidingInverse( this._planeList[ index++ ], matrix );
this._resultMask = ( this._resultMask << 1 ) | 1;
}
selectorMask <<= 1;
}
this._maskStack[ this._maskStack.length - 1 ] = this._resultMask;
},
voidset: function ( pl ) {
this._planeList = pl;
this.setupMask();
},
add: function ( pl ) {
this._planeList.push( pl );
this.setupMask();
},
empty: function () {
return this._planeList.length === 0;
},
getPlaneList: function () {
return this._planeList;
},
setReferenceVertexList: function ( vertices ) {
this._referenceVertexList = vertices;
},
getReferenceVertexList: function () {
return this._referenceVertexList;
},
setupMask: function ( plength ) {
this._resultMask = 0;
var pMasklength = ( plength !== undefined ) ? plength : this._planeList.length;
for ( var i = 0; i < pMasklength; ++i ) {
this._resultMask = ( this._resultMask << 1 ) | 1;
}
this._maskStack = [];
this._maskStack.push( this._resultMask );
},
getCurrentMask: function () {
return this._maskStack[ this._maskStack.length - 1 ];
},
setResultMask: function ( mask ) {
this._resultMask = mask;
},
getResultMask: function () {
return this._resultMask;
},
getMaskStack: function () {
return this._maskStack;
},
// push but keep current mask
pushCurrentMask: function () {
this._maskStack.push( this._resultMask );
},
// pop and restore previous mask
popCurrentMask: function () {
return this._maskStack.pop();
},
/** Check whether a vertex is contained within clipping set.*/
containsVertex: function ( v ) {
if ( !this._maskStack[ this._maskStack.length - 1 ] ) return true;
var selectorMask = 0x1;
for ( var i = 0; i < this._planeList.length; ++i ) {
if ( ( this._maskStack[ this._maskStack.length - 1 ] & selectorMask ) && ( Plane.distanceToPlane( this._planeList[ i ], v ) < 0.0 ) ) {
return false;
}
selectorMask <<= 1;
}
return true;
},
/** Check whether any part of vertex list is contained within clipping set.*/
containsVertices: function ( vertices ) {
if ( !this._maskStack[ this._maskStack.length - 1 ] ) return true;
this._resultMask = this._maskStack[ this._maskStack.length - 1 ];
for ( var k = 0; k < vertices.length; ++k ) {
var v = vertices[ k ];
var outside = false;
var selectorMask = 0x1;
for ( var i = 0; !outside && i < this._planeList.length; ++i ) {
if ( ( this._maskStack[ this._maskStack.length - 1 ] & selectorMask ) && ( Plane.distanceToPlane( this._planeList[ i ], v ) < 0.0 ) ) {
outside = true;
}
selectorMask <<= 1;
}
if ( !outside ) return true;
}
return false;
},
/** Check whether any part of a bounding sphere is contained within clipping set.
Using a mask to determine which planes should be used for the check, and
modifying the mask to turn off planes which wouldn't contribute to clipping
of any internal objects. This feature is used in osgUtil::CullVisitor
to prevent redundant plane checking.*/
containsBoundingSphere: function ( bs ) {
if ( !this._maskStack[ this._maskStack.length - 1 ] || !bs.valid() ) return true;
this._resultMask = this._maskStack[ this._maskStack.length - 1 ];
var selectorMask = 0x1;
for ( var i = 0; i < this._planeList.length; ++i ) {
if ( this._resultMask & selectorMask ) {
var res = Plane.intersectsOrContainsBoundingSphere( this._planeList[ i ], bs );
if ( Plane.OUTSIDE === res ) {
// totally outside a clipping set.
return false;
} else if ( Plane.INSIDE === res ) {
// subsequent checks against this plane not required.
this._resultMask ^= selectorMask;
}
// else if ( Plane.INTERSECT === res ) { // last possible case
// can say nothing.
// subsequent checks against this plane needed.
//}
}
selectorMask <<= 1;
}
return true;
},
/** Check whether any part of a bounding box is contained within clipping set.
Using a mask to determine which planes should be used for the check, and
modifying the mask to turn off planes which wouldn't contribute to clipping
of any internal objects. This feature is used in osgUtil::CullVisitor
to prevent redundant plane checking.*/
containsBoundingBox: function ( bb ) {
if ( !this._maskStack[ this._maskStack.length - 1 ] ) return true;
this._resultMask = this._maskStack[ this._maskStack.length - 1 ];
var selectorMask = 0x1;
for ( var i = 0; i < this._planeList.length; ++i ) {
if ( this._resultMask & selectorMask ) {
var res = Plane.intersectsOrContainsBoundingBox( this._planeList[ i ], bb );
if ( Plane.OUTSIDE === res ) return false; // outside clipping set.
else if ( Plane.INSIDE === res ) this._resultMask ^= selectorMask; // subsequent checks against this plane not required.
// else if ( Plane.INTERSECT === res ) the last case need
// no test here but further tests
}
selectorMask <<= 1;
}
// correct frustum culling should double check now for
// http://www.iquilezles.org/www/articles/frustumcorrect/frustumcorrect.htm
// which is inside one "plane", but outside the convex plane intersection
return true;
},
/** Check whether all of vertex list is contained with clipping set.*/
containsAllOfVertices: function ( vertices ) {
if ( !this._maskStack[ this._maskStack.length - 1 ] ) return false;
this._resultMask = this._maskStack[ this._maskStack.length - 1 ];
var selectorMask = 0x1;
for ( var i = 0; i < this._planeList.length; ++i ) {
if ( this._resultMask & selectorMask ) {
var res = Plane.intersectsOrContainsVertices( this._planeList[ i ], vertices );
if ( res < 1 ) return false; // intersects, or is below plane.
this._resultMask ^= selectorMask; // subsequent checks against this plane not required.
}
selectorMask <<= 1;
}
return true;
},
/** Check whether the entire bounding sphere is contained within clipping set.*/
containsAllOfBoundingSphere: function ( bs ) {
if ( !this._maskStack[ this._maskStack.length - 1 ] ) return false;
this._resultMask = this._maskStack[ this._maskStack.length - 1 ];
var selectorMask = 0x1;
for ( var i = 0; i < this._planeList.length; ++i ) {
if ( this._resultMask & selectorMask ) {
var res = Plane.intersectsOrContainsBoundingSphere( this._planeList[ i ], bs );
if ( res < 1 ) return false; // intersects, or is below plane.
this._resultMask ^= selectorMask; // subsequent checks against this plane not required.
}
selectorMask <<= 1;
}
return true;
},
/** Check whether the entire bounding box is contained within clipping set.*/
containsAllOfBoundingBox: function ( bbox ) {
if ( !this._maskStack[ this._maskStack.length - 1 ] ) return false;
this._resultMask = this._maskStack[ this._maskStack.length - 1 ];
var selectorMask = 0x1;
for ( var i = 0; i < this._planeList.length; ++i ) {
if ( this._resultMask & selectorMask ) {
var res = Plane.intersectsOrContainsBoundingBox( this._planeList[ i ], bbox );
if ( res < 1 ) return false; // intersects, or is below plane.
this._resultMask ^= selectorMask; // subsequent checks against this plane not required.
}
selectorMask <<= 1;
}
return true;
},
/** Transform the clipping set by provide a pre inverted matrix.
* see transform for details. */
transformProvidingInverse: function ( matrix ) {
if ( !this._maskStack[ this._maskStack.length - 1 ] ) return;
this._resultMask = this._maskStack[ this._maskStack.length - 1 ];
var selectorMask = 0x1;
for ( var i = 0; i < this._planeList.length; ++i ) {
if ( this._resultMask & selectorMask ) {
Plane.transformProvidingInverse( this._planeList[ i ], matrix );
selectorMask <<= 1;
}
}
}
} );
/*jshint bitwise: true */
module.exports = Polytope;

Wyświetl plik

@ -1,387 +0,0 @@
'use strict';
var vec3 = require( 'osg/glMatrix' ).vec3;
var PrimitiveSet = require( 'osg/primitiveSet' );
var DrawElements = require( 'osg/DrawElements' );
var DrawArrays = require( 'osg/DrawArrays' );
/**
* PrimitiveFunctor emulates the TemplatePrimitiveFunctor class in OSG and can
* be used to get access to the vertices that compose the things drawn by osgjs.
* Feed it with a callback that will be called for geometry.
* The callback must be a closure and have the next structure:
*
* var myCallback = function( ) {
* return {
* operatorPoint : function ( v ) { }, // Do your point operations here
* operatorLine : function ( v1, v2 ){ }, // Do you line operations here
* operatorTriangle : function ( v1, v2, v3 ) { } // Do your triangle operations here
* }
* };
*
* Important Note: You should take into account that you are accesing the actual vertices of the primitive
* you might want to do a copy of these values in your callback to avoid to modify the primitive geometry
* @class PrimitiveFunctor
*/
var PrimitiveFunctor = function ( geom, cb, vertices ) {
this._geom = geom;
this._cb = cb;
this._vertices = vertices;
};
var functorDrawElements = PrimitiveFunctor.functorDrawElements = [];
var functorDrawArrays = PrimitiveFunctor.functorDrawArrays = [];
functorDrawElements[ PrimitiveSet.POINTS ] = ( function () {
var v = vec3.create();
return function ( offset, count, indexes, cb, vertices ) {
var end = offset + count;
for ( var i = offset; i < end; ++i ) {
var j = indexes[ i ] * 3;
v[ 0 ] = vertices[ j ];
v[ 1 ] = vertices[ j + 1 ];
v[ 2 ] = vertices[ j + 2 ];
cb.operatorPoint( v );
}
};
} )();
functorDrawElements[ PrimitiveSet.LINES ] = ( function () {
var v1 = vec3.create();
var v2 = vec3.create();
return function ( offset, count, indexes, cb, vertices ) {
var end = offset + count;
for ( var i = offset; i < end - 1; i += 2 ) {
var j = indexes[ i ] * 3;
v1[ 0 ] = vertices[ j ];
v1[ 1 ] = vertices[ j + 1 ];
v1[ 2 ] = vertices[ j + 2 ];
j = indexes[ i + 1 ] * 3;
v2[ 0 ] = vertices[ j ];
v2[ 1 ] = vertices[ j + 1 ];
v2[ 2 ] = vertices[ j + 2 ];
cb.operatorLine( v1, v2 );
}
};
} )();
functorDrawElements[ PrimitiveSet.LINE_STRIP ] = ( function () {
var v1 = vec3.create();
var v2 = vec3.create();
return function ( offset, count, indexes, cb, vertices ) {
var end = offset + count;
for ( var i = offset; i < end - 1; ++i ) {
var j = indexes[ i ] * 3;
v1[ 0 ] = vertices[ j ];
v1[ 1 ] = vertices[ j + 1 ];
v1[ 2 ] = vertices[ j + 2 ];
j = indexes[ i + 1 ] * 3;
v2[ 0 ] = vertices[ j ];
v2[ 1 ] = vertices[ j + 1 ];
v2[ 2 ] = vertices[ j + 2 ];
cb.operatorLine( v1, v2 );
}
};
} )();
functorDrawElements[ PrimitiveSet.LINE_LOOP ] = ( function () {
var v1 = vec3.create();
var v2 = vec3.create();
return function ( offset, count, indexes, cb, vertices ) {
var last = offset + count - 1;
for ( var i = offset; i < last; ++i ) {
var j = indexes[ i ] * 3;
v1[ 0 ] = vertices[ j ];
v1[ 1 ] = vertices[ j + 1 ];
v1[ 2 ] = vertices[ j + 2 ];
j = indexes[ i + 1 ] * 3;
v2[ 0 ] = vertices[ j ];
v2[ 1 ] = vertices[ j + 1 ];
v2[ 2 ] = vertices[ j + 2 ];
cb.operatorLine( v1, v2 );
}
last = indexes[ last ] * 3;
v1[ 0 ] = vertices[ last ];
v1[ 1 ] = vertices[ last + 1 ];
v1[ 2 ] = vertices[ last + 2 ];
var first = indexes[ 0 ] * 3;
v2[ 0 ] = vertices[ first ];
v2[ 1 ] = vertices[ first + 1 ];
v2[ 2 ] = vertices[ first + 2 ];
cb.operatorLine( v1, v2 );
};
} )();
functorDrawElements[ PrimitiveSet.TRIANGLES ] = ( function () {
var v1 = vec3.create();
var v2 = vec3.create();
var v3 = vec3.create();
return function ( offset, count, indexes, cb, vertices ) {
var end = offset + count;
for ( var i = offset; i < end; i += 3 ) {
var j = indexes[ i ] * 3;
v1[ 0 ] = vertices[ j ];
v1[ 1 ] = vertices[ j + 1 ];
v1[ 2 ] = vertices[ j + 2 ];
j = indexes[ i + 1 ] * 3;
v2[ 0 ] = vertices[ j ];
v2[ 1 ] = vertices[ j + 1 ];
v2[ 2 ] = vertices[ j + 2 ];
j = indexes[ i + 2 ] * 3;
v3[ 0 ] = vertices[ j ];
v3[ 1 ] = vertices[ j + 1 ];
v3[ 2 ] = vertices[ j + 2 ];
cb.operatorTriangle( v1, v2, v3 );
}
};
} )();
functorDrawElements[ PrimitiveSet.TRIANGLE_STRIP ] = ( function () {
var v1 = vec3.create();
var v2 = vec3.create();
var v3 = vec3.create();
return function ( offset, count, indexes, cb, vertices ) {
for ( var i = 2, pos = offset; i < count; ++i, ++pos ) {
var j = indexes[ pos ] * 3;
v1[ 0 ] = vertices[ j ];
v1[ 1 ] = vertices[ j + 1 ];
v1[ 2 ] = vertices[ j + 2 ];
j = indexes[ pos + 1 ] * 3;
v2[ 0 ] = vertices[ j ];
v2[ 1 ] = vertices[ j + 1 ];
v2[ 2 ] = vertices[ j + 2 ];
j = indexes[ pos + 2 ] * 3;
v3[ 0 ] = vertices[ j ];
v3[ 1 ] = vertices[ j + 1 ];
v3[ 2 ] = vertices[ j + 2 ];
if ( i % 2 ) {
cb.operatorTriangle( v1, v3, v2 );
} else {
cb.operatorTriangle( v1, v2, v3 );
}
}
};
} )();
functorDrawElements[ PrimitiveSet.TRIANGLE_FAN ] = ( function () {
var v1 = vec3.create();
var v2 = vec3.create();
var v3 = vec3.create();
return function ( offset, count, indexes, cb, vertices ) {
var first = indexes[ offset ];
for ( var i = 2, pos = offset + 1; i < count; ++i, ++pos ) {
v1[ 0 ] = vertices[ first ];
v1[ 1 ] = vertices[ first + 1 ];
v1[ 2 ] = vertices[ first + 2 ];
var j = indexes[ pos ] * 3;
v2[ 0 ] = vertices[ j ];
v2[ 1 ] = vertices[ j + 1 ];
v2[ 2 ] = vertices[ j + 2 ];
j = indexes[ pos + 1 ] * 3;
v3[ 0 ] = vertices[ j ];
v3[ 1 ] = vertices[ j + 1 ];
v3[ 2 ] = vertices[ j + 2 ];
cb.operatorTriangle( v1, v2, v3 );
}
};
} )();
functorDrawArrays[ PrimitiveSet.POINTS ] = ( function () {
var v = vec3.create();
return function ( first, count, cb, vertices ) {
for ( var i = first; i < first + count; ++i ) {
var j = i * 3;
v[ 0 ] = vertices[ j ];
v[ 1 ] = vertices[ j + 1 ];
v[ 2 ] = vertices[ j + 2 ];
cb.operatorPoint( v );
}
};
} )();
functorDrawArrays[ PrimitiveSet.LINES ] = ( function () {
var v1 = vec3.create();
var v2 = vec3.create();
return function ( first, count, cb, vertices ) {
for ( var i = first; i < first + count - 1; i += 2 ) {
var j = i * 3;
v1[ 0 ] = vertices[ j ];
v1[ 1 ] = vertices[ j + 1 ];
v1[ 2 ] = vertices[ j + 2 ];
j = ( i + 1 ) * 3;
v2[ 0 ] = vertices[ j ];
v2[ 1 ] = vertices[ j + 1 ];
v2[ 2 ] = vertices[ j + 2 ];
cb.operatorLine( v1, v2 );
}
};
} )();
functorDrawArrays[ PrimitiveSet.LINE_STRIP ] = ( function () {
var v1 = vec3.create();
var v2 = vec3.create();
return function ( first, count, cb, vertices ) {
for ( var i = first; i < first + count - 1; ++i ) {
var j = i * 3;
v1[ 0 ] = vertices[ j ];
v1[ 1 ] = vertices[ j + 1 ];
v1[ 2 ] = vertices[ j + 2 ];
j = ( i + 1 ) * 3;
v2[ 0 ] = vertices[ j ];
v2[ 1 ] = vertices[ j + 1 ];
v2[ 2 ] = vertices[ j + 2 ];
cb.operatorLine( v1, v2 );
}
};
} )();
functorDrawArrays[ PrimitiveSet.LINE_LOOP ] = ( function () {
var v1 = vec3.create();
var v2 = vec3.create();
return function ( first, count, cb, vertices ) {
var last = first + count - 1;
for ( var i = first; i < last; ++i ) {
var j = i * 3;
v1[ 0 ] = vertices[ j ];
v1[ 1 ] = vertices[ j + 1 ];
v1[ 2 ] = vertices[ j + 2 ];
j = ( i + 1 ) * 3;
v2[ 0 ] = vertices[ j ];
v2[ 1 ] = vertices[ j + 1 ];
v2[ 2 ] = vertices[ j + 2 ];
cb.operatorLine( v1, v2 );
}
last = last * 3;
v1[ 0 ] = vertices[ last ];
v1[ 1 ] = vertices[ last + 1 ];
v1[ 2 ] = vertices[ last + 2 ];
first = first * 3;
v2[ 0 ] = vertices[ first ];
v2[ 1 ] = vertices[ first + 1 ];
v2[ 2 ] = vertices[ first + 2 ];
cb.operatorLine( v1, v2 );
};
} )();
functorDrawArrays[ PrimitiveSet.TRIANGLES ] = ( function () {
var v1 = vec3.create();
var v2 = vec3.create();
var v3 = vec3.create();
return function ( first, count, cb, vertices ) {
for ( var i = first; i < first + count; i += 3 ) {
var j = i * 3;
v1[ 0 ] = vertices[ j ];
v1[ 1 ] = vertices[ j + 1 ];
v1[ 2 ] = vertices[ j + 2 ];
j = ( i + 1 ) * 3;
v2[ 0 ] = vertices[ j ];
v2[ 1 ] = vertices[ j + 1 ];
v2[ 2 ] = vertices[ j + 2 ];
j = ( i + 2 ) * 3;
v3[ 0 ] = vertices[ j ];
v3[ 1 ] = vertices[ j + 1 ];
v3[ 2 ] = vertices[ j + 2 ];
cb.operatorTriangle( v1, v2, v3 );
}
};
} )();
functorDrawArrays[ PrimitiveSet.TRIANGLE_STRIP ] = ( function () {
var v1 = vec3.create();
var v2 = vec3.create();
var v3 = vec3.create();
return function ( first, count, cb, vertices ) {
for ( var i = 2, pos = first; i < count; ++i, ++pos ) {
var j = pos * 3;
v1[ 0 ] = vertices[ j ];
v1[ 1 ] = vertices[ j + 1 ];
v1[ 2 ] = vertices[ j + 2 ];
j = ( pos + 1 ) * 3;
v2[ 0 ] = vertices[ j ];
v2[ 1 ] = vertices[ j + 1 ];
v2[ 2 ] = vertices[ j + 2 ];
j = ( pos + 2 ) * 3;
v3[ 0 ] = vertices[ j ];
v3[ 1 ] = vertices[ j + 1 ];
v3[ 2 ] = vertices[ j + 2 ];
if ( i % 2 ) {
cb.operatorTriangle( v1, v3, v2 );
} else {
cb.operatorTriangle( v1, v2, v3 );
}
}
};
} )();
functorDrawArrays[ PrimitiveSet.TRIANGLE_FAN ] = ( function () {
var v1 = vec3.create();
var v2 = vec3.create();
var v3 = vec3.create();
return function ( first, count, cb, vertices ) {
for ( var i = 2, pos = first + 1; i < count; ++i, ++pos ) {
v1[ 0 ] = vertices[ first ];
v1[ 1 ] = vertices[ first + 1 ];
v1[ 2 ] = vertices[ first + 2 ];
var j = pos * 3;
v2[ 0 ] = vertices[ j ];
v2[ 1 ] = vertices[ j + 1 ];
v2[ 2 ] = vertices[ j + 2 ];
j = ( pos + 1 ) * 3;
v3[ 0 ] = vertices[ j ];
v3[ 1 ] = vertices[ j + 1 ];
v3[ 2 ] = vertices[ j + 2 ];
cb.operatorTriangle( v1, v2, v3 );
}
};
} )();
PrimitiveFunctor.prototype = {
apply: function () {
var geom = this._geom;
var primitives = geom.primitives;
if ( !primitives )
return;
var cb = this._cb();
var cbFunctor;
var vertices = this._vertices;
var nbPrimitives = primitives.length;
for ( var i = 0; i < nbPrimitives; i++ ) {
var primitive = primitives[ i ];
if ( primitive instanceof DrawElements ) {
cbFunctor = functorDrawElements[ primitive.getMode() ];
if ( cbFunctor ) {
var indexes = primitive.indices.getElements();
cbFunctor( primitive.getFirst() / indexes.BYTES_PER_ELEMENT, primitive.getCount(), indexes, cb, vertices );
}
} else if ( primitive instanceof DrawArrays ) {
cbFunctor = functorDrawArrays[ primitive.getMode() ];
if ( cbFunctor ) {
cbFunctor( primitive.getFirst(), primitive.getCount(), cb, vertices );
}
}
}
}
};
module.exports = PrimitiveFunctor;

Wyświetl plik

@ -1,323 +0,0 @@
'use strict';
var MACROUTILS = require( 'osg/Utils' );
var Notify = require( 'osg/notify' );
var GLObject = require( 'osg/GLObject' );
var StateAttribute = require( 'osg/StateAttribute' );
var CustomMap = require( 'osg/Map' );
var Timer = require( 'osg/Timer' );
/**
* Program encapsulate an vertex and fragment shader
* @class Program
*/
var Program = function ( vShader, fShader ) {
GLObject.call( this );
StateAttribute.call( this );
this._program = null;
// used to know if it's a default program
// a default program does nothing but avoid to do some
// useless logic
// if we vertex or fragment shader are set it's not a default
// program anymore
this._nullProgram = true;
this._vertex = undefined;
this._fragment = undefined;
this._uniformsCache = undefined;
this._attributesCache = undefined;
this._activeUniforms = undefined;
this._foreignUniforms = undefined;
this._trackAttributes = undefined;
if ( vShader )
this.setVertexShader( vShader );
if ( fShader )
this.setFragmentShader( fShader );
this._dirty = true;
};
var getAttributeList = function ( vertexShader ) {
var attributeMap = {};
var r = vertexShader.match( /attribute\s+\w+\s+\w+/g );
if ( r !== null ) {
for ( var i = 0, l = r.length; i < l; i++ ) {
var attr = r[ i ].match( /attribute\s+\w+\s+(\w+)/ )[ 1 ];
attributeMap[ attr ] = true;
}
}
return attributeMap;
};
// static cache of glPrograms flagged for deletion, which will actually
// be deleted in the correct GL context.
Program._sDeletedGLProgramCache = new window.Map();
// static method to delete Program
Program.deleteGLProgram = function ( gl, program ) {
if ( !Program._sDeletedGLProgramCache.has( gl ) )
Program._sDeletedGLProgramCache.set( gl, [] );
Program._sDeletedGLProgramCache.get( gl ).push( program );
};
// static method to flush all the cached glPrograms which need to be deleted in the GL context specified
Program.flushDeletedGLPrograms = function ( gl, availableTime ) {
// if no time available don't try to flush objects.
if ( availableTime <= 0.0 ) return availableTime;
if ( !Program._sDeletedGLProgramCache.has( gl ) ) return availableTime;
var elapsedTime = 0.0;
var beginTime = Timer.instance().tick();
var deleteList = Program._sDeletedGLProgramCache.get( gl );
var numPrograms = deleteList.length;
for ( var i = numPrograms - 1; i >= 0 && elapsedTime < availableTime; i-- ) {
gl.deleteProgram( deleteList[ i ] );
deleteList.splice( i, 1 );
elapsedTime = Timer.instance().deltaS( beginTime, Timer.instance().tick() );
}
return availableTime - elapsedTime;
};
Program.flushAllDeletedGLPrograms = function ( gl ) {
if ( !Program._sDeletedGLProgramCache.has( gl ) ) return;
var deleteList = Program._sDeletedGLProgramCache.get( gl );
var numPrograms = deleteList.length;
for ( var i = numPrograms - 1; i >= 0; i-- ) {
gl.deleteProgram( deleteList[ i ] );
deleteList.splice( i, 1 );
}
};
/** @lends Program.prototype */
Program.prototype = MACROUTILS.objectLibraryClass( MACROUTILS.objectInherit( GLObject.prototype, MACROUTILS.objectInherit( StateAttribute.prototype, {
attributeType: 'Program',
cloneType: function () {
return new Program();
},
setVertexShader: function ( vs ) {
this._vertex = vs;
this._nullProgram = false;
},
setFragmentShader: function ( fs ) {
this._fragment = fs;
this._nullProgram = false;
},
getVertexShader: function () {
return this._vertex;
},
getFragmentShader: function () {
return this._fragment;
},
getProgram: function () {
return this._program;
},
setActiveUniforms: function ( activeUniforms ) {
this._activeUniforms = activeUniforms;
},
getActiveUniforms: function () {
return this._activeUniforms;
},
setForeignUniforms: function ( foreignUniforms ) {
this._foreignUniforms = foreignUniforms;
},
getForeignUniforms: function () {
return this._foreignUniforms;
},
setUniformsCache: function ( uniformsCache ) {
this._uniformsCache = uniformsCache;
},
getUniformsCache: function () {
return this._uniformsCache;
},
setAttributesCache: function ( attributesCache ) {
this._attributesCache = attributesCache;
},
getAttributesCache: function () {
return this._attributesCache;
},
setTrackAttributes: function ( trackAttributes ) {
this._trackAttributes = trackAttributes;
},
getTrackAttributes: function () {
return this._trackAttributes;
},
releaseGLObjects: function () {
// Call to releaseGLOBjects on shaders
if ( this._vertex !== undefined ) this._vertex.releaseGLObjects();
if ( this._fragment !== undefined ) this._fragment.releaseGLObjects();
if ( this._program === null ) return;
if ( this._gl !== undefined ) {
Program.deleteGLProgram( this._gl, this._program );
}
this._program = undefined;
},
apply: function ( state ) {
if ( this._nullProgram ) return;
if ( !this._gl ) {
this.setGraphicContext( state.getGraphicContext() );
}
var gl = this._gl;
if ( !this._program || this._dirty ) {
var compileClean;
if ( !this._vertex.shader ) {
compileClean = this._vertex.compile( gl );
}
if ( !this._fragment.shader ) {
compileClean = this._fragment.compile( gl );
}
var attributeMap = getAttributeList( this._vertex.getText() );
if ( compileClean ) {
this._program = gl.createProgram();
if ( attributeMap.Vertex ) {
// force Vertex to be on 0
gl.bindAttribLocation( this._program, 0, 'Vertex' );
}
gl.attachShader( this._program, this._vertex.shader );
gl.attachShader( this._program, this._fragment.shader );
MACROUTILS.timeStamp( 'osgjs.metrics:linkShader' );
gl.linkProgram( this._program );
if ( !gl.getProgramParameter( this._program, gl.LINK_STATUS ) && !gl.isContextLost() ) {
var errLink = gl.getProgramInfoLog( this._program );
Notify.errorFold( errLink, 'can\'t link program\nvertex shader:\n' + this._vertex.text + '\n fragment shader:\n' + this._fragment.text );
// rawgl trick is for webgl inspector
var debugShader = ( gl.rawgl !== undefined ? gl.rawgl : gl );
if ( debugShader !== undefined && debugShader.getExtension !== undefined ) debugShader = debugShader.getExtension( 'WEBGL_debug_shaders' );
if ( debugShader && errLink === 'Failed to create D3D shaders.\n' ) {
Notify.error( debugShader.getTranslatedShaderSource( this._vertex.shader ) );
Notify.error( debugShader.getTranslatedShaderSource( this._fragment.shader ) );
}
compileClean = false;
}
// TODO: better usage of validate.
// as it's intended at shader program usage
// validating against current gl state
// Not for compilation stage
// gl.validateProgram( this._program );
}
if ( !compileClean ) {
// Any error, Any
// Pink must die.
if ( !Program.prototype._failSafeCache ) {
var program = gl.createProgram();
this._vertex.failSafe( gl );
this._fragment.failSafe( gl );
gl.attachShader( program, this._vertex.shader );
gl.attachShader( program, this._fragment.shader );
gl.linkProgram( program );
gl.validateProgram( program );
// cache to compile and allocate only once
// not polluting the inspector
Program.prototype._failSafeCache = program;
}
Notify.warn( 'FailSafe shader Activated ' );
this._program = this._failSafeCache;
}
this._uniformsCache = new CustomMap();
this._attributesCache = new CustomMap();
this.cacheUniformList( gl, this._vertex.text );
this.cacheUniformList( gl, this._fragment.text );
this.cacheAttributeList( gl, window.Object.keys( attributeMap ) );
this._dirty = false;
}
state.applyProgram( this._program );
},
cacheUniformList: function ( gl, str ) {
var r = str.match( /uniform\s+\w+\s+\w+((\s)?\[(.*?)\])?/g );
var map = this._uniformsCache;
if ( r !== null ) {
for ( var i = 0, l = r.length; i < l; i++ ) {
var uniform = r[ i ].match( /uniform\s+\w+\s+(\w+)/ )[ 1 ];
var uniformName = r[ i ].match( /uniform\s+\w+\s+(\w+)(\s?\[.*?\])?/ )[ 1 ];
var location = gl.getUniformLocation( this._program, uniform );
if ( location !== undefined && location !== null ) {
if ( map[ uniformName ] === undefined ) {
map[ uniformName ] = location;
this._uniformsCache.dirty();
}
}
}
}
},
cacheAttributeList: function ( gl, attributeList ) {
var map = this._attributesCache;
for ( var i = 0, l = attributeList.length; i < l; i++ ) {
var attr = attributeList[ i ];
var location = gl.getAttribLocation( this._program, attr );
if ( location !== -1 && location !== undefined ) {
if ( map[ attr ] === undefined ) {
map[ attr ] = location;
this._attributesCache.dirty();
}
}
}
}
} ) ), 'osg', 'Program' );
module.exports = Program;

Wyświetl plik

@ -1,21 +0,0 @@
'use strict';
var MACROUTILS = require( 'osg/Utils' );
var Node = require( 'osg/Node' );
var mat4 = require( 'osg/glMatrix' ).mat4;
var Projection = function () {
Node.call( this );
this.projection = mat4.create();
};
Projection.prototype = MACROUTILS.objectInherit( Node.prototype, {
getProjectionMatrix: function () {
return this.projection;
},
setProjectionMatrix: function ( m ) {
this.projection = m;
}
} );
MACROUTILS.setTypeID( Projection );
module.exports = Projection;

Wyświetl plik

@ -1 +0,0 @@
module.exports = require( 'osg/deprecated-MatrixVector/Quat' );

Wyświetl plik

@ -1,321 +0,0 @@
'use strict';
var MACROUTILS = require( 'osg/Utils' );
var Notify = require( 'osg/notify' );
var Object = require( 'osg/Object' );
var osgMath = require( 'osg/math' );
/**
* RenderBin base class. Renderbin contains geometries to be rendered as a group,
* renderbins are rendered once each. They can improve efficiency or
* use different rendering algorithms.
* A renderBin can contain further renderBins producing a tree hierarchy of renderBins.
*
* https://github.com/openscenegraph/osg/blob/master/include/osgUtil/RenderBin#L27-L32
*/
var RenderBin = function ( sortMode ) {
Object.call( this );
this._leafs = [];
this.positionedAttribute = [];
this.stateGraphList = [];
RenderBin.prototype.init.call( this, sortMode );
};
RenderBin.SORT_BY_STATE = 0;
RenderBin.SORT_BACK_TO_FRONT = 1;
RenderBin.SORT_FRONT_TO_BACK = 2;
// change it at runtime for default RenderBin if needed
RenderBin.defaultSortMode = RenderBin.SORT_BY_STATE;
RenderBin.BinPrototypes = {
RenderBin: function () {
return RenderBin.getOrCreate().init();
},
DepthSortedBin: function () {
return RenderBin.getOrCreate().init( RenderBin.SORT_BACK_TO_FRONT );
}
};
var sortBackToFrontFunction = function ( a, b ) {
return b._depth - a._depth;
};
var sortFrontToBackFunction = function ( a, b ) {
return a._depth - b._depth;
};
var sortBinNumberFunction = function ( a, b ) {
return a._binNum - b._binNum;
};
RenderBin.prototype = MACROUTILS.objectLibraryClass( MACROUTILS.objectInherit( Object.prototype, {
init: function ( sortMode ) {
this._leafs.length = 0;
this.positionedAttribute.length = 0;
this._renderStage = undefined;
this._bins = {};
this.stateGraphList.length = 0;
this._parent = undefined;
this._binNum = 0;
this._sorted = false;
this._sortMode = sortMode !== undefined ? sortMode : RenderBin.defaultSortMode;
this._drawCallback = undefined;
return this;
},
_createRenderBin: function ( binName ) {
// default render bin constructor
var renderBinConstructor = RenderBin.BinPrototypes.RenderBin;
if ( binName && RenderBin.BinPrototypes[ binName ] )
renderBinConstructor = RenderBin.BinPrototypes[ binName ];
return renderBinConstructor();
},
getStateGraphList: function () {
return this.stateGraphList;
},
copyLeavesFromStateGraphListToRenderLeafList: function () {
this._leafs.splice( 0, this._leafs.length );
var detectedNaN = false;
for ( var i = 0, l = this.stateGraphList.length; i < l; i++ ) {
var leafs = this.stateGraphList[ i ].leafs;
for ( var j = 0, k = leafs.length; j < k; j++ ) {
var leaf = leafs[ j ];
if ( osgMath.isNaN( leaf._depth ) ) {
detectedNaN = true;
} else {
this._leafs.push( leaf );
}
}
}
if ( detectedNaN ) {
Notify.debug( 'warning: RenderBin::copyLeavesFromStateGraphListToRenderLeafList() detected NaN depth values, database may be corrupted.' );
}
// empty the render graph list to prevent it being drawn along side the render leaf list (see drawImplementation.)
this.stateGraphList.splice( 0, this.stateGraphList.length );
},
getSortMode: function () {
return this._sortMode;
},
sortBackToFront: function () {
this.copyLeavesFromStateGraphListToRenderLeafList();
this._leafs.sort( sortBackToFrontFunction );
},
sortFrontToBack: function () {
this.copyLeavesFromStateGraphListToRenderLeafList();
this._leafs.sort( sortFrontToBackFunction );
},
sortImplementation: function () {
var SortMode = RenderBin;
switch ( this._sortMode ) {
case SortMode.SORT_BACK_TO_FRONT:
this.sortBackToFront();
break;
case SortMode.SORT_FRONT_TO_BACK:
this.sortFrontToBack();
break;
case SortMode.SORT_BY_STATE:
// do nothing
break;
}
},
sort: function () {
if ( this._sorted ) {
return;
}
var bins = this._bins;
var keys = window.Object.keys( bins );
for ( var i = 0, l = keys.length; i < l; i++ ) {
bins[ keys[ i ] ].sort();
}
this.sortImplementation();
this._sorted = true;
},
setParent: function ( parent ) {
this._parent = parent;
},
getParent: function () {
return this._parent;
},
getBinNumber: function () {
return this._binNum;
},
findOrInsert: function ( binNum, binName ) {
var bin = this._bins[ binNum ];
if ( !bin ) {
bin = this._createRenderBin( binName );
bin._parent = this;
bin._binNum = binNum;
bin._renderStage = this._renderStage;
this._bins[ binNum ] = bin;
}
return bin;
},
getStage: function () {
return this._renderStage;
},
addStateGraph: function ( sg ) {
this.stateGraphList.push( sg );
},
reset: function () {
this.stateGraphList.length = 0;
this._bins = {};
this.positionedAttribute.length = 0;
this._leafs.length = 0;
this._sorted = false;
},
draw: function ( state, previousRenderLeaf ) {
var previousLeaf = previousRenderLeaf;
// use callback drawImplementation if exist
if ( this._drawCallback && this._drawCallback.drawImplementation ) {
previousLeaf = this._drawCallback.drawImplementation( this, state, previousLeaf );
} else {
previousLeaf = this.drawImplementation( state, previousLeaf );
}
return previousLeaf;
},
applyPositionedAttribute: function ( state, positionedAttributes ) {
// the idea is to set uniform 'globally' in uniform map.
for ( var index = 0, l = positionedAttributes.length; index < l; index++ ) {
var element = positionedAttributes[ index ];
// add or set uniforms in state
var stateAttribute = element[ 1 ];
var matrix = element[ 0 ];
state.setGlobalDefaultAttribute( stateAttribute );
stateAttribute.apply( state );
stateAttribute.applyPositionedUniform( matrix, state );
state.haveAppliedAttribute( stateAttribute );
}
},
drawImplementation: function ( state, previousRenderLeaf ) {
var previousLeaf = previousRenderLeaf;
var binsKeys = window.Object.keys( this._bins );
var bins = this._bins;
var binsArray = [];
for ( var i = 0, l = binsKeys.length; i < l; i++ ) {
var k = binsKeys[ i ];
binsArray.push( bins[ k ] );
}
binsArray.sort( sortBinNumberFunction );
var current = 0;
var end = binsArray.length;
var bin;
// draw pre bins
for ( ; current < end; current++ ) {
bin = binsArray[ current ];
if ( bin.getBinNumber() > 0 ) {
break;
}
previousLeaf = bin.draw( state, previousLeaf );
}
// draw leafs
previousLeaf = this.drawLeafs( state, previousLeaf );
// draw post bins
for ( ; current < end; current++ ) {
bin = binsArray[ current ];
previousLeaf = bin.draw( state, previousLeaf );
}
return previousLeaf;
},
drawLeafs: function ( state, previousRenderLeaf ) {
var stateList = this.stateGraphList;
var leafs = this._leafs;
var previousLeaf = previousRenderLeaf;
var leaf;
// draw fine grained ordering.
for ( var d = 0, dl = leafs.length; d < dl; d++ ) {
leaf = leafs[ d ];
leaf.render( state, previousLeaf );
previousLeaf = leaf;
}
// draw coarse grained ordering.
for ( var i = 0, l = stateList.length; i < l; i++ ) {
var sg = stateList[ i ];
for ( var j = 0, ll = sg.leafs.length; j < ll; j++ ) {
leaf = sg.leafs[ j ];
leaf.render( state, previousLeaf );
previousLeaf = leaf;
}
}
return previousLeaf;
}
} ), 'osg', 'RenderBin' );
RenderBin.getOrCreate = function () {
var l = RenderBin._reservedStack[ RenderBin._reservedStackCurrent++ ];
if ( RenderBin._reservedStackCurrent === RenderBin._reservedStack.length ) {
RenderBin._reservedStack.push( new RenderBin() );
}
return l;
};
RenderBin.resetStack = function () {
RenderBin._reservedStackCurrent = 0;
};
RenderBin._reservedStack = [ new RenderBin() ];
RenderBin._reservedStackCurrent = 0;
module.exports = RenderBin;

Wyświetl plik

@ -1,213 +0,0 @@
'use strict';
var StateGraph = require( 'osg/StateGraph' );
var CacheUniformApply = function ( state, program ) {
this.modelUniform = program._uniformsCache[ state.modelMatrix.getName() ];
this.viewUniform = program._uniformsCache[ state.viewMatrix.getName() ];
this.apply = undefined;
this.generateUniformsApplyMethods();
};
CacheUniformApply.prototype = {
generateUniformsApplyMethods: function () {
var functionStr = [ '//generated by RenderLeaf\n' ];
functionStr.push( 'var gl = state.getGraphicContext();' );
functionStr.push( 'var matrixModelViewChanged = state.applyModelViewMatrix( modelview );' );
functionStr.push( 'state.applyProjectionMatrix( projection );' );
if ( this.modelUniform !== undefined ) {
functionStr.push( 'if ( matrixModelViewChanged ) {' );
functionStr.push( ' var modelMatrix = state.modelMatrix;' );
functionStr.push( ' modelMatrix.setMatrix4( model );' );
functionStr.push( ' modelMatrix.apply( gl, this.modelUniform);' );
functionStr.push( '};' );
}
if ( this.viewUniform !== undefined ) {
functionStr.push( 'if ( matrixModelViewChanged ) {' );
functionStr.push( ' var viewMatrix = state.viewMatrix;' );
functionStr.push( ' viewMatrix.setMatrix4( view );' );
functionStr.push( ' viewMatrix.apply( gl, this.viewUniform);' );
functionStr.push( '};' );
}
// I am the evil, so please bother someone else
/*jshint evil: true */
// name the function
// http://stackoverflow.com/questions/5905492/dynamic-function-name-in-javascript
var func = ( new Function( 'state', 'modelview', 'model', 'view', 'projection', 'return function RenderLeafApplyMatrixUniformCache( state, modelview, model, view, projection ) { ' + functionStr.join( '\n' ) + '}' ) )();
/*jshint evil: false */
this.apply = func;
}
};
var RenderLeaf = function () {
this._parent = undefined;
this._geometry = undefined;
this._depth = 0.0;
this._projection = undefined;
this._view = undefined;
this._model = undefined;
this._modelView = undefined;
};
RenderLeaf.prototype = {
reset: function () {
this._parent = undefined;
this._geometry = undefined;
this._depth = 0.0;
this._projection = undefined;
this._view = undefined;
this._model = undefined;
this._modelView = undefined;
},
init: function ( parent, geom, projection, view, modelView, model, depth ) {
this._parent = parent;
this._geometry = geom;
this._depth = depth;
this._projection = projection;
this._view = view;
this._model = model;
this._modelView = modelView;
},
drawGeometry: ( function () {
return function ( state ) {
var program = state.getLastProgramApplied();
var programInstanceID = program.getInstanceID();
var cache = state.getCacheUniformsApplyRenderLeaf();
var obj = cache[ programInstanceID ];
if ( !obj ) {
obj = new CacheUniformApply( state, program );
cache[ programInstanceID ] = obj;
}
obj.apply( state, this._modelView, this._model, this._view, this._projection, this._normal );
this._geometry.drawImplementation( state );
};
} )(),
render: ( function () {
var idLastDraw = 0;
var lastStateSetStackSize = -1;
return function ( state, previousLeaf ) {
var prevRenderGraph;
var prevRenderGraphParent;
var curRenderGraph = this._parent;
var curRenderGraphParent = curRenderGraph.parent;
var curRenderGraphStateSet = curRenderGraph.stateset;
// When rendering a RenderLeaf we try to limit the state change
// to do that Graph of State is created during the culling pass.
// this graph contains nodes of StateGraph type see the class StateGraph
//
// So to limit switching of StateSet we check where are the common parent
// between previous RenderLeaf and this current.
//
// There are 3 cases when there is a prev / current render leaf
//
//
// pRG: previousRenderGraph
// cRG: currentRenderGraph
// pRL: previousRenderLeaf
// cRL: currentRenderLeaf
// each RG contains a StateSet
//
// A B C
// +-----+ +-----+ +-----+ +-----+
// | pRG | | cRG | +--+ RG +--+ | RG |
// +--+--+ +--+--+ | +-----+ | +--+--+
// | | | | |
// +--v--+ +--v--+ +--v--+ +--v--+ +--v--+
// | pRG | | cRG | | pRG | | cRG | +--+ RG +--+
// +--+--+ +--+--+ +--+--+ +--+--+ | +-----+ |
// | | | | | |
// +--v--+ +--v--+ +--v--+ +--v--+ +--v--+ +--v--+
// | pRL | | cRL | | pRL | | cRL | | pRL | | cRL |
// +-----+ +-----+ +-----+ +-----+ +-----+ +-----+
//
//
// Case A
// no common parent StateGraphNode we need to
// popStateSet until we find the common parent and then
// pushStateSet from the common parent to the current
// RenderLeaf
//
// Case B
// common parent StateGraphNode so we apply the current stateSet
//
// Case C
// the StateGraphNode is common to the previous RenderLeaf so we dont need
// to do anything except if we used an insertStateSet
//
if ( previousLeaf !== undefined ) {
// apply state if required.
prevRenderGraph = previousLeaf._parent;
prevRenderGraphParent = prevRenderGraph.parent;
if ( prevRenderGraphParent !== curRenderGraphParent ) {
// Case A
StateGraph.moveStateGraph( state, prevRenderGraphParent, curRenderGraphParent );
state.applyStateSet( curRenderGraphStateSet );
} else if ( curRenderGraph !== prevRenderGraph ) {
// Case B
state.applyStateSet( curRenderGraphStateSet );
} else {
// Case C
// in osg we call apply but actually we dont need
// except if the stateSetStack changed.
// for example if insert/remove StateSet has been used
if ( state._stateSetStackChanged( idLastDraw, lastStateSetStackSize ) ) {
state.applyStateSet( curRenderGraphStateSet );
}
}
} else {
StateGraph.moveStateGraph( state, undefined, curRenderGraphParent );
state.applyStateSet( curRenderGraphStateSet );
}
state._setStateSetsDrawID( ++idLastDraw );
lastStateSetStackSize = state.getStateSetStackSize();
this.drawGeometry( state );
};
} )()
};
module.exports = RenderLeaf;

Wyświetl plik

@ -1,313 +0,0 @@
'use strict';
var MACROUTILS = require( 'osg/Utils' );
var Camera = require( 'osg/Camera' );
var FrameBufferObject = require( 'osg/FrameBufferObject' );
var Notify = require( 'osg/notify' );
var RenderBin = require( 'osg/RenderBin' );
var vec4 = require( 'osg/glMatrix' ).vec4;
/**
* From OpenSceneGraph http://www.openscenegraph.org
* RenderStage base class. Used for encapsulate a complete stage in
* rendering - setting up of viewport, the projection and model
* matrices and rendering the RenderBin's enclosed with this RenderStage.
* RenderStage also has a dependency list of other RenderStages, each
* of which must be called before the rendering of this stage. These
* 'pre' rendering stages are used for advanced rendering techniques
* like multistage pixel shading or impostors.
*/
var RenderStage = function () {
RenderBin.call( this );
this.clearColor = vec4.create();
this.preRenderList = [];
this.postRenderList = [];
// calling prototype to make sure
// we call renderstage and not renderbin init
RenderStage.prototype.init.call( this );
};
RenderStage.prototype = MACROUTILS.objectLibraryClass( MACROUTILS.objectInherit( RenderBin.prototype, {
// temporary, Utils.createPrototypeClass will solve this
constructor: RenderStage,
init: function () {
RenderBin.prototype.init.call( this );
this.positionedAttribute.length = 0;
this.clearDepth = 1.0;
vec4.set( this.clearColor, 0.0, 0.0, 0.0, 1.0 );
/*jshint bitwise: false */
this.clearMask = Camera.COLOR_BUFFER_BIT | Camera.DEPTH_BUFFER_BIT;
/*jshint bitwise: true */
this.camera = undefined;
this.viewport = undefined;
this.preRenderList.length = 0;
this.postRenderList.length = 0;
this._renderStage = this;
return this;
},
reset: function () {
RenderBin.prototype.reset.call( this );
this.preRenderList.length = 0;
this.postRenderList.length = 0;
},
setClearDepth: function ( depth ) {
this.clearDepth = depth;
},
getClearDepth: function () {
return this.clearDepth;
},
setClearColor: function ( color ) {
vec4.copy( this.clearColor, color );
},
getClearColor: function () {
return this.clearColor;
},
setClearMask: function ( mask ) {
this.clearMask = mask;
},
getClearMask: function () {
return this.clearMask;
},
setViewport: function ( vp ) {
this.viewport = vp;
},
getViewport: function () {
return this.viewport;
},
setCamera: function ( camera ) {
this.camera = camera;
},
getCamera: function () {
return this.camera;
},
getPositionedAttribute: function () {
return this.positionedAttribute;
},
getPreRenderStageList: function () {
return this.preRenderList;
},
getPostRenderStageList: function () {
return this.postRenderList;
},
addPreRenderStage: function ( rs, order ) {
for ( var i = 0, l = this.preRenderList.length; i < l; i++ ) {
var render = this.preRenderList[ i ];
if ( order < render.order ) {
break;
}
}
if ( i < this.preRenderList.length ) {
this.preRenderList = this.preRenderList.splice( i, 0, {
'order': order,
'renderStage': rs
} );
} else {
this.preRenderList.push( {
'order': order,
'renderStage': rs
} );
}
},
addPostRenderStage: function ( rs, order ) {
for ( var i = 0, l = this.postRenderList.length; i < l; i++ ) {
var render = this.postRenderList[ i ];
if ( order < render.order ) {
break;
}
}
if ( i < this.postRenderList.length ) {
this.postRenderList = this.postRenderList.splice( i, 0, {
'order': order,
'renderStage': rs
} );
} else {
this.postRenderList.push( {
'order': order,
'renderStage': rs
} );
}
},
drawPreRenderStages: function ( state, previousRenderLeaf ) {
var previousLeaf = previousRenderLeaf;
for ( var i = 0, l = this.preRenderList.length; i < l; ++i ) {
var sg = this.preRenderList[ i ].renderStage;
previousLeaf = sg.draw( state, previousLeaf );
}
return previousLeaf;
},
draw: function ( state, previousRenderLeaf ) {
if ( this.camera && this.camera.getInitialDrawCallback() ) {
// if we have a camera with a final callback invoke it.
this.camera.getInitialDrawCallback()( state );
}
var previousLeaf = this.drawPreRenderStages( state, previousRenderLeaf );
previousLeaf = this.drawImplementation( state, previousLeaf );
previousLeaf = this.drawPostRenderStages( state, previousLeaf );
if ( this.camera && this.camera.getFinalDrawCallback() ) {
// if we have a camera with a final callback invoke it.
this.camera.getFinalDrawCallback()( state );
}
return previousLeaf;
},
sort: function () {
for ( var i = 0, l = this.preRenderList.length; i < l; ++i ) {
this.preRenderList[ i ].renderStage.sort();
}
RenderBin.prototype.sort.call( this );
for ( var j = 0, k = this.postRenderList.length; j < k; ++j ) {
this.postRenderList[ j ].renderStage.sort();
}
},
drawPostRenderStages: function ( state, previousRenderLeaf ) {
var previousLeaf = previousRenderLeaf;
for ( var i = 0, l = this.postRenderList.length; i < l; ++i ) {
var sg = this.postRenderList[ i ].renderStage;
previousLeaf = sg.draw( state, previousLeaf );
}
return previousLeaf;
},
applyCamera: function ( state ) {
var gl = state.getGraphicContext();
if ( this.camera === undefined ) {
gl.bindFramebuffer( gl.FRAMEBUFFER, null );
return;
}
var viewport = this.camera.getViewport();
var fbo = this.camera.frameBufferObject;
if ( !fbo ) {
fbo = new FrameBufferObject();
this.camera.frameBufferObject = fbo;
}
if ( fbo.isDirty() ) {
var attachments = this.camera.getAttachments();
// framebuffer texture and renderbuffer must be same dimension
// otherwise framebuffer is incomplete
var framebufferWidth, framebufferHeight;
var colorAttachment = attachments[ FrameBufferObject.COLOR_ATTACHMENT0 ];
if ( colorAttachment && colorAttachment.texture ) {
framebufferWidth = colorAttachment.texture.getWidth();
framebufferHeight = colorAttachment.texture.getHeight();
}
// we should use a map in camera to avoid to regenerate the keys
// each time. But because we dont have a lot of camera I guess
// it does not change a lot
var keys = window.Object.keys( attachments );
if ( keys.length ) {
// texture and renderbuffer must be same size.
for ( var i = 0, l = keys.length; i < l; i++ ) {
var key = keys[ i ];
var a = attachments[ key ];
var attach = {};
attach.attachment = a.attachment;
if ( a.texture === undefined ) { //renderbuffer
attach.format = a.format;
attach.width = framebufferWidth !== undefined ? framebufferWidth : viewport.width();
attach.height = framebufferHeight !== undefined ? framebufferHeight : viewport.height();
} else if ( a.texture !== undefined ) {
attach.texture = a.texture;
attach.textureTarget = a.textureTarget;
if ( a.format ) {
attach.format = a.format;
}
}
fbo.setAttachment( attach );
}
}
}
fbo.apply( state );
},
drawImplementation: function ( state, previousRenderLeaf ) {
var gl = state.getGraphicContext();
this.applyCamera( state );
// projection clipping
if ( this.viewport === undefined ) {
Notify.log( 'RenderStage does not have a valid viewport' );
}
state.applyAttribute( this.viewport );
// fragment clipping
if ( this.camera ) {
var scissor = this.camera.getStateSet() && this.camera.getStateSet().getAttribute( 'Scissor' );
if ( scissor ) state.applyAttribute( scissor );
}
/*jshint bitwise: false */
if ( this.clearMask !== 0x0 ) {
if ( this.clearMask & gl.COLOR_BUFFER_BIT ) {
gl.clearColor( this.clearColor[ 0 ], this.clearColor[ 1 ], this.clearColor[ 2 ], this.clearColor[ 3 ] );
}
if ( this.clearMask & gl.DEPTH_BUFFER_BIT ) {
gl.depthMask( true );
gl.clearDepth( this.clearDepth );
}
/*jshint bitwise: true */
gl.clear( this.clearMask );
}
if ( this.positionedAttribute.length !== 0 ) {
this.applyPositionedAttribute( state, this.positionedAttribute );
}
var previousLeaf = RenderBin.prototype.drawImplementation.call( this, state, previousRenderLeaf );
return previousLeaf;
}
} ), 'osg', 'RenderStage' );
module.exports = RenderStage;

Wyświetl plik

@ -1,67 +0,0 @@
'use strict';
var MACROUTILS = require( 'osg/Utils' );
var StateAttribute = require( 'osg/StateAttribute' );
var Scissor = function ( x, y, w, h ) {
StateAttribute.call( this );
this._x = x !== undefined ? x : -1;
this._y = y !== undefined ? y : -1;
this._width = w !== undefined ? w : -1;
this._height = h !== undefined ? h : -1;
};
Scissor.prototype = MACROUTILS.objectLibraryClass( MACROUTILS.objectInherit( StateAttribute.prototype, {
attributeType: 'Scissor',
cloneType: function () {
return new Scissor();
},
apply: function ( state ) {
var gl = state.getGraphicContext();
if ( this._x !== -1 ) {
gl.enable( gl.SCISSOR_TEST );
gl.scissor( this._x, this._y, this._width, this._height );
} else {
gl.disable( gl.SCISSOR_TEST );
}
},
setScissor: function ( x, y, width, height ) {
this._x = x;
this._y = y;
this._width = width;
this._height = height;
},
x: function () {
return this._x;
},
y: function () {
return this._y;
},
width: function () {
return this._width;
},
height: function () {
return this._height;
}
} ), 'osg', 'Scissor' );
module.exports = Scissor;

Wyświetl plik

@ -1,196 +0,0 @@
'use strict';
var Notify = require( 'osg/notify' );
var MACROUTILS = require( 'osg/Utils' );
var Timer = require( 'osg/Timer' );
var GLObject = require( 'osg/GLObject' );
/**
* Shader manage shader for vertex and fragment, you need both to create a glsl program.
* @class Shader
*/
var Shader = function ( type, text ) {
GLObject.call( this );
var t = type;
if ( typeof ( type ) === 'string' ) {
t = Shader[ type ];
}
this.type = t;
this.setText( text );
};
Shader.VERTEX_SHADER = 0x8B31;
Shader.FRAGMENT_SHADER = 0x8B30;
// Debug Pink shader for when shader fails
Shader.VS_DBG = 'attribute vec3 Vertex;uniform mat4 uModelViewMatrix;uniform mat4 uProjectionMatrix;void main(void) { gl_Position = uProjectionMatrix * uModelViewMatrix * vec4(Vertex, 1.0);}';
Shader.FS_DBG = 'precision lowp float; void main(void) { gl_FragColor = vec4(1.0, 0.6, 0.6, 1.0);}';
var debugName = '\n#define SHADER_NAME FailSafe\n';
Shader.VS_DBG += debugName;
Shader.FS_DBG += debugName;
// static cache of glShaders flagged for deletion, which will actually
// be deleted in the correct GL context.
Shader._sDeletedGLShaderCache = new window.Map();
// static method to delete Program
Shader.deleteGLShader = function ( gl, shader ) {
if ( !Shader._sDeletedGLShaderCache.has( gl ) )
Shader._sDeletedGLShaderCache.set( gl, [] );
Shader._sDeletedGLShaderCache.get( gl ).push( shader );
};
// static method to flush all the cached glShaders which need to be deleted in the GL context specified
Shader.flushDeletedGLShaders = function ( gl, availableTime ) {
// if no time available don't try to flush objects.
if ( availableTime <= 0.0 ) return availableTime;
if ( !Shader._sDeletedGLShaderCache.has( gl ) ) return availableTime;
var elapsedTime = 0.0;
var beginTime = Timer.instance().tick();
var deleteList = Shader._sDeletedGLShaderCache.get( gl );
var numShaders = deleteList.length;
for ( var i = numShaders - 1; i >= 0 && elapsedTime < availableTime; i-- ) {
gl.deleteShader( deleteList[ i ] );
deleteList.splice( i, 1 );
elapsedTime = Timer.instance().deltaS( beginTime, Timer.instance().tick() );
}
return availableTime -= elapsedTime;
};
Shader.flushAllDeletedGLShaders = function ( gl ) {
if ( !Shader._sDeletedGLShaderCache.has( gl ) ) return;
var deleteList = Shader._sDeletedGLShaderCache.get( gl );
var numShaders = deleteList.length;
for ( var i = numShaders - 1; i >= 0; i-- ) {
gl.deleteShader( deleteList[ i ] );
deleteList.splice( i, 1 );
}
return;
};
/** @lends Shader.prototype */
Shader.prototype = MACROUTILS.objectInherit( GLObject.prototype, {
setText: function ( text ) {
this.text = text;
},
getText: function () {
return this.text;
},
// this is where it creates a fail safe shader that should work everywhere
failSafe: function ( gl ) {
this.shader = gl.createShader( this.type );
gl.shaderSource( this.shader, this.type === Shader.VERTEX_SHADER ? Shader.VS_DBG : Shader.FS_DBG );
gl.compileShader( this.shader );
},
// webgl shader compiler error to source contextualization
// for better console log messages
processErrors: function ( errors, source ) {
// regex to extract error message and line from webgl compiler reporting
var r = /ERROR: [\d]+:([\d]+): (.+)/gmi;
// split sources in indexable per line array
var lines = source.split( '\n' );
var linesLength = lines.length;
if ( linesLength === 0 ) return;
var i, m;
// IE reporting is not the same
if ( r.exec( errors ) === null ) {
r = /Shader compilation errors\n\((\d+)\, \d+\): (.+)/gmi;
}
// reset index to start.
r.lastIndex = 0;
while ( ( m = r.exec( errors ) ) != null ) {
if ( m.index === r.lastIndex ) {
r.lastIndex++; // moving between errors
}
// get error line
var line = parseInt( m[ 1 ] );
if ( line > linesLength ) continue;
// webgl error report.
Notify.error( 'ERROR ' + m[ 2 ] + ' in line ' + line );
var minLine = Math.max( 0, line - 7 );
var maxLine = Math.max( 0, line - 2 );
// for context
// log surrounding line priori to error with bof check
for ( i = minLine; i <= maxLine; i++ ) {
Notify.warn( lines[ i ].replace( /^[ \t]+/g, '' ) );
}
// Warn adds a lovely /!\ icon in front of the culprit line
maxLine = Math.max( 0, line - 1 );
Notify.error( lines[ maxLine ].replace( /^[ \t]+/g, '' ) );
minLine = Math.min( linesLength, line );
maxLine = Math.min( linesLength, line + 5 );
// for context
// surrounding line posterior to error (with eof check)
for ( i = minLine; i < maxLine; i++ ) {
Notify.warn( lines[ i ].replace( /^[ \t]+/g, '' ) );
}
}
},
compile: function ( gl ) {
if ( !this._gl ) this.setGraphicContext( gl );
this.shader = gl.createShader( this.type );
var shaderText = this.text;
if ( Shader.enableGLSLOptimizer && Shader.glslOptimizer ) {
var shaderTypeString = this.type === Shader.VERTEX_SHADER ? 'vertex' : 'fragment';
Notify.infoFold( shaderTypeString + ' shader before optimization', shaderText );
// 1: opengl
// 2: opengl es 2.0
// 3: opengl es 3.0
var optimized = Shader.glslOptimizer( shaderText, '2', this.type === Shader.VERTEX_SHADER );
if ( optimized.indexOf( 'Error:' ) !== -1 ) {
Notify.error( optimized );
} else if ( optimized.length <= 1 ) {
Notify.warnFold( 'glsl optimizer returned an empty shader, the original will be used', shaderText );
} else {
Notify.infoFold( shaderTypeString + ' shader after optimization', optimized );
shaderText = optimized;
}
}
gl.shaderSource( this.shader, shaderText );
MACROUTILS.timeStamp( 'osgjs.metrics:compileShader' );
gl.compileShader( this.shader );
if ( !gl.getShaderParameter( this.shader, gl.COMPILE_STATUS ) && !gl.isContextLost() ) {
var err = gl.getShaderInfoLog( this.shader );
this.processErrors( err, shaderText );
var tmpText = '\n' + shaderText;
var splittedText = tmpText.split( '\n' );
var newText = '\n';
for ( var i = 0, l = splittedText.length; i < l; ++i ) {
newText += i + ' ' + splittedText[ i ] + '\n';
}
// still logging whole source but folded
Notify.debugFold( 'can\'t compile shader', newText );
return false;
}
return true;
},
releaseGLObjects: function () {
if ( this._gl !== undefined ) {
Shader.deleteGLShader( this._gl, this.shader );
}
this.shader = undefined;
}
} );
Shader.create = function ( type, text ) {
Notify.log( 'Shader.create is deprecated, use new Shader with the same arguments instead' );
return new Shader( type, text );
};
module.exports = Shader;

Wyświetl plik

@ -1,32 +0,0 @@
'use strict';
var Stack = function () {
this.globalDefault = undefined;
this.lastApplied = undefined;
this.asChanged = false;
this._values = [];
this._back = undefined;
};
Stack.prototype = {
empty: function () {
return this._values.length === 0;
},
values: function () {
return this._values;
},
back: function () {
return this._back;
},
push: function ( value ) {
this._values.push( value );
this._back = value;
},
pop: function () {
var value = this._values.pop();
this._back = this._values[ this._values.length - 1 ];
return value;
}
};
module.exports = Stack;

Wyświetl plik

@ -1,43 +0,0 @@
'use strict';
var MACROUTILS = require( 'osg/Utils' );
var Object = require( 'osg/Object' );
var StateAttribute = function () {
Object.call( this );
};
StateAttribute.prototype = MACROUTILS.objectLibraryClass( MACROUTILS.objectInherit( Object.prototype, {
getType: function () {
return this.attributeType;
},
// basically, if you want two StateAttribute with the same attributeType in a stateSet/State
// their typeMember should be different
getTypeMember: function () {
return this.attributeType;
},
apply: function () {},
// getHash is used by the compiler to know if a change in a StateAttribute
// must trigger a shader build
// If you create your own attribute you will have to customize this function
// a good rule is to that if you change uniform it should not rebuild a shader
// but if you change a type or representation of your StateAttribute, then it should
// if it impact the rendering.
// check other attributes for examples
getHash: function () {
return this.getTypeMember();
}
} ), 'osg', 'StateAttribute' );
StateAttribute.OFF = 0;
StateAttribute.ON = 1;
StateAttribute.OVERRIDE = 2;
StateAttribute.PROTECTED = 4;
StateAttribute.INHERIT = 8;
module.exports = StateAttribute;

Wyświetl plik

@ -1,150 +0,0 @@
'use strict';
var osgPool = require( 'osgUtil/osgPool' );
var StateGraph = function () {
this.depth = 0;
this.children = {};
this.children.keys = [];
this.leafs = [];
this.stateset = undefined;
this.parent = undefined;
};
StateGraph.prototype = {
clean: function () {
this.leafs.length = 0;
this.stateset = undefined;
this.parent = undefined;
this.depth = 0;
var children = this.children;
var child;
var key, keys = children.keys;
for ( var i = 0, l = keys.length; i < l; i++ ) {
key = keys[ i ];
child = children[ key ];
child.clean();
osgPool.memoryPools.stateGraph.put( child );
}
this.children = {};
keys.length = 0;
this.children.keys = keys;
},
getStateSet: function () {
return this.stateset;
},
findOrInsert: function ( stateset ) {
var sg;
var stateSetID = stateset.getInstanceID();
var children = this.children;
if ( !children[ stateSetID ] ) {
//sg = new StateGraph();
sg = osgPool.memoryPools.stateGraph.get();
sg.parent = this;
sg.depth = this.depth + 1;
sg.stateset = stateset;
children[ stateSetID ] = sg;
children.keys.push( stateSetID );
} else {
sg = children[ stateSetID ];
}
return sg;
}
};
StateGraph.moveStateGraph = function ( state, sgCurrentArg, sgNewArg ) {
var stack = [];
var sgNew = sgNewArg;
var sgCurrent = sgCurrentArg;
var i, l;
if ( sgNew === sgCurrent || sgNew === undefined ) return;
if ( sgCurrent === undefined ) {
// push stateset from sgNew to root, and apply
// stateset from root to sgNew
do {
if ( sgNew.stateset !== undefined ) {
stack.push( sgNew.stateset );
}
sgNew = sgNew.parent;
} while ( sgNew );
for ( i = stack.length - 1, l = 0; i >= l; --i ) {
state.pushStateSet( stack[ i ] );
}
return;
} else if ( sgCurrent.parent === sgNew.parent ) {
// first handle the typical case which is two state groups
// are neighbours.
// state has changed so need to pop old state.
if ( sgCurrent.stateset !== undefined ) {
state.popStateSet();
}
// and push new state.
if ( sgNew.stateset !== undefined ) {
state.pushStateSet( sgNew.stateset );
}
return;
}
// need to pop back up to the same depth as the new state group.
while ( sgCurrent.depth > sgNew.depth ) {
if ( sgCurrent.stateset !== undefined ) {
state.popStateSet();
}
sgCurrent = sgCurrent.parent;
}
// use return path to trace back steps to sgNew.
stack = [];
// need to pop back up to the same depth as the curr state group.
while ( sgNew.depth > sgCurrent.depth ) {
if ( sgNew.stateset !== undefined ) {
stack.push( sgNew.stateset );
}
sgNew = sgNew.parent;
}
// now pop back up both parent paths until they agree.
// DRT - 10/22/02
// should be this to conform with above case where two StateGraph
// nodes have the same parent
while ( sgCurrent !== sgNew ) {
if ( sgCurrent.stateset !== undefined ) {
state.popStateSet();
}
sgCurrent = sgCurrent.parent;
if ( sgNew.stateset !== undefined ) {
stack.push( sgNew.stateset );
}
sgNew = sgNew.parent;
}
for ( i = stack.length - 1, l = 0; i >= l; --i ) {
state.pushStateSet( stack[ i ] );
}
};
module.exports = StateGraph;

Wyświetl plik

@ -1,307 +0,0 @@
'use strict';
var Map = require( 'osg/Map' );
var Notify = require( 'osg/notify' );
var Object = require( 'osg/Object' );
var StateAttribute = require( 'osg/StateAttribute' );
var MACROUTILS = require( 'osg/Utils' );
/** Stores a set of modes and attributes which represent a set of OpenGL state.
* Notice that a \c StateSet contains just a subset of the whole OpenGL state.
* <p>In OSG, each \c Drawable and each \c Node has a reference to a
* \c StateSet. These <tt>StateSet</tt>s can be shared between
* different <tt>Drawable</tt>s and <tt>Node</tt>s (that is, several
* <tt>Drawable</tt>s and <tt>Node</tt>s can reference the same \c StateSet).
* Indeed, this practice is recommended whenever possible,
* as this minimizes expensive state changes in the graphics pipeline.
*/
var StateSet = function () {
Object.call( this );
this._parents = [];
this.attributeMap = new Map();
this.textureAttributeMapList = [];
this._binName = undefined;
this._binNumber = 0;
// put the shader generator name in an AttributePair
// so that we can use the mask value
this._shaderGeneratorPair = null;
this._updateCallbackList = [];
this.uniforms = new Map();
this._drawID = -1; // used by the RenderLeaf to decide if it should apply the stateSet
};
StateSet.AttributePair = function ( attr, value ) {
this._object = attr;
this._value = value;
};
StateSet.AttributePair.prototype = {
getShaderGeneratorName: function () {
return this._object;
},
getAttribute: function () {
return this._object;
},
getUniform: function () {
return this._object;
},
getValue: function () {
return this._value;
}
};
StateSet.prototype = MACROUTILS.objectLibraryClass( MACROUTILS.objectInherit( Object.prototype, {
setDrawID: function ( id ) {
this._drawID = id;
},
getDrawID: function () {
return this._drawID;
},
getAttributePair: function ( attribute, value ) {
return new StateSet.AttributePair( attribute, value );
},
addUniform: function ( uniform, originalMode ) {
var mode = originalMode !== undefined ? originalMode : StateAttribute.ON;
var name = uniform.getName();
this.uniforms[ name ] = this.getAttributePair( uniform, mode );
this.uniforms.dirty();
},
addParent: function ( node ) {
this._parents.push( node );
},
removeParent: function ( node ) {
var idx = this._parents.indexOf( node );
if ( idx === -1 ) return;
this._parents.splice( idx, 1 );
},
removeUniform: function ( uniform ) {
this.uniforms.remove( uniform.getName() );
},
removeUniformByName: function ( uniformName ) {
this.uniforms.remove( uniformName );
},
getUniform: function ( uniform ) {
var uniformMap = this.uniforms;
if ( uniformMap[ uniform ] ) return uniformMap[ uniform ].getAttribute();
return undefined;
},
getUniformList: function () {
return this.uniforms;
},
setTextureAttributeAndModes: function ( unit, attribute, originalMode ) {
var mode = originalMode !== undefined ? originalMode : StateAttribute.ON;
this._setTextureAttribute( unit, this.getAttributePair( attribute, mode ) );
},
setTextureAttributeAndMode: function ( unit, attribute, mode ) {
Notify.log( 'StateSet.setTextureAttributeAndMode is deprecated, insteady use setTextureAttributeAndModes' );
this.setTextureAttributeAndModes( unit, attribute, mode );
},
getNumTextureAttributeLists: function () {
return this.textureAttributeMapList.length;
},
getTextureAttribute: function ( unit, attribute ) {
if ( this.textureAttributeMapList[ unit ] === undefined ) return undefined;
var textureMap = this.textureAttributeMapList[ unit ];
if ( textureMap[ attribute ] === undefined ) return undefined;
return textureMap[ attribute ].getAttribute();
},
removeTextureAttribute: function ( unit, attributeName ) {
if ( this.textureAttributeMapList[ unit ] === undefined ) return;
var textureAttributeMap = this.textureAttributeMapList[ unit ];
if ( textureAttributeMap[ attributeName ] === undefined ) return;
textureAttributeMap.remove( attributeName );
this.textureAttributeMapList[ unit ].dirty();
},
getAttribute: function ( attributeType ) {
if ( this.attributeMap[ attributeType ] === undefined ) {
return undefined;
}
return this.attributeMap[ attributeType ].getAttribute();
},
setAttributeAndModes: function ( attribute, originalMode ) {
var mode = originalMode !== undefined ? originalMode : StateAttribute.ON;
this._setAttribute( this.getAttributePair( attribute, mode ) );
},
setAttributeAndMode: function ( attribute, mode ) {
Notify.log( 'StateSet.setAttributeAndMode is deprecated, insteady use setAttributeAndModes' );
this.setAttributeAndModes( attribute, mode );
},
setAttribute: function ( attribute, originalMode ) {
var mode = originalMode !== undefined ? originalMode : StateAttribute.ON;
this._setAttribute( this.getAttributePair( attribute, mode ) );
},
// TODO: check if it's an attribute type or a attribute to remove it
removeAttribute: function ( attributeName ) {
if ( this.attributeMap[ attributeName ] !== undefined ) {
delete this.attributeMap[ attributeName ];
this.attributeMap.dirty();
}
},
setRenderingHint: function ( hint ) {
if ( hint === 'OPAQUE_BIN' ) {
this.setRenderBinDetails( 0, 'RenderBin' );
} else if ( hint === 'TRANSPARENT_BIN' ) {
this.setRenderBinDetails( 10, 'DepthSortedBin' );
} else {
this.setRenderBinDetails( 0, '' );
}
},
getUpdateCallbackList: function () {
return this._updateCallbackList;
},
removeUpdateCallback: function ( cb ) {
var idx = this._updateCallbackList.indexOf( cb );
if ( idx === -1 ) return;
this._updateCallbackList.splice( idx, 1 );
if ( this._updateCallbackList.length === 0 ) {
var parents = this._parents;
for ( var i = 0, l = parents.length; i < l; i++ ) {
var parent = parents[ i ];
parent.setNumChildrenRequiringUpdateTraversal( parent.getNumChildrenRequiringUpdateTraversal() - 1 );
}
}
},
requiresUpdateTraversal: function () {
return !!this._updateCallbackList.length;
},
addUpdateCallback: function ( cb ) {
var dontNoticeParents = Boolean( this._updateCallbackList.length );
this._updateCallbackList.push( cb );
// parent alreay know we have update callback
if ( dontNoticeParents ) return;
var parents = this._parents;
for ( var i = 0, l = parents.length; i < l; i++ ) {
var parent = parents[ i ];
parent.setNumChildrenRequiringUpdateTraversal( parent.getNumChildrenRequiringUpdateTraversal() + 1 );
}
},
hasUpdateCallback: function ( cb ) {
return this._updateCallbackList.indexOf( cb ) !== -1;
},
setRenderBinDetails: function ( num, binName ) {
this._binNumber = num;
this._binName = binName;
},
getAttributeMap: function () {
return this.attributeMap;
},
getBinNumber: function () {
return this._binNumber;
},
getBinName: function () {
return this._binName;
},
setBinNumber: function ( binNum ) {
this._binNumber = binNum;
},
setBinName: function ( binName ) {
this._binName = binName;
},
getAttributeList: function () {
var attributeMap = this.attributeMap;
var attributeMapKeys = attributeMap.getKeys();
var l = attributeMapKeys.length;
var list = [];
for ( var i = 0; i < l; i++ ) {
list.push( attributeMap[ attributeMapKeys[ i ] ] );
}
return list;
},
setShaderGeneratorName: function ( generatorName, mask ) {
this._shaderGeneratorPair = this.getAttributePair( generatorName, mask );
},
getShaderGeneratorPair: function () {
return this._shaderGeneratorPair;
},
getShaderGeneratorName: function () {
return this._shaderGeneratorPair ? this._shaderGeneratorPair.getShaderGeneratorName() : undefined;
},
releaseGLObjects: function () {
for ( var i = 0, j = this.textureAttributeMapList.length; i < j; i++ ) {
this.getTextureAttribute( i, 'Texture' ).releaseGLObjects();
}
var list = this.getAttributeList();
for ( i = 0, j = list.length; i < j; i++ ) {
// Remove only if we have releaseGLObject method.
if ( list[ i ]._object.releaseGLObjects ) {
list[ i ]._object.releaseGLObjects();
}
}
},
_getUniformMap: function () {
return this.uniforms;
},
// for internal use, you should not call it directly
_setTextureAttribute: function ( unit, attributePair ) {
if ( this.textureAttributeMapList[ unit ] === undefined ) {
this.textureAttributeMapList[ unit ] = new Map();
}
var name = attributePair.getAttribute().getTypeMember();
var textureUnitAttributeMap = this.textureAttributeMapList[ unit ];
textureUnitAttributeMap[ name ] = attributePair;
textureUnitAttributeMap.dirty();
},
// for internal use, you should not call it directly
_setAttribute: function ( attributePair ) {
var name = attributePair.getAttribute().getTypeMember();
this.attributeMap[ name ] = attributePair;
this.attributeMap.dirty();
}
} ), 'osg', 'StateSet' );
module.exports = StateSet;

Wyświetl plik

@ -1,761 +0,0 @@
'use strict';
var Notify = require( 'osg/notify' );
var MACROUTILS = require( 'osg/Utils' );
var StateAttribute = require( 'osg/StateAttribute' );
var Uniform = require( 'osg/Uniform' );
var Image = require( 'osg/Image' );
var GLObject = require( 'osg/GLObject' );
var ReaderParser = require( 'osgDB/readerParser' );
var CustomMap = require( 'osg/Map' );
var TextureManager = require( 'osg/TextureManager' );
var WebglCaps = require( 'osg/WebGLCaps' );
var ImageBitmap = window.ImageBitmap || function () {};
// helper
var isPowerOf2 = function ( x ) {
/*jshint bitwise: false */
return ( ( x !== 0 ) && ( ( x & ( ~x + 1 ) ) === x ) );
/*jshint bitwise: true */
};
/**
* Texture encapsulate webgl texture object
* @class Texture
* Not that dirty here is mainly for texture binding
* any dirty will cause re-bind
* hint: don't dirty a texture attached to a camera/framebuffer
* it will end blank
* @inherits StateAttribute
*/
var Texture = function () {
StateAttribute.call( this );
GLObject.call( this );
this.setDefaultParameters();
this._dirty = true;
this._dirtyMipmap = true;
this._applyTexImage2DCallbacks = [];
this._textureObject = undefined;
this._textureNull = true;
};
var checkAndFixEnum = function ( mode, fallback ) {
var value = Texture[ mode ];
if ( value === undefined ) {
Notify.warn( 'bad Texture enum argument ' + mode + '\n' + 'fallback to ' + fallback );
return fallback;
}
return value;
};
Texture.UNPACK_COLORSPACE_CONVERSION_WEBGL = 0x9243;
Texture.UNPACK_FLIP_Y_WEBGL = 0x9240;
Texture.BROWSER_DEFAULT_WEBGL = 0x9244;
Texture.NONE = 0x0;
Texture.DEPTH_COMPONENT = 0x1902;
Texture.ALPHA = 0x1906;
Texture.RGB = 0x1907;
Texture.RGBA = 0x1908;
Texture.LUMINANCE = 0x1909;
Texture.LUMINANCE_ALPHA = 0x190A;
// DXT formats, from:
// http://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_s3tc/
Texture.COMPRESSED_RGB_S3TC_DXT1_EXT = 0x83F0;
Texture.COMPRESSED_RGBA_S3TC_DXT1_EXT = 0x83F1;
Texture.COMPRESSED_RGBA_S3TC_DXT3_EXT = 0x83F2;
Texture.COMPRESSED_RGBA_S3TC_DXT5_EXT = 0x83F3;
// ATC formats, from:
// http://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_atc/
Texture.COMPRESSED_RGB_ATC_WEBGL = 0x8C92;
Texture.COMPRESSED_RGBA_ATC_EXPLICIT_ALPHA_WEBGL = 0x8C93;
Texture.COMPRESSED_RGBA_ATC_INTERPOLATED_ALPHA_WEBGL = 0x87EE;
// PVR formats, from:
// http://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_pvrtc/
Texture.COMPRESSED_RGB_PVRTC_4BPPV1_IMG = 0x8C00;
Texture.COMPRESSED_RGB_PVRTC_2BPPV1_IMG = 0x8C01;
Texture.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG = 0x8C02;
Texture.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG = 0x8C03;
// ETC1 format, from:
// http://www.khronos.org/registry/webgl/extensions/WEBGL_compressed_texture_etc1/
Texture.COMPRESSED_RGB_ETC1_WEBGL = 0x8D64;
// filter mode
Texture.LINEAR = 0x2601;
Texture.NEAREST = 0x2600;
Texture.NEAREST_MIPMAP_NEAREST = 0x2700;
Texture.LINEAR_MIPMAP_NEAREST = 0x2701;
Texture.NEAREST_MIPMAP_LINEAR = 0x2702;
Texture.LINEAR_MIPMAP_LINEAR = 0x2703;
// filter anisotropy
Texture.TEXTURE_MAX_ANISOTROPY_EXT = 0x84FE;
Texture.MAX_TEXTURE_MAX_ANISOTROPY_EXT = 0x84FF;
// wrap mode
Texture.CLAMP_TO_EDGE = 0x812F;
Texture.REPEAT = 0x2901;
Texture.MIRRORED_REPEAT = 0x8370;
// target
Texture.TEXTURE_2D = 0x0DE1;
Texture.TEXTURE_CUBE_MAP = 0x8513;
Texture.TEXTURE_BINDING_CUBE_MAP = 0x8514;
Texture.TEXTURE_CUBE_MAP_POSITIVE_X = 0x8515;
Texture.TEXTURE_CUBE_MAP_NEGATIVE_X = 0x8516;
Texture.TEXTURE_CUBE_MAP_POSITIVE_Y = 0x8517;
Texture.TEXTURE_CUBE_MAP_NEGATIVE_Y = 0x8518;
Texture.TEXTURE_CUBE_MAP_POSITIVE_Z = 0x8519;
Texture.TEXTURE_CUBE_MAP_NEGATIVE_Z = 0x851A;
Texture.MAX_CUBE_MAP_TEXTURE_SIZE = 0x851C;
Texture.UNSIGNED_BYTE = 0x1401;
Texture.UNSIGNED_SHORT = 0x1403;
Texture.UNSIGNED_SHORT_4_4_4_4 = 0x8033;
Texture.UNSIGNED_SHORT_5_5_5_1 = 0x8034;
Texture.UNSIGNED_SHORT_5_6_5 = 0x8363;
Texture.FLOAT = 0x1406;
Texture.HALF_FLOAT_OES = Texture.HALF_FLOAT = 0x8D61;
Texture._sTextureManager = new window.Map();
// Getter for textureManager
Texture.getTextureManager = function ( gl ) {
if ( !Texture._sTextureManager.has( gl ) )
Texture._sTextureManager.set( gl, new TextureManager() );
return Texture._sTextureManager.get( gl );
};
Texture.getEnumFromString = function ( v ) {
var value = v;
if ( typeof ( value ) === 'string' )
value = checkAndFixEnum( value, v );
return value;
};
Texture.prototype = MACROUTILS.objectLibraryClass( MACROUTILS.objectInherit( GLObject.prototype, MACROUTILS.objectInherit( StateAttribute.prototype, {
attributeType: 'Texture',
cloneType: function () {
return new Texture();
},
dirty: function () {
this._dirty = true;
},
isDirty: function () {
return this._dirty;
},
isTextureNull: function () {
return this._textureNull;
},
getOrCreateUniforms: function ( unit ) {
if ( Texture.uniforms === undefined ) {
Texture.uniforms = [];
}
if ( Texture.uniforms[ unit ] === undefined ) {
var name = this.getType() + unit;
var uniformMap = new CustomMap();
var uniform = Uniform.createInt1( unit, name );
uniformMap.setMap( {
texture: uniform
} );
Texture.uniforms[ unit ] = uniformMap;
}
// uniform for an texture attribute should directly in Texture.uniforms[unit]
// and not in Texture.uniforms[unit][Texture0]
// Why it's in Texture.uniforms[unit]['texture'] :
// a 'texture' is a texture attribute but you also have old texenv
// that are texture attribute because they are applied on a texture unit.
// I admit that currently we dont have this or we used to but we dont have it anymore.
// It's the same design than osg.
// We could imagine for example a TextureGreyScale texture attributes,
// that would transform the input texture
// on unit X into greyscale used in the shader.
return Texture.uniforms[ unit ];
},
setDefaultParameters: function () {
this._image = undefined;
this._magFilter = Texture.LINEAR;
this._minFilter = Texture.LINEAR;
this._maxAnisotropy = 1.0;
this._wrapS = Texture.CLAMP_TO_EDGE;
this._wrapT = Texture.CLAMP_TO_EDGE;
this._textureWidth = 0;
this._textureHeight = 0;
this._unrefImageDataAfterApply = false;
this._internalFormat = undefined;
this._dirtyMipmap = true;
this._textureTarget = Texture.TEXTURE_2D;
this._type = Texture.UNSIGNED_BYTE;
this._isCompressed = false;
this._flipY = true;
this._colorSpaceConversion = Texture.NONE; //Texture.BROWSER_DEFAULT_WEBGL;
},
// check https://www.khronos.org/registry/webgl/specs/latest/1.0/#PIXEL_STORAGE_PARAMETERS
setColorSpaceConversion: function ( enumValue ) {
this._colorSpaceConversion = enumValue;
},
setFlipY: function ( bool ) {
this._flipY = bool;
},
getTextureTarget: function () {
return this._textureTarget;
},
getTextureObject: function () {
return this._textureObject;
},
setTextureSize: function ( w, h ) {
var maxSize = WebglCaps.instance().getWebGLParameter( 'MAX_TEXTURE_SIZE' );
if ( w !== this._textureWidth || h !== this._textureHeight )
this.dirty();
if ( w !== undefined ) {
if ( w > maxSize ) {
Notify.error( 'width (' + w + ') too big for GPU. Max Texture Size is "' + maxSize + '"' );
this._textureWidth = maxSize;
} else {
this._textureWidth = w;
}
}
if ( h !== undefined ) {
if ( h > maxSize ) {
Notify.error( 'height (' + h + ') too big for GPU. Max Texture Size is "' + maxSize + '"' );
this._textureHeight = maxSize;
} else {
this._textureHeight = h;
}
}
this._textureNull = false;
},
init: function ( state ) {
if ( !this._gl ) this.setGraphicContext( state.getGraphicContext() );
if ( !this._textureObject ) {
this._textureObject = Texture.getTextureManager( this._gl ).generateTextureObject( this._gl,
this,
this._textureTarget,
this._internalFormat,
this._textureWidth,
this._textureHeight );
this.dirty();
this._dirtyTextureObject = false;
this._textureNull = false;
}
},
addApplyTexImage2DCallback: function ( callback ) {
var index = this._applyTexImage2DCallbacks.indexOf( callback );
if ( index < 0 ) {
this._applyTexImage2DCallbacks.push( callback );
}
},
removeApplyTexImage2DCallback: function ( callback ) {
var index = this._applyTexImage2DCallbacks.indexOf( callback );
if ( index >= 0 ) {
this._applyTexImage2DCallbacks.splice( index, 1 );
}
},
getWidth: function () {
return this._textureWidth;
},
getHeight: function () {
return this._textureHeight;
},
releaseGLObjects: function () {
if ( this._textureObject !== undefined && this._textureObject !== null && this._gl !== undefined ) {
Texture.getTextureManager( this._gl ).releaseTextureObject( this._textureObject );
}
this._textureObject = undefined;
},
getWrapT: function () {
return this._wrapT;
},
getWrapS: function () {
return this._wrapS;
},
setWrapS: function ( value ) {
if ( typeof value === 'string' ) {
this._wrapS = checkAndFixEnum( value, Texture.CLAMP_TO_EDGE );
} else {
this._wrapS = value;
}
this.dirtyTextureParameters();
},
setWrapT: function ( value ) {
if ( typeof value === 'string' ) {
this._wrapT = checkAndFixEnum( value, Texture.CLAMP_TO_EDGE );
} else {
this._wrapT = value;
}
this.dirtyTextureParameters();
},
// TODO CP:
// we should split dirty texture object of parameters
// dirty parameters only regenarate parameter
// dirty texture object needs to release a texture and
// re allocate one
dirtyTextureParameters: function () {
this.dirty(); // make everything dirty for now
this.dirtyMipmap();
this.dirtyTextureObject();
},
dirtyTextureObject: function () {
this._dirtyTextureObject = true;
this.dirtyMipmap();
this.dirty(); // make everything dirty for now
},
getMinFilter: function () {
return this._minFilter;
},
getMagFilter: function () {
return this._magFilter;
},
// https://www.opengl.org/registry/specs/EXT/texture_filter_anisotropic.txt
setMaxAnisotropy: function ( multiplier ) {
this._maxAnisotropy = multiplier;
this.dirtyTextureParameters();
},
getMaxAnisotropy: function () {
return this._maxAnisotropy;
},
// some value enable mipmapping
setMinFilter: function ( value ) {
if ( typeof ( value ) === 'string' ) {
this._minFilter = checkAndFixEnum( value, Texture.LINEAR );
} else {
this._minFilter = value;
}
this.dirtyTextureParameters();
},
// Either Linear or nearest.
setMagFilter: function ( value ) {
if ( typeof ( value ) === 'string' ) {
this._magFilter = checkAndFixEnum( value, Texture.LINEAR );
} else {
this._magFilter = value;
}
this.dirtyTextureParameters();
},
setImage: function ( img, imageFormat ) {
var image = img;
if ( img instanceof window.Image ||
img instanceof HTMLCanvasElement ||
img instanceof ImageBitmap ||
img instanceof Uint8Array ) {
image = new Image( img );
}
this._image = image;
this.setImageFormat( imageFormat );
if ( image ) {
if ( image.getWidth && image.getHeight ) {
this.setTextureSize( image.getWidth(), image.getHeight() );
} else if ( image.width && image.height ) {
this.setTextureSize( image.width, image.height );
}
}
this._textureNull = false;
this.dirty();
},
getImage: function () {
return this._image;
},
setImageFormat: function ( format ) {
var imageFormat = format;
if ( imageFormat ) {
if ( typeof imageFormat === 'string' )
imageFormat = Texture[ imageFormat ];
this._imageFormat = imageFormat;
} else {
this._imageFormat = Texture.RGBA;
}
},
setType: function ( value ) {
Notify.log( 'Texture.setType is deprecated, use instead Texture.setInternalFormatType' );
this.setInternalFormatType( value );
},
setInternalFormatType: function ( value ) {
if ( typeof value === 'string' ) {
this._type = Texture[ value ];
} else {
this._type = value;
}
},
getInternalFormatType: function () {
return this._type;
},
setUnrefImageDataAfterApply: function ( bool ) {
this._unrefImageDataAfterApply = bool;
},
checkIsCompressed: function ( format ) {
var fo = format || this._internalFormat;
switch ( fo ) {
case Texture.COMPRESSED_RGB_S3TC_DXT1_EXT:
case Texture.COMPRESSED_RGBA_S3TC_DXT1_EXT:
case Texture.COMPRESSED_RGBA_S3TC_DXT3_EXT:
case Texture.COMPRESSED_RGBA_S3TC_DXT5_EXT:
case Texture.COMPRESSED_RGB_ATC_WEBGL:
case Texture.COMPRESSED_RGBA_ATC_EXPLICIT_ALPHA_WEBGL:
case Texture.COMPRESSED_RGBA_ATC_INTERPOLATED_ALPHA_WEBGL:
case Texture.COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
case Texture.COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
case Texture.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
case Texture.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
case Texture.COMPRESSED_RGB_ETC1_WEBGL:
return true;
default:
return false;
}
},
setInternalFormat: function ( formatSource ) {
var format = formatSource;
if ( format ) {
if ( typeof format === 'string' )
format = Texture[ format ];
this._isCompressed = this.checkIsCompressed( format );
} else {
this._isCompressed = false;
format = Texture.RGBA;
}
this._internalFormat = format;
},
getInternalFormat: function () {
return this._internalFormat;
},
isDirtyMipmap: function () {
return this._dirtyMipmap;
},
// Will cause the mipmaps to be regenerated on the next bind of the texture
// Nothing will be done if the minFilter is not of the form XXX_MIPMAP_XXX
// TODO : not to be used if the texture is compressed !
dirtyMipmap: function () {
this._dirtyMipmap = true;
},
applyFilterParameter: function ( gl, target ) {
var powerOfTwo = isPowerOf2( this._textureWidth ) && isPowerOf2( this._textureHeight );
if ( !powerOfTwo ) {
// NPOT non support in webGL explained here
// https://www.khronos.org/webgl/wiki/WebGL_and_OpenGL_Differences#Non-Power_of_Two_Texture_Support
// so disabling mipmap...
this._wrapT = Texture.CLAMP_TO_EDGE;
this._wrapS = Texture.CLAMP_TO_EDGE;
if ( this._minFilter === Texture.LINEAR_MIPMAP_LINEAR ||
this._minFilter === Texture.LINEAR_MIPMAP_NEAREST ) {
this._minFilter = Texture.LINEAR;
}
}
gl.texParameteri( target, gl.TEXTURE_MAG_FILTER, this._magFilter );
gl.texParameteri( target, gl.TEXTURE_MIN_FILTER, this._minFilter );
// handle extension EXT_texture_filter_anisotropic
if ( this._maxAnisotropy > 1.0 && Texture.ANISOTROPIC_SUPPORT_EXT ) {
var multiplier = this._maxAnisotropy < Texture.ANISOTROPIC_SUPPORT_MAX ? this._maxAnisotropy : Texture.ANISOTROPIC_SUPPORT_MAX;
gl.texParameterf( target, Texture.TEXTURE_MAX_ANISOTROPY_EXT, multiplier );
}
gl.texParameteri( target, gl.TEXTURE_WRAP_S, this._wrapS );
gl.texParameteri( target, gl.TEXTURE_WRAP_T, this._wrapT );
},
generateMipmap: function ( gl, target ) {
this._dirtyMipmap = false;
if ( !this.hasMipmapFilter() ) return;
// manual mipmap provided
var img = this._image;
if ( img && img.hasMipmap() ) {
var internalFormat = this._internalFormat;
var mips = img.getMipmap();
for ( var level = 1, nbLevel = mips.length; level < nbLevel; level++ ) {
var imi = mips[ level ];
if ( this._isCompressed )
this.applyTexImage2D( gl, this._textureTarget, level, this._internalFormat, imi.getWidth(), imi.getHeight(), 0, imi.getImage() );
else
this.applyTexImage2D( gl, this._textureTarget, level, internalFormat, imi.getWidth(), imi.getHeight(), 0, internalFormat, this._type, imi.getImage() );
}
} else {
// automatic mipmap
gl.generateMipmap( target );
}
},
// return true if contains a mipmap filter
hasMipmapFilter: function () {
return this._minFilter === Texture.NEAREST_MIPMAP_NEAREST ||
this._minFilter === Texture.LINEAR_MIPMAP_NEAREST ||
this._minFilter === Texture.NEAREST_MIPMAP_LINEAR ||
this._minFilter === Texture.LINEAR_MIPMAP_LINEAR;
},
applyTexImage2D: function ( gl ) {
var args = Array.prototype.slice.call( arguments, 1 );
MACROUTILS.timeStamp( 'osgjs.metrics:Texture.texImage2d' );
// use parameters of pixel store
gl.pixelStorei( gl.UNPACK_FLIP_Y_WEBGL, this._flipY );
gl.pixelStorei( gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, this._colorSpaceConversion );
if ( this._isCompressed ) gl.compressedTexImage2D.apply( gl, args );
else gl.texImage2D.apply( gl, args );
// call a callback when upload is done if there is one
var numCallback = this._applyTexImage2DCallbacks.length;
if ( numCallback > 0 ) {
for ( var i = 0, l = numCallback; i < l; i++ ) {
this._applyTexImage2DCallbacks[ i ].call( this );
}
}
},
computeTextureFormat: function () {
if ( !this._internalFormat ) {
this._internalFormat = this._imageFormat || Texture.RGBA;
this._imageFormat = this._internalFormat;
} else {
this._imageFormat = this._internalFormat;
}
},
applyImage: function ( gl, image ) {
if ( this._isCompressed ) {
this.applyTexImage2D( gl, this._textureTarget, 0, this._internalFormat, this._textureWidth, this._textureHeight, 0, image.getImage() );
} else if ( image.isTypedArray() ) {
this.applyTexImage2D( gl,
this._textureTarget,
0,
this._internalFormat,
this._textureWidth,
this._textureHeight,
0,
this._internalFormat,
this._type,
this._image.getImage() );
} else {
this.applyTexImage2D( gl,
this._textureTarget,
0,
this._internalFormat,
this._internalFormat,
this._type,
image.getImage() );
}
image.setDirty( false );
},
apply: function ( state ) {
var gl = state.getGraphicContext();
// if need to release the texture
if ( this._dirtyTextureObject ) {
this.releaseGLObjects();
this._dirtyTextureObject = false;
}
if ( this._textureObject !== undefined && !this.isDirty() ) {
this._textureObject.bind( gl );
// If we have modified the texture via Rtt or texSubImage2D and _need_ updated mipmaps,
// then we must regenerate the mipmaps explicitely.
// In all other cases, don't set this flag because it can be costly
if ( this.isDirtyMipmap() ) {
this.generateMipmap( gl, this._textureTarget );
}
// image update like video
if ( this._image !== undefined && this._image.isDirty() ) {
this.applyImage( gl, this._image );
}
} else if ( this._textureNull ) {
gl.bindTexture( this._textureTarget, null );
} else {
var image = this._image;
if ( image !== undefined ) {
// when data is ready we will upload it to the gpu
if ( image.isReady() ) {
// must be called before init
this.computeTextureFormat();
var imgWidth = image.getWidth() || this._textureWidth;
var imgHeight = image.getHeight() || this._textureHeight;
this.setTextureSize( imgWidth, imgHeight );
if ( !this._textureObject ) {
this.init( state );
}
this._textureObject.bind( gl );
this.applyImage( gl, this._image );
this.applyFilterParameter( gl, this._textureTarget );
this.generateMipmap( gl, this._textureTarget );
if ( this._unrefImageDataAfterApply ) {
this._image = undefined;
}
this._dirty = false;
} else {
gl.bindTexture( this._textureTarget, null );
}
} else if ( this._textureHeight !== 0 && this._textureWidth !== 0 ) {
// must be called before init
this.computeTextureFormat();
if ( !this._textureObject ) {
this.init( state );
}
this._textureObject.bind( gl );
this.applyTexImage2D( gl, this._textureTarget, 0, this._internalFormat, this._textureWidth, this._textureHeight, 0, this._internalFormat, this._type, null );
this.applyFilterParameter( gl, this._textureTarget );
this.generateMipmap( gl, this._textureTarget );
this._dirty = false;
}
}
}
} ) ), 'osg', 'Texture' );
MACROUTILS.setTypeID( Texture );
Texture.textureNull = new Texture();
Texture.createFromImage = function ( image, format ) {
var a = new Texture();
a.setImage( image, format );
return a;
};
Texture.createFromCanvas = function ( canvas, format ) {
return Texture.createFromImage( canvas, format );
};
Texture.create = function ( url ) {
Notify.log( 'Texture.create is deprecated, use Texture.createFromURL instead' );
return Texture.createFromURL( url );
};
Texture.createFromURL = function ( imageSource, format ) {
Notify.log( 'Texture.createFromURL is deprecated, use instead osgDB.readImageURL' );
var texture = new Texture();
ReaderParser.readImage( imageSource ).then( function ( img ) {
texture.setImage( img, format );
} );
return texture;
};
module.exports = Texture;

Wyświetl plik

@ -1,230 +0,0 @@
'use strict';
var MACROUTILS = require( 'osg/Utils' );
var Image = require( 'osg/Image' );
var Notify = require( 'osg/notify' );
var Texture = require( 'osg/Texture' );
/**
* TextureCubeMap
* @class TextureCubeMap
* @inherits Texture
*/
var TextureCubeMap = function () {
Texture.call( this );
this._images = {};
// pre allocated all textures faces slots
for ( var i = 0; i < 6; i++ ) {
this._images[ Texture.TEXTURE_CUBE_MAP_POSITIVE_X + i ] = new Image();
}
};
/** @lends TextureCubeMap.prototype */
TextureCubeMap.prototype = MACROUTILS.objectLibraryClass( MACROUTILS.objectInherit( Texture.prototype, {
setDefaultParameters: function () {
Texture.prototype.setDefaultParameters.call( this );
this._textureTarget = Texture.TEXTURE_CUBE_MAP;
this._flipY = false;
},
cloneType: function () {
return new TextureCubeMap();
},
setImage: function ( imageFace, img, imageFormat ) {
var face = imageFace;
if ( typeof face === 'string' )
face = Texture[ face ];
this._images[ face ].setImage( img, imageFormat );
this.setImageFormat( imageFormat );
this.setTextureSize( this._images[ face ].getWidth(), this._images[ face ].getHeight() );
this._textureNull = false;
this.dirty();
},
getImage: function ( face ) {
return this._images[ face ].getImage();
},
initCubemapContent: function ( gl ) {
var internalFormat = this._internalFormat;
this.applyTexImage2D( gl, gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, internalFormat, this._textureWidth, this._textureHeight, 0, internalFormat, this._type, null );
this.applyTexImage2D( gl, gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, internalFormat, this._textureWidth, this._textureHeight, 0, internalFormat, this._type, null );
this.applyTexImage2D( gl, gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, internalFormat, this._textureWidth, this._textureHeight, 0, internalFormat, this._type, null );
this.applyTexImage2D( gl, gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, internalFormat, this._textureWidth, this._textureHeight, 0, internalFormat, this._type, null );
this.applyTexImage2D( gl, gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, internalFormat, this._textureWidth, this._textureHeight, 0, internalFormat, this._type, null );
this.applyTexImage2D( gl, gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, internalFormat, this._textureWidth, this._textureHeight, 0, internalFormat, this._type, null );
return true;
},
// handle mipmap logic, if images for mipmap are provided or not
generateMipmap: function ( gl, target ) {
if ( !this.hasMipmapFilter() ) return;
// manual mipmap provided
if ( this._images[ Texture.TEXTURE_CUBE_MAP_POSITIVE_X ].hasMipmap() ) {
for ( var face = 0; face < 6; face++ ) {
var faceImage = this._images[ Texture.TEXTURE_CUBE_MAP_POSITIVE_X + face ];
if ( !faceImage.hasMipmap() ) {
Notify.error( 'mipmap not set correctly for TextureCubemap' );
}
var internalFormat = this._internalFormat;
for ( var level = 1; level < faceImage.getMipmap().length; level++ ) {
var size = faceImage.getMipmap()[ level ].getWidth();
this.applyTexImage2D( gl, gl.TEXTURE_CUBE_MAP_POSITIVE_X + face, level, internalFormat, size, size, 0, internalFormat, this._type, faceImage.getMipmap()[ level ].getImage() );
}
}
} else {
// automatic mipmap
gl.generateMipmap( target );
}
this._dirtyMipmap = false;
},
applyImageTarget: function ( gl, internalFormat, target ) {
var faceImage = this._images[ target ];
if ( !faceImage.getImage() ) return 0;
if ( !faceImage.isReady() ) return 0;
if ( !faceImage.isDirty() ) return 1;
this.setTextureSize( faceImage.getWidth(), faceImage.getHeight() );
faceImage.setDirty( false );
if ( faceImage.isTypedArray() ) {
this.applyTexImage2D( gl,
target,
0,
internalFormat,
this._textureWidth,
this._textureHeight,
0,
internalFormat,
this._type,
faceImage.getImage() );
} else {
this.applyTexImage2D( gl,
target,
0,
internalFormat,
internalFormat,
this._type,
faceImage.getImage() );
}
// release here only if no mipmap
if ( this._unrefImageDataAfterApply &&
!( this.hasMipmap() && faceImage.hasMipmap() ) ) {
faceImage.release();
}
return 1;
},
initCubemapContentImage: function ( gl ) {
var internalFormat = this._internalFormat;
var valid = 0;
valid += this.applyImageTarget( gl, internalFormat, gl.TEXTURE_CUBE_MAP_POSITIVE_X );
valid += this.applyImageTarget( gl, internalFormat, gl.TEXTURE_CUBE_MAP_NEGATIVE_X );
valid += this.applyImageTarget( gl, internalFormat, gl.TEXTURE_CUBE_MAP_POSITIVE_Y );
valid += this.applyImageTarget( gl, internalFormat, gl.TEXTURE_CUBE_MAP_NEGATIVE_Y );
valid += this.applyImageTarget( gl, internalFormat, gl.TEXTURE_CUBE_MAP_POSITIVE_Z );
valid += this.applyImageTarget( gl, internalFormat, gl.TEXTURE_CUBE_MAP_NEGATIVE_Z );
if ( valid === 6 )
return true;
return false;
},
apply: function ( state ) {
var gl = state.getGraphicContext();
// if need to release the texture
if ( this._dirtyTextureObject )
this.releaseGLObjects();
if ( this._textureObject !== undefined && !this.isDirty() ) {
this._textureObject.bind( gl );
// If we have modified the texture via Rtt or texSubImage2D and _need_ updated mipmaps,
// then we must regenerate the mipmaps explicitely.
// In all other cases, don't set this flag because it can be costly
if ( this.isDirtyMipmap() ) {
this.generateMipmap( gl, this._textureTarget );
}
} else if ( this._textureNull ) {
gl.bindTexture( this._textureTarget, null );
} else {
if ( !this._textureObject ) {
// must be called before init
this.computeTextureFormat();
this.init( state );
}
this._textureObject.bind( gl );
var valid;
// no images it's must be a cubemap filled from rtt
if ( !this._images[ Texture.TEXTURE_CUBE_MAP_POSITIVE_X ].getImage() ) {
valid = this.initCubemapContent( gl );
} else {
valid = this.initCubemapContentImage( gl );
}
if ( valid ) {
this._dirty = false;
this.applyFilterParameter( gl, this._textureTarget );
this.generateMipmap( gl, this._textureTarget );
}
} // render to cubemap not yet implemented
}
} ), 'osg', 'TextureCubeMap' );
MACROUTILS.setTypeID( TextureCubeMap );
module.exports = TextureCubeMap;

Wyświetl plik

@ -1,272 +0,0 @@
'use strict';
var Notify = require( 'osg/notify' );
var Timer = require( 'osg/Timer' );
var TextureProfile = function ( target, internalFormat, width, height ) {
this._target = target;
this._internalFormat = internalFormat;
this._width = width;
this._height = height;
this._size = 0;
this.computeSize();
};
TextureProfile.prototype = {
match: function ( textureProfile ) {
return textureProfile._target === this._target &&
textureProfile._internalFormat === this._internalFormat &&
textureProfile._width === this._width &&
textureProfile._height === this._height;
},
computeSize: function () {
var Texture = require( 'osg/Texture' );
var numBitsPerTexel = 0;
switch ( this._internalFormat ) {
case ( 1 ):
numBitsPerTexel = 8;
break;
case ( Texture.ALPHA ):
numBitsPerTexel = 8;
break;
case ( Texture.LUMINANCE ):
numBitsPerTexel = 8;
break;
case ( Texture.LUMINANCE_ALPHA ):
numBitsPerTexel = 16;
break;
case ( 2 ):
numBitsPerTexel = 16;
break;
case ( Texture.RGB ):
numBitsPerTexel = 24;
break;
case ( 3 ):
numBitsPerTexel = 24;
break;
case ( Texture.RGBA ):
numBitsPerTexel = 32;
break;
case ( 4 ):
numBitsPerTexel = 32;
break;
}
var size = ( Math.ceil( this._width * this._height * numBitsPerTexel ) / 8.0 );
if ( this._target === Texture.TEXTURE_CUBE_MAP )
size *= 6.0;
// add the mipmap overhead size even if not used
size += size / 3.0;
this._size = size;
},
getSize: function () {
return this._size;
}
};
TextureProfile.getHash = function () {
var array = Array.prototype.slice.call( arguments );
var hash = '';
array.forEach( function ( element ) {
hash += element;
} );
return hash;
};
var TextureObject = function ( texture, id, textureSet ) {
this._texture = texture;
this._id = id;
this._textureSet = textureSet;
};
TextureObject.prototype = {
target: function () {
return this._textureSet._profile._target;
},
id: function () {
return this._id;
},
getTextureSet: function () {
return this._textureSet;
},
reset: function () {
this._textureObject = null;
this._texture = undefined;
},
bind: function ( gl ) {
gl.bindTexture( this.target(), this._id );
}
};
var TextureObjectSet = function ( profile ) {
this._profile = profile;
this._usedTextureObjects = [];
this._orphanedTextureObjects = [];
};
TextureObjectSet.prototype = {
getProfile: function () {
return this._profile;
},
getUsedTextureObjects: function () {
return this._usedTextureObjects;
},
getOrphanedTextureObjects: function () {
return this._orphanedTextureObjects;
},
takeOrGenerate: function ( gl, texture ) {
var textureObject;
if ( this._orphanedTextureObjects.length > 0 ) {
textureObject = this.takeFromOrphans();
textureObject._texture = texture;
this._usedTextureObjects.push( textureObject );
return textureObject;
}
var textureID = gl.createTexture();
textureObject = new TextureObject( texture, textureID, this );
this._usedTextureObjects.push( textureObject );
return textureObject;
},
// get texture object from pool
takeFromOrphans: function () {
if ( this._orphanedTextureObjects.length )
return this._orphanedTextureObjects.pop();
return undefined;
},
// release texture object
orphan: function ( textureObject ) {
var index = this._usedTextureObjects.indexOf( textureObject );
if ( index !== -1 ) {
this._orphanedTextureObjects.push( this._usedTextureObjects[ index ] );
this._usedTextureObjects.splice( index, 1 );
}
},
flushDeletedTextureObjects: function ( gl, availableTime ) {
// if no time available don't try to flush objects.
if ( availableTime <= 0.0 ) return availableTime;
var nbTextures = this._orphanedTextureObjects.length;
// Should we use a maxSizeTexturePool value?
//var size = this.getProfile().getSize();
// We need to test if we have time to flush
var elapsedTime = 0.0;
var beginTime = Timer.instance().tick();
var i;
for ( i = 0; i < nbTextures && elapsedTime < availableTime; i++ ) {
gl.deleteTexture( this._orphanedTextureObjects[ i ].id() );
this._orphanedTextureObjects[ i ].reset();
elapsedTime = Timer.instance().deltaS( beginTime, Timer.instance().tick() );
}
this._orphanedTextureObjects.splice( 0, i );
return availableTime - elapsedTime;
},
flushAllDeletedTextureObjects: function ( gl ) {
var nbTextures = this._orphanedTextureObjects.length;
var size = this.getProfile().getSize();
for ( var i = 0, j = nbTextures; i < j; ++i ) {
gl.deleteTexture( this._orphanedTextureObjects[ i ].id() );
this._orphanedTextureObjects[ i ].reset();
}
this._orphanedTextureObjects.length = 0;
Notify.info( 'TextureManager: released ' + nbTextures + ' with ' + ( nbTextures * size / ( 1024 * 1024 ) ) + ' MB' );
}
};
var TextureManager = function () {
this._textureSetMap = {};
};
TextureManager.prototype = {
generateTextureObject: function ( gl,
texture,
target,
internalFormat,
width,
height ) {
var hash = TextureProfile.getHash( target, internalFormat, width, height );
if ( this._textureSetMap[ hash ] === undefined ) {
this._textureSetMap[ hash ] = new TextureObjectSet( new TextureProfile( target, internalFormat, width, height ) );
}
var textureSet = this._textureSetMap[ hash ];
var textureObject = textureSet.takeOrGenerate( gl, texture );
return textureObject;
},
updateStats: function ( frameNumber, rStats ) {
var totalUsed = 0;
var totalUnused = 0;
window.Object.keys( this._textureSetMap ).forEach( function ( key ) {
var profile = this._textureSetMap[ key ].getProfile();
var size = profile.getSize();
var nbUsed = this._textureSetMap[ key ].getUsedTextureObjects().length;
var nbUnused = this._textureSetMap[ key ].getOrphanedTextureObjects().length;
totalUsed += nbUsed * size;
totalUnused += nbUnused * size;
}, this );
var MB = 1024 * 1024;
rStats( 'textureused' ).set( totalUsed / MB );
rStats( 'texturereserved' ).set( totalUnused / MB );
rStats( 'texturetotal' ).set( ( totalUsed + totalUnused ) / MB );
},
reportStats: function () {
var total = 0;
window.Object.keys( this._textureSetMap ).forEach( function ( key ) {
var profile = this._textureSetMap[ key ].getProfile();
var size = profile.getSize() / ( 1024 * 1024 );
var nb = this._textureSetMap[ key ].getUsedTextureObjects().length;
size *= nb;
total += size;
Notify.notice( String( size ) + ' MB with ' + nb + ' texture of ' + profile._width + 'x' + profile._height + ' ' + profile._internalFormat );
}, this );
Notify.notice( String( total ) + ' MB in total' );
},
flushAllDeletedTextureObjects: function ( gl ) {
window.Object.keys( this._textureSetMap ).forEach( function ( key ) {
this._textureSetMap[ key ].flushAllDeletedTextureObjects( gl );
}, this );
},
flushDeletedTextureObjects: function ( gl, availableTimeArg ) {
var availableTime = availableTimeArg;
var keys = window.Object.keys( this._textureSetMap );
for ( var i = 0, j = keys.length; i < j && availableTime > 0.0; i++ ) {
availableTime = this._textureSetMap[ keys[ i ] ].flushDeletedTextureObjects( gl, availableTime );
}
return availableTime;
},
releaseTextureObject: function ( textureObject ) {
if ( textureObject ) {
var ts = textureObject.getTextureSet();
ts.orphan( textureObject );
}
}
};
module.exports = TextureManager;

Wyświetl plik

@ -1,55 +0,0 @@
// user performance if available or fallback
'use strict';
var now = ( function () {
var w = window || global;
// if no window.performance
if ( w.performance === undefined ) {
return function () {
return Date.now();
};
}
var fn = w.performance.now || w.performance.mozNow || w.performance.msNow || w.performance.oNow || w.performance.webkitNow ||
function () {
return Date.now();
};
return function () {
return fn.apply( w.performance, arguments );
};
} )();
var Timer = function () {};
Timer.instance = function () {
if ( !Timer._instance )
Timer._instance = new Timer();
return Timer._instance;
};
Timer.prototype = {
// delta in seconds
deltaS: function ( t0, t1 ) {
return ( t1 - t0 ) / 1000.0;
},
// delta in milliseconds
deltaM: function ( t0, t1 ) {
return t1 - t0;
},
tick: function () {
return now();
}
};
module.exports = Timer;

Wyświetl plik

@ -1,382 +0,0 @@
'use strict';
var Notify = require( 'osg/notify' );
/*
use EXT_disjoint_timer_queryto time webgl calls GPU side average over multiple frames
If timestamp feature is not supported, we virtualize the query by splitting and adding
dummy queries, that way it should handle both nested and interleaved queries.
Also, if you time the same queryID multiple time in the same frame, it will sum the different
queries, that way you can track a particular of gl command for examples
*/
var TimerGPU = function ( gl ) {
this._enabled = false;
if ( gl ) {
var ext = gl.getExtension( 'EXT_disjoint_timer_query' );
if ( !ext ) return this;
// https://github.com/KhronosGroup/WebGL/blob/master/sdk/tests/conformance/extensions/ext-disjoint-timer-query.html#L102
// run the page if strange results
// to validate you gpu/browser has correct gpu queries support
this._hasTimeElapsed = ext.getQueryEXT( ext.TIME_ELAPSED_EXT, ext.QUERY_COUNTER_BITS_EXT ) >= 30;
this._hasTimeStamp = ext.getQueryEXT( ext.TIMESTAMP_EXT, ext.QUERY_COUNTER_BITS_EXT ) >= 30;
if ( !this._hasTimeElapsed && !this._hasTimeStamp ) {
return this;
}
// no timestamp means not start/end absolute time
// which means each start must be followed by a end
// BEFORE any other start (of other queryID)
if ( !this._hasTimeStamp ) Notify.debug( 'Warning: do not use interleaved GPU query' );
this._gl = gl;
this._glTimer = ext;
this._enabled = true;
}
this._frameAverageCount = 10;
this._glQueries = [];
this._queriesByID = {};
this._userQueries = []; // for timestamp, it's the same as _glQueries
// stuffs used to virtualize query (no timestamp)
this._queryCount = 0;
this._nbOpened = 0;
};
TimerGPU.FRAME_COUNT = 0;
TimerGPU.instance = function ( gl ) {
if ( !TimerGPU._instance ) {
TimerGPU._instance = new TimerGPU( gl );
} else if ( gl && TimerGPU._instance.getContext() !== gl ) {
TimerGPU._instance.setContext( gl );
}
return TimerGPU._instance;
};
TimerGPU.prototype = {
getContext: function () {
return this._gl;
},
setContext: function ( gl ) {
this._gl = gl;
},
setFrameAverageCount: function ( val ) {
this._frameAverageCount = val;
},
clearQueries: function () {
var glQueries = this._glQueries;
for ( var i = 0, nbQueries = glQueries.length; i < nbQueries; ++i ) {
var query = glQueries[ i ];
this._glTimer.deleteQueryEXT( query._pollingStartQuery );
if ( query._pollingEndQuery ) this._glTimer.deleteQueryEXT( query );
}
this._userQueries.length = 0;
this._glQueries.length = 0;
this._queriesByID = {};
},
supportTimeStamp: function () {
return this._hasTimeStamp;
},
// many browser doesn't yet have
// the marvellous gpu timers
enable: function () {
// enable only if we have the extension
this._enabled = this._glTimer;
},
disable: function () {
this._enabled = false;
},
isEnabled: function () {
return this._enabled;
},
setCallback: function ( cb ) {
this._callback = cb;
},
createUserQuery: function ( queryID ) {
var query;
if ( this._hasTimeStamp ) {
query = this.createGLQuery();
} else {
query = {
_startIndex: 0,
_endIndex: 0
};
}
query._id = queryID;
query._frame = TimerGPU.FRAME_COUNT;
query._isOpened = true;
query._siblings = []; // if the query is called multiple time in the same frame
return query;
},
createGLQuery: function () {
var query = {};
query._isWaiting = false; // wait typically 1 or 2 frames
query._pollingStartQuery = undefined; // gl query object
query._pollingEndQuery = undefined; // gl query object (timestamp only)
query._averageTimer = 0.0; // cumulative average time
query._resultCount = 0; // cumulative average count
if ( this._hasTimeStamp ) query._pollingEndQuery = this._glTimer.createQueryEXT();
query._pollingStartQuery = this._glTimer.createQueryEXT();
this._glQueries.push( query );
return query;
},
getOrCreateLastGLQuery: function () {
var query = this._glQueries[ this._queryCount - 1 ];
if ( query ) return query;
query = this._glQueries[ this._queryCount - 1 ] = this.createGLQuery();
return query;
},
beginCurrentQuery: function () {
if ( this._nbOpened === 0 ) return;
this._queryCount++;
var query = this.getOrCreateLastGLQuery();
if ( !query._isWaiting ) {
this._glTimer.beginQueryEXT( this._glTimer.TIME_ELAPSED_EXT, query._pollingStartQuery );
}
},
endCurrentQuery: function () {
if ( this._nbOpened === 0 ) return;
if ( !this.getOrCreateLastGLQuery()._isWaiting ) {
this._glTimer.endQueryEXT( this._glTimer.TIME_ELAPSED_EXT );
}
},
getAvailableQueryByID: function ( queryID ) {
var query = this._queriesByID[ queryID ];
if ( !query ) {
query = this._queriesByID[ queryID ] = this.createUserQuery( queryID );
this._userQueries.push( query );
return query;
}
if ( query._frame === TimerGPU.FRAME_COUNT ) {
if ( query._isOpened ) return query;
var siblings = query._siblings;
for ( var i = 0, nbSiblings = siblings.length; i < nbSiblings; ++i ) {
var qsib = siblings[ i ];
if ( qsib._frame !== TimerGPU.FRAME_COUNT || qsib._isOpened ) {
qsib._frame = TimerGPU.FRAME_COUNT;
return qsib;
}
}
var newQuery = this.createUserQuery();
siblings.push( newQuery );
return newQuery;
}
query._frame = TimerGPU.FRAME_COUNT;
return query;
},
// start recording time if query already exist, don't recreate
start: function ( queryID ) {
// If timing currently disabled or glTimer does not exist, exit early.
if ( !this._enabled ) {
return undefined;
}
var query = this.getAvailableQueryByID( queryID );
query._isOpened = true;
if ( this._hasTimeStamp ) {
if ( !query._isWaiting ) this._glTimer.queryCounterEXT( query._pollingStartQuery, this._glTimer.TIMESTAMP_EXT );
} else {
this.endCurrentQuery();
this._nbOpened++;
query._startIndex = this._queryCount;
this.beginCurrentQuery();
}
},
// stop query recording (if running) polls for results
end: function ( queryID ) {
if ( !this._enabled ) {
return;
}
var query = this.getAvailableQueryByID( queryID );
query._isOpened = false;
if ( this._hasTimeStamp ) {
if ( !query._isWaiting ) this._glTimer.queryCounterEXT( query._pollingEndQuery, this._glTimer.TIMESTAMP_EXT );
} else {
this.endCurrentQuery();
query._endIndex = this._queryCount;
this._nbOpened--;
this.beginCurrentQuery();
}
},
computeQueryAverageTime: function ( query ) {
var average = 0;
var glQueries = this._glQueries;
for ( var i = query._startIndex; i < query._endIndex; ++i ) {
var glAvg = glQueries[ i ]._averageTimer;
if ( glAvg < 0 ) return -1;
average += glAvg;
}
return average;
},
computeFullAverageTime: function ( query ) {
var average = this.computeQueryAverageTime( query );
if ( average < 0 ) return -1;
var siblings = query._siblings;
for ( var i = 0, nbSiblings = siblings.length; i < nbSiblings; ++i ) {
var qsib = siblings[ i ];
if ( qsib._frame !== TimerGPU.FRAME_COUNT - 1 )
continue;
var sibAvg = this.computeQueryAverageTime( qsib );
if ( sibAvg < 0 ) return -1;
average += sibAvg;
}
return average;
},
pollQueries: function () {
TimerGPU.FRAME_COUNT++;
this._queryCount = 0;
this._nbOpened = 0;
if ( !this._enabled || !this._callback ) {
return;
}
var glQueries = this._glQueries;
var nbGlQueries = glQueries.length;
var i;
// all timer are corrupted, clear the queries
var disjoint = this._gl.getParameter( this._glTimer.GPU_DISJOINT_EXT );
if ( disjoint ) {
for ( i = 0; i < nbGlQueries; ++i ) {
glQueries[ i ]._isWaiting = false;
}
return;
}
// update average time for each queries
for ( i = 0; i < nbGlQueries; ++i ) {
this.pollQuery( glQueries[ i ] );
}
var userQueries = this._userQueries;
var nbUserQueries = userQueries.length;
for ( i = 0; i < nbUserQueries; ++i ) {
var query = userQueries[ i ];
var average = this.computeFullAverageTime( query );
if ( average > 0 ) {
this._callback( average, query._id );
}
}
},
pollQuery: function ( query ) {
query._isWaiting = false;
// last to be queried
var lastQuery = this._hasTimeStamp ? query._pollingEndQuery : query._pollingStartQuery;
// wait till results are ready
var available = this._glTimer.getQueryObjectEXT( lastQuery, this._glTimer.QUERY_RESULT_AVAILABLE_EXT );
if ( !available ) {
query._isWaiting = true;
return 0;
}
var timeElapsed;
if ( this._hasTimeStamp ) {
var startTime = this._glTimer.getQueryObjectEXT( query._pollingStartQuery, this._glTimer.QUERY_RESULT_EXT );
var endTime = this._glTimer.getQueryObjectEXT( lastQuery, this._glTimer.QUERY_RESULT_EXT );
timeElapsed = endTime - startTime;
} else {
timeElapsed = this._glTimer.getQueryObjectEXT( lastQuery, this._glTimer.QUERY_RESULT_EXT );
}
query._resultCount++;
// restart cumulative average every frameAveragecount frames
if ( query._resultCount > this._frameAverageCount ) {
query._averageTimer = 0.0;
query._resultCount = 1;
}
// https://en.wikipedia.org/wiki/Moving_average#Cumulative_moving_average
query._averageTimer = query._averageTimer + ( ( timeElapsed - query._averageTimer ) / ( query._resultCount ) );
return query._averageTimer;
}
};
module.exports = TimerGPU;

Wyświetl plik

@ -1,43 +0,0 @@
'use strict';
var MACROUTILS = require( 'osg/Utils' );
var Node = require( 'osg/Node' );
var mat4 = require( 'osg/glMatrix' ).mat4;
var TransformEnums = require( 'osg/transformEnums' );
/**
* Transform - base class for Transform type node ( Camera, MatrixTransform )
* @class Transform
* @inherits Node
*/
var Transform = function () {
Node.call( this );
this.referenceFrame = TransformEnums.RELATIVE_RF;
};
/** @lends Transform.prototype */
Transform.prototype = MACROUTILS.objectInherit( Node.prototype, {
setReferenceFrame: function ( value ) {
this.referenceFrame = value;
},
getReferenceFrame: function () {
return this.referenceFrame;
},
computeBoundingSphere: ( function () {
var matrix = mat4.create();
return function ( bSphere ) {
Node.prototype.computeBoundingSphere.call( this, bSphere );
if ( !bSphere.valid() ) {
return bSphere;
}
mat4.identity( matrix );
// local to local world (not Global World)
this.computeLocalToWorldMatrix( matrix );
bSphere.transformMat4( bSphere, matrix );
return bSphere;
};
} )()
} );
module.exports = Transform;

Wyświetl plik

@ -1,96 +0,0 @@
'use strict';
var PrimitiveSet = require( 'osg/primitiveSet' );
var DrawElements = require( 'osg/DrawElements' );
var DrawArrays = require( 'osg/DrawArrays' );
// This class can be used to visit all the triangles of a geometry
var TriangleIndexFunctor = function () {};
var functorDrawElements = TriangleIndexFunctor.functorDrawElements = [];
var functorDrawArrays = TriangleIndexFunctor.functorDrawArrays = [];
functorDrawElements[ PrimitiveSet.TRIANGLES ] = function ( offset, count, indexes, cb ) {
var end = offset + count;
for ( var i = offset; i < end; i += 3 ) {
cb( indexes[ i ], indexes[ i + 1 ], indexes[ i + 2 ] );
}
};
functorDrawElements[ PrimitiveSet.TRIANGLE_STRIP ] = function ( offset, count, indexes, cb ) {
for ( var i = 2, j = offset; i < count; ++i, ++j ) {
if ( i % 2 ) cb( indexes[ j ], indexes[ j + 2 ], indexes[ j + 1 ] );
else cb( indexes[ j ], indexes[ j + 1 ], indexes[ j + 2 ] );
}
};
functorDrawElements[ PrimitiveSet.TRIANGLE_FAN ] = function ( offset, count, indexes, cb ) {
var first = indexes[ offset ];
for ( var i = 2, j = offset + 1; i < count; ++i, ++j ) {
cb( first, indexes[ j ], indexes[ j + 1 ] );
}
};
functorDrawArrays[ PrimitiveSet.TRIANGLES ] = function ( first, count, cb ) {
for ( var i = 2, pos = first; i < count; i += 3, pos += 3 ) {
cb( pos, pos + 1, pos + 2 );
}
};
functorDrawArrays[ PrimitiveSet.TRIANGLE_STRIP ] = function ( first, count, cb ) {
for ( var i = 2, pos = first; i < count; ++i, ++pos ) {
if ( i % 2 ) cb( pos, pos + 2, pos + 1 );
else cb( pos, pos + 1, pos + 2 );
}
};
functorDrawArrays[ PrimitiveSet.TRIANGLE_FAN ] = function ( first, count, cb ) {
for ( var i = 2, pos = first + 1; i < count; ++i, ++pos ) {
cb( first, pos, pos + 1 );
}
};
TriangleIndexFunctor.prototype = {
// You feed it with a callback that will be called for each triangle
// (with the 3 indexes of vertices as arguments)
init: function ( geom, cb ) {
this._geom = geom;
this._cb = cb;
},
apply: function () {
var geom = this._geom;
var primitives = geom.primitives;
if ( !primitives )
return;
var cb = this._cb;
var cbFunctor;
var nbPrimitives = primitives.length;
for ( var i = 0; i < nbPrimitives; i++ ) {
var primitive = primitives[ i ];
if ( primitive instanceof DrawElements ) {
cbFunctor = functorDrawElements[ primitive.getMode() ];
if ( cbFunctor ) {
var indexes = primitive.indices.getElements();
cbFunctor( primitive.getFirst() / indexes.BYTES_PER_ELEMENT, primitive.getCount(), indexes, cb );
}
} else if ( primitive instanceof DrawArrays ) {
cbFunctor = functorDrawArrays[ primitive.getMode() ];
if ( cbFunctor ) {
cbFunctor( primitive.getFirst(), primitive.getCount(), cb );
}
}
}
}
};
module.exports = TriangleIndexFunctor;

Wyświetl plik

@ -1,277 +0,0 @@
'use strict';
var Notify = require( 'osg/notify' );
/**
* Uniform manage variable used in glsl shader.
* @class Uniform
*/
var Uniform = function ( name ) {
this._data = undefined;
this._transpose = false;
this._glCall = '';
this._cache = undefined;
this._name = name;
this._type = undefined;
this._isMatrix = false;
};
Uniform.isUniform = function ( obj ) {
if ( typeof obj === 'object' && window.Object.getPrototypeOf( obj ) === Uniform.prototype ) {
return true;
}
return false;
};
/** @lends Uniform.prototype */
Uniform.prototype = {
getName: function () {
return this._name;
},
dirty: function () {
Notify.log( 'deprecated dont use Uniform.dirty anymore' );
},
getType: function () {
return this._type;
},
get: function () {
Notify.log( 'deprecated use getInternalArray instead' );
return this._data;
},
set: function ( array ) {
Notify.log( 'deprecated use setFloat/setInt instead' );
var value = array;
if ( !Array.isArray( value ) && value.byteLength === undefined )
this._data[ 0 ] = value;
else
this._data = array;
},
apply: function UniformApply( gl, location ) {
if ( !this._cache )
this._cache = gl[ this._glCall ];
if ( this._isMatrix )
this._cache.call( gl, location, this._transpose, this._data );
else
this._cache.call( gl, location, this._data );
},
// no type checking, so array should be valid
setInternalArray: function ( array ) {
this._data = array;
},
getInternalArray: function () {
return this._data;
},
setFloat: function ( f ) {
this._data[ 0 ] = f;
},
setFloat1: function ( f ) {
this._data[ 0 ] = f[ 0 ];
},
setFloat2: function ( f ) {
this._data[ 0 ] = f[ 0 ];
this._data[ 1 ] = f[ 1 ];
},
setFloat3: function ( f ) {
this._data[ 0 ] = f[ 0 ];
this._data[ 1 ] = f[ 1 ];
this._data[ 2 ] = f[ 2 ];
},
setFloat4: function ( f ) {
this._data[ 0 ] = f[ 0 ];
this._data[ 1 ] = f[ 1 ];
this._data[ 2 ] = f[ 2 ];
this._data[ 3 ] = f[ 3 ];
},
setFloat9: function ( f ) {
this._data[ 0 ] = f[ 0 ];
this._data[ 1 ] = f[ 1 ];
this._data[ 2 ] = f[ 2 ];
this._data[ 3 ] = f[ 3 ];
this._data[ 4 ] = f[ 4 ];
this._data[ 5 ] = f[ 5 ];
this._data[ 6 ] = f[ 6 ];
this._data[ 7 ] = f[ 7 ];
this._data[ 8 ] = f[ 8 ];
},
setFloat16: function ( f ) {
this._data[ 0 ] = f[ 0 ];
this._data[ 1 ] = f[ 1 ];
this._data[ 2 ] = f[ 2 ];
this._data[ 3 ] = f[ 3 ];
this._data[ 4 ] = f[ 4 ];
this._data[ 5 ] = f[ 5 ];
this._data[ 6 ] = f[ 6 ];
this._data[ 7 ] = f[ 7 ];
this._data[ 8 ] = f[ 8 ];
this._data[ 9 ] = f[ 9 ];
this._data[ 10 ] = f[ 10 ];
this._data[ 11 ] = f[ 11 ];
this._data[ 12 ] = f[ 12 ];
this._data[ 13 ] = f[ 13 ];
this._data[ 14 ] = f[ 14 ];
this._data[ 15 ] = f[ 15 ];
}
};
Uniform.prototype.setVec2 = Uniform.prototype.setFloat2;
Uniform.prototype.setVec3 = Uniform.prototype.setFloat3;
Uniform.prototype.setVec4 = Uniform.prototype.setFloat4;
Uniform.prototype.setMatrix4 = Uniform.prototype.setFloat16;
Uniform.prototype.setMatrix3 = Uniform.prototype.setFloat9;
Uniform.prototype.setInt = Uniform.prototype.setFloat;
Uniform.prototype.setInt1 = Uniform.prototype.setFloat1;
Uniform.prototype.setInt2 = Uniform.prototype.setFloat2;
Uniform.prototype.setInt3 = Uniform.prototype.setFloat3;
Uniform.prototype.setInt4 = Uniform.prototype.setFloat4;
var createUniformX = function ( dataOrName, uniformName, defaultConstructor, glSignature, type, isMatrix ) {
var data = uniformName === undefined ? undefined : dataOrName;
var uniform = new Uniform( uniformName === undefined ? dataOrName : uniformName );
uniform._data = defaultConstructor();
if ( data !== undefined ) {
if ( data.length ) {
for ( var i = 0, nbElts = data.length; i < nbElts; ++i )
uniform._data[ i ] = data[ i ];
} else {
uniform._data[ 0 ] = data;
}
}
uniform._glCall = glSignature;
uniform._type = type;
uniform._isMatrix = !!isMatrix;
return uniform;
};
var constructorFloat = function () {
return new Float32Array( 1 );
};
var constructorFloat2 = function () {
return new Float32Array( 2 );
};
var constructorFloat3 = function () {
return new Float32Array( 3 );
};
var constructorFloat4 = function () {
return new Float32Array( 4 );
};
var constructorInt = function () {
return new Int32Array( 1 );
};
var constructorInt2 = function () {
return new Int32Array( 2 );
};
var constructorInt3 = function () {
return new Int32Array( 3 );
};
var constructorInt4 = function () {
return new Int32Array( 4 );
};
var constructorMat2 = function () {
var out = new Float32Array( 4 );
out[ 0 ] = out[ 3 ] = 1.0;
return out;
};
var constructorMat3 = function () {
var out = new Float32Array( 9 );
out[ 0 ] = out[ 4 ] = out[ 8 ] = 1.0;
return out;
};
var constructorMat4 = function () {
var out = new Float32Array( 16 );
out[ 0 ] = out[ 5 ] = out[ 10 ] = out[ 15 ] = 1.0;
return out;
};
// works also for float array but data must be given
Uniform.createFloat1 = function ( data, uniformName ) {
return createUniformX( data, uniformName, constructorFloat, 'uniform1fv', 'float' );
};
Uniform.createInt1 = function ( data, uniformName ) {
return createUniformX( data, uniformName, constructorInt, 'uniform1iv', 'int' );
};
Uniform.createFloat2 = function ( data, uniformName ) {
return createUniformX( data, uniformName, constructorFloat2, 'uniform2fv', 'vec2' );
};
Uniform.createInt2 = function ( data, uniformName ) {
return createUniformX( data, uniformName, constructorInt2, 'uniform2iv', 'vec2i' );
};
Uniform.createFloat3 = function ( data, uniformName ) {
return createUniformX( data, uniformName, constructorFloat3, 'uniform3fv', 'vec3' );
};
Uniform.createInt3 = function ( data, uniformName ) {
return createUniformX( data, uniformName, constructorInt3, 'uniform3iv', 'vec3i' );
};
Uniform.createFloat4 = function ( data, uniformName ) {
return createUniformX( data, uniformName, constructorFloat4, 'uniform4fv', 'vec4' );
};
Uniform.createInt4 = function ( data, uniformName ) {
return createUniformX( data, uniformName, constructorInt4, 'uniform4iv', 'vec4i' );
};
Uniform.createMatrix2 = function ( data, uniformName ) {
return createUniformX( data, uniformName, constructorMat2, 'uniformMatrix2fv', 'mat2', true );
};
Uniform.createMatrix3 = function ( data, uniformName ) {
return createUniformX( data, uniformName, constructorMat3, 'uniformMatrix3fv', 'mat3', true );
};
Uniform.createMatrix4 = function ( data, uniformName ) {
return createUniformX( data, uniformName, constructorMat4, 'uniformMatrix4fv', 'mat4', true );
};
// alias
Uniform.float = Uniform.createFloatArray = Uniform.createFloat = Uniform.createFloat1;
Uniform.int = Uniform.createIntArray = Uniform.createInt = Uniform.createInt1;
Uniform.vec2 = Uniform.createFloat2Array = Uniform.createFloat2;
Uniform.vec2i = Uniform.createInt2Array = Uniform.createInt2;
Uniform.vec3 = Uniform.createFloat3Array = Uniform.createFloat3;
Uniform.vec3i = Uniform.createInt3Array = Uniform.createInt3;
Uniform.vec4 = Uniform.createFloat4Array = Uniform.createFloat4;
Uniform.vec4i = Uniform.createInt4Array = Uniform.createInt4;
Uniform.mat2 = Uniform.createMat2 = Uniform.createMatrix2;
Uniform.mat3 = Uniform.createMat3 = Uniform.createMatrix3;
Uniform.mat4 = Uniform.createMat4 = Uniform.createMatrix4;
module.exports = Uniform;

Wyświetl plik

@ -1,52 +0,0 @@
'use strict';
var MACROUTILS = require( 'osg/Utils' );
var NodeVisitor = require( 'osg/NodeVisitor' );
var UpdateVisitor = function () {
NodeVisitor.call( this );
this.visitorType = NodeVisitor.UPDATE_VISITOR;
this._numUpdateCallback = 0;
};
UpdateVisitor.prototype = MACROUTILS.objectInherit( NodeVisitor.prototype, {
resetStats: function () {
this._numUpdateCallback = 0;
},
apply: function ( node ) {
// a way to avoid extra call is to implement getNumChildrenRequiringUpdateTraversal
// and stateset.requiresUpdateTraversal()
// handle callback in stateset
var stateSet = node.getStateSet();
if ( stateSet && stateSet.requiresUpdateTraversal() ) {
var updateCallbackList = stateSet.getUpdateCallbackList();
var numStateSetUpdateCallback = updateCallbackList.length;
if ( numStateSetUpdateCallback ) {
this._numUpdateCallback += numStateSetUpdateCallback;
for ( var i = 0, l = numStateSetUpdateCallback; i < l; i++ )
updateCallbackList[ i ].update( stateSet, this );
}
}
// handle callback in nodes
var ncs = node.getUpdateCallbackList();
var numUpdateCallback = ncs.length;
for ( var j = 0; j < numUpdateCallback; j++ ) {
this._numUpdateCallback++;
if ( !ncs[ j ].update( node, this ) ) {
return;
}
}
if ( node.getNumChildrenRequiringUpdateTraversal() > 0 )
this.traverse( node );
}
} );
module.exports = UpdateVisitor;

Wyświetl plik

@ -1,210 +0,0 @@
'use strict';
var osgPool = require( 'osgUtil/osgPool' );
var StateGraph = require( 'osg/StateGraph' );
var Timer = require( 'osg/Timer' );
var Notify = require( 'osg/notify' );
// make the warning about StateGraph desappear
window.Object.keys( StateGraph );
var Utils = {};
Utils.init = function () {
var StateGraphClass = require( 'osg/StateGraph' );
osgPool.memoryPools.stateGraph = new osgPool.OsgObjectMemoryPool( StateGraphClass ).grow( 50 );
};
Utils.isArray = function ( obj ) {
Notify.log( 'isArray is deprecated, use instead Array.isArray' );
return Array.isArray( obj );
};
Utils.extend = function () {
// Save a reference to some core methods
var toString = window.Object.prototype.toString;
var hasOwnPropertyFunc = window.Object.prototype.hasOwnProperty;
var isFunction = function ( obj ) {
return toString.call( obj ) === '[object Function]';
};
var isArray = Utils.isArray;
var isPlainObject = function ( obj ) {
// Must be an Object.
// Because of IE, we also have to check the presence of the constructor property.
// Make sure that DOM nodes and window objects don't pass through, as well
if ( !obj || toString.call( obj ) !== '[object Object]' || obj.nodeType || obj.setInterval ) {
return false;
}
// Not own constructor property must be Object
if ( obj.constructor && !hasOwnPropertyFunc.call( obj, 'constructor' ) && !hasOwnPropertyFunc.call( obj.constructor.prototype, 'isPrototypeOf' ) ) {
return false;
}
// Own properties are enumerated firstly, so to speed up,
// if last one is own, then all properties are own.
var key;
for ( key in obj ) {}
return key === undefined || hasOwnPropertyFunc.call( obj, key );
};
// copy reference to target object
var target = arguments[ 0 ] || {},
i = 1,
length = arguments.length,
deep = false,
options, name, src, copy;
// Handle a deep copy situation
if ( typeof target === 'boolean' ) {
deep = target;
target = arguments[ 1 ] || {};
// skip the boolean and the target
i = 2;
}
// Handle case when target is a string or something (possible in deep copy)
if ( typeof target !== 'object' && !isFunction( target ) ) {
target = {};
}
// extend jQuery itself if only one argument is passed
if ( length === i ) {
target = this;
--i;
}
for ( ; i < length; i++ ) {
// Only deal with non-null/undefined values
if ( ( options = arguments[ i ] ) !== null ) {
// Extend the base object
for ( name in options ) {
src = target[ name ];
copy = options[ name ];
// Prevent never-ending loop
if ( target === copy ) {
continue;
}
// Recurse if we're merging object literal values or arrays
if ( deep && copy && ( isPlainObject( copy ) || isArray( copy ) ) ) {
var clone = src && ( isPlainObject( src ) || isArray( src ) ) ? src : isArray( copy ) ? [] : {};
// Never move original objects, clone them
target[ name ] = Utils.extend( deep, clone, copy );
// Don't bring in undefined values
} else if ( copy !== undefined ) {
target[ name ] = copy;
}
}
}
}
// Return the modified object
return target;
};
Utils.objectInherit = function ( base /*, extras*/ ) {
function F() {}
F.prototype = base;
var obj = new F();
// let augment object with multiple arguement
for ( var i = 1; i < arguments.length; i++ ) {
Utils.objectMix( obj, arguments[ i ], false );
}
return obj;
};
Utils.objectInehrit = function () {
console.warn( 'please use objectInherit instead of objectInehrit' );
};
Utils.objectMix = function ( obj, properties, test ) {
for ( var key in properties ) {
if ( !( test && obj[ key ] ) ) {
obj[ key ] = properties[ key ];
}
}
return obj;
};
Utils.objectType = {};
Utils.objectType.type = 0;
Utils.objectType.generate = function ( arg ) {
var t = Utils.objectType.type;
Utils.objectType[ t ] = arg;
Utils.objectType[ arg ] = t;
Utils.objectType.type += 1;
return t;
};
Utils.objectLibraryClass = function ( object, libName, className ) {
object.className = function () {
return className;
};
object.libraryName = function () {
return libName;
};
var libraryClassName = libName + '::' + className;
object.libraryClassName = function () {
return libraryClassName;
};
return object;
};
Utils.setTypeID = function ( classObject ) {
var className = classObject.prototype.libraryClassName();
var typeID = Utils.objectType.generate( className );
var getTypeID = function () {
return typeID;
};
classObject.typeID = classObject.prototype.typeID = typeID;
classObject.getTypeID = classObject.prototype.getTypeID = getTypeID;
};
Utils.createPrototypeClass = function ( Constructor, prototype, libraryName, className ) {
Constructor.prototype = prototype;
prototype.constructor = Constructor;
Utils.objectLibraryClass( prototype, libraryName, className );
Utils.setTypeID( Constructor );
};
Utils.Float32Array = typeof Float32Array !== 'undefined' ? Float32Array : null;
Utils.Int32Array = typeof Int32Array !== 'undefined' ? Int32Array : null;
Utils.Uint8Array = typeof Uint8Array !== 'undefined' ? Uint8Array : null;
Utils.Uint16Array = typeof Uint16Array !== 'undefined' ? Uint16Array : null;
Utils.Uint32Array = typeof Uint32Array !== 'undefined' ? Uint32Array : null;
var times = {};
// we bind the function to Notify.console once and for all to avoid costly apply function
Utils.time = ( Notify.console.time || function ( name ) {
times[ name ] = Timer.instance().tick();
} ).bind( Notify.console );
Utils.timeEnd = ( Notify.console.timeEnd || function ( name ) {
if ( times[ name ] === undefined )
return;
var duration = Timer.instance().deltaM( times[ name ], Timer.instance().tick() );
Notify.debug( name + ': ' + duration + 'ms' );
times[ name ] = undefined;
} ).bind( Notify.console );
Utils.timeStamp = ( Notify.console.timeStamp || Notify.console.markTimeline || function () {} ).bind( Notify.console );
Utils.profile = ( Notify.console.profile || function () {} ).bind( Notify.console );
Utils.profileEnd = ( Notify.console.profileEnd || function () {} ).bind( Notify.console );
module.exports = Utils;

Wyświetl plik

@ -1 +0,0 @@
module.exports = require( 'osg/deprecated-MatrixVector/Vec2' );

Wyświetl plik

@ -1 +0,0 @@
module.exports = require( 'osg/deprecated-MatrixVector/Vec3' );

Wyświetl plik

@ -1 +0,0 @@
module.exports = require( 'osg/deprecated-MatrixVector/Vec4' );

Wyświetl plik

@ -1,69 +0,0 @@
'use strict';
var MACROUTILS = require( 'osg/Utils' );
var StateAttribute = require( 'osg/StateAttribute' );
var mat4 = require( 'osg/glMatrix' ).mat4;
var vec3 = require( 'osg/glMatrix' ).vec3;
var Viewport = function ( x, y, w, h ) {
StateAttribute.call( this );
this._x = x !== undefined ? x : 0;
this._y = y !== undefined ? y : 0;
this._width = w !== undefined ? w : 800;
this._height = h !== undefined ? h : 600;
};
Viewport.prototype = MACROUTILS.objectLibraryClass( MACROUTILS.objectInherit( StateAttribute.prototype, {
attributeType: 'Viewport',
cloneType: function () {
return new Viewport();
},
apply: function ( state ) {
var gl = state.getGraphicContext();
gl.viewport( this._x, this._y, this._width, this._height );
},
setViewport: function ( x, y, width, height ) {
this._x = x;
this._y = y;
this._width = width;
this._height = height;
},
x: function () {
return this._x;
},
y: function () {
return this._y;
},
width: function () {
return this._width;
},
height: function () {
return this._height;
},
computeWindowMatrix: ( function () {
var translate = mat4.create();
var scale = mat4.create();
var unitVec = vec3.fromValues( 1.0, 1.0, 1.0 );
return function ( destination ) {
// res = Matrix offset * Matrix scale * Matrix translate
mat4.fromTranslation( translate, unitVec );
mat4.fromScaling( scale, [ 0.5 * this._width, 0.5 * this._height, 0.5 ] );
var offset = mat4.fromTranslation( destination, vec3.fromValues( this._x, this._y, 0.0 ) );
return mat4.mul( offset, offset, mat4.mul( scale, scale, translate ) );
};
} )()
} ), 'osg', 'Viewport' );
module.exports = Viewport;

Wyświetl plik

@ -1,376 +0,0 @@
'use strict';
var Notify = require( 'osg/notify' );
var WebGLUtils = require( 'osgViewer/webgl-utils' );
var Texture;
var WebGLCaps = function () {
// circular deps with texture
if ( !Texture ) Texture = require( 'osg/Texture' );
this._checkRTT = {};
this._webGLExtensions = {};
this._webGLParameters = {};
this._webGLShaderMaxInt = 'NONE';
this._webGLShaderMaxFloat = 'NONE';
this._bugsDB = {};
this._webGLPlatforms = {};
// webgl minimum requirements as per webgl specs
// useful for nodejs env
this._webGLParameters[ 'MAX_COMBINED_TEXTURE_IMAGE_UNITS' ] = 8;
this._webGLParameters[ 'MAX_CUBE_MAP_TEXTURE_SIZE' ] = 16;
this._webGLParameters[ 'MAX_FRAGMENT_UNIFORM_VECTORS' ] = 16;
this._webGLParameters[ 'MAX_RENDERBUFFER_SIZE' ] = 1;
this._webGLParameters[ 'MAX_TEXTURE_IMAGE_UNITS' ] = 8;
this._webGLParameters[ 'MAX_TEXTURE_SIZE' ] = 64;
this._webGLParameters[ 'MAX_VARYING_VECTORS' ] = 8;
this._webGLParameters[ 'MAX_VERTEX_ATTRIBS' ] = 8;
this._webGLParameters[ 'MAX_VERTEX_TEXTURE_IMAGE_UNITS' ] = 0;
this._webGLParameters[ 'MAX_VERTEX_UNIFORM_VECTORS' ] = 128;
this._webGLParameters[ 'MAX_VIEWPORT_DIMS' ] = [ 1, 1 ];
this._webGLParameters[ 'NUM_COMPRESSED_TEXTURE_FORMATS' ] = 0;
this._webGLParameters[ 'MAX_SHADER_PRECISION_FLOAT' ] = 'none';
this._webGLParameters[ 'MAX_SHADER_PRECISION_INT' ] = 'none';
// for multiple context
// allow checking we're on the good one
this._gl = undefined;
};
WebGLCaps.instance = function ( glParam ) {
if ( !WebGLCaps._instance ) {
var oldWebGLInspector;
var gl = glParam;
if ( !gl ) {
// make sure we don't break webglinspector
// with our webglcaps canvas
var webglInspector = typeof window !== 'undefined' && window.gli;
if ( webglInspector ) {
oldWebGLInspector = window.gli.host.inspectContext;
window.gli.host.inspectContext = false;
}
var c = document.createElement( 'canvas' );
c.width = 32;
c.height = 32;
// not necessary, but for some reasons it crashed on chromium vr build
var opt = {
antialias: false
};
gl = WebGLUtils.setupWebGL( c, opt, function () {} );
}
WebGLCaps._instance = new WebGLCaps();
if ( gl ) {
WebGLCaps._instance.init( gl );
} else {
// gracefully handle non webgl
// like nodejs, phantomjs
// warns but no error so that nodejs/phantomjs
// can still has some webglcaps object
Notify.warn( 'no support for webgl context detected.' );
}
if ( oldWebGLInspector ) {
window.gli.host.inspectContext = oldWebGLInspector;
}
//delete c;
}
if ( glParam && glParam !== WebGLCaps._instance.getContext() ) {
// webgl caps called with a different context
// than the one we draw in, will result on hard crash
// when using extension from another context
WebGLCaps._instance.initContextDependant( glParam );
}
return WebGLCaps._instance;
};
WebGLCaps.prototype = {
getContext: function () {
return this._gl;
},
initContextDependant: function ( gl ) {
// store context in case of multiple context
this._gl = gl;
// Takes care of circular dependencies on Texture
// Texture should be resolved at this point
// Texture = require( 'osg/Texture' );
// get extensions
this.initWebGLExtensions( gl );
// get float support
this.hasLinearHalfFloatRTT( gl );
this.hasLinearFloatRTT( gl );
this.hasHalfFloatRTT( gl );
this.hasFloatRTT( gl );
},
init: function ( gl ) {
// get capabilites
this.initWebGLParameters( gl );
// order is important
// to allow webgl extensions filtering
this.initPlatformSupport();
this.initBugDB();
this.initContextDependant( gl );
this._isGL2 = typeof window.WebGL2RenderingContext !== 'undefined' && gl instanceof window.WebGL2RenderingContext;
if ( this._isGL2 ) {
// osgjs code is webgl1, so we fake webgl2 capabilities
// and calls for retrocompatibility with webgl1
this._checkRTT[ Texture.FLOAT + ',' + Texture.NEAREST ] = true;
this._checkRTT[ Texture.HALF_FLOAT + ',' + Texture.NEAREST ] = true;
this._checkRTT[ Texture.FLOAT + ',' + Texture.LINEAR ] = true;
this._checkRTT[ Texture.HALF_FLOAT + ',' + Texture.LINEAR ] = true;
var nativeExtension = [
'OES_element_index_uint',
'EXT_sRGB',
'EXT_blend_minmax',
'EXT_frag_depth',
'WEBGL_depth_texture',
'EXT_shader_texture_lod',
'OES_standard_derivatives',
'OES_texture_float',
'OES_texture_half_float',
'OES_vertex_array_object',
'WEBGL_draw_buffers',
'OES_fbo_render_mipmap',
'ANGLE_instanced_arrays'
];
var ext = WebGLCaps._instance.getWebGLExtensions();
var dummyFunc = function () {};
for ( var i = 0, l = nativeExtension.length; i < l; i++ ) {
ext[ nativeExtension[ i ] ] = dummyFunc;
}
}
},
isWebGL2: function () {
return this._isGL2;
},
// inevitable bugs per platform (browser/OS/GPU)
initBugDB: function () {
},
initPlatformSupport: function () {
var p = this._webGLPlatforms;
p.Apple = navigator.vendor.indexOf( 'Apple' ) !== -1 || navigator.vendor.indexOf( 'OS X' ) !== -1;
// degrades complexity on handhelds.
p.Mobile = /Mobi/.test( navigator.userAgent ) || /ablet/.test( navigator.userAgent );
},
getWebGLPlatform: function ( str ) {
return this._webGLPlatforms[ str ];
},
getWebGLPlatforms: function () {
return this._webGLPlatforms;
},
getWebGLParameter: function ( str ) {
return this._webGLParameters[ str ];
},
getWebGLParameters: function () {
return this._webGLParameters;
},
getShaderMaxPrecisionFloat: function () {
return this._webGLParameters.MAX_SHADER_PRECISION_FLOAT;
},
getShaderMaxPrecisionInt: function () {
return this._webGLParameters.MAX_SHADER_PRECISION_INT;
},
checkSupportRTT: function ( gl, typeFloat, typeTexture ) {
var key = typeFloat + ',' + typeTexture;
// check once only
if ( this._checkRTT[ key ] !== undefined )
return this._checkRTT[ key ];
// no cached results, need gl context
if ( !gl ) return false;
// from http://codeflow.org/entries/2013/feb/22/how-to-write-portable-webgl/#how-can-i-detect-if-i-can-render-to-floating-point-textures
// setup the texture
var texture = gl.createTexture();
gl.bindTexture( gl.TEXTURE_2D, texture );
gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGBA, 2, 2, 0, gl.RGBA, typeFloat, null );
gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, typeTexture );
gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, typeTexture );
// setup the framebuffer
var framebuffer = gl.createFramebuffer();
gl.bindFramebuffer( gl.FRAMEBUFFER, framebuffer );
gl.framebufferTexture2D( gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0 );
// check the framebuffer
var status = this._checkRTT[ key ] = gl.checkFramebufferStatus( gl.FRAMEBUFFER ) === gl.FRAMEBUFFER_COMPLETE;
// cleanup
gl.deleteTexture( texture );
gl.deleteFramebuffer( framebuffer );
gl.bindTexture( gl.TEXTURE_2D, null );
gl.bindFramebuffer( gl.FRAMEBUFFER, null );
return status;
},
hasLinearHalfFloatRTT: function ( gl ) {
return this._webGLExtensions[ 'OES_texture_half_float_linear' ] && this.checkSupportRTT( gl, Texture.HALF_FLOAT, Texture.LINEAR );
},
hasLinearFloatRTT: function ( gl ) {
return this._webGLExtensions[ 'OES_texture_float_linear' ] && this.checkSupportRTT( gl, Texture.FLOAT, Texture.LINEAR );
},
hasHalfFloatRTT: function ( gl ) {
return this._webGLExtensions[ 'OES_texture_half_float' ] && this.checkSupportRTT( gl, Texture.HALF_FLOAT, Texture.NEAREST );
},
hasFloatRTT: function ( gl ) {
return this._webGLExtensions[ 'OES_texture_float' ] && this.checkSupportRTT( gl, Texture.FLOAT, Texture.NEAREST );
},
queryPrecision: function ( gl, shaderType, precision ) {
var answer = gl.getShaderPrecisionFormat( shaderType, precision );
if ( !answer ) return false;
return answer.precision !== 0;
},
initWebGLParameters: function ( gl ) {
if ( !gl ) return;
var limits = [
'MAX_COMBINED_TEXTURE_IMAGE_UNITS',
'MAX_CUBE_MAP_TEXTURE_SIZE',
'MAX_FRAGMENT_UNIFORM_VECTORS',
'MAX_RENDERBUFFER_SIZE',
'MAX_TEXTURE_IMAGE_UNITS',
'MAX_TEXTURE_SIZE',
'MAX_VARYING_VECTORS',
'MAX_VERTEX_ATTRIBS',
'MAX_VERTEX_TEXTURE_IMAGE_UNITS',
'MAX_VERTEX_UNIFORM_VECTORS',
'MAX_VIEWPORT_DIMS',
'SHADING_LANGUAGE_VERSION',
'VERSION',
'VENDOR',
'RENDERER',
'ALIASED_LINE_WIDTH_RANGE',
'ALIASED_POINT_SIZE_RANGE',
'RED_BITS',
'GREEN_BITS',
'BLUE_BITS',
'ALPHA_BITS',
'DEPTH_BITS',
'STENCIL_BITS'
];
var params = this._webGLParameters;
for ( var i = 0, len = limits.length; i < len; ++i ) {
var par = limits[ i ];
params[ par ] = gl.getParameter( gl[ par ] );
}
//shader precisions for float
if ( this.queryPrecision( gl, gl.FRAGMENT_SHADER, gl.HIGH_FLOAT ) ) {
params.MAX_SHADER_PRECISION_FLOAT = 'high';
} else if ( this.queryPrecision( gl, gl.FRAGMENT_SHADER, gl.MEDIUM_FLOAT ) ) {
params.MAX_SHADER_PRECISION_FLOAT = 'medium';
} else if ( this.queryPrecision( gl, gl.FRAGMENT_SHADER, gl.LOW_FLOAT ) ) {
params.MAX_SHADER_PRECISION_FLOAT = 'low';
}
//shader precisions for float
if ( this.queryPrecision( gl, gl.FRAGMENT_SHADER, gl.HIGH_INT ) ) {
params.MAX_SHADER_PRECISION_INT = 'high';
} else if ( this.queryPrecision( gl, gl.FRAGMENT_SHADER, gl.MEDIUM_INT ) ) {
params.MAX_SHADER_PRECISION_INT = 'medium';
} else if ( this.queryPrecision( gl, gl.FRAGMENT_SHADER, gl.LOW_INT ) ) {
params.MAX_SHADER_PRECISION_INT = 'low';
}
// get GPU, Angle or not, Opengl/directx, etc.
// ffx && chrome only
var debugInfo = gl.getExtension( 'WEBGL_debug_renderer_info' );
if ( debugInfo ) {
params.UNMASKED_RENDERER_WEBGL = gl.getParameter( debugInfo.UNMASKED_VENDOR_WEBGL );
params.UNMASKED_VENDOR_WEBGL = gl.getParameter( debugInfo.UNMASKED_RENDERER_WEBGL );
}
// TODO ?
// try to compile a small shader to test the spec is respected
},
getWebGLExtension: function ( str ) {
return this._webGLExtensions[ str ];
},
getWebGLExtensions: function () {
return this._webGLExtensions;
},
initWebGLExtensions: function ( gl, filterBugs ) {
// nodejs, phantomjs
if ( !gl ) return;
var doFilter = filterBugs;
if ( doFilter === undefined )
doFilter = true;
var supported = gl.getSupportedExtensions();
var ext = this._webGLExtensions;
// we load all the extensions
for ( var i = 0, len = supported.length; i < len; ++i ) {
var sup = supported[ i ];
if ( doFilter && this._bugsDB[ sup ] ) {
// bugs on that configuration, do not enable
continue;
}
ext[ sup ] = gl.getExtension( sup );
}
var anisoExt = this.getWebGLExtension( 'EXT_texture_filter_anisotropic' );
if ( anisoExt ) {
Texture.ANISOTROPIC_SUPPORT_EXT = true;
Texture.ANISOTROPIC_SUPPORT_MAX = gl.getParameter( anisoExt.MAX_TEXTURE_MAX_ANISOTROPY_EXT );
}
}
};
module.exports = WebGLCaps;

Wyświetl plik

@ -1,52 +0,0 @@
'use strict';
var mat4 = require( 'osg/glMatrix' ).mat4;
var TransformEnums = require( 'osg/transformEnums' );
var computeLocalToWorld = function ( nodePath, ignoreCameras, userMatrix ) {
var ignoreCamera = ignoreCameras;
if ( ignoreCamera === undefined ) ignoreCamera = true;
var matrix = userMatrix || mat4.create();
var j = 0;
if ( ignoreCamera ) {
for ( j = nodePath.length - 1; j >= 0; j-- ) {
var camera = nodePath[ j ];
if ( camera.className() === 'Camera' &&
( camera.getReferenceFrame() !== TransformEnums.RELATIVE_RF || camera.getParents().length === 0 ) ) {
break;
}
}
// because when we break it's to an index - 1
// it works because if nothing camera found j == -1 at the end of the loop
// and if we found a camera we want to start at the camera index + 1
j += 1;
}
for ( var i = j, l = nodePath.length; i < l; i++ ) {
var node = nodePath[ i ];
if ( node.computeLocalToWorldMatrix ) {
node.computeLocalToWorldMatrix( matrix );
}
}
return matrix;
};
module.exports = {
computeLocalToWorld: computeLocalToWorld
};

Wyświetl plik

@ -1,701 +0,0 @@
'use strict';
var Notify = require( 'osg/notify' );
var osgMath = require( 'osg/math' );
var BoundingBox = require( 'osg/BoundingBox' );
var Plane = require( 'osg/Plane' );
var vec3 = require( 'osg/glMatrix' ).vec3;
var glm = require( 'osg/glMatrix' );
var Mabs = Math.abs;
var NMIN_VALUE = Number.MIN_VALUE;
// call by closur'd variables because Matrix object is not
// resolved yet, a workaround would be to define Matrix such as:
// var Matrix = {};
// Matrix.create = function... ;
// Matrix.func2 = function... ;
var matrixCreate = glm.mat4.create;
/** @class Matrix Operations */
var Matrix = {
create: glm.mat4.create,
createAndSet: glm.mat4.fromValues,
isIdentity: function ( matrix ) {
return glm.mat4.equals( Matrix.identity, matrix );
},
valid: function ( matrix ) {
for ( var i = 0; i < 16; i++ )
if ( osgMath.isNaN( matrix[ i ] ) )
return false;
return true;
},
setRow: function ( matrix, row, v0, v1, v2, v3 ) {
var rowIndex = row * 4;
matrix[ rowIndex + 0 ] = v0;
matrix[ rowIndex + 1 ] = v1;
matrix[ rowIndex + 2 ] = v2;
matrix[ rowIndex + 3 ] = v3;
},
innerProduct: function ( a, b, r, c ) {
var rIndex = r * 4;
return ( ( a[ rIndex + 0 ] * b[ 0 + c ] ) + ( a[ rIndex + 1 ] * b[ 4 + c ] ) + ( a[ rIndex + 2 ] * b[ 8 + c ] ) + ( a[ rIndex + 3 ] * b[ 12 + c ] ) );
},
set: function ( matrix, row, col, value ) {
matrix[ row * 4 + col ] = value;
return value;
},
get: function ( matrix, row, col ) {
return matrix[ row * 4 + col ];
},
makeIdentity: glm.mat4.identity,
equal: glm.mat4.exactEquals,
/**
* @param {Number} x position
* @param {Number} y position
* @param {Number} z position
* @param {Array} matrix to write result
*/
makeTranslate: function ( x, y, z, matrix ) {
return glm.mat4.fromTranslation( matrix, vec3.fromValues( x, y, z ) );
},
setTrans: function ( matrix, x, y, z ) {
matrix[ 12 ] = x;
matrix[ 13 ] = y;
matrix[ 14 ] = z;
return matrix;
},
getTrans: function ( matrix, result ) {
return glm.mat4.getTranslation( result, matrix );
},
// do a * b and result in a
preMult: function ( a, b ) {
return glm.mat4.multiply( a, a, b );
},
// do a * b and store the result in b
// Be aware of the change w.r.t OSG as b holds the result!
postMult: function ( a, b ) {
return glm.mat4.multiply( b, a, b );
},
/* r = a * b */
mult: function ( a, b, r ) {
return glm.mat4.multiply( r, a, b );
},
makeLookFromDirection: ( function () {
var s = vec3.create();
var u = vec3.create();
var neg = vec3.create();
return function ( eye, eyeDir, up, result ) {
var f = eyeDir;
vec3.cross( s, f, up );
vec3.normalize( s, s );
vec3.cross( u, s, f );
vec3.normalize( u, u );
// s[0], u[0], -f[0], 0.0,
// s[1], u[1], -f[1], 0.0,
// s[2], u[2], -f[2], 0.0,
// 0, 0, 0, 1.0
result[ 0 ] = s[ 0 ];
result[ 1 ] = u[ 0 ];
result[ 2 ] = -f[ 0 ];
result[ 3 ] = 0.0;
result[ 4 ] = s[ 1 ];
result[ 5 ] = u[ 1 ];
result[ 6 ] = -f[ 1 ];
result[ 7 ] = 0.0;
result[ 8 ] = s[ 2 ];
result[ 9 ] = u[ 2 ];
result[ 10 ] = -f[ 2 ];
result[ 11 ] = 0.0;
result[ 12 ] = 0;
result[ 13 ] = 0;
result[ 14 ] = 0;
result[ 15 ] = 1.0;
Matrix.multTranslate( result, vec3.neg( neg, eye ), result );
return result;
};
} )(),
makeLookAt: function ( eye, center, up, result ) {
return glm.mat4.lookAt( result, eye, center, up );
},
makeOrtho: function ( left, right, bottom, top, zNear, zFar, result ) {
return glm.mat4.ortho( result, left, right, bottom, top, zNear, zFar );
},
getLookAt: ( function () {
var inv = matrixCreate();
var v1 = vec3.create();
var v2 = vec3.fromValues( 0.0, 1.0, 0.0 );
var v3 = vec3.fromValues( 0.0, 0.0, -1.0 );
return function ( matrix, eye, center, up, distance ) {
if ( distance === undefined ) {
distance = 1.0;
}
var result = Matrix.inverse( matrix, inv );
if ( !result ) {
glm.mat4.identity( inv );
}
Matrix.transformVec3( inv, v1, eye );
Matrix.transform3x3( matrix, v2, up );
Matrix.transform3x3( matrix, v3, center );
vec3.normalize( center, center );
vec3.add( center, vec3.scale( v1, center, distance ), eye );
};
} )(),
//getRotate_David_Spillings_Mk1
getRotate: function ( mat, quatResult ) {
return glm.mat4.getRotation( quatResult, mat );
},
// Matrix M = Matrix M * Matrix Translate
preMultTranslate: function ( mat, translate ) {
return glm.mat4.translate( mat, mat, translate );
},
postMultTranslate: function ( mat, translate ) {
return glm.mat4.multiply( mat, glm.mat4.fromTranslation( glm.mat4.create(), translate ), mat );
},
// result = Matrix M * Matrix Translate
multTranslate: function ( mat, translate, result ) {
return glm.mat4.translate( result, mat, translate );
},
makeRotate: function ( angle, x, y, z, result ) {
var v = vec3.fromValues( x, y, z );
if ( x === 0.0 && y === 0.0 && z === 0.0 )
v[ 2 ] = 1.0;
return glm.mat4.fromRotation( result, angle, v );
},
preMultRotate: ( function () {
var r = matrixCreate();
return function ( matrix, q ) {
return glm.mat4.multiply( matrix, matrix, glm.mat4.fromQuat( r, q ) );
};
} )(),
postMultRotate: ( function () {
var r = matrixCreate();
return function ( m, q ) {
return glm.mat4.multiply( m, glm.mat4.fromQuat( r, q ), m );
};
} )(),
transform3x3: function ( m, v, result ) {
result[ 0 ] = m[ 0 ] * v[ 0 ] + m[ 1 ] * v[ 1 ] + m[ 2 ] * v[ 2 ];
result[ 1 ] = m[ 4 ] * v[ 0 ] + m[ 5 ] * v[ 1 ] + m[ 6 ] * v[ 2 ];
result[ 2 ] = m[ 8 ] * v[ 0 ] + m[ 9 ] * v[ 1 ] + m[ 10 ] * v[ 2 ];
return result;
},
transformVec3: function ( matrix, vector, result ) {
return glm.vec3.transformMat4( result, vector, matrix );
},
transformVec4: function ( matrix, vector, result ) {
return glm.vec4.transformMat4( result, vector, matrix );
},
// http://dev.theomader.com/transform-bounding-boxes/
// https://github.com/erich666/GraphicsGems/blob/master/gems/TransBox.c
transformBoundingBox: ( function () {
var tempBbox = new BoundingBox();
return function ( m, bbIn, bbOut ) {
if ( bbOut === bbIn ) {
bbOut = tempBbox;
}
var inMin = bbIn.getMin();
var inMax = bbIn.getMax();
/* Take care of translation by beginning at T. */
var outMin = glm.mat4.getTranslation( bbOut.getMin(), m );
var outMax = vec3.copy( bbOut.getMax(), outMin );
/* Now find the extreme points by considering the product of the */
/* min and max with each component of M. */
for ( var i = 0; i < 3; ++i ) {
var i4 = i * 4;
var mini = inMin[ i ];
var maxi = inMax[ i ];
for ( var j = 0; j < 3; ++j ) {
var cm = m[ i4 + j ];
var a = cm * maxi;
var b = cm * mini;
if ( a < b ) {
outMin[ j ] += a;
outMax[ j ] += b;
} else {
outMin[ j ] += b;
outMax[ j ] += a;
}
}
}
if ( bbOut === tempBbox ) {
bbIn.copy( tempBbox );
}
};
} )(),
transformBoundingSphere: ( function () {
var scaleVec = vec3.create();
return function ( matrix, bSphere, bsOut ) {
if ( !bSphere.valid() ) {
return bsOut;
}
vec3.copy( bsOut._center, bSphere._center );
bsOut._radius = bSphere._radius;
var sphCenter = bsOut._center;
var sphRadius = bsOut._radius;
Matrix.getScale2( matrix, scaleVec );
var scale = Math.sqrt( Math.max( Math.max( scaleVec[ 0 ], scaleVec[ 1 ] ), scaleVec[ 2 ] ) );
sphRadius = sphRadius * scale;
bsOut._radius = sphRadius;
Matrix.transformVec3( matrix, sphCenter, sphCenter );
return bsOut;
};
} )(),
transformVec4PostMult: function ( matrix, vector, result ) {
var x = vector[ 0 ];
var y = vector[ 1 ];
var z = vector[ 2 ];
var w = vector[ 3 ];
result[ 0 ] = matrix[ 0 ] * x + matrix[ 1 ] * y + matrix[ 2 ] * z + matrix[ 3 ] * w;
result[ 1 ] = matrix[ 4 ] * x + matrix[ 5 ] * y + matrix[ 6 ] * z + matrix[ 7 ] * w;
result[ 2 ] = matrix[ 8 ] * x + matrix[ 9 ] * y + matrix[ 10 ] * z + matrix[ 11 ] * w;
result[ 3 ] = matrix[ 12 ] * x + matrix[ 13 ] * y + matrix[ 14 ] * z + matrix[ 15 ] * w;
return result;
},
copy: function ( matrix, result ) {
return glm.mat4.copy( result, matrix );
},
inverse: function ( matrix, result ) {
var r = glm.mat4.invert( result, matrix );
if ( r === null ) return false;
return true;
},
transpose: function ( mat, dest ) {
return glm.mat4.transpose( dest, mat );
},
getFrustumPlanes: ( function () {
var mvp = matrixCreate();
return function ( projection, view, result, withNearFar ) {
glm.mat4.multiply( mvp, projection, view );
if ( withNearFar === undefined )
withNearFar = false;
// Right clipping plane.
var right = result[ 0 ];
right[ 0 ] = mvp[ 3 ] - mvp[ 0 ];
right[ 1 ] = mvp[ 7 ] - mvp[ 4 ];
right[ 2 ] = mvp[ 11 ] - mvp[ 8 ];
right[ 3 ] = mvp[ 15 ] - mvp[ 12 ];
// Left clipping plane.
var left = result[ 1 ];
left[ 0 ] = mvp[ 3 ] + mvp[ 0 ];
left[ 1 ] = mvp[ 7 ] + mvp[ 4 ];
left[ 2 ] = mvp[ 11 ] + mvp[ 8 ];
left[ 3 ] = mvp[ 15 ] + mvp[ 12 ];
// Bottom clipping plane.
var bottom = result[ 2 ];
bottom[ 0 ] = mvp[ 3 ] + mvp[ 1 ];
bottom[ 1 ] = mvp[ 7 ] + mvp[ 5 ];
bottom[ 2 ] = mvp[ 11 ] + mvp[ 9 ];
bottom[ 3 ] = mvp[ 15 ] + mvp[ 13 ];
// Top clipping plane.
var top = result[ 3 ];
top[ 0 ] = mvp[ 3 ] - mvp[ 1 ];
top[ 1 ] = mvp[ 7 ] - mvp[ 5 ];
top[ 2 ] = mvp[ 11 ] - mvp[ 9 ];
top[ 3 ] = mvp[ 15 ] - mvp[ 13 ];
if ( withNearFar ) {
// Far clipping plane.
var far = result[ 4 ];
far[ 0 ] = mvp[ 3 ] - mvp[ 2 ];
far[ 1 ] = mvp[ 7 ] - mvp[ 6 ];
far[ 2 ] = mvp[ 11 ] - mvp[ 10 ];
far[ 3 ] = mvp[ 15 ] - mvp[ 14 ];
// Near clipping plane.
var near = result[ 5 ];
near[ 0 ] = mvp[ 3 ] + mvp[ 2 ];
near[ 1 ] = mvp[ 7 ] + mvp[ 6 ];
near[ 2 ] = mvp[ 11 ] + mvp[ 10 ];
near[ 3 ] = mvp[ 15 ] + mvp[ 14 ];
}
//Normalize the planes
var j = withNearFar ? 6 : 4;
for ( var i = 0; i < j; i++ ) {
Plane.normalizeEquation( result[ i ] );
}
};
} )(),
makePerspective: function ( fovy, aspect, znear, zfar, result ) {
return glm.mat4.perspective( result, fovy * Math.PI / 180.0, aspect, znear, zfar );
},
getFrustum: function ( matrix, result ) {
var right = 0.0;
var left = 0.0;
var top = 0.0;
var bottom = 0.0;
var zNear, zFar;
if ( matrix[ 0 * 4 + 3 ] !== 0.0 || matrix[ 1 * 4 + 3 ] !== 0.0 || matrix[ 2 * 4 + 3 ] !== -1.0 || matrix[ 3 * 4 + 3 ] !== 0.0 ) {
return false;
}
// note: near and far must be used inside this method instead of zNear and zFar
// because zNear and zFar are references and they may point to the same variable.
var tempNear = matrix[ 3 * 4 + 2 ] / ( matrix[ 2 * 4 + 2 ] - 1.0 );
var tempFar = matrix[ 3 * 4 + 2 ] / ( 1.0 + matrix[ 2 * 4 + 2 ] );
left = tempNear * ( matrix[ 2 * 4 ] - 1.0 ) / matrix[ 0 ];
right = tempNear * ( 1.0 + matrix[ 2 * 4 ] ) / matrix[ 0 ];
top = tempNear * ( 1.0 + matrix[ 2 * 4 + 1 ] ) / matrix[ 1 * 4 + 1 ];
bottom = tempNear * ( matrix[ 2 * 4 + 1 ] - 1.0 ) / matrix[ 1 * 4 + 1 ];
zNear = tempNear;
zFar = tempFar;
result.left = left;
result.right = right;
result.top = top;
result.bottom = bottom;
result.zNear = zNear;
result.zFar = zFar;
return true;
},
getPerspective: ( function () {
var c = {
'right': 0,
'left': 0,
'top': 0,
'bottom': 0,
'zNear': 0,
'zFar': 0
};
return function ( matrix, result ) {
// get frustum and compute results
var r = Matrix.getFrustum( matrix, c );
if ( r ) {
result.fovy = 180 / Math.PI * ( Math.atan( c.top / c.zNear ) - Math.atan( c.bottom / c.zNear ) );
result.aspectRatio = ( c.right - c.left ) / ( c.top - c.bottom );
}
result.zNear = c.zNear;
result.zFar = c.zFar;
return result;
};
} )(),
preMultScale: function ( m, scale ) {
return glm.mat4.scale( m, m, scale );
},
postMultScale: function ( m, scale ) {
return glm.mat4.multiply( m, glm.mat4.fromScaling( glm.mat4.create(), scale ), m );
},
makeScale: function ( x, y, z, result ) {
return glm.mat4.fromScaling( result, [ x, y, z ] );
},
getScale: ( function () {
var sx = vec3.create();
var sy = vec3.create();
var sz = vec3.create();
return function ( matrix, result ) {
sx[ 0 ] = matrix[ 0 ];
sx[ 1 ] = matrix[ 4 ];
sx[ 2 ] = matrix[ 8 ];
sy[ 0 ] = matrix[ 1 ];
sy[ 1 ] = matrix[ 5 ];
sy[ 2 ] = matrix[ 9 ];
sz[ 0 ] = matrix[ 2 ];
sz[ 1 ] = matrix[ 6 ];
sz[ 2 ] = matrix[ 10 ];
result[ 0 ] = vec3.length( sx );
result[ 1 ] = vec3.length( sy );
result[ 2 ] = vec3.length( sz );
return result;
};
} )(),
getScale2: ( function () {
var sx = vec3.create();
var sy = vec3.create();
var sz = vec3.create();
return function ( matrix, result ) {
sx[ 0 ] = matrix[ 0 ];
sx[ 1 ] = matrix[ 4 ];
sx[ 2 ] = matrix[ 8 ];
sy[ 0 ] = matrix[ 1 ];
sy[ 1 ] = matrix[ 5 ];
sy[ 2 ] = matrix[ 9 ];
sz[ 0 ] = matrix[ 2 ];
sz[ 1 ] = matrix[ 6 ];
sz[ 2 ] = matrix[ 10 ];
result[ 0 ] = vec3.sqrLen( sx );
result[ 1 ] = vec3.sqrLen( sy );
result[ 2 ] = vec3.sqrLen( sz );
return result;
};
} )(),
clampProjectionMatrix: function ( projection, znear, zfar, nearFarRatio, resultNearFar ) {
var epsilon = 1e-6;
if ( zfar < znear - epsilon ) {
Notify.log( 'clampProjectionMatrix not applied, invalid depth range, znear = ' + znear + ' zfar = ' + zfar, false, true );
return false;
}
var desiredZnear, desiredZfar;
if ( zfar < znear + epsilon ) {
// znear and zfar are too close together and could cause divide by zero problems
// late on in the clamping code, so move the znear and zfar apart.
var average = ( znear + zfar ) * 0.5;
znear = average - epsilon;
zfar = average + epsilon;
// OSG_INFO << '_clampProjectionMatrix widening znear and zfar to '<<znear<<' '<<zfar<<std::endl;
}
if ( Math.abs( projection[ 3 ] ) < epsilon &&
Math.abs( projection[ 7 ] ) < epsilon &&
Math.abs( projection[ 11 ] ) < epsilon ) {
// OSG_INFO << 'Orthographic matrix before clamping'<<projection<<std::endl;
var deltaSpan = ( zfar - znear ) * 0.02;
if ( deltaSpan < 1.0 ) {
deltaSpan = 1.0;
}
desiredZnear = znear - deltaSpan;
desiredZfar = zfar + deltaSpan;
// assign the clamped values back to the computed values.
znear = desiredZnear;
zfar = desiredZfar;
projection[ 10 ] = -2.0 / ( desiredZfar - desiredZnear );
projection[ 14 ] = -( desiredZfar + desiredZnear ) / ( desiredZfar - desiredZnear );
// OSG_INFO << 'Orthographic matrix after clamping '<<projection<<std::endl;
} else {
// OSG_INFO << 'Persepective matrix before clamping'<<projection<<std::endl;
//std::cout << '_computed_znear'<<_computed_znear<<std::endl;
//std::cout << '_computed_zfar'<<_computed_zfar<<std::endl;
var zfarPushRatio = 1.02;
var znearPullRatio = 0.98;
//znearPullRatio = 0.99;
desiredZnear = znear * znearPullRatio;
desiredZfar = zfar * zfarPushRatio;
// near plane clamping.
var minNearPlane = zfar * nearFarRatio;
if ( desiredZnear < minNearPlane ) {
desiredZnear = minNearPlane;
}
// assign the clamped values back to the computed values.
znear = desiredZnear;
zfar = desiredZfar;
var m22 = projection[ 10 ];
var m32 = projection[ 14 ];
var m23 = projection[ 11 ];
var m33 = projection[ 15 ];
var transNearPlane = ( -desiredZnear * m22 + m32 ) / ( -desiredZnear * m23 + m33 );
var transFarPlane = ( -desiredZfar * m22 + m32 ) / ( -desiredZfar * m23 + m33 );
var ratio = Math.abs( 2.0 / ( transNearPlane - transFarPlane ) );
var center = -( transNearPlane + transFarPlane ) / 2.0;
var centerRatio = center * ratio;
projection[ 2 ] = projection[ 2 ] * ratio + projection[ 3 ] * centerRatio;
projection[ 6 ] = projection[ 6 ] * ratio + projection[ 7 ] * centerRatio;
projection[ 10 ] = m22 * ratio + m23 * centerRatio;
projection[ 14 ] = m32 * ratio + m33 * centerRatio;
// same as
// var matrix = [ 1.0, 0.0, 0.0, 0.0,
// 0.0, 1.0, 0.0, 0.0,
// 0.0, 0.0, ratio, 0.0,
// 0.0, 0.0, center * ratio, 1.0
// ];
// mat4.mul( projection , matrix, projection );
// OSG_INFO << 'Persepective matrix after clamping'<<projection<<std::endl;
}
if ( resultNearFar !== undefined ) {
resultNearFar[ 0 ] = znear;
resultNearFar[ 1 ] = zfar;
}
return true;
},
// compute the 4 corners vector of the frustum
computeFrustumCornersVectors: function ( projectionMatrix, vectorsArray ) {
//var znear = projectionMatrix[ 12 + 2 ] / ( projectionMatrix[ 8 + 2 ] - 1.0 );
//var zfar = projectionMatrix[ 12 + 2 ] / ( projectionMatrix[ 8 + 2 ] + 1.0 );
var x = 1.0 / projectionMatrix[ 0 ];
var y = 1.0 / projectionMatrix[ 1 * 4 + 1 ];
vectorsArray[ 0 ] = vec3.fromValues( -x, y, 1.0 );
vectorsArray[ 1 ] = vec3.fromValues( -x, -y, 1.0 );
vectorsArray[ 2 ] = vec3.fromValues( x, -y, 1.0 );
vectorsArray[ 3 ] = vec3.fromValues( x, y, 1.0 );
return vectorsArray;
},
// better precison
// no far clipping artifacts.
// no reason not to use.
// Tightening the Precision of Perspective Rendering
//http://www.geometry.caltech.edu/pubs/UD12.pdf
// drop-in, just remove the one below, and rename this one
makeFrustumInfinite: function ( left, right, bottom, top, znear, zfar, result ) {
var X = 2.0 * znear / ( right - left );
var Y = 2.0 * znear / ( top - bottom );
var A = ( right + left ) / ( right - left );
var B = ( top + bottom ) / ( top - bottom );
var C = -1.0;
Matrix.setRow( result, 0, X, 0.0, 0.0, 0.0 );
Matrix.setRow( result, 1, 0.0, Y, 0.0, 0.0 );
Matrix.setRow( result, 2, A, B, C, -1.0 );
Matrix.setRow( result, 3, 0.0, 0.0, -2.0 * znear, 0.0 );
return result;
},
makeFrustum: function ( left, right, bottom, top, znear, zfar, result ) {
return glm.mat4.frustum( result, left, right, bottom, top, znear, zfar );
},
makeRotateFromQuat: function ( q, result ) {
return glm.mat4.fromQuat( result, q );
},
setRotateFromQuat: function ( m, q ) {
var length2 = glm.quat.sqrLen( q );
if ( Mabs( length2 ) <= NMIN_VALUE ) {
m[ 0 ] = 0.0;
m[ 1 ] = 0.0;
m[ 2 ] = 0.0;
m[ 4 ] = 0.0;
m[ 5 ] = 0.0;
m[ 6 ] = 0.0;
m[ 8 ] = 0.0;
m[ 9 ] = 0.0;
m[ 10 ] = 0.0;
} else {
var rlength2;
// normalize quat if required.
// We can avoid the expensive sqrt in this case since all 'coefficients' below are products of two q components.
// That is a square of a square root, so it is possible to avoid that
if ( length2 !== 1.0 ) {
rlength2 = 2.0 / length2;
} else {
rlength2 = 2.0;
}
// Source: Gamasutra, Rotating Objects Using Quaternions
//
//http://www.gamasutra.com/features/19980703/quaternions_01.htm
var wx, wy, wz, xx, yy, yz, xy, xz, zz, x2, y2, z2;
// calculate coefficients
x2 = rlength2 * q[ 0 ];
y2 = rlength2 * q[ 1 ];
z2 = rlength2 * q[ 2 ];
xx = q[ 0 ] * x2;
xy = q[ 0 ] * y2;
xz = q[ 0 ] * z2;
yy = q[ 1 ] * y2;
yz = q[ 1 ] * z2;
zz = q[ 2 ] * z2;
wx = q[ 3 ] * x2;
wy = q[ 3 ] * y2;
wz = q[ 3 ] * z2;
// Note. Gamasutra gets the matrix assignments inverted, resulting
// in left-handed rotations, which is contrary to OpenGL and OSG's
// methodology. The matrix assignment has been altered in the next
// few lines of code to do the right thing.
// Don Burns - Oct 13, 2001
m[ 0 ] = 1.0 - ( yy + zz );
m[ 4 ] = xy - wz;
m[ 8 ] = xz + wy;
m[ 0 + 1 ] = xy + wz;
m[ 4 + 1 ] = 1.0 - ( xx + zz );
m[ 8 + 1 ] = yz - wx;
m[ 0 + 2 ] = xz - wy;
m[ 4 + 2 ] = yz + wx;
m[ 8 + 2 ] = 1.0 - ( xx + yy );
}
return m;
}
};
Matrix.identity = Matrix.create();
module.exports = Matrix;

Wyświetl plik

@ -1,386 +0,0 @@
'use strict';
var vec3 = require( 'osg/glMatrix' ).vec3;
var Vec4 = require( 'osg/Vec4' );
var config = require( '../../config' );
var ArrayType = config.ArrayType;
var Msqrt = Math.sqrt;
var Mcos = Math.cos;
var Msin = Math.sin;
var Quat = {
create: function () {
var out = new ArrayType( 4 );
out[ 0 ] = 0.0;
out[ 1 ] = 0.0;
out[ 2 ] = 0.0;
out[ 3 ] = 1.0;
return out;
},
createAndSet: Vec4.createAndSet,
makeIdentity: function ( element ) {
return Quat.init( element );
},
init: function ( element ) {
element[ 0 ] = 0.0;
element[ 1 ] = 0.0;
element[ 2 ] = 0.0;
element[ 3 ] = 1.0;
return element;
},
// reuse Vec4 methods
copy: Vec4.copy,
set: Vec4.set,
sub: Vec4.sub,
add: Vec4.add,
dot: Vec4.dot,
neg: Vec4.neg,
lerp: Vec4.lerp,
length2: function ( a ) {
return a[ 0 ] * a[ 0 ] + a[ 1 ] * a[ 1 ] + a[ 2 ] * a[ 2 ] + a[ 3 ] * a[ 3 ];
},
zeroRotation: function ( q ) {
return q[ 0 ] === 0.0 && q[ 1 ] === 0.0 && q[ 2 ] === 0.0 && q[ 3 ] === 1.0;
},
length: function ( a ) {
return Math.sqrt( a[ 0 ] * a[ 0 ] + a[ 1 ] * a[ 1 ] + a[ 2 ] * a[ 2 ] + a[ 3 ] * a[ 3 ] );
},
makeRotate: function ( angle, x, y, z, result ) {
var epsilon = 0.0000001;
var length = Msqrt( x * x + y * y + z * z );
if ( length < epsilon ) {
return this.init( result );
}
var inversenorm = 1.0 / length;
var coshalfangle = Mcos( 0.5 * angle );
var sinhalfangle = Msin( 0.5 * angle );
result[ 0 ] = x * sinhalfangle * inversenorm;
result[ 1 ] = y * sinhalfangle * inversenorm;
result[ 2 ] = z * sinhalfangle * inversenorm;
result[ 3 ] = coshalfangle;
return result;
},
// http://physicsforgames.blogspot.fr/2010/02/quaternions.html
// called quatBlend
//
// NLERP is supposed to be
// - Commutative,
// - NOT Constant velocity
// - Torque minimal
//
// a and be must be normalized
// (otherwise they're not rotation...)
// t must be between 0 and 1
nlerp: function ( t, a, b, r ) {
var dot = this.dot( a, b );
var at = 1.0 - t;
// shortest path
if ( dot < 0.0 ) {
// negates directly b in the 4 equation
// this.neg( b, r );
r[ 0 ] = a[ 0 ] * at - b[ 0 ] * t;
r[ 1 ] = a[ 1 ] * at - b[ 1 ] * t;
r[ 2 ] = a[ 2 ] * at - b[ 2 ] * t;
r[ 3 ] = a[ 3 ] * at - b[ 3 ] * t;
} else {
r[ 0 ] = a[ 0 ] * at + b[ 0 ] * t;
r[ 1 ] = a[ 1 ] * at + b[ 1 ] * t;
r[ 2 ] = a[ 2 ] * at + b[ 2 ] * t;
r[ 3 ] = a[ 3 ] * at + b[ 3 ] * t;
}
return this.normalize( r, r );
},
//
// MUST READ on SLERP, NLERP, LOG-LERP
// http://number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/
// with a slerp implementation (robust)
//
// MUST READ Howto enhance lerp, slerp and q normalize
// http://number-none.com/product/Hacking%20Quaternions/
//
// MUST READ The book:
// Essential Mathematics for Games and Interactive Applications page
// ( from 10.6.1 Linear Interpolation to 10.6.3 Performance Improvements )
//
// SLERP is:
// - NOT commutative
// - constant velocity
// - torque minimal
//
// so not to be used when blending multiple non ordered rotations
// (as in multiple animation)
//
slerp: ( function () {
var epsilon = 0.00001;
// a and be must be normalized
// (otherwise they're not rotation...)
// t must be between 0 and 1
return function ( t, a, b, r ) {
var cos = this.dot( a, b );
var invTB = 1.0;
// shortest path
if ( cos < 0.0 ) {
invTB = -1.0;
cos = -cos;
}
var ta, tb;
if ( cos > 1.0 - epsilon ) {
// negligible rotation: optimize by just a lerp
// a line rather than a rotation.
ta = 1.0 - t;
tb = t;
} else {
var sin = Math.sqrt( 1.0 - cos * cos );
// which one is better ?
// Atan2:
// sin != 0 && cos !f= 0
// Atan2 returns the angle between -π and π radians (equivalent to -180 and 180 degrees)
var angle = Math.atan2( sin, cos );
// Acos:
// need clamp(-1,1) on input Cos to avoid NaN but we make it lerp anyway
// acos returns the angle between 0 and π radians (equivalent to 0 and 180 degrees)
//var angle = Math.acos( cos ); / / 0 <= omega <= Pi( see man acos )
var oneOverSin = 1.0 / sin;
ta = Math.sin( ( 1.0 - t ) * angle ) * oneOverSin;
tb = Math.sin( t * angle ) * oneOverSin;
}
tb *= invTB;
r[ 0 ] = a[ 0 ] * ta + b[ 0 ] * tb;
r[ 1 ] = a[ 1 ] * ta + b[ 1 ] * tb;
r[ 2 ] = a[ 2 ] * ta + b[ 2 ] * tb;
r[ 3 ] = a[ 3 ] * ta + b[ 3 ] * tb;
return r;
};
} )(),
transformVec3: function ( q, a, result ) {
var x = a[ 0 ];
var y = a[ 1 ];
var z = a[ 2 ];
var qx = q[ 0 ];
var qy = q[ 1 ];
var qz = q[ 2 ];
var qw = q[ 3 ];
// calculate quat * vec
var ix = qw * x + qy * z - qz * y;
var iy = qw * y + qz * x - qx * z;
var iz = qw * z + qx * y - qy * x;
var iw = -qx * x - qy * y - qz * z;
// calculate result * inverse quat
result[ 0 ] = ix * qw + iw * -qx + iy * -qz - iz * -qy;
result[ 1 ] = iy * qw + iw * -qy + iz * -qx - ix * -qz;
result[ 2 ] = iz * qw + iw * -qz + ix * -qy - iy * -qx;
return result;
},
normalize: function ( q, qr ) {
var div = 1.0 / this.length( q );
qr[ 0 ] = q[ 0 ] * div;
qr[ 1 ] = q[ 1 ] * div;
qr[ 2 ] = q[ 2 ] * div;
qr[ 3 ] = q[ 3 ] * div;
return qr;
},
// conjugate
// we suppose to have unit quaternion
conj: function ( a, result ) {
result[ 0 ] = -a[ 0 ];
result[ 1 ] = -a[ 1 ];
result[ 2 ] = -a[ 2 ];
result[ 3 ] = a[ 3 ];
return result;
},
// only if you don't have unit quaternion
// otherwise use conjugate
inverse: function ( a, result ) {
var div = 1.0 / this.length2( a );
this.conj( a, result );
result[ 0 ] *= div;
result[ 1 ] *= div;
result[ 2 ] *= div;
result[ 3 ] *= div;
return result;
},
// we suppose to have unit quaternion
// multiply 2 quaternions
mult: function ( a, b, result ) {
var ax = a[ 0 ];
var ay = a[ 1 ];
var az = a[ 2 ];
var aw = a[ 3 ];
var bx = b[ 0 ];
var by = b[ 1 ];
var bz = b[ 2 ];
var bw = b[ 3 ];
result[ 0 ] = ax * bw + ay * bz - az * by + aw * bx;
result[ 1 ] = -ax * bz + ay * bw + az * bx + aw * by;
result[ 2 ] = ax * by - ay * bx + az * bw + aw * bz;
result[ 3 ] = -ax * bx - ay * by - az * bz + aw * bw;
return result;
},
div: function ( a, b, result ) {
var d = 1.0 / b;
result[ 0 ] = a[ 0 ] * d;
result[ 1 ] = a[ 1 ] * d;
result[ 2 ] = a[ 2 ] * d;
result[ 3 ] = a[ 3 ] * d;
return result;
},
exp: function ( a, res ) {
var r = Math.sqrt( a[ 0 ] * a[ 0 ] + a[ 1 ] * a[ 1 ] + a[ 2 ] * a[ 2 ] );
var et = Math.exp( a[ 3 ] );
var s = 0;
if ( r > 0.00001 ) {
s = et * Math.sin( r ) / r;
}
res[ 0 ] = s * a[ 0 ];
res[ 1 ] = s * a[ 1 ];
res[ 2 ] = s * a[ 2 ];
res[ 3 ] = et * Math.cos( r );
return res;
},
ln: function ( a, res ) {
var n = a[ 0 ] * a[ 0 ] + a[ 1 ] * a[ 1 ] + a[ 2 ] * a[ 2 ];
var r = Math.sqrt( n );
var t = 0;
if ( r > 0.00001 ) {
t = Math.atan2( r, a[ 3 ] ) / r;
}
n += a[ 3 ] * a[ 3 ];
res[ 0 ] = t * a[ 0 ];
res[ 1 ] = t * a[ 1 ];
res[ 2 ] = t * a[ 2 ];
res[ 3 ] = 0.5 * Math.log( n );
return res;
},
//http://theory.org/software/qfa/writeup/node12.html
//http://www.ece.uwaterloo.ca/~dwharder/C++/CQOST/src/
//http://willperone.net/Code/quaternion.php
// a is computeTangent(q1-1,q1,q2)
// b is computeTangent(q2-1,q2,q2+1)
squad: function ( t, q1, a, b, q2, r ) {
var r1 = this.slerp( t, q1, q2 );
var r2 = this.slerp( t, a, b );
return this.slerp( 2.0 * t * ( 1.0 - t ), r1, r2, r );
},
// qcur is current
// q0 is qcur-1
// q2 is qcur+1
// compute tangent in of q1
computeTangent: function ( q0, qcur, q2, r ) {
// first step
var invq = this.inv( qcur );
var qa = this.create();
var qb = this.create();
this.mult( q2, invq, qa );
this.ln( qa, qa );
this.mult( q0, invq, qb );
this.ln( qb, qb );
this.add( qa, qb, qa );
this.div( qa, -4.0, qa );
this.exp( qa, qb );
return this.mult( qb, qcur, r );
},
makeRotateFromTo: function ( from, to, out ) {
// Now let's get into the real stuff
// Use "dot product plus one" as test as it can be re-used later on
var dotProdPlus1 = 1.0 + vec3.dot( from, to );
// Check for degenerate case of full u-turn. Use epsilon for detection
if ( dotProdPlus1 < 1e-7 ) {
// Get an orthogonal vector of the given vector
// in a plane with maximum vector coordinates.
// Then use it as quaternion axis with pi angle
// Trick is to realize one value at least is >0.6 for a normalized vector.
var x = from[ 0 ];
var y = from[ 1 ];
var z = from[ 2 ];
var norm;
if ( Math.abs( x ) < 0.6 ) {
norm = Math.sqrt( 1.0 - x * x );
out[ 1 ] = z / norm;
out[ 2 ] = -y / norm;
out[ 0 ] = out[ 3 ] = 0.0;
} else if ( Math.abs( y ) < 0.6 ) {
norm = Math.sqrt( 1.0 - y * y );
out[ 0 ] = -z / norm;
out[ 2 ] = x / norm;
out[ 1 ] = out[ 3 ] = 0.0;
} else {
norm = Math.sqrt( 1.0 - z * z );
out[ 0 ] = y / norm;
out[ 1 ] = -x / norm;
out[ 2 ] = out[ 3 ] = 0.0;
}
} else {
// Find the shortest angle quaternion that transforms normalized vectors
// into one other. Formula is still valid when vectors are colinear
var s = Math.sqrt( 0.5 * dotProdPlus1 );
vec3.cross( out, from, to );
var f = 0.5 / s;
out[ 0 ] *= f;
out[ 1 ] *= f;
out[ 2 ] *= f;
out[ 3 ] = s;
}
return out;
}
};
Quat.identity = Quat.create();
module.exports = Quat;

Wyświetl plik

@ -1,67 +0,0 @@
'use strict';
var osgMath = require( 'osg/math' );
var glm = require( 'osg/glMatrix' );
var vec2 = glm.vec2;
/** @class Vec2 Operations */
var Vec2 = {
create: vec2.create,
createAndSet: vec2.fromValues,
copy: function ( a, r ) {
return vec2.copy( r, a );
},
set: function ( a, b, r ) {
return vec2.set( r, a, b );
},
valid: function ( a ) {
if ( osgMath.isNaN( a[ 0 ] ) ) return false;
if ( osgMath.isNaN( a[ 1 ] ) ) return false;
return true;
},
mult: function ( a, b, r ) {
r[ 0 ] = a[ 0 ] * b;
r[ 1 ] = a[ 1 ] * b;
return r;
},
length2: vec2.sqrLen,
length: vec2.len,
distance2: function ( a, b ) {
return vec2.sqrDist( b, a );
},
distance: function ( a, b ) {
return vec2.dist( b, a );
},
normalize: function ( a, r ) {
return vec2.normalize( r, a );
},
dot: vec2.dot,
sub: function ( a, b, r ) {
return vec2.sub( r, a, b );
},
add: function ( a, b, r ) {
return vec2.add( r, a, b );
},
neg: function ( a, r ) {
return vec2.negate( r, a );
},
lerp: function ( t, a, b, r ) {
return vec2.lerp( r, a, b, t );
}
};
module.exports = Vec2;

Wyświetl plik

@ -1,85 +0,0 @@
'use strict';
var osgMath = require( 'osg/math' );
var glm = require( 'osg/glMatrix' );
var vec3 = glm.vec3;
/** @class Vec3 Operations */
var Vec3 = {
create: vec3.create,
createAndSet: vec3.fromValues,
init: function ( a ) {
return vec3.set( a, 0.0, 0.0, 0.0 );
},
set: function ( a, b, c, r ) {
return vec3.set( r, a, b, c );
},
copy: function ( a, r ) {
return vec3.copy( r, a );
},
cross: function ( a, b, r ) {
return vec3.cross( r, a, b );
},
valid: function ( a ) {
if ( osgMath.isNaN( a[ 0 ] ) ) return false;
if ( osgMath.isNaN( a[ 1 ] ) ) return false;
if ( osgMath.isNaN( a[ 2 ] ) ) return false;
return true;
},
mult: function ( a, b, r ) {
r[ 0 ] = a[ 0 ] * b;
r[ 1 ] = a[ 1 ] * b;
r[ 2 ] = a[ 2 ] * b;
return r;
},
length2: vec3.sqrLen,
length: vec3.len,
distance2: function ( a, b ) {
return vec3.sqrDist( b, a );
},
distance: function ( a, b ) {
return vec3.dist( b, a );
},
normalize: function ( a, r ) {
return vec3.normalize( r, a );
},
dot: vec3.dot,
sub: function ( a, b, r ) {
return vec3.sub( r, a, b );
},
add: function ( a, b, r ) {
return vec3.add( r, a, b );
},
neg: function ( a, r ) {
return vec3.negate( r, a );
},
lerp: function ( t, a, b, r ) {
return vec3.lerp( r, a, b, t );
},
equal: function ( a, b ) {
return vec3.exactEquals( a, b );
}
};
Vec3.zero = Vec3.create();
Vec3.one = Vec3.createAndSet( 1.0, 1.0, 1.0 );
Vec3.infinity = Vec3.createAndSet( Infinity, Infinity, Infinity );
Vec3.negativeInfinity = Vec3.createAndSet( -Infinity, -Infinity, -Infinity );
module.exports = Vec3;

Wyświetl plik

@ -1,50 +0,0 @@
'use strict';
var glm = require( 'osg/glMatrix' );
var vec4 = glm.vec4;
/** @class Vec4 Operations */
var Vec4 = {
create: vec4.create,
createAndSet: vec4.fromValues,
init: function ( a ) {
return vec4.set( a, 0.0, 0.0, 0.0, 0.0 );
},
set: function ( a, b, c, d, r ) {
return vec4.set( r, a, b, c, d );
},
dot: vec4.dot,
copy: function ( a, r ) {
return vec4.copy( r, a );
},
sub: function ( a, b, r ) {
return vec4.sub( r, a, b );
},
mult: function ( a, b, r ) {
r[ 0 ] = a[ 0 ] * b;
r[ 1 ] = a[ 1 ] * b;
r[ 2 ] = a[ 2 ] * b;
r[ 3 ] = a[ 3 ] * b;
return r;
},
add: function ( a, b, r ) {
return vec4.add( r, a, b );
},
neg: function ( a, r ) {
return vec4.negate( r, a );
},
lerp: function ( t, a, b, r ) {
return vec4.lerp( r, a, b, t );
}
};
module.exports = Vec4;

Wyświetl plik

@ -1,537 +0,0 @@
'use strict';
var mth = require( 'osg/math' );
var glm = require( 'gl-matrix' );
var config = require( '../config.js' );
glm.glMatrix.setMatrixArrayType( config.ArrayType );
glm.glMatrix.EPSILON = 1e-9;
var vec2 = glm.vec2;
var vec3 = glm.vec3;
var vec4 = glm.vec4;
var mat4 = glm.mat4;
var quat = glm.quat;
// osg vec3 additions
vec3.create32 = function () {
return new Float32Array( 3 );
};
vec3.create64 = function () {
return new Float64Array( 3 );
};
vec3.fromValues32 = function ( a, b, c ) {
var out = new Float32Array( 3 );
out[ 0 ] = a;
out[ 1 ] = b;
out[ 2 ] = c;
return out;
};
vec3.fromValues64 = function ( a, b, c ) {
var out = new Float64Array( 3 );
out[ 0 ] = a;
out[ 1 ] = b;
out[ 2 ] = c;
return out;
};
vec3.init = function ( out ) {
return vec3.set( out, 0.0, 0.0, 0.0 );
};
vec3.transformMat4R = function ( out, v, m ) {
out[ 0 ] = m[ 0 ] * v[ 0 ] + m[ 1 ] * v[ 1 ] + m[ 2 ] * v[ 2 ];
out[ 1 ] = m[ 4 ] * v[ 0 ] + m[ 5 ] * v[ 1 ] + m[ 6 ] * v[ 2 ];
out[ 2 ] = m[ 8 ] * v[ 0 ] + m[ 9 ] * v[ 1 ] + m[ 10 ] * v[ 2 ];
};
vec3.valid = function ( a ) {
if ( mth.isNaN( a[ 0 ] ) ) return false;
if ( mth.isNaN( a[ 1 ] ) ) return false;
if ( mth.isNaN( a[ 2 ] ) ) return false;
return true;
};
vec3.neg = vec3.negate;
vec3.ZERO = vec3.create();
vec3.ONE = vec3.fromValues( 1.0, 1.0, 1.0 );
vec3.INFINITY = vec3.fromValues( Infinity, Infinity, Infinity );
vec3.NEGATIVE_INFINITY = vec3.fromValues( -Infinity, -Infinity, -Infinity );
// osg vec2 additions
vec2.create32 = function () {
return new Float32Array( 2 );
};
vec2.create64 = function () {
return new Float64Array( 2 );
};
vec2.fromValues32 = function ( a, b ) {
var out = new Float32Array( 2 );
out[ 0 ] = a;
out[ 1 ] = b;
return out;
};
vec2.fromValues64 = function ( a, b ) {
var out = new Float64Array( 2 );
out[ 0 ] = a;
out[ 1 ] = b;
return out;
};
vec2.init = function ( out ) {
return vec2.set( out, 0.0, 0.0 );
};
vec2.valid = function ( a ) {
if ( mth.isNaN( a[ 0 ] ) ) return false;
if ( mth.isNaN( a[ 1 ] ) ) return false;
return true;
};
vec2.ZERO = vec2.create();
vec2.ONE = vec2.fromValues( 1.0, 1.0 );
vec2.INFINITY = vec2.fromValues( Infinity, Infinity );
vec2.NEGATIVE_INFINITY = vec2.fromValues( -Infinity, -Infinity );
// osg vec4 additions
vec4.create32 = function () {
return new Float32Array( 4 );
};
vec4.create64 = function () {
return new Float64Array( 4 );
};
vec4.fromValues32 = function ( a, b, c, d ) {
var out = new Float32Array( 4 );
out[ 0 ] = a;
out[ 1 ] = b;
out[ 2 ] = c;
out[ 3 ] = d;
return out;
};
vec4.fromValues64 = function ( a, b, c, d ) {
var out = new Float64Array( 4 );
out[ 0 ] = a;
out[ 1 ] = b;
out[ 2 ] = c;
out[ 3 ] = d;
return out;
};
vec4.init = function ( out ) {
return vec4.set( out, 0.0, 0.0, 0.0, 0.0 );
};
vec4.valid = function ( a ) {
if ( mth.isNaN( a[ 0 ] ) ) return false;
if ( mth.isNaN( a[ 1 ] ) ) return false;
if ( mth.isNaN( a[ 2 ] ) ) return false;
if ( mth.isNaN( a[ 3 ] ) ) return false;
return true;
};
vec4.neg = vec4.negate;
vec4.ZERO = vec4.create();
vec4.ONE = vec4.fromValues( 1.0, 1.0, 1.0, 1.0 );
vec4.INFINITY = vec4.fromValues( Infinity, Infinity, Infinity, Infinity );
vec4.NEGATIVE_INFINITY = vec4.fromValues( -Infinity, -Infinity, -Infinity, -Infinity );
// quat
quat.IDENTITY = quat.create();
quat.zeroRotation = function ( q ) {
return q[ 0 ] === 0.0 && q[ 1 ] === 0.0 && q[ 2 ] === 0.0 && q[ 3 ] === 1.0;
};
quat.create32 = function () {
var out = new Float32Array( 4 );
out[ 3 ] = 1.0;
return out;
};
quat.create64 = function () {
var out = new Float64Array( 4 );
out[ 3 ] = 1.0;
return out;
};
quat.fromValues32 = vec4.fromValues32;
quat.fromValues64 = vec4.fromValues64;
quat.init = quat.identity;
// http://physicsforgames.blogspot.fr/2010/02/quaternions.html
// called quatBlend
//
// NLERP is supposed to be
// - Commutative,
// - NOT Constant velocity
// - Torque minimal
//
// a and be must be normalized
// (otherwise they're not rotation...)
// t must be between 0 and 1
quat.nlerp = function ( out, a, b, t ) {
var ax = a[ 0 ],
ay = a[ 1 ],
az = a[ 2 ],
aw = a[ 3 ],
bx = b[ 0 ],
by = b[ 1 ],
bz = b[ 2 ],
bw = b[ 3 ];
var dot = ax * bx + ay * by + az * bz + aw * bw;
var at = 1.0 - t;
var outx, outy, outz, outw;
// shortest path
if ( dot < 0.0 ) {
// negates directly b in the 4 equation
// this.neg( b, r );
outx = ax * at - bx * t;
outy = ay * at - by * t;
outz = az * at - bz * t;
outw = aw * at - bw * t;
} else {
outx = ax * at + bx * t;
outy = ay * at + by * t;
outz = az * at + bz * t;
outw = aw * at + bw * t;
}
var invLen = 1.0 / Math.sqrt( outx * outx + outy * outy + outz * outz + outw * outw );
out[ 0 ] = outx * invLen;
out[ 1 ] = outy * invLen;
out[ 2 ] = outz * invLen;
out[ 3 ] = outw * invLen;
return out;
};
// MUST READ on SLERP, NLERP, LOG-LERP
// http://number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/
// with a slerp implementation (robust)
//
// MUST READ Howto enhance lerp, slerp and q normalize
// http://number-none.com/product/Hacking%20Quaternions/
//
// MUST READ The book:
// Essential Mathematics for Games and Interactive Applications page
// ( from 10.6.1 Linear Interpolation to 10.6.3 Performance Improvements )
//
// SLERP is:
// - NOT commutative
// - constant velocity
// - torque minimal
//
// so not to be used when blending multiple non ordered rotations
// (as in multiple animation)
//
// slerp see glMatrix implementation
// mat4 additions
mat4.IDENTITY = mat4.create();
mat4.create32 = function () {
var out = new Float32Array( 16 );
out[ 0 ] = out[ 5 ] = out[ 10 ] = out[ 15 ] = 1.0;
return out;
};
mat4.create64 = function () {
var out = new Float64Array( 16 );
out[ 0 ] = out[ 5 ] = out[ 10 ] = out[ 15 ] = 1.0;
return out;
};
mat4.setTranslation = function ( out, a ) {
out[ 12 ] = a[ 0 ];
out[ 13 ] = a[ 1 ];
out[ 14 ] = a[ 2 ];
return out;
};
mat4.getFrustum = function ( out, matrix ) {
var right = 0.0;
var left = 0.0;
var top = 0.0;
var bottom = 0.0;
var zNear, zFar;
if ( matrix[ 0 * 4 + 3 ] !== 0.0 || matrix[ 1 * 4 + 3 ] !== 0.0 || matrix[ 2 * 4 + 3 ] !== -1.0 || matrix[ 3 * 4 + 3 ] !== 0.0 ) {
return false;
}
// note: near and far must be used inside this method instead of zNear and zFar
// because zNear and zFar are references and they may point to the same variable.
var tempNear = matrix[ 3 * 4 + 2 ] / ( matrix[ 2 * 4 + 2 ] - 1.0 );
var tempFar = matrix[ 3 * 4 + 2 ] / ( 1.0 + matrix[ 2 * 4 + 2 ] );
left = tempNear * ( matrix[ 2 * 4 ] - 1.0 ) / matrix[ 0 ];
right = tempNear * ( 1.0 + matrix[ 2 * 4 ] ) / matrix[ 0 ];
top = tempNear * ( 1.0 + matrix[ 2 * 4 + 1 ] ) / matrix[ 1 * 4 + 1 ];
bottom = tempNear * ( matrix[ 2 * 4 + 1 ] - 1.0 ) / matrix[ 1 * 4 + 1 ];
zNear = tempNear;
zFar = tempFar;
out.left = left;
out.right = right;
out.top = top;
out.bottom = bottom;
out.zNear = zNear;
out.zFar = zFar;
return true;
};
mat4.getPerspective = ( function () {
var c = {
right: 0,
left: 0,
top: 0,
bottom: 0,
zNear: 0,
zFar: 0
};
return function ( out, matrix ) {
// get frustum and compute results
var r = mat4.getFrustum( c, matrix );
if ( r ) {
out.fovy = 180 / Math.PI * ( Math.atan( c.top / c.zNear ) - Math.atan( c.bottom / c.zNear ) );
out.aspectRatio = ( c.right - c.left ) / ( c.top - c.bottom );
}
out.zNear = c.zNear;
out.zFar = c.zFar;
return out;
};
} )();
mat4.getLookAt = ( function () {
var inv = mat4.create();
var v1 = vec3.create();
var v2 = vec3.fromValues( 0.0, 1.0, 0.0 );
var v3 = vec3.fromValues( 0.0, 0.0, -1.0 );
return function ( eye, center, up, matrix, distance ) {
var d = distance !== undefined ? distance : 1.0;
mat4.invert( inv, matrix );
vec3.transformMat4( eye, v1, inv );
vec3.transformMat4R( up, v2, matrix );
vec3.transformMat4R( center, v3, matrix );
vec3.normalize( center, center );
vec3.add( center, vec3.scale( v1, center, d ), eye );
};
} )();
mat4.getFrustumPlanes = ( function () {
var mvp = mat4.create();
return function ( out, projection, view, withNearFar ) {
mat4.mul( mvp, projection, view );
var computeNearFar = !!withNearFar;
// Right clipping plane.
var right = out[ 0 ];
right[ 0 ] = mvp[ 3 ] - mvp[ 0 ];
right[ 1 ] = mvp[ 7 ] - mvp[ 4 ];
right[ 2 ] = mvp[ 11 ] - mvp[ 8 ];
right[ 3 ] = mvp[ 15 ] - mvp[ 12 ];
// Left clipping plane.
var left = out[ 1 ];
left[ 0 ] = mvp[ 3 ] + mvp[ 0 ];
left[ 1 ] = mvp[ 7 ] + mvp[ 4 ];
left[ 2 ] = mvp[ 11 ] + mvp[ 8 ];
left[ 3 ] = mvp[ 15 ] + mvp[ 12 ];
// Bottom clipping plane.
var bottom = out[ 2 ];
bottom[ 0 ] = mvp[ 3 ] + mvp[ 1 ];
bottom[ 1 ] = mvp[ 7 ] + mvp[ 5 ];
bottom[ 2 ] = mvp[ 11 ] + mvp[ 9 ];
bottom[ 3 ] = mvp[ 15 ] + mvp[ 13 ];
// Top clipping plane.
var top = out[ 3 ];
top[ 0 ] = mvp[ 3 ] - mvp[ 1 ];
top[ 1 ] = mvp[ 7 ] - mvp[ 5 ];
top[ 2 ] = mvp[ 11 ] - mvp[ 9 ];
top[ 3 ] = mvp[ 15 ] - mvp[ 13 ];
var nbPlanes = 4;
if ( computeNearFar ) {
nbPlanes = 6;
// Far clipping plane.
var far = out[ 4 ];
far[ 0 ] = mvp[ 3 ] - mvp[ 2 ];
far[ 1 ] = mvp[ 7 ] - mvp[ 6 ];
far[ 2 ] = mvp[ 11 ] - mvp[ 10 ];
far[ 3 ] = mvp[ 15 ] - mvp[ 14 ];
// Near clipping plane.
var near = out[ 5 ];
near[ 0 ] = mvp[ 3 ] + mvp[ 2 ];
near[ 1 ] = mvp[ 7 ] + mvp[ 6 ];
near[ 2 ] = mvp[ 11 ] + mvp[ 10 ];
near[ 3 ] = mvp[ 15 ] + mvp[ 14 ];
}
//Normalize the planes, from osg code
for ( var i = 0; i < nbPlanes; i++ ) {
var p = out[ i ];
// multiply the coefficients of the plane equation with a constant factor so that the equation a^2+b^2+c^2 = 1 holds.
var inv = 1.0 / Math.sqrt( p[ 0 ] * p[ 0 ] + p[ 1 ] * p[ 1 ] + p[ 2 ] * p[ 2 ] );
p[ 0 ] *= inv;
p[ 1 ] *= inv;
p[ 2 ] *= inv;
p[ 3 ] *= inv;
}
};
} )();
// better precison
// no far clipping artifacts.
// no reason not to use.
// Tightening the Precision of Perspective Rendering
//http://www.geometry.caltech.edu/pubs/UD12.pdf
// drop-in, just remove the one below, and rename this one
mat4.infiniteFrustum = function ( out, left, right, bottom, top, znear ) {
var X = 2.0 * znear / ( right - left );
var Y = 2.0 * znear / ( top - bottom );
var A = ( right + left ) / ( right - left );
var B = ( top + bottom ) / ( top - bottom );
var C = -1.0;
out[ 0 ] = X;
out[ 1 ] = 0.0;
out[ 2 ] = 0.0;
out[ 3 ] = 0.0;
out[ 4 ] = 0.0;
out[ 5 ] = Y;
out[ 6 ] = 0.0;
out[ 7 ] = 0.0;
out[ 8 ] = A;
out[ 9 ] = B;
out[ 10 ] = C;
out[ 11 ] = -1.0;
out[ 12 ] = 0.0;
out[ 13 ] = 0.0;
out[ 14 ] = -2.0 * znear;
out[ 15 ] = 0.0;
return out;
};
mat4.lookAtDirection = ( function () {
var s = vec3.create();
var u = vec3.create();
var neg = vec3.create();
return function ( out, eye, eyeDir, up ) {
var f = eyeDir;
vec3.cross( s, f, up );
vec3.normalize( s, s );
vec3.cross( u, s, f );
vec3.normalize( u, u );
// s[0], u[0], -f[0], 0.0,
// s[1], u[1], -f[1], 0.0,
// s[2], u[2], -f[2], 0.0,
// 0, 0, 0, 1.0
out[ 0 ] = s[ 0 ];
out[ 1 ] = u[ 0 ];
out[ 2 ] = -f[ 0 ];
out[ 3 ] = 0.0;
out[ 4 ] = s[ 1 ];
out[ 5 ] = u[ 1 ];
out[ 6 ] = -f[ 1 ];
out[ 7 ] = 0.0;
out[ 8 ] = s[ 2 ];
out[ 9 ] = u[ 2 ];
out[ 10 ] = -f[ 2 ];
out[ 11 ] = 0.0;
out[ 12 ] = 0;
out[ 13 ] = 0;
out[ 14 ] = 0;
out[ 15 ] = 1.0;
return mat4.translate( out, out, vec3.neg( neg, eye ) );
};
} )();
mat4.getScale = ( function () {
var sx = vec3.create();
var sy = vec3.create();
var sz = vec3.create();
return function ( out, matrix ) {
sx[ 0 ] = matrix[ 0 ];
sx[ 1 ] = matrix[ 4 ];
sx[ 2 ] = matrix[ 8 ];
sy[ 0 ] = matrix[ 1 ];
sy[ 1 ] = matrix[ 5 ];
sy[ 2 ] = matrix[ 9 ];
sz[ 0 ] = matrix[ 2 ];
sz[ 1 ] = matrix[ 6 ];
sz[ 2 ] = matrix[ 10 ];
out[ 0 ] = vec3.length( sx );
out[ 1 ] = vec3.length( sy );
out[ 2 ] = vec3.length( sz );
return out;
};
} )();
mat4.getSqrScale = ( function () {
var sx = vec3.create();
var sy = vec3.create();
var sz = vec3.create();
return function ( out, matrix ) {
sx[ 0 ] = matrix[ 0 ];
sx[ 1 ] = matrix[ 4 ];
sx[ 2 ] = matrix[ 8 ];
sy[ 0 ] = matrix[ 1 ];
sy[ 1 ] = matrix[ 5 ];
sy[ 2 ] = matrix[ 9 ];
sz[ 0 ] = matrix[ 2 ];
sz[ 1 ] = matrix[ 6 ];
sz[ 2 ] = matrix[ 10 ];
out[ 0 ] = vec3.sqrLen( sx );
out[ 1 ] = vec3.sqrLen( sy );
out[ 2 ] = vec3.sqrLen( sz );
return out;
};
} )();
var glmRotate = mat4.rotate;
mat4.rotate = function ( out, a, rad, axis ) {
return glmRotate( out, a, rad, axis ) || mat4.identity( out );
};
var glmFromRotate = mat4.fromRotation;
mat4.fromRotation = function ( out, rad, axis ) {
return glmFromRotate( out, rad, axis ) || mat4.identity( out );
};
module.exports = glm;

Wyświetl plik

@ -1,25 +0,0 @@
'use strict';
var clamp = function ( x, min, max ) {
// http://jsperf.com/math-clamp
// http://jsperf.com/clamping-methods/2
return Math.min( max, Math.max( min, x ) );
};
var smoothStep = function ( edge0, edge1, x ) {
var t = clamp( ( x - edge0 ) / ( edge1 - edge0 ), 0.0, 1.0 );
return t * t * ( 3.0 - 2.0 * t );
};
// native isNaN is slow (e.g: https://jsperf.com/isnan-performance/2)
// note : native isNaN will return true for undefined but
// this function assume that x is a number
var fastIsNaN = function ( x ) {
return x !== x;
};
module.exports = {
clamp: clamp,
smoothStep: smoothStep,
isNaN: fastIsNaN
};

Wyświetl plik

@ -1,108 +0,0 @@
'use strict';
var Notify = {};
// must be uppercase and match loggers
Notify.DEBUG = 0;
Notify.INFO = 1;
Notify.NOTICE = Notify.LOG = 2;
Notify.WARN = 3;
Notify.ERROR = 4;
Notify.console = window.console;
/** logging with readability in mind.
* @param { level } what severity is that log (gives text color too )
* @param { str } actual log text
* @param { fold } sometimes you want to hide looooong text
*/
function logSub( level, str ) {
if ( !Notify.console ) return;
Notify.console[ level ]( str );
if ( Notify.traceLogCall && level !== 'error' ) console.trace();
}
function logSubFold( level, title, str ) {
if ( !Notify.console ) return;
if ( Notify.console.groupCollapsed ) Notify.console.groupCollapsed( title );
Notify.console[ level ]( str );
if ( Notify.traceLogCall && level !== 'error' ) console.trace();
if ( Notify.console.groupEnd ) Notify.console.groupEnd();
}
function unFlattenMatrix( m, rowMajor ) {
if ( rowMajor ) {
return [ m.slice( 0, 4 ), m.slice( 4, 8 ), m.slice( 8, 12 ), m.slice( 12, 16 ) ];
}
return [
[ m[ 0 ], m[ 4 ], m[ 8 ], m[ 12 ] ],
[ m[ 1 ], m[ 5 ], m[ 9 ], m[ 13 ] ],
[ m[ 2 ], m[ 6 ], m[ 10 ], m[ 14 ] ],
[ m[ 3 ], m[ 7 ], m[ 11 ], m[ 15 ] ]
];
}
function logMatrix( m, rowMajor ) {
if ( Notify.console.table )
logSub( 'table', unFlattenMatrix( m, rowMajor ) );
}
function logMatrixFold( title, m, rowMajor ) {
if ( Notify.console.table )
logSubFold( 'table', title, unFlattenMatrix( m, rowMajor ) );
}
var levelEntries = [ 'log', 'info', 'warn', 'error', 'debug' ];
var loggers = {};
for ( var i = 0; i < levelEntries.length; ++i ) {
var level = levelEntries[ i ];
loggers[ level ] = logSub.bind( Notify, level );
loggers[ level + 'Fold' ] = logSubFold.bind( Notify, level );
loggers[ level + 'Matrix' ] = logMatrix.bind( Notify );
loggers[ level + 'MatrixFold' ] = logMatrixFold.bind( Notify );
}
var assert = function ( test, str ) {
if ( this.console !== undefined && !test ) {
this.console.assert( test, str );
}
};
Notify.assert = assert;
Notify.setNotifyLevel = function ( logLevel ) {
var dummy = function () {};
for ( var i = 0; i < levelEntries.length; ++i ) {
var level = levelEntries[ i ];
var doDummy = logLevel > Notify[ level.toUpperCase() ];
Notify[ level ] = doDummy ? dummy : loggers[ level ];
Notify[ level + 'Fold' ] = doDummy ? dummy : loggers[ level + 'Fold' ];
Notify[ level + 'Matrix' ] = doDummy ? dummy : loggers[ level + 'Matrix' ];
Notify[ level + 'MatrixFold' ] = doDummy ? dummy : loggers[ level + 'MatrixFold' ];
}
// alias
Notify.notice = Notify.log;
Notify.noticeFold = Notify.logFold;
Notify.noticeMatrix = Notify.logMatrix;
Notify.noticeMatrixFold = Notify.logMatrixFold;
};
Notify.setNotifyLevel( Notify.NOTICE );
Notify.reportWebGLError = false;
Notify.setConsole = function ( replacement ) {
Notify.console = replacement;
};
module.exports = Notify;

Wyświetl plik

@ -1,176 +0,0 @@
'use strict';
var AutoTransform = require( 'osg/AutoTransform' );
var BillboardAttribute = require( 'osg/BillboardAttribute' );
var BlendColor = require( 'osg/BlendColor' );
var BlendFunc = require( 'osg/BlendFunc' );
var BoundingBox = require( 'osg/BoundingBox' );
var BoundingSphere = require( 'osg/BoundingSphere' );
var BufferArray = require( 'osg/BufferArray' );
var Camera = require( 'osg/Camera' );
var ColorMask = require( 'osg/ColorMask' );
var ComputeBoundsVisitor = require( 'osg/ComputeBoundsVisitor' );
var ComputeMatrixFromNodePath = require( 'osg/computeMatrixFromNodePath' );
var CullFace = require( 'osg/CullFace' );
var CullingSet = require( 'osg/CullingSet' );
var CullSettings = require( 'osg/CullSettings' );
var CullStack = require( 'osg/CullStack' );
var CullVisitor = require( 'osg/CullVisitor' );
var Depth = require( 'osg/Depth' );
var DrawArrayLengths = require( 'osg/DrawArrayLengths' );
var DrawArrays = require( 'osg/DrawArrays' );
var DrawElements = require( 'osg/DrawElements' );
var EllipsoidModel = require( 'osg/EllipsoidModel' );
var FrameBufferObject = require( 'osg/FrameBufferObject' );
var FrameStamp = require( 'osg/FrameStamp' );
var Geometry = require( 'osg/Geometry' );
var GLObject = require( 'osg/GLObject' );
var Image = require( 'osg/Image' );
var ImageStream = require( 'osg/ImageStream' );
var KdTree = require( 'osg/KdTree' );
var KdTreeBuilder = require( 'osg/KdTreeBuilder' );
var Light = require( 'osg/Light' );
var LightSource = require( 'osg/LightSource' );
var LineWidth = require( 'osg/LineWidth' );
var Lod = require( 'osg/Lod' );
var Map = require( 'osg/Map' );
var Material = require( 'osg/Material' );
var osgjsMath = require( 'osg/math' );
var Matrix = require( 'osg/Matrix' );
var MatrixMemoryPool = require( 'osg/MatrixMemoryPool' );
var MatrixTransform = require( 'osg/MatrixTransform' );
var Node = require( 'osg/Node' );
var NodeVisitor = require( 'osg/NodeVisitor' );
var Notify = require( 'osg/notify' );
var Object = require( 'osg/Object' );
var PagedLOD = require( 'osg/PagedLOD' );
var Polytope = require( 'osg/Polytope' );
var Plane = require( 'osg/Plane' );
var PrimitiveFunctor = require( 'osg/PrimitiveFunctor' );
var PrimitiveSet = require( 'osg/primitiveSet' );
var Program = require( 'osg/Program' );
var Projection = require( 'osg/Projection' );
var Quat = require( 'osg/Quat' );
var RenderBin = require( 'osg/RenderBin' );
var RenderLeaf = require( 'osg/RenderLeaf' );
var RenderStage = require( 'osg/RenderStage' );
var Shader = require( 'osg/Shader' );
var Shape = require( 'osg/shape' );
var Stack = require( 'osg/Stack' );
var State = require( 'osg/State' );
var StateAttribute = require( 'osg/StateAttribute' );
var StateGraph = require( 'osg/StateGraph' );
var StateSet = require( 'osg/StateSet' );
var Texture = require( 'osg/Texture' );
var TextureCubeMap = require( 'osg/TextureCubeMap' );
var Transform = require( 'osg/Transform' );
var TriangleIndexFunctor = require( 'osg/TriangleIndexFunctor' );
var Uniform = require( 'osg/Uniform' );
var UpdateVisitor = require( 'osg/UpdateVisitor' );
var MACROUTILS = require( 'osg/Utils' );
var Vec2 = require( 'osg/Vec2' );
var Vec3 = require( 'osg/Vec3' );
var Vec4 = require( 'osg/Vec4' );
var Viewport = require( 'osg/Viewport' );
var osgPool = require( 'osgUtil/osgPool' );
var Scissor = require( 'osg/Scissor' );
var TransformEnums = require( 'osg/transformEnums' );
var Timer = require( 'osg/Timer' );
var TimerGPU = require( 'osg/TimerGPU' );
var WebGLCaps = require( 'osg/WebGLCaps' );
var osg = {};
osg.AutoTransform = AutoTransform;
osg.BillboardAttribute = BillboardAttribute;
osg.BlendColor = BlendColor;
osg.BlendFunc = BlendFunc;
osg.BoundingBox = BoundingBox;
osg.BoundingSphere = BoundingSphere;
osg.BufferArray = BufferArray;
osg.ColorMask = ColorMask;
osg.Camera = Camera;
osg.ColorMask = ColorMask;
osg.ComputeBoundsVisitor = ComputeBoundsVisitor;
MACROUTILS.objectMix( osg, ComputeMatrixFromNodePath );
osg.CullFace = CullFace;
osg.CullingSet = CullingSet;
osg.CullSettings = CullSettings;
osg.CullStack = CullStack;
osg.CullVisitor = CullVisitor;
osg.Depth = Depth;
osg.DrawArrayLengths = DrawArrayLengths;
osg.DrawArrays = DrawArrays;
osg.DrawElements = DrawElements;
osg.EllipsoidModel = EllipsoidModel;
osg.WGS_84_RADIUS_EQUATOR = EllipsoidModel.WGS_84_RADIUS_EQUATOR;
osg.WGS_84_RADIUS_POLAR = EllipsoidModel.WGS_84_RADIUS_POLAR;
osg.FrameBufferObject = FrameBufferObject;
osg.FrameStamp = FrameStamp;
osg.Geometry = Geometry;
osg.GLObject = GLObject;
osg.Image = Image;
osg.ImageStream = ImageStream;
osg.KdTree = KdTree;
osg.KdTreeBuilder = KdTreeBuilder;
osg.Light = Light;
osg.LightSource = LightSource;
osg.LineWidth = LineWidth;
osg.Lod = Lod;
osg.Map = Map;
osg.Material = Material;
MACROUTILS.objectMix( osg, osgjsMath );
osg.Matrix = Matrix;
osg.MatrixTransform = MatrixTransform;
osg.MatrixMemoryPool = MatrixMemoryPool;
osg.Node = Node;
osg.NodeVisitor = NodeVisitor;
MACROUTILS.objectMix( osg, Notify );
osg.Object = Object;
osg.PagedLOD = PagedLOD;
osg.Plane = Plane;
osg.Polytope = Polytope;
osg.PrimitiveSet = PrimitiveSet;
osg.PrimitiveFunctor = PrimitiveFunctor;
osg.Program = Program;
osg.Projection = Projection;
osg.Quat = Quat;
osg.RenderBin = RenderBin;
osg.RenderLeaf = RenderLeaf;
osg.RenderStage = RenderStage;
osg.Shader = Shader;
MACROUTILS.objectMix( osg, Shape );
osg.Stack = Stack;
osg.State = State;
osg.StateAttribute = StateAttribute;
osg.StateGraph = StateGraph;
osg.StateSet = StateSet;
osg.Scissor = Scissor;
osg.Texture = Texture;
osg.TextureCubeMap = TextureCubeMap;
osg.Transform = Transform;
osg.TriangleIndexFunctor = TriangleIndexFunctor;
osg.Uniform = Uniform;
osg.UpdateVisitor = UpdateVisitor;
MACROUTILS.objectMix( osg, MACROUTILS );
osg.Vec2 = Vec2;
osg.Vec3 = Vec3;
osg.Vec4 = Vec4;
osg.Viewport = Viewport;
var glm = require( 'osg/glMatrix' );
osg.vec2 = glm.vec2;
osg.vec3 = glm.vec3;
osg.vec4 = glm.vec4;
osg.quat = glm.quat;
osg.mat4 = glm.mat4;
osg.memoryPools = osgPool.memoryPools;
osg.Transform.RELATIVE_RF = TransformEnums.RELATIVE_RF;
osg.Transform.ABSOLUTE_RF = TransformEnums.ABSOLUTE_RF;
osg.Timer = Timer;
osg.TimerGPU = TimerGPU;
osg.WebGLCaps = WebGLCaps;
module.exports = osg;

Wyświetl plik

@ -1,11 +0,0 @@
'use strict';
var PrimitiveSet = {};
PrimitiveSet.POINTS = 0x0000;
PrimitiveSet.LINES = 0x0001;
PrimitiveSet.LINE_LOOP = 0x0002;
PrimitiveSet.LINE_STRIP = 0x0003;
PrimitiveSet.TRIANGLES = 0x0004;
PrimitiveSet.TRIANGLE_STRIP = 0x0005;
PrimitiveSet.TRIANGLE_FAN = 0x0006;
module.exports = PrimitiveSet;

Wyświetl plik

@ -1,797 +0,0 @@
'use strict';
var Notify = require( 'osg/notify' );
var vec3 = require( 'osg/glMatrix' ).vec3;
var BufferArray = require( 'osg/BufferArray' );
var Geometry = require( 'osg/Geometry' );
var PrimitiveSet = require( 'osg/primitiveSet' );
var DrawArrays = require( 'osg/DrawArrays' );
var DrawElements = require( 'osg/DrawElements' );
var Program = require( 'osg/Program' );
var Shader = require( 'osg/Shader' );
var MACROUTILS = require( 'osg/Utils' );
/**
* Create a Textured Box on the given center with given size
* @name createTexturedBox
*/
var createTexturedBoxGeometry = function ( cx, cy, cz,
sx, sy, sz ) {
var centerx = cx !== undefined ? cx : 0.0;
var centery = cy !== undefined ? cy : 0.0;
var centerz = cz !== undefined ? cz : 0.0;
var sizex = sx !== undefined ? sx : 1.0;
var sizey = sy !== undefined ? sy : 1.0;
var sizez = sz !== undefined ? sz : 1.0;
var g = new Geometry();
var dx, dy, dz;
dx = sizex / 2.0;
dy = sizey / 2.0;
dz = sizez / 2.0;
var vertexes = new MACROUTILS.Float32Array( 72 );
var uv = new MACROUTILS.Float32Array( 48 );
var normal = new MACROUTILS.Float32Array( 72 );
// -ve y plane
vertexes[ 0 ] = centerx - dx;
vertexes[ 1 ] = centery - dy;
vertexes[ 2 ] = centerz + dz;
normal[ 0 ] = 0.0;
normal[ 1 ] = -1.0;
normal[ 2 ] = 0.0;
uv[ 0 ] = 0.0;
uv[ 1 ] = 1.0;
vertexes[ 3 ] = centerx - dx;
vertexes[ 4 ] = centery - dy;
vertexes[ 5 ] = centerz - dz;
normal[ 3 ] = 0.0;
normal[ 4 ] = -1.0;
normal[ 5 ] = 0.0;
uv[ 2 ] = 0.0;
uv[ 3 ] = 0.0;
vertexes[ 6 ] = centerx + dx;
vertexes[ 7 ] = centery - dy;
vertexes[ 8 ] = centerz - dz;
normal[ 6 ] = 0.0;
normal[ 7 ] = -1.0;
normal[ 8 ] = 0.0;
uv[ 4 ] = 1.0;
uv[ 5 ] = 0.0;
vertexes[ 9 ] = centerx + dx;
vertexes[ 10 ] = centery - dy;
vertexes[ 11 ] = centerz + dz;
normal[ 9 ] = 0.0;
normal[ 10 ] = -1.0;
normal[ 11 ] = 0.0;
uv[ 6 ] = 1.0;
uv[ 7 ] = 1.0;
// +ve y plane
vertexes[ 12 ] = centerx + dx;
vertexes[ 13 ] = centery + dy;
vertexes[ 14 ] = centerz + dz;
normal[ 12 ] = 0.0;
normal[ 13 ] = 1.0;
normal[ 14 ] = 0.0;
uv[ 8 ] = 0.0;
uv[ 9 ] = 1.0;
vertexes[ 15 ] = centerx + dx;
vertexes[ 16 ] = centery + dy;
vertexes[ 17 ] = centerz - dz;
normal[ 15 ] = 0.0;
normal[ 16 ] = 1.0;
normal[ 17 ] = 0.0;
uv[ 10 ] = 0.0;
uv[ 11 ] = 0.0;
vertexes[ 18 ] = centerx - dx;
vertexes[ 19 ] = centery + dy;
vertexes[ 20 ] = centerz - dz;
normal[ 18 ] = 0.0;
normal[ 19 ] = 1.0;
normal[ 20 ] = 0.0;
uv[ 12 ] = 1.0;
uv[ 13 ] = 0.0;
vertexes[ 21 ] = centerx - dx;
vertexes[ 22 ] = centery + dy;
vertexes[ 23 ] = centerz + dz;
normal[ 21 ] = 0.0;
normal[ 22 ] = 1.0;
normal[ 23 ] = 0.0;
uv[ 14 ] = 1.0;
uv[ 15 ] = 1.0;
// +ve x plane
vertexes[ 24 ] = centerx + dx;
vertexes[ 25 ] = centery - dy;
vertexes[ 26 ] = centerz + dz;
normal[ 24 ] = 1.0;
normal[ 25 ] = 0.0;
normal[ 26 ] = 0.0;
uv[ 16 ] = 0.0;
uv[ 17 ] = 1.0;
vertexes[ 27 ] = centerx + dx;
vertexes[ 28 ] = centery - dy;
vertexes[ 29 ] = centerz - dz;
normal[ 27 ] = 1.0;
normal[ 28 ] = 0.0;
normal[ 29 ] = 0.0;
uv[ 18 ] = 0.0;
uv[ 19 ] = 0.0;
vertexes[ 30 ] = centerx + dx;
vertexes[ 31 ] = centery + dy;
vertexes[ 32 ] = centerz - dz;
normal[ 30 ] = 1.0;
normal[ 31 ] = 0.0;
normal[ 32 ] = 0.0;
uv[ 20 ] = 1.0;
uv[ 21 ] = 0.0;
vertexes[ 33 ] = centerx + dx;
vertexes[ 34 ] = centery + dy;
vertexes[ 35 ] = centerz + dz;
normal[ 33 ] = 1.0;
normal[ 34 ] = 0.0;
normal[ 35 ] = 0.0;
uv[ 22 ] = 1.0;
uv[ 23 ] = 1.0;
// -ve x plane
vertexes[ 36 ] = centerx - dx;
vertexes[ 37 ] = centery + dy;
vertexes[ 38 ] = centerz + dz;
normal[ 36 ] = -1.0;
normal[ 37 ] = 0.0;
normal[ 38 ] = 0.0;
uv[ 24 ] = 0.0;
uv[ 25 ] = 1.0;
vertexes[ 39 ] = centerx - dx;
vertexes[ 40 ] = centery + dy;
vertexes[ 41 ] = centerz - dz;
normal[ 39 ] = -1.0;
normal[ 40 ] = 0.0;
normal[ 41 ] = 0.0;
uv[ 26 ] = 0.0;
uv[ 27 ] = 0.0;
vertexes[ 42 ] = centerx - dx;
vertexes[ 43 ] = centery - dy;
vertexes[ 44 ] = centerz - dz;
normal[ 42 ] = -1.0;
normal[ 43 ] = 0.0;
normal[ 44 ] = 0.0;
uv[ 28 ] = 1.0;
uv[ 29 ] = 0.0;
vertexes[ 45 ] = centerx - dx;
vertexes[ 46 ] = centery - dy;
vertexes[ 47 ] = centerz + dz;
normal[ 45 ] = -1.0;
normal[ 46 ] = 0.0;
normal[ 47 ] = 0.0;
uv[ 30 ] = 1.0;
uv[ 31 ] = 1.0;
// top
// +ve z plane
vertexes[ 48 ] = centerx - dx;
vertexes[ 49 ] = centery + dy;
vertexes[ 50 ] = centerz + dz;
normal[ 48 ] = 0.0;
normal[ 49 ] = 0.0;
normal[ 50 ] = 1.0;
uv[ 32 ] = 0.0;
uv[ 33 ] = 1.0;
vertexes[ 51 ] = centerx - dx;
vertexes[ 52 ] = centery - dy;
vertexes[ 53 ] = centerz + dz;
normal[ 51 ] = 0.0;
normal[ 52 ] = 0.0;
normal[ 53 ] = 1.0;
uv[ 34 ] = 0.0;
uv[ 35 ] = 0.0;
vertexes[ 54 ] = centerx + dx;
vertexes[ 55 ] = centery - dy;
vertexes[ 56 ] = centerz + dz;
normal[ 54 ] = 0.0;
normal[ 55 ] = 0.0;
normal[ 56 ] = 1.0;
uv[ 36 ] = 1.0;
uv[ 37 ] = 0.0;
vertexes[ 57 ] = centerx + dx;
vertexes[ 58 ] = centery + dy;
vertexes[ 59 ] = centerz + dz;
normal[ 57 ] = 0.0;
normal[ 58 ] = 0.0;
normal[ 59 ] = 1.0;
uv[ 38 ] = 1.0;
uv[ 39 ] = 1.0;
// bottom
// -ve z plane
vertexes[ 60 ] = centerx + dx;
vertexes[ 61 ] = centery + dy;
vertexes[ 62 ] = centerz - dz;
normal[ 60 ] = 0.0;
normal[ 61 ] = 0.0;
normal[ 62 ] = -1.0;
uv[ 40 ] = 0.0;
uv[ 41 ] = 1.0;
vertexes[ 63 ] = centerx + dx;
vertexes[ 64 ] = centery - dy;
vertexes[ 65 ] = centerz - dz;
normal[ 63 ] = 0.0;
normal[ 64 ] = 0.0;
normal[ 65 ] = -1.0;
uv[ 42 ] = 0.0;
uv[ 43 ] = 0.0;
vertexes[ 66 ] = centerx - dx;
vertexes[ 67 ] = centery - dy;
vertexes[ 68 ] = centerz - dz;
normal[ 66 ] = 0.0;
normal[ 67 ] = 0.0;
normal[ 68 ] = -1.0;
uv[ 44 ] = 1.0;
uv[ 45 ] = 0.0;
vertexes[ 69 ] = centerx - dx;
vertexes[ 70 ] = centery + dy;
vertexes[ 71 ] = centerz - dz;
normal[ 69 ] = 0.0;
normal[ 70 ] = 0.0;
normal[ 71 ] = -1.0;
uv[ 46 ] = 1.0;
uv[ 47 ] = 1.0;
var indexes = new MACROUTILS.Uint16Array( 36 );
indexes[ 0 ] = 0;
indexes[ 1 ] = 1;
indexes[ 2 ] = 2;
indexes[ 3 ] = 0;
indexes[ 4 ] = 2;
indexes[ 5 ] = 3;
indexes[ 6 ] = 4;
indexes[ 7 ] = 5;
indexes[ 8 ] = 6;
indexes[ 9 ] = 4;
indexes[ 10 ] = 6;
indexes[ 11 ] = 7;
indexes[ 12 ] = 8;
indexes[ 13 ] = 9;
indexes[ 14 ] = 10;
indexes[ 15 ] = 8;
indexes[ 16 ] = 10;
indexes[ 17 ] = 11;
indexes[ 18 ] = 12;
indexes[ 19 ] = 13;
indexes[ 20 ] = 14;
indexes[ 21 ] = 12;
indexes[ 22 ] = 14;
indexes[ 23 ] = 15;
indexes[ 24 ] = 16;
indexes[ 25 ] = 17;
indexes[ 26 ] = 18;
indexes[ 27 ] = 16;
indexes[ 28 ] = 18;
indexes[ 29 ] = 19;
indexes[ 30 ] = 20;
indexes[ 31 ] = 21;
indexes[ 32 ] = 22;
indexes[ 33 ] = 20;
indexes[ 34 ] = 22;
indexes[ 35 ] = 23;
g.getAttributes().Vertex = new BufferArray( BufferArray.ARRAY_BUFFER, vertexes, 3 );
g.getAttributes().Normal = new BufferArray( BufferArray.ARRAY_BUFFER, normal, 3 );
g.getAttributes().TexCoord0 = new BufferArray( BufferArray.ARRAY_BUFFER, uv, 2 );
var primitive = new DrawElements( PrimitiveSet.TRIANGLES, new BufferArray( BufferArray.ELEMENT_ARRAY_BUFFER, indexes, 1 ) );
g.getPrimitives().push( primitive );
return g;
};
// better perf
// no more pixel shader hurt for nothing
// http://michaldrobot.com/2014/04/01/gcn-execution-patterns-in-full-screen-passes/
// It's a Singleton, as it's rendering invariant
// so same remove uneeded state change when same geom
var createTexturedFullScreenFakeQuadGeometry = ( function () {
var g = new Geometry();
var uvs = new MACROUTILS.Float32Array( [ -1.0, -1.0, -1.0, 4.0, 4.0, -1.0 ] );
var vertexes = new MACROUTILS.Float32Array( [ -1.0, -1.0, -1.0, 4.0, 4.0, -1.0 ] );
var indexes = new MACROUTILS.Uint16Array( 3 );
indexes[ 0 ] = 2;
indexes[ 1 ] = 1;
indexes[ 2 ] = 0;
// Further optim: no index, no uv (uv.xy = position.xy in vertex shader)
g.getAttributes().Vertex = new BufferArray( BufferArray.ARRAY_BUFFER, vertexes, 2 );
g.getAttributes().TexCoord0 = new BufferArray( BufferArray.ARRAY_BUFFER, uvs, 2 );
var primitive = new DrawElements( PrimitiveSet.TRIANGLES, new BufferArray( BufferArray.ELEMENT_ARRAY_BUFFER, indexes, 1 ) );
g.getPrimitives().push( primitive );
return function () {
return g;
};
} )();
var createTexturedQuadGeometry = function ( cornerx, cornery, cornerz,
wx, wy, wz,
hx, hy, hz,
l, b, r, t ) {
if ( r === undefined && t === undefined ) {
r = l;
t = b;
l = 0.0;
b = 0.0;
}
var g = new Geometry();
var vertexes = new MACROUTILS.Float32Array( 12 );
vertexes[ 0 ] = cornerx + hx;
vertexes[ 1 ] = cornery + hy;
vertexes[ 2 ] = cornerz + hz;
vertexes[ 3 ] = cornerx;
vertexes[ 4 ] = cornery;
vertexes[ 5 ] = cornerz;
vertexes[ 6 ] = cornerx + wx;
vertexes[ 7 ] = cornery + wy;
vertexes[ 8 ] = cornerz + wz;
vertexes[ 9 ] = cornerx + wx + hx;
vertexes[ 10 ] = cornery + wy + hy;
vertexes[ 11 ] = cornerz + wz + hz;
if ( r === undefined ) {
r = 1.0;
}
if ( t === undefined ) {
t = 1.0;
}
var uvs = new MACROUTILS.Float32Array( 8 );
uvs[ 0 ] = l;
uvs[ 1 ] = t;
uvs[ 2 ] = l;
uvs[ 3 ] = b;
uvs[ 4 ] = r;
uvs[ 5 ] = b;
uvs[ 6 ] = r;
uvs[ 7 ] = t;
var n = vec3.fromValues( wx, wy, wz );
vec3.cross( n, n, vec3.fromValues( hx, hy, hz ) );
vec3.normalize( n, n );
var normal = new MACROUTILS.Float32Array( 12 );
normal[ 0 ] = n[ 0 ];
normal[ 1 ] = n[ 1 ];
normal[ 2 ] = n[ 2 ];
normal[ 3 ] = n[ 0 ];
normal[ 4 ] = n[ 1 ];
normal[ 5 ] = n[ 2 ];
normal[ 6 ] = n[ 0 ];
normal[ 7 ] = n[ 1 ];
normal[ 8 ] = n[ 2 ];
normal[ 9 ] = n[ 0 ];
normal[ 10 ] = n[ 1 ];
normal[ 11 ] = n[ 2 ];
var indexes = new MACROUTILS.Uint16Array( 6 );
indexes[ 0 ] = 0;
indexes[ 1 ] = 1;
indexes[ 2 ] = 2;
indexes[ 3 ] = 0;
indexes[ 4 ] = 2;
indexes[ 5 ] = 3;
g.getAttributes().Vertex = new BufferArray( BufferArray.ARRAY_BUFFER, vertexes, 3 );
g.getAttributes().Normal = new BufferArray( BufferArray.ARRAY_BUFFER, normal, 3 );
g.getAttributes().TexCoord0 = new BufferArray( BufferArray.ARRAY_BUFFER, uvs, 2 );
var primitive = new DrawElements( PrimitiveSet.TRIANGLES, new BufferArray( BufferArray.ELEMENT_ARRAY_BUFFER, indexes, 1 ) );
g.getPrimitives().push( primitive );
return g;
};
var createTexturedBox = function ( centerx, centery, centerz,
sizex, sizey, sizez ) {
Notify.log( 'createTexturedBox is deprecated use instead createTexturedBoxGeometry' );
return createTexturedBoxGeometry( centerx, centery, centerz,
sizex, sizey, sizez );
};
var createTexturedQuad = function ( cornerx, cornery, cornerz,
wx, wy, wz,
hx, hy, hz,
l, b, r, t ) {
Notify.log( 'createTexturedQuad is deprecated use instead createTexturedQuadGeometry' );
return createTexturedQuadGeometry( cornerx, cornery, cornerz,
wx, wy, wz,
hx, hy, hz,
l, b, r, t );
};
var createAxisGeometry = function ( size ) {
if ( size === undefined ) {
size = 5.0;
}
if ( createAxisGeometry.getShader === undefined ) {
createAxisGeometry.getShader = function () {
if ( createAxisGeometry.getShader.program === undefined ) {
var vertexshader = [
'#ifdef GL_ES',
'precision highp float;',
'#endif',
'attribute vec3 Vertex;',
'attribute vec4 Color;',
'uniform mat4 uModelViewMatrix;',
'uniform mat4 uProjectionMatrix;',
'',
'varying vec4 vColor;',
'',
'void main(void) {',
' gl_Position = uProjectionMatrix * (uModelViewMatrix * vec4(Vertex, 1.0));',
' vColor = Color;',
'}'
].join( '\n' );
var fragmentshader = [
'#ifdef GL_ES',
'precision highp float;',
'#endif',
'varying vec4 vColor;',
'void main(void) {',
'gl_FragColor = vColor;',
'}'
].join( '\n' );
var program = new Program( new Shader( 'VERTEX_SHADER', vertexshader ),
new Shader( 'FRAGMENT_SHADER', fragmentshader ) );
createAxisGeometry.getShader.program = program;
}
return createAxisGeometry.getShader.program;
};
}
var g = new Geometry();
var vertexes = new MACROUTILS.Float32Array( 18 );
vertexes[ 3 ] = size;
vertexes[ 10 ] = size;
vertexes[ 17 ] = size;
var colors = new MACROUTILS.Float32Array( 24 );
//red color
colors[ 0 ] = colors[ 3 ] = 1.0;
colors[ 4 ] = colors[ 4 + 3 ] = 1.0;
//green color
colors[ 4 * 2 + 1 ] = colors[ 4 * 2 + 3 ] = 1.0;
colors[ 4 * 3 + 1 ] = colors[ 4 * 3 + 3 ] = 1.0;
//blue color
colors[ 4 * 4 + 2 ] = colors[ 4 * 4 + 3 ] = 1.0;
colors[ 4 * 5 + 2 ] = colors[ 4 * 5 + 3 ] = 1.0;
g.getAttributes().Vertex = new BufferArray( BufferArray.ARRAY_BUFFER, vertexes, 3 );
g.getAttributes().Color = new BufferArray( BufferArray.ARRAY_BUFFER, colors, 4 );
var primitive = new DrawArrays( PrimitiveSet.LINES, 0, 6 );
g.getPrimitives().push( primitive );
g.getOrCreateStateSet().setAttributeAndModes( createAxisGeometry.getShader() );
return g;
};
/**
* Create a Textured Sphere on the given center with given radius
* @name createTexturedSphere
* @author Darrell Esau
*/
var createTexturedSphere = function ( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) {
radius = radius || 50.0;
phiStart = phiStart !== undefined ? phiStart : 0.0;
phiLength = phiLength !== undefined ? phiLength : Math.PI * 2;
thetaStart = thetaStart !== undefined ? thetaStart : 0.0;
thetaLength = thetaLength !== undefined ? thetaLength : Math.PI;
var segmentsX = Math.max( 3, Math.floor( widthSegments ) || 8 );
var segmentsY = Math.max( 2, Math.floor( heightSegments ) || 6 );
var useDrawArrays = ( ( segmentsX * segmentsY ) / 3 ) >= 65536;
var nbPrim = useDrawArrays ? segmentsX * segmentsY * 6 : segmentsX * segmentsY * 4;
var fullVerticesList = new MACROUTILS.Float32Array( nbPrim * 3 );
var fullNormalsList = new MACROUTILS.Float32Array( nbPrim * 3 );
var fullUVList = new MACROUTILS.Float32Array( nbPrim * 2 );
var indexes = !useDrawArrays ? new MACROUTILS.Uint16Array( segmentsX * segmentsY * 6 ) : undefined;
var vtxCount = 0;
var triCount = 0;
var v1 = new MACROUTILS.Float32Array( 3 );
var v2 = new MACROUTILS.Float32Array( 3 );
var v3 = new MACROUTILS.Float32Array( 3 );
var v4 = new MACROUTILS.Float32Array( 3 );
var n1 = new MACROUTILS.Float32Array( 3 );
var n2 = new MACROUTILS.Float32Array( 3 );
var n3 = new MACROUTILS.Float32Array( 3 );
var n4 = new MACROUTILS.Float32Array( 3 );
var uv1 = new MACROUTILS.Float32Array( 2 );
var uv2 = new MACROUTILS.Float32Array( 2 );
var uv3 = new MACROUTILS.Float32Array( 2 );
var uv4 = new MACROUTILS.Float32Array( 2 );
var getCoordAndUvSphere = function ( u, v, coord, norm, uv ) {
coord[ 0 ] = -radius * Math.cos( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength );
coord[ 1 ] = radius * Math.cos( thetaStart + v * thetaLength );
coord[ 2 ] = radius * Math.sin( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength );
vec3.normalize( norm, coord );
uv[ 0 ] = u;
uv[ 1 ] = 1 - v;
};
for ( var y = 0; y < segmentsY; y++ ) {
for ( var x = 0; x < segmentsX; x++ ) {
getCoordAndUvSphere( ( x + 1 ) / segmentsX, y / segmentsY, v1, n1, uv1 );
getCoordAndUvSphere( x / segmentsX, y / segmentsY, v2, n2, uv2 );
getCoordAndUvSphere( x / segmentsX, ( y + 1 ) / segmentsY, v3, n3, uv3 );
getCoordAndUvSphere( ( x + 1 ) / segmentsX, ( y + 1 ) / segmentsY, v4, n4, uv4 );
var idv = vtxCount * 3;
fullVerticesList[ idv ] = v1[ 0 ];
fullVerticesList[ idv + 1 ] = v1[ 1 ];
fullVerticesList[ idv + 2 ] = v1[ 2 ];
fullVerticesList[ idv + 3 ] = v2[ 0 ];
fullVerticesList[ idv + 4 ] = v2[ 1 ];
fullVerticesList[ idv + 5 ] = v2[ 2 ];
fullVerticesList[ idv + 6 ] = v3[ 0 ];
fullVerticesList[ idv + 7 ] = v3[ 1 ];
fullVerticesList[ idv + 8 ] = v3[ 2 ];
fullNormalsList[ idv ] = n1[ 0 ];
fullNormalsList[ idv + 1 ] = n1[ 1 ];
fullNormalsList[ idv + 2 ] = n1[ 2 ];
fullNormalsList[ idv + 3 ] = n2[ 0 ];
fullNormalsList[ idv + 4 ] = n2[ 1 ];
fullNormalsList[ idv + 5 ] = n2[ 2 ];
fullNormalsList[ idv + 6 ] = n3[ 0 ];
fullNormalsList[ idv + 7 ] = n3[ 1 ];
fullNormalsList[ idv + 8 ] = n3[ 2 ];
var idu = vtxCount * 2;
fullUVList[ idu ] = uv1[ 0 ];
fullUVList[ idu + 1 ] = uv1[ 1 ];
fullUVList[ idu + 2 ] = uv2[ 0 ];
fullUVList[ idu + 3 ] = uv2[ 1 ];
fullUVList[ idu + 4 ] = uv3[ 0 ];
fullUVList[ idu + 5 ] = uv3[ 1 ];
vtxCount += 3;
if ( useDrawArrays ) {
idv = vtxCount * 3;
fullVerticesList[ idv ] = v1[ 0 ];
fullVerticesList[ idv + 1 ] = v1[ 1 ];
fullVerticesList[ idv + 2 ] = v1[ 2 ];
fullVerticesList[ idv + 3 ] = v3[ 0 ];
fullVerticesList[ idv + 4 ] = v3[ 1 ];
fullVerticesList[ idv + 5 ] = v3[ 2 ];
fullVerticesList[ idv + 6 ] = v4[ 0 ];
fullVerticesList[ idv + 7 ] = v4[ 1 ];
fullVerticesList[ idv + 8 ] = v4[ 2 ];
fullNormalsList[ idv ] = n1[ 0 ];
fullNormalsList[ idv + 1 ] = n1[ 1 ];
fullNormalsList[ idv + 2 ] = n1[ 2 ];
fullNormalsList[ idv + 3 ] = n3[ 0 ];
fullNormalsList[ idv + 4 ] = n3[ 1 ];
fullNormalsList[ idv + 5 ] = n3[ 2 ];
fullNormalsList[ idv + 6 ] = n4[ 0 ];
fullNormalsList[ idv + 7 ] = n4[ 1 ];
fullNormalsList[ idv + 8 ] = n4[ 2 ];
idu = vtxCount * 2;
fullUVList[ idu ] = uv1[ 0 ];
fullUVList[ idu + 1 ] = uv1[ 1 ];
fullUVList[ idu + 2 ] = uv3[ 0 ];
fullUVList[ idu + 3 ] = uv3[ 1 ];
fullUVList[ idu + 4 ] = uv4[ 0 ];
fullUVList[ idu + 5 ] = uv4[ 1 ];
vtxCount += 3;
} else {
idv = vtxCount * 3;
fullVerticesList[ idv ] = v4[ 0 ];
fullVerticesList[ idv + 1 ] = v4[ 1 ];
fullVerticesList[ idv + 2 ] = v4[ 2 ];
fullNormalsList[ idv ] = n4[ 0 ];
fullNormalsList[ idv + 1 ] = n4[ 1 ];
fullNormalsList[ idv + 2 ] = n4[ 2 ];
idu = vtxCount * 2;
fullUVList[ idu ] = uv4[ 0 ];
fullUVList[ idu + 1 ] = uv4[ 1 ];
var iStart = triCount * 3;
var tristart = vtxCount - 3;
indexes[ iStart ] = tristart;
indexes[ iStart + 1 ] = tristart + 1;
indexes[ iStart + 2 ] = tristart + 2;
indexes[ iStart + 3 ] = tristart;
indexes[ iStart + 4 ] = tristart + 2;
indexes[ iStart + 5 ] = tristart + 3;
triCount += 2;
vtxCount += 1;
}
}
}
var g = new Geometry();
g.getAttributes().Vertex = new BufferArray( 'ARRAY_BUFFER', fullVerticesList, 3 );
g.getAttributes().Normal = new BufferArray( 'ARRAY_BUFFER', fullNormalsList, 3 );
g.getAttributes().TexCoord0 = new BufferArray( 'ARRAY_BUFFER', fullUVList, 2 );
if ( useDrawArrays )
g.getPrimitives().push( new DrawArrays( PrimitiveSet.TRIANGLES, 0, fullVerticesList.length / 3 ) );
else
g.getPrimitives().push( new DrawElements( PrimitiveSet.TRIANGLES, new BufferArray( 'ELEMENT_ARRAY_BUFFER', indexes, 1 ) ) );
return g;
};
var createGridGeometry = function ( cx, cy, cz, wx, wy, wz, hx, hy, hz, res1, res2 ) {
cx = cx !== undefined ? cx : -0.5;
cy = cy !== undefined ? cy : -0.5;
cz = cz !== undefined ? cz : 0.0;
wx = wx !== undefined ? wx : 1.0;
wy = wy !== undefined ? wy : 0.0;
wz = wz !== undefined ? wz : 0.0;
hx = hx !== undefined ? hx : 0.0;
hy = hy !== undefined ? hy : 1.0;
hz = hz !== undefined ? hz : 0.0;
res1 = res1 !== undefined ? res1 : 5;
res2 = res2 !== undefined ? res2 : res1;
res1 += 2;
res2 += 2;
var g = new Geometry();
var vertices = new Float32Array( ( res1 + res2 ) * 2 * 3 );
var i = 0;
var j = 0;
var sx = wx / ( res1 - 1 );
var sy = wy / ( res1 - 1 );
var sz = wz / ( res1 - 1 );
var ux = cx + wx + hx;
var uy = cy + wy + hy;
var uz = cz + wz + hz;
for ( i = 0; i < res1; ++i ) {
j = i * 6;
vertices[ j ] = cx + sx * i;
vertices[ j + 1 ] = cy + sy * i;
vertices[ j + 2 ] = cz + sz * i;
vertices[ j + 3 ] = ux - sx * ( res1 - i - 1 );
vertices[ j + 4 ] = uy - sy * ( res1 - i - 1 );
vertices[ j + 5 ] = uz - sz * ( res1 - i - 1 );
}
sx = hx / ( res2 - 1 );
sy = hy / ( res2 - 1 );
sz = hz / ( res2 - 1 );
for ( i = 0; i < res2; ++i ) {
j = ( res1 + i ) * 6;
vertices[ j ] = cx + sx * i;
vertices[ j + 1 ] = cy + sy * i;
vertices[ j + 2 ] = cz + sz * i;
vertices[ j + 3 ] = ux - sx * ( res2 - i - 1 );
vertices[ j + 4 ] = uy - sy * ( res2 - i - 1 );
vertices[ j + 5 ] = uz - sz * ( res2 - i - 1 );
}
g.getAttributes().Vertex = new BufferArray( BufferArray.ARRAY_BUFFER, vertices, 3 );
var primitive = new DrawArrays( PrimitiveSet.LINES, 0, ( res1 + res2 ) * 2 );
g.getPrimitives().push( primitive );
return g;
};
/*
* debug lines showing bounding box abstraction
* @param col bbox color
*/
var createBoundingBoxGeometry = function ( col ) {
var g = new Geometry();
//unit cube centered on 0
var vertices = new Float32Array( [ -0.5, -0.5, -0.5,
0.5, -0.5, -0.5,
0.5, 0.5, -0.5, -0.5, 0.5, -0.5, -0.5, -0.5, 0.5,
0.5, -0.5, 0.5,
0.5, 0.5, 0.5, -0.5, 0.5, 0.5
] );
g.getAttributes().Vertex = new BufferArray( BufferArray.ARRAY_BUFFER, vertices, 3 );
// use color or red
if ( !col ) col = [ 1.0, 0.0, 0.0, 1.0 ];
var colors = new MACROUTILS.Float32Array( 8 * 4 );
for ( var i = 0; i < 8; i++ ) {
for ( var k = 0; k < 4; k++ ) {
colors[ i * 3 + k ] = col[ k ];
}
}
g.getAttributes().Color = new BufferArray( BufferArray.ARRAY_BUFFER, colors, 4 );
var indexes = new MACROUTILS.Uint16Array(
[
//up
0, 1,
1, 2,
2, 3,
3, 0,
//down
4, 5,
5, 6,
6, 7,
7, 4,
// side
0, 4,
1, 5,
2, 6,
3, 7
] );
g.getPrimitives().push( new DrawElements( PrimitiveSet.LINES, new BufferArray( 'ELEMENT_ARRAY_BUFFER', indexes, 1 ) ) );
return g;
};
module.exports = {
createTexturedBoxGeometry: createTexturedBoxGeometry,
createTexturedQuadGeometry: createTexturedQuadGeometry,
createTexturedSphereGeometry: createTexturedSphere,
createTexturedBox: createTexturedBox,
createTexturedFullScreenFakeQuadGeometry: createTexturedFullScreenFakeQuadGeometry,
createTexturedQuad: createTexturedQuad,
createAxisGeometry: createAxisGeometry,
createTexturedSphere: createTexturedSphere,
createGridGeometry: createGridGeometry,
createBoundingBoxGeometry: createBoundingBoxGeometry
};

Wyświetl plik

@ -1,5 +0,0 @@
'use strict';
module.exports = {
RELATIVE_RF: 0,
ABSOLUTE_RF: 1
};

Wyświetl plik

@ -1,58 +0,0 @@
'use strict';
var Notify = require( 'osg/notify' );
var MACROUTILS = require( 'osg/Utils' );
var Object = require( 'osg/Object' );
var MatrixTransform = require( 'osg/MatrixTransform' );
/**
* AnimationUpdateCallback
* @class AnimationUpdateCallback
*/
var AnimationUpdateCallback = function () {
Object.call( this );
};
// check if the path is animated, it could be elsewhere though
AnimationUpdateCallback.checkPathIsAnimated = function ( path ) {
for ( var i = 0, nbNodes = path.length; i < nbNodes; ++i ) {
var node = path[ i ];
if ( node instanceof MatrixTransform ) {
var ups = node.getUpdateCallbackList();
for ( var j = 0, nbUp = ups.length; j < nbUp; ++j ) {
if ( ups[ j ] instanceof AnimationUpdateCallback )
return true;
}
}
}
return false;
};
/** @lends AnimationUpdateCallback.prototype */
AnimationUpdateCallback.prototype = MACROUTILS.objectInherit( Object.prototype, {
linkChannel: function () {},
linkAnimation: function ( anim ) {
var name = this.getName();
if ( name.length === 0 ) {
Notify.log( 'no name on an update callback, discard' );
return 0;
}
var nbLinks = 0;
var channels = anim.getChannels();
for ( var i = 0, l = channels.length; i < l; i++ ) {
var channel = channels[ i ];
if ( channel.getTargetName() === name ) {
this.linkChannel( channel );
nbLinks++;
}
}
return nbLinks;
}
} );
module.exports = AnimationUpdateCallback;

Wyświetl plik

@ -1,711 +0,0 @@
'use strict';
var Notify = require( 'osg/notify' );
var MACROUTILS = require( 'osg/Utils' );
var BaseObject = require( 'osg/Object' );
var quat = require( 'osg/glMatrix' ).quat;
var vec3 = require( 'osg/glMatrix' ).vec3;
var mat4 = require( 'osg/glMatrix' ).mat4;
var Channel = require( 'osgAnimation/channel' );
var Animation = require( 'osgAnimation/animation' );
var Interpolator = require( 'osgAnimation/interpolator' );
var CollectAnimationUpdateCallbackVisitor = require( 'osgAnimation/CollectAnimationUpdateCallbackVisitor' );
var Target = require( 'osgAnimation/target' );
var UpdateMorph = require( 'osgAnimation/UpdateMorph' );
var Float = {
lerp: function ( a, b, t ) {
return a + ( b - a ) * t;
},
init: function () {
return 0.0;
},
copy: function ( src ) {
return src;
},
create: function () {
return 0.0;
}
};
var TypeToSize = [];
TypeToSize[ Channel.ChannelType.Float ] = 1;
TypeToSize[ Channel.ChannelType.FloatCubicBezier ] = 1;
TypeToSize[ Channel.ChannelType.Vec3 ] = 3;
TypeToSize[ Channel.ChannelType.Vec3CubicBezier ] = 3;
TypeToSize[ Channel.ChannelType.Quat ] = 4;
TypeToSize[ Channel.ChannelType.QuatSlerp ] = 4;
TypeToSize[ Channel.ChannelType.Matrix ] = 16;
var ResultType = [];
ResultType.length = Channel.ChannelType.Count;
ResultType[ Channel.ChannelType.Vec3 ] = vec3;
ResultType[ Channel.ChannelType.Quat ] = quat;
ResultType[ Channel.ChannelType.QuatSlerp ] = quat;
ResultType[ Channel.ChannelType.Float ] = Float;
ResultType[ Channel.ChannelType.FloatCubicBezier ] = Float;
ResultType[ Channel.ChannelType.Vec3CubicBezier ] = vec3;
ResultType[ Channel.ChannelType.Matrix ] = mat4;
/**
* BasicAnimationManager
* @class BasicAnimationManager
*/
var BasicAnimationManager = function () {
BaseObject.call( this );
this._simulationTime = 0.0;
this._pauseTime = 0.0;
this._timeFactor = 1.0;
this._startTime = 0.0;
// contains a map with instance animations
this._instanceAnimations = {};
// animations to start
this._startAnimations = {};
// target contains an array of all target for this manager
// index in the array is used as ID
// see Animation.createTarget
// [
// { id: 0,
// channels: [],
// value: 0.0,
// defaultValue: 0.0,
// type
// },
// ...
// ];
this._targets = [];
this._targetsMap = {};
// target id with active lists
// [
// vec3: [ targetID0, targetID1 ]
// Quat: [ targetID2, targetID3, ... ]
// Float: [ ... ]
// ]
this._targetsByTypes = [];
this._targetsByTypes.length = Channel.ChannelType.Count;
for ( var i = 0, ni = this._targetsByTypes.length; i < ni; i++ ) {
this._targetsByTypes[ i ] = [];
}
// current playing animations
this._activeAnimations = {};
this._activeAnimationList = [];
// current actives channels by types
// [ chanel0, channel1, ... ] // vec3 type
// [ chanel2, channel3, ... ] // Quat type
// [ chanel5, channel6, ... ] // Float type
this._activeChannelsByTypes = [];
this._activeChannelsByTypes.length = Channel.ChannelType.Count;
for ( var j = 0, nj = this._activeChannelsByTypes.length; j < nj; j++ ) {
this._activeChannelsByTypes[ j ] = [];
}
// assign all target/channel in animationCallback
// then they can read it directly
// animation callback to update
this._animationsUpdateCallback = {};
this._animationsUpdateCallbackArray = [];
// queue of animations to register
this._animationsToRegister = [];
//Pause status (true / false)
this._pause = false;
this._dirty = false;
this._seekTime = -1;
};
BasicAnimationManager.prototype = MACROUTILS.objectInherit( BaseObject.prototype, {
init: function ( animations ) {
// reset all
this._simulationTime = 0.0;
this._pauseTime = 0.0;
this._timeFactor = 1.0;
this._startTime = 0.0;
// contains a map with instance animations
this._instanceAnimations = {};
// animations to start
this._startAnimations = {};
this._resetTargets();
this._activeAnimations = {};
this._activeAnimationList.length = 0;
for ( var i = 0, ni = this._activeChannelsByTypes.length; i < ni; i++ )
this._activeChannelsByTypes[ i ].length = 0;
this._animationsUpdateCallback = {};
this._animationsUpdateCallbackArray.length = 0;
this._pause = false;
this._seekTime = -1;
// add animations
this.addAnimations( animations );
},
// push all animations into the queue
addAnimations: function ( animations ) {
var instanceAnimationList = this._addAnimation( animations );
// qeue them to assign target
Array.prototype.push.apply( this._animationsToRegister, instanceAnimationList );
this._dirty = true;
this._registerAnimations();
},
update: function ( node, nv ) {
if ( this._dirty ) {
this._findAnimationUpdateCallback( node );
this._registerTargetFoundInAnimationCallback();
this._registerAnimations();
}
var t = nv.getFrameStamp().getSimulationTime();
if ( this._seekTime !== -1 )
this._pauseTime = -this._seekTime + this._startTime + t;
this._seekTime = -1;
if ( !this._pause ) { // Not in pause
this._simulationTime = this._startTime + ( t - this._pauseTime );
} else {
this._pauseTime = ( t - this._simulationTime + this._startTime );
}
this.updateManager( this._simulationTime * this._timeFactor );
return true;
},
updateManager: function ( t ) {
// adds active animations / channels requested
//
this._processStartAnimation( t );
var l = Channel.ChannelType.Count;
// update all actives channels by type
//
for ( var i = 0; i < l; i++ ) {
var activeChannelType = this._activeChannelsByTypes[ i ];
this._updateChannelsType( t, activeChannelType, Interpolator[ i ] );
}
// update targets
//
for ( var j = 0; j < l; j++ ) {
var targetType = this._targetsByTypes[ j ];
this._updateTargetType( targetType, ResultType[ j ] );
}
// update all animation callback
// expect to have UpdateMatrixTransform
for ( var k = 0, nk = this._animationsUpdateCallbackArray.length; k < nk; k++ ) {
var animCallback = this._animationsUpdateCallbackArray[ k ];
animCallback.computeChannels();
}
// check animation finished
this._removeFinishedAnimation( t );
},
togglePause: function () { //Pause the manager's time
this._pause = !this._pause;
// if we resume an animation we don't want to move forward the animation
if ( !this._pause )
this._seekTime = this._simulationTime;
},
getSimulationTime: function () {
return this._simulationTime;
},
setSimulationTime: function ( t ) {
this._simulationTime = t;
},
setSeekTime: function ( t ) {
this._simulationTime = t;
this._seekTime = t;
},
stopAnimation: function ( name ) {
var activeAnimationList = this._activeAnimationList;
for ( var i = 0, nbAnim = activeAnimationList.length; i < nbAnim; ++i ) {
if ( activeAnimationList[ i ].name === name ) {
this._removeActiveChannels( this._instanceAnimations[ name ] );
this._activeAnimations[ name ] = undefined;
activeAnimationList.splice( i, 1 );
return;
}
}
},
stopAllAnimation: function () {
var activeAnimationList = this._activeAnimationList;
for ( var i = 0, nbAnim = activeAnimationList.length; i < nbAnim; ++i ) {
var name = activeAnimationList[ i ].name;
this._removeActiveChannels( this._instanceAnimations[ name ] );
this._activeAnimations[ name ] = undefined;
}
activeAnimationList.length = 0;
},
setTimeFactor: function ( timeFactor ) {
var tf = timeFactor / this._timeFactor;
this._startTime += ( this._simulationTime - this._simulationTime * tf ) / tf;
this._timeFactor = timeFactor;
if ( this._pause )
this._simulationTime += ( this._simulationTime - this._simulationTime * tf ) / tf;
},
getTimeFactor: function () {
return this._timeFactor;
},
isPlaying: function ( name ) {
if ( this._activeAnimations[ name ] ) return true;
return false;
},
// play animation using object as config
// {
// name: string,
// priority: 0,
// weight: 1.0,
// loop: true / false
// }
playAnimationObject: function ( obj ) {
var anim = this._instanceAnimations[ obj.name ];
if ( !anim ) {
Notify.info( 'no animation ' + obj.name + ' found' );
return;
}
if ( this.isPlaying( obj.name ) ) return;
anim.priority = ( obj.priority === undefined ) ? 0 : obj.priority;
anim.weight = ( obj.weight === undefined ) ? 1.0 : obj.weight;
anim.loop = ( obj.loop === undefined ) ? true : obj.loop;
this._startAnimations[ anim.name ] = anim;
},
// if first argument is an object
// playAnimationObject is called instead
playAnimation: function ( name, loop, priority, weight ) {
var animationObject;
if ( typeof name === 'object' )
animationObject = name;
else {
animationObject = {
name: name,
priority: priority,
weight: weight,
loop: loop
};
}
return this.playAnimationObject( animationObject );
},
getAnimations: function () {
return this._instanceAnimations;
},
_registerAnimations: function () {
if ( !this._targets.length ) return;
for ( var i = 0, ni = this._animationsToRegister.length; i < ni; i++ ) {
var instanceAnimation = this._animationsToRegister[ i ];
this._registerInstanceAnimation( instanceAnimation );
}
this._animationsToRegister.length = 0;
this._dirty = false;
},
// Register animation
//
// Register animation list all target from channel in the animations and associate
// target found in the scenegraph. If no target are registered animation cant be
// registered. In this case animation will be pending and resolved after a visitor
// extract target.
_registerInstanceAnimation: function ( instanceAnimation ) {
var instanceChannels = instanceAnimation.channels;
for ( var i = 0, ni = instanceChannels.length; i < ni; i++ ) {
var instanceChannel = instanceChannels[ i ];
var targetName = instanceChannel.channel.target;
var name = instanceChannel.channel.name;
var uniqueTargetName = targetName + '.' + name;
// disply a warning if animation has a channel but not target found in the
// scene graph. We could probably optimize and removes those channels, but
// it must be a user decision in case the user plugin different scene
// graph together and target would appear later in the scenegraph
if ( !this._targetMap[ uniqueTargetName ] ) {
Notify.warn( 'registerInstanceAnimation did not find targetName (' + uniqueTargetName + ') in the scene graph' );
continue;
}
instanceChannel.targetID = this._targetMap[ uniqueTargetName ].id;
}
return true;
},
_findAnimationUpdateCallback: function ( node ) {
var collector = new CollectAnimationUpdateCallbackVisitor();
node.accept( collector );
this._animationsUpdateCallback = collector.getAnimationUpdateCallbackMap();
},
// assignTargetToAnimationCallback
//
// check all animationUpdateCallback collected and try to
// assign the channel instance registered in the manager. If a
// animationUpdateCallback contains channels not known by the
// manager we skip it. It means that it should be called
// after the animations has been registered into the animation
// manager
_registerTargetFoundInAnimationCallback: function () {
this._resetTargets();
var targetID = 0;
var targetMap = this._targetMap;
var targets = this._targets;
var registerTarget = function ( uniqueTargetName, target, name ) {
if ( !targetMap[ uniqueTargetName ] ) {
targetMap[ uniqueTargetName ] = target;
// assign an id that will be an index into a array
target.id = targetID++;
targets.push( target );
var type = target.type; // split by type
this._targetsByTypes[ type ].push( target );
} else {
// detect differents target instance with same
// unique target name. It's a problem
if ( target !== targetMap[ uniqueTargetName ] )
Notify.warn( 'detected differents target instance with the same name (' + name + ')' );
}
}.bind( this );
var target;
var name;
var uniqueTargetName;
var animationCallbackMap = this._animationsUpdateCallback;
var keys = window.Object.keys( animationCallbackMap );
for ( var i = 0, ni = keys.length; i < ni; i++ ) {
var key = keys[ i ];
var animationCallback = animationCallbackMap[ key ];
// handle UpdateBone and UpdateMatrixTransform but not stateSet
if ( animationCallback.getStackedTransforms && animationCallback.getStackedTransforms().length ) {
this._animationsUpdateCallbackArray.push( animationCallback );
var stackedTransforms = animationCallback.getStackedTransforms();
for ( var j = 0, nj = stackedTransforms.length; j < nj; j++ ) {
var stackedTransform = stackedTransforms[ j ];
target = stackedTransform.getTarget();
name = stackedTransform.getName();
uniqueTargetName = animationCallback.getName() + '.' + name;
registerTarget( uniqueTargetName, target, name );
}
} else if ( animationCallback instanceof UpdateMorph ) {
for ( var t = 0, numTarget = animationCallback.getNumTarget(); t < numTarget; t++ ) {
name = animationCallback.getTargetName( t );
uniqueTargetName = name + '.' + t;
target = animationCallback.getTarget( t );
registerTarget( uniqueTargetName, target, name );
}
}
}
},
_addAnimation: function ( animations ) {
var instanceAnimationList = [];
for ( var i = 0, ni = animations.length; i < ni; i++ ) {
var animation = animations[ i ];
var animationName = animation.name;
if ( this._instanceAnimations[ animationName ] )
continue;
var instanceAnimation = Animation.createInstanceAnimation( animation );
this._instanceAnimations[ animationName ] = instanceAnimation;
instanceAnimationList.push( instanceAnimation );
}
return instanceAnimationList;
},
// add channels from instance animation to the active channels list
_addActiveChannels: function ( t, instanceAnimation ) {
var instanceChannels = instanceAnimation.channels;
for ( var i = 0, ni = instanceChannels.length; i < ni; i++ ) {
var instanceChannel = instanceChannels[ i ];
var type = instanceChannel.channel.type;
instanceChannel.t = t; // reset time
instanceChannel.instanceAnimation = instanceAnimation; // link with parent animation
var targetID = instanceChannel.targetID;
if ( targetID === Target.InvalidTargetID ) continue;
this._activeChannelsByTypes[ type ].push( instanceChannel );
this._targets[ targetID ].channels.push( instanceChannel );
}
},
_removeActiveChannels: function ( instanceAnimation ) {
var instanceChannels = instanceAnimation.channels;
for ( var i = 0, ni = instanceChannels.length; i < ni; i++ ) {
var instanceChannel = instanceChannels[ i ];
var type = instanceChannel.channel.type;
var targetID = instanceChannel.targetID;
if ( targetID === Target.InvalidTargetID ) continue;
// remove channel instance from targetID channel list
var targetChannelsList = this._targets[ targetID ].channels;
var index = targetChannelsList.indexOf( instanceChannel );
targetChannelsList.splice( index, 1 );
// remove channel from active channels
var channelTypeList = this._activeChannelsByTypes[ type ];
var channelIndex = channelTypeList.indexOf( instanceChannel );
channelTypeList.splice( channelIndex, 1 );
}
},
// blend value from each channels for each target
// or copy default value if not updated by an active animation
_updateTargetType: function ( targetList, operatorType ) {
for ( var i = 0, ni = targetList.length; i < ni; i++ ) {
var target = targetList[ i ];
var affectedChannels = target.channels;
var nbChannels = affectedChannels.length;
// note operatorType operations doesn't always operate on arrays (float)
// so we can't simply assume that target.value is an array so we need
// to write "target.value = ..."
if ( nbChannels === 0 ) { // no blending ?
target.value = operatorType.copy( target.defaultValue, target.value );
} else if ( nbChannels === 1 ) {
target.value = operatorType.copy( affectedChannels[ 0 ].value, target.value );
} else {
// blend between multiple channels
target.value = operatorType.init( target.value );
var accumulatedWeight = 0.0;
// it's the same as targetOut = (v0 * w0 + v1 * w1 + ...) / (w0 + w1 + ...)
for ( var j = 0, nj = affectedChannels.length; j < nj; j++ ) {
var achannel = affectedChannels[ j ];
var weight = achannel.weight;
accumulatedWeight += weight;
// avoid divide by zero and useless lerp
if ( accumulatedWeight === 0.0 || weight === 0.0 )
continue;
var ratio = weight / accumulatedWeight;
target.value = operatorType.lerp( target.value, target.value, achannel.value, ratio );
}
}
}
},
_updateChannelsType: function ( t, channels, interpolator ) {
for ( var i = 0, ni = channels.length; i < ni; i++ ) {
var channel = channels[ i ];
var instanceAnimation = channel.instanceAnimation;
var loop = instanceAnimation.loop;
var tLocal = t - channel.t;
// handle loop, careful in case animation is one frame
if ( loop && instanceAnimation.duration > 0.0 ) tLocal = tLocal % instanceAnimation.duration;
interpolator( tLocal + instanceAnimation.firstKeyTime, channel );
}
},
_removeFinishedAnimation: function ( t ) {
var activeAnimationList = this._activeAnimationList;
var i = 0;
while ( i < activeAnimationList.length ) {
var instanceAnimation = activeAnimationList[ i ];
var name = instanceAnimation.name;
if ( t > instanceAnimation.end && instanceAnimation.loop === false ) {
this._removeActiveChannels( instanceAnimation );
this._activeAnimations[ name ] = undefined;
activeAnimationList.splice( i, 1 );
} else {
i++;
}
}
},
_addActiveAnimation: function ( t, cmd ) {
this._activeAnimations[ cmd.name ] = cmd; // set animation in the list of active one
var instanceAnimation = this._instanceAnimations[ cmd.name ];
instanceAnimation.start = t;
instanceAnimation.end = t + instanceAnimation.duration;
this._addActiveChannels( t, instanceAnimation );
// keep track of instance animation active in a list
this._activeAnimationList.push( instanceAnimation );
},
// execute start animations events
// during the updateManager
_processStartAnimation: function ( t ) {
// dont really start animation if we dont have yet targets
if ( !this._targets.length ) return;
var animations = this._startAnimations;
var keys = window.Object.keys( animations );
for ( var i = 0, ni = keys.length; i < ni; i++ ) {
var key = keys[ i ];
var cmd = animations[ key ];
var name = cmd.name;
if ( this.isPlaying( name ) )
continue;
this._addActiveAnimation( t, cmd );
}
if ( keys.length ) this._startAnimations = {};
},
_resetTargets: function () {
this._targetMap = {};
this._targets.length = 0;
for ( var i = 0, ni = this._targetsByTypes.length; i < ni; i++ ) {
this._targetsByTypes[ i ].length = 0;
}
},
resetAllStackedTransforms: function () {
var anims = this._animationsUpdateCallbackArray;
for ( var i = 0, nbAnims = anims.length; i < nbAnims; i++ ) {
var stacked = anims[ i ].getStackedTransforms();
for ( var j = 0, nbStacked = stacked.length; j < nbStacked; j++ ) {
stacked[ j ].resetToDefaultValue();
}
// computeChannels is not mandatory here as the following frame will call
// this function anyway
anims[ i ].computeChannels();
}
},
setAnimationLerpEndStart: function ( anim, lerpDuration ) {
var channels = anim.channels;
if ( anim.originalDuration === undefined )
anim.originalDuration = anim.duration;
anim.duration = anim.originalDuration + lerpDuration;
var firstKey = anim.firstKeyTime;
var animDuration = anim.originalDuration;
for ( var i = 0, nbChannels = channels.length; i < nbChannels; ++i ) {
var ch = channels[ i ].channel;
// compare first and last key and detect if we can loop the channel or not
// it uses an arbitrary epsilon
if ( Math.abs( ch.start - firstKey ) > 0.01 || Math.abs( ch.duration - animDuration ) > 0.01 )
continue;
// update channel end time
if ( ch.originalEnd === undefined )
ch.originalEnd = ch.end;
ch.end = ch.originalEnd + lerpDuration;
// add or remove additonal key and time
var sizeElt = TypeToSize[ ch.type ];
var size = ch.times.buffer.byteLength / 4;
// no lerp between end and start
if ( lerpDuration === 0.0 ) {
ch.keys = new Float32Array( ch.keys.buffer, 0, ( size - 1 ) * sizeElt );
ch.times = new Float32Array( ch.times.buffer, 0, size - 1 );
} else {
// take full size of buffer (with additional keys)
ch.keys = new Float32Array( ch.keys.buffer, 0, size * sizeElt );
// copy first key
var idLast = ( size - 1 ) * sizeElt;
for ( var j = 0; j < sizeElt; ++j )
ch.keys[ idLast + j ] = ch.keys[ j ];
ch.times = new Float32Array( ch.times.buffer, 0, size );
ch.times[ size - 1 ] = ch.times[ size - 2 ] + lerpDuration;
}
}
}
} );
BasicAnimationManager.TypeToSize = TypeToSize;
module.exports = BasicAnimationManager;

Wyświetl plik

@ -1,84 +0,0 @@
'use strict';
var MACROUTILS = require( 'osg/Utils' );
var vec3 = require( 'osg/glMatrix' ).vec3;
var BoundingBox = require( 'osg/BoundingBox' );
var mat4 = require( 'osg/glMatrix' ).mat4;
var MatrixTransform = require( 'osg/MatrixTransform' );
var UpdateBone = require( 'osgAnimation/UpdateBone' );
/**
* Bone
* @class Bone
*/
var Bone = function ( name ) {
if ( name !== undefined )
this.setName( name );
MatrixTransform.call( this );
this._invBindInSkeletonSpace = mat4.create();
this._boneInSkeletonSpace = mat4.create();
this._boneBoundingBox = new BoundingBox();
};
Bone.prototype = MACROUTILS.objectLibraryClass( MACROUTILS.objectInherit( MatrixTransform.prototype, {
// consistent color depending of id
// _rand: function ( id ) {
// var x = Math.sin( id * 45.233 ) * 43758.5453;
// return x - Math.floor( x );
// },
// _generateBoneColor: function ( id ) {
// return vec3.fromValues( this._rand( id + 2.16 ), this._rand( id * 57.27 ), this._rand( id * 0.874 ) );
// },
getOrCreateDebugColor: function () {
// for bone display (debugging, etc)
if ( this._boneColor ) return this._boneColor;
// this._boneColor = this._generateBoneColor( this.getInstanceID() );
this._boneColor = vec3.fromValues( Math.random(), Math.random(), Math.random() );
return this._boneColor;
},
getBoneBoundingBox: function () {
return this._boneBoundingBox;
},
setBoneBoundingBox: function ( bb ) {
this._boneBoundingBox = bb;
},
getMatrixInSkeletonSpace: function () {
return this._boneInSkeletonSpace;
},
getInvBindMatrixInSkeletonSpace: function () {
return this._invBindInSkeletonSpace;
},
setMatrixInSkeletonSpace: function ( m ) {
mat4.copy( this._boneInSkeletonSpace, m );
},
setInvBindMatrixInSkeletonSpace: function ( m ) {
mat4.copy( this._invBindInSkeletonSpace, m );
},
getBoneParent: function () {
var parents = this.getParents();
for ( var i = 0, l = parents.length; i < l; i++ ) {
var typeID = parents[ i ].getTypeID();
if ( typeID === Bone.getTypeID() ) {
return parents[ i ];
}
}
return undefined;
},
setDefaultUpdateCallback: function ( name ) {
this.addUpdateCallback( new UpdateBone( ( name !== undefined ) ? name : this.getName() ) );
}
} ), 'osgAnimation', 'Bone' );
MACROUTILS.setTypeID( Bone );
module.exports = Bone;

Some files were not shown because too many files have changed in this diff Show More