Blender export for THREE.js - three.js

I have an issue with THREE.js export in Blender, namely: materials and textures don't get exported at all.
To show the issue, I've created a simple plane with one material and one texture.
This is entire file generated by JSON export:
{
"faces":[41,0,1,3,2,0,1,2,3,0,0,0,0],
"metadata":{
"faces":1,
"type":"Geometry",
"uvs":1,
"generator":"io_three",
"normals":1,
"version":3,
"vertices":4
},
"uvs":[[0.0001,0.0001,0.9999,0.0001,0.9999,0.9999,0.0001,0.9999]],
"normals":[1,0,0],
"name":"PlaneGeometry",
"vertices":[-0,3e-06,16,1e-06,-4e-06,-16,-1e-06,32,16,0,32,-16]
}
In comparision, this one is for OBJ/MTL Wavefront format export (which confirms there indeed is a material and texture set for the model)
# Blender v2.76 (sub 0) OBJ File: 'wall_pipes.blend'
# www.blender.org
mtllib wall_pipes.mtl
o Plane
v -0.000000 0.000003 16.000002
v 0.000001 -0.000002 -15.999997
v -0.000001 32.000000 15.999997
v 0.000000 31.999996 -16.000002
vt 0.000100 0.000100
vt 0.999900 0.000100
vt 0.999900 0.999900
vt 0.000100 0.999900
vn 1.000000 0.000000 0.000000
usemtl Material.001
s off
f 1/1/1 2/2/1 4/3/1 3/4/1
...and its corresponding mtl file...
# Blender MTL File: 'wall_pipes.blend'
# Material Count: 1
newmtl Material.001
Ns 96.078431
Ka 1.000000 1.000000 1.000000
Kd 0.800000 0.800000 0.800000
Ks 0.021739 0.021739 0.021739
Ke 0.000000 0.000000 0.000000
Ni 1.000000
d 1.000000
illum 2
map_Kd E:\blender\models\library\textures\pk02_pipes01_C.png
map_Bump E:\\blender\\models\\library\\textures\\pk02_pipes01_C.png
I was thinking about using these generated obj/mtl files, but THREE.js r73 (I prefer its shadow format over the new one) seems to have some issues with them:
[.CommandBufferContext]RENDER WARNING: Render count or primcount is 0.
Anyway I'd like to use JSON format as it feels more natural to me and this is what other people suggest elsewhere. I apologise in case this lack-of-material issue is something really, really stupid :)
Here is the .blend file, maybe I am doing something wrong or have a checkbox unchecked somewhere...?
https://github.com/Scharnvirk/wingmod/raw/blender_issue/models/wall_pipes.blend
Thanks in advance!

The three.js exporter has a lot of options, check that each material/UV option is on.
With the following options enabled
I get the following json
{
"faces":[43,0,1,3,2,0,0,1,2,3,0,0,0,0],
"metadata":{
"version":3,
"type":"Geometry",
"uvs":1,
"materials":1,
"faces":1,
"normals":1,
"generator":"io_three",
"vertices":4
},
"normals":[1,0,0],
"name":"PlaneGeometry",
"uvs":[[0.0001,0.0001,0.9999,0.0001,0.9999,0.9999,0.0001,0.9999]],
"materials":[{
"mapBumpAnisotropy":1,
"mapDiffuseAnisotropy":1,
"wireframe":false,
"mapBumpWrap":["RepeatWrapping","RepeatWrapping"],
"mapSpecularAnisotropy":1,
"specularCoef":50,
"visible":true,
"mapSpecularRepeat":[1,1],
"mapBumpScale":[2.05634,2.05634],
"DbgColor":15658734,
"mapSpecular":"pk02_pipes01_C.png",
"mapDiffuse":"pk02_pipes01_C.png",
"depthWrite":true,
"mapBump":"pk02_pipes01_C.png",
"mapDiffuseWrap":["RepeatWrapping","RepeatWrapping"],
"shading":"phong",
"depthTest":true,
"DbgName":"Material.001",
"opacity":1,
"colorDiffuse":[0.8,0.8,0.8],
"transparent":false,
"mapSpecularWrap":["RepeatWrapping","RepeatWrapping"],
"DbgIndex":0,
"colorSpecular":[0.021739,0.021739,0.021739],
"mapBumpRepeat":[1,1],
"mapDiffuseRepeat":[1,1],
"colorEmissive":[0,0,0],
"blending":"NormalBlending"
}],
"vertices":[-0,3e-06,16,1e-06,-4e-06,-16,-1e-06,32,16,0,32,-16]
}

Related

How to make mtlLoader, and objloader wait for material texture to be loaded, before continuing with the rest of the program?

Please take a look at this code
The scene is static so it should be enough to explicitly call renderer.render() command once, after the assets are loaded, and see the head.
But the head is not seen.
If I replace renderer.render( scene, camera ); with animate() (set doRenderViaSingleRender = false) the head is seen.
I think that the failure when calling render() once, is because the texture is not yet loaded.
Whereas, animate() calls render() constantly, and so, when the texture is finally loaded, the head is seen.
After setting the materials in objLoader.setMaterials( materials ); I expect the map to be defined, but it is undefined.
the console log of the material map shows:
console.log('objLoader.materials.materials[lambert2SG.001].map', objLoader.materials.materials['lambert2SG.001'].map);
null
How can I make the program wait until after the texture has been loaded?
Thanks
That material doesn't have a map set. If you open the material file https://threejs.org/examples/models/obj/walt/WaltHead.mtl in a text editor you'll see it has several attributes, but you won't find a path to a texture, so that's why performing console.log() on the map property outputs null.
# Material Count: 1
newmtl lambert2SG.001
Ns 92.156863
Ka 0.000000 0.000000 0.000000
Kd 0.640000 0.640000 0.640000
Ks 0.250000 0.250000 0.250000
Ni 1.000000
d 1.000000
illum 2
Additionally, that WaltHead object file has vertex position and normals but it does not have any UV data, so even if you assigned a map texture, it won't display without UVs.
However, to answer your question, you could manually download any texture with TextureLoader.load(). The first argument is the path to the texture file, and the second argument is the callback function that's triggered after the texture has finished loading.

THREE.js OBJMTLLoader - Request for simple example files

As detailed in a previous question I have learned how to use THREE.js OBJMTLLoader by using the same objects & materials used in the official example.
That example uses a (for me) complex model with the DDSLoader.
I would like to load simpler OBJ+MTL models and have been trying with several free models obtained from the web. I have managed to load the OBJ files OK (by applying further THREE.js code such as defining normals) but there is a problem loading material textures from the MTL files.
Here is a simple example of my code.
//...DolphinB
var posX = -3445; var posY = 750; var posZ = -100;
var common_scale = 100;
var loader = new THREE.OBJMTLLoader();
loader.load(
'TRI_VP_files/models/dolphin/DOLPHIN_B.obj',
'TRI_VP_files/models/dolphin/DOLPHIN_B.mtl',
function(object)
{
object.position.set( posX, posY, posZ );
scene222.add( object );
object.scale.set(common_scale, common_scale, common_scale);
} );
Here is the MTL code
# Wavefront material library
# Tue Aug 03 07:47:56 1999
# Created with Viewpoint Interchange www.viewpoint.com
newmtl dl_body
Ka 0 0 0
Kd 0 0.8 0.9
Ks 0 0 0
illum 1
map_Kd DOLPHIN2.JPG
My Question
Please could someone point me to some simple OBJ + MTL files which are known to load OK with OBJMTLLoader.
You can use the following free-for-private-use fileset hand created by Mohammad Alizadeh (nice work thankyou Mohammad).
It uses a single .JPG image file as source for the material texture.
It uses a single material.
Here is the .MTL file contents...
# Blender MTL File: 'Hand.blend'
# Material Count: 1
newmtl defaultMat
Ns 96.078431
Ka 0.000000 0.000000 0.000000
Kd 0.640000 0.640000 0.640000
Ks 0.500000 0.500000 0.500000
Ni 1.000000
d 1.000000
illum 2
map_Kd hand_mapNew.jpg
You will need to change the top few lines of the .OBJ file from...
# Blender v2.74 (sub 0) OBJ File: 'Hand.blend'
# www.blender.org
mtllib Hand.mtl
o ZBrushPolyMesh3D
v 0.614360 0.281365 -0.675872
v 0.684894 0.445729 -0.634615
to
# Blender v2.74 (sub 0) OBJ File: 'Hand.blend'
# www.blender.org
## mtllib Hand.mtl <===== commented out
usemtl defaultMat ## <===== added usemtl command,note proper name of material
## o ZBrushPolyMesh3D <===== commented out
v 0.614360 0.281365 -0.675872
v 0.684894 0.445729 -0.634615
Note that many free 3D object filesets use .TIF image files. But .TIF's cannot display in browsers (or THREE.js). Converting them to .JPG format is possible but the UV mapping is not preserved.
Also note that some free 3D object filesets need to be edited so that the material names in the .OBJ file match the names given in the .MTL file.
Also note that some .OBJ files (like the hand example above) need to be editted so that the material is indicated by a usemtl command e.g.:-
usemtl defaultMat
Child processing
For the Hand fileset there are vertex normals (vn) in the .OBJ file. But for some reason smoothing is not applied. Applying the following code will produce smoothing (and adjust shininess and set rootObject references for object picking):-
object.traverse ( function (child)
{
if (child instanceof THREE.Mesh)
{
child.material.shininess = 10;//range 0.1 to 30 (default) to 1000 or more, applies to Phong materials.
//child.userData.rootObject = object; //... see West Langley answer at http://stackoverflow.com/questions/22228203/picking-object3d-loaded-via-objmtlloader
//... used for object picking so that, for further operations, we can select picked child object or child's rootObject.
child.rootObject = object; //... avoids infinite loop if cloning 3D objects.
child.geometry.computeFaceNormals();
child.geometry.computeVertexNormals();
//child.geometry.normalsNeedUpdate = true; //... only required if object has already been rendered.
}
}; )
DISCLAIMER
These tricks got things working for me with this particular scenario. I don't say that this is the best way of doing things.

Three.js with texture not loading using .png file

I am new to 3D Technology by referring few sited I have managed to get some code running to render 3D object. The object was generated by 3D Software Maya. I received these files –
.obj (object file)
.mtl (material file)
.png (texture files).
Using ‘three.js’ I tried to render the object in browser and for that I used three approaches as given below –
1. OBJLoader and explicitly load texture file.
2. OBJMTLLoader
3. JSON loader by converting .obj file into .js.
In all the cases 3D object was rendered successfully but common problem I faced is that it is not at all loading its ‘texture’. Object file, Material file and Texture file all are at same location. It is observed that shading is applied on the object so I can see some parts colourful but the ‘texture’ part (png files) is not getting applied on the object so partly it looks black and dark. There is no error as browser doesn’t show any.
Snippets using JSON loader –
var oLoader = new THREE.JSONLoader();
oLoader.load('Main_unit_01.js', function (geometry, materials) {
// get original materials
var material = new THREE.MeshFaceMaterial(materials);
//var material = new THREE.MeshPhongMaterial();
//material.map = new THREE.ImageUtils.loadTexture(
// "final_texture_v01.png");
var mesh = new THREE.Mesh(geometry, material);
mesh.scale.set(10, 10, 10);
Test.scene.add(mesh);
OBJMTL loader needs material file, using this approach it is observed that it loads both object and material file but not texture, here is a small part information present in MTL file –
newmtl phongE1SG
illum 4
Kd 0.00 0.00 0.00
Ka 0.00 0.00 0.00
Tf 1.00 1.00 1.00
map_Kd final_texture_v01.png
Ni 1.00
Ks 0.50 0.50 0.50
Here is the some part of information present in .js file which was the result of .obj to .js conversion –
"DbgColor" : 238,
"DbgIndex" : 3,
"DbgName" : "phongE1SG",
"colorAmbient" : [0.0, 0.0, 0.0],
"colorDiffuse" : [0.0, 0.0, 0.0],
"colorSpecular" : [0.5, 0.5, 0.5],
"illumination" : 4,
"mapDiffuse" : "final_texture_v01.png",
"opticalDensity" : 1.0
In both above material and js files we can see that ‘.png’ file has been mentioned with some tag. After reading some suggestions given on some blogs I tried to explicitly set the relative path into these files but no success. I have checked most of the blog here and applied most of suggestion but it didn't work. Also I have checked in "github.com" for help but could not get any help. None of the browser gives any error like particular file not found.
Here are the few links which I have followed.
1. three.js JSONLoader Material Not Showing
2. Loading textures with JSONloader
I am not able to post more than 2 links but I have followed so many sites.
Please suggest if any solution to get texture on the object.
The MTL file Kd attribute corresponds to the js attribute colorDiffuse. The Ka attribute is the colorAmbient. As you can see they are both 0. That is why you cannot see the model. Try to make the ambient term (0.2, 0.2, 0.2) and the diffuse term (0.8, 0.0, 0.8).

Normal map in *.obj file

In blender i create a normal map, i will export to blender like OBJ (Wawefront) and there is stored in *.mtl file like "map_Bump".
map_Bump have always the same bumpsacale. What parramter in MTL file defines bumpscale in THREE.JS?
my MTL file:
newmtl ship_white
Ns 0.000000
Ka 0.000000 0.000000 0.000000
Kd 0.656604 0.656604 0.656604
Ks 0.433962 0.433962 0.433962
Ni 1.000000
d 1.000000
illum 2
map_Kd 2t3l.png
map_Bump 2t3l_normal.jpg
Currently this is not supported. However you can remove the bump map from the file and map it manually in Three.js.
Loading the texture.
var bmap = THREE.ImageUtils.loadTexture('bumpmap.jpg');
You will need to traverse your model and find it's material. e.g.
object.traverse( function( node ) {
if ( node instanceof THREE.Mesh ) {
// for smoothing
node.geometry.computeVertexNormals();
console.log(node);
}
if (node instanceof THREE.Mesh && node.material instanceof THREE.MeshPhongMaterial ) {
// console.log(node);
geometry = node.geometry;
material = node.material;
}
});
Then either assign directly on the material you need. Or create a new Three JS mesh and assign it there. Be warned though if the OBJ contains multiple meshes you will need to find the 'right' one.
mesh = new THREE.Mesh( geometry, material);
material.bumpMap = bmap;
material.bumpScale = 1;

Rmagick, GraphicsMagick seems to be super slow on server (why OK on local)

I am looking for a very quick way to render dynamic images from small tiles placed on some background (imagine dynamically rendering a chess game and sending images after each player makes a move).
So the procedure seems to be quite simple:
1. Take some background
2. Put transparent images of chess figures from top to bottom using image offsets (to have correct perspective)
3. Save the whole picture as gif
Tried using imagemagick:
using something similar to:
convert -page 176x220 -gravity SouthWest 1.png -page +35+30 -gravity SouthWest 1.png -page +62+50 1.png -page +10+55 1.png -background none -compose DstOver -flatten result.gif
And graphics magick in similar way:
gm convert ... -page+35+-30 -flatten..
But was not impressed, GraphicsMagick provided better results but:
SERVER:
user system total real
all: 0.000000 0.000000 47.650000 ( 70.991829)
small: 0.000000 0.000000 6.600000 ( 8.110900)
medium: 0.000000 0.000000 6.820000 ( 8.494131)
large: 0.000000 0.000000 10.890000 ( 15.818351)
extreme: 0.000000 0.000000 11.160000 ( 19.873541)
biggest: 0.000000 0.000000 11.640000 ( 14.327450)
On local Phenom II x6:
user system total real
all: 0.000000 0.000000 1.980000 ( 0.757320)
small: 0.000000 0.000000 0.330000 ( 0.082142)
medium: 0.000000 0.000000 0.380000 ( 0.127744)
large: 0.000000 0.000000 0.410000 ( 0.147252)
extreme: 0.000000 0.000000 0.440000 ( 0.180338)
biggest: 0.000000 0.000000 0.470000 ( 0.210802)
Thought maybe the file loading is the issue, tried Rmagick(script from: http://www.imagemagick.org/RMagick/doc/ilist.html#mosaic ):
require "benchmark"
require 'RMagick'
#Demonstrate the mosaic method
a = Magick::ImageList.new
26.times do
a.read("csii/some_asset.miff")
end
b = Magick::ImageList.new
page = Magick::Rectangle.new(0,0,0,0)
a.scene = 0
2.times do |i|
2.times do |j|
b << a.scale(1)
page.x = j * b.columns
page.y = i * b.rows
b.page = page
(a.scene += 1) rescue a.scene = 0
end
end
# Make a 5x5 mosaic
#mosaic = b.flatten_images
#mosaic.write("mosaic.gif")
# mosaic.display
Benchmark.bm(7) do |ben|
ben.report("tiny:") {mosaic = b.mosaic}
end
exit
The result is even more wierd:
THIS IS FOR A TINY 2*2 tiles image
SERVER:
user system total real
tiny: 16.210000 0.000000 16.210000 ( 16.982007)
PHENOM:
user system total real
tiny: 0.000000 0.010000 0.010000 ( 0.001637)
ADDITIONAL INFO:
INPUT FILE FORMATS: tried png and miff
OUTPUT: must be gif
SERVER: 1 XEON core on VPS ~2.2Ghz
PHENOM: 6* 3.2Ghz
Version differences:
Phenom
Version: ImageMagick 6.5.7-8 2010-12-02 Q16 http://www.imagemagick.org
Server
Version: ImageMagick 6.5.1-0 2010-12-02 Q16 OpenMP http://www.imagemagick.org
QUESTIONS
Any ideas for the up to 10000 times reduction in speed?
Any ideas of how I could achieve this task in any other way(other GM or IM function?) or method (Trying out chunky_PNG now (with oily_png ext.)?
The old 2d games of DOS era could render even more pixels at 60fps, so I guess it should be able to accomplish this on a 2Ghz CPU (200ms would be OK I guess)?
It seems every time I ask a question on SO, the answer comes to me immediately.
This time it seems the performance issue is because of OpenVz VPS and OpenMP in IM and GM. After recompiling without OpenMP feature, the performance is great on the server.
RMagick is known to cause all sorts of issues in production (mostly related to memory leaks). I don't know the details, but I do know that using mini_magick alleviates most performance problems. Maybe you should give it a shot.

Resources