Multiple scene on multiple canvas Threejs - javascript

I have created two scenes on two different canvases:
var scene1 = new THREE.Scene()
var scene2 = new THREE.Scene()
scene1.add(camera1)
scene2.add(camera2)
next i have created two renders with "autoClear: false" :
renderer = new THREE.WebGLRenderer({alpha: true, antialias: true});
renderer.autoClear = false;
$obj3D[0].appendChild(renderer.domElement);
renderer2 = new THREE.WebGLRenderer({alpha: true, antialias: true});
renderer2.autoClear = false;
$obj3D2[0].appendChild(renderer2.domElement);
Now in update function i do (with renderer.clear() and renderer.clearDepth()) :
function update() {
controls.update();
controls2.update();
renderer.clear();
renderer.render(scene, camera);
renderer.clearDepth();
renderer2.clear();
renderer2.render(scene2, camera2);
renderer2.clearDepth();
}
But in this way it only shows the object on the last canvas.
Where am I wrong? I do not understand
Here there is the demo: http://atktest.000webhostapp.com/,
Here there is the code: https://github.com/ab89/3d
I explain better what I want to do:
I need to create a page that shows up to 5 identical objects.
That is, I load the .obj only once but then I will go to customize them.
I tried to do it but only shows me the last one.
I did it this way because the way I know to change the material of the object is this:
OBJ.traverse (function (child) {
if (child.name! == '') {
console.log (child)
var clone_material = child.material [0] .clone ();
clone_material.map = texture;
child.material = clone_material;
}
});
scene.add (OBJ);
so i thought i need to have more scenes to do it.
But I should also have: OBJ2, OBJ3, OBJ4, OBJ5 to do the 'traverse' function
and change the texture of each object

Related

Create a mesh from GLTFLaoder().load() in Thre.js

I have a local 3D object model and I load it with:
const loader = new GLTFLoader();
loader.load("path/to/model", gltf => {
scene.add(gltf.scene);
});
How should I create a mesh out of the gltf, because when I try:
loader.load("path/to/model", (geometry, materials) => {
var mesh = new THREE.Mesh(geometry, materials);
scene.add(mesh);
mesh.position.z = -10;
});
I get the error:
Cannot convert undefined to object
I found out that actually by modifying the first function above like this:
loader.load("path/to/model", gltf => {
var object = gltf.scene.children[0];
scene.add(gltf.scene);
});
is the solution.
Because now object variable can be totally handled like a normal mesh.
Maybe a video to help you.

Switch between two scenes using the same renderer in three.js

I have been trying to find a way to be able to toggle between two scenes in three.js. I am aware that one can load a scene by using sceneLoader / exportScene combo.
Code taken from josdirksen/learning-threejs - loading a scene
var controls = new function () {
this.exportScene = function () {
var exporter = new THREE.SceneExporter();
var sceneJson = JSON.stringify(exporter.parse(scene));
localStorage.setItem('scene', sceneJson);
};
this.clearScene = function () {
scene = new THREE.Scene();
};
this.importScene = function () {
var json = (localStorage.getItem('scene'));
var sceneLoader = new THREE.SceneLoader();
sceneLoader.parse(JSON.parse(json), function (e) {
scene = e.scene;
}, '.');
}
};
From my understanding of the above code you need to have the scene loaded first before you can extract it and save to local storage before you can put it back into the scene. I am also aware that SceneLoader is now deprecated.
For my senario I want to have an initial scene load and by clicking the 'scene2' button I then want to display scene2 only and if I click the 'scene1' button go back to seeing scene1 only (see fiddle below).
A Basic Example setup
I'm not sure where to begin with this, so any pointers suggestions or advice would be helpful.
If you need to just switch to new scene, then why not have two scene object and one main scene. Try following code
/* Buttons to handle scene switch */
$("#scene2").click(function() {
scene = scene2
})
$("#scene1").click(function() {
scene = scene1
})
function init() {
....
/* I dont think you need to add camera to scene for viewing perpose. By doing this, essentially you are adding camera object to scene, and you won't be able to see it because scene is rendered using this camera and camera eye is at same location
*/
scene1 = new THREE.Scene();
// Build scene1
// scene1.add(camera);
scene2 = new THREE.Scene();
// Build scene2
// Choosing default scene as scene1
scene = scene1;
}
function render() {
// Try some checking to update what is necessary
renderer.render(scene, camera);
}
Updated jsfiddle
You can redraw the canvas by removing current scene scene.remove(mesh); and add create new mesh add into scene
Demo http://jsfiddle.net/sumitridhal/x8t801f5/4/
You can add custom controls using dat.GUI library.
<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.4/dat.gui.js"></script>
//
var controls = new function() {
// we need the first child, since it's a multimaterial
this.radius = 10;
this.detail = 0;
this.type = 'Icosahedron';
this.redraw = function() {
// remove the old plane
scene.remove(mesh);
// create a new one
// add it to the scene.
scene.add(mesh);
}
});
var gui = new dat.GUI();
gui.add(controls, 'radius', 0, 40).step(1).onChange(controls.redraw);
gui.add(controls, 'detail', 0, 3).step(1).onChange(controls.redraw);
gui.add(controls, 'type', ['Icosahedron', 'Tetrahedron', 'Octahedron', 'Custom']).onChange(controls.redraw);
Demo http://codepen.io/sumitridhal/pen/NjbGpB

Optimize Three.JS render time for a static scene

I have a scene which contains 15-20 objects, 4 lights. And properties of my renderer are
function getRenderer(container, width, height) {
var renderer;
renderer = new THREE.WebGLRenderer({ alpha: false, antialias: true, preserveDrawingBuffer: false });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(width, height);
container.appendChild(renderer.domElement);
renderer.shadowMapEnabled = true;
renderer.shadowMapType = THREE.PCFSoftShadowMap;
renderer.setClearColor(new THREE.Color(0xCCE0FF), 1);
renderer.gammaInput = true;
renderer.gammaOutput = true;
renderer.clear();
return renderer;
}
My render loop renders the scene every second.
function renderLoop() {
this.renderer.render(this.scene, this.camera);
setTimeout(function () {
renderLoop();
}, 1000);
}
The problem I am facing is this.renderer.render(this.scene, this.camera) is taking about 100 ms to render the scene but I want it to be below 33ms so that I can have frame rate of at least 30 fps.
Is there a way to optimize the renderer performance by any means (like changing any properties or something)?
I don't want to use worker.js as my scene is static and doesn't contain any complex calculations.
If you have a static scene, there is no reason to have an animation loop. You just have to render once after the scene -- and all your assets -- load.
That is why there are callbacks for the loader functions. And that is why there is a THREE.LoadingManager.
There are many possible use cases. Study the three.js examples to find solutions for your particular use case.
If you are using OrbitControls to control the camera, you can force a re-render whenever the camera moves, like so:
controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.addEventListener( 'change', render ); // use if there is no animation loop
three.js r.75

Toggle between multiple 3d models in three.js using dat.gui

I'm trying to toggle between multiple 3d models (loaded with OBJMTLLoader.js) rendered in my three.js scene. I'm using dat.gui to create a dropdown list of model names and when one is chosen, the scene will add the respective obj model to the scene and remove the original one.
Here, I'm loading 2 separate models and adding the second one to the scene and then setting up the dat.gui controls:
var loader = new THREE.OBJMTLLoader();
loader.load("../assets/models/boardlego.obj", "../assets/models/boardlego.mtl", function (obj2) {
obj2.name = 'lego2';
});
loader.load("../assets/models/boardlego2.obj", "../assets/models/boardlego.mtl", function (obj) {
obj.name = 'lego';
scene.add(obj);
});
camControl = new THREE.OrbitControls(camera, renderer.domElement);
// call the render function
render();
//set up dat.gui controls
control = new function () {
this.Templates = 'shortboard';
}
addControls(control);
}
Then, the addControls function:
function addControls(controlObject) {
var gui = new dat.GUI();
gui.add(controlObject, 'Templates', ['shortboard', 'longboard', 'fish', 'funboard', 'simmons', 'parallel', 'gun']).listen();
Both models are loaded but only one is added to the scene. Is it possible to add the other model when the 'Templates' control is changed? I tried to create a separate function updateboard() and call it in the render function, like this:
function updateboard() {
if(controlObject.Templates === "longboard"){
scene.add(obj2);
}
}
But it didn't work. I also tried to set up an if statement in the render function:
function render() {
renderer.render(scene, camera);
if (scene.getObjectByName('lego')) {
scene.getObjectByName('lego').scale.set(control.Length, control.Thickness, control.Width);
}
if(control.Templates === "longboard"){
scene.add(obj2);
}
But it didn't work either. Any help would be greatly appreciated! Or if you can scout out an example that could help too! Thanks in advance.
Load your objects in array();
var my_models();
var loader = new THREE.OBJMTLLoader();
loader.load("../assets/models/boardlego.obj", "../assets/models/boardlego.mtl", function (obj2) {
obj.name = 'lego2';
my_models.push(obj);
});
scene.add(my_models[0]); // 0 would be the first model 1 is the second

three.js load multiple objects asynchronous issue

am loading multiple models on the same time to a scene, but it fails to load all the models, it only loading one model on the scene
For example am having a building scene with the multiple objects like chairs, toys and so on inside that building, while loading those objects the only one object is loading, but somehow if i do a alert on end of the function all the models are loading
Image1 what am getting now, Image2 what actually i want
my code is follows
function load_file(floor_number,x,y,z,width,height,rotation,angle,file)
{
obj_x=x;
obj_y=y;
obj_z=z;
obj_width=width;
obj_height=height;
obj_rotation=rotation;
var object_material = new THREE.MeshBasicMaterial({
color: 0xd6d6d6,
traansparent : true,
opacity : -2.5,
side: THREE.DoubleSide
});
var loader = new THREE.JSONLoader();
loader.load("uploads/accessories/3d/code/3dfile_"+file+".js",
function(geometry, object_material)
{
var object = new THREE.Mesh(geometry, new THREE.MeshFaceMaterial(object_material));
console.log(object);
model = new THREE.Object3D();
model.add(object);
model.position.set(obj_x,obj_y,obj_z);
model.scale.set(obj_width,obj_height,obj_rotation);
model.opacity =2;
model.rotation.y = 600;
model.duration = 12000;
model.mirroredLoop = true;
model.castShadow = true;
model.receiveShadow = true;
scene.add(model);
}
);
// alert('hi'); if i remove this comment second model is loading perfectly
return true;
}
also tried to load the object's by id using Object3D.getObjectById() this is also fails
i know this is about the asynchronous problem, but i can't get ride of this, any help on this?
The problem are the globals.
Here a nice reading about Why is Global State so Evil?.
update
I played around a bit with a code similar to your, and I see now what could be what it seem a problem, but it isn't really, you can use an approach like this:
/* object declaration and initialization on load completed */
var model1;
load_file('object1', function(model) {
model1 = model;
model1.position.x = -2;
});
...
function laad_file(file, on_load_complete) {
...
loader.load("http://localhost/"+file+".js", function(geometry, object_material) {
...
scene.add(model);
/* call the callback to initialize your object */
if (on_load_complete !== undefined)
on_load_complete(model);
});
...
}
render() {
...
if (model1 !== undefined)
model1.rotation.x += 0.1;
...
}
Seems like your problem is that renderer not firing after model added to the scene. Try to call it after model added to the scene at your callback function:
scene.add(model);
renderer.render(scene, camera);

Categories