To avoid passing of object through ground


I’m trying to drag this cube to the ground but i do not want it to pass through the ground.how can i avoid it.
I tried making changes in DragControls.js but was not able to select and work on that object again

can anyone please suggest something
i have also attached the entire filenew.zip (565.0 KB)

//scripts
// global variables
var scene;
var renderer;
var boxBox;

var containerBox;
// used for drag and drop
var chairBox, sofaBox ,goodsBox;
    var pen, c_mesh, interactiveObj = [], rotateObj = [], groundRaycastObj = [];
var selectedObject;
var offset = new THREE.Vector3();
var objects = [];
var container, controls, clock, selection;
var obj;
var init, initializeLesson;
var canvas, scene, renderer, camera;
var GoodsBoxHelper;
var wallbackBox,wallrightBox,wallleftBox;
var raycaster; // A THREE.Raycaster for user mouse input.
var leftovergoods,totalnooggoods;
var ground; // A square base on which the cylinders stand.
var cylinder; // A cylinder that will be cloned to make the visible cylinders.
var warehousez,warehousey,warehousex;
var world, animate; // An Object3D that contains all the mesh objects in the scene.
// Rotation of the scene is done by rotating the world about its
// y-axis.  (I couldn't rotate the camera about the scene since
// the Raycaster wouldn't work with a camera that was a child
// of a rotated object.)
raycaster = new THREE.Raycaster();
var mouseAction; // currently selected mouse action
var dragItem; // the cylinder that is being dragged, during a drag operation
var intersects; //the objects intersected
var positionx = 0;
var positiony = 0;
var positionz = 0;
var plane; // An invisible object that is used as the target for raycasting while
// dragging a cylinder.  I use it to find the new location of the
// cylinder.  I tried using the ground for this purpose, but to get
// the motion right, I needed a target that is at the same height
// above the ground as the point where the user clicked the cylinder.
  var container, renderer;
    var camera, scene, projector, mouseVector, controls;
    var mouseX, mouseY, draggable;
    var pen, c_mesh, interactiveObj = [], rotateObj = [], groundRaycastObj = [];
    var wallWidth = 1200;
    var wallHeight = 400;
    var chair_model, sofa_model;
    var chair_selected = false;
    var sofa_selected = false;

    var raycaster;
    var mouse = new THREE.Vector2(), INTERSECTED;
    var radius = 100, theta = 0;
    var oldIntersectPoint = new THREE.Vector3();
    var newIntersectPoint = new THREE.Vector3(); 
    var intersectOffset   = new THREE.Vector3();
    var chairOldPosition = new THREE.Vector3();
    var sofaOldPosition = new THREE.Vector3();

    var chair_rotate = false;
    var walls;
    var mesh_box;
    var wallright, wallleft, wallback, wallfront, ceiling, ground;
    var strDownloadMime = "Wood_Bam.jpg";
    var chairBox, sofaBox;
    var wallrightBox, wallleftBox, wallbackBox, wallfrontBox;

var p;
/****/
/**
 * Set our global variables.
 */
var camera, // We need a camera.
    scene, // The camera has to see something.
    renderer, // Render our graphics.
    controls, // Our Orbit Controller for camera magic.
    container, // Our HTML container for the program.
    rotationPoint;  // The point in which our camera will rotate around.

var characterSize = 50;
var outlineSize = characterSize * 0.05;

// Track all objects and collisions.
var objects = [];
var collisions = [];

// Set mouse and raycaster.
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();

// Store movements.
var movements = [];
var playerSpeed = 5;

// Watch for double clicks.
var clickTimer = null;

// The movement destination indicator.
var indicatorTop;
var indicatorBottom;

var p =0;


function initializeLesson() {

	init();

}




function init() {

	    // Prepare container
	container = document.createElement( 'div' );
	document.body.appendChild( container );
	scene = new THREE.Scene();
	camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
	camera.position.z = 100;
	camera.position.y = 100;
	camera.position.x = 50;// added to get a better control on screen
	camera.lookAt( new THREE.Vector3( 0, 0, 0 ) );


	renderer = new THREE.WebGLRenderer( { antialias: true } );
	renderer.setClearColor( "#e5e5e5" ); //setting a grey color on the screen
	renderer.setPixelRatio( window.devicePixelRatio );
	renderer.setSize( window.innerWidth, window.innerHeight ); //adjusting the black screen on the browser
	document.body.appendChild( renderer.domElement );
	window.addEventListener( 'resize', () => {

		renderer.setSize( window.innerWidth, window.innerHeight );
		camera.aspect = window.innerWidth / window.innerHeight;
		camera.updateProjectionMatrix(); //today edited

	} );

  // Create a rotation point.
  rotationPoint = new THREE.Object3D();
  rotationPoint.position.set( 0, 0, 0 );
  scene.add( rotationPoint );

 walls = new THREE.Object3D();
   var groundGeo_2 = new THREE.PlaneGeometry(500, 500); 
  var floorTexture = new THREE.MeshBasicMaterial({color : 0xff2255});

	container.appendChild( renderer.domElement );

	var groundlength = 2000;
	var groundheight = 0;
	var groundwidth = 1000;
	var geometry = new THREE.BoxGeometry( groundlength, groundheight, groundwidth );
//	var material = new THREE.MeshBasicMaterial( { map: new THREE.TextureLoader().load( 'textures/6.jpg' ) } ); //B5651D
  var material = new THREE.MeshBasicMaterial( { color:"brown" } ); //B5651D

	var ground = new THREE.Mesh( geometry, material );
 ground.position.x = groundlength / 2;
	ground.position.z = groundwidth / 2;
	ground.position.y = - 0.5;
	 walls.add(ground);
     groundBox = new THREE.BoundingBoxHelper( ground );
        groundBox.update(ground);
        scene.add(walls);
    groundRaycastObj.push(walls);
 
	var axessize = 2 * groundlength;
	var axes = new THREE.AxesHelper( 1000 ); //to view x y z axis
	scene.add( axes );


	controls = new THREE.OrbitControls( camera, renderer.domElement );
	controls.minDistance = 1;
	controls.maxDistance = 1000;
	controls.target = new THREE.Vector3( 0, 0, 0 );
	clock = new THREE.Clock();


	//plane = new THREE.Mesh(new THREE.BoxGeometry(groundlength, groundheight, groundwidth), new THREE.MeshBasicMaterial({color: 0xffffff}));
	//  plane.visible = false;
	var plane = new THREE.Mesh( new THREE.BoxGeometry( groundlength, 1, groundwidth ), new THREE.MeshBasicMaterial( {
		color: 0xffff00,
		opacity: 0.50,
		transparent: true
		,visible: false
	} ) );
	plane.position.x = groundlength / 2;
	plane.position.z = groundwidth / 2;
	plane.position.y = 0;
	scene.add( plane );

	

	THREEx.WindowResize( renderer, camera );
	//createnewwarehouse();	
  createcontainer(120,100,120,100,100,100);
    // createcontainer(250,100,120,100,100,100);
//  createcontainer(100,100,100);
//	creategoods();
	
	  /*var chairMaterial = new THREE.MeshBasicMaterial({ color:'red'});

          var geometry =  new THREE.BoxGeometry(12, 12, 12);
            chair_model = new THREE.Mesh(geometry, chairMaterial);
          
            chair_model.position.set(100,20, 100);
         //   chair_model.rotation.set(0, 0, 0);
          //  chair_model.scale.set(3, 3, 3);
            chair_model.name = 'chair_model';
            interactiveObj.push(chair_model);
            scene.add(chair_model);

        chairBox = new THREE.BoundingBoxHelper( chair_model );

        // comment next line out if you don't want to see the wireframe chair boxHelper
            scene.add(chairBox);
            objects.push(chairBox);*/
  //document.addEventListener('mousewheel', onDocumentMouseWheel, false);
        //Firefox
       // document.addEventListener('DOMMouseScroll', onDocumentMouseWheel, false);
     /*   document.addEventListener('mousemove', onDocumentMouseMove, false);
        document.addEventListener('mousedown', onDocumentMouseDown, false);
        document.addEventListener('mouseup', onDocumentMouseUp, false);
        window.addEventListener('resize', onWindowResize, false);*/


    function onWindowResize() {
        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();
        renderer.setSize(window.innerWidth, window.innerHeight);

        //controls.handleResize();

    }

    function onDocumentMouseDown(event) {
        draggable = true;
        event.preventDefault();

    var testIntersects;
        testIntersects = raycaster.intersectObjects(groundRaycastObj, true);
        if (testIntersects.length > 0)
            oldIntersectPoint.copy(testIntersects[0].point);

        // find intersections
        raycaster.setFromCamera(mouse, camera);
        var intersects = raycaster.intersectObjects(interactiveObj, true);
        if (intersects.length > 0) {
            controls.enabled=false;

            if (intersects[0].object.name == 'chair_model') {
                container.style.cursor = 'pointer';
                chair_selected = true;
            //oldIntersectPoint.copy(chair_model.position);
        chairBox.material.color.set('black');
            } 
            else {
                chair_selected = false;
               
            }
            draggable = false;
        }

    }
    function onDocumentMouseUp(event) {
     // draggable = false;
        chair_selected = false;
      container.style.cursor = 'auto';
        controls.enabled=true;

    oldIntersectPoint.set(0,0,0);
    newIntersectPoint.set(0,0,0);
        intersectOffset.set(0,0,0);

    chairBox.material.color.set('yellow');
   
    }


    function onDocumentMouseMove(event) {

        mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
        mouse.y = -( event.clientY / window.innerHeight ) * 2 + 1;

        var deltaX = event.clientX - mouseX;
        var deltaY = event.clientY - mouseY;

        var testIntersects;

        raycaster.setFromCamera(mouse, camera);
        var intersects = raycaster.intersectObjects(interactiveObj, true);

        if (intersects.length > 0) {
            container.style.cursor = 'pointer';
            //addRotationLine(intersects[0].object);

        } else {
            container.style.cursor = 'auto';
        }

        if (draggable) {

        } else if (chair_selected == true) {

                testIntersects = raycaster.intersectObjects(groundRaycastObj, true);
                if (testIntersects.length > 0) {

            var okToMove = true;

            chairOldPosition.copy(chair_model.position);

            newIntersectPoint.copy(testIntersects[0].point);

            intersectOffset.copy(newIntersectPoint);
                intersectOffset.sub(oldIntersectPoint);
            //uncomment below if you want more precision mouse movements of objects
            //intersectOffset.multiplyScalar(0.1);
            // store old intersect point for next frame
            oldIntersectPoint.copy(newIntersectPoint);

            chair_model.position.add(intersectOffset);
            chair_model.updateMatrixWorld(true);
            //chairBox.updateMatrixWorld(true);
            chairBox.update(chair_model);

            // default
            chairBox.material.color.set('white');   

            if( chairBox.box.intersectsBox(groundBox.box) ) {
                okToMove = false;
                chairBox.material.color.set('green');
            }

            // if NOT ok to move and chair is hitting something,
            if ( !okToMove ) {
                // put chair back where it was
                chair_model.position.copy(chairOldPosition);
            }


                }
                // clamp chair position to the ground
             //  chair_model.position.y >= 0.5;

        } 
        
        mouseX = event.clientX;
        mouseY = event.clientY;
        //render(); // no need to render
    }


//var dragControls = new DragDropControls( objects, camera, renderer.domElement);
	var dragControls = new THREE.DragControls( objects, camera,renderer.domElement,groundRaycastObj,interactiveObj);

	dragControls.addEventListener( 'dragstart', function ( event ) {

		controls.enabled = false;
		} );

	dragControls.addEventListener( 'dragend', function ( event ) {


		controls.enabled = true;
	

	} );
	animate();

}

function createcontainer( posX, posY, posZ ) {
 // Create the trunk.
  var geometry = new THREE.BoxGeometry( 100, 100, 100 );
 //var material = new THREE.MeshBasicMaterial( { map: new THREE.TextureLoader().load('textures/5.jpg')});
var material = new THREE.MeshBasicMaterial( { color:"green"});

	var trunk = new THREE.Mesh( geometry, material );

   var outline_geo = new THREE.BoxGeometry( 100 + outlineSize, 100 + outlineSize, 100 + outlineSize );
    var outline_mat = new THREE.MeshBasicMaterial({
     map: new THREE.TextureLoader().load('textures/5.jpg') ,side: THREE.DoubleSide
  });
  var outlineTrunk = new THREE.Mesh( outline_geo, outline_mat );
  
  outlineTrunk = new THREE.BoxHelper( trunk);
	 
    trunk.add(outlineTrunk);
    scene.add( trunk );
    objects.push( trunk );
    trunk.name = 'container' + p;
     trunk.position.set(posX, posY , posZ);
     p = p +1;
     console.log(' trunk.name' +  trunk.name);
}

    






function openC(evt, cityName) {
     var i, tabcontent, tablinks;

  // Get elements class="tabcontent" and hide
      tabcontent = document.getElementsByClassName("tabcontent");
      for (i = 0; i < tabcontent.length; i++) {
        tabcontent[i].style.display = "none";
      }

 

      // Get all elements with class="tablinks" and remove the class "active"
      tablinks = document.getElementsByClassName("tablinks");
      for (i = 0; i < tablinks.length; i++) {
        tablinks[i].className = tablinks[i].className.replace(" active", "");
      }

 
      // Show current and add an "active" class to the button that opened the tab
      document.getElementById(cityName).style.display = "block";
      evt.currentTarget.className += " active";
    }


/*function animate() {

	requestAnimationFrame( animate );
	renderer.render( scene, camera );

}*/
function animate() {

        requestAnimationFrame(animate);

        //chair_model.rotation.y += 0.02;

        //chairBox.update(chair_model);
   
    //wallrightBox.update(wallright);
    //wallleftBox.update(wallleft);
    //wallfrontBox.update(wallfront);
    //wallbackBox.update(wallback);



       // controls.update();

        // Render the frame
        //Don't render twice, it will slow down your animation!
        //render();
        renderer.render(scene, camera);

    }


/***** scripts.js**************/




/* Dragcontrols.js*/
/**
 * @author zz85 / https://github.com/zz85
 * @author mrdoob / http://mrdoob.com
 * Running this will allow you to drag three.js objects around the screen.
 */

THREE.DragControls = function ( _objects, _camera, _domElement ) {

	var _plane = new THREE.Plane();
	var _raycaster = new THREE.Raycaster();

	var _mouse = new THREE.Vector2();
	var _offset = new THREE.Vector3();
	var _intersection = new THREE.Vector3();
	var _worldPosition = new THREE.Vector3();
	var _inverseMatrix = new THREE.Matrix4();

	var _selected = null, _hovered = null;

	//

	var scope = this;

	function activate() {

		_domElement.addEventListener( 'mousemove', onDocumentMouseMove, false );
		_domElement.addEventListener( 'mousedown', onDocumentMouseDown, false );
		_domElement.addEventListener( 'mouseup', onDocumentMouseCancel, false );
		_domElement.addEventListener( 'mouseleave', onDocumentMouseCancel, false );
		_domElement.addEventListener( 'touchmove', onDocumentTouchMove, false );
		_domElement.addEventListener( 'touchstart', onDocumentTouchStart, false );
		_domElement.addEventListener( 'touchend', onDocumentTouchEnd, false );

	}

	function deactivate() {

		_domElement.removeEventListener( 'mousemove', onDocumentMouseMove, false );
		_domElement.removeEventListener( 'mousedown', onDocumentMouseDown, false );
		_domElement.removeEventListener( 'mouseup', onDocumentMouseCancel, false );
		_domElement.removeEventListener( 'mouseleave', onDocumentMouseCancel, false );
		_domElement.removeEventListener( 'touchmove', onDocumentTouchMove, false );
		_domElement.removeEventListener( 'touchstart', onDocumentTouchStart, false );
		_domElement.removeEventListener( 'touchend', onDocumentTouchEnd, false );

	}

	function dispose() {

		deactivate();

	}

	function onDocumentMouseMove( event ) {

		event.preventDefault();

		var rect = _domElement.getBoundingClientRect();

		_mouse.x = ( ( event.clientX - rect.left ) / rect.width ) * 2 - 1;
		_mouse.y = - ( ( event.clientY - rect.top ) / rect.height ) * 2 + 1;

		_raycaster.setFromCamera( _mouse, _camera );

		if ( _selected && scope.enabled ) {

			if ( _raycaster.ray.intersectPlane( _plane, _intersection ) ) {
				console.log('_selectedpostionyvalue' + _selected.position.y);

  if(_selected.position.y > 50){

  	_selected.position.copy( _intersection.sub( _offset ).applyMatrix4( _inverseMatrix ) );

  }

	
}

			scope.dispatchEvent( { type: 'drag', object: _selected } );

			return;

		}

		_raycaster.setFromCamera( _mouse, _camera );

		var intersects = _raycaster.intersectObjects( _objects, true );

		if ( intersects.length > 0 ) {

			var object = intersects[ 0 ].object;

			_plane.setFromNormalAndCoplanarPoint( _camera.getWorldDirection( _plane.normal ), _worldPosition.setFromMatrixPosition( object.matrixWorld ) );

			if ( _hovered !== object ) {

				scope.dispatchEvent( { type: 'hoveron', object: object } );

				_domElement.style.cursor = 'pointer';
				_hovered = object;

			}

		} else {

			if ( _hovered !== null ) {

				scope.dispatchEvent( { type: 'hoveroff', object: _hovered } );

				_domElement.style.cursor = 'auto';
				_hovered = null;

			}

		}

	}

	function onDocumentMouseDown( event ) {

		event.preventDefault();

		_raycaster.setFromCamera( _mouse, _camera );

		var intersects = _raycaster.intersectObjects( _objects, true );

		if ( intersects.length > 0 ) {

			_selected = intersects[ 0 ].object;

			console.log('_selected' + _selected.name);
			console.log('_selectedpostiony' + _selected.position.y);

			if ( _raycaster.ray.intersectPlane( _plane, _intersection ) ) {


 

  	_inverseMatrix.getInverse( _selected.parent.matrixWorld );
  	 if(_selected.position.y > 50){
				_offset.copy( _intersection ).sub( _worldPosition.setFromMatrixPosition( _selected.matrixWorld ) );



  }

 
	
}

			_domElement.style.cursor = 'move';

			scope.dispatchEvent( { type: 'dragstart', object: _selected } );	

		}


	}

	function onDocumentMouseCancel( event ) {

		event.preventDefault();

		if ( _selected ) {

			scope.dispatchEvent( { type: 'dragend', object: _selected } );

			_selected = null;

		}



		_domElement.style.cursor = _hovered ? 'pointer' : 'auto';

	}

	function onDocumentTouchMove( event ) {

		event.preventDefault();
		event = event.changedTouches[ 0 ];

		var rect = _domElement.getBoundingClientRect();

		_mouse.x = ( ( event.clientX - rect.left ) / rect.width ) * 2 - 1;
		_mouse.y = - ( ( event.clientY - rect.top ) / rect.height ) * 2 + 1;

		_raycaster.setFromCamera( _mouse, _camera );

		if ( _selected && scope.enabled ) {
			//console.log('_selected' + _selected.name);
			
			if ( _raycaster.ray.intersectPlane( _plane, _intersection ) ) {
	_selected.position.copy( _intersection.sub( _offset ).applyMatrix4( _inverseMatrix ) );

			}

			scope.dispatchEvent( { type: 'drag', object: _selected } );

			return;

		}

	}

	function onDocumentTouchStart( event ) {

		event.preventDefault();
		event = event.changedTouches[ 0 ];

		var rect = _domElement.getBoundingClientRect();

		_mouse.x = ( ( event.clientX - rect.left ) / rect.width ) * 2 - 1;
		_mouse.y = - ( ( event.clientY - rect.top ) / rect.height ) * 2 + 1;

		_raycaster.setFromCamera( _mouse, _camera );

		var intersects = _raycaster.intersectObjects( _objects, true );

		if ( intersects.length > 0 ) {

			_selected = intersects[ 0 ].object;

			_plane.setFromNormalAndCoplanarPoint( _camera.getWorldDirection( _plane.normal ), _worldPosition.setFromMatrixPosition( _selected.matrixWorld ) );

			if ( _raycaster.ray.intersectPlane( _plane, _intersection ) ) {

				_inverseMatrix.getInverse( _selected.parent.matrixWorld );
				_offset.copy( _intersection ).sub( _worldPosition.setFromMatrixPosition( _selected.matrixWorld ) );

			}

			_domElement.style.cursor = 'move';

			scope.dispatchEvent( { type: 'dragstart', object: _selected } );

		}


	}

	function onDocumentTouchEnd( event ) {

		event.preventDefault();

		if ( _selected ) {

			scope.dispatchEvent( { type: 'dragend', object: _selected } );

			_selected = null;

		}

		_domElement.style.cursor = 'auto';

	}

	activate();

	// API

	this.enabled = true;

	this.activate = activate;
	this.deactivate = deactivate;
	this.dispose = dispose;

};

THREE.DragControls.prototype = Object.create( THREE.EventDispatcher.prototype );
THREE.DragControls.prototype.constructor = THREE.DragControls;
1 Like

Hi,
I think you should look into AABB collision detection

2 Likes

Thanks Felix for the response,
I had read about that.
I’m dragging the box with the help of DragControls
I dont know where should place this check and if it intersects then how to avoid going down further the moving the box up and other directions

DragControls supports an event “drag”, which is fired every time the user is dragging an object.
So you could do something like :

dragControls.addEventListener( "drag", ( event )=> {

     /*
     Find collisions here.
     If collision, move back your object to the limit where it's allowed to be.
     */

});
1 Like

Hi,

I have replaced the code with this logic.it detects collision.any way to stop passing in this below code.current logic is enable to stop passing the object

var dragControls = new THREE.DragControls( objects, camera, renderer.domElement);

dragControls.addEventListener( ‘drag’, function ( event ) {

if(objects[0].position.y <= (groundRaycastObj[0].position.y +1))

{

	  dragControls.addEventListener( 'drag', false);


}
else{
dragControls.addEventListener( 'dragstart', function ( event ) {

controls.enabled=false;
});
dragControls.addEventListener( ‘dragend’, function ( event ) {
controls.enabled=true;
});
}

could you please provide some suggestion

Can you please format your message correctly ?

HI
var dragControls = new THREE.DragControls( objects, camera,renderer.domElement,groundRaycastObj,interactiveObj);
dragControls.addEventListener( ‘drag’, function ( event )
{

 if(objects[0].position.y <= 50)
 {
 dragControls = false;	
 }
else
 {
  	dragControls.addEventListener( 'dragstart', function ( event ) 
  	{
     controls.enabled=false;
  		
  	});
    dragControls.addEventListener( 'dragend', function ( event )
    {
    controls.enabled=true;
    });
  }

});

please find new code

This is what I meant by “formatted correctly” :

var dragControls = new THREE.DragControls( objects, camera, renderer.domElement, groundRaycastObj, interactiveObj );

dragControls.addEventListener( 'drag', function ( event ) {

  if ( objects[0].position.y <= 50 ) {

  dragControls = false ;	

  } else {

  	dragControls.addEventListener( 'dragstart', function ( event ) {

      controls.enabled = false;
  		
  	});

    dragControls.addEventListener( 'dragend', function ( event ) {

      controls.enabled = true;

    });

  };

});

Now I’m sorry but I struggle to interpret what you said here :

I have replaced the code with this logic.it detects collision.any way to stop passing in this below code.current logic is enable to stop passing the object

If I had to forbid the object to go bellow 50, I’d write :

if ( object.position.y < 50 ) {

  object.position.y = 50;	

};
4 Likes

Thank you soo much Felix :slight_smile: