Three.js mesh resize - javascript

I have a 3D model that was loaded as an obj file into Three.js. The model itself is a furniture.
The problem is, that furniture material is dynamic and is different in size (thickness). I need to have to able to made thickness of material bigger, but the total size of the model can't be changed. So scaling isn't an option.
Is there a way I can resize parts of the model (few specific meshes) and doesn't compromise the structure of mesh itself ? I need to change thickness of the structure, but internal parts of the model shouldn't change.
The only solution I can think of is to change scale of some of the meshes and then to change global position of the other meshes based on that. Is this the right way ?
object.traverse(function(child) {
if (child instanceof THREE.Mesh) {
// resize and reposition some of the meshes
}
});
Possible ways to solve it:
Bones
Deformation

Well, if all of the meshes are separate primitives, then you can just change the scale of each part you want to change along one axis, and just set up anchor points to constrain to the outside. So for pieces on the border, you scale the empty object that they're attached to so that they maintain the outer shell.
EG:
OOOOOO
OMMMMMMO
OMmmmmMO
OMmmmmMO
OMMMMMMO
OOOOOO
where O is an Object3D carrying the adjacent Mesh-M, and the m's represent meshes that are scaled themselves. This way if you adjust the scale of all 'm's and 'O's, the outer shell stays in place,
But you're on the right track with the traversal. You'll just have to do this.
For an easy way to traverse, I would give everything you want to change some attribute in their .userData object. Because in some cases you'll want to scale empty objects (O) (so that you can effectively move the anchor point) whereas at others you'll want to scale the meshes in place (m). So it's not purely a mesh based operation (since meshes want to scale from their center). Doing some tagging makes the traversal simpler:
object.traverse(function(child){
if(child instanceof THREE.Mesh){
if(child.userData.isScalable){
//do the scaling.
}
}
});
and if you set up the heirarchy and .userData tagging correctly, then you just scale things and you keep the outer shell.
Is this what you're asking? because the question is unclear.

You could use Clara.io, it is built on top of ThreeJS and allows for you to run operators on geometry that you setup in Clara.io scenes. There is a thickness operator in Clara.io that you can use.
Documentation here: http://clara.io/learn/sdk/interactive-experiences
Anything you can do in the Clara.io editor you can do in an interactive-embed.

You can use your method of changing different meshes sizes and other positions, but when you use object.scale.set( x, y, z ); the browser has to change the scale of the model for every frame rendered. So if you use this for lots of meshes, it can decrease your game's performance. The best way to go would be to use a 3d editor like Blender. It is easier and more efficient.

Related

Wrong positions of exported objects when exporting from blender to three.js

I'm exporting a simple scene from blender to three. Aside from the texture not showing up (which I'm also fighting with), I have a weird problem with the positions of objects. Here's how it looks in blender:
and this is how it renders in three
as you can see, elements are stacked up on each other (and the skybox texture is missing, even though it's referenced properly in the json, embedded as a base64 image). I'm using Three.js exporter v 1.5.0, three.js v84 and blender v 2.77
this is my configuration:
here's the code loading the scene:
var loader = new THREE.ObjectLoader();
loader.load(
'../dist/landscape.json',
function ( obj ) {
scene.add(obj)
}
);
now, I do realise that this way I'm adding a scene to a scene but for some reason, if I try to extract children from it like this:
loader.load(
'../dist/landscape.json',
function ( obj ) {
obj.children.forEach(function(elem) {
scene.add(elem)
}
}
)
I only get half of the objects. No idea why. Besides the objects are still stacked up on each other. I checked the positions in the result versus the original values in blender, and aside from the standard y/z swap x values are reversed (though that's not the cause of the problem), and rotation is removed from the bridge which causes it to render upside down. I'm completely lost
Also, here are the .blend and .json files:
http://www.filehosting.org/file/details/653174/landscape.blend
http://www.filehosting.org/file/details/653175/landscape.json
EDIT:
Partial solution: Scale was set to 10 in exporter, caused the objects to look as if they were misplaced. The thing is, they are still rotated and there's still some mismatch compared to the original. picture here:
I've just come across this issue for myself once again. Having the scale setting at 1 didn't fix it. The issue was that I hadn't applied object transformations in Blender.
Select all problematic objects in your blender file (or just all with A)
Press CTRL+A
Select Rotation & Scale
Repeat for Location if necessary

Apply transformation to the matrix and reset values on Three.js

I'm having an issue with my 3D manipulation application. I'm using the THREE.JS. What I'm trying to do is change the scale of one object, apply this transformation to the original matrix and then restore the values of scale to 1.
I need to restore the transformation because some functions used by the UI are using this information. So, basicaly I want to considere this new size as the original size, without any transformations.
Is there any way to do that? I did some research but none of the answers has solved my issue.
var scale = 0.5;
object.scale.set(scale, scale, scale);
https://stackoverflow.com/a/27023024/3866399
Fixed with this, but I hade to change:
object.geometry.applyMatrix( object.matrix );
to
insertedPrintable.object.children[0].geometry.applyMatrix(cloneMatrix);

Render Order of BufferGeometry in Thee.js

Following the previous question, I'm dealing with building models in BufferGeometry, and realize that the transparent flag affects the render order: objects with transparent materials will be rendered after non-transparent ones.
Also, I read from this thread, did an experiment on JSFiddle and realized the render order of faces in BufferGeometry is the same as the order they are specified in buffers, but not distance from cameras. (In the above experiment, I specify a closer triangle first in the buffer, and it occludes others behind it.)
So my question is: is it possible to set render order of faces manually in BufferGeometry?
In my case, I may need to change transparency of building elements dynamically.
(I've read the thread saying we can set renderOrder of Object3D.)
Thank you.
Faces are rendered in the order in which they appear in the BufferGeometry.
If you have to vary the transparency of scene elements dynamically, I suggest you maintain separate geometries, each paired with its own material.
The renderer will render the objects having transparent = false first. Then it will render the objects having transparent = true.
You will likely find you have fewer artifacts if you use the following settings for your transparent materials:
material.transparent = true;
material.opacity = 0.5; // or as desired
material.depthTest = true; // the default
material.depthWrite = false; // use for transparent materials only
Also, self-transparency is particularly tricky. An example would be a semi-transparent cube (or building). One way to reduce artifacts in such situations is to render the object twice: first with material.side = THREE.BackSide and then again with material.side = THREE.FrontSide. You can use object.renderOrder to force a specific render order between objects.
three.js r.75

D3.js patterns for managing multiple elements bound to same data

I'm learning D3 and my toy application is a visualizer for a 2-dimensional gravity simulation using Symplectic Velocity Verlet Integration.
I have had quite some success animating and drawing a path using bound structured data, but it seems to me that D3 isn't really designed for attaching data to more than one element. It sort of assumes that for any given data that there is a clear and simple SVG element that should own it, and this is evident in the direct storage of data within the __data__ property inside the DOM.
It's not clear, though, the proper way to represent a datum with more than one SVG element. For instance, I'd really prefer to draw a path and a circle for each planet, the path traces its past position (and can have a bunch of clever line-length and color interpolation applied), and the circle plots its current position.
I can even come up with a few more elements I might want to draw: A vector-arrow for velocity... A vector-arrow for acceleration...
In my case, my master data structure is constructed like this, and is dynamically maintained in this structure:
var data = [];
function makeParticle(x, y, vx, vy) {
// state vector plus goodies
return [
x, y,
vx, vy,
0, 0,
[] // path
];
}
data.push(makeParticle(400, 100, -0.5, 1));
data.push(makeParticle(300, -100, 0.5, 2)); // and so on
Each element of data is a planet, which contains its current state vector (position, velocity, and cached acceleration (needed for the integrator)) as well as its path history which is an array of positions which is kept truncated to some reasonably large length.
Currently I am updating the path history like this:
var paths = d3.select('svg').selectAll("path").data(data);
paths.enter().append('path'); // put cool transitions here
paths.exit().remove();
paths.attr("stroke", "red")
.attr("d", function(d){
return lineDrawer(d[6]);
})
This works fine, each path tracks its own copy of its own planet's path.
It's not immediately clear to me how to extend this elegantly to include my circle at the head of each path. I certainly do not want to duplicate the entire datum into the circle's DOM element (as the path data is simply not necessary for it).
Edit in light of my self-answer:
I am hoping that someone can help to elucidate a way to use "groups" to make data-driven the set of things to draw for each datum. e.g. [position, velocity, force, path] as data where they are visualized using, respectively, a circle, an arrow closed path, an arrow closed path, and an open path. It is also possible that this is completely overthinking it because these properties are sort of fixed.
I guess in the process of thinking the problem through, it's become clear to me that all I have to do is filter out the data, so that I only attach the position state data to selectAll('circle.planet') rather than the full datum value which includes the massive path history array. This way it gets exactly the data it is responsible for displaying.
It seems like I have to do some more reading about subselections (I'm mostly puzzled by why (or if) the subselections are limited to two dimensions of hierarchy), but this seems completely reasonable. It seems logical, if I want to draw 4 items for each datum, I just have to somehow "assign" the correct subsets of my datum's structure to each SVG visualizer element.

combine rotation and translation with three.js

i'm using Three.js (without shaders, only with existing objects methods) in order to realize animations, but my question is very simple : i'm sure it's possible, but can you tell me (or help me) how should i combine several animations on a shape ? For example, rotating and translating a sphere.
When i'm doing :
three.sphere.rotation.y += 0.1;
three.sphere.translateZ += 1;
the sphere rotates but the translation vector is also rotating, so the translation has no effect.
I know a bit openGL and i already have used glPushMatrix and glPopMatrix functions, so do them exist in this framework ?
Cheers
Each three.js object3D has a position, rotation and scale; the rotation (always relative to its origin or "center") defines its own local axis coordinates (say, what the object sees as its own "front,up, right" directions) and when you call translateZ, the object is moved according to those local directions (not along the world -or parent- Z axis). If you want the later, do three.sphere.position.z += 1 instead.
The order of transformation is important. You get a different result if you translate first and then rotate than if you rotate first and then translate. Of course with a sphere it will be hard to see the rotation.

Categories