Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/src/packages/assets/threejs/r73/Projector.js
Views: 687
/*1* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.2* License: MS-RSL – see LICENSE.md for details3*/45/**6* @author mrdoob / http://mrdoob.com/7* @author supereggbert / http://www.paulbrunt.co.uk/8* @author julianwa / https://github.com/julianwa9*/1011THREE.RenderableObject = function () {1213this.id = 0;1415this.object = null;16this.z = 0;17this.renderOrder = 0;1819};2021//2223THREE.RenderableFace = function () {2425this.id = 0;2627this.v1 = new THREE.RenderableVertex();28this.v2 = new THREE.RenderableVertex();29this.v3 = new THREE.RenderableVertex();3031this.normalModel = new THREE.Vector3();3233this.vertexNormalsModel = [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ];34this.vertexNormalsLength = 0;3536this.color = new THREE.Color();37this.material = null;38this.uvs = [ new THREE.Vector2(), new THREE.Vector2(), new THREE.Vector2() ];3940this.z = 0;41this.renderOrder = 0;4243};4445//4647THREE.RenderableVertex = function () {4849this.position = new THREE.Vector3();50this.positionWorld = new THREE.Vector3();51this.positionScreen = new THREE.Vector4();5253this.visible = true;5455};5657THREE.RenderableVertex.prototype.copy = function ( vertex ) {5859this.positionWorld.copy( vertex.positionWorld );60this.positionScreen.copy( vertex.positionScreen );6162};6364//6566THREE.RenderableLine = function () {6768this.id = 0;6970this.v1 = new THREE.RenderableVertex();71this.v2 = new THREE.RenderableVertex();7273this.vertexColors = [ new THREE.Color(), new THREE.Color() ];74this.material = null;7576this.z = 0;77this.renderOrder = 0;7879};8081//8283THREE.RenderableSprite = function () {8485this.id = 0;8687this.object = null;8889this.x = 0;90this.y = 0;91this.z = 0;9293this.rotation = 0;94this.scale = new THREE.Vector2();9596this.material = null;97this.renderOrder = 0;9899};100101//102103THREE.Projector = function () {104105var _object, _objectCount, _objectPool = [], _objectPoolLength = 0,106_vertex, _vertexCount, _vertexPool = [], _vertexPoolLength = 0,107_face, _faceCount, _facePool = [], _facePoolLength = 0,108_line, _lineCount, _linePool = [], _linePoolLength = 0,109_sprite, _spriteCount, _spritePool = [], _spritePoolLength = 0,110111_renderData = { objects: [], lights: [], elements: [] },112113_vector3 = new THREE.Vector3(),114_vector4 = new THREE.Vector4(),115116_clipBox = new THREE.Box3( new THREE.Vector3( - 1, - 1, - 1 ), new THREE.Vector3( 1, 1, 1 ) ),117_boundingBox = new THREE.Box3(),118_points3 = new Array( 3 ),119_points4 = new Array( 4 ),120121_viewMatrix = new THREE.Matrix4(),122_viewProjectionMatrix = new THREE.Matrix4(),123124_modelMatrix,125_modelViewProjectionMatrix = new THREE.Matrix4(),126127_normalMatrix = new THREE.Matrix3(),128129_frustum = new THREE.Frustum(),130131_clippedVertex1PositionScreen = new THREE.Vector4(),132_clippedVertex2PositionScreen = new THREE.Vector4();133134//135136this.projectVector = function ( vector, camera ) {137138console.warn( 'THREE.Projector: .projectVector() is now vector.project().' );139vector.project( camera );140141};142143this.unprojectVector = function ( vector, camera ) {144145console.warn( 'THREE.Projector: .unprojectVector() is now vector.unproject().' );146vector.unproject( camera );147148};149150this.pickingRay = function ( vector, camera ) {151152console.error( 'THREE.Projector: .pickingRay() is now raycaster.setFromCamera().' );153154};155156//157158var RenderList = function () {159160var normals = [];161var uvs = [];162163var object = null;164var material = null;165166var normalMatrix = new THREE.Matrix3();167168var setObject = function ( value ) {169170object = value;171material = object.material;172173normalMatrix.getNormalMatrix( object.matrixWorld );174175normals.length = 0;176uvs.length = 0;177178};179180var projectVertex = function ( vertex ) {181182var position = vertex.position;183var positionWorld = vertex.positionWorld;184var positionScreen = vertex.positionScreen;185186positionWorld.copy( position ).applyMatrix4( _modelMatrix );187positionScreen.copy( positionWorld ).applyMatrix4( _viewProjectionMatrix );188189var invW = 1 / positionScreen.w;190191positionScreen.x *= invW;192positionScreen.y *= invW;193positionScreen.z *= invW;194195vertex.visible = positionScreen.x >= - 1 && positionScreen.x <= 1 &&196positionScreen.y >= - 1 && positionScreen.y <= 1 &&197positionScreen.z >= - 1 && positionScreen.z <= 1;198199};200201var pushVertex = function ( x, y, z ) {202203_vertex = getNextVertexInPool();204_vertex.position.set( x, y, z );205206projectVertex( _vertex );207208};209210var pushNormal = function ( x, y, z ) {211212normals.push( x, y, z );213214};215216var pushUv = function ( x, y ) {217218uvs.push( x, y );219220};221222var checkTriangleVisibility = function ( v1, v2, v3 ) {223224if ( v1.visible === true || v2.visible === true || v3.visible === true ) return true;225226_points3[ 0 ] = v1.positionScreen;227_points3[ 1 ] = v2.positionScreen;228_points3[ 2 ] = v3.positionScreen;229230return _clipBox.isIntersectionBox( _boundingBox.setFromPoints( _points3 ) );231232};233234var checkBackfaceCulling = function ( v1, v2, v3 ) {235236return ( ( v3.positionScreen.x - v1.positionScreen.x ) *237( v2.positionScreen.y - v1.positionScreen.y ) -238( v3.positionScreen.y - v1.positionScreen.y ) *239( v2.positionScreen.x - v1.positionScreen.x ) ) < 0;240241};242243var pushLine = function ( a, b ) {244245var v1 = _vertexPool[ a ];246var v2 = _vertexPool[ b ];247248_line = getNextLineInPool();249250_line.id = object.id;251_line.v1.copy( v1 );252_line.v2.copy( v2 );253_line.z = ( v1.positionScreen.z + v2.positionScreen.z ) / 2;254_line.renderOrder = object.renderOrder;255256_line.material = object.material;257258_renderData.elements.push( _line );259260};261262var pushTriangle = function ( a, b, c ) {263264var v1 = _vertexPool[ a ];265var v2 = _vertexPool[ b ];266var v3 = _vertexPool[ c ];267268if ( checkTriangleVisibility( v1, v2, v3 ) === false ) return;269270if ( material.side === THREE.DoubleSide || checkBackfaceCulling( v1, v2, v3 ) === true ) {271272_face = getNextFaceInPool();273274_face.id = object.id;275_face.v1.copy( v1 );276_face.v2.copy( v2 );277_face.v3.copy( v3 );278_face.z = ( v1.positionScreen.z + v2.positionScreen.z + v3.positionScreen.z ) / 3;279_face.renderOrder = object.renderOrder;280281// use first vertex normal as face normal282283_face.normalModel.fromArray( normals, a * 3 );284_face.normalModel.applyMatrix3( normalMatrix ).normalize();285286for ( var i = 0; i < 3; i ++ ) {287288var normal = _face.vertexNormalsModel[ i ];289normal.fromArray( normals, arguments[ i ] * 3 );290normal.applyMatrix3( normalMatrix ).normalize();291292var uv = _face.uvs[ i ];293uv.fromArray( uvs, arguments[ i ] * 2 );294295}296297_face.vertexNormalsLength = 3;298299_face.material = object.material;300301_renderData.elements.push( _face );302303}304305};306307return {308setObject: setObject,309projectVertex: projectVertex,310checkTriangleVisibility: checkTriangleVisibility,311checkBackfaceCulling: checkBackfaceCulling,312pushVertex: pushVertex,313pushNormal: pushNormal,314pushUv: pushUv,315pushLine: pushLine,316pushTriangle: pushTriangle317};318319};320321var renderList = new RenderList();322323this.projectScene = function ( scene, camera, sortObjects, sortElements ) {324325_faceCount = 0;326_lineCount = 0;327_spriteCount = 0;328329_renderData.elements.length = 0;330331if ( scene.autoUpdate === true ) scene.updateMatrixWorld();332if ( camera.parent === null ) camera.updateMatrixWorld();333334_viewMatrix.copy( camera.matrixWorldInverse.getInverse( camera.matrixWorld ) );335_viewProjectionMatrix.multiplyMatrices( camera.projectionMatrix, _viewMatrix );336337_frustum.setFromMatrix( _viewProjectionMatrix );338339//340341_objectCount = 0;342343_renderData.objects.length = 0;344_renderData.lights.length = 0;345346scene.traverseVisible( function ( object ) {347348if ( object instanceof THREE.Light ) {349350_renderData.lights.push( object );351352} else if ( object instanceof THREE.Mesh || object instanceof THREE.Line || object instanceof THREE.Sprite ) {353354var material = object.material;355356if ( material.visible === false ) return;357358if ( object.frustumCulled === false || _frustum.intersectsObject( object ) === true ) {359360_object = getNextObjectInPool();361_object.id = object.id;362_object.object = object;363364_vector3.setFromMatrixPosition( object.matrixWorld );365_vector3.applyProjection( _viewProjectionMatrix );366_object.z = _vector3.z;367_object.renderOrder = object.renderOrder;368369_renderData.objects.push( _object );370371}372373}374375} );376377if ( sortObjects === true ) {378379_renderData.objects.sort( painterSort );380381}382383//384385for ( var o = 0, ol = _renderData.objects.length; o < ol; o ++ ) {386387var object = _renderData.objects[ o ].object;388var geometry = object.geometry;389390renderList.setObject( object );391392_modelMatrix = object.matrixWorld;393394_vertexCount = 0;395396if ( object instanceof THREE.Mesh ) {397398if ( geometry instanceof THREE.BufferGeometry ) {399400var attributes = geometry.attributes;401var groups = geometry.groups;402403if ( attributes.position === undefined ) continue;404405var positions = attributes.position.array;406407for ( var i = 0, l = positions.length; i < l; i += 3 ) {408409renderList.pushVertex( positions[ i ], positions[ i + 1 ], positions[ i + 2 ] );410411}412413if ( attributes.normal !== undefined ) {414415var normals = attributes.normal.array;416417for ( var i = 0, l = normals.length; i < l; i += 3 ) {418419renderList.pushNormal( normals[ i ], normals[ i + 1 ], normals[ i + 2 ] );420421}422423}424425if ( attributes.uv !== undefined ) {426427var uvs = attributes.uv.array;428429for ( var i = 0, l = uvs.length; i < l; i += 2 ) {430431renderList.pushUv( uvs[ i ], uvs[ i + 1 ] );432433}434435}436437if ( geometry.index !== null ) {438439var indices = geometry.index.array;440441if ( groups.length > 0 ) {442443for ( var o = 0; o < groups.length; o ++ ) {444445var group = groups[ o ];446447for ( var i = group.start, l = group.start + group.count; i < l; i += 3 ) {448449renderList.pushTriangle( indices[ i ], indices[ i + 1 ], indices[ i + 2 ] );450451}452453}454455} else {456457for ( var i = 0, l = indices.length; i < l; i += 3 ) {458459renderList.pushTriangle( indices[ i ], indices[ i + 1 ], indices[ i + 2 ] );460461}462463}464465} else {466467for ( var i = 0, l = positions.length / 3; i < l; i += 3 ) {468469renderList.pushTriangle( i, i + 1, i + 2 );470471}472473}474475} else if ( geometry instanceof THREE.Geometry ) {476477var vertices = geometry.vertices;478var faces = geometry.faces;479var faceVertexUvs = geometry.faceVertexUvs[ 0 ];480481_normalMatrix.getNormalMatrix( _modelMatrix );482483var material = object.material;484485var isFaceMaterial = material instanceof THREE.MeshFaceMaterial;486var objectMaterials = isFaceMaterial === true ? object.material : null;487488for ( var v = 0, vl = vertices.length; v < vl; v ++ ) {489490var vertex = vertices[ v ];491492_vector3.copy( vertex );493494if ( material.morphTargets === true ) {495496var morphTargets = geometry.morphTargets;497var morphInfluences = object.morphTargetInfluences;498499for ( var t = 0, tl = morphTargets.length; t < tl; t ++ ) {500501var influence = morphInfluences[ t ];502503if ( influence === 0 ) continue;504505var target = morphTargets[ t ];506var targetVertex = target.vertices[ v ];507508_vector3.x += ( targetVertex.x - vertex.x ) * influence;509_vector3.y += ( targetVertex.y - vertex.y ) * influence;510_vector3.z += ( targetVertex.z - vertex.z ) * influence;511512}513514}515516renderList.pushVertex( _vector3.x, _vector3.y, _vector3.z );517518}519520for ( var f = 0, fl = faces.length; f < fl; f ++ ) {521522var face = faces[ f ];523524material = isFaceMaterial === true525? objectMaterials.materials[ face.materialIndex ]526: object.material;527528if ( material === undefined ) continue;529530var side = material.side;531532var v1 = _vertexPool[ face.a ];533var v2 = _vertexPool[ face.b ];534var v3 = _vertexPool[ face.c ];535536if ( renderList.checkTriangleVisibility( v1, v2, v3 ) === false ) continue;537538var visible = renderList.checkBackfaceCulling( v1, v2, v3 );539540if ( side !== THREE.DoubleSide ) {541542if ( side === THREE.FrontSide && visible === false ) continue;543if ( side === THREE.BackSide && visible === true ) continue;544545}546547_face = getNextFaceInPool();548549_face.id = object.id;550_face.v1.copy( v1 );551_face.v2.copy( v2 );552_face.v3.copy( v3 );553554_face.normalModel.copy( face.normal );555556if ( visible === false && ( side === THREE.BackSide || side === THREE.DoubleSide ) ) {557558_face.normalModel.negate();559560}561562_face.normalModel.applyMatrix3( _normalMatrix ).normalize();563564var faceVertexNormals = face.vertexNormals;565566for ( var n = 0, nl = Math.min( faceVertexNormals.length, 3 ); n < nl; n ++ ) {567568var normalModel = _face.vertexNormalsModel[ n ];569normalModel.copy( faceVertexNormals[ n ] );570571if ( visible === false && ( side === THREE.BackSide || side === THREE.DoubleSide ) ) {572573normalModel.negate();574575}576577normalModel.applyMatrix3( _normalMatrix ).normalize();578579}580581_face.vertexNormalsLength = faceVertexNormals.length;582583var vertexUvs = faceVertexUvs[ f ];584585if ( vertexUvs !== undefined ) {586587for ( var u = 0; u < 3; u ++ ) {588589_face.uvs[ u ].copy( vertexUvs[ u ] );590591}592593}594595_face.color = face.color;596_face.material = material;597598_face.z = ( v1.positionScreen.z + v2.positionScreen.z + v3.positionScreen.z ) / 3;599_face.renderOrder = object.renderOrder;600601_renderData.elements.push( _face );602603}604605}606607} else if ( object instanceof THREE.Line ) {608609if ( geometry instanceof THREE.BufferGeometry ) {610611var attributes = geometry.attributes;612613if ( attributes.position !== undefined ) {614615var positions = attributes.position.array;616617for ( var i = 0, l = positions.length; i < l; i += 3 ) {618619renderList.pushVertex( positions[ i ], positions[ i + 1 ], positions[ i + 2 ] );620621}622623if ( geometry.index !== null ) {624625var indices = geometry.index.array;626627for ( var i = 0, l = indices.length; i < l; i += 2 ) {628629renderList.pushLine( indices[ i ], indices[ i + 1 ] );630631}632633} else {634635var step = object instanceof THREE.LineSegments ? 2 : 1;636637for ( var i = 0, l = ( positions.length / 3 ) - 1; i < l; i += step ) {638639renderList.pushLine( i, i + 1 );640641}642643}644645}646647} else if ( geometry instanceof THREE.Geometry ) {648649_modelViewProjectionMatrix.multiplyMatrices( _viewProjectionMatrix, _modelMatrix );650651var vertices = object.geometry.vertices;652653if ( vertices.length === 0 ) continue;654655v1 = getNextVertexInPool();656v1.positionScreen.copy( vertices[ 0 ] ).applyMatrix4( _modelViewProjectionMatrix );657658var step = object instanceof THREE.LineSegments ? 2 : 1;659660for ( var v = 1, vl = vertices.length; v < vl; v ++ ) {661662v1 = getNextVertexInPool();663v1.positionScreen.copy( vertices[ v ] ).applyMatrix4( _modelViewProjectionMatrix );664665if ( ( v + 1 ) % step > 0 ) continue;666667v2 = _vertexPool[ _vertexCount - 2 ];668669_clippedVertex1PositionScreen.copy( v1.positionScreen );670_clippedVertex2PositionScreen.copy( v2.positionScreen );671672if ( clipLine( _clippedVertex1PositionScreen, _clippedVertex2PositionScreen ) === true ) {673674// Perform the perspective divide675_clippedVertex1PositionScreen.multiplyScalar( 1 / _clippedVertex1PositionScreen.w );676_clippedVertex2PositionScreen.multiplyScalar( 1 / _clippedVertex2PositionScreen.w );677678_line = getNextLineInPool();679680_line.id = object.id;681_line.v1.positionScreen.copy( _clippedVertex1PositionScreen );682_line.v2.positionScreen.copy( _clippedVertex2PositionScreen );683684_line.z = Math.max( _clippedVertex1PositionScreen.z, _clippedVertex2PositionScreen.z );685_line.renderOrder = object.renderOrder;686687_line.material = object.material;688689if ( object.material.vertexColors === THREE.VertexColors ) {690691_line.vertexColors[ 0 ].copy( object.geometry.colors[ v ] );692_line.vertexColors[ 1 ].copy( object.geometry.colors[ v - 1 ] );693694}695696_renderData.elements.push( _line );697698}699700}701702}703704} else if ( object instanceof THREE.Sprite ) {705706_vector4.set( _modelMatrix.elements[ 12 ], _modelMatrix.elements[ 13 ], _modelMatrix.elements[ 14 ], 1 );707_vector4.applyMatrix4( _viewProjectionMatrix );708709var invW = 1 / _vector4.w;710711_vector4.z *= invW;712713if ( _vector4.z >= - 1 && _vector4.z <= 1 ) {714715_sprite = getNextSpriteInPool();716_sprite.id = object.id;717_sprite.x = _vector4.x * invW;718_sprite.y = _vector4.y * invW;719_sprite.z = _vector4.z;720_sprite.renderOrder = object.renderOrder;721_sprite.object = object;722723_sprite.rotation = object.rotation;724725_sprite.scale.x = object.scale.x * Math.abs( _sprite.x - ( _vector4.x + camera.projectionMatrix.elements[ 0 ] ) / ( _vector4.w + camera.projectionMatrix.elements[ 12 ] ) );726_sprite.scale.y = object.scale.y * Math.abs( _sprite.y - ( _vector4.y + camera.projectionMatrix.elements[ 5 ] ) / ( _vector4.w + camera.projectionMatrix.elements[ 13 ] ) );727728_sprite.material = object.material;729730_renderData.elements.push( _sprite );731732}733734}735736}737738if ( sortElements === true ) {739740_renderData.elements.sort( painterSort );741742}743744return _renderData;745746};747748// Pools749750function getNextObjectInPool() {751752if ( _objectCount === _objectPoolLength ) {753754var object = new THREE.RenderableObject();755_objectPool.push( object );756_objectPoolLength ++;757_objectCount ++;758return object;759760}761762return _objectPool[ _objectCount ++ ];763764}765766function getNextVertexInPool() {767768if ( _vertexCount === _vertexPoolLength ) {769770var vertex = new THREE.RenderableVertex();771_vertexPool.push( vertex );772_vertexPoolLength ++;773_vertexCount ++;774return vertex;775776}777778return _vertexPool[ _vertexCount ++ ];779780}781782function getNextFaceInPool() {783784if ( _faceCount === _facePoolLength ) {785786var face = new THREE.RenderableFace();787_facePool.push( face );788_facePoolLength ++;789_faceCount ++;790return face;791792}793794return _facePool[ _faceCount ++ ];795796797}798799function getNextLineInPool() {800801if ( _lineCount === _linePoolLength ) {802803var line = new THREE.RenderableLine();804_linePool.push( line );805_linePoolLength ++;806_lineCount ++;807return line;808809}810811return _linePool[ _lineCount ++ ];812813}814815function getNextSpriteInPool() {816817if ( _spriteCount === _spritePoolLength ) {818819var sprite = new THREE.RenderableSprite();820_spritePool.push( sprite );821_spritePoolLength ++;822_spriteCount ++;823return sprite;824825}826827return _spritePool[ _spriteCount ++ ];828829}830831//832833function painterSort( a, b ) {834835if ( a.renderOrder !== b.renderOrder ) {836837return a.renderOrder - b.renderOrder;838839} else if ( a.z !== b.z ) {840841return b.z - a.z;842843} else if ( a.id !== b.id ) {844845return a.id - b.id;846847} else {848849return 0;850851}852853}854855function clipLine( s1, s2 ) {856857var alpha1 = 0, alpha2 = 1,858859// Calculate the boundary coordinate of each vertex for the near and far clip planes,860// Z = -1 and Z = +1, respectively.861bc1near = s1.z + s1.w,862bc2near = s2.z + s2.w,863bc1far = - s1.z + s1.w,864bc2far = - s2.z + s2.w;865866if ( bc1near >= 0 && bc2near >= 0 && bc1far >= 0 && bc2far >= 0 ) {867868// Both vertices lie entirely within all clip planes.869return true;870871} else if ( ( bc1near < 0 && bc2near < 0 ) || ( bc1far < 0 && bc2far < 0 ) ) {872873// Both vertices lie entirely outside one of the clip planes.874return false;875876} else {877878// The line segment spans at least one clip plane.879880if ( bc1near < 0 ) {881882// v1 lies outside the near plane, v2 inside883alpha1 = Math.max( alpha1, bc1near / ( bc1near - bc2near ) );884885} else if ( bc2near < 0 ) {886887// v2 lies outside the near plane, v1 inside888alpha2 = Math.min( alpha2, bc1near / ( bc1near - bc2near ) );889890}891892if ( bc1far < 0 ) {893894// v1 lies outside the far plane, v2 inside895alpha1 = Math.max( alpha1, bc1far / ( bc1far - bc2far ) );896897} else if ( bc2far < 0 ) {898899// v2 lies outside the far plane, v2 inside900alpha2 = Math.min( alpha2, bc1far / ( bc1far - bc2far ) );901902}903904if ( alpha2 < alpha1 ) {905906// The line segment spans two boundaries, but is outside both of them.907// (This can't happen when we're only clipping against just near/far but good908// to leave the check here for future usage if other clip planes are added.)909return false;910911} else {912913// Update the s1 and s2 vertices to match the clipped line segment.914s1.lerp( s2, alpha1 );915s2.lerp( s1, 1 - alpha2 );916917return true;918919}920921}922923}924925};926927928