kopia lustrzana https://github.com/OpenDroneMap/WebODM
702 wiersze
23 KiB
JavaScript
702 wiersze
23 KiB
JavaScript
'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;
|