Import 3D model Threejs - three.js

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 );
} )

Related

how do we load multiple OBJ Loader & MTL Loader in array (Three.js)

It is only Loading Last model which in the array.
based on this source
Create an instance of LoadingManager and apply it to the ctor of all loaders you are going to create. In the next step, assign an onLoad() callback to the manager so you can execute code when everything has been loaded.
but I don't know how to write it
this is my code
// build markerControls
let patternArray = ["hiro", "pattern-markerobj1"];
let colorArray = [0xff8800, 0xffff00, ];
let mtlobj = ['fish-2', 'percobaan', ];
let scale = [0.25, 0.0025, ];
for (let i = 0; i < 2; i++) {
markerRoot1 = new THREE.Group();
scene.add(markerRoot1);
let markerControls1 = new THREEx.ArMarkerControls(arToolkitContext, markerRoot1, {
type: 'pattern',
patternUrl: "data/" + patternArray[i] + ".patt",
})
let geometry1 = new THREE.PlaneBufferGeometry(1, 1, 4, 4);
// let texture = loader.load( 'images/earth.jpg', render );
let material1 = new THREE.MeshBasicMaterial({
color: colorArray[i],
opacity: 0.0005
});
mesh1 = new THREE.Mesh(geometry1, material1);
mesh1.rotation.x = -Math.PI / 2;
markerRoot1.add(mesh1);
function onProgress(xhr) {
console.log((xhr.loaded / xhr.total * 100) + '% loaded');
}
function onError(xhr) {
console.log('An error happened');
}
new THREE.MTLLoader()
.setPath('models/')
.load(mtlobj[i] + '.mtl',function (materials) {
materials.preload();
new THREE.OBJLoader()
.setMaterials(materials)
.setPath('models/')
.load(mtlobj[i] + '.obj', function (group) {
mesh0 = group.children[0];
mesh0.material.side = THREE.DoubleSide;
mesh0.position.y = 0.25;
mesh0.scale.set(scale[i], scale[i], scale[i]);
markerRoot1.add(mesh0);
}, onProgress, onError);
});
}
screenshot: all 3D models are loaded in the last marker :')
the fish model (mtlobj[0]) should be included in the Hiro index[0] marker. but the hiro marker doesn't contain fish ->screenshot: marker hero -> why no fish?
can you help me to rewrite the code using LoadingManager according to this directive ? Mugen87
?

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.

How can do uniformly (same sized checker boxes) of custom checkered texture image which applied on all objects of Model which loaded in Three Js?

I have loaded one model (obj file) in three js and applied custom checker texture image on all objects. Texture is applied on Model. But, issue is that - checker are not like uniformly - some checker are look small and some are look larger.
Here is link of screenshot.
Is there any way to fix it ? I mean - any calculation on geometry or any in-built properties of texture etc. in three js.
Here is link of model file Model.obj
loaded this model in three js and applied texture image.
// Below some code which I have tried.
function loadModel() {
object.traverse( function ( child ) {
if (child.type.toLowerCase() == "mesh" && child.material) {
if (child.material.length) {
for (var i=0; i < child.material.length; i++) {
child.material[i].map = texture;
child.material[i].needsUpdate = true;
}
}
else {
child.material.map = texture;
child.material.needsUpdate = true;
}
}
} );
scene.add( object );
}
manager = new THREE.LoadingManager( loadModel );
manager.onProgress = function ( item, loaded, total ) {
console.log( item, loaded, total );
};
textureLoader = new THREE.TextureLoader( manager );
texture = textureLoader.load(currentTextureUrl); // texture checker image
texture.onUpdate = true;
function onProgress( xhr ) {
if ( xhr.lengthComputable ) {
var percentComplete = xhr.loaded / xhr.total * 100;
console.log( 'model ' + Math.round( percentComplete, 2 ) + '% downloaded' );
}
}
function onError() {}
var loader = new THREE.OBJLoader( manager );
loader.load(modals.currentModal.objectFile, function ( obj ) {
object = obj;
}, onProgress, onError );

Simply assign a Material to loaded .OBJ - ThreeJS

I've been hitting myself overhead with this one for the good three hours now..
My question is, would someone be kind enough to reorganize my example in such a way, that the object that I load comes with a color, any color
var loader = new THREE.OBJLoader()
loader.load( 'learning/exported1.obj', function ( object )
{
object.traverse( function (child)
{
if ( child instanceof THREE.Mesh )
{
child.material.color.setHex( 0xffffff );
}
}
var OBJBoundingBox = new THREE.Box3().setFromObject(object);
OBJBoundingBox.center(object.position);
object.position.multiplyScalar(-1);
object.position.x = object.position.x;
object.position.y = object.position.y;
object.position.z = object.position.z;
scene.add( object );
}, onProgress, onError );
If I throw the traverse part away the object is loaded successfully but is a simple white color, with it, the object does not appear on my screen...
<script src="../build/three.js"></script>
<script src="js/loaders/OBJLoader.js"></script>
<script src="js/controls/OrbitControls.js"></script>
<script src="js/shaders/CopyShader.js"></script>
<script src="js/shaders/SMAAShader.js"></script>
<script src="js/postprocessing/EffectComposer.js"></script>
<script src="js/postprocessing/SMAAPass.js"></script>
<script src="js/postprocessing/RenderPass.js"></script>
<script src="js/postprocessing/MaskPass.js"></script>
<script src="js/postprocessing/ShaderPass.js"></script>
<script src="js/libs/dat.gui.min.js"></script>
These are my imports in case you think the problem lies in here
Thanks so much in advance, this is a project which I'm developing independently and would love it if I can get it working!
I feel like an idiot but the thing I was missing was
);
at the end of object.traverse function
var loader = new THREE.OBJLoader()
loader.load( 'learning/exported1.obj', function ( object )
{
object.traverse( function (child)
{
if ( child instanceof THREE.Mesh )
{
child.material.color.setHex( 0xffffff );
}
});
// ^This over here^
var OBJBoundingBox = new THREE.Box3().setFromObject(object);
OBJBoundingBox.center(object.position);
object.position.multiplyScalar(-1);
object.position.x = object.position.x;
object.position.y = object.position.y;
object.position.z = object.position.z;
scene.add( object );
}, onProgress, onError );
Assigning a material now works perfectly with this code.

Artifacts in loaded texture - Three js

I am trying to render an object with UV maps and updating the texture with a loaded image thru Three JS. My problem is, I'm having artifacts on the rendered result. Why does this happen?
Notes:
Object is from a gltf file
I used blender for creating the model
I used KhronosGroup's blender gltf exporter for exporting the model
Image texture is 3239x2745 big
Here's my code
var inside_image = load_image("texture/inside.jpg");
var outside_image = load_image("texture/outside.jpg");
var textures = [];
Promise.all([inside_image, outside_image]).then((images)=>{
console.log('image', images);
for (var i in images) {
var canvas = document.createElement('canvas');
var compositeTexture = new THREE.Texture(canvas);
compositeTexture.wrapS = compositeTexture.wrapT = THREE.RepeatWrapping;
compositeTexture.repeat.y = -1;
var ctx = canvas.getContext('2d');
canvas.width = images[i].width;
canvas.height = images[i].height;
ctx.globalCompositeOperation = 'source-over';
ctx.fillRect(0,0,0,0);
ctx.drawImage(images[i], 0, 0, images[i].width, images[i].height);
compositeTexture.needsUpdate = true;
textures.push(compositeTexture);
}
loader.load(
'http://local.webgl.com/model.gltf',
function ( gltf ) {
console.log('gltf', gltf);
gltf.scene.traverse( function ( child ) {
if ( child.isMesh ) {
if (child.material.name == "Inside") {
child.material.map = textures[0];
} else {
child.material.map = textures[1];
}
console.log('child', child);
}
});
scene.add(gltf.scene);
// mixer = new THREE.AnimationMixer(gltf.scene);
// animations = gltf.animations;
},
// called when loading is in progresses
function ( xhr ) {
console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );
},
// called when loading has errors
function ( error ) {
console.log( 'An error happened', error );
}
);
});

Resources