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
Related
I want to load a model in my scene, and the loading works well, but I want to keep a reference to it, so I can edit position and other variables later.
As you can see by the naming, the model is a boat. (not that that matters a whole bunch)
When I write the code like this it works, and I can edit the scale of the model:
function Boat(scene, loader) {
var boatObject;
this.SpawnBoat = function() {
loader.load('resources/SimpleBoat.gltf', handleLoad,
undefined, function (error) {
console.error(error);
});
}
function handleLoad(gltf) {
boatObject = gltf.scene;
scene.add(boatObject);
boatObject.scale.set(0.1,0.1,0.1);
} }
However, when I want to edit the variable after it's been loaded it says the variable is "undefined" and won't run the code.
function Boat(scene, loader) {
var boatObject;
this.SpawnBoat = function() {
loader.load('resources/SimpleBoat.gltf', handleLoad,
undefined, function (error) {
console.error(error);
});
boatObject.scale.set(0.1,0.1,0.1);
}
function handleLoad(gltf) {
boatObject = gltf.scene;
scene.add(boatObject);
} }
The boat function is called as followed, in a module that has reference to Three.js and GLTFLoader
const loader = new GLTFLoader();
const boat = new Boat(scene, loader);
const boatModel = boat.SpawnBoat();
Is there a way I can keep reference to the loaded model so I can edit proporties later?
been stuck for hours trying to figure out how to make my 3d model spin like a coin spinning. my code is below anything help i really appreciate you guys.
// add a light
const light = new THREE.AmbientLight(0xffffff,5)
scene.add(light);
// controls
// load object
const loader = new THREE.GLTFLoader();
loader.load('yattee.gltf', function (gltf) {
scene.add(gltf.scene);
})
const render = function() {
requestAnimationFrame(render)
// camera.rotation.z += .0010
renderer.render(scene, camera);
}
render();
Try it like so:
let myModel;
const loader = new GLTFLoader();
loader.load( 'model.gltf', function ( gltf ) {
myModel = gltf.scene;
scene.add( myModel );
} );
const render = function() {
requestAnimationFrame(render)
if ( myModel ) {
myModel.rotation.z += 0.01;
}
renderer.render(scene, camera);
}
The problem is, you are defining the model gltf inside a function, which means that it cannot be accessed from render(). In order to spin the model, you need to define the variable gltf prior to loading the model, so it can be stored inside of it:
const loader = new THREE.GLTFLoader();
var gltf; //By defining it prior to loading, it is now in global scope.
loader.load('yattee.gltf', function (gltf) {
scene.add(gltf.scene);
})
Then, you can add the flipping effect in the render() loop. Make sure that you add the given if statement so it doesn't crash before the model even loads!
const render = function() {
requestAnimationFrame(render);
if(gltf) {
gltf.rotation.z += .0010; //Make sure you rotate the gltf, not the camera.
}
renderer.render(scene, camera);
}
And that should do it!
Note: I've taken a look at some of the other answers, and it seems like they either don't work, or they don't explain what they are doing properly. I think that this should help you achieve what you want.
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 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.
am exporting my models using ObjectExporter, my code is follows
exporter = new THREE.ObjectExporter;
var obj = exporter.parse(globalObject);
var json = JSON.stringify(obj);
console.log(json);
i can get the json exported data successfully, but after load it using ObjectLoader the Geometry only loading materials are not loading, am loading my saved model by following code
var loader = new THREE.ObjectLoader();
loader.load("savedjson.json",function ( obj ) {
scene.add( obj );
console.log(obj);
});
any clue to get materials work with the ObjectExporter?
I had the same problem. I have a first attempt at a workaround(but it needs to be improved for sure). What I do is, after loading the object, I traverse the model
loader.load("savedjson.json", function (obj){
obj.traverse(function(child){ initChild(child); });
scene.add(obj);
}
In initChild(child) I do this:
initChild(child)
{
if(child.material != null)
{
var childMaterialName = child.material.name;
child.material = new THREE.MeshPhongMaterial();
child.material.name = childMaterialName ;
AssignMap(child.material);
}
}
In AssignMap(material) I first load the textures, then assign them based on the material name:
AssignMap(material)
{
var texture_metal = new THREE.ImageUtils.loadTexture("media/texture_metal.jpg");
var texture_glass = new THREE.ImageUtils.loadTexture("media/texture_glass.jpg");
if(material.name == "metal texture")
{
material.map = texture_metal;
}
if(material.name == "glass texture")
{
material.map = texture_glass;
}
}