OpenDroneMap-WebODM/app/static/app/js/vendor/osgjs/osg/RenderLeaf.js

214 wiersze
7.5 KiB
JavaScript

'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;