Actually I am trying to upload these .obj and .mtl file by OBJMTLloader. all is working fine but the image in mtl file is loaded by map_d is not uploaded.
newmtl Eyelashes
Ns 10.0000
Ni 1.5000
d 0.5000
Tr 0.0000
Tf 1.0000 1.0000 1.0000
illum 2
Ka 0.5880 0.5880 0.5880
Kd 0.5880 0.5880 0.5880
Ks 0.0000 0.0000 0.0000
Ke 0.0000 0.0000 0.0000
map_Ka EyelashesDiffuseTexture.jpg
map_Kd EyelashesDiffuseTexture.jpg
map_d EyeLashes_Opacity_Texture.jpg
My code is
var loader = new THREE.OBJMTLLoader();
loader.load( 'upload/model.obj', 'upload/model.mtl', function ( object ) {
object.position.y = -35;
scene.add( object );
} );
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
What i need to change in my code.
I try so may example and checked so many answers but not get helpful answer.
Now three.js supports alpha maps. But you need change MTLLoaded.js. Add to createMaterial_
case 'map_d':
// Alpha texture map
params[ 'alphaMap' ] = this.loadTexture( this.baseUrl + value );
params[ 'transparent' ] = true;
break;
three.js r.74
three.js does not support alpha-maps in any of its materials.
The work-around is to bake the alpha-map into the alpha-channel of the diffuse map.
three.js r.66
Related
I would like to render my user generated obj instead of loading from file.
In my example below, objString represents a cube.
The browser just show a dark screen. I'm expecting the display of a green cube rotating.
I wonder what I'm missing
import React from 'react';
import * as THREE from "three";
import { OBJLoader } from "three/examples/jsm/loaders/OBJLoader"
class App extends React.Component {
componentDidMount() {
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );
let loader = new OBJLoader();
// obj string below represents a cube
var objString = `
v 0.000000 2.000000 2.000000
v 0.000000 0.000000 2.000000
v 2.000000 0.000000 2.000000
v 2.000000 2.000000 2.000000
v 0.000000 2.000000 0.000000
v 0.000000 0.000000 0.000000
v 2.000000 0.000000 0.000000
v 2.000000 2.000000 0.000000
f 1 2 3 4
f 8 7 6 5
f 4 3 7 8
f 5 1 4 8
f 5 6 2 1
f 2 6 7 3
`;
var cube = loader.parse(objString);
scene.add( cube );
// var geometry = new THREE.BoxGeometry( 1, 1, 1 );
// var material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
// var cube = new THREE.Mesh( geometry, material );
// scene.add( cube );
camera.position.z = 5;
var animate = function () {
requestAnimationFrame( animate );
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render( scene, camera );
};
animate();
}
render() {
return (
<div></div>
);
}
}
export default App;
OBJLoader actually works fine. The problem is that the loader returns meshes with MeshPhongMaterial which is a lit material. Since you don't have any lights in your scene, you just have a black screen. Try it like so:
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );
camera.position.z = 5;
let loader = new THREE.OBJLoader();
// obj string below represents a cube
var objString = `
v 0.000000 2.000000 2.000000
v 0.000000 0.000000 2.000000
v 2.000000 0.000000 2.000000
v 2.000000 2.000000 2.000000
v 0.000000 2.000000 0.000000
v 0.000000 0.000000 0.000000
v 2.000000 0.000000 0.000000
v 2.000000 2.000000 0.000000
f 1 2 3 4
f 8 7 6 5
f 4 3 7 8
f 5 1 4 8
f 5 6 2 1
f 2 6 7 3
`;
var cube = loader.parse(objString);
scene.add( cube );
var hemiLight = new THREE.HemisphereLight( 0xffffff, 0x444444 );
hemiLight.position.set( 0, 20, 0 );
scene.add( hemiLight );
var dirLight = new THREE.DirectionalLight( 0xffffff );
dirLight.position.set( - 3, 10, - 10 );
scene.add( dirLight );
var animate = function () {
requestAnimationFrame( animate );
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render( scene, camera );
};
animate();
body {
margin: 0px;
}
canvas {
display: block;
}
<script src="https://cdn.jsdelivr.net/npm/three#0.116.1/build/three.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three#0.116.1/examples/js/loaders/OBJLoader.js"></script>
Here I have a simple script that uses Three.JS MTL Loader and OBJ loader to load a model and the material for the model.
Now when it loads the model it only loads the first objects color and the rest it leaves white. Can anyone shed some light on what may be the cause of thise ?
Here is my code
var loader = new THREE.MTLLoader();
loader.load('http://ustarp.com/3DModels/WebsiteParts/Polished Aluminum/Underbody/11228.mtl', function (materials) {
materials.preload();
var objLoaderOfficeChair = new THREE.OBJLoader();
objLoaderOfficeChair.setMaterials(materials);
objLoaderOfficeChair.load('http://ustarp.com/3DModels/WebsiteParts/Polished Aluminum/Underbody/11228.obj', function (object) {
object.traverse( function ( child ) {
if ( child instanceof THREE.Mesh ){
x=document.getElementsByClassName("popup"); // Find the elements
for(var i = 0; i < x.length; i++){
x[i].innerHTML += "<li class='mi_child'>"+child.name+"</li>"; // Change the content
}
}
});
object.name = 'Part1';
object.scale.set(50,50,50);obj3d.add( object );
object.updateMatrix();
model2 = object;
scene.add(object);
});
});
Here is an example of the model being shown.
http://ustarp.com/3DModels/?part=2c75cf2681788adaca63aa95ae028b22
Your mtl file is not formatted correctly:
# WaveFront *.mtl file (generated by Autodesk ATF)
newmtl 254,254,255
Ka 0.996078 0.996078 1.000000
Kd 0.996078 0.996078 1.000000
Ks 0.996078 0.996078 1.000000
Ns 1000.000000
d 1.000000
newmtl 229,31,31
Ka 0.898039 0.121569 0.121569
Kd 0.898039 0.121569 0.121569
Ks 1.000000 1.000000 1.000000
Ns 1000.000000
d 1.000000
newmtl takes a string to be used as an identifier.
Edit
What you can do is replace the string 254,254,255 with the string white and the string 229,31,31 with the string redish in the mtl file and the obj file.
This is my code:
var mtlLoader = new THREE.MTLLoader();
mtlLoader.setPath( '3dAssets/structure1/' );
mtlLoader.load( 'Structure_Combined.mtl', function( materials ) {
materials.preload();
mtl = materials;
var objLoader = new THREE.OBJLoader();
objLoader.setMaterials( materials );
objLoader.setPath( '3dAssets/structure1/' );
objLoader.load( 'Structure_Combined.obj', function ( object ) {
object.position.y = - 13;
scene.add( object );
});
});
The following is my .mtl file:
newmtl aiStandard2SG
illum 4
Kd 0.00 0.00 0.00
Ka 0.00 0.00 0.00
Tf 1.00 1.00 1.00
Ni 1.00
map_Kd Suela_Master_A.jpg
newmtl aiStandard3SG
illum 4
Kd 0.00 0.00 0.00
Ka 0.00 0.00 0.00
Tf 1.00 1.00 1.00
Ni 1.00
map_Kd Suela_A2.jpg
Every answer regarding this topic uses .dds texture maps, however at the time of loading, it doesn't seem to even attempt to load jpg files, .dds files add a handler with the following code to allow the loading:
THREE.Loader.Handlers.add( /.dds$/i, new THREE.DDSLoader() );
Maybe there's a similar thing for jpg?
It seems that OBJMTLLoader has been removed recently (r74?), but I cannot track down any documentation on how to use the two replacement classes. Here is the current code I have (adapted from Three.js Cookbook):
<script src="../libs/three.r74.js"></script>
<script src="../libs/MTLLoader.js"></script>
<script src="../libs/OBJMTLLoader.js"></script>
<script>
var legoManMesh = null;
function init(){ /* Create my scene here */ }
var loader = new THREE.OBJMTLLoader();
loader.load("../assets/models/lego.obj", "../assets/models/lego.mtl",
function (obj) {
legoManMesh = obj;
init();
}
);
</script>
(BTW, when moving from r69 to r74 the above code fails with "TypeError: loader.setCrossOrigin is not a function")
ADDITIONAL:
The sample lego.mtl file here references a texture png using a relative path.
# Blender MTL File: 'LEGO Minifigure - Blendswap.blend'
# Material Count: 2
newmtl Cap
Ns 96.078431
Ka 0.000000 0.000000 0.000000
Kd 0.990000 0.120000 0.120000
Ks 0.500000 0.500000 0.500000
Ni 1.000000
d 1.00000
illum 2
newmtl Minifig
Ns 874.999998
Ka 0.000000 0.000000 0.000000
Kd 0.800000 0.800000 0.800000
Ks 0.200000 0.200000 0.200000
Ni 1.000000
d 1.000000
illum 2
map_Kd ../textures/Mini-tex.png
Here is code that demonstrates how to load .obj and .mtl files in r74:
var mesh = null;
var mtlLoader = new THREE.MTLLoader();
mtlLoader.setPath( "https://threejs.org/examples/models/obj/walt/" );
mtlLoader.load( 'WaltHead.mtl', function( materials ) {
materials.preload();
var objLoader = new THREE.OBJLoader();
objLoader.setMaterials( materials );
objLoader.setPath( "https://threejs.org/examples/models/obj/walt/" );
objLoader.load( 'WaltHead.obj', function ( object ) {
mesh = object;
mesh.position.y = -50;
scene.add( mesh );
} );
} );
Fiddle at: http://jsfiddle.net/g2evz0q5/
Updated answer to reflect correction for completeness.
I have read a lot of questions and articles about this issue, but anyway png images for models are not transparent. Instead it has white background. Like:
three.js: how to apply alpha-map when using OBJMTL loader?
Assigning Alpha channels to OBJ/MTL model meshes
Three.js png texture - alpha renders as white instead as transparent
Maybe someone has ideas how to fix it and what code to add?
renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
var loader = new THREE.OBJMTLLoader();
loader.crossOrigin = 'anonymous';
loader.load( 'model.obj', 'model.mtl', function ( object ) {
object.position.set(0, 0, 0);
object.traverse( function ( child ) {
if ( child instanceof THREE.Mesh ) {
child.castShadow = true;
child.receiveShadow = true;
}
if ( child.material instanceof THREE.MeshPhongMaterial ) {
child.material.opacity = 1;
// child.material.alphaTest = 0.5;
// child.material.depthWrite = false;
// child.material.depthTest = false;
// child.material.side = THREE.BackSide;
child.material.transparent = true;
}
});
scene.add(object);
});
model.mtl:
newmtl Cap
Ns 37.6553
Ni 1.5000
d 0.9990
Tr 0.0010
Tf 0.9990 0.9990 0.9990
illum 2
Ka 0.7333 0.7333 0.7333
Kd 1.0000 1.0000 1.0000
Ks 0.0980 0.0980 0.0980
Ke 0.0000 0.0000 0.0000
map_Kd Cap_01.png
map_bump Cap_01_Normal.png
bump Cap_01_Normal.png
newmtl Bark
Ns 37.6553
Ni 1.5000
d 1.0000
Tr 0.0000
Tf 1.0000 1.0000 1.0000
illum 2
Ka 0.7333 0.7333 0.7333
Kd 1.0000 1.0000 1.0000
Ks 0.0980 0.0980 0.0980
Ke 0.0000 0.0000 0.0000
map_Kd BroadleafBark.png
map_bump BroadleafBark_Normal.png
bump BroadleafBark_Normal.png
newmtl Leaves
Ns 37.6553
Ni 1.5000
d 1.0000
Tr 0.0000
Tf 1.0000 1.0000 1.0000
illum 2
Ka 0.7647 0.7647 0.7647
Kd 1.0000 1.0000 1.0000
Ks 0.4118 0.4118 0.4118
Ke 0.0000 0.0000 0.0000
map_Kd BroadleafLeaves.png
map_Ks BroadleafLeaves_Spec.png
map_d BroadleafLeaves_Alpha.png
map_bump BroadleafLeaves_Normal.png
bump BroadleafLeaves_Normal.png
Finally! I found solution. I have converted .obj to .js loader with authors of threejs python script (How to convert object to json file for three.js model loader) and then use JSONLoader():
var loader = new THREE.JSONLoader();
loader.load('model.js', function(geometry, materials) {
var material = new THREE.MeshFaceMaterial(materials);
var object = new THREE.Mesh(geometry, material);
...