I am trying two upload one OBJ and its associated MTL files into a WebGL scene using the lovely Three.js.
I have just came up with an issue which I can't find a justification for that. I have put some global variables in my code to monitor what is going on when loading the OBJ and MTL files. Although it is just one set of files, the "obj" variable is from "Group" type and it does have two "children". It is not itself instance of mesh but its children are, as console.log() says. However, when I am checking inside children, the first one -- which is measured by geo[0] -- contains just vertices and the "faces" array is empty. However, the second child -- measured by geo[1] -- has all the vertices and faces. It is even enough to just use geo[1] to get the same scene when you use obj.
My concern is the logic behind this. Why for a set of OBJ and MTL files we have an object with two children in which the first children has just vertices and the second one has vertices again and also faces.
It is important for me because I want to work on the vertices and faces to get a voxelized volume and this needs direct manipulations on the scene objects.
scapula = new THREE.OBJMTLLoader();
scapula.load('obj/scapulaTWO.obj', 'obj/scapulaTWO.mtl', function (object) {
// var material = new THREE.MeshFaceMaterial(materials);
var material = new THREE.MeshLambertMaterial({
color: 0xFFFF66
});
obj = object; //group
object.traverse(function (child) {
if (child instanceof THREE.Mesh) {
console.log(child instanceof THREE.Mesh)
geo[i] = child; //mesh
// apply custom material
child.material = material;
// enable casting shadows
child.castShadow = true;
child.receiveShadow = true;
i = i + 1;
}
});
scene.add(geo[1]);
});
What you will find in your object after it has been parsed by the loader is produced by your model.
You can open your *.obj with a text editor and see the groups etc. for yourself. Its not like three.js rips out the vertices and puts them in a seperate group.
Related
Let's say I have a parent and n children objects of the parent in a scene.
Edit: added code for mesh creation (assuming that I have a basic scene and camera set up)
parent group creation:
var geometry = new THREE.PlaneGeometry( 0, 0 );
var surface = new THREE.Group();
surface.geometry = geometry;
Child Mesh:
surface.add(new Sprite());
scene.add(surface);
Is there a way I can ignore the parent's transformation matrix for the children only (but keep its transformation intact as a parent )?
I know that matrixAutoUpdate = false; lets me update the child's transformation matrix manually, but it still applies the parent transformation matrix.
I want to ignore it completely for the children, but still be able to preserve its world transform and extract its rotation, translation, and scaling values.
In sense, there is only one object in the group so the group will behave like a single entity. And you can't associate the geometry with the group so my suggestion will add the plane as mesh and then do whatever you want to.
So updated code shall look like as follows:
var geometry = new THREE.PlaneGeometry( 0, 0 );
var material = new THREE.MeshBasicMaterial( {color: 0xffff00, side: THREE.DoubleSide} );
var plane = new THREE.Mesh( geometry, material );
var surface = new THREE.Group();
surface.add(plane);
surface.add(new Sprite());
scene.add(surface);
Whatever there is to say about javascript, it's a pleasure to hack with!
You can just overload the #updateMatrix function of the specific child Object3D instance by doing something like this:
myChildObject3D.updateMatrixWorld = function( force ) {
if ( this.matrixAutoUpdate ) this.updateMatrix();
if ( this.matrixWorldNeedsUpdate || force ) {
this.matrixWorld.copy( this.matrix );
this.matrixWorldNeedsUpdate = false;
force = true;
}
}
The original Object3D#updateMatrixWorld will multiply the local matrix and the parent's matrix. It also calls the update function on its children.
Here, I switch it with a function that only copies the local transformation matrix so that it's transformation is independent of its parent.
I have several meshes, with about 5000 vertices each. these are the original vertices and call "verticesA" the problem is that it is delayed to run the following line:
shapeFigure[x] = new THREE.Shape (geometry [x] .vertices); // Very slow.
then transformed "shape [x]" in a mesh.
shape[x] = new THREE.ShapeGeometry( shapeFigure[x][x] );
mesh[x] = new THREE.Mesh (shape[x], new THREE.MeshLambertMaterial ({color: "# FF0000"}));
this is obvious because they are many mesh with many vertices. I have a button in my alplicación which generates an algorithm. This algorithm ONLY generates new vertices (I'll call verticesB, these vertices have the same length as the "verticesA"). I want to update the "verticesA" with "verticesB".
how I can update the "verticesA" that figure is in the form of "verticesB".
I do not want to use again "new THREE.Shape ..." because it is delayed (because I have many mesh with many vertices). I want to directly update verticesA TO verticesB, (it is faster)
I'm doing something like this:
//mesh-> is the original (verticesA)
http://imgur.com/ympHorb (verticesA)
//geometry[x]-> is a array with the new vertices (verticesB)
//geometry[x] and mesh[x] is the same length of vertices
for (var a in mesh[x].geometry.vertices) {
mesh[x].geometry.vertices[a].x=geometry[x][a].x;
mesh[x].geometry.vertices[a].y=geometry[x][a].y;
}
In my function render(), i have:
for (var t in mesh){
mesh[t].geometry.verticesNeedUpdate=true;
mesh[t].geometry.dynamic = true;
}
this is a map, but after running the above code and is updated but is distorted.the problem is that is not properly updated geometry.
http://imgur.com/qCWoMWe
the map should be this way:
http://imgur.com/MYXzaEd (this is verticesB)
how I can update the geometry correctly?
I need to export scene as single STL file.
Whereas its easy to export each single <asset>/<mesh>/<model> exporting whole scene with transformations its another story. That requires applying world matrix transform to every vertex of each asset data on-the-fly before export.
Does XML3D has some mechanisms that would help me with that?
Where should I start?
Actually, XML3D is an presentation format and was never designed to extract something useful other than interactive renderings. However, since it is JavaScript, you can access everything somehow and obviously you can also get the data you need to apply all transformations and create a single huge STL mesh from the scene.
The easiest way I can imagine is using the internal scene:
var scene = document.querySelector("xml3d")._configured.adapters["webgl_1"].getScene();
// Iterate render objects
scene.ready.forEach(function(renderObject) {
// Get word matrix
var worldMatrix = new Float32Array(16);
renderObject.getWorldMatrix(worldMatrix);
// Get local position data
var dataRequest = new Xflow.ComputeRequest(renderObject.drawable.dataNode, ["position"]);
var positions = dataRequest.getResult().getOutputData("position").getValue();
console.log(worldMatrix, positions.length);
// apply worldmatrix to all positions
...
});
my application loads a lot of meshes.
to get rid of old meshes i try to dispose them. but the memory is never being freed.
am i missing something ?
my simple example for reproducing:
load 100 of big binary meshes
dispose all of them again
chrome task manager says 250mb memory used, its exactly the same as without step 2
memtest
var scene = new THREE.Scene();
var mymesh=Array();
// 1. load a lot of geometry/meshes...
for(var i=0;i<100;i++)
{
var bloader;
bloader = new THREE.BinaryLoader();
bloader.load( "objekte/presto_6.js" , function( geometry )
{
mymesh.push(new THREE.Mesh( geometry, new THREE.MeshBasicMaterial( {color:0xffffff } ) ));
scene.add(mymesh.length-1);
});
}
// 2. try to dispose objects and free memory...
for(var j=0;j<mymesh.length;j++)
{
mymesh[j].geometry.dispose();
mymesh[j].material.dispose();
screne.remove(mymesh[j]);
}
mymesh=Array();
</script>
Probably a typo, but if it isn't: screne.remove(mymesh[j]); should be scene.remove(mymesh[j]);
Other than that: rember (or find out) how JS manages the memory. Its garbage collector is a sweep-and-clean GC. It flags objects that aren't being referenced anywhere and then cleans them next time the GC kicks in:
for(var j=0;j<mymesh.length;j++)
{
mymesh[j].geometry.dispose();
mymesh[j].material.dispose();
scene.remove(mymesh[j]);
}
The mymesh array still contains references to the mesh objects you are attemting to free. The GC sees this referenec, and therefore refrains from flagging these objects. Reassign, delete, either the entire array of those specific keys you no longer need:
for(var j=0;j<mymesh.length;j++)
{
mymesh[j].geometry.dispose();
mymesh[j].material.dispose();//don't know if you need these, even
scene.remove(mymesh[j]);
mymesh[j] = undefined;//or
delete(mymesh[j]);
}
//or simply:
mymesh = undefined;//or some other value
That allows the memory to be freed, unless another variable remains in scope that references some or all of these objects, too.
As an asside:
mymesh=Array();
Is bad code on many levels. JS functions that begin with an UpperCase are constructors, and should be called usign the new keyword, though most constructors (especially the native objects) shoul be called as little as possibe.
Their behaviour can be unpredictable, and there's often a shorter way to write the code:
mymesh = [];//an array literal
//example of werird behaviour:
mymesh = new Array(10);//[undefined, undefined, undefined....]
mymesh = [10];
mymesh = new Array('10');//['10']
mymesh = new Array(1.2);//RangeError
var o = new Object(123);//returns new Nuber
o = new Object('something');//new String
o = new Object(false);//new Boolean
o = new Object('foo', 'bar');//new String('foo')!!!
o = {foo: 'bar'};//<-- this is soooo much easier
I have a a question that's been bothering me for some time.
I am using the three.js webgl library to render a large scene with many textures and meshes.
This question is not necessarily bound to webgl, but more javascript arrays and memory management.
I am basically doing this:
var modelArray = [];
var model = function(geometry,db_data){
var tex = THREE.ImageUtils.loadTexture('texture.jpg');
var mat = new THREE.MeshPhongMaterial({map:tex})
this.mesh = new THREE.Mesh(geometry,mat);
this.db = db_data;
scene.add(this.mesh);
};
function loadModels(model_array){
for(i=0;i<geometry.length;i++){
modelArray.push(new model(model_array[i]['geometry'],model_array[i]['db_info']));
}
}
loadModels();
Am I being inefficient here? Am I essentially doubling up the amount of memory being used since I have the mesh loaded to the scene and an array. Or does the model (specifically the model.mesh) object in the array simply point to a singular memory block?
Should I just create an array of mesh ids and reference the scene objects, or is it ok to add the mesh to the scene and an array?
Thanks in advance and I hope I was clear enough.
The main thing that jumps out at me is this:
var tex = THREE.ImageUtils.loadTexture('texture.jpg');
var mat = new THREE.MeshPhongMaterial({map:tex})
If you are loading the same texture every time you create a new model, that could create a lot of overhead (and it can also be pretty slow). I would load the texture(s) and corresponding material(s) you need outside of your loop once.
Your modelArray is a list of plain model objects, each of which has a pointer to the corresponding mesh object (and db object). The scene has a pointer to the same mesh object so you are not exploding your memory use by cloning meshes.
It's possible that your memory use is just because your mesh geometries take up a lot of memory. Try loading your models one by one while watching memory usage; perhaps you have one that is unexpectedly detailed.