three.js fontloader cannot read generateshapes of undefined - javascript

I have the following code that generates some meshes. I want to add 3d text to the scene but when i do this i get the following error:
TypeError: Cannot read property 'generateShapes' of undefined
this is the code i have to generate the meshes and the 3d text:
var x = 0;
var y = 0;
var finalSize = 450;
var textureLoader = new THREE.TextureLoader();
var fontLoader = new THREE.FontLoader();
the var font is undefined why?
var font = fontLoader.load( 'css/arial_bold.json');
var fontColor = textMaterial = new THREE.MeshBasicMaterial({ color: 0x000000, overdraw: 0.5 });
for (var i = javascriptProjects.length - 1; i >= 0; i--) {
var object = {};
object.scale = javascriptProjects[i].baseImageData["0"] / finalSize;
var geometry = new THREE.PlaneGeometry(javascriptProjects[i].baseImageData["0"]/object.scale,javascriptProjects[i].baseImageData["1"]/object.scale, 10, 10);
object.texture = textureLoader.load( "data/"+ javascriptProjects[i].base_image );
object.material = new THREE.MeshBasicMaterial( { map: object.texture, overdraw: 0.5, transparent: true } );
object.material.opacity = 0.5;
object.mesh = new THREE.Mesh(geometry, object.material);
//the line below generates the error
object.FontGeo = new THREE.TextGeometry( javascriptProjects[i].project_name , {
font: font,
size: 50,
height: 2,
curveSegments: 12,
bevelThickness: 1,
bevelSize: 1,
bevelEnabled: false
});
object.textMesh = new THREE.Mesh( object.FontGeo, fontColor );
object.textMesh.position.x = object.location.x;
object.textMesh.position.y = object.location.y;
object.textMesh.position.z = object.location.z - 100;
scene.add(object.textMesh);
object.location = new THREE.Vector3(x, 120, y);
object.id = "" + javascriptProjects[i].project_id;
object.mesh.position.x = object.location.x;
object.mesh.position.y = object.location.y;
object.mesh.position.z = object.location.z;
scene.add(object.mesh);
meshes.push(object.mesh);
objects.push(object);
x += 600;
if(i % 3 == 0){
y += 600;
x = 0;
};
};
apparently font is undefined. why i don't see what i am doing wrong. Any suggestions would be great. If something is not clear let me know.
Thanks in advance

FontLoader.load() is an asynchronous function call. This is why there is an onLoad call back function.
The library is calling font.generateShapes() before the font is loaded.
Use a pattern like this one, instead:
var loader = new THREE.FontLoader();
loader.load( 'myFontFile.json', function ( font ) {
// insert your code here
} );
See, for example, this three.js example, and the three.js documentation .
three.js r.84

Related

three js - raycaster failing

I have a mesh defined which is at the origin.
var textureCanvas = new THREE.CanvasTexture( imageCanvas );
textureCanvas.repeat.set( 4, 4 );
textureCanvas.wrapS = THREE.RepeatWrapping;
textureCanvas.wrapT = THREE.RepeatWrapping;
var materialCanvas = new THREE.MeshBasicMaterial( { map: textureCanvas }
);
var geometry = new THREE.Geometry();
geometry.vertices.push(
new THREE.Vector3(-4,-4,0),
new THREE.Vector3(-4,4,0),
new THREE.Vector3(4,4,0),
new THREE.Vector3(4,-4,0),
);
geometry.faces.push(
new THREE.Face3(3, 1, 0),
new THREE.Face3(3, 2, 1)
);
var vertexMappings = [];
vertexMappings[0] = new THREE.Vector2(0,1);
vertexMappings[1] = new THREE.Vector2(0,0);
vertexMappings[2] = new THREE.Vector2(1,0);
vertexMappings[3] = new THREE.Vector2(1,1);
var vm = vertexMappings;
geometry.faceVertexUvs[ 0 ] = [];
geometry.faceVertexUvs[0][0] = [ vm[3], vm[1], vm[0] ];
geometry.faceVertexUvs[0][1] = [ vm[3], vm[2], vm[1] ];
meshCanvas = new THREE.Mesh( geometry, materialCanvas );
meshCanvas.rotation.x = - Math.PI / 3;
meshCanvas.rotation.z = - Math.PI / 2.5;
meshCanvas.scale.set( 80, 80, 80 );
scene.add( meshCanvas );
I also have a line which goes through the mesh. It was originally passing through the origin but I moved it a bit (See github issue below).
var linegeo = new THREE.Geometry();
linegeo.vertices.push(
new THREE.Vector3(55, 300, 0),
new THREE.Vector3(-10, -300, 32)
);
scene.add(linemesh);
I want to get the position where the line intersects the mesh, but the intersections result is always empty:
getInersectionPosition(linemesh, meshCanvas);
function getInersectionPosition(linemesh, meshCanvas) {
linemesh.updateMatrixWorld();
meshCanvas.updateMatrixWorld();
var p1 = linemesh.geometry.vertices[0].clone(),
p2 = linemesh.geometry.vertices[1].clone();
p1.applyMatrix4(linemesh.matrixWorld);
p2.applyMatrix4(linemesh.matrixWorld);
//console.log(`p1: ${JSON.stringify(p1)}, p2: ${JSON.stringify(p2)}`);
//console.log(`canvas position: ${JSON.stringify(meshCanvas.position)}`);
var raycaster = new THREE.Raycaster(p1, p2);
raycaster.linePrecision = 10;
//var intersections = raycaster.intersectObjects([meshCanvas]);
var intersections = raycaster.intersectObjects(scene.children, true);
if (intersections.length > 0)
console.log(`intersections: ${ intersections.length}`);
}
Full sample: https://jsfiddle.net/mribbons/103wwsda/
Is it possible that I have this issue?
https://github.com/mrdoob/three.js/issues/11449
The raycaster.intersectObjects() call seems to fail here, with very large values for distance (2.7 million or so, while sphere.radius is ~450).
https://github.com/mrdoob/three.js/blob/dev/build/three.js#L9761
intersectsSphere: function ( sphere ) {
var distance = this.distanceToPoint( sphere.center )
return distance <= sphere.radius;
},
My mistake, raycaster expects a point and a normal, this resolves the issue:
var normal = new THREE.Vector3();
normal.subVectors(p2, p1).normalize();
var raycaster = new THREE.Raycaster(p1, normal);
var intersections = raycaster.intersectObjects(scene.children, true);
if (intersections.length > 0)
console.log(`intersections: ${ intersections.length}`); // outputs "intersections: 2"

Substract 3D text to a Geometry in Three.js

I want to transform my 3D text to Geometry so I can use it with CSG (I used a Three.js CSG wrapper also) to substract it from another object like in this question.
My 3D text :
loader.load('optimer_regular.typeface.json', function (font){
var text = new THREE.TextGeometry('Tayst', {
font: font,
size: 4,
height: 3
});
var textMat = new THREE.MeshBasicMaterial({color: 0xffffff});
var textGeo = new THREE.Mesh(text, textMat);
textGeo.position.x = -7;
textGeo.position.z = 6;
scene.add(textGeo);
});
My substract thing I want to do for the 3D text (but here it's from circles):
var dots = new THREE.Geometry();
for(var i = 0; i < coordinates.length; i++){
var coords = coordinates[i];
sphereMesh.position.x = coords[0];
sphereMesh.position.y = coords[1];
sphereMesh.position.z = coords[2];
sphereMesh.updateMatrix();
dots.merge(sphereMesh.geometry, sphereMesh.matrix);
}
var sphereCsg = THREE.CSG.toCSG(dots);
var resultGeo = THREE.CSG.fromCSG(resultCsg.subtract(sphereCsg));
cube = new THREE.Mesh(resultGeo, material);
But the thing is, I think, I need to convert my text to a real Geometry so I can substract it?
Well i found out using the library I already got, but instead I didn't had to do the "merge" for example.
Here is the working code (in case someone needs it) :
var loader = new THREE.FontLoader();
loader.load('helvetiker_regular.typeface.json', function (font){
var text = new THREE.TextGeometry('Test', {
font: font,
size: 4,
height: 0.5
});
var textGeo = new THREE.Mesh(text);
textGeo.position.x = -5;
textGeo.position.z = 7.5;
var txtCsg = THREE.CSG.toCSG(textGeo);
var resultGeo = THREE.CSG.fromCSG(resultCsg.subtract(txtCsg));
cube = new THREE.Mesh(resultGeo, material);
scene.add(cube);
});

Strange result with ThreeCSG and subtract

I'm learning three.js and for a project i need to create an inersection between a cylinder and a sphere.
Here is the interesting part of the code :
var sphere_mesh_3 = createSphereMesh(rayon_1, 145, color);//,-2,2,-2,2);
sphere_mesh_3.position.z = 6;
//scene.add(sphere_mesh_3);
var sphere_mesh_4 = createSphereMesh(rayon_2, 145, color);//,-2,2,-2,2);
sphere_mesh_4.position.z = 7.5;
//scene.add(sphere_mesh_4);
function getZmaxRelSurfaceAspherique(mesh)
{
var zMax = 0;
for(var i = 0; i < mesh.geometry.vertices.length; i++)
{
var vec = mesh.geometry.vertices[i].clone();
var x = vec.x;
var y = vec.y;
var z = vec.z;
var abs_z = Math.abs(z);
if(x!== 0 && y!==0 && Math.abs(z) !== 1.0)
{
zMax = abs_z;
}
}
return zMax;
}
var min_sph_2 = getZmaxRelSurfaceAspherique(sphere_mesh_3);
var max_sph_2 = getZmaxRelSurfaceAspherique(sphere_mesh_4);
var pos_z_1 = 6 + min_sph_2;
var pos_z_2 = 7.5 + max_sph_2;
var cylindre_sph = cylindreJointure(0,0,pos_z_2,0,0,pos_z_1,Math.abs(rayon_1*80),0xffff00);
var distance = Math.abs(pos_z_1 - pos_z_2);
scene.add(cylindre_sph);
R_sph = (max_sph_2*max_sph_2 + rayon_2*rayon_2)/(2*max_sph_2);
var geometry = new THREE.SphereGeometry( R_sph, 40, 40 );
var material = new THREE.MeshBasicMaterial( {color: 0x00ffff} );
var sphere = new THREE.Mesh( geometry, material );
sphere.position.z = pos_z_2 + R_sph - max_sph_2 ;
scene.add( sphere );
var cylindre_bsp = new ThreeBSP(cylindre_sph);
var sphere_bsp = new ThreeBSP(sphere);
var inter = cylindre_bsp.subtract(sphere_bsp);
var result_1 = inter.toMesh(new THREE.MeshBasicMaterial({color : 0x0000ff}));
result_1.position.z = 15;
result_1.rotateX( Math.PI/2 );
scene.add(result_1);
Here is my two objets:
Cylinder and Sphere
....And the result :
After cylinder.subtract(sphere)...strange result
I don't understand why the substract betwwen the cylinder and the sphere give me these results.
thank you in advance :)
PS : I'm using three.js r74 and the latest version for threeCSG. Like it's impossible for the CSG to maintain the position of the Mesh with the r74 version ... but i can't change my version of three.js ^^''

Dat GUI + Three.js to get user inputted text to create the 3d text geometry that is updated in real time

I'm trying to use Dat GUI + Three.js to get user inputted text to create the 3d text geometry that is updated in real time. So far I have been able to get the positions x, y & z to be controlled and the text input box to show up.
I can't figure out what I'm doing wrong with the text input so any help would be appreciated
here is a link to what i've got so far: http://nuevil.com/index3.html here is the code that deals with the 3d text geometry + dat GUI:
var theText = "FEED ME";
var hash = document.location.hash.substr( 1 );
if ( hash.length !== 0 ) { theText = hash; }
var text3d = new THREE.TextGeometry( theText, {
size: 80,
height: 80,
curveSegments: 2,
font: "helvetiker",
weight: "bold"
});
text3d.computeBoundingBox();
var centerOffset = -0.5 * ( text3d.boundingBox.max.x - text3d.boundingBox.min.x );
var textMaterial = new THREE.MeshNormalMaterial;
text = new THREE.Mesh( text3d, textMaterial );
text.position.x = centerOffset;
text.position.y = 0;
text.position.z = 0;
// text.position.z = Math.tan( Date.now() * 2 ) * 20;
text.rotation.x = 0;
text.rotation.y = Math.PI * 2;
parent = new THREE.Object3D();
parent.add( text );
scene.add( parent );
var axes = new THREE.AxisHelper();
scene.add(axes);
gui = new dat.GUI();
parameters =
{
x: 0, y: 30, z: 0,
color: "#ff0000", // color (change "#" to "0x")
theText: "",
opacity: 1,
visible: true,
material: "Phong",
reset: function() { resetText() }
};
var folder1 = gui.addFolder('text');
var line1 = folder1.add( parameters, 'theText');
// var line2 = folder1.add( text, '').step(1).listen();
// var line3 = folder1.add( text, '' ).step(1).listen();
// folder1.open();
line1.onChange(function(newValue)
{ theText = newValue});
var folder2 = gui.addFolder('position');
var textX = folder2.add( parameters, 'x' ).min(-400).max(200).step(1).listen();
var textY = folder2.add( parameters, 'y' ).min(0).max(100).step(1).listen();
var textZ = folder2.add( parameters, 'z' ).min(-200).max(200).step(1).listen();
// folder2.open();
var folder3 = gui.addFolder('size');
textX.onChange(function(value)
{ text.position.x = value; });
textY.onChange(function(value)
{ text.position.y = value; });
textZ.onChange(function(value)
{ text.position.z = value; });
Your code :
line1.onChange(function(newValue)
{ theText = newValue});
has no effect on the mesh displaying the text.
You need to redefine the mesh with the new text :
line1.onChange(function(newValue)
{
var text3d = new THREE.TextGeometry( newValue, {
size: 80,
height: 80,
curveSegments: 2,
font: "helvetiker",
weight: "bold"
});
text3d.computeBoundingBox();
text = new THREE.Mesh( text3d, textMaterial );
});
the text variable is passed via canvas -- via the font libraries-- not generated within THREE.TextGeometry so I created a function so that when values are entered they are fed to a new text mesh each time. i'm thinking of adding an update function or refresh function in the gui for users to choose to erase old meshes.
line1.onFinishChange(function(newValue)
{
function createtext(){
var hash = document.location.hash.substr( 1 );
if ( hash.length !== 0 ) { newValue = hash; }
var text3d = new THREE.TextGeometry( newValue, {
size: 80,
height: 80,
curveSegments: 2,
font: "helvetiker",
weight: "bold"
});
text3d.computeBoundingBox();
var centerOffset = -0.5 * ( text3d.boundingBox.max.x - text3d.boundingBox.min.x );
var textMaterial = new THREE.MeshNormalMaterial;
text = new THREE.Mesh( text3d, textMaterial );
text.position.x = centerOffset;
text.position.y = 0;
text.position.z = 0;
// text.position.z = Math.tan( Date.now() * 2 ) * 20;
text.rotation.x = 0;
text.rotation.y = Math.PI * 2;
parent = new THREE.Object3D();
parent.add( text );
scene.add( parent );
var axes = new THREE.AxisHelper();
scene.add(axes);
}
createtext();
});

Wrong coordinates for bounding box in three.js

I have some strange behaviour with bounding box in three.js.
I use STLLoader and for some models everything works fine, but for some of them box is shifted.
For example:
http://oi37.tinypic.com/35a1y4l.jpg
and
http://oi34.tinypic.com/4hf4tl.jpg
Bounding box has right size and it's position is (0,0,0). The same position has loaded STL model.
And here is my code:
function stlLoader() {
var redPhongMaterial = new THREE.MeshPhongMaterial({ color: 0xFFEA32, side: THREE.DoubleSide, ambient:0x000000}); // yellow
var stlLoader = new THREE.STLLoader();
stlLoader.addEventListener('load', function (event) {
var stlGeometry = event.content;
var mesh = new THREE.Mesh(stlGeometry, redPhongMaterial);
mesh.scale.set(2, 2, 2);
mesh.castShadow = true;
mesh.receiveShadow = true;
stlGeometry.computeBoundingBox();
var boundingBox = mesh.geometry.boundingBox.clone();
drawBoundingBox(boundingBox, mesh.scale.x, mesh.scale.y, mesh.scale.z);
mesh.position.y = 0;
mesh.position.x = 0;
mesh.position.z = 0;
scene.add( mesh );
loadComplete();
} );
stlLoader.load( ptsfilestoload );
}
function drawBoundingBox(box, scaleX, scaleY, scaleZ)
{
var length = scaleX * (box.max.x - box.min.x);
var height = scaleY * (box.max.y - box.min.y);
var depth = scaleZ * (box.max.z - box.min.z);
var boundingBoxGeometry = new THREE.CubeGeometry( length, height, depth );
for ( var i = 0; i < boundingBoxGeometry.faces.length; i ++ )
{
boundingBoxGeometry.faces[i].color.setHex( Math.random() * 0xffffff );
}
var boundingBoxMaterial = new THREE.MeshBasicMaterial( { color: 0xffffff, vertexColors: THREE.FaceColors, transparent: true, opacity: 0.7 } );
var boundingBoxMesh = new THREE.Mesh( boundingBoxGeometry, boundingBoxMaterial);
scene.add( boundingBoxMesh );
}
Or maybe this is problem with STLLoader? I'm really new to webgl and three.js so any help appreciated
In your drawBoundingBox routine you need
var bboxCenter = box.center ();
boundingBoxMesh .translateX (bboxCenter.x);
boundingBoxMesh .translateY (bboxCenter.y);
boundingBoxMesh .translateZ (bboxCenter.z);
just before you add the mesh to the scene. Your Cube is created around 0,0,0.

Categories

Resources