I'm reading a book "Learning Three.js - The JavaScript 3D Library for WebGL - 2nd Edition" and first example in book which is not working at all.
Can someone please give me a direction why? I'd tried with "How can I enable WebGL in my browser?" and it didn't help. But examples on three.js / examples are working as they should.
I've extracted three.js and put example bellow in build folder where three.js is located.
Do I need local web server to test WebGL?
Now I try to debug and code in Visual Code. Any other recommendations?
<html>
<head>
<title>Example 01.02 - First Scene</title>
<script type="text/javascript" src="three.js"></script>
<style>
body {
/* set margin to 0 and overflow to hidden, to go fullscreen */
margin: 0;
overflow: hidden;
}
</style>
</head>
<body>
<!-- Div which will hold the Output -->
<div id="WebGL-output">
</div>
<!-- Javascript code that runs our Three.js examples -->
<script type="text/javascript">
// once everything is loaded, we run our Three.js stuff.
function init() {
// 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(45, window.innerWidth / window.innerHeight, 0.1, 1000);
// create a render and set the size
var renderer = new THREE.WebGLRenderer();
renderer.setClearColorHex();
renderer.setClearColor(new THREE.Color(0xEEEEEE));
renderer.setSize(window.innerWidth, window.innerHeight);
// show axes in the screen
var axes = new THREE.AxisHelper(20);
scene.add(axes);
// create the ground plane
var planeGeometry = new THREE.PlaneGeometry(60, 20);
var planeMaterial = new THREE.MeshBasicMaterial({color: 0xcccccc});
var plane = new THREE.Mesh(planeGeometry, planeMaterial);
// rotate and position the plane
plane.rotation.x = -0.5 * Math.PI;
plane.position.x = 15;
plane.position.y = 0;
plane.position.z = 0;
// add the plane to the scene
scene.add(plane);
// create a cube
var cubeGeometry = new THREE.BoxGeometry(4, 4, 4);
var cubeMaterial = new THREE.MeshBasicMaterial({color: 0xff0000, wireframe: true});
var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
// position the cube
cube.position.x = -4;
cube.position.y = 3;
cube.position.z = 0;
// add the cube to the scene
scene.add(cube);
// create a sphere
var sphereGeometry = new THREE.SphereGeometry(4, 20, 20);
var sphereMaterial = new THREE.MeshBasicMaterial({color: 0x7777ff, wireframe: true});
var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
// position the sphere
sphere.position.x = 20;
sphere.position.y = 4;
sphere.position.z = 2;
// add the sphere to the scene
scene.add(sphere);
// position and point the camera to the center of the scene
camera.position.x = -30;
camera.position.y = 40;
camera.position.z = 30;
camera.lookAt(scene.position);
// add the output of the renderer to the html element
document.getElementById("WebGL-output").appendChild(renderer.domElement);
// render the scene
renderer.render(scene, camera);
}
window.onload = init;
</script>
</body>
</html>
the line
renderer.setClearColorHex()
should be removed.
Here is new code with a jsfiddle (using three.js from the net):
<html>
<head>
<title>Example 01.02 - First Scene</title>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/three.js/89/three.js"></script>
<style>
body {
/* set margin to 0 and overflow to hidden, to go fullscreen */
margin: 0;
overflow: hidden;
}
</style>
</head>
<body>
<!-- Div which will hold the Output -->
<div id="WebGL-output">
</div>
<!-- Javascript code that runs our Three.js examples -->
<script type="text/javascript">
// once everything is loaded, we run our Three.js stuff.
function init() {
// 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(45, window.innerWidth / window.innerHeight, 0.1, 1000);
// create a render and set the size
var renderer = new THREE.WebGLRenderer();
//renderer.setClearColorHex();
renderer.setClearColor(new THREE.Color(0xEEEEEE));
renderer.setSize(window.innerWidth, window.innerHeight);
// show axes in the screen
var axes = new THREE.AxisHelper(20);
scene.add(axes);
// create the ground plane
var planeGeometry = new THREE.PlaneGeometry(60, 20);
var planeMaterial = new THREE.MeshBasicMaterial({
color: 0xcccccc
});
var plane = new THREE.Mesh(planeGeometry, planeMaterial);
// rotate and position the plane
plane.rotation.x = -0.5 * Math.PI;
plane.position.x = 15;
plane.position.y = 0;
plane.position.z = 0;
// add the plane to the scene
scene.add(plane);
// create a cube
var cubeGeometry = new THREE.BoxGeometry(4, 4, 4);
var cubeMaterial = new THREE.MeshBasicMaterial({
color: 0xff0000,
wireframe: true
});
var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
// position the cube
cube.position.x = -4;
cube.position.y = 3;
cube.position.z = 0;
// add the cube to the scene
scene.add(cube);
// create a sphere
var sphereGeometry = new THREE.SphereGeometry(4, 20, 20);
var sphereMaterial = new THREE.MeshBasicMaterial({
color: 0x7777ff,
wireframe: true
});
var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
// position the sphere
sphere.position.x = 20;
sphere.position.y = 4;
sphere.position.z = 2;
// add the sphere to the scene
scene.add(sphere);
// position and point the camera to the center of the scene
camera.position.x = -30;
camera.position.y = 40;
camera.position.z = 30;
camera.lookAt(scene.position);
// add the output of the renderer to the html element
document.getElementById("WebGL-output").appendChild(renderer.domElement);
// render the scene
renderer.render(scene, camera);
}
window.onload = init;
</script>
</body>
</html>
https://jsfiddle.net/90zzka64/
Related
I want to create a cylinder with slanted bottom shape in three.js.
I don't see any direct way to create such geometry in three.js. I tried to see if I can cut the cylinder by a slanted plane, but could not find such operation in the documentation. Can anybody suggest a way to create this?
You can operate with vertices as you want.
Just a simple concept:
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(0, 0, 10);
var renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var controls = new THREE.OrbitControls(camera, renderer.domElement);
var light = new THREE.DirectionalLight(0xffffff, 0.5);
light.position.setScalar(10);
scene.add(light);
scene.add(new THREE.AmbientLight(0xffffff, 0.5));
var cylGeom = new THREE.CylinderBufferGeometry(1, 1, 5, 16);
var vertices = cylGeom.attributes.position;
// change upper vertices
var v3 = new THREE.Vector3(); // temp vector
for (let i = 0; i < vertices.count; i++) {
v3.fromBufferAttribute(vertices, i); // set the temp vector
v3.y = v3.y > 0 ? (v3.x * 0.5) + 2.5 : v3.y; // change position by condition and equation
vertices.setY(i, v3.y); // set Y-component of a vertex
}
var cylMat = new THREE.MeshLambertMaterial({
color: "aqua"
});
var cyl = new THREE.Mesh(cylGeom, cylMat);
scene.add(cyl);
renderer.setAnimationLoop(() => {
renderer.render(scene, camera)
});
body {
overflow: hidden;
margin: 0;
}
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
I was doing a Three js tutorial and this code should cast shadows, but when render shadows does not exists over the plane.
What is wrong on code? I'm reading documentation and other codes and I can not find the problem.
Best regards!
EDIT:
If i make a loop with requestAnimationFrame just works... but only in that case... why?
<!DOCTYPE html>
<html>
<head>
<title>Learning THREE JS Basic</title>
<script src="../../libs/three.js"></script>
<script src="../../libs/jquery.js"></script>
<style>
body {
margin : 0;
overflow : hidden;
}
</style>
</head>
<body>
<div id="visor"></div>
<script>
$(function () {
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, 1, 1000);
var renderer = new THREE.WebGLRenderer();
renderer.setClearColor(0xEEEEEE);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
var axes = new THREE.AxisHelper(20);
scene.add(axes);
var planeGeometry = new THREE.PlaneGeometry(60, 20, 1, 1);
var planeMaterial = new THREE.MeshLambertMaterial({
color: 0xFFFFFF
});
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;
plane.receiveShadow = true;
scene.add(plane);
var cubeGeometry = new THREE.BoxGeometry(4,4,4);
var cubeMaterial = new THREE.MeshLambertMaterial({
color: 0xFF0000
});
var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
cube.position.x = -4;
cube.position.y = 3;
cube.position.z = 0;
cube.castShadow = true;
scene.add(cube);
var sphereGeometry = new THREE.SphereGeometry(4, 20, 20);
var sphereMaterial = new THREE.MeshLambertMaterial({
color: 0x7777FF
});
var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
sphere.position.x = 20;
sphere.position.y = 4;
sphere.position.z = 2;
sphere.castShadow = true;
scene.add(sphere);
var spotLight = new THREE.SpotLight(0xFFFFFF);
spotLight.position.set(-40, 60, -10);
spotLight.castShadow = true;
scene.add(spotLight);
camera.position.x = -30;
camera.position.y = 40;
camera.position.z = 30;
camera.lookAt(scene.position);
$("#visor").append(renderer.domElement);
renderer.render(scene, camera);
});
</script>
</body>
</html>
three.js r.74 and r.75 have a bug in which shadows are not always rendered in the first call to render(). This bug has been fixed in three.js r.76dev.
Your work-around is to call renderer.render( scene, camera ) a 2nd time, or to have an animation loop.
three.js r.75
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.
jsfiddle: http://jsfiddle.net/VsWb9/2151/
After a reading a few articles i am at a loss.
Rotate camera around object with Three.js
Below is simple code for a cube rotating with a floor. This should hopefully be a simple example to follow.
I am trying to add a camera so on click and drag it rotates around the scene. Similar to this http://threejs.org/examples/#misc_controls_trackball
For anyone with the same quesiton lets get you to my point below:
Download three.js here:
http://threejs.org/
You need to have something call orbit controls in your js folder. You will find a link to orbitcontrols to download here:
https://dl.dropboxusercontent.com/u/3587259/Code/Threejs/OrbitControls.js
Copy this and put it in your site folder.
You then need to link to orbit control and three.js it in your html. Like the below:
<script src="js/OrbitControls.js"></script>
<script src="js/three.min.js"></script>
Then see below for a simple wireframe cube with a floor.
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(50, window.innerWidth/window.innerHeight, 0.1, 1000);
var axisHelper = new THREE.AxisHelper( 5 );
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
//This breaks it?
//controls = new THREE.OrbitControls( camera, renderer.domElement );
var geometry = new THREE.CubeGeometry(2,1,1);
var material = new THREE.MeshBasicMaterial({wireframe: true});
var cube = new THREE.Mesh(geometry, material);
scene.add(cube);
var floorMaterial = new THREE.MeshBasicMaterial( {wireframe: true} );
var floorGeometry = new THREE.PlaneGeometry(1000, 1000, 10, 10);
var floor = new THREE.Mesh(floorGeometry, floorMaterial);
floor.position.y = -50.0;
floor.rotation.x = Math.PI / 2;
scene.add(floor);
camera.position.z = 3;
var render = function () {
requestAnimationFrame(render);
cube.rotation.z += 0.005;
cube.rotation.x += 0.005;
renderer.render(scene, camera);
};
render();
http://jsfiddle.net/wp6E3/3/
var camera, scene, renderer;
var cubes = [];
init();
animate();
function init() {
scene = new THREE.Scene();
scene.add(new THREE.AmbientLight(0x212223));
for (var i = 0; i < 10; i++) {
var cubeGeometry = new THREE.CubeGeometry(1, 1.5, 1);
var cubeMaterial = new THREE.MeshLambertMaterial({ color: 0x1ec876 });
var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
cube.position.set(i*1.2, 0, 0.5);
cube.castShadow = true;
scene.add(cube);
cubes.push(cube);
}
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 10000);
camera.position.x = -4;
camera.position.y = -4;
camera.position.z = 20;
camera.lookAt(cubes[5].position);
scene.add(camera);
var terrainGeo = new THREE.PlaneGeometry(50, 50);
var terrainMaterial = new THREE.MeshLambertMaterial({ color: 0xc0c0a0 });
var terrain = new THREE.Mesh(terrainGeo, terrainMaterial);
terrain.receiveShadow = true;
scene.add(terrain);
var light = new THREE.DirectionalLight(0xffffff, 1);
light.castShadow = true;
light.shadowCameraVisible = true;
light.position.set(-3, 1, 5);
scene.add(light);
scene.add( new THREE.DirectionalLightHelper(light, 0.2) );
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMapEnabled = true;
renderer.shadowMapSoft = false;
document.body.appendChild(renderer.domElement);
}
function animate() {
requestAnimationFrame(animate);
for (var i = 0; i < cubes.length; i++) {
cubes[i].rotation.x += 0.01 * i;
cubes[i].rotation.y += 0.02 * i;
}
renderer.render(scene, camera);
}
Why shadows doesn't work?
I've looked related questions and three.js references but don't understand what I do wrong.
Three.js shadows not working properly
How to create directional light shadow in Three.JS?
ThreeJS shadow not rendering
http://threejs.org/docs/#Reference/Lights/DirectionalLight
http://learningthreejs.com/blog/2012/01/20/casting-shadows/
First of all, add a camera controller to your scene so you can see what you are doing. Now you can rotate the camera for different views.
controls = new THREE.OrbitControls( camera, renderer.domElement );
Second, when using a jsfiddle, be sure to link to the recent version of the three.js library.
<script src="http://threejs.org/build/three.min.js"></script>
For proper resolution, is important that your shadow camera is positioned tight around your scene. You do that by setting the following:
light.shadowCameraLeft = -20; // or whatever value works for the scale of your scene
light.shadowCameraRight = 20;
light.shadowCameraTop = 20;
light.shadowCameraBottom = -20;
For directional lights, only the "direction to" the light's position matters. However, when shadow maps are involved, the actual position of the light is important, since it controls the shadow camera, too.
light.position.set( -60, 20, 100 );
Here is an updated fiddle. Rotate the camera with the mouse.
http://jsfiddle.net/wp6E3/4/
three.js r.66
Add these to your light definition:
light.shadowMapWidth =
light.shadowMapHeight = 1024;
light.shadowCameraNear = 1;
light.shadowCameraFar = 100;