A-frame, Polygon animation - animation

I'm trying to animate a polygon in A-frame, seen also here Add polygon in A-frame:
// Create new shape out of the points:
var shape = new THREE.Shape( vector2List );
// Create geometry out of the shape
var geometry = new THREE.ShapeGeometry( shape );
// Give it a basic material
var material = new THREE.MeshBasicMaterial( { color: 0xffffff, opacity: 1} );
// Create a mesh using our geometry and material
var mesh = new THREE.Mesh( geometry, material ) ;
// add it to the entity:
this.el.object3D.add( mesh );
The goal now is to change the opacity of the shape in an animation. I don't know how to access the shape/polygon attributes within the animation - maybe something like this:
// animation
let opacityAnimation = document.createElement( 'a-animation' );
following lines are not clear:
opacityAnimation.setAttribute( 'mesh.material', 'opacity' );
opacityAnimation.setAttribute( 'to', '0' );
opacityAnimation.setAttribute( 'dur', '5000' );
this.el.appendChild( opacityAnimation );
edit:
here is a live-example: fiddle

You set mesh.material to opacity. I believe You want to specify the animated attribute. As the animation element should look like this:
<a-animation attribute="material.opacity"
to = "0"
dur = "5000">
</a-animation>
Your js must be setting those accordingly:
// animation
let opacityAnimation = document.createElement( 'a-animation' );
opacityAnimation.setAttribute( 'attribute', 'material.opacity' );
opacityAnimation.setAttribute( 'to', '0' );
opacityAnimation.setAttribute( 'dur', '5000' );
this.el.appendChild( opacityAnimation );
Now, if you want to use the material component with a custom/polygon geometry, You need to create it a bit differently.
Instead of creating a new mesh, consisting of its own geometry, and material, lets make the geometry in three.js, and use the existing material component.
So i simply replaced adding the new mesh with a simple:
var myShape = new THREE.Shape(points);
var geometry = new THREE.ShapeGeometry(myShape);
this.el.getObject3D('mesh').geometry = geometry;
You should wait till the object3D is loaded to do it properly, in my fiddle i just made a simple timeout.
Now we can use the animation component as intended, and change the material.opacity.
Check it live on a box here.
Check it live on a polygon here.

Related

Three.js: Add a texture to an object just on the outside

I'm very new with Three.js and I'm trying to make a ring:
http://www.websuvius.it/atma/myring/preview.html
I have a background texture ( the silver one ) and another one with a text.
I want the text only on the ring external face.
This is part of my code:
var loader = new THREE.OBJLoader( manager );
var textureLoader = new THREE.TextureLoader( manager );
loader.load( 'assets/3d/ring.obj', function ( event ) {
var object = event;
var geometry = object.children[ 0 ].geometry;
var materials = [];
var backgroundTexture = textureLoader.load('img/texture/silver.jpg');
backgroundTexture.flipY = false;
var background = new THREE.MeshBasicMaterial({
map: backgroundTexture,
color: 0xffffff
});
materials.push(background);
var customTexture = textureLoader.load('img/text.png');
customTexture.flipY = false;
var custom = new THREE.MeshBasicMaterial({
map: customTexture,
transparent: true,
opacity: 1,
color: 0xffffff
});
materials.push(custom);
mesh = THREE.SceneUtils.createMultiMaterialObject(geometry, materials);
mesh.position.y=-50;
scene.add(mesh);
}, onProgress, onError );
It is possible?
Thanks
The reason behind your issue appears to be in your .obj file. Judging from a quick glance at the texture coordinates stored in the file, the inside of the ring uses the same part of the texture image as the outside of the ring.
Increasing the transparent parts of the image won't help. Neither will the attempts to stop the texture from repeating. Those would help if the texture coordinates were larger than 1 but this is not your case unfortunately.
However, there are several solutions:
Split the object in a 3D modeling software to two objects - outside and inside of the ring - and apply the texture only to the first one.
Adjust the UV coordinates of the object in a 3D modeling software.
Adjust the UV coordinates of the vertices programmatically after loading the object to Three.JS

Drawing edges of a mesh in Three.js

Is there something as Stroke to draw the edges of a mesh?
I would like to have my object to look like this:
EDIT: This answer was outdated, and has been updated.
If you want to render only the edges of your mesh, you can use EdgesGeometry.
var geometry = new THREE.EdgesGeometry( mesh.geometry );
var material = new THREE.LineBasicMaterial( { color: 0xffffff } );
var wireframe = new THREE.LineSegments( geometry, material );
scene.add( wireframe );
You can also use THREE.WireframeGeometry.
For an example showing how to render both edges and faces, see this stackoverflow answer.
three.js r.94

pick geometry from the scene and remove geometry and its wireframe together

I want to add and remove a geometry with its wireframe together. I can use raycaster to pick object from the scene but it is hard to pick a wireframe.
One way I can think of is creating a group of object and its wireframe, when the raycaster intersect with the object (e.g. obj.geometry.type == "BoxGeometry"), find its parent and delete the parent. However, the wireframe has to be some geometry that can be added as a child. I am using a Boxhelper to create a wireframe for a cube, which should be added to the scene directly, not to be added as a child to any object. What is a good way to solve this?
Thanks.
I am not sure if i understand what you are after exactly, but maybe ou can create a clone of your object, and render that one as a wireframe. The clone wireframe object can then be added as a child to the original object. So when the original object is picked, you can remove it from the scene, and then the wireframe object will be removed aswell.
Clone your object and change its material to wireframe:
var wireframe = cube.clone();
wireframe.material = new THREE.MeshBasicMaterial({color: 0xff0000, wireframe: true});
cube.add( wireframe ); // adding wireframe as child to the cube
When object is picked: check whether it is a cubegeometry (if you only want it to work with cubes) and check whether its material is wireframe (if you dont want to be able to remove the wireframe without removing the cube aswell)
if (pickedObject.geometry.type == "BoxGeometry" &&
!pickedObject.material["wireframe"]){
pickedObject.parent.remove(pickedObject); //this will remove object from
// scene if it has no parents
}
Working example:
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
var geometry = new THREE.BoxGeometry( 1, 1, 1 );
var material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
var cube = new THREE.Mesh( geometry, material );
scene.add( cube );
var wireframe = cube.clone();
wireframe.material = new THREE.MeshBasicMaterial({color: 0xff0000, wireframe: true});
cube.add( wireframe );
//picking stuff
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
function onMouseClick( event ) {
// calculate mouse position in normalized device coordinates
// (-1 to +1) for both components
mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
// update the picking ray with the camera and mouse position
raycaster.setFromCamera( mouse, camera );
// calculate objects intersecting the picking ray
var intersects = raycaster.intersectObjects( scene.children );
for ( var i = 0; i < intersects.length; i++ ) {
if (intersects[ i ].object.geometry.type == "BoxGeometry" &&
!intersects[ i ].object.material["wireframe"]){
intersects[ i ].object.parent.remove(intersects[ i ].object);
}
}
}
camera.position.z = 5;
var render = function () {
requestAnimationFrame( render );
cube.rotation.x += 0.1;
cube.rotation.y += 0.1;
renderer.render(scene, camera);
};
window.addEventListener( 'mouseup', onMouseClick, false );
render();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r71/three.min.js"></script>
There is also a way of doing what you require with the Three.EdgesHelper instead of cloning, as exemplified in this fiddle. This shows the wireframes without the diagonals.
Even if you don't want to use the Three.EdgesHelper, I noticed that while implementing the clone solution above, it didn't completely show the wireframe, because it was slightly hidden.
To avoid this hiding I added the following code to the constructor of material, which offsets the original shape slightly so that the wireframe can be completely seen:
var material = new THREE.MeshLambertMaterial({ polygonOffset: true, polygonOffsetFactor: 1, polygonOffsetUnits: 1 })
I hope this is somehow useful.

three.js add border to material by materiel name on loaded models

is it possible to add border around a material, as attached in the image,
i can set the material color by following code
object.traverse( function ( child )
{
if ( child instanceof THREE.Mesh )
child.material.color.setRGB (1, 0, 0);
});
where object is my loaded 3d model, so am assume there should be a way to draw the border, is there any option in three.js.
As per the #shiva's comment i have tried it with the following code to draw the glow effect
if(childObject.material.name=="material4046")
{
mesh = new THREE.Mesh( globalGeomtry, material );
// mesh.visible = false
scene.add( mesh );
console.log(mesh);
// create a glowMesh
var glowMesh = new THREEx.GeometricGlowMesh(mesh);
mesh.add(glowMesh.object3d);
// example of customization of the default glowMesh
var insideUniforms = glowMesh.insideMesh.material.uniforms;
insideUniforms.coeficient.value = 2;
insideUniforms.power.value = 1.4;
insideUniforms.glowColor.value.set('red');
var outsideUniforms = glowMesh.outsideMesh.material.uniforms;
outsideUniforms.coeficient.value = 2;
outsideUniforms.power.value = 1.4;
outsideUniforms.glowColor.value.set('red');
}
now the ouput is looking as like in the second image,
i want this glow effect as the border around that material, is it is possible
I think this is what you were after. It is achieved with:
new THREE.MeshBasicMaterial( { color: 0x00ff00, side: THREE.BackSide } );
You can see a demo here:
https://stemkoski.github.io/Three.js/Outline.html
Source code of the demo: https://github.com/stemkoski/stemkoski.github.com/blob/master/Three.js/Outline.html
I tried my level best to achieve it, but unfortunately I can't get it, so I decided to do it with the wireframe option to highlight the material:
if(childObject.material.name=="material9695")
{
var mesh = new THREE.Mesh( globalGeomtry, material );
scene.add( mesh );
var outlineMaterial1 = new THREE.MeshBasicMaterial( { color: 0xff0000,wireframe : true } );
var outlineMesh1 = new THREE.Mesh( globalGeomtry, outlineMaterial1 );
scene.add( outlineMesh1 );
}
Now the wireframe is added for the material material9695 so I can identify that the material material9695 is currently selected
This is not the exact answer I expected but it is enough right now after some hard hours

invert mesh in three.js

How to invert a mesh using three.js
I had a mesh created using THREE.Mesh
var geometry = new THREE.ExtrudeGeometry( featurePts,extrudeSettings);
var mat = new THREE.MeshBasicMaterial( { color: color, wireframe: true, transparent: true } );
var mesh = new THREE.Mesh(geometry, mat );
But my shape looks inverted. Is there any way in Three.js to invert my shape?
shape used above is a list of THREE.Vector2
var featurePts = [];
featurePts.push(new THREE.Vector2 (550,107));
If you mean it looks inside out, try reversing your normals.

Resources