I need update the mesh's texture in my project, by changing the image's source in the texture. The code is below:
mesh.material.map.image.src= "path/to/image";
mesh.material.map.texture.needsUpdate = true;
The image has completely loaded. It works well in chrome, but not in firefox, the browser doesn't render new texture immediately, and i fixed it by:
setTimeout( function(){ mesh.material.map.texture.needsUpdate = true; }, 100);
I don't know why it can't update immediately in firefox, has anyone encountered this problem?
since timeout fixes the issue, the needsUpdate flag is set back to false before the texture loads
you should probably use a loader for getting the texture
var texture = THREE.ImageUtils.loadTexture("path/to/image");
it also has a callback for what happens when texture is loaded
var texture = THREE.ImageUtils.loadTexture("path/to/image", THREE.UVMapping, onLoadCallback);
the callback gets loaded texture as parameter so you can add it to the material after load but the loader sets the textures needsUpdate flag to true itself so simple
var texture = THREE.ImageUtils.loadTexture("path/to/image");
mesh.material.map = texture;
should suffice
Related
I am currently working on a project where I am trying to replace the texture of a 3D model with an image from a canvas that has the original texture and with same resolution. I have been able to successfully load the image from the canvas and apply it to the model's material, but the texture is appearing distorted and stretched.
Original glTF before using the canvas image as the texture
After using the canvas image as the model's texture
Currently this is the code I am using to load the image from the canvas to the glTF:
this.button.addEventListener("click", () => {
var image = new Image();
image.src = this.canvas.toDataURL();
image.onload = function()
{
var texture = new THREE.Texture(image);
texture.encoding = THREE.sRGBEncoding;
material.map = texture;
texture.needsUpdate = true;
}
});
I am wondering if anyone has any experience with this issue and can offer any suggestions or solutions. Any help would be greatly appreciated.
Thank you.
I have a question about mapbox autoclearcolor setup when it uses three.js custom layer.
I managed to make a cube within a mapspace using the customlayer setup in mapbox and
I wanted to make the map layer visible at the beginning and turned it visible in a certain moment.By doing things as below.
In onAdd method,
this.map = map;
this.canvas = map.getCanvas()
this.renderer = new THREE.WebGLRenderer({
canvas: map.getCanvas(),
context: gl,
antialias: true
});
this.renderer.autoClear = false;
In render Method,
if(frameCount>10 && frameCount<11){
this.renderer.autoClear = true;
}
I by accident made it happened but I don't know why it happened.
frameCount += 0.1
if(frameCount>10 && frameCount<11){
this.renderer.autoClear = true;
}
In three.js document it says
.autoClear : Boolean
Defines whether the renderer should automatically clear its output before rendering a frame.
I don't get how it works.
To me it sounds like,
if I set autoClear true, it should clear things in the scene and if it's true,
I shouldn't see anything but by setting this, only the map tile is gone and my mesh and map labels are still alive like the screen shot below.
after autoclear is set true
Before autoclear becomes true, currently it's false which is default value
Assign the material from the video tag to the Mesh and get an inverted video. Before that, this place had a texture with the correct orientation. What can this be related to? I've have this problem when I switched from loading models in GLTF format
material = new MeshPhysicalMaterial();
const video = document.getElementById('myvideo');
video.play();
material.map = new VideoTexture(video);
material.map.format = RGBFormat;
http://prntscr.com/t4ldyf
If your texture is showing up vertically inverted, you can flip it with the Texture.flipY property. The default value is true, so try setting it to false.
material.map = new VideoTexture(video);
material.map.format = RGBFormat;
material.map.flipY = false;
Im started to develop my project, where fabric js canvas used as a texture on my 3d object, loaded by three js library. Unfortunately I don`t have a full working snippet now, maybe you can show me solution or right way to solve my problem
The problem is the controls drawing on the lower canvas and its transfer on my 3d object, i want to render it on the upper canvas. Is it possible?
The second problem is the brush at first rendered on the upper canvas and after event 'mouse: up' its rendered on the lower canvas. How to render brush line by event 'mouse; move' on the lower canvas at the moment drawing?
p.s. sorry for my english, its really hard to say for me. Hope, you understand my mind
Here you can see my first issue:
https://1drv.ms/u/s!AqtIFlFVWz4MhNtBc3g1DQElfA6_7Q?e=y7ly37
Thank you for you response!
Woow! this is a very good code example! And it works pretty smooth too. It shows the problem a lot better.
I found a solution for the first problem (that is kind of a three.js problem) in the fabric js demo: http://fabricjs.com/controls-customization.
I'm not good with fabric so there might be a more elegant solution than this. You can hide the controls, render to three.js and then show them again. You also have to force the canvas to render, it won't work otherwise.
function animate() {
requestAnimationFrame(animate);
//find the selected object on the fabric canvas
let selected = canvas.getActiveObject();
//hide controles and render on the fabric canvas;
if (selected){
selected.hasControls = false;
selected.hasBorders = false;
canvas.renderAll();
}
//update texture and render
texture.needsUpdate = true;
renderer.render(scene, camera);
//show controls and render on the fabric canvas
if (selected){
selected.hasControls = true;
selected.hasBorders = true;
canvas.renderAll();
}
}
The second problem is a bit harder to understand. I'm not sure what the 'lower canvas' is and if that is a part of fabric that i don't understand. This is the closest i can get. I almost made it work on the three.js renderer. If i understood the idea correctly...
You need to have a variable to know if you are pressing the mouse or not. Only if you are pressing the mouse AND moving the mouse, it draws a circle.
To do the same with fabric 'mouse:move' you will at least have to disable that selectionbox on the fabric canvas. But i do not know how that works in fabric.
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
var mouseDown = false;///////////////////////////// global boolean
var onClickPosition = new THREE.Vector2();
container.addEventListener("mousedown", function(){
mouseDown = true;
canvas.selection = false;
onMouseEvt(); //draw circle
}, false);
container.addEventListener("mouseup", function(){
mouseDown = false
canvas.selection = true;
}, false);
container.addEventListener("mousemove", function(e){
if (mouseDown){
onMouseEvt(); //draw circle
}
}, false);
///This code does not work, it goes into selection mode..
canvas.on('mouse:down', function(){
mouseDown = true;
addCircle();
}, false);
canvas.on('mouse:up', function(){
mouseDown = false;
}, false);
canvas.on('mouse:move', function(){
if ( mouseDown ){
addCircle();
}
}, false);
This is a hard question and it's not really a three.js thing, it has more to do with fabric.js and drawing to a canvas. The three.js part of texturing the object seems to work fine.
If I understand correctly you have an overlaying canvas on which you want to render the controls, but they are also rendered to the actual texture canvas? If in case you are actually rendering the controls on the texture; don't do that :p
It should be possible to make it work the way you want to. It would be helpful to post a small code example on https://jsfiddle.net/ or something.
I cant get my collada model to render with three.js until I interact with the browser window. In Chrome, it can be as simple as moving my mouse anywhere on the page (actual canvas is smaller than entire window), and on Safari, it requires a click and drag for the model to render. What's odd is that the rest of the scene is loading properly (I have a grid that I render to the scene and a couple of lights), but the model won't show until I do something. Any thoughts on how I can trick the scene into knowing it should show the model?
var loader = new THREE.ColladaLoader();
loader.options.convertUpAxis = true;
loader.load('../MODELS/teapot.dae', function colladaReady( collada ) {
dae = collada.scene;
skin = collada.skins[ 0 ];
dae.scale.x = dae.scale.y = dae.scale.z = 10;
dae.position.y = 75;
dae.updateMatrix();
scene.add(dae);
});
document.getElementById('myCanvas').appendChild(renderer.domElement);
render();
The loading is occurring asynchronously. You are only showing a code fragment, but it looks like you can move the render() call to the last line of the colladaReady() callback function.