load texture in a class before proceeding - javascript

I have presented a simple example to illustrate what my problem is. in functions it's easy to use await async to make sure textures are loaded before proceeding with the program. if I want to work with classes because of the cleanliness of the program, I have no idea how I can do this so that the constructor waits until the texture is loaded before the subsequent function is called.
//in my three.js init function
var sphereObject = new Sphere(100, texture);
var sphere = this.sphereObject.sphere;
scene.add(sphere);
//------------------------
class Sphere{
constructor(radius, preloadedtex){
//this.material = this.doSomething(preloadedtex); this work fine
const loader = new THREE.TextureLoader();
loader.load("grass.png", function(texture){
this.material = this.doSomething(texture);
});
const geometry = new THREE.SphereGeometry( radius, 128, 64 );
this.sphere = new THREE.Mesh( geometry, this.material);
}
doSomething(texture){
//further operations with the texture before the function returns a material
return material;
}
}

TextureLoader has an onLoad callback as the second argument of .load(). This is taken directly from the docs:
const loader = new THREE.TextureLoader();
// load a resource
loader.load(
// resource URL
'textures/land_ocean_ice_cloud_2048.jpg',
// onLoad callback
function ( texture ) {
// in this example we create the material when the texture is loaded
const material = new THREE.MeshBasicMaterial( {
map: texture
} );
},
// onProgress callback currently not supported
undefined,
// onError callback
function ( err ) {
console.error( 'An error happened.' );
}
);

Related

How to get the geometry of a model imported from STL in three.js

I'm using STLLoader to load STL file into three.js and I want to get the vertices (and the geometry) of the model after I call the loader for further usage. How can I do that? My current code is as below but I cannot get the geometry after calling the loader.
var loader = new THREE.STLLoader();
var myModel = new THREE.Object3D();
loader.load("myModel.stl", function (geometry) {
var mat = new THREE.MeshLambertMaterial({color: 0x7777ff});
var geo = new THREE.Geometry().fromBufferGeometry(geometry);
myModel = new THREE.Mesh(geo, mat);
scene.add(myModel);
});
console.log(myModel.geometry.vertices)
As of three.js R125, the recommended way to do this is with the loadAsync method, which is now native to three.js:
https://threejs.org/docs/#api/en/loaders/Loader.loadAsync
That method returns a promise. You couldthen use a 'then' to get the geometry of the STL and create the mesh. You could also use a traditional callback, or an async/await structure, but I think the example below using the native three.js method is the simplest way. The example shows how you can get geometry to a global variable once the promise is resolved and the STL file is loaded:
// Global variables for bounding boxes
let bbox;
const loader = new STLLoader();
const promise = loader.loadAsync('model1.stl');
promise.then(function ( geometry ) {
const material = new THREE.MeshPhongMaterial();
const mesh = new THREE.Mesh( geometry, material );
mesh.geometry.computeBoundingBox();
bbox = mesh.geometry.boundingBox;
scene.add( mesh );
buildScene();
console.log('STL file loaded!');
}).catch(failureCallback);
function failureCallback(){
console.log('Could not load STL file!');
}
function buildScene() {
console.log('STL file is loaded, so now build the scene');
// !VA bounding box of the STL mesh accessible now
console.log(bbox);
// Build the rest of your scene...
}

three.js aoMap is not rendering on uv2 while lightmap is rendering

We are trying to set the aoMap with three.js, but it is not rendering, while lightMap is working on model
Code for setting uv2 into geometry:
// instantiate a loader
var loader = new THREE.BinaryLoader();
// load a resource
loader.load(
// resource URL
'temp-models/binary/door-boot-01.json',
// Function when resource is loaded
function ( geometry, materials ) {
geometry.sortFacesByMaterialIndex();
geometry.mergeVertices();
geometry = new THREE.BufferGeometry().fromGeometry( geometry );
// self.setupOBJCAR(geometry, materials, self.car.urls.obj[0]);
// return;
loader.load(
// resource URL
'temp-models/binary/door-boot-02.json',
// Function when resource is loaded
function ( geo2, materials ) {
geo2.sortFacesByMaterialIndex();
geo2.mergeVertices();
geo2 = new THREE.BufferGeometry().fromGeometry( geo2 );
var uvs = geo2.attributes.uv.array;
geometry.addAttribute( 'uv2', new THREE.BufferAttribute( uvs, 2 ) );
// console.log(geometry.toJSON());
//Creting Mesh with aoMap in all materials.
}
));
Example link:
http://design.girnarsoft.com/centraljs/creta3d/index-ao.html

How to add a JSON object / model into your whitestorm.js world / scene?

I am loading the object from my json file.
var loader = new THREE.ObjectLoader();
loader.load("blue-car.json",
function ( car ) {
car.position.set(2, 0, 0);
car.addTo(world);
}
);
And this is the error...
How can I add the object to my world? In regular three.js it works when I load the json file, but how do I do it in whitestorm?
Thank You!
Have you tried looking to documentation?
Use this sample code:
// instantiate a loader
var loader = new THREE.JSONLoader();
// load a resource
loader.load(
// resource URL
'models/animated/monster/monster.js',
// Function when resource is loaded
function ( geometry, materials ) {
var material = new THREE.MultiMaterial( materials );
var object = new THREE.Mesh( geometry, material );
scene.add( object );
}
);

How to check item is loaded in the scene in three.js?

I use THREE.js Loading Manager to check the object or texture is loaded .
var Mesh;
var TLoader = new THREE.TextureLoader(manager);
var manager = new THREE.LoadingManager();
manager.onProgress = function ( item, loaded, total ) {
console.log( item, loaded, total );
};
manager.onLoad = function()
{
console.log(Renderer.domElement.toDataURL());
}
function renderModel(path,texture) {
var Material = new THREE.MeshPhongMaterial({shading: THREE.SmoothShading});
Material.side = THREE.DoubleSide;
var Loader = new THREE.JSONLoader(manager);
Loader.load(path,function(geometry){
geometry.mergeVertices();
geometry.computeFaceNormals();
geometry.computeVertexNormals();
TLoader.load(texture,function(texture){
Mesh = new THREE.Mesh(geometry, Material);
Mesh.material.map =texture;
Scene.add(Mesh);
});
});
}
and i just call the renderModel function in a loop .
But the console.log(Renderer.domElement.toDataURL()) output from the manager.onload function is giving only image of the some 3d models not all the ones in the scene
I just want to get 'Renderer.domElement.toDataURL()' when all the 3d models are rendered in the scene
now only the image of 2 or 3 models are getting ,but in scene all the items are loaded.
The renderer renders an image each frame. When the loading of all the objects is completed, the onLoad method of the manager is called immediately. So, the last objects were added to the scene and you retrieve the image data without giving the renderer a chance to render a new image. You need to wait for a new frame. Maybe a timeout with e.g. 200 milliseconds will help.
EDIT
You could also call the render method in your onLoad, so the renderer draws a new image before you call console.log.
manager.onLoad = function()
{
Renderer.render( Scene, camera );
console.log(Renderer.domElement.toDataURL());
}

Loading an object with Three.js fails (missing formal parameter)

I want to use Three.js (OGL + JavaScript) to load an object from file. I have an working example without loading it (some basic elements rendered). But when I try to load object using JSONLoader.load(...), Firefox console shows error:
SyntaxError: missing formal parameter
The reference: http://threejs.org/docs/#Reference/Loaders/JSONLoader
The source code for my added fragment (loading object), which cause an error:
//loading an object
var loader = new THREE.JSONLoader(); //works so far
loader.load("./Project2/proj/grzyb.js",
function(geometry,
new THREE.MeshLambertMaterial( { map: texture, ambient: 0xbbbbbb } )
//for the line above, in Firefox console i get
//"SyntaxError: missing formal parameter"
){
var materials = new THREE.MeshFaceMaterial(
new THREE.MeshLambertMaterial( { map: texture, ambient: 0xbbbbbb } )
);
grzyb = new THREE.Mesh(geometry, materials);
grzyb.scale.set(5, 5, 5);
grzyb.position.set(2,2,2);
grzyb.receiveShadow = true;
grzyb.castShadow = true;
scene.add(grzyb);
}
);
You are trying to insert MeshLambertMaterial creation into a function header definition. Function header can only contain parameter names - not any actual code to create them.
Also it is not clear whether you want to use material coming from model file or your own material with texture that you loaded elsewhere (in the example there is no code that would set texture variable). Assuming you want to use materials from model, your code should look like this:
var loader = new THREE.JSONLoader(); //works so far
loader.load("./Project2/proj/grzyb.js",
function(geometry, materials) {
var material = new THREE.MeshFaceMaterial( materials );
grzyb = new THREE.Mesh(geometry, material);
grzyb.scale.set(5, 5, 5);
grzyb.position.set(2,2,2);
grzyb.receiveShadow = true;
grzyb.castShadow = true;
scene.add(grzyb);
}
);
if you want to use different material, then set material variable to anything you want. exmaple:
var texture = THREE.ImageUtils.LoadTexture( "../path/image.jpg" );
var material = new THREE.MeshBasicMaterial( { map:texture } );
var grzyb = new THREE.Mesh(geometry, material);

Categories