3D object turning black on loading the mtl file - javascript

On loading the MTL file, the entire model is turning black. I have referred to this link and set the rbg parameters to 1 but that hasnt solved my issue.
three.js mtl loader renders black
Here is the code associated with it:
var scene = new THREE.Scene();
scene.background = new THREE.Color('0xf1f1f1');
var axesHelper = new THREE.AxesHelper( 5 );
scene.add( axesHelper );
const canvas = document.querySelector('#scene1');
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );
camera.position.set(5,5,5);
scene.add(camera);
var renderer = new THREE.WebGLRenderer({ canvas, antialias: true });
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
var controls = new THREE.OrbitControls(camera, renderer.domElement);
//controls.autoRotate = true;
//controls.autoRotateSpeed = 5;
controls.enableZoom = true;
var keyLight = new THREE.DirectionalLight(new THREE.Color('hsl(30, 100%, 75%)'), 1.0);
keyLight.position.set(-100, 0, 100);
var fillLight = new THREE.DirectionalLight(new THREE.Color('hsl(240, 100%, 75%)'), 0.75);
fillLight.position.set(20, 20, 20);
var backLight = new THREE.DirectionalLight(0xffffff, 1.0);
backLight.position.set(20, 20, -20).normalize();
var ambientLight = new THREE.AmbientLight();
var pointLight = new THREE.PointLight(0xffffff,1,100);
pointLight.position.set(20,20,20);
var pointLight2 = new THREE.PointLight(0xffffff,0.5,100);
pointLight2.position.set(20,-20,20);
var pointLight3 = new THREE.PointLight(0xffffff,0.5,100);
pointLight3.position.set(-20,20,-20);
var pointLight4 = new THREE.PointLight(0xffffff,0.5,100);
pointLight4.position.set(-20,-20,-20);
//scene.add(ambientLight);
scene.add(pointLight);
scene.add(pointLight2);
scene.add(pointLight3);
scene.add(pointLight4);
//scene.add(keyLight);
//scene.add(fillLight);
//scene.add(backLight);
var mtlLoader = new THREE.MTLLoader();
//mtlLoader.setTexturePath('https://i.ibb.co/n1vnyP6/piper-diffuse.jpg');
mtlLoader.setPath('https://raw.githubusercontent.com/fnaseem/3dModelTest/tc/Test/');
mtlLoader.load('soccer_ball.mtl',function(material){
material.preload();
var objLoader = new THREE.OBJLoader();
objLoader.setMaterials(material);
objLoader.load('https://raw.githubusercontent.com/fnaseem/3dModelTest/tc/Test/soccer_ball.obj', function(object){
object.position.set(0,0,0);
console.log(object.children[0].material.color);
object.children[0].material.color.r = 1;
object.children[0].material.color.g = 1;
object.children[0].material.color.b = 1;
console.log(object.children[0].material.color);
scene.add(object);
//renderer.render(scene, camera);
});
});
var animate= function(){
controls.update();
renderer.render( scene, camera );
requestAnimationFrame( animate );
};
animate();
Here is the link to the codepen:
https://codepen.io/FarhaNaseem/pen/gOmwbYj?editors=0010
What I am expecting is this output:

The MTL loads the texture as a TIFF image which can't be used as an image data source. Use JPG or PNG instead.
Sidenote: You will notice that the object's material has a texture assigned to the map property but with an undefined image value. In such a case, the texture appears black.

Related

Need help in figuring out why my 3d model is not being rendered in the browser

I am new to three.js and 3D model rendering and have been playing around with this sample code that i found on the internet. My aim here is to be able to render my 3D model using the chrome browser.
The default code is :
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
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.1;
cube.rotation.y += 0.1;
renderer.render(scene, camera);
};
animate();
When i go to my browser and type in http://localhost:8080/ i get a cube rotating
Now i try modifying the code to
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );
camera.position.z = 200;
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
var controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.25;
controls.enableZoom = true;
var keyLight = new THREE.DirectionalLight(new THREE.Color('hsl(30, 100%, 75%)'), 1.0);
keyLight.position.set(-100, 0, 100);
var fillLight = new THREE.DirectionalLight(new THREE.Color('hsl(240, 100%, 75%)'), 0.75);
fillLight.position.set(100, 0, 100);
var backLight = new THREE.DirectionalLight(0xffffff, 1.0);
backLight.position.set(100, 0, -100).normalize();
scene.add(keyLight);
scene.add(fillLight);
scene.add(backLight);
var mtlLoader = new THREE.MTLLoader();
mtlLoader.setTexturePath('/examples/3d-obj-loader/assets/');
mtlLoader.setPath('/examples/3d-obj-loader/assets/');
mtlLoader.load('r2-d2.mtl', function (materials) {
materials.preload();
var objLoader = new THREE.OBJLoader();
objLoader.setMaterials(materials);
objLoader.setPath('/examples/3d-obj-loader/assets/');
objLoader.load('r2-d2.obj', function (object) {
scene.add(object);
object.position.y -= 60;
});
});
var animate = function () {
requestAnimationFrame( animate );
controls.update();
renderer.render(scene, camera);
};
animate();
This should give me an image of r2-d2 model being rendered but i see a blank screen
I would really appreciate help in understanding what i am missing.

Why does "light.castShadow = true" cause my scene to break?

I am trying to build a simple solar system with sun, earth and moon, using threejs. The system includes lighting and shadows.
My only problem is, while creating the shadow that will be cast from earth to the moon and vice-versa, my script will stop working.
Console gives me an error of "isMultiSample is not defined".
I have tried searching the web but could not find any solutions to why the error would occur.
The part causing problems:
var sunLight = new THREE.PointLight(0x404040, 10, 1000000);
sunLight.position.set(0, 0, 0);
sunLight.castShadow = true; // This line will cause the error
Full code:
<script>
var camera, scene, renderer;
var spaceBox, sunPivot, earthPivot, moonPivot;;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 4000000 );
camera.position.z = 2400;
scene = new THREE.Scene();
// Surrounding space
var texture = new THREE.TextureLoader().load( 'space.jpg' );
var skygeometry = new THREE.BoxBufferGeometry( 15000, 15000, 15000 );
var skymaterial = new THREE.MeshBasicMaterial({ map: texture, side : THREE.DoubleSide});
spaceBox = new THREE.Mesh(skygeometry, skymaterial);
scene.add(spaceBox);
// Sun, earth and moon textures
var sunTexture = new THREE.TextureLoader().load('sun.jpg')
var sunGeometry = new THREE.SphereBufferGeometry(800, 32, 32);
var sunMaterial = new THREE.MeshPhongMaterial({ map: sunTexture });
var earthTexture = new THREE.TextureLoader().load('earth.jpg')
var earthGeometry = new THREE.SphereBufferGeometry(250, 32, 32);
var earthMaterial = new THREE.MeshPhongMaterial({ map: earthTexture, side: THREE.DoubleSide });
var moonTexture = new THREE.TextureLoader().load('moon.jpg')
var moonGeometry = new THREE.SphereBufferGeometry(80, 32, 32);
var moonMaterial = new THREE.MeshPhongMaterial({ map: moonTexture, side: THREE.DoubleSide });
// LIGHTS
var ambientLight = new THREE.AmbientLight(0x404040,3); // soft white light
scene.add(ambientLight);
var sunLight = new THREE.PointLight(0x404040, 10, 1000000);
sunLight.position.set(0, 0, 0);
//sunLight.castShadow = true;
sunLight.shadow.mapSize.width = 1024;
sunLight.shadow.mapSize.height = 1024;
sunLight.shadow.camera.near = 500;
sunLight.shadow.camera.far = 10000;
sunLight.shadow.camera.fov = 30;
scene.add(sunLight);
// Add sun, earth and moon rotating around eachother
sun = new THREE.Mesh(sunGeometry, sunMaterial);
scene.add(sun);
earthPivot = new THREE.Object3D();
sun.add(earthPivot);
earth = new THREE.Mesh(earthGeometry, earthMaterial);
earth.position.x = 4000;
earth.castShadow = true;
earth.receiveShadow = true;
earthPivot.add(earth);
moonPivot = new THREE.Object3D();
earth.add(moonPivot);
var moon = new THREE.Mesh(moonGeometry, moonMaterial);
moon.position.x = 750;
moon.castShadow = true;
moon.receiveShadow = true;
moonPivot.add(moon);
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
//
controls = new THREE.OrbitControls(camera, renderer.domElement);
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function animate() {
earthPivot.rotation.y += 0.002;
moonPivot.rotation.y += 0.005;
requestAnimationFrame( animate );
controls.update();
renderer.render( scene, camera );
}</script>

How to animate the gltf model with threejs

I have a cube model which is GLTF format, now i am trying to animate it by changing the textures material.
Now currently, there are 300 heat map images as the texture material, the requirement from supervisor is animating the cube model by loading heat map images one by one.
Texture materials set
About the animation, I tried to use VectorKeyFrameTrack to change the child.material. But it does not work.
the codes:
if (WEBGL.isWebGLAvailable() === false) {
document.body.appendChild(WEBGL.getWebGLErrorMessage());
}
var camera, scene, renderer;
init();
function init() {
//init scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x999999);
//add directional light and spotlight
var light = new THREE.DirectionalLight(0xffffff);
light.position.set(3, 15.0, -29).normalize();
scene.add(light);
var light1 = new THREE.DirectionalLight(0xffffff);
light.position.set(-20, 7.0, -2).normalize();
scene.add(light1);
var light2 = new THREE.DirectionalLight(0xffffff);
light.position.set(-5, 15.0, 30).normalize();
scene.add(light2);
var light3 = new THREE.DirectionalLight(0xffffff);
light.position.set(15, 5.0, -15).normalize();
scene.add(light3);
//add camera
camera = new THREE.PerspectiveCamera(35, window.innerWidth / window.innerHeight, 1, 500);
camera.position.y = 5;
camera.position.z = 10;
scene.add(camera);
//add grid
var grid = new THREE.GridHelper(50, 50, 0xffffff, 0x555555);
scene.add(grid);
renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
//Generate textures array
var loadedTexture = new THREE.TextureLoader().load("1.png");
var material = new THREE.MeshBasicMaterial({map: loadedTexture});
var loadedTexture2 = new THREE.TextureLoader().load("2.png");
var material1 = new THREE.MeshBasicMaterial({map: loadedTexture2});
//Load Collada file
var path = "./image/"
var format = ".png";
var a = "Avg_Displacement_";
var material_list = [];
var times = [];
for (var i = 0; i <= 314; i++) {
var loadedTexture = new THREE.TextureLoader().load(path + a + i + format);
var material = new THREE.MeshBasicMaterial({map: loadedTexture});
material_list.push(material);
times.push(i);
}
console.log(material_list);
var loader = new THREE.GLTFLoader();
loader.load('scene.gltf', function (gltf) {
gltf.scene.scale.set(0.3, 0.3, 0.3);
// console.log(gltf.scene.children[0].material);
// var kf = new THREE.VectorKeyframeTrack( '.scene.material', times, material_list );
// var clip = new THREE.AnimationClip('Action', 315, [kf]);
//
// mixer = new THREE.AnimationMixer(gltf);
// var clipAction = mixer.clipAction(clip);
// clipAction.play();
gltf.scene.traverse(function (child) {
if (child.isMesh) {
var kf = new THREE.VectorKeyframeTrack('child.material', times, material_list);
var clip = new THREE.AnimationClip('Action', 3, [kf]);
mixer = new THREE.AnimationMixer(child);
var clipAction = mixer.clipAction(clip);
clipAction.play()
// child.material = material;
}
scene.add(gltf.scene);
});
});
var controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.addEventListener('change', render);
controls.update();
window.addEventListener('resize', onWindowResize, false);
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
render();
}
function render() {
renderer.render(scene, camera);
}
// function animate() {
//
// requestAnimationFrame( animate );
//
// mesh.material.map.offset.x += 0.005;
// mesh.material.map.offset.y += 0.005;
//
// renderer.render( scene, camera );
//
// }
child.material
the second problem is how to animate the model by loading each image as the texture as material.

Rendering to render target makes some of my graphics invisible

Hi I have been playing with render targets but I ran into some problems. I created a simplified example here:
init = function() {
// RENDERER
canvas = document.getElementById("mycanvas");
renderer = new THREE.WebGLRenderer({
antialias: true
});
document.body.appendChild( renderer.domElement );
renderer.setClearColor(0x000000, 1.0);
renderer.setSize(window.innerWidth, window.innerHeight);
// SCENE
texscene = new THREE.Scene();
texcamera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1000 );
texcamera.position.z = 2;
// FRAMEBUFFER
var renderTargetParams = {
minFilter:THREE.LinearFilter,
stencilBuffer:false,
depthBuffer:false,
wrapS: THREE.RepeatWrapping,
wrapT: THREE.RepeatWrapping
};
rendertarget = new THREE.WebGLRenderTarget( 512, 512, renderTargetParams );
// CUBE
var cubeGeo = new THREE.BoxGeometry( 1, 1, 1, 1, 1, 1 );
var cubeMat = new THREE.MeshBasicMaterial( { color: 0xff0000 } );
texcube = new THREE.Mesh( cubeGeo, cubeMat )
texscene.add(texcube);
var blueMaterial = new THREE.MeshBasicMaterial({color:0x7074FF})
var plane = new THREE.PlaneBufferGeometry( 100, 100 );
var planeObject = new THREE.Mesh(plane,blueMaterial);
planeObject.position.z = -15;
texscene.add(planeObject);
/////////////////////////////////
//SCENE
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1000 );
var boxMaterial = new THREE.MeshBasicMaterial({map:rendertarget.texture});
var boxGeometry2 = new THREE.BoxGeometry( 5, 5, 5 );
mainBoxObject = new THREE.Mesh(boxGeometry2,boxMaterial);
// Move it back so we can see it
mainBoxObject.position.z = -10;
// Add it to the main scene
scene.add(mainBoxObject);
animate();
}
animate = function() {
requestAnimationFrame(animate);
renderer.render(texscene, texcamera, rendertarget);
renderer.render(scene, camera);
texcube.rotation.y += 0.01;
texcube.rotation.z += 0.01;
mainBoxObject.rotation.x +=0.01;
mainBoxObject.rotation.y += 0.005;
mainBoxObject.rotation.z += 0.008;
}
init();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r83/three.js"></script>
I render a red cube and a blue plane to a render target then use it as a texture. Problem is the red cube is not visible in the final result.
Try for yourself to see the render target scene by changing
renderer.render(texscene, texcamera, rendertarget);
renderer.render(scene, camera);
to
renderer.render(texscene, texcamera);
Apparantly the problem is caused by turning off the depth buffer as I had done in the settings of my rendertarget
depthBuffer:false,
Removing this line makes my rendertarget render as it should with a red box on a blue background

Plane always black

I want to add a texture to my plane that repeats horizontal and vertical. The thing is, when I try to apply the texture, it is always black. I don't get any errors, and i already tried to add some lights, but the problem is still there; I don't know how to solve it... Here is what I did:
window.onload = function init()
{
scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.x = -30;
camera.position.y = 40;
camera.position.z = 30;
camera.lookAt(scene.position);
var light = new THREE.AmbientLight( 0x404040 ); // soft white light
scene.add( light );
var spotlight = new THREE.SpotLight( 0xffffff);
spotlight.position.set( -50, 40, 0 );
scene.add( spotlight );
var axes = new THREE.AxisHelper( 20 ); scene.add(axes);
var renderer = new THREE.WebGLRenderer();
renderer.setClearColor(0xEEEEEE);
renderer.setSize(window.innerWidth, window.innerHeight);
desenhaMapa();
document.body.appendChild( renderer.domElement );
renderer.render(scene, camera);
}
function desenhaMapa()
{
labirinto = new THREE.Object3D();
var texturaPlano = new THREE.TextureLoader().load("texturaPac.jpg");
geometryPlano = new THREE.PlaneGeometry(50,50);
materialPlano = new THREE.MeshPhongMaterial( {map: texturaPlano} );
var planoPacMan = new THREE.Mesh(geometryPlano,materialPlano);
planoPacMan.rotation.x = -0.5 * Math.PI;
scene.add(planoPacMan);
}
Any suggestions?
TextureLoader.load() is an asynchronous method. That is why it has an onload argument.
You are calling render() before the texture loads. One solution is to call render() in the loader callback.
var loader = new THREE.TextureLoader();
var texture = loader.load( 'myTexture.jpg', function ( texture ) {
renderer.render( scene, camera );
} );
Another solution is to have an animation loop. But that is not required for static scenes.
three.js r.78

Categories

Resources