texture didn't load in to 3d object(mapping) - javascript

texture is not loaded in to ring 3d model.but it will work for some other objects.there is no compile errors.I set the all all light condition correctly.but 3d model color is grey/black.texture loaded for other object correctly.3d object file format is .obj,I didn't load mtl file to my code. mtlobjloader is not in threejs.org,there are someway to load mtl file and mapping the texture to object.
plz help me.
enter code here
<html>
<head>
<title> Test Three.js</title>
<style type="text/css">
BODY
{
margin: 0;
}
canvas
{
width: 100%;
height:100%;
}
</style>
</head>
<body>
<div>
<p>Color:
<button class="jscolor{onFineChange:'onClick(this)',valueElement:null,value:'66ccff'}"
style="width:50px; height:20px;"></button>
</p>
<p>Object:
<button style="width:50px; height:20px;" id="object"></button>
</p>
</div>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
<script src="three.min.js"></script>
<script src="TrackballControls.js"></script>
<script src="jscolor.js"></script>
<script src="AmbientLight.js"></script>
<script src="SpotLight.js"></script>">
<script src="JSONLoader.js"></script>">
<script src="ObjectLoader.js"></script>">
<script src="OBJLoader.js"></script>">
<script src="MTLLoader.js"></script>">
<script src="Material.js"></script>">
<script src="MeshPhongMaterial.js"></script>">
<script>
function onClick(jscolor) {
cube.material.color = new THREE.Color('#'+jscolor);
cube.material.needsUpdate = true;
};
var onClicked=function (){
scene.remove(cube);
var material1 = new THREE.LineBasicMaterial({
color: 'red'
});
var geometry1 = new THREE.Geometry();
geometry1.vertices.push(
new THREE.Vector3( -10, 0, 0 ),
new THREE.Vector3( 0, 10, 0 ),
new THREE.Vector3( 10, 0, 0 )
);
var cube1 = new THREE.Line( geometry1, material1 );
scene.add( cube1);
};
$('#object').click(onClicked);
var scene =new THREE.Scene();
var camera=new THREE.PerspectiveCamera(45,window.innerWidth/window.innerHeight,0.1,1000);
var controls =new THREE.TrackballControls(camera);
controls.addEventListener('change',render);
var renderer = new THREE.WebGLRenderer( { alpha: true });
renderer.setSize(window.innerWidth,window.innerHeight);
document.body.appendChild(renderer.domElement);
/*var material = new THREE.MeshLambertMaterial({color:'red'});
var geometry=new THREE.CubeGeometry(100,100,100);
var cube=new THREE.Mesh(geometry,material);
scene.add(cube);*/
camera.position.z=500;
var light = new THREE.AmbientLight( 0x404040 );
light.intensity = 0;
light.position.z=10;
light.position.y=10; // soft white light
scene.add( light );
// }
//init();
/* var loader = new THREE.JSONLoader();
loader.load( 'ring.json', function ( geometry ) {
var mesh = new THREE.Mesh( geometry, new THREE.MeshBasicMaterial() );
mesh.position.x =500;
mesh.position.y =100;
mesh.position.z =500;
scene.add( mesh );
}); *//*
var loader = new THREE.ObjectLoader();
loader.load("ring.json",function ( obj ) {
THREE.ImageUtils.crossOrigin = '';
var texture = THREE.TextureLoader("images.jpg");
//obj.map= texture;
obj.scale.set (10,10,10);
obj.traverse( function( child ) {
if ( child instanceof THREE.Mesh ) {
child.geometry.computeVertexNormals();
child.material.map=texture;
}
} );
scene.add( obj );
});*/
var manager = new THREE.LoadingManager();
manager.onProgress = function ( item, loaded, total ) {
console.log( item, loaded, total );
};
var texture = new THREE.Texture();
var loader = new THREE.ImageLoader( manager );
// You can set the texture properties in this function.
// The string has to be the path to your texture file.
loader.load( 'brick_bump.jpg', function ( image ) {
texture.image = image;
texture.needsUpdate = true;
// I wanted a nearest neighbour filtering for my low-poly character,
// so that every pixel is crips and sharp. You can delete this lines
// if have a larger texture and want a smooth linear filter.
// texture.magFilter = THREE.NearestFilter;
//texture.minFilter = THREE.NearestMipMapLinearFilter;
} );
var loader = new THREE.OBJLoader(manager);
/*var Mloader= new THREE.MTLLoader(manager);
Mloader.load('ring.mtl',function(object){
object.traverse( function ( child ) {
if (child.material instanceof THREE.MeshPhongMaterial ) {
child.material.map = texture;
}
} );
scene.add( object );
});*/
// As soon as the OBJ has been loaded this function looks for a mesh
// inside the data and applies the texture to it.
loader.load( 'ring1.obj', function ( event ) {
var object = event;
/*for ( var i = 0, l = object.children.length; i < l; i ++ ) {
object.children[ i ].material.map = texture;
console.log("rgr"+ object);
}*/
object.traverse( function ( child ) {
if ( child instanceof THREE.Mesh ) {
child.material.map = texture;
console.log("rgr"+ object.children);
}
} );
// My initial model was too small, so I scaled it upwards.
object.scale = new THREE.Vector3( 25, 25, 25 );
// You can change the position of the object, so that it is not
// centered in the view and leaves some space for overlay text.
object.position.y -= 2.5;
scene.add( object );
});
function render(){
renderer.render(scene,camera);
}
function animate(){
requestAnimationFrame(animate);
controls.update();
}
animate();
</script>
</body>
</html>

First I would check the ring.obj file. You'll need to verify that the ring.obj file is exporting with UV values on all vertexes. UV values assign points on the texture to specific points on the mesh. E.g. they define how the texture is draped over the surface. If you do not have control of the ring.obj export process to quality assure it, there was a conversation on stack about generating UVs at load time here:
THREE.js generate UV coordinate
But your milage may vary if the mesh author had specific texture anchors.
This may not be the issue, but since the texture is working for other meshes, I would think there is an issue with the ring mesh.

Related

three.js mtl loader renders black

I am trying to add a level .obj for my program but it renders black. The .mtl file requires several images placed everywhere (not one space is non-textured). I used to same object in my last project and it works, but it doesn't in my current project. When I remove the materials the lighting affects it, but when I add it, it is pitch black. The renderer renders continously. Also, there are no errors in the console.
Here is the code used in my current project: (MaterialLoader is an MTLLoader instance and ObjectLoader is an OBJLoader instance)
MaterialLoader.load("bbb/bbb.mtl",
function(materials) {
materials.preload()
ObjectLoader.setMaterials(materials)
ObjectLoader.load("bbb.obj",
function(model) {
let mesh = model.children[0]
scene.add(mesh)
}, null, function(error) {alert(error)}
)
}, null, function(error) {alert(error)}
)
Here is the code from my previous project (the loader variable is an OBJLoader instance, and the materials load successfully here.)
mtlLoader.load(
"bbb.mtl",
function(materials) {
materials.preload()
loader.setMaterials(materials)
loader.load("bbb.obj",
function(obj) {
level = obj.children[0]
scene.add(level)
}, null,
function(error) { alert(error) }
)
}, null,
function(error) { alert(error) }
)
https://discourse.threejs.org/t/objloader-mtlloader-not-loading-texture-image/2534
try change object material color, like this:
model.children[0].material.color.r = 1;
model.children[0].material.color.g = 1;
model.children[0].material.color.b = 1;
its work for me
Your code works when tested! Maybe it's an issue with the material export, uv unwrapping, the texture's path, do you have lighting added to the scene, etc. Here's my test code:
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75,320/240,1,500);
camera.position.set( 0,2,2 );
camera.lookAt( scene.position );
var lightIntensity = 1;
var lightDistance = 10;
var light = new THREE.AmbientLight( 0xFFFFFF, lightIntensity, lightDistance );
light.position.set( 0, 5, 0 );
scene.add( light );
var grid = new THREE.GridHelper(10,10);
scene.add( grid );
var renderer = new THREE.WebGLRenderer({});
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( 320,240 );
renderer.domElement.style.margin = '0 auto';
renderer.domElement.style.display = 'block';
renderer.domElement.style.backgroundColor = '#dddddd';
$(document.body).append(renderer.domElement);
function update(){
renderer.render( scene, camera );
requestAnimationFrame( update );
}
update();
mtl_loader = new THREE.MTLLoader();
mtl_loader.load("assets/doughnut.mtl",
function(materials) {
materials.preload()
var obj_loader = new THREE.OBJLoader();
obj_loader.setMaterials(materials)
obj_loader.load("assets/doughnut.obj",
function(object) {
let mesh = object.children[0]
scene.add(mesh);
}, null, function(error) {alert(error)}
)
}, null, function(error) {alert(error)}
);

.obj file in javascript is not moving when using keyboard

The most important part in my code is in JavaScript. I want that my objects can move when I press "down" or "right" or etc. The problem is that object from .json file is moving, but object from .obj file is not. Is it possible to fix that?
This is my code:
<script>
var container, scene, camera, renderer, controls, stats;
var keyboard = new THREEx.KeyboardState();
var keyboard = new KeyboardState();
var galva;
init();
animate();
render();
function init()
{
var spgeometry = new THREE.SphereGeometry( 30, 32, 32 );
var spmaterial = new THREE.MeshBasicMaterial( {color: 0x00000} );
galva = new THREE.Mesh( spgeometry, spmaterial );
galva.position.set(125, 150, 90);
scene.add( galva );
var jsonLoader = new THREE.JSONLoader();
jsonLoader.load( "models/android.js", addModelToScene );
var loader = new THREE.OBJLoader();
loader.load("models/teaport.obj", function ( object ) {
var material = new THREE.MeshLambertMaterial( );
object.traverse( function ( child ) {
if ( child instanceof THREE.Mesh ) {
child.material = material;
}
} );
object.scale.set(50,50,50);
scene.add( object );
} );
}
function addModelToScene( geometry, materials )
{
var material = new THREE.MeshLambertMaterial( materials );
c = new THREE.Mesh( geometry, material );
c.scale.set(50,50,50);
scene.add( c );
}
function update()
{
keyboard.update();
if ( keyboard.down("left") ){
galva.translateX( -50 );
}
if ( keyboard.down("right") ){
c.translateX( 50 );
galva.translateX( 50 );
object.translateX( 50 );
}
controls.update();
stats.update();
}
If you put together a jsfiddle or something similar - it could be easier to figure out. I think you end up with variable shadowing, and your "object" is simply undefined. Try following change.
var loader = new THREE.OBJLoader();
loader.load("models/teaport.obj", function ( o ) {
var material = new THREE.MeshLambertMaterial( );
o.traverse( function ( child ) {
if ( child instanceof THREE.Mesh ) {
child.material = material;
}
} );
o.scale.set(50,50,50);
scene.add( o );
object = o; // <-- important

Getting SSAO shader working with SkinnedMesh

I've been attempting to get the SSAO post-processing shader to work with the latest (r77) version of three.js. I've been using the EffectComposer, with the code entirely duplicated from the example page here:
http://threejs.org/examples/webgl_postprocessing_ssao.html
The relevant code being:
var renderPass = new THREE.RenderPass( Engine.scene, Engine.camera );
ssaoPass = new THREE.ShaderPass( THREE.SSAOShader );
ssaoPass.renderToScreen = true;
// ...various ShaderPass setup parameters
Engine.effectComposer = new THREE.EffectComposer( Engine.renderer );
Engine.effectComposer.addPass(renderPass);
Engine.effectComposer.addPass(ssaoPass);
The issue I have been having is that that SSAO doesn't seem to work with SkinnedMeshes. It seems to take into account the position of the meshes before the skinning calculations are performed.
It looks like this:
Problem with SSAO on SkinnedMesh
Does anyone have any experience with this on the latest version? I've looked all over the place, but can't find any documentation about how to start fixing this at all.
I found mention of a fix for this in another SO post (ThreeJS SSAO Shader w/ Skinned/Animated Models), but the solution has been deprecated.
Thanks in advance, and happy to go into more detail if needed.
As requested, here is the complete code for the simple demo page:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script type="text/javascript" src="js/libs/jquery.min.js"></script>
<script type="text/javascript" src="js/libs/three.min.js"></script>
<script type="text/javascript" src="js/libs/postprocessing/CopyShader.js"></script>
<script type="text/javascript" src="js/libs/postprocessing/EffectComposer.js"></script>
<script type="text/javascript" src="js/libs/postprocessing/MaskPass.js"></script>
<script type="text/javascript" src="js/libs/postprocessing/RenderPass.js"></script>
<script type="text/javascript" src="js/libs/postprocessing/ShaderPass.js"></script>
<script type="text/javascript" src="js/libs/postprocessing/DotScreenShader.js"></script>
<script type="text/javascript" src="js/libs/postprocessing/SSAOShader.js"></script>
<link rel="stylesheet" type="text/css" href="demo.css" />
</head>
<body>
<div id="demo-container"></div>
</body>
</html>
<script>
$(document).ready(function() {
window.doPostPro = 0;
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 1, 1000);
camera.position.set(0, 200, 200);
camera.lookAt(new THREE.Vector3(0, 0, 0));
clock = new THREE.Clock();
// Setup the renderer.
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( 0xFFFFFF );
function setupPostProcessing() {
// Setup render pass
var renderPass = new THREE.RenderPass( scene, camera );
// Setup depth pass
depthMaterial = new THREE.MeshDepthMaterial();
depthMaterial.depthPacking = THREE.RGBADepthPacking;
depthMaterial.blending = THREE.NoBlending;
depthRenderTarget = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight, {
minFilter: THREE.LinearFilter,
magFilter: THREE.LinearFilter,
stencilBuffer: true
});
// Setup SSAO pass
ssaoPass = new THREE.ShaderPass( THREE.SSAOShader );
ssaoPass.renderToScreen = true;
//ssaoPass.uniforms[ "tDiffuse" ].value will be set by ShaderPass
ssaoPass.uniforms[ "tDepth" ].value = depthRenderTarget.texture;
ssaoPass.uniforms[ 'size' ].value.set( window.innerWidth, window.innerHeight );
ssaoPass.uniforms[ 'cameraNear' ].value = camera.near;
ssaoPass.uniforms[ 'cameraFar' ].value = camera.far;
//ssaoPass.uniforms[ 'onlyAO' ].value = ( postprocessing.renderMode == 1 );
ssaoPass.uniforms[ 'aoClamp' ].value = 0.3;
ssaoPass.uniforms[ 'lumInfluence' ].value = 0.5;
// Add pass to effect composer
effectComposer = new THREE.EffectComposer( renderer );
effectComposer.addPass( renderPass );
effectComposer.addPass( ssaoPass );
};
setupPostProcessing();
// Load the mesh.
var loader = new THREE.JSONLoader();
loader.load( "js/zombie.js", function( geometry, materials ) {
var originalMaterial = materials[ 0 ];
originalMaterial.skinning = true;
geometry.computeVertexNormals();
var mesh = new THREE.SkinnedMesh(geometry, originalMaterial);
window.animMixer = new THREE.AnimationMixer(mesh);
var animAction = animMixer.clipAction(geometry.animations[0]);
animAction.play();
scene.add(mesh);
});
var ambientLight = new THREE.AmbientLight( 0xCCCCCC );
scene.add( ambientLight );
$("#demo-container").append( renderer.domElement );
function render() {
if ( doPostPro ) {
// Render depth into depthRenderTarget
scene.overrideMaterial = depthMaterial;
renderer.render( scene, camera, depthRenderTarget, true );
// Render renderPass and SSAO shaderPass
scene.overrideMaterial = null;
effectComposer.render();
}
else {
renderer.render( scene, camera );
}
}
function animate() {
requestAnimationFrame( animate );
if ( window.animMixer != undefined ) {
var deltaTime = clock.getDelta();
animMixer.update(deltaTime);
}
render();
}
animate();
$(document).keyup(function(e) {
// P is pressed.
if ( e.which == 80 ) {
window.doPostPro = !window.doPostPro;
}
});
});
</script>
If you are skinning, and using this pattern in your render loop
// Render depth into depthRenderTarget
scene.overrideMaterial = depthMaterial;
renderer.render( scene, camera, depthRenderTarget, true );
you have to make sure to set
depthMaterial.skinning = true;
Thing is, if there are other elements in the scene that are not skinned, doing so will throw errors. In which case, this may be a three.js design issue that will have to be addressed.
three.js r.77

How to update colors after vertex colors are changed?

I copy and paste the whole(short) html file here to illustrate the problem. Basically, I create a simple triangle geometry as a global variable. When you click the "Red" button, function red() is called to render the triangle as red. The problem is that clicking "Green" does not render it as green if the triangle has already been rendered as red.
<html>
<body>
<div id="container"></div>
<button onclick="red()">Red</button>
<button onclick="green()">Green</button>
<script src="http://threejs.org/build/three.js"></script>
<script>
//Boilerplate stuff
var w=300;
var h=300;
var renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize(w, h);
document.getElementById('container').appendChild( renderer.domElement );
var scene = new THREE.Scene();
var light = new THREE.DirectionalLight(0xffffff);
light.position.z = 10;
scene.add(light);
var camera = new THREE.PerspectiveCamera( 20, w / h, 1, 1000 );
camera.position.z = 10;
var materials = [new THREE.MeshPhongMaterial( { color: 0xffffff, shading: THREE.FlatShading, vertexColors: THREE.VertexColors, shininess: 0 } )];
//Make a geometry
var shape = new THREE.Shape();
shape.moveTo( 0,0 );
shape.lineTo( 0, 1 );
shape.lineTo( 1, 0);
var geometry = new THREE.ShapeGeometry([shape]);
var obj = THREE.SceneUtils.createMultiMaterialObject(geometry, materials);
scene.add(obj);
//
function red()
{
change_color(new THREE.Color(0xff0000));
renderer.render(scene, camera);
}
//
function green()
{
change_color(new THREE.Color(0x00ff00));
renderer.render(scene, camera);
}
//
function change_color(color)
{
geometry.colorsNeedUpdate = true;
for(var i=0;i<geometry.faces.length;i++)
{
if(geometry.faces[i].vertexColors[0]==undefined)
{
geometry.faces[i].vertexColors[0]=color;
}
else
{
geometry.faces[i].vertexColors[0].copy(color);
}
if(geometry.faces[i].vertexColors[1]==undefined)
{
geometry.faces[i].vertexColors[1]=color ;
}
else
{
geometry.faces[i].vertexColors[1].copy(color);
}
if(geometry.faces[i].vertexColors[2]==undefined)
{
geometry.faces[i].vertexColors[2]=color;
}
else
{
geometry.faces[i].vertexColors[2].copy(color);
}
}
}
</script>
</body>
</html>
You are changing vertex colors after the first render of a mesh.
Currently, you can't use the following pattern in three.js once the object has been rendered at least once.
geometry.faces[ i ].vertexColors[ 0 ] = color; // assigning a Color object
You have to use this pattern instead:
geometry.faces[ i ].vertexColors[ 0 ].copy( color ); // or use set()
You must also set the needsUpdate flag when the vertex colors are changed.
geometry.colorsNeedUpdate = true;
Consequently, in your program, you need to add vertex colors to your geometry when you create it. Then just change the color values.
three.js r.77
Try making your var obj a global variable, so instantiate it at the beginning of your program. Also where are you changing the colors, in your render function or another function?

Three.js unexpected render result?

Created the following mesh in blender:
Whenever I load it into three.js I receive the following result:
I export to .obj format and triangulate all of my faces. Not sure why this is happening. Below is the threejs code I am using to render the mesh. I use the same code with other meshes and they render as expected. I'm guessing I've done something that three.js doesn't like with this mesh?
<!DOCTYPE html>
<html>
<head>
<title></title>
<script type="text/javascript" src="/js/three.js"></script>
<script type="text/javascript" src="/js/DDSLoader.js"></script>
<script type="text/javascript" src="/js/MTLLoader.js"></script>
<script type="text/javascript" src="/js/OBJLoader.js"></script>
<script type="text/javascript" src="/js/OrbitControls.js"></script>
<script type="text/javascript" src="/js/stats.js"></script>
<script type="text/javascript" src="/js/dat.gui.js"></script>
<style>
body {
/* set margin to 0 and overflow to hidden, to go fullscreen */
margin: 0;
overflow: hidden;
}
</style>
</head>
<body>
<div id="Stats-output">
</div>
<!-- Div which will hold the Output -->
<div id="WebGL-output">
</div>
<!-- Javascript code that runs our Three.js examples -->
<script type="text/javascript">
function init() {
var stats = initStats();
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.x = 130;
camera.position.y = 40;
camera.position.z = 50;
camera.lookAt(scene.position);
scene.add(camera);
// create a render and set the size
var webGLRenderer = new THREE.WebGLRenderer();
//webGLRenderer.setPixelRatio( window.devicePixelRatio );
webGLRenderer.setClearColor(new THREE.Color(0xffffff, 1.0));
webGLRenderer.setSize(window.innerWidth, window.innerHeight);
webGLRenderer.shadowMapEnabled = true;
var ambient = new THREE.AmbientLight( 0x444444 );
ambient.intensity = 5;
scene.add( ambient );
if('stiletto_switchblade_knife.mtl' !== ''){
THREE.Loader.Handlers.add( /\.dds$/i, new THREE.DDSLoader() );
var mtlLoader = new THREE.MTLLoader();
mtlLoader.setBaseUrl( '/assets/download/mesh/18/' );
mtlLoader.setPath( '/assets/download/mesh/18/' );
mtlLoader.load( 'stiletto_switchblade_knife.mtl', function( materials ) {
materials.preload();
var objLoader = new THREE.OBJLoader();
objLoader.setMaterials( materials );
objLoader.setPath( '/assets/download/mesh/18/' );
objLoader.load( 'stiletto_switchblade_knife.obj', function ( object ) {
//object.scale.set(100, 100, 100);
//object.rotation.x = -0.3;
scene.add( object );
});
});
} else {
var objLoader = new THREE.OBJLoader();
objLoader.setPath( '/assets/download/mesh/18/' );
objLoader.load( 'stiletto_switchblade_knife.obj', function ( object ) {
object.material = new THREE.MeshLambertMaterial({color: 0xFFFFFF});
//object.scale.set(100, 100, 100);
//object.rotation.x = -0.3;
scene.add( object );
});
}
// add the output of the renderer to the html element
document.getElementById("WebGL-output").appendChild(webGLRenderer.domElement);
var controls = new THREE.OrbitControls(camera, webGLRenderer.domElement );
render();
// simple render
function render() {
stats.update();
controls.update();
requestAnimationFrame(render);
webGLRenderer.render(scene, camera);
}
function initStats() {
var stats = new Stats();
stats.setMode(0); // 0: fps, 1: ms
// Align top-left
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px';
document.getElementById("Stats-output").appendChild(stats.domElement);
return stats;
}
}
window.onload = init;
</script>
</body>
</html>
EDIT
Are meshes required to be watertight in three.js? If so that could be the problem as there are a couple areas that are not in this mesh. That's the only thing I can think of at the moment that differs between this and the meshes that render properly.
Renders like that turned up with OBJ models in three.js R76. It turned out that any object containing a stray "l" (line) element blew up just like what you have shown. I found the bad objects by searching the ASCII OBJ file on "l ", got rid of the strays by selecting and hiding all of the faces, and dealing with whatever was left.
Solved. Turned out I had left a few faces drawn inside of the mesh. This was causing the unexpected behavior. Interesting debugging method. I just started stripping away vertices and rendering with threejs until I found the section that was causing the issue.

Categories