Fist time I'm working with javascript, WebGL and Three.js.
I added dae 3D model to my scene and now I have to get it's size to generate objects inside of it. But when I added dae object, it displayed rotated on the scene. As I read somewhere and also tested, I can't just rotate my object because bounding box will not rotate with it. What should I do to get the size of the object?
<!DOCTYPE html>
<html>
<head>
<title>Collada Size.js</title>
</head>
<body>
<script src="js/three.min.js"></script>
<script src="js/ColladaLoader.js"></script>
<script>
window.onload = function () {
var renderer = new THREE.WebGLRenderer();
renderer.setSize(800, 600);
document.body.appendChild(renderer.domElement);
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(
55, // Field of view
800 / 600, // Aspect ratio
0.1, // Near plane
1000 // Far plane
);
camera.position.set(-15, 1000, 10);
camera.lookAt(scene.position);
var loader = new THREE.ColladaLoader();
loader.options.convertUpAxis = true;
loader.load('models/MyFile.dae', function (collada) {
var dae = collada.scene;
var skin = collada.skins[0];
dae.position.set(0, 0, 0);
//dae.rotation.y = 45;
render();
dae.scale.set(120, 150, 120);
scene.add(dae);
sizeofDesk(dae);
});
function sizeofDesk(dae) {
var helper = new THREE.BoundingBoxHelper(dae, 0xff0000);
helper.update();
// If you want a visible bounding box
scene.add(helper);
// If you just want the numbers
var min = helper.box.min;
var max = helper.box.max;
console.log(min);
console.log(max);
}
var dirLight = new THREE.DirectionalLight(0xffffff, 1);
dirLight.position.set(100, 100, 50);
scene.add(dirLight);
renderer.setClearColor(0xffe5e5, 1);
render();
function render() {
requestAnimationFrame(render);
renderer.render(scene, camera);
}
};
</script>
</body>
</html>
You using dae.scale.set(120, 150, 120); Are you sure you want to scale object 150 times? Default scale is dae.scale.set(1,1,1).
You can setup obj = new THREE.Object3D();scene.add(obj); and your model put to the object obj.add(dae); Then you can manipulate with object (pre-scale object, rotate and translate.)...
Related
I am trying to build a rocketship model by add different shapes to a large group and position them at specific axis.
When I try to use
rocketConeMesh.position.y = 15;
The shape does not move at all, I am trying to put the rocketCone (The nose of the rocket ship) on top of the rocketBody and then have them under the same group.
I get the followig error message
"THREE.Object3D.add: object not an instance of THREE.Object3D. "
for the coneGeometry object.
my code is as follows:
<script type="text/javascript">
// create a scene, that will hold all our elements such as objects, cameras and lights.
var scene = new THREE.Scene();
// create a camera, which defines where we're looking at.
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
// create a render and set the size
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
window.addEventListener('resize', function()
{
var width = window.innerWidth;
var height = window.innerHeight;
renderer.setSize(width, height);
camera.aspect = width / height;
camera.updateProjectionMatrix();
} );
controls = new THREE.OrbitControls(camera, renderer.domElement);
// create the object group that contains all the sub-shapes
var rocketGroup = new THREE.Object3D();
scene.add(rocketGroup);
//The object below is the top cone of the rocket
var rocketCone = new THREE.ConeGeometry(6, 10, 6);
var material = new THREE.MeshBasicMaterial({color: 0xcccccc, wireframe: true});
var cone = new THREE.Mesh(rocketCone, material);
rocketConeMesh = new THREE.Mesh(rocketCone,new THREE.MeshPhongMaterial())
scene.add(cone);
//Specify the position of the rocket cone
rocketConeMesh.position.y = 15;
//Add the rocketCone to the lowpolyRocket group
rocketGroup.add(rocketCone);
/******************************************************************************************************************/
//var rocketBody = new THREE.CylinderGeometry( 5, 5, 20, 32 );
//var material = new THREE.MeshBasicMaterial({color: 0xcccccc, wireframe:false});
//var cylinder = new THREE.Mesh(rocketBody, material);
//scene.add(cylinder);
// position and point the camera to the center of the scene
camera.position.x = -30;
camera.position.y = 20;
camera.position.z = 30;
camera.lookAt(scene.position);
// game logic
var update = function ( )
{
//cone.rotation.x += 0.01;
//cone.rotation.y += 0.005;
};
// draw scene
var render = function ( )
{
renderer.render(scene, camera);
};
// run game loop (update, render, repeat)
var GameLoop = function ( )
{
requestAnimationFrame(GameLoop);
update( );
render( );
};
GameLoop( );
</script>
rocketGroup.add(rocketCone);
This code is not valid since it's not possible to add an instance of ConeGeometry to an Object3D. Try to change your code to the following:
rocketGroup.add(rocketConeMesh);
Now you add the mesh (which is derived from THREE.Object3D) to rocketGroup. It's now part of the scene graph and changing its transformation should work.
BTW: I don't understand why you create two meshes with your rocketCone geometry. I guess you can remove the cone variable.
I'm trying to import blender scene to three.js with ObjectLoader() function. I want this to be as easy as possible, without animation just objects with right texture and colour in right place. Unfortunately three.js documentation is not a friendly place for newbies. So far I managed to draw every object from scene but every object is in different colour, plane lacks its texture and they are all in wrong places. What am I doing wrong? Here is my .js code:
var scene, camera, renderer;
var WIDTH = window.innerWidth;
var HEIGHT = window.innerHeight;
function init() {
scene = new THREE.Scene();
initCamera();
initLights();
initRenderer();
document.body.appendChild(renderer.domElement);
}
function initCamera() {
camera = new THREE.PerspectiveCamera(70, WIDTH / HEIGHT, 1, 10);
camera.position.set(0, 3.5, 5);
camera.lookAt(scene.position);
}
function initRenderer() {
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(WIDTH, HEIGHT);
}
function initLights() {
var light = new THREE.AmbientLight(0xffffff);
scene.add(light);
}
var loader = new THREE.ObjectLoader();
loader.load('./city.json', function(loadedObj) {
mesh = new THREE.Mesh(loadedObj);
var plane = loadedObj.getObjectByName("plane");
var building1 = loadedObj.getObjectByName("building1");
var building2 = loadedObj.getObjectByName("building2");
var building3 = loadedObj.getObjectByName("building3");
var building4 = loadedObj.getObjectByName("building4");
var building5 = loadedObj.getObjectByName("building5");
var building6 = loadedObj.getObjectByName("building6");
var building7 = loadedObj.getObjectByName("building7");
var building8 = loadedObj.getObjectByName("building8");
scene.add(loadedObj);
console.log(building1);
console.log(building2);
console.log(building3);
console.log(building4);
console.log(building5);
console.log(building6);
console.log(building7);
console.log(building8);
});
function render() {
requestAnimationFrame(render);
renderer.render(scene, camera);
}
init();
render();
Is it possible that there is problem with way of exporting from blender not with code?
EDIT: Sorry about that, here's my city.json file
city.json
I am just learning three.js and am struggling to animate an object.
I need to be able to load a .json file (exported from Blender) and have the object rotate horizontally continually (as an animation), kind of like this example. Rotating the scene could also work.
Most solutions I've seen involve rotating the mesh, but any time I try to reference the mesh variable, I get a console error that it is undefined or null (depending on whether I initialize it or not), which I assume is because it is only used inside of my .json loader. Another solution suggested referencing the scene, but that gives me an error "Disallowing antialiased backbuffers due to blacklisting."
The code I currently have is:
<!DOCTYPE html>
<html>
<head>
<title>Rotating Sphere</title>
<meta charset="utf-8">
<!-- https://cdnjs.com/libraries/three.js -->
<script src="http://www.amdesigngroup.com/clients/AM_6292_Learning/js/three.min.js"></script>
<script src="http://www.amdesigngroup.com/clients/AM_6292_Learning/js/OrbitControls.js"></script>
<!-- Tween.js: https://cdnjs.com/libraries/tween.js/ -->
<!--<script src="http://www.amdesigngroup.com/clients/AM_6292_Learning/js/Tween.js"></script>-->
</head>
<body style="margin: 0; background-color:#6cdbf5;">
<script>
// Set up the scene, camera, and renderer as global variables.
var scene = null,
camera = null,
renderer = null,
mesh = null;
init();
animate();
// Sets up the scene.
function init() {
// Create the scene and set the scene size.
scene = new THREE.Scene();
var WIDTH = window.innerWidth,
HEIGHT = window.innerHeight;
// Create a renderer and add it to the DOM.
renderer = new THREE.WebGLRenderer({antialias:true, alpha:true});
renderer.setSize(WIDTH, HEIGHT);
document.body.appendChild(renderer.domElement);
// Create a camera, zoom it out from the model a bit, and add it to the scene.
camera = new THREE.PerspectiveCamera(45, WIDTH / HEIGHT, 0.1, 20000);
camera.position.set(0,6,0);
scene.add(camera);
// Create an event listener that resizes the renderer with the browser window.
window.addEventListener('resize', function() {
var WIDTH = window.innerWidth,
HEIGHT = window.innerHeight;
renderer.setSize(WIDTH, HEIGHT);
camera.aspect = WIDTH / HEIGHT;
camera.updateProjectionMatrix();
});
// Set the background color of the scene to transparent
//renderer.setClearColor(0x000000, 0);
// Create a light, set its position, and add it to the scene.
var light = new THREE.PointLight(0xffffff);
light.position.set(-100,200,100);
scene.add(light);
// Load in the mesh and add it to the scene.
var loader = new THREE.JSONLoader();
loader.load( "http://www.amdesigngroup.com/clients/AM_6292_Learning/models/circle.json", function(geometry){
var material = new THREE.MeshLambertMaterial({color: 0x55B663});
mesh = new THREE.Mesh(geometry, material);
mesh.translation = THREE.GeometryUtils.center(geometry);
/*mesh.rotation.x = 0;*/
scene.add(mesh);
});
// Add OrbitControls so that we can pan around with the mouse.
controls = new THREE.OrbitControls(camera, renderer.domElement);
}
/* rotate mesh */
/*var duration = 5000; // ms
var currentTime = Date.now();
function rotate() {
var now = Date.now();
var deltat = now - currentTime;
currentTime = now;
var fract = deltat / duration;
var angle = Math.PI * 2 * fract;
scene.rotation.y += angle;
}*/
// Renders the scene and updates the render as needed.
function animate() {
// Read more about requestAnimationFrame at http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/
requestAnimationFrame(animate);
//rotate();
// Render the scene.
renderer.render(scene, camera);
controls.update();
}
</script>
</body>
</html>
As posted, it will display, but not animate, the model - various sections that are commented out are my failed attempts to accomplish a rotation animation.
Can anyone give me some pointers?
I found the solution! Thanks to one article that used a function called within the loader, passing the object as a variable, I was able to access the object. Then this StackOverflow post used Tween to create an animation. I was able to modify that code to get the rotation that I was looking for.
Here is the code that is now working for me:
<!DOCTYPE html>
<html>
<head>
<title>Rotating Sphere</title>
<meta charset="utf-8">
<!-- https://cdnjs.com/libraries/three.js -->
<script src="http://www.amdesigngroup.com/clients/AM_6292_Learning/js/three.min.js"></script>
<script src="http://www.amdesigngroup.com/clients/AM_6292_Learning/js/OrbitControls.js"></script>
<!-- Tween.js: https://cdnjs.com/libraries/tween.js/ -->
<script src="http://www.amdesigngroup.com/clients/AM_6292_Learning/js/Tween.js"></script>
</head>
<body style="margin: 0; background-color:#6cdbf5;">
<script>
// Set up the scene, camera, and renderer as global variables.
var scene = null,
camera = null,
renderer = null,
mesh = null;
init();
run();
// Sets up the scene.
function init() {
// Create the scene and set the scene size.
scene = new THREE.Scene();
var WIDTH = window.innerWidth,
HEIGHT = window.innerHeight;
// Create a renderer and add it to the DOM.
renderer = new THREE.WebGLRenderer({antialias:true, alpha:true});
renderer.setSize(WIDTH, HEIGHT);
document.body.appendChild(renderer.domElement);
// Create a camera, zoom it out from the model a bit, and add it to the scene.
camera = new THREE.PerspectiveCamera(45, WIDTH / HEIGHT, 0.1, 20000);
camera.position.set(0,6,0);
scene.add(camera);
// Create an event listener that resizes the renderer with the browser window.
window.addEventListener('resize', function() {
var WIDTH = window.innerWidth,
HEIGHT = window.innerHeight;
renderer.setSize(WIDTH, HEIGHT);
camera.aspect = WIDTH / HEIGHT;
camera.updateProjectionMatrix();
});
// Set the background color of the scene to transparent
//renderer.setClearColor(0x000000, 0);
// Create a light, set its position, and add it to the scene.
var light = new THREE.PointLight(0xffffff);
light.position.set(-100,200,100);
scene.add(light);
// Load in the mesh and add it to the scene.
var loader = new THREE.JSONLoader();
loader.load( "http://www.amdesigngroup.com/clients/AM_6292_Learning/models/circle.json", function(geometry){
var material = new THREE.MeshLambertMaterial({color: 0x55B663});
mesh = new THREE.Mesh(geometry, material);
mesh.translation = THREE.GeometryUtils.center(geometry);
/*mesh.rotation.x = 0;*/
scene.add(mesh);
animate(mesh);
});
// Add OrbitControls so that we can pan around with the mouse.
controls = new THREE.OrbitControls(camera, renderer.domElement);
}
/* rotate mesh */
function animate(mesh) {
var tween = new TWEEN.Tween(mesh.rotation)
.to({ z: "-" + Math.PI/2}, 2500) // relative animation
.onComplete(function() {
// Check that the full 360 degrees of rotation,
// and calculate the remainder of the division to avoid overflow.
if (Math.abs(mesh.rotation.z)>=2*Math.PI) {
mesh.rotation.y = mesh.rotation.z % (2*Math.PI);
}
})
.start();
tween.repeat(Infinity)
}
// Renders the scene and updates the render as needed.
function run() {
// Read more about requestAnimationFrame at http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/
requestAnimationFrame(run);
TWEEN.update();
// Render the scene.
renderer.render(scene, camera);
controls.update();
}
</script>
</body>
</html>
Another option is adding cameraControls to your camera
THREE.OrbitControls: add orbitControls to your camera define a lookAt target position and allow the camera to automatically rotate constantly
camera.lookAt(scene.position);
cameraControl = new THREE.OrbitControls(camera);
cameraControl.autoRotate = true;
scene.postion is this case would be the centre of your rendering world space.
Your can adjust the speed of the rotation using
cameraControl.autoRotateSpeed = //value
I wanna control rotation speed of my model,so I try to use dat.gui to accomplish it.And I write flollows in my render script:
function render() {
group.rotation.y -= controls.rotation;
renderer.render(scene, camera);
}
controls is parameter of dat.gui.
var controls = {
rotation :-0.004,
};
var gui = new dat.GUI();
gui.add(controls, 'rotation', -0.001, 0.001);
But when I run my demo,my model disappeared!I can see my scene only.
I wanna know where errors occur,so I modify it:
function render() {
alert(controls.rotation);
group.rotation.y -= controls.rotation;
renderer.render(scene, camera);
}
I found first alert was -0.004,but the others (the second,the third,etc...)were undefined.So I guess my demo only render the first frame,because model was not loading competely,so I cannot see it.
I wanna to know why it happened,and how to fix it?
Ps:all codes follows:
<head>
<meta charset="UTF-8">
<title>ytest</title>
<script type="text/javascript" src="JSandCSS/three.js"></script>
<script type="text/javascript" src="JSandCSS/OrbitControls.js"></script>
<script type="text/javascript" src="JSandCSS/OBJLoader.js"></script>
<script type="text/javascript" src="JSandCSS/Raycaster.js"></script>
<script type="text/javascript" src="dat.gui-master/build/dat.gui.js"></script>
<script type="text/javascript" src="JSandCSS/stats.min.js"></script>
<style>
body {
/* set margin to 0 and overflow to hidden, to go fullscreen */
margin: 0;
overflow: hidden;
}
</style>
</head>
<body>
<div id="Stats-output">
</div>
<div id="WebGL-output">
</div>
<div id="form">
</div>
<div id="ui">
</div>
<script type="text/javascript">
function init() {
var stats = initStats();
var scene = new THREE.Scene();
var group = new THREE.Group;
scene.add(group);
var controls = new function() {
this.rotation = 0.004;
};
var gui = new dat.GUI();
gui.add(controls, 'rotation', 0, 0.008);
var textureLoader = new THREE.TextureLoader();
var mat = new THREE.MeshLambertMaterial({
map: textureLoader.load("model/earth/texture.jpg"),
specularMap: textureLoader.load("model/earth/specular.jpg"),
lightMap: textureLoader.load("model/earth/light.jpg")
});
var loader = new THREE.OBJLoader();
loader.load('model/earth/earth.obj',
function chuanzhi(obj) {
obj.traverse(function(child) {
if(child instanceof THREE.Mesh) {
child.material = mat;
}
});
Mesh = obj;
obj.scale.set(2, 2, 2);
group.add(obj);
objects.push(Mesh);
});
var light = new THREE.PointLight(0xffffff);
light.position.set(300, 400, 200);
light.intensity.set = 0.1;
scene.add(light);
scene.add(new THREE.AmbientLight(0x333333));
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(200, 200, 200);
camera.lookAt(scene.position);
var renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
renderer.render(scene, camera);
renderer.setClearColor(0x808080, 0.5);
document.getElementById("WebGL-output").appendChild(renderer.domElement);
var controls = new THREE.OrbitControls(camera);
controls.addEventListener('change', render);
render();
window.addEventListener('resize', handleWindowResize, false);
function render() {
stats.update();
group.rotation.y-=controls.rotation;
requestAnimationFrame(render);
renderer.render(scene, camera);
}
function handleWindowResize() {
HEIGHT = window.innerHeight;
WIDTH = window.innerWidth;
renderer.setSize(WIDTH, HEIGHT);
camera.aspect = WIDTH / HEIGHT;
camera.updateProjectionMatrix();
}
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 = init;
</script>
</body>
Have you tried to use in the render cycle
group.rotateY(controls.rotation);
for setting the geometry rotation? (I'm asumming you're rotating the geometry).
Another aproach could be the following:
var rotationAngle = 0.001;
...
var gui = new dat.GUI();
gui.add(controls, 'rotation', -5, 5).onChange(function(value){
rotationAngle = value * Math.PI / 180;
});
...
function render() {
group.rotateY(rotationAngle);
renderer.render(scene, camera);
}
I know what make this……because follows:
var controls = new THREE.OrbitControls(camera);
controls.addEventListener('change', render);
Delete that and model appeared.
Modify it as follows and it work correctly:
cameraControls = new THREE.OrbitControls(camera, renderer.domElement);
cameraControls.addEventListener('change', render);
But it still has an error:when you rotate using mouse,it rotates more and more fast^
The answer provided by #adonike worked for me.
However, I observed that whenever I move the dat.gui slider to "0", the object continues to rotate.
So I tried out a few modifications that stopped the rotation when slider is set to "0" value.
1] Setting the rotation value to a decimal value which is closest to step 1. I dont know why or how it works to explain the logic. It was dumbluck i guess.
var controls = new function() {
this.rotation = 0.9; // a value close to step 1
};
2] Setting the rotation steps to 1.(any non decimal value works)
// Setting slider steps to 1
var gui = new dat.GUI();
gui.add(controls, 'rotation', -5, 5).step(1).listen().onChange(function(value){
rotationAngle = value * Math.PI / 180;
});
This method only seemed to work when the steps are whole numbers.
How to get axis from a Three-Dimensional objects in three js?
My code is
<html>
<head>
<title>three Demo</title>
</head>
<body>
<script src="three.js"></script>
<script src="STLLoader.js"></script>
<script src="Detector.js"></script>
<script>
if (!Detector.webgl) {
Detector.addGetWebGLMessage();
}
var container;
var scene, renderer, camera, cameraTarget;
init();
animate();
function init() {
container = document.createElement('div');
document.body.appendChild(container);
var img_width = 250;
var img_height = 300;
var viewAngle = 45;
var aspectRatio = img_width / img_height;
camera = new THREE.PerspectiveCamera(viewAngle, aspectRatio, 0.1, 1000);
camera.position.set(300, 450, 300);
cameraTarget = new THREE.Vector3(0, 0, 0);
scene = new THREE.Scene();
scene.fog = new THREE.Fog(0x72645b, 2, 15);
var light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(0, 300, 300);
scene.add(light);
scene.add(new THREE.AmbientLight(0x555555));
renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setClearColor(scene.fog.color);
renderer.setSize(img_width, img_height);
document.body.appendChild(renderer.domElement);
var stl_loader = new THREE.STLLoader();
stl_loader.load("Bird_cage.stl", function (geometry) {
var material = new THREE.MeshPhongMaterial({color: 0xff5533, specular: 0x111111, shininess: 200});
var mesh = new THREE.Mesh(geometry, material);
mesh.position.set(0, -0.25, 0.6);
mesh.rotation.set(0, -Math.PI / 2, 0);
mesh.scale.set(0.5, 0.5, 0.5);
scene.add(mesh);
});
}
function animate() {
requestAnimationFrame(animate);
render();
}
function render()
{
var timer = Date.now() * 0.0005
camera.position.x = Math.cos(timer) * 3;
camera.position.z = Math.sin(timer) * 300;
camera.lookAt(cameraTarget);
renderer.render(scene, camera);
}
</script>
</body>
http://jsfiddle.net/80ozg046/
Using this html.I load stl file and convert it into three dimensional objects by using thee js.Now ,What is the problem is,I want to find X-Axis,Y-Axis and Z-Axis value.
If some suggestion to solve this problem,I must be thankful to them.
I see now the original boundingBox shows null but there's is a somewhat undocumented Helper now I think.
var helper = new THREE.BoundingBoxHelper(mesh, 0xff0000);
helper.update();
// If you want a visible bounding box
scene.add(helper);
// If you just want the numbers
console.log(helper.box.min);
console.log(helper.box.max);
http://jsfiddle.net/MasterJames/m67v5bz7/2/
Then you can take a ratio of the two BIG and small objects you want to match up before you scale.