Closed willyvvu closed 11 years ago
Would be helpful if you could share a .bend file that shows the problem.
I tried it with multiple .blend files to no avail. I don't think it matters what's inside the .blend file. I realized I'm using blender 2.63, with the plugin for 2.65. I'll try with the newest version of blender and see if it helps.
Did that help?
Not really. Sorry for the delayed reply. It might just be THREE.Raycaster
, because that is what I'm using, which reports an upwards-facing face with a normal of {x:0,y:0,z:1}. It might be that THREE.Raycaster
fails to take into account the object's rotation, just using the face normal of the geometry.
I think I've got it!
I quickly added a plane in Blender 2.65, facing upwards (z axis in Blender, y axis in Three.js) Then, I exported it with two sets of settings.
This yielded the following code:
{
"metadata" :
{
"formatVersion" : 3.1,
"generatedBy" : "Blender 2.65 Exporter",
"vertices" : 4,
"faces" : 1,
"normals" : 1,
"colors" : 0,
"uvs" : [],
"materials" : 1,
"morphTargets" : 0,
"bones" : 0
},
"scale" : 1.000000,
"materials" : [ {
"DbgColor" : 15658734,
"DbgIndex" : 0,
"DbgName" : "default",
"vertexColors" : false
}],
"vertices" : [1,4.37114e-08,1,-1,4.37114e-08,1,1,-4.37114e-08,-1,-1,-4.37114e-08,-1],
"morphTargets" : [],
"normals" : [0,1,0],
"colors" : [],
"uvs" : [],
"faces" : [35,1,0,2,3,0,0,0,0,0],
"bones" : [],
"skinIndices" : [],
"skinWeights" : [],
"animation" : {}
}
Note the line specifying normals, which contains "normals" : [0,1,0],
This is consistent with Three.js's coordinate system.
This is correct in Three.js, which explains why exporting a model without a scene always works. Therefore, when added an THREE.Mesh
, then to a THREE.Scene
, the object faces the correct way, since THREE.Mesh
initializes without any rotations or transformations that could alter the normal.
This yielded the following code:
{
"metadata" :
{
"formatVersion" : 3.2,
"type" : "scene",
"sourceFile" : "",
"generatedBy" : "Blender 2.65 Exporter",
"objects" : 1,
"geometries" : 1,
"materials" : 1,
"textures" : 0
},
"urlBaseType" : "relativeToScene",
"objects" :
{
"Plane" : {
"geometry" : "geo_Plane",
"groups" : [ ],
"material" : "",
"position" : [ 0, 0, 0 ],
"rotation" : [ -1.5708, 0, 0 ],
"quaternion": [ -0.707107, 0, 0, 0.707107 ],
"scale" : [ 1, 1, 1 ],
"visible" : true,
"castShadow" : false,
"receiveShadow" : false,
"doubleSided" : false
}
},
"geometries" :
{
"geo_Plane" : {
"type" : "embedded",
"id" : "emb_Plane"
}
},
"materials" :
{
"Material" : {
"type": "MeshLambertMaterial",
"parameters": { "color": 10724259, "opacity": 1, "blending": "NormalBlending" }
}
},
"embeds" :
{
"emb_Plane": { "scale" : 1.000000,
"materials" : [ {
"DbgColor" : 15658734,
"DbgIndex" : 0,
"DbgName" : "default",
"vertexColors" : false
}],
"vertices" : [1,-1,0,-1,-1,0,1,1,0,-1,1,0],
"morphTargets" : [],
"normals" : [0,0,1],
"colors" : [],
"uvs" : [],
"faces" : [35,1,0,2,3,0,0,0,0,0],
"bones" : [],
"skinIndices" : [],
"skinWeights" : [],
"animation" : {}
}
},
"transform" :
{
"position" : [ 0, 0, 0 ],
"rotation" : [ -1.5708, 0, 0 ],
"scale" : [ 1, 1, 1 ]
},
"defaults" :
{
"bgcolor" : [ 0, 0, 0 ],
"bgalpha" : 1.000000,
"camera" : ""
}
}
There are a few things that need to be mentioned. First of all, the same line that declared normals in the previous export now reads "normals" : [0,0,1],
This is consistent with Blender, with z as the up axis, but to make the plane face the correct direction in Three.js, it needs to be rotated, which is what "rotation" : [ -1.5708, 0, 0 ],
does, appearing twice. This is why when directly adding the geometry (where the normals are [0,0,1]
) to a THREE.Mesh
to a THREE.Scene
yields weird results, because a newly initialized THREE.Mesh
does not have the 90 degree rotation needed to be correct in Three.js. When adding the exported object directly to the scene, it renders properly, because the object has the much-needed 90 degree rotation. However, THREE.Raycaster
can only provide the original, unrotated face from the geometry, so when a ray is cast at the face, it will correctly report an intersection, but incorrectly report the normals. To summarize, THREE.Raycaster
only returns the face in the original, unrotated geometry as opposed to the final, rotated object.
THREE.Raycaster
could be improved by providing a property which reports the face normals of an object's geometry taking into account the object's rotation. In other words, the intersection object, in addition to having a distance
, point
, and face
, should have a normal
which takes into account the rotation of the object. I have made a jsfiddle to demonstrate this.THREE.Raycaster
has difficulties intersecting with non-triangle meshes which are skewed. Possibly another issue that branches off this one.Basically, it all boils down to an incorrect assumption of what the intersections array has. I'm afraid I disagree. You should get the original normal of the face. What if you wanted it? You would then have to multiply the inverse matrix and that would be awkward.
So yes, having to do this is expected:
intersection.face.normal.clone().transformDirection(plane.matrix);
In fact, you should be doing this:
intersection.face.normal.clone().transformDirection(plane.matrixWorld);
True. I hope this helps clarify the output of THREE.Raycaster
for any others who stumble upon this question. Thanks for clearing things up, @mrdoob !
In fact, you should be doing this:
intersection.face.normal.clone().transformDirection(plane.matrixWorld);
If plane.matrixWorld
has non-uniform scale applied, you have to do the following to properly rotate the normal vector. In fact, I'd do it the following way always.
var normalMatrix = new THREE.Matrix3().getNormalMatrix( plane.matrixWorld );
var normal = intersection.face.normal.clone().applyMatrix3( normalMatrix );
Using blender 2.77 and the latest version of the exporter I'm getting unexpected normals for the .json export, but they're working fine for the .obj export. I don't have a flip yz option in the threejs exporter version i'm using. any ideas @willy-vvu ?
Same to me. Also dealing with broken normals exports from blender, currently no idea. Unfortunately this thread is three years old...
Tried to export mesh (cube with inverted normals) and apply bump map to it. Some faces look good but the rest look awful. If I just don't export normals, all faces look good. Looks like my problem is related to this issue.
@Galiaf47 that probably is a different issue, where some recent changes in the exporter broke bump map orientation. Haven't gotten around to logging a bug for that one yet. Try exporting with exporter from r74 to see if that fixes your issue
@dherben Thanks for your answer, but I moved away from json exporter. I use convert_obj_three.py now.
When I export a scene from Blender, the face normals of the meshes are messed up.
From the object that
THREE.SceneLoader
returns:If I add the exported object itself to the scene, it is oriented and positioned correctly. The normals are just off. Example:
scene.add(data.objects.Thing)
If I add the exported geometry to a mesh, and the mesh to the scene, the model is rotated and positioned incorrectly, but the normals are fine. Example:
scene.add(new THREE.Mesh(data.geometries.geo_Thing,new THREE.MeshLambertMaterial())
I have a hunch that the exporter failed to flip the Y and Z for the normals.
One last thing: sometime the Three.js exporter renames the geometries of the objects being exported, without notice. If you look at the scene hierarchy panel before and after exporting, a mesh's geometry might be renamed from Thing to Thing.001, while the name will remain Thing. This messes up
THREE.SceneLoader
when importing. The weird thing is that it only affects certain meshes. See the attached image.The geometry for Building is renamed to Building.001. Same thing with Collider's geometry, but somehow not for Track. How bizarre.