OBJ + MTL loads but doesn't render - three.js

If I use the following code to load the .obj and .mtl downloaded from
https://poly.google.com/view/9NXf-SDxJny it works fine, I see the star rendered in my scene.
return new Promise((resolve, reject) =>
{
let mtlLoader = new THREE.MTLLoader();
mtlLoader.crossOrigin = true;
mtlLoader.setPath(ASSETS_PATH);
mtlLoader.load(filename + '.mtl', (materials) =>
{
materials.preload();
let objLoader = new THREE.OBJLoader();
objLoader.setPath(ASSETS_PATH);
objLoader.setMaterials(materials);
objLoader.load(filename + '.obj', (obj) =>
{
this.obj = obj;
resolve(true);
});
});
});
But when I use the same code to load the obj and mtl from https://poly.google.com/view/4-OZNPuTqFq it doesn't show. I don't get any errors. If I remove the line objLoader.setMaterials(materials); then i see the cake but with no material. So it appears to be a material issue.
I have a codepen with the full code here https://codepen.io/steveg3003/pen/6f0d8c4a17ed12bea49b3391a6d80ce3?editors=0010
Thanks

Something similar happened to me, except the model was all black. I had to open up the .mtl file and change the "Kd 0.00 0.00 0.00" to "Kd 1.00 1.00 1.00"

So the solution for me was to manually change the 'd' value inside the material file (.mtl) from 0.00000 to 1.00000

Related

Import 3D model Threejs

i tried to import a 3D model but I'm not sure if i m doing in right way.
var loader = new THREE.GLTFLoader();
loader.load('./CesiumMilkTruck.gltf',
function (gltf) {
scene.add(gltf.scene);
gltf.animations;
gltf.scene;
gltf.scenes;
gltf.cameras;
gltf.asset;
},
function (xhr) {
console.log((xhr.loaded / xhr.total * 100 ) + '% loaded' );
},
function (error) {
console.log( 'An error happened = ', error );
}
);
my html is
<script type="text/javascript" src="js/three.min.js"></script>
<script type="text/javascript" src="js/GLTFLoader.js"></script>
I download the model on this page :
link
in particular i download the three files:
CesiumMilkTruck.gltf
CesiumMilkTruck.png
CesiumMilkTruck0.bin
I had this errors:
An error happened = SyntaxError: "JSON.parse: unexpected character at
line 7 column 1 of the JSON data" parse
file:///C:/Users/an/Desktop/master/js/GLTFLoader.js:157
load file:///C:/Users/an/Desktop/master/js/GLTFLoader.js:75
load file:///C:/Users/an/Desktop/master/js/three.min.js:715
What I m wrong?
Sorry for my question, but is my first time with Threejs.
It's possible you have an issue with the GLTF model, perhaps corrupted?. The error message would lead me to believe that the formatting of the GLTF file is incorrect (it's all numerical).
Here is a code excerpt from my flight simulator I'm building with Threejs and Konva.js: https://github.com/mpaccione/everest_flight_sim
In the code below I load in a helicopter model, turn it wireframe, and add it to a group which contains the first person camera so it seems you are flying a helicopter.
I'm using commonJS modules with browserfy for this project.
const GLTFLoader = require('three-gltf-loader'),
miniModelLoader = new GLTFLoader();
// Load Helicopter Model
miniModelLoader.load( './src/models/helicopter/scene.gltf', function(gltf){
miniModel = gltf.scene;
miniModel.name = "miniHeli"
miniModel.rotation.y = -90 * Math.PI / 180; // Radians
miniModel.position.set( 0, 0, 0 );
let miniModelMesh = miniModel.children[0].children[0].children[0],
miniModelMeshArr = [ miniModelMesh.children[0], miniModelMesh.children[1], miniModelMesh.children[2] ];
for (var i = miniModelMeshArr.length - 1; i >= 0; i--) {
miniModelMeshArr[i].material.wireframe = true;
}
miniHeliGroup.add( miniModel );
} )

Three.js - exporting scene with TextGeometry to OBJ/GLTF then load by OBJ/GLTF Loader

I have problem with import/export scenes in Three.js
I have few objects (models loaded with OBJLoader, Text generated with TextGeometry). Im able to export it to string definition using OBjExporter/GLTFExporter, but when Im trying to load it again, it loads text to BufferGeometry not TextGeometry.
Is it possible to load all scene meshes with proper geometries?
Or maybe its possible to parse geometries?
I know I can save scene without text (store text parametries in different definition then generate it again), but I would like to avoid it.
Im looking forward for Your help.
Thanks.
Code samples:
1. Function to export scene to OBJ
function CanvasToOBJ(callback) {
var exporter = new THREE.OBJExporter();
var options = {
trs: false,
onlyVisible: true,
truncateDrawRange: true,
binary: false,
forceIndices: false,
forcePowerOfTwoTextures: false,
embedImages: true
};
var result = exporter.parse(scene);
callback(result);
exporter.parse(scene, function (result) {
if (result instanceof ArrayBuffer) {
callback(null);
} else {
var output = JSON.stringify(result, null, 2);
callback(output);
}
}, options);
}
Function to import from OBJ string
function LoadOBJ() {
var elem = document.getElementById("modelEditor");
if (elem != null && elem !== "undefined" && elem.value !== "undefined" && elem.value != null && elem.value != "") {
var gltfString = elem.value;
var loader = new THREE.OBJLoader();
loader.load = function load(url, localtext, onLoad, onProgress, onError) {
var scope = this;
var loader = new THREE.XHRLoader(scope.manager);
loader.setPath(this.path);
loader.load(url, function (text) {
if (url == "") {
text = localtext;
}
onLoad(scope.parse(text));
}, onProgress, onError);
},
loader.load('', gltfString, function (gltf) {
scene = new THREE.Scene();
scene.background = new THREE.Color(0xf0f0f0);
scene.add(new THREE.AmbientLight(0x505050));
var light = new THREE.SpotLight(0xffffff, 1.5);
light.position.set(0, 500, 2000);
light.angle = Math.PI / 9;
light.castShadow = true;
light.shadow.camera.near = 1000;
light.shadow.camera.far = 4000;
light.shadow.mapSize.width = 1024;
light.shadow.mapSize.height = 1024;
scene.add(light);
var elem = gltf.children[0];
scene.add(elem);
objects.push(elem);
renderer.setSize(renderer.domElement.width, renderer.domElement.height, false);
})
}
}
Answer: NO. Neither .obj nor .gltf support anything other than plain buffergeometry.
If you want to keep everything in its original format, for a example a sphere defined by a radius and number of subdivisions rather than just a bunch of triangles, you'll need to use three.js's custom format .json format used by the three.js editor which AFAICT is undocumented.
Unfortunately even it doesn't support any Geometry formats, only BufferGeometry formats like SphereBufferGeometry but it also doesn't currently support TextBufferGeometry though you could try to add support.
https://github.com/mrdoob/three.js/blob/513eceb0fedfd05089168bde81c5bb85ba0e6ec1/src/loaders/ObjectLoader.js#L200
One issue you'll need to deal with is loading and saving references to fonts.

I can't load the model using GLTFLoader

this.loadMyModel = function(){
const loader2 = new THREE.GLTFLoader();
// Load a glTF resource
loader2.load(
// resource URL
'Duck.gltf',
// called when the resource is loaded
function ( gltf ) {
//alert('success');
this.scene.add( gltf.scene );
})
};
The js files have been included.
I got an error, but I don't know why:
TypeError:undefined is not an object (evaluating 'this,scene.add')
Inside of your callback function, this is not the same as outside of the function. For more information on how this works in JS, I'd suggest this article: http://www.digital-web.com/articles/scope_in_javascript/
To fix the issue, you should save a reference to the scene outside the callback:
var scene = this.scene;
this.loadMyModel = function () {
// ...
loader.load( 'foo.glb', function ( gltf ) {
scene.add( gltf.scene );
} );
}
Alternatively, using newer JS features like arrow functions will also get around this problem.

How can i call the BufferGeometryUtils from threejs?

I tried to merge two geometries pre-loaded from two PLY files, the console of the browser told me should be use the BufferGeometryUtils.mergeBufferGeometries() for merge de two geometries into one, but I some problems for call this from the class.
Here is my code:
var scene = new THREE.Scene();
var singleGeometry, material, mesh;
var loader = new THREE.PLYLoader();
function loadPLY(path) {
return new Promise(resolve => {
loader.load(path, result => {
console.log('Success');
resolve(result);
});
});
}
init();
Promise.all([
loadPLY("ply/Paso_1_mandible.ply"),
loadPLY("ply/maxila.ply")
])
.then(geometries => {
geometries.forEach(geometry => geometry.computeVertexNormals());
singleGeometry = new THREE.BufferGeometry();
singleGeometry = THREE.BufferGeometryUtils.mergeBufferGeometries(geometries);
material = new THREE.MeshPhongMaterial({color: 0x0055ff });
mesh = new THREE.Mesh(singleGeometry, material);
mesh.position.y = 1;
mesh.position.z = 1;
mesh.position.x = 1;
mesh.scale.multiplyScalar( 0.0001 );
mesh.castShadow = true;
mesh.receiveShadow = true;
scene.add(mesh);
})
.then(() => {
animate();
})
.catch(err => {console.error(err);});
but I got this error:
TypeError: "THREE.BufferGeometryUtils is undefined"
here is the link to the documentation:
class BufferGeometryUtils
It's in examples/js/BufferGeometryUtils.js in the THREE master distro.
https://github.com/mrdoob/three.js/archive/master.zip
The error TypeError: "THREE.BufferGeometryUtils is undefined" is quite clear.
You need to include the BufferGeometryUtils class / file in your code.
As it is in the examples folder, it is not included in the main Three.js library.

Show only one side of 3D object Threejs

I have pb with threeJS obj, I loaded 3d object and want show only one side of this object not full,
export function loadObjWithMaterial(mtlFile, objFile, imgPath) {
let mtlLoader = new MTLLoader();
mtlLoader.setTexturePath(imgPath);
let url = mtlFile;
return new Promise((resolve, reject) => {
mtlLoader.load(url, materials => {
materials.preload();
let objLoader = new OBJLoader();
objLoader.setMaterials(materials);
objLoader.load(objFile, object => resolve(object));
objLoader.load(objFile, function(object){
resolve(object)
});
});
});
}
and now I tried to show only one side of the object and add this one
mtlLoader.setMaterialOptions({side: 1});
seems now it should show only one side of object but its not.
what i want
what i have now
You can try this one. Anyway 'THREE.FrontSide' is the default value for the side property.
mtlLoader.setMaterialOptions( { side : THREE.FrontSide } );
Here you can see the documentation

Resources