Multiple mateials with pointcloudmaterial and linebasicmaterial - three.js

i like to draw a line with two vertices[10,10,0][-10,-10,0]. i can create a line sucessfully,
var geometry = new THREE.Geometry();
geometry.vertices.push(new THREE.Vector(10,10,0));
geometry.vertices.push(new THREE.Vector(-10,-10,0));
geometry.verticesNeedUpdate = true;
var material = new THREE.LineBasicMaterial({ color: 0xff0000, linewidth: 2, side: 2 });
var line = new THREE.Line(geometry, material);
scene.add(line);
I like to draw two particle on the vertices of the line,
var geometry = new THREE.Geometry();
geometry.vertices.push(new THREE.Vector(10,10,0));
geometry.vertices.push(new THREE.Vector(-10,-10,0));
geometry.verticesNeedUpdate = true;
var material = new THREE.LineBasicMaterial({ color: 0xff0000, linewidth: 2, side: 2 });
var material1 = new THREE.PointCloudMaterial({ color: 0xff0000, size: 3, sizeAttenuation: false });
var materials = new THREE.MeshFaceMaterial([material, material1]);
var line = new THREE.Mesh(geometry, materials);
scene.add(line);
this method not working, mesh created but not visible in scene.
can any one give some good suggestion on it..

AFAIK a mesh would need atleast 3 vertices to create a face in a mesh. take a look at the Line class docs for how to create a line.
eg.
var line = new THREE.Line( geometry, material )

Related

Get world position of plane

I'm very new to three.js so I'm sure I'm miss-understanding something here.
I've created a plane in the following way:
var planeGeom = new THREE.PlaneGeometry(0.2, 0.2);
planeGeom.rotateX(-Math.PI / 2);
var plane = new THREE.Mesh(planeGeom, new THREE.MeshBasicMaterial({color: 0xffff00, side: THREE.DoubleSide}));
plane.position.set(0, 0.1, 0);
scene.add(plane);
var mathPlane = new THREE.Plane();
planePointA.copy(plane.geometry.vertices[plane.geometry.faces[0].a]);
planePointB.copy(plane.geometry.vertices[plane.geometry.faces[0].b]);
planePointC.copy(plane.geometry.vertices[plane.geometry.faces[0].c]);
plane.localToWorld(planePointA);
plane.localToWorld(planePointB);
plane.localToWorld(planePointC);
mathPlane.setFromCoplanarPoints(planePointA, planePointB, planePointC);
var helper = new THREE.PlaneHelper( mathPlane, 1, 0xffff00 );
scene.add( helper );
Why is my PlaneGeometry object and Plane positioned differently? Why doesn't .localToWorld() get the world position of the plane?
https://jsfiddle.net/sek0yzLp/
Use .updateMatrixWorld() on the plane after setting its position:
plane.position.set(0, 0.1, 0);
plane.updateMatrixWorld();
scene.add(plane);

ThreeJS raycasting is different in R81 than R71

I have a plane with a mesh on it. My code draws a ball when the user double clicks on the mesh. This works just fine in R71 but as soon as I switched to R81 raycaster doesn't return an intersect. Here's the code:
In init():
// Plane
plane = new THREE.Mesh(
new THREE.PlaneBufferGeometry( 1000, 1000, 3, 3 ),
new THREE.MeshBasicMaterial( { color: 0xff0000, opacity: .5, transparent: true } )
);
plane.visible = false;
scene.add( plane );
planes.push(plane);
In doubleClickEvent():
event.preventDefault();
var mouse = new THREE.Vector2((event.clientX / window.innerWidth ) * 2 - 1, -(((event.clientY / window.innerHeight ) * 2 - 1)));
var directionVector = new THREE.Vector3();
directionVector.set(mouse.x, mouse.y, 0.1);
directionVector.unproject(camera);
directionVector.sub(camera.position);
directionVector.normalize();
raycaster.set(camera.position, directionVector);
intersects = raycaster.intersectObjects(planes);
if (intersects.length) {
var sphereParent = new THREE.Object3D();
var sphereGeometry = new THREE.SphereGeometry(.1, 16, 8);
var sphereMaterial = new THREE.MeshLambertMaterial({ color: 0xffffff });
var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
sphereParent.add(sphere);
sphereParent.position.set(intersects[0].point.x, intersects[0].point.y, 0.0);
scene.add(sphereParent);
objects.push(sphereParent);
}
If I change
intersects = raycaster.intersectObjects(planes);
to
intersects = raycaster.intersectObjects(scene.children);
the ball gets drawn but it gets drawn on the wrong position.
Any ideas?
I found the answer. The reason why the raycast isn't working is because the plane's visibility is false. The solution is to change the visibility of the material visibility rather the plane.

Three.js self transparency, object should not be see through

Codepen demonstrating the problem
https://codepen.io/anon/pen/GjJpYw?editors=0010
I have 2 meshes, one which contains 2 cubes, and the other which is 1 cube. The mesh with 2 cubes sandwiches the mesh with one cube (so the single cube is in the center). When I set all cubes to transparent but set the opacity of the center cube to 1, I would not expect to be able to see the back cube when looking through the front cube but I can.
I was wondering is there any easy way to fix this? This is a very simplified version of the problem I'm facing so I can't easily split the geometries. I also cannot just set transparent to false since ideally I would like to be able to have the middle cube partially transparent as well. Any suggestions?
var width = window.innerWidth;
var height = window.innerHeight;
var renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(width, height);
document.body.appendChild(renderer.domElement);
var scene = new THREE.Scene();
var cubeGeometry = new THREE.CubeGeometry(100, 100, 100);
var cube = new THREE.Mesh(cubeGeometry);
cube.position.set(0, 25, -200);
var cube2 = new THREE.Mesh(cubeGeometry);
cube2.position.set(0, -25, 200);
cube.updateMatrix();
cube2.updateMatrix();
var singleGeometry = new THREE.Geometry();
singleGeometry.merge(cube.geometry, cube.matrix);
singleGeometry.merge(cube2.geometry, cube2.matrix);
var combinedMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000, opacity: 0.5, transparent: true});
var mesh = new THREE.Mesh(singleGeometry, combinedMaterial);
var cubeGeometry = new THREE.CubeGeometry(200, 200, 200);
var cubeMaterial = new THREE.MeshBasicMaterial({ color: 0x0000ff, opacity: 0.8, transparent: true});
var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
scene.add(cube);
scene.add(mesh);
var camera = new THREE.PerspectiveCamera(60, width / height, 1, 1000);
camera.position.z = 500;
var controls = new THREE.OrbitControls(camera);
controls.addEventListener('change', render);
var pointLight = new THREE.PointLight(0xffffff);
pointLight.position.set(0, 300, 200);
scene.add(pointLight);
render();
animate();
function animate() {
requestAnimationFrame( animate );
controls.update();
}
function render() {
renderer.render( scene, camera );
}

Textures and RingGeometry / CylinderGeometry

UPDATE:
I made jsfiddle example - jsfiddle.net/NEXny/1/
[ignore this - just including a code block so stackoverflow will
let me post the above JSFiddle link. Yeah, seriously.]
I'm having trouble with applying texture to RingGeometry and CylinderGeometry, hope this image will explain my issue.
It is possible to apply texture by one of this ways ?
Currently i'm getting very unexpected results...
You have to modify the geometry vertex UVs to your liking.
Instead, why not just use CircleGeometry for your cylinder end-caps. That is, construct the end-caps yourself?
// cylinder
geometry = new THREE.CylinderGeometry( 192, 192, 40, 64, 1, true ); // open-ended
geometry1 = new THREE.CircleGeometry(192, 64);
// end-cap material
material1 = new THREE.MeshBasicMaterial({
map: textures.circle,
overdraw: 0.5 // for canvas renderer only
});
// cylinder material
material = new THREE.MeshBasicMaterial({
map: textures.line,
overdraw: 0.5 // for canvas renderer only
});
object = new THREE.Object3D();
scene.add(object);
// end-caps
var mesh1 = new THREE.Mesh(geometry1, material1);
mesh1.rotation.x = - Math.PI / 2;
mesh1.position.y = 20
object.add(mesh1);
var mesh2 = new THREE.Mesh(geometry1, material1);
mesh2.rotation.x = Math.PI / 2;
mesh2.position.y = -20
object.add(mesh2);
// cylinder
var mesh = new THREE.Mesh(geometry, material);
object.add(mesh);
fiddle: http://jsfiddle.net/NEXny/2/
three.js r.61

Different material on back and frontside of extruded shape

I'm trying to apply different material on front and back sides of extruded shape, but cannot figure out where to put side: THREE.FrontSide and side: THREE.BackSide. Where they should be putted?
My relevant code part is:
var materialFront = new THREE.MeshPhongMaterial({ ambient: 0xffffff, map: frontTexture });
var materialSide = new THREE.MeshPhongMaterial({color: 0xE68A00, ambient: 0xffffff});
var extrusionSettings = {
amount: 10,
bevelEnabled: false,
bevelThickness: 0.2,
bevelSize: 0.2,
bevelSegments: 8,
material: 0,
extrudeMaterial: 1
};
var geometry = new THREE.ExtrudeGeometry(shapes, extrusionSettings);
var materials = [materialFront, materialSide];
var material = new THREE.MeshFaceMaterial(materials);
mesh = new THREE.Mesh(geometry, material);
UPDATE:
According to WestLangley's comment I succeeded in adding the different texture to backfaces:
// ...
var materials = [materialFront, materialSide, materialBack];
// ...
for ( var face in mesh.geometry.faces ) {
if (mesh.geometry.faces[ face ].normal.z == 1) mesh.geometry.faces[ face ].materialIndex = 2;
}
After you create your mesh geometry, and before the first call to render(), you have to change the materialIndex to 2 for the back faces. Then, add a third material in your material array.
You can identify the back faces by their face normals. Face normals for faces on the back of the geometry should all point in the same direction.
three.js r.58
Try using:
var materialFront = new THREE.MeshPhongMaterial({ ambient: 0xffffff, map: frontTexture, side: THREE.FrontSide });
var materialSide = new THREE.MeshPhongMaterial({ color: 0xE68A00, ambient: 0xffffff, side: THREE.BackSide });
even though you should probably lower your ambient contribution and give a color to the FrontSide material.
Then:
var materials = [materialFront, materialSide];
scene.add( THREE.SceneUtils.createMultiMaterialObject( geometry, materials ));

Resources