Trying to add my own custom font, but nothing shows up I think it's crashing??, is there a way to get three.js to render my font: Custom Font
"{%static "js/pink.json"%}" --> this is django's template tagging.
var loader = new THREE.FontLoader();
var font = loader.load( "{%static "js/pink.json"%}", function ( font ) {
var textGeo = new THREE.TextGeometry( "My Text", {
font: font,
size: 3,
height: 3,
} );
var textMaterial = new THREE.MeshPhongMaterial( { color: 0x000000 } );
var mesh = new THREE.Mesh( textGeo, textMaterial );
mesh.position.set( x, y, z );
scene.add( mesh );
I get these errors as well:
Browser crashing
and
Duplicate Point
Thanks you very much #prisoner849, it's work !
Link to convert files in JSON : gero3.github.io/facetype.js
I converted a .ttf file to an .json file and it's work perfectly with the "THREE.FontLoader" of "Three js" !
var loader = new THREE.FontLoader();
loader.load( 'font_file_name.json', function ( font ) { ... }
Related
I'm a beginner to three.js.I'm trying to build something similar to this https://virtualshowroom.nissan.in/car-selected.html?selectedCar=ext360_deep_blue_pearl. I built everything using three.js, but I'm not able to figure out how to create a hotspot(like the red dot in the above link) and show pop up when you click on it. below is my project code, let me know if anything else is required.
<html>
<head>
<title>My first three.js app</title>
<style>
body { margin: 0; }
canvas { display: block; }
</style>
</head>
<body>
<h1></h1>
<script src="./three.js"></script>
<script type="module">
import { GLTFLoader } from 'https://threejs.org/examples/jsm/loaders/GLTFLoader.js';
import { OrbitControls } from 'https://threejs.org/examples/jsm/controls/OrbitControls.js';
var renderer,scene,camera;
scene = new THREE.Scene();
scene.background = new THREE.Color(0xfff6e6)
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
var loader = new GLTFLoader();
var hlight = new THREE.AmbientLight(0x404040, 100)
scene.add(hlight)
var directionalLight = new THREE.DirectionalLight(0xffffff, 100)
directionalLight.position.set(0,1,0)
directionalLight.castShadow = true
scene.add(directionalLight)
var light = new THREE.PointLight(0xffffff, 10)
light.position.set(0, 300, 500)
scene.add(light)
var light2 = new THREE.PointLight(0xffffff, 10)
light2.position.set(500, 100, 0)
scene.add(light2)
var light3 = new THREE.PointLight(0xffffff, 10)
light3.position.set(0, 100, -500)
scene.add(light3)
var light4 = new THREE.PointLight(0xffffff, 10)
light4.position.set(-5000, 300, 0)
scene.add(light4)
var controls = new OrbitControls(camera, renderer.domElement);
document.body.appendChild(renderer.domElement)
var loader = new GLTFLoader();
loader.load( './scene.gltf', function ( gltf )
{
scene.add( gltf.scene );
}, undefined, function ( error ) { console.error( error ); } );
// load a image resource
camera.position.z = 5;
var animate = function () {
requestAnimationFrame( animate );
renderer.render( scene, camera );
};
animate();
</script>
</body>
</html>
Those “hotspots” as you call them are Annotations where the annotation content is basically pure HTML.
The tutorial in the link is probably the best step-by-step readiness you can follow to learn how to do it in your scene.
I can give a walkthrough on the steps required to get the desired effect since I have done it a few times myself.
define a 3d point in your scene where the hotspot should be. You can optionally nest this in a an other Object3D to make sure it scales, moves and rotates with the model / parent.
Add a plane to this point load a image texture to this plane. and there you have your visible hotspot
update the hotspots to make sure they are always looking at the camera by using the lookAt function.
when the user clicks the screen cast a raycast against all the hotspots you have in your scene. Easiest way to do this is by storing all your hotspots in an array.
When the raycast hits a hotspot get the location either of the hitpoint or the hotspots location. Transform that to screen coordinates. Search on stackoverflow how to do this. I am sure there is a post about this.
Final step display your html on the correct location you obtained from the previous step.
The advantage of this method is that the hotspot will integrate nicely with the model in your scene. Since html based hotspots will always be on top of the scene.
That is about all that is to it. Let me know if you need any further clarification!
I would like to add a mask effect on my scene.
I found this cool jsfiddle : https://jsfiddle.net/f2Lommf5/4703/
I've been wondering if it's possible to set the white part of that texture transparent so I can have my background object cropped depending on the above plane texture.
I tried to play with the alphaTest value but in vain.
Does anyone have any idea on how to reach this result ? Thank you
I'm not 100% sure I understand your intended result but it should be possible to implement the effect via post processing. In the following live demo, MaskPass is used to create a mask where no pixels of the actually beauty pass are rendered. The important code section is:
var clearPass = new ClearPass();
var maskPass = new MaskPass( sceneMask, camera );
maskPass.inverse = true;
var renderPass = new RenderPass( scene, camera );
renderPass.clear = false;
var clearMaskPass = new ClearMaskPass();
var outputPass = new ShaderPass( CopyShader );
var parameters = {
minFilter: THREE.LinearFilter,
magFilter: THREE.LinearFilter,
format: THREE.RGBFormat,
stencilBuffer: true
};
var renderTarget = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight, parameters );
composer = new EffectComposer( renderer, renderTarget );
composer.addPass( clearPass );
composer.addPass( maskPass );
composer.addPass( renderPass );
composer.addPass( clearMaskPass );
composer.addPass( outputPass );
Notice that the mask object (the plane) is managed in a separate scene.
Live demo: https://jsfiddle.net/e6p0axb1/5/
I am new to three.js, pls guide me how to change the image dynamically
Tried with the below option of replacing the image from the original image
I tried with the below code
var mtlLoader = new THREE.MTLLoader();
mtlLoader.load( 't2.mtl', function( materials ) {
materials.preload();
var texture = THREE.TextureLoader('bbc.png');
var material = new THREE.MeshLambertMaterial( { map: texture } );
materials.setMaterials( material );
objLoader.load( 't2.obj', function ( object ) {
scene.add( object );
}, onProgress, onError );
});
I am not getting any error but updated image is not displayed ? but the actual object is displayed in blank color. Pls suggest
Thanks
Shaik
I'm having trouble creating a button to change the .mtl file of my .obj to another .mtl using three.js. Any thoughts on how to do that would be awesome!
Here is the original code, adapted from the objmtl loader example on threejs.org. So far, I've only been able to make the obj visible / invisible using a button, but I'd love to add more buttons to change the .mtl files to reflect .mtls with other colors and properties.
var mtlLoader = new THREE.MTLLoader();
mtlLoader.setBaseUrl( 'examples/obj/male02/' );
mtlLoader.setPath( 'examples/obj/male02/' );
mtlLoader.load( 'male02_dds.mtl', function( materials ) {
materials.preload();
var objLoader = new THREE.OBJLoader();
objLoader.setMaterials( materials );
objLoader.setPath( 'examples/obj/male02/' );
objLoader.load( 'male02.obj', function ( object ) {
object.position.y = - 95;
dude = object;
scene.add( dude );
info.innerHTML += '<br/><br/><input id=pants2 type="button" onclick="dude.visible = false" value="Dude: OFF"/>';
info.innerHTML += '<input id=pants2 type="button" onclick="dude.visible = true" value="Dude: ON"/>';
If you can work without the .mtl file, you can use something like that:
texture = new THREE.TextureLoader().load('dir/to/texture.jpg');
sectexture = new THREE.TextureLoader().load('dir/to/second_texture.jpg');
lambert = new THREE.MeshLambertMaterial({color: 0xffffff, map: texture});
objLoader = new THREE.OBJLoader();
objLoader.setPath( 'examples/obj/male02/' );
objLoader.load( 'male02.obj', function ( object ) {
object.traverse(function(child) {
if (child instanceof THREE.Mesh){
child.material = lambert;
}
});
scene.add( object );
}, onProgress, onError );
With that, you can load your texture into the lambert material, so if you want to change it you can use lambert.map=texture or lambert.map=sectexture.
[EDIT] I have fixed the mistake on child.material
I have some .js files exported from Blender and load them with THREE.JSONLoader();
my callback:
var callback = function( geometry ) { createMesh(geometry);
my loading:
loader.load( "Models/sculp.js", callback );
my create method:
function createMesh(geometry){
inArr[id] = new THREE.Mesh( geometry, new THREE.MeshLambertMaterial( { color: 0xbbbbbb} ) );
inArr[id].scale.set( 100, 100, 100 );
scene.add( inArr[id] );
id++;
}
Now I want to change my material on runtime by using my keyboard (changes color and opacity).
How can I do that?
As you create a new material for each mesh I assume you only want to change the color of one mesh and not of all in the inArr array, and you probably need some sort of select for that. But changing the color of the material alone is quite easy:
var onKeyDown = function(event) {
if (event.keyCode == 67) { // when 'c' is pressed
object.material.color.setHex(0xff0000); // there is also setHSV and setRGB
}
};
document.addEventListener('keydown', onKeyDown, false);
object is the mesh you want to change. Key codes can be found here: http://www.cambiaresearch.com/articles/15/javascript-char-codes-key-codes