JAVASCRIPT 82
Viewpoint.js Guest on 14th April 2021 11:34:47 AM
  1. /** @namespace x3dom.nodeTypes */
  2. /*
  3.  * X3DOM JavaScript Library
  4.  * http://www.x3dom.org
  5.  *
  6.  * (C)2009 Fraunhofer IGD, Darmstadt, Germany
  7.  * Dual licensed under the MIT and GPL
  8.  */
  9.  
  10. /* ### Viewpoint ### */
  11. x3dom.registerNodeType(
  12.     "Viewpoint",
  13.     "Navigation",
  14.     defineClass( x3dom.nodeTypes.X3DViewpointNode,
  15.  
  16.         /**
  17.          * Constructor for Viewpoint
  18.          * @constructs x3dom.nodeTypes.Viewpoint
  19.          * @x3d 3.3
  20.          * @component Navigation
  21.          * @status experimental
  22.          * @extends x3dom.nodeTypes.X3DViewpointNode
  23.          * @param {Object} [ctx=null] - context object, containing initial settings like namespace
  24.          * @classdesc Viewpoint provides a specific location and direction where the user may view the scene.
  25.          * The principalPoint extention allows to set asymmetric frustums.
  26.          */
  27.         function ( ctx )
  28.         {
  29.             x3dom.nodeTypes.Viewpoint.superClass.call( this, ctx );
  30.  
  31.             /**
  32.              * Preferred minimum viewing angle from this viewpoint in radians.
  33.              * Small field of view roughly corresponds to a telephoto lens, large field of view roughly corresponds to a wide-angle lens.
  34.              * Hint: modifying Viewpoint distance to object may be better for zooming.
  35.              * Warning: fieldOfView may not be correct for different window sizes and aspect ratios.
  36.              * Interchange profile hint: this field may be ignored.
  37.              * @var {x3dom.fields.SFFloat} fieldOfView
  38.              * @range [0, pi]
  39.              * @memberof x3dom.nodeTypes.Viewpoint
  40.              * @initvalue 0.785398
  41.              * @field x3d
  42.              * @instance
  43.              */
  44.             this.addField_SFFloat( ctx, "fieldOfView", 0.785398 );
  45.  
  46.             /**
  47.              * The position fields of the Viewpoint node specifies a relative location in the local coordinate system. Position is relative to the coordinate system's origin (0,0,0),
  48.              * @var {x3dom.fields.SFVec3f} position
  49.              * @memberof x3dom.nodeTypes.Viewpoint
  50.              * @initvalue 0,0,10
  51.              * @field x3d
  52.              * @instance
  53.              */
  54.             this.addField_SFVec3f( ctx, "position", 0, 0, 10 );
  55.  
  56.             /**
  57.              * The orientation fields of the Viewpoint node specifies relative orientation to the default orientation.
  58.              * @var {x3dom.fields.SFRotation} orientation
  59.              * @memberof x3dom.nodeTypes.Viewpoint
  60.              * @initvalue 0,0,1,0
  61.              * @field x3d
  62.              * @instance
  63.              */
  64.             this.addField_SFRotation( ctx, "orientation", 0, 0, 1, 0 );
  65.  
  66.             /**
  67.              * The centerOfRotation field specifies a center about which to rotate the user's eyepoint when in EXAMINE mode.
  68.              * @var {x3dom.fields.SFVec3f} centerOfRotation
  69.              * @memberof x3dom.nodeTypes.Viewpoint
  70.              * @initvalue 0,0,0
  71.              * @field x3d
  72.              * @instance
  73.              */
  74.             this.addField_SFVec3f( ctx, "centerOfRotation", 0, 0, 0 );
  75.  
  76.             /**
  77.              * Specifies the near plane.
  78.              * @var {x3dom.fields.SFFloat} zNear
  79.              * @range -1 or [0, inf]
  80.              * @memberof x3dom.nodeTypes.Viewpoint
  81.              * @initvalue -1
  82.              * @field x3dom
  83.              * @instance
  84.              */
  85.             this.addField_SFFloat( ctx, "zNear", -1 ); //0.1);
  86.  
  87.             /**
  88.              * Specifies the far plane.
  89.              * @var {x3dom.fields.SFFloat} zFar
  90.              * @range -1 or [0, inf]
  91.              * @memberof x3dom.nodeTypes.Viewpoint
  92.              * @initvalue -1
  93.              * @field x3dom
  94.              * @instance
  95.              */
  96.             this.addField_SFFloat( ctx, "zFar", -1 );  //100000);
  97.  
  98.             //this._viewMatrix = this._vf.orientation.toMatrix().transpose().
  99.             //    mult(x3dom.fields.SFMatrix4f.translation(this._vf.position.negate()));
  100.             this._viewMatrix = x3dom.fields.SFMatrix4f.translation( this._vf.position ).
  101.                 mult( this._vf.orientation.toMatrix() ).inverse();
  102.  
  103.             this._projMatrix = null;
  104.             this._lastAspect = 1.0;
  105.  
  106.             //use x3d4 fields if provided
  107.             if ( this._vf.nearClippingPlane > -1 )
  108.             {
  109.                 this._vf.zNear = this._vf.nearClippingPlane;
  110.             }
  111.             if ( this._vf.farClippingPlane > -1 )
  112.             {
  113.                 this._vf.zFar = this._vf.farClippingPlane;
  114.             }
  115.  
  116.             // z-ratio: a value around 5000 would be better...
  117.             this._zRatio = 10000;
  118.             this._zNear = this._vf.zNear;
  119.             this._zFar = this._vf.zFar;
  120.  
  121.             // special stuff...
  122.             this._imgPlaneHeightAtDistOne = 2.0 * Math.tan( this._vf.fieldOfView / 2.0 );
  123.         },
  124.         {
  125.             fieldChanged : function ( fieldName )
  126.             {
  127.                 if ( fieldName == "nearClippingPlane" )
  128.                 {
  129.                     this._vf.zNear = this._vf.nearClippingPlane;
  130.                     fieldName = "zNear";
  131.                 }
  132.                 else if ( fieldName == "farClippingPlane" )
  133.                 {
  134.                     this._vf.zFar = this._vf.farClippingPlane;
  135.                     fieldName = "zFar";
  136.                 }
  137.  
  138.                 if ( fieldName == "position" || fieldName == "orientation" )
  139.                 {
  140.                     this.resetView();
  141.                 }
  142.                 else if ( fieldName == "fieldOfView" ||
  143.                     fieldName == "zNear" || fieldName == "zFar" )
  144.                 {
  145.                     this._projMatrix = null;   // only trigger refresh
  146.                     this._zNear = this._vf.zNear;
  147.                     this._zFar = this._vf.zFar;
  148.                     this._imgPlaneHeightAtDistOne = 2.0 * Math.tan( this._vf.fieldOfView / 2.0 );
  149.                 }
  150.                 else if ( fieldName.indexOf( "bind" ) >= 0 )
  151.                 {
  152.                     // FIXME; call parent.fieldChanged();
  153.                     this.bind( this._vf.bind );
  154.                     if ( this._cf.navigationInfo.node )
  155.                     {
  156.                         this._cf.navigationInfo.node.bind( this._vf.bind );
  157.                     }
  158.                 }
  159.                 else if ( fieldName == "viewAll" && this._vf.viewAll )
  160.                 {
  161.                     this._nameSpace.doc._x3dElem.runtime.fitAll();
  162.                 }
  163.             },
  164.  
  165.             setProjectionMatrix : function ( matrix )
  166.             {
  167.                 this._projMatrix = matrix;
  168.             },
  169.  
  170.             getCenterOfRotation : function ()
  171.             {
  172.                 return this._vf.centerOfRotation;
  173.             },
  174.  
  175.             getViewMatrix : function ()
  176.             {
  177.                 return this._viewMatrix;
  178.             },
  179.  
  180.             getFieldOfView : function ()
  181.             {
  182.                 return this._vf.fieldOfView;
  183.             },
  184.  
  185.             resetView : function ()
  186.             {
  187.                 this._viewMatrix = x3dom.fields.SFMatrix4f.translation( this._vf.position ).
  188.                     mult( this._vf.orientation.toMatrix() ).inverse();
  189.  
  190.                 //Reset navigation helpers of the viewarea
  191.                 if ( this._vf.isActive && this._nameSpace && this._nameSpace.doc._viewarea )
  192.                 {
  193.                     this._nameSpace.doc._viewarea.resetNavHelpers();
  194.                 }
  195.             },
  196.  
  197.             getNear : function ()
  198.             {
  199.                 return this._zNear;
  200.             },
  201.  
  202.             getFar : function ()
  203.             {
  204.                 return this._zFar;
  205.             },
  206.  
  207.             getImgPlaneHeightAtDistOne : function ()
  208.             {
  209.                 return this._imgPlaneHeightAtDistOne;
  210.             },
  211.  
  212.             getProjectionMatrix : function ( aspect )
  213.             {
  214.                 var fovy = this._vf.fieldOfView;
  215.                 var zfar = this._vf.zFar;
  216.                 var znear = this._vf.zNear;
  217.  
  218.                 if ( znear <= 0 || zfar <= 0 )
  219.                 {
  220.                     var nearScale = 0.8,
  221.                         farScale = 1.2;
  222.                     var viewarea = this._nameSpace.doc._viewarea;
  223.                     var scene = viewarea._scene;
  224.  
  225.                     // Doesn't work if called e.g. from RenderedTexture with different sub-scene
  226.                     var min = x3dom.fields.SFVec3f.copy( scene._lastMin );
  227.                     var max = x3dom.fields.SFVec3f.copy( scene._lastMax );
  228.  
  229.                     var dia = max.subtract( min );
  230.                     var sRad = dia.length() / 2;
  231.  
  232.                     var mat = viewarea.getViewMatrix().inverse();
  233.                     var vp = mat.e3();
  234.  
  235.                     // account for scales around the viewpoint
  236.                     var translation = new x3dom.fields.SFVec3f( 0, 0, 0 ),
  237.                         scaleFactor = new x3dom.fields.SFVec3f( 1, 1, 1 );
  238.                     var rotation = new x3dom.fields.Quaternion( 0, 0, 1, 0 ),
  239.                         scaleOrientation = new x3dom.fields.Quaternion( 0, 0, 1, 0 );
  240.  
  241.                     // unfortunately, decompose is a rather expensive operation
  242.                     mat.getTransform( translation, rotation, scaleFactor, scaleOrientation );
  243.  
  244.                     var minScal = scaleFactor.x,
  245.                         maxScal = scaleFactor.x;
  246.  
  247.                     if ( maxScal < scaleFactor.y ) {maxScal = scaleFactor.y;}
  248.                     if ( minScal > scaleFactor.y ) {minScal = scaleFactor.y;}
  249.                     if ( maxScal < scaleFactor.z ) {maxScal = scaleFactor.z;}
  250.                     if ( minScal > scaleFactor.z ) {minScal = scaleFactor.z;}
  251.  
  252.                     if ( maxScal > 1 )
  253.                     {nearScale /= maxScal;}
  254.                     else if ( minScal > x3dom.fields.Eps && minScal < 1 )
  255.                     {farScale /= minScal;}
  256.                     // near/far scale adaption done
  257.  
  258.                     var sCenter = min.add( dia.multiply( 0.5 ) );
  259.                     var vDist = ( vp.subtract( sCenter ) ).length();
  260.  
  261.                     if ( sRad )
  262.                     {
  263.                         if ( vDist > sRad )
  264.                         {znear = ( vDist - sRad ) * nearScale;}  // Camera outside scene
  265.                         else
  266.                         {znear = 0;}                           // Camera inside scene
  267.  
  268.                         zfar = ( vDist + sRad ) * farScale;
  269.                     }
  270.                     else
  271.                     {
  272.                         znear = 0.1;
  273.                         zfar = 100000;
  274.                     }
  275.  
  276.                     var zNearLimit = zfar / this._zRatio;
  277.                     znear = Math.max( znear, Math.max( x3dom.fields.Eps, zNearLimit ) );
  278.  
  279.                     if ( zfar > this._vf.zNear && this._vf.zNear > 0 )
  280.                     {znear = this._vf.zNear;}
  281.                     if ( this._vf.zFar > znear )
  282.                     {zfar = this._vf.zFar;}
  283.  
  284.                     if ( zfar <= znear )
  285.                     {zfar = znear + 1;}
  286.                     //x3dom.debug.logInfo("near: " + znear + " -> far:" + zfar);
  287.                 }
  288.  
  289.                 if ( this._projMatrix == null )
  290.                 {
  291.                     this._projMatrix = x3dom.fields.SFMatrix4f.perspective( fovy, aspect, znear, zfar );
  292.                 }
  293.                 else if ( this._zNear != znear || this._zFar != zfar )
  294.                 {
  295.                     var div = znear - zfar;
  296.                     this._projMatrix._22 = ( znear + zfar ) / div;
  297.                     this._projMatrix._23 = 2 * znear * zfar / div;
  298.                 }
  299.                 else if ( this._lastAspect != aspect )
  300.                 {
  301.                     this._projMatrix._00 = ( 1 / Math.tan( fovy / 2 ) ) / aspect;
  302.                     this._lastAspect = aspect;
  303.                 }
  304.  
  305.                 // also needed for being able to ask for near and far
  306.                 this._zNear = znear;
  307.                 this._zFar = zfar;
  308.  
  309.                 return this._projMatrix;
  310.             }
  311.         }
  312.     )
  313. );

Paste-bin is for source code and general debugging text.

Login or Register to edit, delete and keep track of your pastes and more.

Raw Paste

Login or Register to edit or fork this paste. It's free.