I've started looking at THREE.js and have built a basic rotating globe based on some examples out there. I'm trying to add orbital controls but not having any luck. I keep getting the following error in the console log
Uncaught TypeError: _threeJs2.default.OrbitControls is not a function
the code is below
var posX = 200;
var posY = 400;
var posZ = 1800;
var width = document.getElementById('main').getBoundingClientRect().width;
var height = 600;
var FOV = 45;
var NEAR = 2;
var FAR = 4000;
var clock=new THREE.Clock();
var rotationSpeed = 0.02;
var controls;
// some global variables and initialization code
// simple basic renderer
var renderer = new THREE.WebGLRenderer();
renderer.setSize(width,height);
renderer.setClearColor( 0xfff1e0, 1);
// add it to the target element
var globeDiv = document.getElementById("globeDiv");
globeDiv.appendChild(renderer.domElement);
// setup a camera that points to the center
var camera = new THREE.PerspectiveCamera(FOV,width/height,NEAR,FAR);
camera.position.set(posX,posY, posZ);
camera.lookAt(new THREE.Vector3(0,0,0));
// create a basic scene and add the camera
var scene = new THREE.Scene();
scene.add(camera);
//spotlight set up in the same location as the camera
var light = new THREE.DirectionalLight(0xffffff, 1.0, 200 );
light.position.set(posX,posY,posZ);
scene.add(light);
//Add Earth
var earthGeo=new THREE.SphereGeometry(650,60,60);
var earthMat=new THREE.MeshPhongMaterial();
earthMat.map=THREE.ImageUtils.loadTexture("images/world.jpg");
earthMat.bumpMap=THREE.ImageUtils.loadTexture("images/bumpmap.jpg");
earthMat.bumpScale=12;
earthMat.shininess=4
var earthObject = new THREE.Mesh(earthGeo,earthMat);
scene.add(earthObject);
//Add clouds
var cloudGeo=new THREE.SphereGeometry(650,60,60);
var cloudsMat=new THREE.MeshPhongMaterial({
opacity: 0.17,
transparent: true,
color: 0xffffff
});
cloudsMat.map=THREE.ImageUtils.loadTexture("images/clouds.png");
var meshClouds = new THREE.Mesh( cloudGeo, cloudsMat );
meshClouds.scale.set(1.015, 1.015, 1.015 );
scene.add( meshClouds );
render();
function render() {
var timer = Date.now() * 0.0001;
camera.position.x=(Math.cos(timer)*1800);
camera.position.z=(Math.sin(timer)*1800);
camera.lookAt( scene.position );
light.position.x = (Math.cos(timer)*1800);
light.position.z = (Math.sin(timer)*1800) ;
light.lookAt(scene.position);
renderer.render(scene,camera);
requestAnimationFrame(render );
}
controls = new THREE.OrbitControls(camera);
controls.addEventListener( 'change', render );
Any help appreciated. I'd also welcome any suggestions on good books or tutorial on this. I'd be interested in knowing how well it integrates with d3 if anyone has experience.
Many thanks
You have to include the OrbitControls script before you can use it:
<script type="text/javascript" src="js/controls/OrbitControls.js"></script>
Also, you dont need the EventListener when you are continuosly rendering the scene anyways.
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 want to show a simple plane and a simple cube but the plane hides the cube, the cube is located between the camera and the plane, but the plane "hides" the cube.
This is my scene without plane:
and here it is with the plane added:
I am pretty sure they are in a location where the cube should to be showed.
Here is my code:
var scene = new THREE.Scene(),
camera = new THREE.PerspectiveCamera(45,Window.innerWidth,window.innerHeight,0.1,1000),
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.shadowMapEnabled = true;
renderer.shadowMapSoft = true;
var axes = new THREE.AxisHelper(20);
scene.add(axes);
var cubeGeometry = new THREE.CubeGeometry(4,4,4);
var cubeMaterial = new THREE.MeshBasicMaterial({color:0x777777});
var cube = new THREE.Mesh(cubeGeometry,cubeMaterial);
//cube.castShadow = true;
cube.position.x = 0;
cube.position.y = 10;
cube.position.z = 5;
scene.add(cube);
var planeGeometry = new THREE.PlaneGeometry(60,20);
var planeMaterial = new THREE.MeshBasicMaterial({color: 0x55cc88});
var plane = new THREE.Mesh(planeGeometry,planeMaterial);
plane.rotation.x = -0.5*Math.PI;
plane.position.x = 15;
plane.position.y = 0;
plane.position.z = 0;
//scene.add(plane);
//plane.receiveShadow = true;
camera.position.x = -30;
camera.position.y = 40;
camera.position.z = 30;
camera.lookAt(scene.position);
var spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(-40,60,-10);
scene.add(spotLight);
//renderer.setClearColor(0xEEEEEE,1);
renderer.setSize(window.innerWidth,window.innerHeight);
renderer.render(scene,camera);
$("#WebGl-salida").append(renderer.domElement);
Pay attention to names of objects and order and correctness of parameters in methods:
camera = new THREE.PerspectiveCamera(45,Window.innerWidth,window.innerHeight,0.1,1000)
should be like:
camera = new THREE.PerspectiveCamera(45,window.innerWidth / window.innerHeight,0.1,1000)
jsfiddle example
Many thanks! Both for the answer and for the suggestion to edit the question to make it more understandable (my English has to improve) Now it is working perfectly.
I am working in a ruby on rails project with three.js. I installed the corresponding gem and it seems to work just fine. But somehow the javascript still throws the following Error:
Uncaught ReferenceError: THREE is not defined
on the Line:
renderer = new THREE.WebGLRenderer();
The weird thing is that my program seems to be working. My object gets displayed.
my javscript file looks like this:
// set size to the size of the containing box
var box = document.getElementById('player');
if(box){
var boxSize = box.clientWidth;
}
var a = 0.05;
// set some camera attributes
var VIEW_ANGLE = 45,
ASPECT = 1,
NEAR = 0.1,
FAR = 10000;
var camera, scene, renderer;
var $player;
var char, materialChar ;
init();
animate();
function init() {
renderer = new THREE.WebGLRenderer();
camera = new THREE.PerspectiveCamera( 75, 1, 0.1, 10000 );
camera.position.y = 10;
camera.position.z = 20;
scene = new THREE.Scene();
// get the DOM element to attach to
// - assume we've got jQuery to hand
$player = $('#player');
// attach the render-supplied DOM element
$player.append(renderer.domElement);
// create the character
initChar();
// create a point light
addLight();
scene.add(camera);
// draw!
renderer.setSize(boxSize, boxSize);
renderer.render(scene, camera);
renderer.shadowMap.enabled = true;
document.getElementById("player").addEventListener("click", zoom);
}
function addLight(){
var dirLight = new THREE.DirectionalLight(0xffffff, 1);
dirLight.position.set(100, 100, 50);
scene.add(dirLight);
var ambLight = new THREE.AmbientLight(0x404040);
scene.add(ambLight);
var bluePoint = new THREE.PointLight(0x0033ff, 3, 150);
bluePoint.position.set( 70, 5, 70 );
scene.add(bluePoint);
scene.add(new THREE.PointLightHelper(bluePoint, 3));
var greenPoint = new THREE.PointLight(0x33ff00, 1, 150);
greenPoint.position.set( -70, 5, 70 );
scene.add(greenPoint);
scene.add(new THREE.PointLightHelper(greenPoint, 3));
}
function initChar(){
var textureLoader = new THREE.TextureLoader();
var texture = textureLoader.load('<%= asset_path 'grey.jpg' %>');
materialChar = new THREE.MeshBasicMaterial({
map: texture
});
var loader = new THREE.JSONLoader();
loader.load('<%= asset_path 'standard-male-figure2.json' %>', function(geometry){
char = new THREE.Mesh( geometry, materialChar );
scene.add(char);
});
}
function animate(){
requestAnimationFrame( animate );
render();
}
function render(){
//char.rotation.y += 0.05;
renderer.render( scene, camera );
}
function zoom(){
camera.position.z = camera.position.z - 10;
}
I have similar problem in Rails 4.2. I think the default jquery / Ajax gem is missing the following component. I have it linked in my erb which solved the problem. It can also be configured to precompile by using asset pipeline if you choose to.
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r79/three.min.js"></script>
I'm really struggling with this and have gone through several discussions that are not really related to my problem. If anybody can help, I would greatly appreciate.
I'm writing a html document using the three.js library. There is a scene called scaledScene as below (scaledMap and scaledScene are already defined):
scaledMap = new THREE.Mesh(
new THREE.PlaneGeometry( 1600, 1200 ),
new THREE.MeshBasicMaterial( {
map: new THREE.ImageUtils.loadTexture( 'texture/test1.png' ),
//wireframe: true,
side: THREE.DoubleSide
} )
);
scaledScene.add( scaledMap );
The scene is created by a high solution picture that's zoomed in to the highest level. Zooming is not allowed but only panning.
controls.noZoom = true;
controls.noPan = false;
I would like to get the absolute coordinates on the scene when panning. For example, if I pan to the top left corner, I'd like to get the information that the cursor or the view is located at top left corner. Is this possible? If so, how do I do it?
You want a picking ray.
A ray can be sent from the center of the viewport to the map in 3d space. this will tell you the pixel of the map that's currently at the center of the viewport.
I have created a fiddle.
The code is as follows. It disables rotation of the camera so that only panning is available. The pixel of the image that is at the center of the view port is listed below the viewport. Remember that threejs uses cartesian space. So an image that is 150px / 150px will report pixels from -75 to 75. So if both of your x is negative and your y is positive, then you know you're viewing the top left portion of the image.
The fiddle: http://jsfiddle.net/v1g64zkb/
var width = 400;
var height = 300;
var aspect = width/height;
var near = 1;
var far = 1000;
var angle = 45;
var createRenderer = function(){
var renderer = new THREE.WebGLRenderer();
renderer.setSize(width,height);
return renderer;
}
var camera;
var createCamera = function(){
camera = new THREE.PerspectiveCamera(
angle, aspect, near, far);
camera.position.set( 0, 0, 100 );
camera.lookAt(new THREE.Vector3( 0, 0, 0 ));
return camera;
}
var createScene = function(){
var scene = new THREE.Scene();
return scene;
}
var createControls = function(camera){
var controls = new
THREE.OrbitControls(camera);
controls.rotateSpeed = 0;
controls.zoomSpeed = 1.2;
controls.panSpeed = 0.8;
controls.noZoom = true;
controls.noPan = false;
return controls;
}
var createLight = function(){
var light = new THREE.PointLight(0xFFFFFF);
light.position.x=0;
light.position.y=0;
light.position.z=100;
return light;
}
var scene = createScene();
var camera = createCamera();
var controls = createControls(camera);
var light = createLight();
var renderer = createRenderer();
scene.add(light);
scaledMap = new THREE.Mesh(
new THREE.PlaneGeometry( 150, 150 ),
new THREE.MeshBasicMaterial( {
map: new THREE.ImageUtils.loadTexture( '../img/logo.png' ),
color:0xFFFFFF,
side: THREE.DoubleSide
} )
);
scene.add( scaledMap );
var raycaster = new THREE.Raycaster();
var cameraPosition = new THREE.Vector2();
cameraPosition.x = 0;
cameraPosition.y = 0;
console.log(cameraPosition)
var render = function(){
renderer.render(scene,camera);
raycaster.setFromCamera( cameraPosition, camera );
var intersects = raycaster.intersectObjects( scene.children );
if(intersects[0] != undefined){
$("#output").html(intersects[0].point.x.toFixed(2)+" "+intersects[0].point.y.toFixed(2));
}
renderer.render( scene, camera );
}
controls.addEventListener('change',render);
var animate = function(){
requestAnimationFrame(animate);
render();
controls.update();
}
animate();
$("#container").append(renderer.domElement);
//edit: I would not run a picking ray inside a render call. This is just a simplified example. Use the controls change event or whatever to fire the picking ray.
I loaded the script in index.html but when I open the page it shows the rendered but nothing inside, nothing renderer, I can't find the problem
Here is the code of external .js:
var wdt = $('.design').width();
var hgh = $('.design').height();
var scene = new THREE.Scene();
var camera = new THREE.Camera(75, wdt/hgh, 0.1, 1000);
var renderer = new THREE.WebGLRenderer({ alpha: true });
renderer.setSize(wdt, hgh);
document.getElementById('designer').appendChild(renderer.domElement);
var geometry = new THREE.CubeGeometry(1,1,1);
var material = new THREE.MeshBasicMaterial({color: 0x00ff00});
var cube = new THREE.Mesh(geometry, material);
scene.add(cube);
camera.position.z = 5;
var render = function () {
requestAnimationFrame(render);
cube.rotation.x += 0.1;
cube.rotation.y += 0.1;
renderer.render(scene, camera);
};
render();
Can anybody help please?
Camera issues
Here's a jsfiddle of a working version.
Camera in Three.js is abstract, so I picked the common one to construct:
var camera = new THREE.PerspectiveCamera (75, wdt / hgh, 0.1, 1000);
The camera's viewpoint doesn't line up by default, so explicit calls eliminate confusion:
camera.lookAt(cube.position);
And adding the camera to the scene:
scene.add(camera);