How has using THREE.Object3D changed from r52 to r72? - javascript

I have been editing models and grouping them together using Object3D in r52 which works fine. When I change to using r72 the model loads but in a distorted way and without some elements. I think it might have something to do with the "Object3D's position, rotation, quaternion and scale properties are now immutable." from the change log r67-r68.
~mrdoob/three.js/wiki/Migration
With r52
http://timepcode.web44.net/invaders-master/ships/saterlite.html
with r72
http://timepcode.web44.net/invaders-master/ships/saterlite72.html

Related

3D Model Same Scale at Three JS

I'm adding more than one .OBJ file (3D Model) to my Three.js scene via Input File, and I want to make them the same size.
The problem is that this 3D models come each one in different sizes, some of them being huge and the other ones being very small.
Does anybody know a way of making all the 3D Models the same size?
Thank You!!!
You have to modify the Object3D scale property. You can scale independently X, Y and Z, so you can set them up to half of its size setting this scale like this:
yorDownloadedObject.scale = new THREE.Vector3(0.5, 0.5, 0.5);
or double its size like this:
yorDownloadedObject.scale = new THREE.Vector3(2, 2, 2);
But if the sizes are too different you may want to scale up or down depending their actual size...
To know their original size, before scaling, get their bounding box using the Object3D.Geometry property method named computeBoundingBox (or computeBoundingSphere).
Afterwards scale up or down up to your desired size depending on the Geometry.boundingBox property using Cross-multiplication.
Another recommendation is that you get the models resized and do not touch anything.

How to apply parent transforms in the same order to child elements?

In my application users can select 3d objects on a workplane in order to scale, move or rotate these elements together using a "transformation" container, i.e. an Object3D, that groups all transformations and applies these to all children. When deselecting the child elements, the parent container's transformation should be transferred to all children which in turn are removed from the transform container and added back to the main scene object.
However, the child elements are transformed differently when in the transform container where the transformation is applied to the container and not the element itself, e.g. when applying a scale transform to the container with a child having a local rotation then it looks that the local rotation is applied first and afterwards the container's scale transform.
When applying parent's transformations to all children with child.applyMatrix(parent.matrixWorld) and putting the child back to the scene container the transformation order is reversed.
container[scale]{child[rotation]} -> order: rotation, scale
child.applyMatrix(parent.matrixWorld)
child[scale,rotation]{} -> order: scale, rotation
What would I have to do with the child elements to get the same transformation order and appearance result?
Update:
I figured out how to correctly apply the parent's transformations to the child. I used the same code from Object3D.applyMatrix():
child.matrix.multiplyMatrices(parent_old.matrixWorld, child.matrix); but also set child.matrixAutoUpdate = false; and left out child.matrix.decompose(child.position, child.quaternion, child.scale);
Therefore, matrixAutoUpdate = true does not work. Matrix4.decompose() somehow changes the matrix values before setting position, scale and quaternion thus in my example case the shearing transform of the inner child applied by parent's scale transform is reset.
To me this looks inconsistent since such kind of transformation is allowed and displayed when nested object transformations are used. Furthermore, using child.applyMatrix(parent.matrixWorld) to apply parent transforms to a child object (what I have quite often read as a solution for that purpose) would not be correct. I don't know if this is an intended behavior of three.js. If so, can someone explain why?
Thanks to #WestLangley and the provided THREE.js post and SO answer I figured out a solution for me. The issue I experienced is due to THREE.js' design concept of
representing an object's transform with a position, quaternion/rotation, and scale -- applied in the order S-R-T.
Simply put, when applying a non-uniform scale on an object's parent this order is changed and cannot be mapped from an object's transform matrix back to the convenient position, scale and quaternion properties.
My solution is to
represent the object transform with a matrix only.
That means that I set my 3d objects' matrixAutoUpdate = false and do not use the mentioned position, scale, quaternion properties anymore. Instead, I set any transformations on the object's matrix directly by utilizing THREE.Matrix4 methods only.

How to make a 'Flash' effect over a Sprite in Phaser.js?

I'm creating an Rpg in Phaser, and I'm trying to make a Flash effect happen over a Sprite -that means turning the Sprite all white for a moment and then returning to its original color-.
So my question is: what's the best way of achieving this effect?. I've tried two solutions so far, but i'm missing something:
Solution 1:
I tried tweening the tint parameter of the sprite, like this:
this.game.add.tween(enemy).to({
tint: 0xffffff,
}, 100, Phaser.Easing.Exponential.Out, true, 0, 0, true);
But it doesn't work since setting the tint to 0xffffff is the same as setting it to its default color.
Solution 2:
My second possible solution is adding a white square that has the same size of the sprite, and using the actual sprite as a mask for the square:
var flash = this.game.add.graphics(0, 0);
flash.beginFill(0xffffff);
flash.drawRect(enemy.x, enemy.y, enemy.width, enemy.height);
flash.endFill();
flash.mask = enemy // enemy is my Sprite
/* .. code for tweening the flash */
The problem with this solution is that the mask needs to be a PIXI.Graphics object; and I'm using a Sprite object.
So please, any guidance would be appreciated.
In the version of Pixi that Phaser 2.2.2 uses there is a 'tintCache' which basically rounds the tint value, then caches the result. This means you can't do subtle tint ramping like you're trying to do with a tween. We removed this in Phaser 2.3, so it will be available from then, but as of now it's still in dev.
Also you can tint to a 'near white' colour - only 0xffffff precisely resets the tint. But a value very close to that would still be set ok and probably have the desired result.
If you're using WebGL I would still use a tint with 'as near as white as possible' colour values and tween them. You could disable the tint cache for yourself by copying that part of the changed code from the Phaser dev branch.
In Canvas mode it's expensive though as it has to recalculate the pixels every single time you update it.
If you need to worry about Canvas performance then honestly I would create a new PNG that matches your sprite, colour it in all-white and display it over the top of your main sprite as needed and alpha it out. It's less than ideal because of the extra assets required, but it would be the fastest in canvas mode for sure. All depends on your game though is that's acceptable or not.
Edit: Also occurred to me that you could probably achieve what you need by using a blend mode too, such as lighten. You'd duplicate your main sprite, set the blend mode on it, display it over the top of your sprite and fade it out. This would work fine in Canvas at least.
You can use a ColorMatrixFilter on the Sprite. In Phaser, you may have to manually load in the PIXI script first:
game.load.script('filter', 'js/filters/ColorMatrixFilter.js');
Use this for white:
var filter = new PIXI.ColorMatrixFilter();
filter.matrix = [1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,1];
this.game.filter = [filter];
You can also tween the matrix values if you want a smooth transition.

Three.js custom geometry raycaster catches wrong object

I need to use my own gemetry since the default cube does not look like it should in wireframe mode (now it is made of triangles instead of squares).
So I made my own geometry and it looks ok, but the raycaster does not work as good with my own objects as it does with the built-in cubes.
var cube = new THREE.Line( getCube( 5,5, 5), new THREE.LineDashedMaterial( { color: 0x000000,dashSize: 1, gapSize: 0.1, linewidth: 2 } ),THREE.LinePieces );
where getCube() returns
var geometry = new THREE.Geometry()
See example:
http://jsfiddle.net/QHjSM/12/
6 colour filled box on the top are the defalt THREE.CubeGeometry boxes, and selecting them with raycaster works perfect, 6 wireframe are my custom geometry.
Issues:
If you try to click outside the box, but pretty close to it it will catch the box, and if you click inside the box (in the middle of it) it will not catch it neither.
But the most annoying thing is that if you click inside one box, but close to another one sometimes it catches not the wrong one.
I'm not sure can it be done better, tried all the geometry.compute... methods, but still no effect.
Good day, your custom cubes are not in fact cubes. They are just a stack of lines with no cooresponding faces. Your selection is not returning as expected due to the fact that your "cubes" indeed have gapping holes right threw them. What you can do is in your getCube function after you've built the vertices you can then build all your faces in a similar way.
Have a look at this example: Issue with custom geometry and face normal
Generally you'll need to carefully pattern out every 3 set of vertices so that when you build the faces there in a clock-wise direction so that the normals will be computerd correctly. Here's a basic example of adding a face.
geometry.faces.push(new THREE.Face3(1,2,3));
BUT! Note that this will result in the same aforementioned diagonal lines through your wireframe. So, for your use case why not simply use both the basic cube mesh with picking and remove the wireframe then overlay the line drawn boxes as your custom wireframe. Best of both worlds.
FYI, you probably already know but Face4 is gone, so you'll need to use Face3 and some sort of custom wireframe to do this anyway.
Edit:
I did a little test to your fiddle, noticed something strange. Using the CanvasRender, even with the wireframe off the default cube you still see the diagonal lines! I try WebGLRenderer and it's fine. I'll have to look into that one further.
CanvasRenderer
http://jsfiddle.net/QHjSM/13/
WebGLRenderer
http://jsfiddle.net/QHjSM/14/
Me again, hmm it appears those ghosted face lines are visible in all the CanvasRenderer examples that use a MeshBasicMaterial on the Three.js site. The only thing I was able to do was simply reduce the opacity of the cube mesh material to 0.1 to lessen the effect. I suppose the only other method is to switch to the WebGLRenderer but I look forward to being wrong on this :) Here's the last test
http://jsfiddle.net/QHjSM/16/

Raphael JS move/rotate group of drawings as one?

I have a little tool that draws up a grid of circles(representing holes) that allows the user to add text and lines to these circles. Right now I have it set up so if the user clicks on any of the holes then wherever the hole is moved so is every other element on the Paper object. What I am trying to implement next is the ability to rotate everything as one object. I realize that for this to work that I need to know the central point of all the objects, which I can easily get.
What I want to know is should I draw everything on another object. This object will act as another Paper object of sorts, but will only serve for movement and rotation. Any click events on the holes drawn on the object will be passed on to the parent (i.e. the pseudo-paper object everything is drawn on). Is this possible? If so how would I draw everything onto say, a rectangle? And if not what would be the best way to go implementing it?
What you need is a Set. You create it, push objects to it, and then treat it as an entire group, in your case by applying transformations.
Example:
var elements = paper.set();
if (!view.text) {
view.text = App.R.text(0, 0, this.value);
view.text.attr({
'font-size': font_size,
});
elements.push(view.text);
}
elements.transform('something');
Note that you can also bind events to this entire set.

Categories