I am new to three.js, but am just coming off of a project using Java and JMonkeyEngine, so I know my way around 3d.
My issue comes with loading a texture. I'm sure this question has come up quite a few times coming from the topics I've read, however the topics I have seen are older, and it didn't work with what I needed.
I took an example from the site and tried editing it to my own needs. I was able to load my texture fine, and it spun around just like the example....
HOWEVER, when I removed the animation from the rendering process my image poofed. I can use a regular square with color just fine, but no texture.
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - geometries</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,
user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body {
font-family: Monospace;
background-color: #000;
margin: 0px;
overflow: hidden;
}
</style>
</head>
<body>
<script src="three.min.js"></script>
<script>
var container, stats;
var camera, scene, renderer;
init();
animate();
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
camera = new THREE.PerspectiveCamera(
45, window.innerWidth / window.innerHeight, 1, 2000 );
camera.position.y = 400;
scene = new THREE.Scene();
var light, object;
scene.add( new THREE.AmbientLight( 0x404040 ) );
light = new THREE.DirectionalLight( 0xffffff );
light.position.set( 0, 1, 0 );
scene.add( light );
var map = THREE.ImageUtils.loadTexture( 'butter.jpg' );
map.wrapS = map.wrapT = THREE.RepeatWrapping;
map.anisotropy = 16;
var material =
new THREE.MeshLambertMaterial(
{ ambient: 0xbbbbbb, map: map, side: THREE.DoubleSide } );
//
object = new THREE.Mesh(
new THREE.PlaneGeometry(100, 100, 4, 4 ), material );
object.position.set( -400, 0, 0 );
scene.add( object );
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
//
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
//
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
var timer = Date.now() * 0.0001;
camera.position.x = Math.cos( timer ) * 800;
camera.position.z = Math.sin( timer ) * 800;
camera.lookAt( scene.position );
for ( var i = 0, l = scene.children.length; i < l; i ++ ) {
var object = scene.children[ i ];
object.rotation.x = timer * 5;
object.rotation.y = timer * 2.5;
}
renderer.render( scene, camera );
}
</script>
</body>
I read up something here Using textures in THREE.js stating I needed to call the render after the texture loads. Sure, no problem, but it doesn't work. I assumed this could be the case, but I think about the animation. Did it load and since the animation is constant it just loaded after a render pass and then was okay during the rest of it, or something else?
Next I saw Texture from hard disk not loading in three.js - showing black
Now the user says he cannot see anything doing all sorts of things, I haven't tried any of that, but I'm using Netbeans 8.0 and it calls from the LocalHost, and I can see the animated textures, so I'm assuming this isn't the issue.
I saw another forum like this as well, with similar answers to the 2 above."
Any thoughts to think? Hopefully it's something simple.
Thanks for the help all, hopefully this library works out great!
EDIT: I found a post here ThreeJS texture issue saying there is an issue with chrome (which I was using as the browser to test). I tried the internal netbeans browser (it just gave me an error with webgl so meh) and ie didn;t work either...
I also tried to use a loader as suggested but his method gives off an "undefined" error.
I saw another post stating R58 -> R59 had changes to thw ImageLoader, so idk :(
EDIT2: Trying out the starting example of Three.JS I cannot get the texture to work stationary or during the animation.... weird..
<html>
<head>
<title>My first Three.js app</title>
<style>canvas { width: 100%; height: 100% }</style>
</head>
<body>
<script src="three.min.js"></script>
<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 );
var geometry = new THREE.BoxGeometry(1,1,1);
var map = THREE.ImageUtils.loadTexture('butter.jpg', {}, function() {render();});
// render();
map.wrapS = map.wrapT = THREE.RepeatWrapping;
map.anisotropy = 16;
var material = new THREE.MeshLambertMaterial( { ambient: 0xbbbbbb, map: map, side: THREE.DoubleSide } );
//var material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
var cube = new THREE.Mesh( geometry, material );
scene.add( cube );
camera.position.z = 5;
function render()
{
requestAnimationFrame(render);
cube.rotation.x += 0.1;
cube.rotation.y += 0.1;
renderer.render(scene, camera);
}
render();
</script>
</body>
EDIT3: Thought about this last night as I was going to sleep, and realized today that there is no NPOT... I tried another image that was 184x184 with no luck :(
Related
I was making a sphere that can be moved by a mouse using three.js but the output is just a black screen as shown.
The code I used is:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>My first three.js app</title>
<style>
body { margin: 0; }
</style>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r79/three.min.js"></script>
<script>
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
camera.position.set( 0, 0, 50 );
camera.lookAt( 0, 0, 0 );
const renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
const geometry = new THREE.SphereGeometry( 15, 32, 16 );
const texture = new THREE.TextureLoader().load( 'https://i.imgur.com/kFoWvzw.jpg' );
const material = new THREE.MeshBasicMaterial( { map: texture } );
const sphere = new THREE.Mesh( geometry, material );
const controls = new OrbitControls( camera, renderer.domElement );
controls.mouseButtons = {
LEFT: THREE.MOUSE.ROTATE,
MIDDLE: THREE.MOUSE.DOLLY,
RIGHT: THREE.MOUSE.PAN
}
controls.update();
scene.add( sphere );
function animate()
{
requestAnimationFrame( animate );
sphere.rotation.x += 0.01;
sphere.rotation.y += 0.01;
renderer.render( scene, camera );
};
animate();
</script>
</body>
</html>
I couldn't explain why the code was unable to render the sphere. What went wrong?
Thank you!
Like the error message indicates, you are trying to use OrbitControls but it cannot be found. This is because it is not part of the core THREE.js library, but it is in the THREE.js examples directory so you need to import it separately.
You can import it through an HTML script tag like you do with THREE.js:
<script src="path/to/your/local/file/OrbitControls.js">.
Notice also that if you import it in your HTML, you should call it as
const controls = new THREE.OrbitControls(...);
as the js/ file adds the class to the THREE object.
See the docs or the source.
This is the complete code on how to move the camera on the Sphere.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>My first three.js app</title>
<style>
body { margin: 0; }
</style>
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/three#0.143/build/three.min.js"></script>
<script src=".\three.js-master\three.js-master\examples\js\controls\OrbitControls.js"></script>
<script>
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
camera.position.set( 0, 0, 50 );
camera.lookAt( 0, 0, 0 );
const renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
const geometry = new THREE.SphereGeometry( 15, 32, 16 );
const texture = new THREE.TextureLoader().load( 'https://i.imgur.com/kFoWvzw.jpg' );
const material = new THREE.MeshBasicMaterial( { map: texture } );
const sphere = new THREE.Mesh( geometry, material );
const controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.update();
scene.add( sphere );
function animate()
{
requestAnimationFrame( animate );
sphere.rotation.x += 0.01;
sphere.rotation.y += 0.01;
renderer.render( scene, camera );
};
animate();
</script>
</body>
</html>
This is the correct code on how to move the camera on the Sphere...:-)
I have tested PCL triangluation introduced here:
And from the experiment I got a .vtk file.
And I tried to render it via web browser whith three.js on windows.
It is like below:
See! There are many holes. These holes are triangles that have opposite normal vectors.
What I need is flipping those normal vectors that are opposite than others.
This way I believe I would get clean mesh image as shown below:
How can I do this?
Do I work with three.js?
Had I better work with pcl library? - the triangluation?
This is the html I tested:
<!DOCTYPE html>
<html lang="en">
<head>
<!--title>four.js webgl - loaders - vtk loader</title-->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<link type="text/css" rel="stylesheet" href="main.css">
</head>
<body>
<script type="module">
var console = (window.console = window.console || {});
import * as THREE from '../build/three.module.js';
import { TrackballControls } from './jsm/controls/TrackballControls.js';
import { VTKLoader } from './jsm/loaders/VTKLoader.js';
import { VertexNormalsHelper } from './jsm/helpers/VertexNormalsHelper.js';
let container, camera, controls, scene, renderer, vnh;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 0.01, 1e10);
camera.position.set( -1, 0, 0 );
scene = new THREE.Scene();
scene.add( camera );
// light
const hemiLight = new THREE.HemisphereLight( 0xffffff, 0x000000, 1 );
scene.add( hemiLight );
const dirLight = new THREE.DirectionalLight( 0xffffff, 0.5 );
dirLight.position.set( 2, 2, 2 );
scene.add( dirLight );
const material = new THREE.MeshLambertMaterial( { color: 0xffffff } );
const loader = new VTKLoader();
loader.load( "models/vtk/point_cloud_mesh.vtk", function ( geometry )
//loader.load( "models/vtk/point_cloud_mesh_not_smoothed.vtk", function ( geometry )
{
//geometry.applyMatrix(new THREE.Matrix4().makeScale(-1, -1,-1));
//geometry.computeFaceNormals();
//var tmp;
//console.log(geometry.index.count);
//console.log(geometry.userData);
geometry.computeVertexNormals();
const mesh = new THREE.Mesh( geometry, material );
mesh.position.set( - 0.075, 0.005, 0 );
mesh.scale.multiplyScalar( 0.2 );
scene.add( mesh );
//vnh = new VertexNormalsHelper(mesh, 0.001, 0x00ff00, 1);
//scene.add( vnh );
} );
// renderer
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container = document.createElement( 'div' );
document.body.appendChild( container );
container.appendChild( renderer.domElement );
// controls
controls = new TrackballControls( camera, renderer.domElement );
controls.minDistance = .1;
controls.maxDistance = 0.5;
controls.rotateSpeed = 5.0;
window.addEventListener( 'resize', onWindowResize );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
controls.handleResize();
}
function animate() {
requestAnimationFrame( animate );
controls.update();
//if (vnh) vnh.update();
renderer.render( scene, camera );
}
</script>
</body>
</html>
Thanks to WestLangley , I finally got a expected result as shown below:
Thank you WestLangley and Stackoverflow!!
But the question still remains. WestLangley's suggestion helps but it wouldn't be the only one solution. As you see below, some of the normal vectors are facing into the body of my hand. I believe there would be a way to make all the normal vectors face out of the body of my hand. Answers to this question still wanted...
I am trying to change the color of 3D object where intersected using color picker.I am trying with dat.gui.I want to change the color of 3d part where it gets clicked and change the selected from the colorPicker.I tried out some possible ways but it doesn't work out.Please,refer to the code I tried out. Help me out with some solution and draw my attention to where I am getting wrong. Thanks.
<!DOCTYPE html>
<html lang="en">
<head>
<title>color</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body {
font-family: Monospace;
background-color: #000;
color: #fff;
margin: 0px;
overflow: hidden;
}
</style>
</head>
<body>
<script src="three.js"></script>
<script src="OrbitControls.js"></script>
<script src="Detector.js"></script>
<script src="stats.min.js"></script>
<script src="loaders/MTLLoader.js"></script>
<script src="loaders/OBJLoader.js"></script>
<script type='text/javascript' src='DAT.GUI.min.js'></script>
<script>
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
var container, stats;
var camera, controls, scene, renderer,effectController;
var raycaster;
var objects = [];
var selectedObject,selectedPos;
var rotation;
var pos,quat;
var INTERSECTED;
var guiColor;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.z = 15;
controls = new THREE.OrbitControls( camera );
scene = new THREE.Scene();
scene.background = new THREE.Color( 0x555000 );
scene.add( camera );
// light
var dirLight = new THREE.DirectionalLight( 0xffffff );
dirLight.position.set( 200, 200, 1000 ).normalize();
camera.add( dirLight );
camera.add( dirLight.target );
var mtlLoader = new THREE.MTLLoader(); mtlLoader.setBaseUrl('assets/'); mtlLoader.setPath('assets/'); mtlLoader.load('anno.mtl', function (materials) {
materials.preload();
var objLoader = new THREE.OBJLoader();
objLoader.setMaterials(materials);
objLoader.setPath('assets/');
objLoader.load('anno.obj', function (object) {
scene.add( object );
objects.push( object );
});
});
// renderer
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
/* Controls */
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.25;
controls.enableZoom = false;
raycaster = new THREE.Raycaster();
gui = new dat.GUI();
parameters =
{
color: "#ff0000",
};
gui.add( parameters, 'reset' ).name("Reset");
guiColor = gui.addColor( parameters, 'color' ).name('Color');
container = document.createElement( 'div' );
document.body.appendChild( container );
container.appendChild( renderer.domElement );
stats = new Stats();
container.appendChild( stats.dom );
window.addEventListener( 'resize', onWindowResize, false );
renderer.domElement.addEventListener("click", onclick, false);
}
var mouse = new THREE.Vector2();
function onclick(event) {
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
raycaster.setFromCamera(mouse, camera);
var intersects = raycaster.intersectObjects(objects, true);
if (intersects.length > 0) {
INTERSECTED = intersects[0].object;
if ( INTERSECTED && INTERSECTED.material.emissive != null ){
guiColor.onChange(function(){
INTERSECTED.material.emissive.setHex(parameters.color)
});
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function animate() {
requestAnimationFrame( animate );
renderer.render( scene, camera );
stats.update();
}
</script>
</body>
</html>
I've create a little live demo with your code and a basic working solution. I'd like to highlight three important changes:
You can use the onChange() event handler in order to know when a certain dat.gui property has changed. The demo uses this feature to update the color of a selected object.
I have refactored your raycasting logic into something more simple. I've seen you've copied some code from the official three.js examples but the new code should be sufficient for your case. Besides, it's also better to update Material.color instead of Material.emissive.
If you set OrbitControls.enableDamping to true, you have to update the controls in your animation loop.
https://jsfiddle.net/btuzd23o/2/
three.js R103
I am using the basic example on three.js but am unable to interact with the object to rotate via mouse interaction. Am I missing something obvious? My desired functionality is to rotate an object (such as a box) left,right,up,down, etc. The code I am using is as follows:
<!DOCTYPE html>
<script src="scripts/three.min.js"></script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>My first Three.js app</title>
<style>
body {
margin: 0;
}
canvas {
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<script src="scripts/three.min.js"></script>
<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 );
var geometry = new THREE.BoxGeometry( 3, 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.01;
cube.rotation.y += 0.01;
renderer.render(scene, camera);
};
render();
</script>
</body>
</html>
You are missing EventListeners, your scene doesnt know about your mouse moving.
See this simple example from mr.doob on how to spin a cube with the mouse:
http://mrdoob.github.io/three.js/examples/canvas_geometry_cube.html
Similiar to the rotation on the Y-Axis (left, right) you can add rotation on the X-Axis (up, down) too.
I am just looking at the documentation on the threejs.org website and thought I would give making a sphere a shot, here is what I have quickly mocked up:
<!DOCTYPE html>
<html>
<head>
<title>Sphere</title>
<style>canvas { width: 100%; height: 100% }</style>
</head>
<body>
<script type="text/javascript" src="../../threejs/build/Three.js"></script>
<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 );
var geometry = new THREE.SphereGeometry(5, 32, 32);
var material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
var sphere = new THREE.Mesh(geometry, material);
sphere.overdraw = true;
scene.add( sphere );
camera.position.z = 5;
function render() {
requestAnimationFrame(render);
renderer.render(scene, camera);
}
render();
</script>
</body>
</html>
Trouble I see no sphere, there are no errors in the console either...could someone help with this one.
Seems like the camera is at the edge of the sphere. Try camera.position.z = 20;.