I am trying to make the page display either a green or a brown floor using three.js depending on the selection from a drop down list. However, I see that the floor images do not change although control does go to the function.
JS fiddle here (I could not upload images though)
The code is below.
<!DOCTYPE html>
<html>
<head>
<title>Floor change</title>
<style>
body {
margin: 0;
overflow: hidden;
}
</style>
</head>
<script>
// global variables
var renderer;
var scene;
var camera;
var container;
//controls
var controls;
//html elements
var colorselection = "green";
function init() {
var SCREEN_WIDTH = window.innerWidth, SCREEN_HEIGHT = window.innerHeight;
SCREEN_WIDTH-=200;
// SCREEN_HEIGHT -= 100;
// create a scene, that will hold all our elements such as objects, cameras and lights.
scene = new THREE.Scene();
// create a camera, which defines where we're looking at.
camera = new THREE.PerspectiveCamera(45, SCREEN_WIDTH / SCREEN_HEIGHT, 0.1, 1000);
// create a render, sets the background color and the size
renderer = new THREE.WebGLRenderer();
renderer.setClearColor(0x000000, 1.0);
renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
// position and point the camera to the center of the scene
camera.position.x = 0;
camera.position.y = 30;
camera.position.z = 40;
camera.lookAt(scene.position);
// add the output of the renderer to the html element
document.body.appendChild(renderer.domElement);
// attach div element to variable to contain the renderer
container = document.getElementById( 'ThreeJS' );
// attach renderer to the container div
container.appendChild( renderer.domElement );
}
function floor()
{
///////////
// FLOOR //
///////////
if(colorselection == "green")
var floorTexture = new THREE.ImageUtils.loadTexture( 'green.jpg' );
else if(colorselection == "brown")/*go with 2 for now*/
var floorTexture = new THREE.ImageUtils.loadTexture( 'brown.png' );
floorTexture.wrapS = floorTexture.wrapT = THREE.RepeatWrapping;
floorTexture.repeat.set( 20, 20 );
// DoubleSide: render texture on both sides of mesh
var floorMaterial = new THREE.MeshBasicMaterial( { map: floorTexture, side: THREE.DoubleSide } );
var floorGeometry = new THREE.PlaneGeometry(110, 110, 1, 1);
var floor = new THREE.Mesh(floorGeometry, floorMaterial);
floor.position.y = -0.5;
floor.rotation.x = Math.PI / 2;
scene.add(floor);
animate();
}
//scheduler loop
function animate() {
renderer.render(scene,camera)
requestAnimationFrame(animate)
}
function myfunction()
{
colorselection = document.getElementById("mydropdownlist").value;
console.log("clicked on '"+ colorselection + "'")
floor();
}
// calls the init function when the window is done loading.
window.onload = init;
</script>
<body>
<script src="js/Three.js"></script>
<div id="ThreeJS" style="z-index: 1; position: absolute; left:0px; top:0px"></div>
<select id="mydropdownlist" onchange="myfunction()">
<option value="green">green</option>
<option value="brown">brown</option>
</select>
</body>
<style>
#mydropdownlist
{
position:absolute;
left:1200px;
top:20px
}
</style>
</html>
I have uploaded the images brown.png and green.jpg used above.
I copied your code to a local .html file, put it in the example directory for 3js, stuck the pictures there, and then updated the path to three.js to the default one
src="../build/Three.js"
and ran it in chrome. It worked, the floor colors changed when i used the drop-down. It also works in firefox.
I do see a problem however. You add the new floor mesh each time to the scene, but do not remove the old one. I expect to see a scene.remove(floor) before you make a new one so you dont get a bunch piled up in the scene. I also noticed that you have a function called floor and a variable called floor which can cause confusion.
Also, if you are using chrome, you need to use --disable-web-security as a command-line switch if you want to see the textures when the files are on your local drive instead of a web-server.
<!DOCTYPE html>
<html>
<head>
<title>Floor change</title>
<style>
body {
margin: 0;
overflow: hidden;
}
</style>
</head>
<script>
// global variables
var renderer;
var scene;
var camera;
var container;
var floormesh=null;
//controls
var controls;
//html elements
var colorselection = "green";
function init() {
var SCREEN_WIDTH = window.innerWidth, SCREEN_HEIGHT = window.innerHeight;
SCREEN_WIDTH-=200;
// SCREEN_HEIGHT -= 100;
// create a scene, that will hold all our elements such as objects, cameras and lights.
scene = new THREE.Scene();
// create a camera, which defines where we're looking at.
camera = new THREE.PerspectiveCamera(45, SCREEN_WIDTH / SCREEN_HEIGHT, 0.1, 1000);
// create a render, sets the background color and the size
renderer = new THREE.WebGLRenderer();
renderer.setClearColor(0x000000, 1.0);
renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
// position and point the camera to the center of the scene
camera.position.x = 0;
camera.position.y = 30;
camera.position.z = 40;
camera.lookAt(scene.position);
// add the output of the renderer to the html element
document.body.appendChild(renderer.domElement);
// attach div element to variable to contain the renderer
container = document.getElementById( 'ThreeJS' );
// attach renderer to the container div
container.appendChild( renderer.domElement );
}
function floor()
{
///////////
// FLOOR //
///////////
if(colorselection == "green")
var floorTexture = new THREE.ImageUtils.loadTexture( 'green.jpg' );
else if(colorselection == "brown")/*go with 2 for now*/
var floorTexture = new THREE.ImageUtils.loadTexture( 'brown.png' );
floorTexture.wrapS = floorTexture.wrapT = THREE.RepeatWrapping;
floorTexture.repeat.set( 20, 20 );
// DoubleSide: render texture on both sides of mesh
var floorMaterial = new THREE.MeshBasicMaterial( { map: floorTexture, side: THREE.DoubleSide } );
var floorGeometry = new THREE.PlaneGeometry(110, 110, 1, 1);
if(floormesh)
scene.remove(floormesh);
floormesh = new THREE.Mesh(floorGeometry, floorMaterial);
floormesh.position.y = -0.5;
floormesh.rotation.x = Math.PI / 2;
scene.add(floormesh);
animate();
}
//scheduler loop
function animate() {
renderer.render(scene,camera)
requestAnimationFrame(animate)
}
function myfunction()
{
colorselection = document.getElementById("mydropdownlist").value;
console.log("clicked on '"+ colorselection + "'")
floor();
}
// calls the init function when the window is done loading.
window.onload = init;
</script>
<body>
<script src="../build/Three.js"></script>
<div id="ThreeJS" style="z-index: 1; position: absolute; left:0px; top:0px"></div>
<select id="mydropdownlist" onchange="myfunction()">
<option value="green">green</option>
<option value="brown">brown</option>
</select>
</body>
<style>
#mydropdownlist
{
position:absolute;
left:1200px;
top:20px
}
</style>
</html>
Related
I try to do a 3D animation with Three.js controls. During the execution of my code in Firefox, a have this error :
EDIT
SyntaxError: import declarations may only appear at top level of a module
And here is my code, simplified :
<!DOCTYPE html>
<head>
<title>Three.js Test</title>
<style>
body { margin: 0; }
canvas { width: 100%; height: 100%;};
</style>
</head>
<body>
<script src="js/three.js"></script>
<script src="js/OrbitControls.js"></script>
<script type="module">
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75,window.innerWidth / window.innerHeight, 0.1, 1000);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
//keep the scene in center of the page
window.addEventListener('resize', function() {
var width = window.innerWidth;
var height = window.innerHeight;
renderer.setSize(width,height);
//prevent distortion
camera.aspect = width / height;
camera.updateProjectionMatrix();
});
controls = new THREE.OrbitControls(camera, renderer.domElement);
// create the shape
var geometry = new THREE.BoxGeometry( 1, 1, 1 );
var material = new THREE.MeshBasicMaterial( { color: 0xFF0080 } );
var cube = new THREE.Mesh( geometry, material );
scene.add( cube );
camera.position.z = 5;
function animate()
{
requestAnimationFrame( animate );
/*cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
cube.rotation.z += 0.01;*/
renderer.render( scene, camera );
}
animate();
</script>
</body>
</html>
I don't understand where the error came from and I don't know how to fix it.
I now run my code on a wamp server.
Thanks for your help !
import * as THREE from './jsthree.module.js';
It seems there is a typo. It should be ./js/three.module.js.
In any event, ensure to run your code on a local web server in order to avoid any security issues. More information about this topic in the following guide:
https://threejs.org/docs/index.html#manual/en/introduction/How-to-run-things-locally
I am starting with three.js. And now I find an issue and need help. Look simple but I don't find a good answer. The problem is: Even declaring the use of OrbitControls.js (CODE1), Even if it's showed in THREE tree at DOM (Figure 1). When I try to use the constructor (CODE 2) I am receiving the error:" TypeError: THREE.OrbitControls is not a constructor" FIGURE2.
CODE1 :***index.html***
<html>
<head>
<title>My first three.js app</title>
<style>
body { margin: 0; }
canvas { width: 100%; height: 100% }
</style>
</head>
<body>
<script src="js/libs/three.min.js"></script>
<script src="js/cena.js"></script>
<script src="js/libs/AxisHelper.js"></script>
<script src="js/libs/GridHelper.js"></script>
<script src="js/libs/OrbitControls.js"></script>
</script>
</body>
</html>
CODE2***:cena.js***
var cena = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
var renderizador = new THREE.WebGLRenderer({antialias:true});
renderizador.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderizador.domElement );
//----------------------------
var geometry = new THREE.BoxGeometry( 3, 1, 2 );
var material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
var cube = new THREE.Mesh( geometry, material );
var axisHelper = new THREE.AxisHelper( 5 );
cena.add( axisHelper )
var tamanho = 10;
var elementos = 10;
var grid = new THREE.GridHelper(tamanho,elementos);
cena.add(grid);
cena.add( cube );
camera.position.z = 10;
camera.position.y = 10;
camera.position.x = 5;
var lookat_vector = new THREE.Vector3(0,0,0);
camera.lookAt(lookat_vector);
//++++++++++++++++++++++++++++++++++++++++++++++++++++++
var controle = new THREE.OrbitControls(camera, renderizador.domElement);
var render = function () {
requestAnimationFrame( render );
controle.update();
cube.rotation.x += 0.01;
cube.rotation.y +=0.01;
cube.rotation.z +=0.03;
renderizador.render(cena, camera);
//controle.update();
};
render();
You need to include the libs and put your cena.js script at the end.
Script tags are loaded synchronously.
<script src="js/libs/three.min.js"></script>
<script src="js/libs/AxisHelper.js"></script>
<script src="js/libs/GridHelper.js"></script>
<script src="js/libs/OrbitControls.js"></script>
<script src="js/cena.js"></script>
you need to include OBJLoader.js in the script tags prior to creating THREE.OrbitalControls.
I am trying to create folding effect like folding a paper in half.
I am using Three.js Library to help me manipulate the image.
I have created 2 face paper using 2 PlaneGeometry and loaded on them texture with ImageUtils.loadTexture.
I am curious if there is a way to split the image in half and then rotate one half on his edge so you create the folding effect.
I guess this can be done since the create plane function THREE.PlaneGeometry(width, height, widthSegments, heightSegments); has widthSegments and heightSegments parameters.
<html>
<head>
<title>My first Three.js app</title>
<style>
body {
background-color: #ffffff;
margin: 0px;
overflow: hidden;
}
container {
background-color: #ffffff;
}
</style>
</head>
<body>
<div id="container" ></div>
<script src="three.min.js"></script>
<script src="OrbitControls.js"></script>
<script src="stats.min.js"></script>
<script>
var renderer, scene, camera, card;
var container, stats;
init();
animate();
function init() {
container = document.getElementById('container');
// renderer
renderer = new THREE.WebGLRenderer();
renderer.setClearColor(0xffffff, 1.0);
renderer.setSize(window.innerWidth, window.innerHeight);
container.appendChild(renderer.domElement);
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
container.appendChild(stats.domElement);
// scene
scene = new THREE.Scene();
// camera
camera = new THREE.PerspectiveCamera(40, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.z = 300;
controls = new THREE.OrbitControls(camera, container);
camera.lookAt(scene.position);
// geometry
var geometry1 = new THREE.PlaneGeometry(90, 110, 3, 1);
var geometry2 = new THREE.PlaneGeometry(90, 110, 3, 1);
geometry2.applyMatrix(new THREE.Matrix4().makeRotationY(Math.PI));
// textures
var textureFront = new THREE.ImageUtils.loadTexture('Flyer2pag1.png'); // Flyer has image sorce in project folder
var textureBack = new THREE.ImageUtils.loadTexture('Flyer2pag2.png');
// material
var material1 = new THREE.MeshBasicMaterial({ color: 0xffffff, map: textureFront });
var material2 = new THREE.MeshBasicMaterial({ color: 0xffffff, map: textureBack });
// card
card = new THREE.Object3D();
scene.add(card);
// mesh
var mesh1 = new THREE.Mesh(geometry1, material1);
card.add(mesh1);
var mesh2 = new THREE.Mesh(geometry2, material2);
card.add(mesh2);
}
function animate() {
requestAnimationFrame(animate);
//card.rotation.y += 0.01;
stats.update();
renderer.render(scene, camera);
}
</script>
</body>
</html>
For some reason with this code it will not call 'createScene();' in index.html. I'm probably overlooking something very simple as I'm new to JS but I haven't been able to find anything.
index.html
<html>
<head>
<title>Pallidity</title>
<script type = "text/javascript" src="Javascript/scene.js"></script>
<style type ="text/css">
BODY
{
Margin: 0;
}
canvas
{
width: 100%;
height:100%;
}
</style>
</head>
<body>
<script type="text/javascript">
createScene();
</script>
</body>
scene.js:
function createScene(){
<script src="Libraries/three.min.js"></script>
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
//Bare minmum to render
var geometry = new THREE.BoxGeometry( 1, 1, 1 );
var material = new THREE.MeshBasicMaterial( { color: 0x045f00 } );
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();
}
You have an html element (a script tag) as the first line of you createScene function. This is not valid JavaScript, therefore that function essentially does not exist. That's why it is not defined.
You probably want this line in your HTML file right before your scene.js script tag.
i have an instance of dat.GUI. I added a "comboBox" to that instance to make a selection of possible values. When i run my app, the dat.GUI appears with the comboBox but there is a problem: I cannot change it's default value (my gui is frozen), here is my code:
<html>
<head>
<title>Stack Overflow</title>
<style>
body { margin: 0; }
canvas { width: 100%; height: 100% }
</style>
</head>
<body>
<div id="container"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="js/three.min.js"></script>
<script src="js/optimer_regular.typeface.js"></script>
<script src="js/TrackballControls.js"></script>
<script src="js/stats.min.js"></script>
<script src="js/threex.dynamictexture.js"></script>
<script src="js/dat.gui.min.js"></script>
<script>
//Basic Three components
var scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000 );
//position camera
camera.position.z = 700;
//Set camera controls
var controls = new THREE.TrackballControls( camera );
controls.rotateSpeed = 1.0;
controls.zoomSpeed = 1.2;
controls.panSpeed = 0.8;
controls.noZoom = false;
controls.noPan = false;
controls.staticMoving = true;
controls.dynamicDampingFactor = 0.3;
controls.keys = [ 65, 83, 68 ];
//Set the renderer
var renderer = new THREE.WebGLRenderer( { antialias: false } );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
//Set the lights
var light;
scene.add( new THREE.AmbientLight( 0x404040 ) );
light = new THREE.DirectionalLight( 0xffffff );
light.position.set( 0, 1, 1 );
scene.add( light );
//GUI
initGUI();
//Let's add a cube
var geometry = new THREE.BoxGeometry( 50, 50, 50 );
var material = new THREE.MeshBasicMaterial( { color: 0x5484d3 } );
var cube = new THREE.Mesh( geometry, material );
cube.position.set(0,20,50)
scene.add( cube );
function initGUI(){ //HERE IS THE MEAT, I THINK
var LevelView = function() {
this.level = 'Operacion';
// Define render logic ...
};
var gui = new dat.GUI();
var text = new LevelView();
gui.add(text, 'level', [ 'Operacion', 'Procesos', 'Participantes', 'Fuentes de Datos', 'Logica de software', 'Telecomunicaciones', 'Infraestructura'] ).onChange(function(value){
this.level = value;
});
}
function animate() {
requestAnimationFrame( animate );
render();
}
//Render scene
function render() {
controls.update();
renderer.render( scene, camera );
}
animate();
</script>
</body>
</html>
¿What i am doing wrong? I need to be able to change values with my GUI.
Solution: If you use a mouse-controlled camera with three.js, you have to comment the following line in the MouseListener of the mouseDown action:
event.preventDefault();
Place div containing dat.gui element bellow Three.js div
<div id="ThreeJS" style="position: absolute; left:0px; top:0px"></div>
and then dat.gui
<div id="gui"></div>