Related
I am using three js for loading 3D model on webpage.and i used PerspectiveCamera class to see 3d model.but when i zoom out that 3d model it dispppears.how to fix that issue?
This is my code in javascript
import { GLTFLoader } from './GLTFLoader.js';
import { OrbitControls } from './OrbitControls.js';
var scene, camera, renderer, obj, newMaterial;
var object_name = []; //array to store object_name getting from api.
var exhibitor_id = localStorage.getItem('exhibitor');
console.log(exhibitor_id)
function init() {
scene = new THREE.Scene();
//camera
camera = new THREE.PerspectiveCamera(65, window.innerWidth / window.innerHeight, 0.1, 1000);
// camera = new THREE.PerspectiveCamera(65, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(0, 0, 700);
// renderer
renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
renderer.setSize(window.innerWidth, window.innerHeight);
$('.model').append(renderer.domElement)
var loader = new GLTFLoader();
//filepath:it is path for scene.gltf file
loader.load(filepath, function (gltf) {
obj = gltf.scene;
obj.position.set(0, -200, 0);
obj.traverse(function (object) { object.frustumCulled = false; });
scene.add(obj);
animate();
$.ajax({
type: 'get',
url: '/3dbasetextures/1',
data: {},
success: function (response) {
for (i = 0; i < response.length; i++) {
object_name.push(response[i].object_name)
}
},
error: function (data) {
},
});
$.ajax({
type: 'get',
url: '/3dcollage/' + exhibitor_id,
data: {},
success: function (response) {
// console.log("3dtextures", data.data[0].collage_path);
var textureLoader = new THREE.TextureLoader();
console.log(response.data)
for (i = 0; i < response.data.length; i++) {
// console.log(i, response.data[i])
if (response.data[i].collage_path != null) {
var newTexture = textureLoader.load(response.data[i].collage_path);
var posterobj = obj.getObjectByName(object_name[i]);
posterobj.material.map = newTexture;
newTexture.flipY = false;
}
else {
alert("Images not creted.")
}
}
},
error: function (data) {
}
});
console.log(object_name)
});
// background
// scene.background = new THREE.Color(0xC1C1C1);
// light
// var light = new THREE.HemisphereLight(0xffffff, 0x000000, 3);
var light = new THREE.HemisphereLight(0xffffff, 0x000000, 3);
scene.add(light);
//controls
controller();
scene.add(camera);
}
function controller() {
var controls = new OrbitControls(camera, renderer.domElement);
controls.target.set(0, 1, 0);
controls.enableDamping = true;
controls.dampingFactor = 0.25;
controls.enableZoom = true;
controls.minAzimuthAngle = -0.6;
controls.maxAzimuthAngle = 1.5;
controls.minPolarAngle = controls.maxPolarAngle = 1.57079
}
function animate() {
requestAnimationFrame(animate);
// controls.update();
renderer.render(scene, camera);
}
// for implementing responsiveness
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
window.addEventListener('resize', onWindowResize, false);
init();
There is one method to fix zoom in and out but it is applicable for OrthrographicCamera.
But PerspectiveCamera is more suitable for viewing 3D model
For Perspective Camera, zooming is called "dollying". you can use the distance (minDistance & maxDistance) to limit the zoom/ dolly.
controls.minDistance = <your value here>;
https://threejs.org/docs/?q=CONTROL#examples/en/controls/OrbitControls
Working on the task for connecting two cubes by a line where I want to keep a dot while clicking in the cube and another cube where the dot represents as the line starting point and ending point. Here's the code and thanks in advance.
The code has two cubes which joints each other with a line in a click where I want to represent a dot in the start and end line
var camera, scene, renderer, controls;
var raycaster = new THREE.Raycaster(),
mouse = new THREE.Vector2();
var intersected, lineObjects = [],
objects = [];
init();
animate();
function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(80, window.innerWidth / window.innerHeight, 1, 500);
camera.position.set(5, 15, 10);
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0xffffff);
document.body.appendChild(renderer.domElement);
window.addEventListener("mousedown", onMouseDown, false);
controls = new THREE.OrbitControls(camera, renderer.domElement);
var geometry = new THREE.BoxGeometry(1, 1, 1);
var material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
var cube = new THREE.Mesh(geometry, material);
scene.add(cube);
var cube1 = new THREE.Mesh(geometry, material);
cube1.position.set(2, 5, 5)
scene.add(cube1);
}
function lineObj(pointStart, pointEnd) {
var lineGeom = new THREE.Geometry();
lineGeom.vertices.push(pointStart.clone());
lineGeom.vertices.push(pointEnd.clone());
var lineMat = new THREE.LineBasicMaterial({
color: "red"
});
line = new THREE.Line(lineGeom, lineMat);
return line;
}
function onMouseDown(event) {
mouse.x = (event.clientX / renderer.domElement.clientWidth) * 2 - 1;
mouse.y = -((event.clientY) / renderer.domElement.clientHeight) * 2 + 1;
raycaster.setFromCamera(mouse, camera);
var intersects = raycaster.intersectObjects(scene.children);
// var intersects = raycaster.intersectObjects(scene.children,true);
if (intersects.length > 0) {
var found = intersects[0].object;
if (found != intersected) {
if (lineObjects.length > 0) {
var line = lineObj(lineObjects[0].position, found.position);
scene.add(line);
lineObjects[0].material.color.setHex(lineObjects[0].userData.oldColor);
intersected = null;
lineObjects = [];
} else {
found.userData.oldColor = found.material.color.getHex();
found.material.color.set(0x00FF00);
intersected = found;
lineObjects.push(found);
}
} else {
found.material.color.setHex(found.userData.oldColor);
intersected = null;
lineObjects = [];
}
}
}
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
renderer.render(scene, camera);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/100/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
I am a beginner of Threejs.
I created a Box Mesh and a Sphere Mesh and applied physics using physiJs.
What I want to do is to hit the ball when the Box Mesh rotates and passing through the ball.
However, when the box mesh rotates, it passes without hitting the ball.
I think the box mesh loses physicality when it starts spinning.
function createBall () {
var ball = null;
var ballGeo = new THREE.SphereGeometry(1.5, 30, 30);
var ballMat = Physijs.createMaterial(
new THREE.MeshBasicMaterial({specular: 0x111111})
, 0.3, 0.1
);
ball = new Physijs.SphereMesh(
ballGeo,
ballMat,
5
);
ball.position.set(30, 10, 0);
scene.add(ball);
}
function createBox () {
var material = Physijs.createMaterial(
new THREE.MeshLambertMaterial(
{
color: 0x8041D9,
}), 5, 0.3);
var boxMesh = new THREE.BoxGeometry(5, 5, 25);
box = new Physijs.BoxMesh(
boxMesh,
material,
5
);
box.position.z = 20;
scene.add(box);
}
function createHeightMap() {
var initColor = new THREE.Color( 0x00ff00 );
initColor.setHSL( 0.25, 0.85, 0.5 );
var ground_material = Physijs.createMaterial(
new THREE.MeshPhongMaterial(
{ color: 0x47C83E}
),
.5,
.5
);
var ground_geometry = new THREE.PlaneGeometry(800, 800, 100, 100);
ground = new Physijs.HeightfieldMesh(
ground_geometry,
ground_material,
0, // 질량
100, // PlaneGeometry 의 분할 세그먼트랑 똑같은 값으로 줘야 한다.
100 // PlaneGeometry 의 분할 세그먼트랑 똑같은 값으로 줘야 한다.
);
ground.position.y = -10;
ground.rotation.x = Math.PI / -2;
ground.receiveShadow = true;
var meshes = [];
var controls = new function () {
this.startRotate = false;
this.addBall = function () {
createBall();
};
this.addBox = function () {
createBox();
};
this.clearMeshes = function () {
meshes.forEach(function (e) {
scene.remove(e);
});
meshes = [];
}
};
var gui = new dat.GUI();
gui.add(controls, 'addBall');
gui.add(controls, 'addBox');
gui.add(controls, 'clearMeshes');
gui.add(controls, 'startRotate').onChange(function (e) {
isStartRoate = e;
});
return ground;
}
render = function () {
stats.update();
if (isStartRoate === true) {
var rotateMatrix = new THREE.Matrix4();
rotateMatrix.identity();
rotateMatrix.makeRotationY(0.05);
box.applyMatrix(rotateMatrix);
}
requestAnimationFrame(render);
renderer.render(scene, camera);
var axes = new THREE.AxesHelper(30);
scene.add(axes);
scene.simulate(undefined, 2);
};
function initStats() {
var stats = new Stats();
stats.setMode(0); // 0: fps, 1: ms
// Align top-left
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px';
document.getElementById("Stats-output").appendChild(stats.domElement);
return stats;
}
window.onload = initScene;
below is codepen link
codepen
It seems like physicality not updated.
please give me any idea
When using Physijs, you should use setLinearVelocity() or setAngularVelocity() in order to update the position and rotation of your objects in a physical correct way. The updated codepen shows this approach:
https://codepen.io/anon/pen/YJmajN
Besides, the way you create AxesHelper in the render loop is no good approach. Create the helper once during the setup up of your scene.
Been doing this for 10 hours or so and still can't figure out how should I be able (or indeed should I be able at all) to move imported object in scene.
Here are my code samples:
// OBJECT (.obj loader)
var onProgress = function (xhr) {
if (xhr.lengthComputable) {
var percentComplete = xhr.loaded / xhr.total * 100;
console.log(Math.round(percentComplete, 2) + '% downloaded');
}
};
var onError = function (xhr) { };
THREE.Loader.Handlers.add(/\.dds$/i, new THREE.DDSLoader());
var mtlLoader = new THREE.MTLLoader();
mtlLoader.setPath('./');
mtlLoader.load('object.mtl', function (materials) {
materials.preload();
var objLoader = new THREE.OBJLoader();
objLoader.setMaterials(materials);
objLoader.setPath('./');
objLoader.load('object.obj', function (object) {
object.scale.x = object.scale.y = object.scale.z = 20;
object.position.set(1100, 0, -600);
object.castShadow = true;
object.receiveShadow = true;
scene.add(object);
}, onProgress, onError);
});
Now the object is in the scene. I can look at it, no problem, but when I try:
function animate() {
requestAnimationFrame(animate);
object.rotation.x += 0.005;
renderer.render(scene, camera);
controls.update();
}
Nothing. Just nothing. If I have a crate created in init(), I can rotate it in animate() with crate.rotation.x += 0.005; with no problems whatsoever, but the imported object... no. Nothing happens. It says:
SCRIPT5007: Unable to get property 'rotation' of undefined or null reference
Can you help? How to animate imported .obj file in three.js?
Try this one,
var model;
var onProgress = function (xhr) {
if (xhr.lengthComputable) {
var percentComplete = xhr.loaded / xhr.total * 100;
console.log(Math.round(percentComplete, 2) + '% downloaded');
}
};
var onError = function (xhr) { };
var mtlLoader = new THREE.MTLLoader();
mtlLoader.setPath('./');
mtlLoader.load('object.mtl', function (materials) {
materials.preload();
var objLoader = new THREE.OBJLoader();
objLoader.setMaterials(materials);
objLoader.setPath('./');
objLoader.load('object.obj', function (object) {
object.scale.x = object.scale.y =
object.scale.z = 20;
object.position.set(1100, 0, -600);
object.castShadow = true;
object.receiveShadow = true;
model = object;
scene.add(model);
}, onProgress, onError); });
And then change the animate function,
function animate() {
requestAnimationFrame( animate );
model.rotation.x += 0.005;
renderer.render(scene, camera);
controls.update();
}
You were referring to object which is out of scope in the animate function. I changed it by using variable model.
I am trying to use Ray intersect to find out if 2 collada object collide.
But so far no success :(
my code http://jsfiddle.net/XqQzF/
object.updateMatrix();
// ray
var f_vector = new THREE.Vector3( 0, 0, -1 );
var b_vector = new THREE.Vector3( 0, 0, 1 );
var l_vector = new THREE.Vector3( -1, 0, 0 );
var r_vector = new THREE.Vector3( 1, 0, 0 );
everytime i use something its removed from the newest three.js revision.
Can you help me on the way ?
I recently update my three.js examples collection to be compatible with the latest version (v56 at time of writing), and this includes an example of collision detection. Check out http://stemkoski.github.com/Three.js/Collision-Detection.html (see http://stemkoski.github.com/Three.js/#collision-detection for instructions).
The main difference in your case will be choosing a central point of your model as an origin point for the rays, and choosing a set of vertices of your model to use as endpoints for the rays, as rays are what is used for collision detection.
Hope this helps!
#Lee Stemkoski answer is ok, when we doesn't use collada data.
First what I know is that we need min. 2 Mesh objects. So I took all Mesh objects from collada object. I wrote two scripts - first tried colliding 2 collada objects. Second tried to collide collada object with wall(simple Mesh). In both cases script it doesn't recognize colliding 😕. So how i should write it?
At last I tried to detect mouse on collada object. It's not about this topic but it's similar problem so I write it here.
Dae file was generated by SketchUp.
Code for two collada objects:
var container;
var meshs = [];
var camera, scene, renderer, raycaster;
var controls;
var mouse = new THREE.Vector2();
var dae, dae2;
var collidableMeshList = [];
var clock = new THREE.Clock();
var keyboard = new THREEx.KeyboardState();
$(document).ready(function() {
init();
animate();
});
function init() {
container = document.createElement('div');
$('.container').append(container);
camera = new THREE.PerspectiveCamera(45, 500 / 500, 1, 1000);
group = new THREE.Group();
scene = new THREE.Scene();
scene.add(camera);
camera.position.set(10 * 10, 12 * 10, 16 * 10);
camera.lookAt(scene.position);
// Lights
group.add(new THREE.AmbientLight(0x777777));
var light = new THREE.DirectionalLight(0xdfebff, 1.25);
light.position.set(300, 400, 50);
light.position.multiplyScalar(1.3);
light.castShadow = true;
group.add(light);
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setClearColor(0xcccccc, 1);
renderer.setSize(500, 500);
container.appendChild(renderer.domElement);
controls = new THREE.OrbitControls(camera, renderer.domElement);
var loader = new THREE.ColladaLoader();
loader.options.convertUpAxis = true;
loader.load('./sample.dae', loadDae);
function loadDae(collada) {
dae = collada.scene;
dae.scale.x = 0.5;
dae.scale.y = 0.3;
dae.scale.z = 0.3;
dae.updateMatrix();
group.add(dae);
}
var wallGeometry = new THREE.CubeGeometry(10, 10, 20, 1, 1, 1);
var wallMaterial = new THREE.MeshBasicMaterial({
color: 0x8888ff
});
var wireMaterial = new THREE.MeshBasicMaterial({
color: 0x000000,
wireframe: true
});
loader = new THREE.ColladaLoader();
loader.options.convertUpAxis = true;
loader.load('./sample.dae', loadDae2);
function loadDae2(collada) {
dae2 = collada.scene;
dae2.scale.x = 0.5;
dae2.scale.y = 0.3;
dae2.scale.z = 0.3;
dae2.updateMatrix();
dae2.position.set(-40, 0, 0);
dae2.traverse(function(child) {
if (child instanceof THREE.Mesh) {
collidableMeshList.push(child);
}
});
group.add(dae2);
}
group.translateX(-20);
scene.add(group);
raycaster = new THREE.Raycaster();
window.addEventListener('resize', onWindowResize, false);
window.addEventListener('mousemove', onDocumentMouseMove, false);
}
function onDocumentMouseMove(event) {
event.preventDefault();
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
}
function onWindowResize() {
camera.aspect = 500 / 500;
camera.updateProjectionMatrix();
renderer.setSize(500, 500);
}
function update() {
var delta = clock.getDelta();
var moveDistance = 200 * delta;
var rotateAngle = Math.PI / 2 * delta;
if (keyboard.pressed("A"))
dae.rotation.y += rotateAngle;
if (keyboard.pressed("D"))
dae.rotation.y -= rotateAngle;
if (keyboard.pressed("left"))
dae.translateX(-moveDistance);
if (keyboard.pressed("right"))
dae.translateX(moveDistance);
if (keyboard.pressed("up"))
dae.translateZ(-moveDistance);
if (keyboard.pressed("down"))
dae.translateZ(moveDistance);
meshs = [];
if (typeof dae !== 'undefined') {
dae.traverse(function(child) {
if (child instanceof THREE.Mesh) {
meshs.push(child);
}
});
$.each(meshs, function(number_mesh, mesh) {
var originPoint = mesh.position.clone();
for (var vertexIndex = 0; vertexIndex < mesh.geometry.vertices.length; vertexIndex++) {
var localVertex = mesh.geometry.vertices[vertexIndex].clone();
var globalVertex = localVertex.applyMatrix4(mesh.matrix);
var directionVector = globalVertex.sub(mesh.position);
var ray = new THREE.Raycaster(originPoint, directionVector.clone().normalize());
var collisionResults = ray.intersectObjects(collidableMeshList);
if (collisionResults.length > 0 && collisionResults[0].distance < directionVector.length()) {
console.log(" Hit ");
}
}
});
}
controls.update();
}
function animate() {
requestAnimationFrame(animate);
render();
update();
}
function render() {
renderer.render(scene, camera);
}
Code for collada + wall(Mesh):
var container;
var meshs = [];
var camera, scene, renderer, raycaster;
var controls;
var mouse = new THREE.Vector2();
var dae;
var collidableMeshList = [];
var clock = new THREE.Clock();
var keyboard = new THREEx.KeyboardState();
$(document).ready(function() {
init();
animate();
});
function init() {
container = document.createElement('div');
$('.container').append(container);
camera = new THREE.PerspectiveCamera(45, 500 / 500, 1, 1000);
group = new THREE.Group();
scene = new THREE.Scene();
scene.add(camera);
camera.position.set(10 * 10, 12 * 10, 16 * 10);
camera.lookAt(scene.position);
// Lights
group.add(new THREE.AmbientLight(0x777777));
var light = new THREE.DirectionalLight(0xdfebff, 1.25);
light.position.set(300, 400, 50);
light.position.multiplyScalar(1.3);
light.castShadow = true;
group.add(light);
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setClearColor(0xcccccc, 1);
renderer.setSize(500, 500);
container.appendChild(renderer.domElement);
controls = new THREE.OrbitControls(camera, renderer.domElement);
var loader = new THREE.ColladaLoader();
loader.options.convertUpAxis = true;
loader.load('./sample.dae', loadDae);
function loadDae(collada) {
dae = collada.scene;
dae.scale.x = 0.5;
dae.scale.y = 0.3;
dae.scale.z = 0.3;
dae.updateMatrix();
group.add(dae);
}
var wallGeometry = new THREE.CubeGeometry(10, 10, 20, 1, 1, 1);
var wallMaterial = new THREE.MeshBasicMaterial({
color: 0x8888ff
});
var wireMaterial = new THREE.MeshBasicMaterial({
color: 0x000000,
wireframe: true
});
var wall = new THREE.Mesh(wallGeometry, wallMaterial);
wall.position.set(-40, 5, -10);
group.add(wall);
collidableMeshList.push(wall);
var wall = new THREE.Mesh(wallGeometry, wireMaterial);
wall.position.set(-40, 5, -10);
group.add(wall);
group.translateX(-20);
scene.add(group);
raycaster = new THREE.Raycaster();
window.addEventListener('resize', onWindowResize, false);
window.addEventListener('mousemove', onDocumentMouseMove, false);
}
function onDocumentMouseMove(event) {
event.preventDefault();
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
}
function onWindowResize() {
camera.aspect = 500 / 500;
camera.updateProjectionMatrix();
renderer.setSize(500, 500);
}
function update() {
var delta = clock.getDelta();
var moveDistance = 200 * delta;
var rotateAngle = Math.PI / 2 * delta;
if (keyboard.pressed("A"))
dae.rotation.y += rotateAngle;
if (keyboard.pressed("D"))
dae.rotation.y -= rotateAngle;
if (keyboard.pressed("left"))
dae.translateX(-moveDistance);
if (keyboard.pressed("right"))
dae.translateX(moveDistance);
if (keyboard.pressed("up"))
dae.translateZ(-moveDistance);
if (keyboard.pressed("down"))
dae.translateZ(moveDistance);
meshs = [];
if (typeof dae !== 'undefined') {
dae.traverse(function(child) {
if (child instanceof THREE.Mesh) {
meshs.push(child);
}
});
$.each(meshs, function(number_mesh, mesh) {
var originPoint = mesh.position.clone();
for (var vertexIndex = 0; vertexIndex < mesh.geometry.vertices.length; vertexIndex++) {
var localVertex = mesh.geometry.vertices[vertexIndex].clone();
var globalVertex = localVertex.applyMatrix4(mesh.matrix);
var directionVector = globalVertex.sub(mesh.position);
var ray = new THREE.Raycaster(originPoint, directionVector.clone().normalize());
var collisionResults = ray.intersectObjects(collidableMeshList);
if (collisionResults.length > 0 && collisionResults[0].distance < directionVector.length()) {
console.log(" Hit ");
}
}
});
}
controls.update();
}
function animate() {
requestAnimationFrame(animate);
render();
update();
}
function render() {
renderer.render(scene, camera);
}
Detect mouse on collada object. Short code version:
var meshs = [],
raycaster,
mouse = new THREE.Vector2();
...
function init() {
...
function loadDae(collada) {
dae = collada.scene;
dae.scale.x = 0.5;
dae.scale.y = 0.3;
dae.scale.z = 0.3;
dae.updateMatrix();
group.add(dae);
dae.traverse(function(child) {
if (child instanceof THREE.Mesh) {
meshs.push(child);
}
});
}
var loader = new THREE.ColladaLoader();
loader.options.convertUpAxis = true;
loader.load('./sample.dae', loadDae);
raycaster = new THREE.Raycaster();
window.addEventListener('mousemove', onDocumentMouseMove, false);
...
}
...
function onDocumentMouseMove(event) {
event.preventDefault();
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
}
function render() {
raycaster.setFromCamera(mouse, camera);
if (group.children.length === 5) {
var intersects = raycaster.intersectObjects(meshs);
if (intersects.length > 0) {
console.log(" Hit ");
}
}
renderer.render(scene, camera);
}
...
General - yes, it works, but throw errors with some $meshs 😕.
TypeError: undefined is not an object (evaluating 'O')
three.min.js:8304
cthree.min.js:3544
intersectObjectsthree.min.js:3609:144
Why and how to recognize which mesh is correct for intersectObjects and which not?