Skip to content
Snippets Groups Projects
Select Git revision
  • 9711bab70084cf39a092a68f7c34851cd3321712
  • master default protected
2 results

grid.js

Blame
  • user avatar
    Amira Abdel-Rahman authored
    9711bab7
    History
    grid.js 19.14 KiB
    function threejs(GLOBALS,utils,containerName,container1Name){
        this.camera;
        this.scene;
        this.renderer;
        this.plane;
        this.mouse;
        this.raycaster;
        this.isShiftDown = false;
        this.rollOverMesh;
        this.rollOverMaterial;
        this.cubeGeo;
        this.cubeMaterial;
        this.sphereGeo;
        this.helperMaterial;
        this.helperPosition;
        this.helperColor;
        this.objects = [];
        this.container = document.getElementById( containerName );
        this.container1Name = container1Name;
        this.controls;
        this.voxelSpacing=GLOBALS.voxelSpacing;
        this.occupancyHelper;
        this.voxels=[];
        this.color1=GLOBALS.color1;
        this.color3=GLOBALS.color3;
        this.color4=GLOBALS.color4;
        this.gridSize=GLOBALS.gridSize;
        this.utils=utils;
        this.grid=GLOBALS.grid;
        this.cubicGrid=GLOBALS.gridPresets.Cubic;
        this.occupancy=GLOBALS.occupancy;
        this.selectedNodeID;
        this.menu;
        this.highlight;
    
        //TODO: REMOVE FROM HERE TO GLOBALS
        var color1= "#ffffff"; //white
        var color11= "#ffffff8c"; //white transparent
        var color2= "#020227";  //dark blue
        var color3= "#1c5c61"; //teal
        var color33= "#1c5c618c"; //teal transparent
        var color4= "#fa6e70"; //red/orange
        var color44= "#fa6e708c"; //red/orange
        var color5="#380152"; //purple
        var color6="#696767"; //grey
        
        this.cy =  cytoscape({
            container: document.getElementById(container1Name),
        
            ready: function(){
            },
            
            style: [ 
                
            ],
            autolock: true,
        
            elements: {
                nodes: [
                ],
                edges: [
                    ]
            },
              
        });
    
        this.cxtdefaults = {
            selector: 'core',//'node, edge',
            menuRadius: 50,
            fillColor: color11, // the background colour of the menu
            activeFillColor: color44, // the colour used to indicate the selected command
            // activePadding: 20, // additional size in pixels for the active command
            indicatorSize: 20, // the size in pixels of the pointer to the active command
            // separatorWidth: 3, // the empty spacing in pixels between successive commands
            spotlightPadding: 4, // extra spacing in pixels between the element and the spotlight
            minSpotlightRadius: 15, // the minimum radius in pixels of the spotlight
            maxSpotlightRadius: 10, // the maximum radius in pixels of the spotlight
            // openMenuEvents: 'cxttapstart taphold', // space-separated cytoscape events that will open the menu; only `cxttapstart` and/or `taphold` work here
            itemColor: color6, // the colour of text in the command's content
            // itemTextShadowColor: 'transparent', // the text shadow colour of the command's content
            zIndex: 9999, // the z-index of the ui div
            // atMouse: false // draw menu at mouse position
            commands: [
                {
                    //RUN/PLAY NODE
                    content: '<span class="fa fa-play fa-1x"></span>',
                    select: function(){
                        // console.log( "play");//todo move to globals
                        GLOBALS.runNode(three.selectedNodeID.x,three.selectedNodeID.y,three.selectedNodeID.z);
                    }
                },
    
                {
                    content: '<span class="fa fa-trash fa-1x"></span>',
                    select: function(){
                        GLOBALS.selectNode(three.selectedNodeID.x,three.selectedNodeID.y,three.selectedNodeID.z);
                        GLOBALS.removeNode(three.selectedNodeID.x,three.selectedNodeID.y,three.selectedNodeID.z);
                        
                    },
                    // enabled: true
                },
    
                {
                    // content: 'Select',
                    content: '<span class="fa fa-mouse-pointer fa-1x"></span>',
                    select: function(){
                        // console.log( "Select");//todo move to globals
                        GLOBALS.selectNode(three.selectedNodeID.x,three.selectedNodeID.y,three.selectedNodeID.z);
    
                    }
                }
            ]
        };
        
    
        // this.init();
    }
    
    threejs.prototype.init=function() {
        this.camera = new THREE.PerspectiveCamera( 45, this.getWidth()/ this.getHeight()  , 1, 10000*this.voxelSpacing);
        this.camera.position.set( -this.gridSize*this.voxelSpacing*1.0, this.gridSize*this.voxelSpacing, this.gridSize*this.voxelSpacing/2.0 );
        this.camera.lookAt( this.gridSize/2, 0, this.gridSize/2 );
        this.scene = new THREE.Scene();
        this.scene.background = new THREE.Color( 0xffffff );
    
        this.cubeGeo = new THREE.BoxBufferGeometry( this.voxelSpacing, this.voxelSpacing, this.voxelSpacing );
        
    
        this.sphereGeo = new THREE.SphereGeometry( this.voxelSpacing/2, 32, 32 );
        this.cubeMaterial = new THREE.MeshPhongMaterial( { color: 0x1c5c61 } );
    
        // grid
        var gridHelper = new THREE.GridHelper( (this.gridSize)*this.voxelSpacing, this.gridSize );
        gridHelper.position.x=this.gridSize/2.0*this.voxelSpacing-this.voxelSpacing/2.0;
        gridHelper.position.z=this.gridSize/2.0*this.voxelSpacing-this.voxelSpacing/2.0;
        gridHelper.position.y=-this.voxelSpacing/2.0*this.grid.voxelScaleZ;
    
        gridHelper.scale.x=this.grid.xScale;
        gridHelper.scale.z=this.grid.yScale;
        gridHelper.scale.y=this.grid.zScale;
        this.scene.add( gridHelper );
    
    
    
        // roll-over helpers
        var rollOverGeo = new THREE.BoxBufferGeometry( this.voxelSpacing, this.voxelSpacing, this.voxelSpacing  );
        this.rollOverMaterial = new THREE.MeshBasicMaterial( { color: this.color4, opacity: 0.8, transparent: true } );
        this.rollOverMesh = new THREE.Mesh( rollOverGeo, this.rollOverMaterial );
        this.rollOverMesh.scale.x=this.grid.voxelScaleX;
        this.rollOverMesh.scale.z=this.grid.voxelScaleY;
        this.rollOverMesh.scale.y=this.grid.voxelScaleZ;
        var edges = new THREE.EdgesGeometry( rollOverGeo );
        this.highlight = new THREE.LineSegments( edges, new THREE.LineBasicMaterial( { color: this.color4,linewidth: 4} ) );
        this.highlight.scale.x=this.grid.voxelScaleX*1.1;
        this.highlight.scale.z=this.grid.voxelScaleY*1.1;
        this.highlight.scale.y=this.grid.voxelScaleZ*1.1;
        this.scene.add(this.highlight);
        this.scene.add( this.rollOverMesh );
    
        this.raycaster = new THREE.Raycaster();
        this.mouse = new THREE.Vector2();
        
        
        this.helperPosition = new Float32Array( 1 * 3 );
        var c = new THREE.Color( this.color1 );
        this.helperColor = new Float32Array( 1 * 3 );
        this.helperColor[0]=c.r;
        this.helperColor[1]=c.g;
        this.helperColor[2]=c.b;
        this.helperMaterial = new THREE.PointsMaterial( { size: 5, vertexColors: THREE.VertexColors,color:this.color3 } );
    
        this.buildGrid(this.gridSize);
        this.createHelperMeshes(this.grid,this.gridSize);
        
    
        // var axesHelper = new THREE.AxesHelper( 20 *grid.voxelSpacing);
        // scene.add( axesHelper );
    
        // lights
        var ambientLight = new THREE.AmbientLight( 0x606060 );
        this.scene.add( ambientLight );
        var directionalLight = new THREE.DirectionalLight( 0xffffff );
        directionalLight.position.set( 1, 0.75, 0.5 ).normalize();
        this.scene.add( directionalLight );
        this.renderer = new THREE.WebGLRenderer( { antialias: true } );
        this.renderer.setPixelRatio( window.devicePixelRatio );
        this.renderer.setSize( this.getWidth(), this.getHeight() );
    
        this.renderer = new THREE.WebGLRenderer();
        
        this.container.appendChild( this.renderer.domElement );
        this.controls = new THREE.OrbitControls( this.camera, this.renderer.domElement );
        this.controls.target=new THREE.Vector3( this.gridSize/2*this.voxelSpacing,0 ,this.gridSize/2*this.voxelSpacing );
        this.controls.update();
        
        // document.body.appendChild( renderer.domElement );
        onWindowResizeThree();
        this.container.addEventListener( 'mousemove', onDocumentMouseMoveThree, false );
        this.container.addEventListener( 'mousedown', onDocumentMouseDownThree, false );
        // window.addEventListener( 'keydown', onDocumentKeyDown, false );
        window.addEventListener( 'mouseup', onDocumentKeyUpThree, false );
        //
        window.addEventListener( 'mouseup', onWindowResizeThree, false );
    
        window.addEventListener( 'resize', onWindowResizeThree, false );
    
    
        this.animate();
    };
    
    ////////////////////////
    
    threejs.prototype.animate=function() {
    
        requestAnimationFrame(this.animate.bind(this));
    
        this.render();
    };
    
    threejs.prototype.render=function() {
        this.renderer.render( this.scene, this.camera );
        this.controls.update();
    };
    
    ////////////////////////////
    threejs.prototype.buildGrid=function(gridSize){
        this.occupancyHelper=[];
        for (var i=0;i<gridSize;++i){
            // occupancy.push([]);
            this.occupancyHelper.push([]);
            for (var j=0;j<gridSize;++j){
                // occupancy[i].push([]);
                this.occupancyHelper[i].push([]);
                for (var k=0;k<gridSize;++k){
                    // occupancy[i][j].push(false);
                    this.occupancyHelper[i][j].push(false);
                }
            }
        }
       
    };
    
    threejs.prototype.buildVoxelAt=function( grid,x, y,z){
        
        var voxel = new THREE.Mesh( this.cubeGeo, this.cubeMaterial );
        // var voxel = new THREE.Mesh( sphereGeo, cubeMaterial );
    
        var p_x ,p_y ,p_z ,s_x ,s_y,s_z,r_y;
        [p_x ,p_y ,p_z ,s_x ,s_y,s_z,r_y]=this.utils.getTransforms(grid,x, y,z);
    
        voxel.scale.x=s_x;
        voxel.scale.z=s_z;
        voxel.scale.y=s_y;
    
        voxel.position.x=0;
        voxel.position.y=0;
        voxel.position.z=0;
    
        voxel.rotation.y=r_y;
    
        
        voxel.position.x=p_x;
        voxel.position.y=p_y;
        voxel.position.z=p_z;
        
        voxel.name="["+parseInt(x) +","+parseInt(y) +","+parseInt(z) +"]";
    
        
        this.scene.add(voxel);
        this.voxels.push(voxel);
    };
    
    threejs.prototype.createHelperMeshes=function(grid,gridSize){
        for (var i=0;i<gridSize;++i){
            for (var j=0;j<gridSize;++j){
                this.buildHelperSnap(grid,i,j,0);
            }
        }
    
    };
    
    threejs.prototype.buildHelperSnap=function(grid,x,y,z){
        this.occupancyHelper[x][y][z]=true;
        var geometry = new THREE.PlaneBufferGeometry( grid.voxelSpacing*grid.xScale, grid.voxelSpacing*grid.yScale );
        geometry.rotateX( - Math.PI / 2 );
        this.plane = new THREE.Mesh( geometry, new THREE.MeshBasicMaterial( { visible: false } ) );
        // this.plane = new THREE.Mesh( geometry,this.helperMaterial );
        
    
        [p_x ,p_y ,p_z ,s_x ,s_y,s_z,r_y]=this.utils.getTransforms(grid,x, y,z);
    
        this.plane.scale.x=s_x;
        this.plane.scale.z=s_z;
        // rollOverMesh.scale.y=s_y;
    
        this.plane.position.x=0;
        this.plane.position.y=0;
        this.plane.position.z=0;
    
        this.plane.rotation.y=r_y;
    
        
        this.plane.position.x=p_x;
        this.plane.position.y=p_y;
        this.plane.position.z=p_z;
    
        this.plane.name="p["+parseInt(x) +","+parseInt(y) +","+parseInt(z) +"]";
        
        this.helperPosition[0]=this.plane.position.x;
        this.helperPosition[1]=this.plane.position.y;
        this.helperPosition[2]=this.plane.position.z;
        var helperGeometry = new THREE.BufferGeometry();
        helperGeometry.setAttribute( 'position', new THREE.BufferAttribute( this.helperPosition.slice(), 3 ) );
        helperGeometry.setAttribute( 'color', new THREE.BufferAttribute( this.helperColor.slice(), 3 ) );
        this.helper = new THREE.Points( helperGeometry, this.helperMaterial );
        this.helper.name="s["+parseInt(x) +","+parseInt(y) +","+parseInt(z) +"]";
    
        this.scene.add( this.helper );
        this.scene.add( this.plane );
        this.objects.push( this.plane );
    };
    
    threejs.prototype.buildNeighborHelpers=function(grid, x, y,z){
    
        var list=this.utils.getNeighborsList(grid,x,y,z); 
        
        for(var i=0;i<list.length;i++){
            var x1,y1,z1;
            [x1,y1,z1]=list[i];
            if(this.helperAt(x1,y1,z1)){
                this.buildHelperSnap(grid,x1,y1,z1);
            }
    
        }
    
        //go through all neighbors
            //if occupancy empty
                //add helper meshes??
                //how to rotate plane
    
    };
    
    threejs.prototype.helperAt=function(x,y,z){
        if(x<0||y<0||z<0){
            return false;
        }
        if(x>=this.gridSize||y>=this.gridSize||z>=this.gridSize){
            return false;
        }
        if(this.occupancy[x][y][z]||this.occupancyHelper[x][y][z]){
            return false;
        }
        
        return true;
    
    };
    
    threejs.prototype.updateHelperMeshesAfterRemove=function(grid,x,y,z){
        // this.buildHelperSnap(grid,x,y,z);
        this.occupancy[x][y][z]=false;
        if(z<1){
            this.buildHelperSnap(grid,x,y,z);
        }
        var list=this.utils.getNeighborsList(grid,x,y,z); //TODO ENCLOSE
        
        for(var i=0;i<list.length;i++){
            var x1,y1,z1;
            [x1,y1,z1]=list[i];
            if(!this.helperAt(x1,y1,z1)&&z1>0){
                // buildHelperSnap(grid,x1,y1,z1);
                var name='[' +x1+"," +y1+","+z1+']';
                var object = this.scene.getObjectByName( 'p'+name );
                if(object!==undefined){
                    this.scene.remove( object );
                    this.objects.splice( this.objects.indexOf( object ), 1 );
    
                    object = this.scene.getObjectByName( 's'+name );
                    this.scene.remove( object );
                    this.occupancyHelper[x1][y1][z1]=false;
    
                }
                
    
            }
        }
        list=this.utils.getNeighborsList(this.cubicGrid,x,y,z); 
        for(var i=0;i<list.length;i++){
            var x1,y1,z1;
            [x1,y1,z1]=list[i];
            if(this.occupancy[x1][y1][z1]){
                this.buildNeighborHelpers(grid, x1, y1,z1);
            }
            
        }
        
    };
    
    
    threejs.prototype.changeToGrid=function(newGrid){
    
    };
    
    threejs.prototype.getWidth=function(){
        // return container.style.width;
        return $('#'+this.container1Name).width() ;
    };
    
    threejs.prototype.getHeight=function(){
        // return container.style.height;
        return $('#'+this.container1Name).height() ;
    };
    
    
    //////////////////////////////////////////////////
    function onWindowResizeThree( event ) {
    
        three.camera.aspect = three.getWidth() / three.getHeight();
        three.camera.updateProjectionMatrix();
    
        three.renderer.setSize( three.getWidth(), three.getHeight() );
    }
    
    function onDocumentMouseMoveThree( event ) {
        event.preventDefault();
        three.mouse.set( ( event.clientX / three.getWidth() ) * 2 - 1, - ( event.clientY /three.getHeight() ) * 2 + 1 );
        three.raycaster.setFromCamera(three.mouse, three.camera );
        var intersects = three.raycaster.intersectObjects( three.objects );
        if ( intersects.length > 0 ) {
            var intersect = intersects[ 0 ];
            var obj=utils.getXYZfromName(intersect.object.name);
    
            [p_x ,p_y ,p_z ,s_x ,s_y,s_z,r_y]=utils.getTransforms(three.grid,obj.x, obj.y,obj.z);
    
            
            // rollOverMesh.scale.x=s_x;
            // rollOverMesh.scale.z=s_z;
            // rollOverMesh.scale.y=s_y;
            three.rollOverMesh.name="r["+parseInt(obj.x) +","+parseInt(obj.y) +","+parseInt(obj.z) +"]"
            three.rollOverMesh.position.x=0;
            three.rollOverMesh.position.y=0;
            three.rollOverMesh.position.z=0;
    
            three.rollOverMesh.rotation.y=r_y;
    
            
            three.rollOverMesh.position.x=p_x;
            three.rollOverMesh.position.y=p_y;
            three.rollOverMesh.position.z=p_z;
    
            
            // rollOverMesh.position.copy( intersect.object.position ).add(temp );
            
        }
        three.render();
    }
    
    function onDocumentMouseDownThree( event ) {
    
        event.preventDefault();
        three.mouse.set( ( event.clientX / three.getWidth() ) * 2 - 1, - ( event.clientY / three.getHeight() ) * 2 + 1 );
        three.raycaster.setFromCamera( three.mouse, three.camera );
        var intersects = three.raycaster.intersectObjects( three.objects );
        var intersects1 = three.raycaster.intersectObjects( three.voxels );
        
        if ( intersects.length > 0  ||intersects1.length>0){
            if(event.which==1 && intersects.length > 0) { //left click
                var intersect = intersects[ 0 ];
                var obj=utils.getXYZfromName(intersect.object.name);
                obj=utils.getXYZfromName(three.rollOverMesh.name);
                GLOBALS.addNode (obj.x, obj.y,obj.z);
            }
            if ( intersects1.length > 0 && event.which==3){//right click
                    var intersect = intersects1[ 0 ];
                    
                    var obj=utils.getXYZfromName(intersect.object.name);
                    three.selectedNodeID=obj;
                    three.menu=three.cy.cxtmenu( three.cxtdefaults );
    
    
                    [p_x ,p_y ,p_z ,s_x ,s_y,s_z,r_y]=utils.getTransforms(three.grid,obj.x, obj.y,obj.z);
            
                    
                    three.highlight.name="h["+parseInt(obj.x) +","+parseInt(obj.y) +","+parseInt(obj.z) +"]";
                    three.highlight.position.x=0;
                    three.highlight.position.y=0;
                    three.highlight.position.z=0;
            
                    three.highlight.rotation.y=r_y;
            
                    
                    three.highlight.position.x=p_x;
                    three.highlight.position.y=p_y;
                    three.highlight.position.z=p_z;
                    
                    
                    
            }
            three.render();
        }
        
    }
    
    function onDocumentKeyUpThree(event){
        if(event.which==3){
    
            if(three.menu!==undefined){
                three.menu.destroy();
            }
        }
    
    }
    
    document.addEventListener('removeNode', function (e) { 
        var name='[' +e.detail.x +"," +e.detail.y+","+e.detail.z+']';
        var object = three.scene.getObjectByName( name );
        three.scene.remove( object );
        three.voxels.splice( three.voxels.indexOf( object ), 1 );
        three.updateHelperMeshesAfterRemove(three.grid,e.detail.x,e.detail.y,e.detail.z);   
        if(three.highlight.name=== 'h'+name) {
            three.highlight.name="h["+0+","+0 +","+0 +"]";
            three.highlight.position.x=0;
            three.highlight.position.y=0;
            three.highlight.position.z=0;
    
        }
        
    }, false);
    
    document.addEventListener('addNode', function (e) { 
        three.buildVoxelAt( three.grid, e.detail.x, e.detail.y,e.detail.z);
    
        //deleteHelper Meshes
        var name='[' +e.detail.x +"," +e.detail.y+","+e.detail.z+']';
        var object = three.scene.getObjectByName( 'p'+name );
        three.scene.remove( object );
        three.objects.splice( three.objects.indexOf( object ), 1 );
    
        object = three.scene.getObjectByName( 's'+name );
        three.scene.remove( object );
        three.occupancyHelper[e.detail.x][e.detail.y][e.detail.z]=false;
    
        three.buildNeighborHelpers(three.grid, e.detail.x, e.detail.y,e.detail.z);
        
    }, false);
    
    document.addEventListener('selectNode', function (e) { 
         var obj=e.detail;
         [p_x ,p_y ,p_z ,s_x ,s_y,s_z,r_y]=utils.getTransforms(three.grid,obj.x, obj.y,obj.z);
            
                    
        three.highlight.name="h["+parseInt(obj.x) +","+parseInt(obj.y) +","+parseInt(obj.z) +"]";
        three.highlight.position.x=0;
        three.highlight.position.y=0;
        three.highlight.position.z=0;
    
        three.highlight.rotation.y=r_y;
    
        
        three.highlight.position.x=p_x;
        three.highlight.position.y=p_y;
        three.highlight.position.z=p_z;
    
        
    }, false);
    
    
    /////////////////////