Hi,
I’ve loaded a 3D model and I want to limit the dragging property of tree from entering into certain areas(like car ,house etc.) I’ve used dragcontrols, and I would also like to restrict the tree from going outside the base mesh. How to achieve it? Someone please help! I’ve been stuck for a while.
Thank you and below is my script
<script>
var house,tree,raycaster,mouse,selectedObject,selob;
let scene,camera,renderer,controls,snow,objects=[],flag=0,flag2=0,flag3=0,positions=[],velocities=[];
const snowCount=150000;
const maxRange = 1000, minRange=maxRange/2;
const minHeight= 150;
function initialize() {
scene = new THREE.Scene();
scene.background = new THREE.Color(0x696969);
scene.fog = new THREE.Fog(0x1261A0,1,100);
camera = new THREE.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,100);
camera.position.set(25,8,0);
renderer = new THREE.WebGLRenderer({antialias:true});
renderer.setSize(window.innerWidth,window.innerHeight);
document.body.appendChild(renderer.domElement);
controls = new THREE.OrbitControls(camera,renderer.domElement);
controls.addEventListener('change',render);
controls.maxPolarAngle = 1.53;
controls.minDistance = 8;
controls.maxDistance = 50;
const dragControls = new THREE.DragControls( objects, camera, renderer.domElement );
const directionalLight = new THREE.DirectionalLight(0xffffff,1);
directionalLight.position.set(0,10,-5);
directionalLight.target.position.set(-10, 0, 0);
scene.add(directionalLight);
scene.add(directionalLight.target);
const hemisphereLight = new THREE.HemisphereLight(0xB1E1FF, 0xB97A20, 1);
scene.add(hemisphereLight);
const spotLight = new THREE.SpotLight(0xffffff, 0.3);
spotLight.position.set(10, 10, 0);
spotLight.target.position.set(-2, -2, -2);
scene.add(spotLight);
scene.add(spotLight.target);
const planeSize = 4000;
const repeats = planeSize / 2;
var groundTexture = new THREE.TextureLoader().load('./textures/1.webp')
groundTexture.wrapS = THREE.RepeatWrapping;
groundTexture.wrapT = THREE.RepeatWrapping;
groundTexture.repeat.set(repeats, repeats);
const groundGeometry = new THREE.PlaneBufferGeometry(planeSize, planeSize);
const groundMaterial = new THREE.MeshPhongMaterial({
map: groundTexture,
side: THREE.DoubleSide,
});
const ground = new THREE.Mesh(groundGeometry, groundMaterial);
ground.rotation.x = Math.PI * .5;
ground.position.y=0.61;
scene.add(ground);
const snowGeometry = new THREE.BufferGeometry();
const snowTexture = new THREE.TextureLoader();
addSnowflakes();
function addSnowflakes(){
for(let i =0;i<snowCount;i++) {
positions.push(
Math.floor(Math.random()* maxRange - minRange),
Math.floor(Math.random()* minRange + minHeight),
Math.floor(Math.random()* maxRange - minRange));
velocities.push(
Math.floor(Math.random()* 6 - 3) * 0.1,
Math.floor(Math.random()* 5 + 0.12) * 0.18,
Math.floor(Math.random()* 6 - 3) * 0.1);
}
snowGeometry.setAttribute('position', new THREE.Float32BufferAttribute(positions,3));
snowGeometry.setAttribute('velocity', new THREE.Float32BufferAttribute(velocities,3));
const snowMaterial = new THREE.PointsMaterial({
size:3,
map: snowTexture.load('./textures/Ice_cristal_-_heraldic_figure.svg'),
blending: THREE.AdditiveBlending,
depthTest:false,
transparent:true,
opacity:0.8,
});
snow = new THREE.Points(snowGeometry,snowMaterial);
scene.add(snow);
}
var hemiSphereGeom = new THREE.SphereBufferGeometry(15,32,16);
let verts = hemiSphereGeom.attributes.position.array
for(var i=0;i<verts.length;i+=3){
if(verts[i+1]<0)
verts[i+1]=0;
}
const hemiSphereMaterial = new THREE.MeshBasicMaterial({wireframe:true,color: "black",transparent:true,opacity:0.25 });
const hemiSphereMesh = new THREE.Mesh(hemiSphereGeom,hemiSphereMaterial);
scene.add(hemiSphereMesh);
hemiSphereMesh.position.y = 1.3;
const cylinderGeometry = new THREE.CylinderBufferGeometry(15,15,2.5,32);
const cylinderMaterial = new THREE.MeshBasicMaterial( {color: 0x5B270B, wireframe: false,});
const cylinderMesh = new THREE.Mesh(cylinderGeometry,cylinderMaterial);
scene.add(cylinderMesh);
//DAT.GUI
class ColorGUIHelper {
constructor(object, prop) {
this.object = object;
this.prop = prop;
}
get value() {
return `#${this.object[this.prop].getHexString()}`;
}
set value(hexString) {
this.object[this.prop].set(hexString);
}
}
{
const color = 0xFFFFFF;
const intensity = 1;
const ambientLight = new THREE.AmbientLight(color, intensity);
scene.add(ambientLight);
const gui = new dat.GUI();
gui.addColor(new ColorGUIHelper(ambientLight, 'color'), 'value').name('Ambient Light');
gui.add(ambientLight, 'intensity', 0, 2, 0.01).name('Intensity');
}
//Loading 3D Model
let gltfLoader = new THREE.GLTFLoader();
gltfLoader.load('http://localhost/myproject/3js/3jsdemo/house.gltf',function(gltf){
scene.add(gltf.scene);
house = gltf.scene;
house.traverse(function (child){
//CAR
if(child.name==='initialShadingGrouppolySurface116_polySurface3'){
document.onkeydown = (e) => {
if(event.keyCode == 37) {
if(child.position.z <27.5 ) {
child.position.z+=0.35;
}
}else if(event.keyCode == 39) {
if(child.position.z>-4.3) {
child.position.z-=0.3;
}
}
}
}
//TREE
if(child.name==='polySurface355_lambert14_0'){
tree = child;
objects.push(tree);
dragControls.addEventListener( 'dragstart', function ( event ) {
controls.enabled=false;
event.object.material.opacity=0.5;
});
dragControls.addEventListener( 'drag', function ( event ) {
event.object.position.y=0;
// console.log(event.object.position.z)
// console.log(event.object.position.x)
if(event.object.position.z>32 || event.object.position.x<=1){
console.log("Cannot place there");
dragControls.enabled=false;
}
if(event.object.position.z<32 || event.object.position.x>=1){
dragControls.enabled=true;
}
});
dragControls.addEventListener( 'dragend', function ( event ) {
event.object.material.opacity=1;
controls.enabled=true;
});
}
});
gltf.scene.scale.set(0.5,0.5,0.5);
gltf.scene.position.set(0,1.3,0);
},undefined,function(error) {
console.log("Error Occured");
renderer.render(scene,camera);
});
}
raycaster = new THREE.Raycaster();
mouse = new THREE.Vector2();
document.addEventListener('click',onclick,true );
document.addEventListener( 'pointermove', onPointerMove );
window.addEventListener('resize',onWindowResize,false);
initialize();
animate();
function onclick(event) {
raycaster.setFromCamera(mouse, camera);
var intersects = raycaster.intersectObjects(scene.children,true);
if (intersects.length > 0) {
selectedObject = intersects[1].object.name;
selob=intersects[1];
console.log(selob)
if(selectedObject=='initialShadingGrouppolySurface116_polySurface3_lambert17_0'){
if(flag3==0){
intersects[1].object.material.transparent=true;
intersects[1].object.material.opacity=0.5;
flag3=1;
}
else{
intersects[1].object.material.opacity=1;
flag3 = 0;
}
}
if(selectedObject=='Garage_door_lambert16_0'){
if(flag2==0){
intersects[1].object.rotation.set(0,0,-0.6);
flag2 = 1;
}
else {
intersects[1].object.rotation.set(0,0,0);
flag2 =0;
}
}
if(selectedObject=='House_door_lambert16_0'){
if(flag==0){
intersects[1].object.position.set(2,0,0)
intersects[1].object.rotation.set(0,-0.2,0);
flag = 1;
}
else {
intersects[1].object.rotation.set(0,0,0);
flag =0;
}
}
}
}
function onPointerMove( event ) {
mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
}
function render() {
renderer.render(scene,camera);
}
function animate() {
requestAnimationFrame(animate);
updateSnow();
renderer.render(scene,camera);
controls.update();
}
function onWindowResize() {
camera.aspect = window.innerWidth/window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth,window.innerHeight);
}
function updateSnow(){
for(let i=0; i<snowCount*3; i+=3){
snow.geometry.attributes.position.array[i]-=snow.geometry.attributes.velocity.array[i];
snow.geometry.attributes.position.array[i+1]-=snow.geometry.attributes.velocity.array[i+1];
snow.geometry.attributes.position.array[i+2]-=snow.geometry.attributes.velocity.array[i+2];
if(snow.geometry.attributes.position.array[i+1]<0) {
snow.geometry.attributes.position.array[i] = Math.floor(Math.random()* maxRange - minRange);
snow.geometry.attributes.position.array[i+1] = Math.floor(Math.random()* minRange + minHeight);
snow.geometry.attributes.position.array[i+2] = Math.floor(Math.random()* maxRange - minRange);
}
}
snow.geometry.attributes.position.needsUpdate = true;
}
</script>