Generate a mesh from points Three.js - javascript

I'm trying to generate a mesh from points. I've read here the way to generate the mesh is,
var mesh = new THREE.ConvexGeometry( vertices_array );
In this example they've declared the vertices_array like below
var vertices = new THREE.DodecahedronGeometry( 10 ).vertices;
What I need to understand is, how to define the vertices_array for points created using THREE.BufferGeometry with the code below.
Thank you very much
<!DOCTYPE html>
<html lang="en">
<head>
<title>Three.js</title>
<meta charset="utf-8">
<script src="js/three.js"></script>
<script src="js/TrackballControls.js"></script>
<script src="js/WebGL.js"></script>
<script src="js/ConvexGeometry.js"></script>
<script src="js/QuickHull.js"></script>
</head>
<body>
<script>
if ( WEBGL.isWebGLAvailable() === false ) {
document.body.appendChild( WEBGL.getWebGLErrorMessage() );
}
var camera, scene, renderer, controls;
init();
animate();
function init() {
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 45.0, window.innerWidth / window.innerHeight, 5, 3500 );
camera.position.z = 2500;
controls = new THREE.TrackballControls( camera, renderer.domElement );
createScene();
}
function createScene() {
scene = new THREE.Scene();
scene.background = new THREE.Color( 0x000000 );
var geometry = new THREE.BufferGeometry();
var positions = [];
for ( var i = 0; i < 20; i ++ ) {
for ( var j = 0; j < 20; j ++ ) {
var y = j;
var x = i;
var z = 0;
positions.push( new THREE.Vector3(x, y, z) );
//positions.push( x, y, z );
}
}
//geometry.addAttribute( 'position', new THREE.Float32BufferAttribute( positions, 3 ) );
//var material = new THREE.PointsMaterial( {color: 0xFF0000} );
//points = new THREE.Points( geometry, material );
//scene.add( points );
var meshMaterial = new THREE.MeshBasicMaterial( {color: 0xffffff,} );
var meshGeometry = new THREE.ConvexBufferGeometry( positions );
var mesh = new THREE.Mesh( meshGeometry, meshMaterial );
scene.add( mesh );
}
function animate( time ) {
requestAnimationFrame( animate );
controls.update();
renderer.render( scene, camera );
}
</script>
</body>
</html>

Related

three.js multiple images on cylinder face

I am trying to display multiple images on the outside (not the top or bottom) of a rotating cylinder using three.js. I am able to display 1 image, but my goal is to display several side by side. I have added 3 textures to my materials array, but only the first is displayed. Any help is appreciated.
<html>
<head>
<title>My first three.js app</title>
<span>Test</span>
<style>
body { margin: 0; }
canvas { width: 100%; height: 100% }
</style>
</head>
<body>
<script src="js/three.js"></script>
<script>
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 100, window.innerWidth / window.innerHeight, 0.1, 1000 );
camera.position.y = 24;
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
var diameter = 20;
var geometry = new THREE.CylinderGeometry( diameter, diameter, 15, 32 );
var texture1 = new THREE.TextureLoader().load( 'images/image1.jpg' );
var texture2 = new THREE.TextureLoader().load( 'images/image2.jpg' );
var texture3 = new THREE.TextureLoader().load( 'images/image3.png' );
texture1.wrapS = THREE.RepeatWrapping;
//texture.wrapT = THREE.RepeatWrapping;
//texture.repeat.set( 1, 4 );
var materials = [];
materials.push(new THREE.MeshBasicMaterial({ map: texture1 }));
materials.push(new THREE.MeshBasicMaterial({ map: texture2 }));
materials.push(new THREE.MeshBasicMaterial({ map: texture3 }));
var cylinder = new THREE.Mesh( geometry, materials );
cylinder.position.y = 25;
scene.add( cylinder);
camera.position.z = 40;
function render() {
requestAnimationFrame(render);
//cylinder.rotation.z += 0.05;
cylinder.rotation.y += 0.005;
renderer.render(scene, camera);
}
render();
</script>
</body>
You want to apply three textures to your cylinder.
If you don't want to merge your textures into a single texture, one easy solution is to render three cylinder wedges, each with its own texture. Use a pattern like the following:
var group = new THREE.Group();
scene.add( group );
var geometry = new THREE.CylinderBufferGeometry( 5, 5, 10, 16, 1, false, 0, 2 * Math.PI / 3 ); // 1/3 cylinder wedge
var endCapMaterial = new THREE.MeshBasicMaterial();
// mesh
mesh = new THREE.Mesh( geometry, [ new THREE.MeshBasicMaterial( { map: texture1 } ), endCapMaterial, endCapMaterial ] );
mesh.rotation.set( 0, 0, 0 );
group.add( mesh );
mesh = new THREE.Mesh( geometry, [ new THREE.MeshBasicMaterial( { map: texture2 } ), endCapMaterial, endCapMaterial ] );
mesh.rotation.set( 0, 2 * Math.PI / 3, 0 );
group.add( mesh );
mesh = new THREE.Mesh( geometry, [ new THREE.MeshBasicMaterial( { map: texture3 } ), endCapMaterial, endCapMaterial ] );
mesh.rotation.set( 0, 4 * Math.PI / 3, 0 );
group.add( mesh );
three.js r.89
Another way is to assign textures to each face of your geometry using geometry.faces[i].materialIndex property. In this case you should use the number of radial segments that is a multiple of three (if you have 3 textures).
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/89/three.min.js"></script>
<html>
<head>
<title>My first three.js app</title>
<style>
body { margin: 0; overflow:hidden;}
canvas { width: 100%; height: 100% }
</style>
</head>
<body>
<script>
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 100, window.innerWidth / window.innerHeight, 0.1, 1000 );
camera.position.y = 24;
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
var diameter = 20;
var radialSegments = 33;
var geometry = new THREE.CylinderGeometry( diameter, diameter, 15, radialSegments );
var img1 = "http://d2gg9evh47fn9z.cloudfront.net/800px_COLOURBOX9108127.jpg";
var img2 = "http://d2gg9evh47fn9z.cloudfront.net/thumb_COLOURBOX8923432.jpg";
var img3 = "http://d2gg9evh47fn9z.cloudfront.net/800px_COLOURBOX19377428.jpg";
var texture1 = new THREE.TextureLoader().load( img1 );
var texture2 = new THREE.TextureLoader().load( img2 );
var texture3 = new THREE.TextureLoader().load( img3 );
THREE.DefaultLoadingManager.onLoad = function () {
var materials = [];
materials.push(new THREE.MeshBasicMaterial({ map: texture1 }));
materials.push(new THREE.MeshBasicMaterial({ map: texture2 }));
materials.push(new THREE.MeshBasicMaterial({ map: texture3 }));
var l = geometry.faces.length;
for (var i = 0; i < l; i++) {
if (geometry.faces[i].normal.y !== 0) {
// these are caps
geometry.faces[i].materialIndex = 0;
} else {
// each segment has 2 faces
geometry.faces[i].materialIndex = Math.floor(i * 3 / (radialSegments * 2));
}
}
var cylinder = new THREE.Mesh( geometry, materials);
cylinder.position.y = 25;
scene.add( cylinder);
camera.position.z = 40;
function render() {
requestAnimationFrame(render);
cylinder.rotation.y += 0.005;
renderer.render(scene, camera);
}
render();
}
</script>
</body>

Three JS TextGeometry always facing user

This is my source code.
I'm trying to make the TextGeometry always look to the camera?It's possible?
Code:
var stats;
var camera, controls, scene, renderer;
init();
render();
function init() {
scene = new THREE.Scene();
var ambient = new THREE.AmbientLight( 0xFFFFFF );
scene.add( ambient );
var container = document.getElementById('container');
renderer = new THREE.WebGLRenderer({antialias: 1 });
renderer.shadowMap.enabled = true;
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight);
renderer.setClearColor(0x013A65);
container.appendChild( renderer.domElement );
camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 5000 );
camera.position.set(0,0,0);
controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.addEventListener( 'change', render );
controls.enableKeys = false;
controls.enableZoom = true;
controls.minDistance = 2000;
controls.maxDistance = 3500;
controls.maxPolarAngle = Math.PI/2;
// world
var onError = function ( xhr ) { };
THREE.Loader.Handlers.add( /\.dds$/i, new THREE.DDSLoader() );
var mtlLoader = new THREE.MTLLoader();
mtlLoader.setPath( './assets/3d/' );
mtlLoader.load( 'A.mtl', function( materials ) {
materials.preload();
var objLoader = new THREE.OBJLoader();
objLoader.setMaterials( materials );
mtlLoader.setPath( './assets/3d/' );
objLoader.load( './assets/3d/A.obj', function ( object ) {
object.position.x = 0;
object.position.y = 0;
object.position.z = 0;
scene.add( object );
}, onError );
});
//Text
var loader = new THREE.FontLoader();
loader.load( './fonts/Open_Sans_Regular.json', function ( font ) {
var textGeometry = new THREE.TextGeometry( "Test", {font: font, size: 22, height: 3, curveSegments: 1});var textMaterial = new THREE.MeshPhongMaterial({ color: 0xFFFFFF, specular: 0xFFFFFF });var mesh1 = new THREE.Mesh( textGeometry, textMaterial );mesh1.position.x = -200;mesh1.position.y = 250;mesh1.position.z = 725;scene.add( mesh1);});
// lights
light = new THREE.DirectionalLight( 0xFFFFFF );
light.position.set( 1, 1, 1 );
scene.add( light );
window.addEventListener( 'resize', onWindowResize, true );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function animate() {
requestAnimationFrame( animate );
stats.update();
render();
}
function render() {
renderer.render( scene, camera );
}
I already tried mesh.lookAt(camera.position) inside the render function but no sucess.
Best Regards.
I believe your question is how to make the text appear regardless of where the camera is. Instead of using text geometry you can try to put your text in a div container and make the position absolute using CSS. https://threejs.org/docs/#manual/en/introduction/Creating-text

Three.js issue creating meshes outside of loader's load() function

I had difficulty exporting more than one texture using Blender's Three.js add-on, so had planned to work around it be separating the parts into separate meshes, but then came across the unexpected problem of the code not working when I created the meshes outside of the load() function. I've supplied an example below using a single model with a single mesh. The following works fine:
<!DOCTYPE html>
<html lang="en">
<head>
<title>working</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: #000000;
margin: 0px;
overflow: hidden;
}
</style>
</head>
<body>
<script src="js/build/three.min.js"></script>
<script src="js/loaders/ColladaLoader.js"></script>
<script src="js/Detector.js"></script>
<script>
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
var container;
var camera, scene, renderer, objects;
var scaleAdj = 100;
init();
animate();
function init()
{
container = document.createElement( 'div' );
document.body.appendChild( container );
camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 20000 );
camera.position.set( 0, 500, 0 );
scene = new THREE.Scene();
scene.fog = new THREE.Fog( 0xcce0ff, 10, 10000 );
var loader = new THREE.JSONLoader();
loader.load( 'cube.json', function ( geometry, materials )
{
var faceMaterial = new THREE.MultiMaterial( materials );
for ( var i = 0; i < 250; i ++ )
{
var x = ( ( i % 27 ) - 13.5 ) * (5 * scaleAdj) + THREE.Math.randFloatSpread( 300 * scaleAdj);
var z = ( Math.floor( i / 27 ) - 13.5 ) * (5 * scaleAdj) + THREE.Math.randFloatSpread( 300 * scaleAdj);
mesh = new THREE.Mesh( geometry, faceMaterial );
var s = THREE.Math.randFloat( 0.5, 2 ) * scaleAdj;
mesh.scale.set( s, s, s );
mesh.position.set( x, scaleAdj, z );
mesh.rotation.y = THREE.Math.randFloat( -0.25, 0.25 );
mesh.matrixAutoUpdate = false;
mesh.updateMatrix();
scene.add( mesh );
}
} );
scene.add( new THREE.AmbientLight( 0xffffff ) );
// ground
var textureLoader = new THREE.TextureLoader();
var groundTexture = textureLoader.load( "texture.jpg" );
groundTexture.wrapS = groundTexture.wrapT = THREE.RepeatWrapping;
groundTexture.repeat.set( 40, 40 );
groundTexture.anisotropy = 16;
var groundMaterial = new THREE.MeshPhongMaterial( { color: 0xffffff, specular: 0x111111, map: groundTexture } );
var mesh = new THREE.Mesh( new THREE.PlaneBufferGeometry( 20000, 20000 ), groundMaterial );
mesh.position.y = 0;
mesh.rotation.x = - Math.PI / 2;
mesh.receiveShadow = true;
scene.add( mesh );
// Renderer
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( scene.fog.color );
container.appendChild( renderer.domElement );
// Events
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize( event ) {
renderer.setSize( window.innerWidth, window.innerHeight );
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
}
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
renderer.render( scene, camera );
}
</script>
</body>
</html>
But this doesn't (I've annotated which sections contain the differences):
<!DOCTYPE html>
<html lang="en">
<head>
<title>not working</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: #000000;
margin: 0px;
overflow: hidden;
}
</style>
</head>
<body>
<script src="js/build/three.min.js"></script>
<script src="js/loaders/ColladaLoader.js"></script>
<script src="js/Detector.js"></script>
<script>
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
//--------------- difference number 1
var obj_geometry;
var obj_material;
//-----------------------------------
var container;
var camera, scene, renderer, objects;
var scaleAdj = 100;
init();
animate();
function init()
{
container = document.createElement( 'div' );
document.body.appendChild( container );
camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 20000 );
camera.position.set( 0, 500, 0 );
scene = new THREE.Scene();
scene.fog = new THREE.Fog( 0xcce0ff, 10, 10000 );
//-------------------difference number 2--------------------
var loader = new THREE.JSONLoader();
loader.load( 'cube.json', function ( geometry, material )
{
obj_geometry = geometry;
obj_material = material;
});
var faceMaterial = new THREE.MultiMaterial( obj_material);
for ( var i = 0; i < 250; i ++ )
{
var x = ( ( i % 27 ) - 13.5 ) * (5 * scaleAdj) + THREE.Math.randFloatSpread( 300 * scaleAdj);
var z = ( Math.floor( i / 27 ) - 13.5 ) * (5 * scaleAdj) + THREE.Math.randFloatSpread( 300 * scaleAdj);
mesh = new THREE.Mesh( obj_geometry, faceMaterial);
var s = THREE.Math.randFloat( 0.5, 2 ) * scaleAdj;
mesh.scale.set( s, s, s );
mesh.position.set( x, 0, z );
mesh.rotation.y = THREE.Math.randFloat( -0.25, 0.25 );
mesh.matrixAutoUpdate = false;
mesh.updateMatrix();
scene.add( mesh );
}
//--------------------------------------
scene.add( new THREE.AmbientLight( 0xffffff ) );
// ground
var textureLoader = new THREE.TextureLoader();
var groundTexture = textureLoader.load( "texture.jpg" );
groundTexture.wrapS = groundTexture.wrapT = THREE.RepeatWrapping;
groundTexture.repeat.set( 40, 40 );
groundTexture.anisotropy = 16;
var groundMaterial = new THREE.MeshPhongMaterial( { color: 0xffffff, specular: 0x111111, map: groundTexture } );
var mesh = new THREE.Mesh( new THREE.PlaneBufferGeometry( 20000, 20000 ), groundMaterial );
mesh.position.y = 0;
mesh.rotation.x = - Math.PI / 2;
mesh.receiveShadow = true;
scene.add( mesh );
// Renderer
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( scene.fog.color );
container.appendChild( renderer.domElement );
// Events
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize( event ) {
renderer.setSize( window.innerWidth, window.innerHeight );
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
}
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
renderer.render( scene, camera );
}
</script>
</body>
</html>
Here is a copy of the contents of the cube.json file:
{
"uvs":[[0,0,1,0,1,1,0,1]],
"faces":[43,0,1,2,3,0,0,1,2,3,0,1,2,3,43,4,7,6,5,0,0,1,2,3,4,5,6,7,43,0,4,5,1,0,0,1,2,3,0,4,7,1,43,1,5,6,2,0,0,1,2,3,1,7,6,2,43,2,6,7,3,0,0,1,2,3,2,6,5,3,43,4,0,3,7,0,0,1,2,3,4,0,3,5],
"normals":[0.577349,-0.577349,-0.577349,0.577349,-0.577349,0.577349,-0.577349,-0.577349,0.577349,-0.577349,-0.577349,-0.577349,0.577349,0.577349,-0.577349,-0.577349,0.577349,-0.577349,-0.577349,0.577349,0.577349,0.577349,0.577349,0.577349],
"metadata":{
"generator":"io_three",
"type":"Geometry",
"normals":8,
"vertices":8,
"uvs":1,
"version":3,
"materials":1,
"faces":6
},
"vertices":[1,-1,-1,1,-1,1,-1,-1,1,-1,-1,-1,1,1,-1,0.999999,1,1,-1,1,1,-1,1,-1],
"materials":[{
"DbgName":"Material",
"colorSpecular":[0.5,0.5,0.5],
"DbgIndex":0,
"mapDiffuseWrap":["RepeatWrapping","RepeatWrapping"],
"mapDiffuse":"texture.jpg",
"shading":"phong",
"depthTest":true,
"opacity":1,
"transparent":false,
"colorDiffuse":[0.64,0.64,0.64],
"mapDiffuseAnisotropy":1,
"blending":"NormalBlending",
"depthWrite":true,
"visible":true,
"specularCoef":50,
"mapDiffuseRepeat":[1,1],
"colorEmissive":[0,0,0],
"wireframe":false,
"DbgColor":15658734
}],
"name":"CubeGeometry"
}
And here is an attached texture which could be used.
It might just be a trivial problem for some of the posters on here, and if so, thanks in advance for just letting me know what it is. If not, then the answer could be useful to a lot more people, and thanks for any help you can give on it.
You cant do this, asynchronously:
var obj_geometry; // === undefined
var myMesh = new THREE.Mesh( obj_geometry ); //because undefined, same as calling new THREE.Mesh();
obj_geometry = geometry;//does nothing, mesh has no idea about this happening
obj_material = material;
When you construct a mesh, you've given it undefined for geometry, so i think it just calls new Geometry() inside the constructor. This mesh has been created with a unique isntance of empty Geometry and has nothing to do with your obj_geometry.
The solution here is to do:
var obj_geometry = new THREE.Geometry();
var myMesh = new THREE.Mesh( obj_geometry ); //holds a reference to an empty "proxy"
then onLoad
loader.load( 'url' , function( geom ) {
obj_geometry.merge(geom); //"FILL PREVIOUSLY CREATED GEOMETRY WITH DATA"
obj_geometry.vertsNeedUpdate = true; // there's a few flags like this you need to turn on
}
OR
var myMesh = new THREE.Mesh();
loader.load( 'url', function( geom ) {
myMesh.geometry = geom; //"PUT THE JUST CREATED GEOMETRY IN THE RIGHT PLACE"
//myOtherMesh.geometry = geom; //if you have more places where this needs to end up
//myThirdMesh.geometry = geom; //gets very cumbersome
}
Both are pretty cumbersome and not very intuitive :( i really dislike this part of three.js.
Thanks to help from pailhead, pointing out the asynchronous issue I made the following modification to the code and found that it worked. Surprisingly the count that I added doesn't seem to raise above 0, but I am assuming that it was because it was quite a close run thing.
<!DOCTYPE html>
<html lang="en">
<head>
<title>asynchronous working</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: #000000;
margin: 0px;
overflow: hidden;
}
</style>
</head>
<body>
<script src="build/three.min.js"></script>
<script>
//--------------- difference number 1
var obj_geometry;
var obj_material;
var loaded = false;
//-----------------------------------
var container;
var camera, scene, renderer, objects;
var scaleAdj = 100;
init();
animate();
function init()
{
container = document.createElement( 'div' );
document.body.appendChild( container );
//-----an info display
info = document.createElement( 'div' );
info.id = "info";
info.style.position = 'absolute';
info.style.top = '10px';
info.style.width = '100%';
info.style.textAlign = 'center';
container.appendChild(info);
//-----------------
camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 20000 );
camera.position.set( 0, 500, 0 );
scene = new THREE.Scene();
scene.fog = new THREE.Fog( 0xcce0ff, 10, 10000 );
//-------------------difference number 2--------------------
var loader = new THREE.JSONLoader();
loader.load( 'cube.json', function ( geometry, material )
{
obj_geometry = geometry;
obj_material = material;
loaded = true;
});
var notLoadedCount = 0;
var processor = setInterval(function()
{
if(!loaded)
{
notLoadedCount++;
}
else
{
var faceMaterial = new THREE.MultiMaterial( obj_material);
for ( var i = 0; i < 250; i ++ )
{
var x = ( ( i % 27 ) - 13.5 ) * (5 * scaleAdj) + THREE.Math.randFloatSpread( 300 * scaleAdj);
var z = ( Math.floor( i / 27 ) - 13.5 ) * (5 * scaleAdj) + THREE.Math.randFloatSpread( 300 * scaleAdj);
mesh = new THREE.Mesh( obj_geometry, faceMaterial);
var s = THREE.Math.randFloat( 0.5, 2 ) * scaleAdj;
mesh.scale.set( s, s, s );
mesh.position.set( x, 0, z );
mesh.rotation.y = THREE.Math.randFloat( -0.25, 0.25 );
mesh.matrixAutoUpdate = false;
mesh.updateMatrix();
scene.add( mesh );
info.innerHTML= '*not loaded count = ' + notLoadedCount;
}
clearInterval(processor);
}
}, 100);
//--------------------------------------
scene.add( new THREE.AmbientLight( 0xffffff ) );
// ground
var textureLoader = new THREE.TextureLoader();
var groundTexture = textureLoader.load( "texture.jpg" );
groundTexture.wrapS = groundTexture.wrapT = THREE.RepeatWrapping;
groundTexture.repeat.set( 40, 40 );
groundTexture.anisotropy = 16;
var groundMaterial = new THREE.MeshPhongMaterial( { color: 0xffffff, specular: 0x111111, map: groundTexture } );
var mesh = new THREE.Mesh( new THREE.PlaneBufferGeometry( 20000, 20000 ), groundMaterial );
mesh.position.y = 0;
mesh.rotation.x = - Math.PI / 2;
mesh.receiveShadow = true;
scene.add( mesh );
// Renderer
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( scene.fog.color );
container.appendChild( renderer.domElement );
// Events
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize( event ) {
renderer.setSize( window.innerWidth, window.innerHeight );
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
}
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
renderer.render( scene, camera );
}
</script>
</body>
</html>
Thanks for the help with this, hopefully it helps others too. If there are any problems with this resolution that anybody notices, please let me know. Thanks.

Javascript script gives error "TypeError: n is undefined"

I have created a javascript script to do something, and mostly it worked. There are two issues I had with the script, so I planned to put a working example here on SO. However, during the 'reduction' of the code to something less complex a third error occurred, which completely made the script stop working. Here is the javascript part of the script:
var container, stats;
var camera, scene, renderer;
var group1, group2;
var mouseX = 0, mouseY = 0;
var map_width = 512;
var map_height = 512;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;
init();
animate();
function createMesh(filename) {
var geometry = new THREE.SphereGeometry( 70, 40, 40 );
var texture = new THREE.TextureLoader(filename);
texture.needsUpdate = true;
var material = new THREE.MeshBasicMaterial( { map: texture, overdraw: 0.5 } );
var mesh = new THREE.Mesh( geometry, material );
return mesh;
}
function init() {
container = document.getElementById( 'container' );
camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 2000 );
camera.position.z = 500;
scene = new THREE.Scene();
group1 = new THREE.Group();
var mesh = createMesh("textures/tree1.jpg");
group1.add( mesh );
group1.position.x = 00;
scene.add( group1 );
group2 = new THREE.Group();
var mesh = createMesh("textures/tree2.jpg");
group2.add( mesh );
group2.position.x = 250;
scene.add( group2 );
renderer = new THREE.WebGLRenderer({ alpha: true });
renderer.setClearColor( 0xffffff, 0 );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
}
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
camera.position.x += ( mouseX - camera.position.x ) * 0.05;
camera.position.y += ( - mouseY - camera.position.y ) * 0.05;
camera.lookAt( scene.position );
group1.rotation.y -= 0.005;
group2.rotation.y -= 0.015;
renderer.render( scene, camera );
}
The idea is to have several spheres with some texture on it; to try just use any image. However, when I call this code within a html I get the error
TypeError: n is undefined
all over again. The error seems to originate in THREE.js. How can I fix this error, so I see two spheres with a 'tree' texture on it...?
The body of the html code is as follows:
<body>
<div id="container"></div>
<script src="js/build/three.min.js"></script>
<script>
>> the code from above <<
</script>
</body>
This problem is caused by the following line:
var texture = new THREE.TextureLoader(filename);
The solution is to use a loader instead:
var loader = new THREE.TextureLoader();
var texture = loader.load( filename );

THREE.js rotation on loaded file

I've been playing around with this ThreeJS library for a couple of weeks now, and using inspiration from others, I've made a canvas that displays an external .stl-file.
My only problem is I can't seem to apply any transformations to it. I can move the camera around just fine, but I can't get even the most simple transformations to work. I'm not best with JavaScript, so I might have missed some essential parts.
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - STL</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 {
background-color: #000000;
margin: 0px;
overflow: hidden;
}
</style>
</head>
<body>
<script src="../build/three.min.js"></script>
<script src="js/loaders/STLLoader.js"></script>
<script src="js/Detector.js"></script>
<script src="dat.gui.js"></script>
<script>
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
var container;
var rotationSpeed;
var camera, cameraTarget, scene, renderer;
init();
animate();
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
camera = new THREE.PerspectiveCamera( 35, window.innerWidth / window.innerHeight, 1, 15 );
camera.position.set( -3, 1, 3 );
cameraTarget = new THREE.Vector3( 0, 0, 0 );
scene = new THREE.Scene();
scene.fog = new THREE.Fog( 0x72645b, 2, 15 );
// Ground
var plane = new THREE.Mesh( new THREE.PlaneGeometry( 40, 40 ), new THREE.MeshPhongMaterial( { ambient: 0x999999, color: 0x999999, specular: 0x101010 } ) );
plane.rotation.x = -Math.PI/2;
plane.position.y = -0.5;
scene.add( plane );
plane.receiveShadow = true;
// ASCII file
var loader = new THREE.STLLoader();
loader.addEventListener( 'load', function ( event ) {
var geometry = event.content;
var material = new THREE.MeshPhongMaterial( { ambient: 0xff5533, color: 0xff5533, specular: 0x111111, shininess: 200 } );
var model = new THREE.Mesh( geometry, material );
model.position.set( 0, 0.05, 0 );
model.rotation.set( Math.PI / 2.0, - Math.PI / 1.5, 0 );
model.scale.set( 0.01, 0.01, 0.01 );
model.castShadow = true;
model.receiveShadow = true;
scene.add( model );
} );
loader.load( './models/stl/ascii/cover.stl' );
// Lights
scene.add( new THREE.AmbientLight( 0x777777 ) );
addShadowedLight( 1, 1, 1, 0xffffff, 1.35 );
addShadowedLight( 0.5, 1, -1, 0xffaa00, 1 );
// renderer
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( scene.fog.color, 1 );
renderer.gammaInput = true;
renderer.gammaOutput = true;
renderer.shadowMapEnabled = true;
renderer.shadowMapCullFace = THREE.CullFaceBack;
container.appendChild( renderer.domElement );
window.addEventListener( 'resize', onWindowResize, false );
}
function addShadowedLight( x, y, z, color, intensity ) {
var directionalLight = new THREE.DirectionalLight( color, intensity );
directionalLight.position.set( x, y, z )
scene.add( directionalLight );
directionalLight.castShadow = true;
// directionalLight.shadowCameraVisible = true;
var d = 1;
directionalLight.shadowCameraLeft = -d;
directionalLight.shadowCameraRight = d;
directionalLight.shadowCameraTop = d;
directionalLight.shadowCameraBottom = -d;
directionalLight.shadowCameraNear = 1;
directionalLight.shadowCameraFar = 4;
directionalLight.shadowMapWidth = 1024;
directionalLight.shadowMapHeight = 1024;
directionalLight.shadowBias = -0.005;
directionalLight.shadowDarkness = 0.15;
}
/* var controls = new function()
{
this.rotationSpeed = 0.2;
}
var gui = new dat.GUI();
gui.add(controls, 'rotationSpeed',0,1);
*/
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.0005;
camera.lookAt( cameraTarget );
//THIS LINE DOESN'T WORK
//model.position.x = Math.cos( timer );
//model.position.z = Math.sin( timer );
renderer.render( scene, camera );
}
</script>
</body>
</html>
The last lines before the render() function just gives me a black, blank page.
Even things like model.position.x += 0.02; kills it
I could find the mistake here , but sorry some how not able to port your code to JSFIDDLE
Here is the problem I found,
model variable is not declared in the global scope. It is initialized locally in the init() function and you are trying the manipulate that variable with in the render function, where it does not have any scope.
So the solution is Just declare the variable model before calling the init() function just like other variables that you are declaring there by adding this below line.
var model;

Categories

Resources