Trying to add custom mesh to offline viewer - javascript

I try to add a custom sphereMesh to a offline viewer. I saw this can be done with the online version of the viewer. But I get an uncaught TypeError: Cannot read property 'Add' of undefined if I try this in my viewer.
<div id="MyViewerDiv"></div>
<script>
var myViewerDiv = document.getElementById('MyViewerDiv');
var viewer = new Autodesk.Viewing.Private.GuiViewer3D(myViewerDiv);
var options = {
'env' : 'Local',
'document' : './_3D_ 197440/_3D_.svf'
};
Autodesk.Viewing.Initializer(options, function() {
viewer.start(options.document, options);
});
var geom = new THREE.SphereGeometry(1000, 8, 8);
var material = new THREE.MeshBasicMaterial({ color: 0xff0000 });
var sphereMesh = new THREE.Mesh(geom, material);
sphereMesh.position.set(0, 0, 0);
viewer.impl.scene.add(sphereMesh);
</script>

There is no difference between online and offline viewer, when it comes to ways of adding custom geometry.
In your case you have a situation similar to "race condition", where you try to use a resource while it is initializing: sometimes the init process finishes first => success, sometimes it finishes later => get errors.
To solve the problem, there are 2 approaches:
Add your code into an extension and load extension as mentioned in documentation (the recommended one). Example: https://apprentice3d.github.io/SD226781-Samples/02.html
Move your custom mesh code into the body of the document loading callback function. Example: Check the source of https://s3.amazonaws.com/sample-collection/GiroWatch_Latest.html

Related

ThreeJS TextureLoader is black in .NET blazor application

When using textureloader from three.js in a blazor application. when trying to get a picture on a cube, it just gets displayed in black. I have tried a lot of things including:
new THREE.TextureLoader().load('https://images.pexels.com/photos/2422/sky-earth-galaxy-universe.jpg?auto=compress&cs=tinysrgb&dpr=1&w=500', function (texture) {
var objGeometry = new THREE.SphereBufferGeometry(11, 11, 11);
var objMaterial = new THREE.MeshPhongMaterial({
map: texture,
shading: THREE.FlatShading
});
moonMesh = new THREE.Mesh(objGeometry, objMaterial);
scene.add(moonMesh);
});
Local images that are preloaded don't work, tried with and without callback. Tried another browser.
The console is empty, if I log the texture, it's always define.
Still the sphere is always displayed in black. Maybe a light is missing, although they don't get used in any example. The js is loaded from a blazor page using the following code:
protected override async Task OnAfterRenderAsync(bool firstRender)
{
object[] args = { canvasId };
await JSRuntime.InvokeVoidAsync("threeExample", args); // NOTE: call JavaScript function
}
And the scene and stuff load fine, I can use orbidcontrols, normal cubes with a color texture are visibe. Any ideas?
EDIT:
When using MeshBasicMaterial It works! So I guess I used the wrong type of material to use the texture.
Kind regards

How to assign to variable content of Three.js model file

When you export your model from Blender to Three.js you end up with a file with JSON data inside. I know two ways of loading this model from that file:
var loader = new THREE.JSONLoader()
var material = new THREE.MeshPhongMaterial({color: '#8080a0'})
1.
loader.load('tower.json', function (geometry) {
var mesh = new THREE.Mesh(geometry, material)
})
2. Edit tower.js file and add
var tower =
in first line. Then you can load it with:
var towerModel = loader.parse(tower)
var mesh = new THREE.Mesh(towerModel.geometry, material)
I like second solution more because using loader.load() function every time you want to create a mesh when you have thousands of meshes based on the same model is very slow and can easly kill your browser.
So my question is - can I get JSON data from tower.json file into a variable without editing the file manually? The best solution would be to get JSON data into a variable without making changes to the file.
I would go for option 1.
It sounds very strange to add a loader to a source file.
To keep things clean you should keep loaders and data sources (your model files) separated if you ask me.
Why would you reload the same model anyway. You should just store it in a variable and reuse it. It is a waste of CPU and memory to load the same geometry twice.
You can do easily something like this to optimize things. It is just a concept but I hope you get the idea:
// Storage for model files
myFiles = {
tower: 'tower.json',
car: 'car.json'
};
// Storage for loaded geometries
myModels = {
tower: null,
car: null
};
// Loader, loads only first time from file then from storage
var load = function( modelName ){
if( myModels[modelName] === null ){
loader.load(myFiles[modelName], function (geometry) {
myModels[modelName] = geometry;
});
}
var model = new THREE.Mesh(myModels[modelName], material)
scene.add( model );
}
You can rework it how you think is best.

THREE.PointerLockControls() returning "undefined is not a function"

I'm trying to implement a moving camera in THREE like so:
function initThree(){
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,1000);
renderer = new THREE.CanvasRenderer();
renderer.setSize(window.innerWidth,window.innerHeight);
document.body.appendChild(renderer.domElement);
geometry = new THREE.CubeGeometry(1,1,1);
material = new THREE.MeshBasicMaterial({color:0x00ff00});
cube = new THREE.Mesh(geometry,material);
scene.add(cube);
camera.position.z=5;
controls = new THREE.PointerLockControls(camera); //fails at this line
}
At the line marked, I get the following error:
Uncaught TypeError: undefined is not a function
However, there is an example of it on this page? I'm currently using a local copy of this THREE build.
Any help would be great!
You're getting that error because the controls are not part of the main source. If you want to use the controls, you probably need to include them separately. See this related post.

Can't load converted from FBX to JSON model using THREE.JSONLoader

I converted an FBX model to JSON using convert-to-threejs.py, but I can't get three.js (r58) to load it. It says "Uncaught TypeError: Cannot read property 'length' of undefined". The error is at line 9930 in three.js which line is for ( i = 0; i < json.uvs.length; i++ ) ...
Here's the converted JSON: http://pastebin.com/86ZGvKnW. You'll see that it does not, in fact, have a uvs property.
Is convert-to-threejs.py outdated? If so, what's the alternative? If not, how can I get this model to load?
Here's my code:
window.loader = new THREE.JSONLoader();
loader.load('jet.json', function(geometry) {
// Never gets to here; error is thrown first
console.log(geometry);
});
Oh, I see. The actual model is embedded in that JSON file. I want embeds["Embed_31_jet 3"].
FBX files converted to JSON seem to describe complete scenes. So, instead of THREE.JSONLoader, use THREE.SceneLoader.
For example
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(...);
var loader = new THREE.SceneLoader();
loader.load('jet.json', function(res) {
scene.add(res.scene);
renderer.render(res.scene, camera);
});

Manage click on a mesh

I am trying to manage click on a mesh (cube) to do some processing stuff.
var cubeFor3D = new THREE.Mesh(new THREE.CubeGeometry(40,80,40),img3D);
scene.add(cubeFor3D);
//
renderer.render(scene,camera);
//
animate();
//Track the click on cube3d
cubeFor3D.on('click', function(){
// response to click...
console.log('you have clicked on cube 2D');
});
When running, i got this error on the web console:
TypeError: cubeFor3D.on is not a function
In the API documentation, it's shown to do like this:
mesh.on('click',..
But i guess i should replace mesh by my mesh real name. Seems i am going wrong. help please.
I am including the API JS in my file: <script src='threex.domevent.js'></script>
Late answer but, if you add this to the begging of the init function it should work:
THREE.Object3D._threexDomEvent.camera(camera);
In fact I normally put in straight after scene = new THREE.Scene();

Categories