I want to find point of intersection curve and line. Created raycast, but it doesn't work well. The point of the ray is far from the actual intersection.
Webgl 1, threejs 0.109
var sartPoint = new THREE.Vector3( -30, -50, 0 );
var endPoint = new THREE.Vector3( 50, 80, 0 );
var geometry = new THREE.Geometry();
geometry.vertices.push(sartPoint);
geometry.vertices.push(endPoint);
var materialTmp = new THREE.LineBasicMaterial( { color: 0xffffff, linewidth: 5 } );
var itemTmp = new THREE.Line( geometry, materialTmp );
_this.add( itemTmp, 'lines' );
scene.updateMatrixWorld()
var curve = new THREE.EllipseCurve(
0, 0, // ax, aY
10, 10, // xRadius, yRadius
0, 2 * Math.PI, // aStartAngle, aEndAngle
false, // aClockwise
0 // aRotation
);
var points = curve.getPoints( 10 );
var geometry = new THREE.BufferGeometry().setFromPoints( points );
var material = new THREE.LineBasicMaterial( { color : 0xff00ff } );
var ellipse = new THREE.Line( geometry, material );
scene.add( ellipse );
var raycaster = new THREE.Raycaster(sartPoint, endPoint.clone().normalize());
var intersects = raycaster.intersectObject( ellipse );
console.log(intersects);
if(intersects.length > 0){
// FIRST dot of intersect
var dotGeometry2 = new THREE.Geometry();
dotGeometry2.vertices.push(intersects[0].point);
var dotMaterial2 = new THREE.PointsMaterial( { size: 5, color: 0x00ff00 } );
var dot2 = new THREE.Points( dotGeometry2, dotMaterial2 );
_this.add( dot2, 'points' );
}
The second argument to the Raycaster constructor is a direction vector. Instead of:
endPoint.clone().normalize()
I think you want:
endPoint.clone().sub(startPoint).normalize()
It is work if
curve.getPoints( 10 );
When
curve.getPoints( 100 );
That doesn't work.
I want to create a vertical ruler with measurements like the image below. can anyone help me with it.
var material = new THREE.LineBasicMaterial({
color: 0x07E1E1,
linewidth: 3
});
var geometry = new THREE.Geometry();
geometry.vertices.push(
new THREE.Vector3( 0, 0, 0 ),
new THREE.Vector3( 0, 1100, 0 ),
new THREE.Vector3( 0, 0, 0 )
);
var line = new THREE.Line( geometry, material );
scene.add( line );
line.position.set(-550, -550, 200);
But it is not getting as the image and also the measurements…
You can use LineBasicMaterial and Line elements.
var camera, scene, renderer, object;
init();
function init() {
var container;
container = document.getElementById( 'container' );
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 1100 );
camera.target = new THREE.Vector3( 0, 0, 0 );
scene = new THREE.Scene();
object = new THREE.Object3D();
var lineMtr = new THREE.LineBasicMaterial({ color: 0xffffff, linewidth: 3, opacity: 1 });
var geo = new THREE.Geometry();
geo.vertices.push(new THREE.Vector3(0, 10 ,3));
geo.vertices.push(new THREE.Vector3(0, 0 ,3));
var line = new THREE.Line(geo, lineMtr);
var i = 0, l = 10;
object.add(line);
while (i <= l) {
var geoSegm = new THREE.Geometry();
geoSegm.vertices.push(new THREE.Vector3(0.1, i, 3));
geoSegm.vertices.push(new THREE.Vector3(0, i, 3));
var lineSegm = new THREE.Line(geoSegm, lineMtr);
object.add(lineSegm);
var textSprite = makeTextSprite((i * 10).toString(), {r: 255, g: 255, b: 255, a: 255}, new THREE.Vector3(0.2, i, 3), Math.PI);
object.add(textSprite);
i++;
}
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
}
function animate() {
requestAnimationFrame( animate );
renderer.render( scene, camera );
}
You can create a texture for a SpriteMaterial, then use Sprite for ruler texts.
function makeTextSprite(label, fontColor, pos, rot) {
var fontface = "Arial";
var fontsize = 100;
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
context.font = "Bold " + fontsize.toString() + "px " + fontface;
var metrics = context.measureText(label);
context.rotate(-Math.PI);
context.translate(-canvas.width, -canvas.height);
context.fillStyle = "rgba(" + fontColor.r + "," + fontColor.g + "," + fontColor.b + "," + fontColor.a + ")";
context.fillText(label, 0, 100);
var texture = new THREE.Texture(canvas);
texture.needsUpdate = true;
texture.center = new THREE.Vector2(0.5, 0.5);
texture.rotation = Math.PI;
var spriteMaterial = new THREE.SpriteMaterial({
map: texture, color: 0xffffff
});
var sprite = new THREE.Sprite(spriteMaterial);
sprite.scale.set(0.25, 0.25, 0.25);
sprite.position.set(pos.x, pos.y, pos.z);
return sprite;
}
I used codes in that link http://jsfiddle.net/3mrzL75h/19/
In first look you can't seeing ruler, drag camera to right.
I want to create a "U" shaped magnet in three.js. So can I use TubeGeometry for that?
So if this is the code for creating a 3D sin curve. How can I make it as "U" shaped Magnet?
var CustomSinCurve = THREE.Curve.create(
function ( scale ) { //custom curve constructor
this.scale = ( scale === undefined ) ? 1 : scale;
},
function ( t ) { //getPoint: t is between 0-1
var tx = t * 3 - 1.5;
var ty = Math.sin( 2 * Math.PI * t );
var tz = 0;
return new THREE.Vector3( tx, ty, tz ).multiplyScalar(this.scale);
}
);
var path = new CustomSinCurve( 10 );
var geometry = new THREE.TubeGeometry( path, 20, 2, 8, false );
var material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
var mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
If the shape of the magnet's profile is not critical (rectangle instead of circle), then you can use THREE.ExtrudeGeometry():
var path = new THREE.Shape(); // create a U-shape with its parts
path.moveTo(-1, 1);
path.absarc(0, 0, 1, Math.PI, Math.PI * 2);
path.lineTo(1, 1);
path.lineTo(.8, 1);
path.absarc(0, 0, .8, Math.PI * 2, Math.PI, true);
path.lineTo(-.8,1);
path.lineTo(-1, 1);
var extOpt = { // options of extrusion
curveSegments: 15,
steps: 1,
amount: .2,
bevelEnabled: false
}
var uGeom = new THREE.ExtrudeGeometry(path, extOpt); // create a geometry
uGeom.center(); // center the geometry
var average = new THREE.Vector3(); // this variable for re-use
uGeom.faces.forEach(function(face){
average.addVectors(uGeom.vertices[face.a], uGeom.vertices[face.b]).add(uGeom.vertices[face.c]).divideScalar(3); // find the average vector of a face
face.color.setHex(average.x > 0 ? 0xFF0000 : 0x0000FF); // set color of faces, depends on x-coortinate of the average vector
});
var uMat = new THREE.MeshBasicMaterial({ vertexColors: THREE.FaceColors }); // we'll use face colors
var u = new THREE.Mesh(uGeom, uMat);
scene.add(u);
jsfiddle example
I'm using three.js to make some solar system, all my objects are sphere (suns and planets), but I found this really weird and ghosty square shadow:
Another ghost shadow seems to be that, the shadow that sphere A casts on sphere B, appears on both the front and back side of sphere B, like this:
I am so confused since I don't really remember create any square stuff and I've checked my code for like million times without any finding.
Finally, I dismissed all the lights in the world, and set the background to light color, it appears:
But when I move my camera to the back of it, it just disappears, like a "1-dimension" square created by some high-level creature from the universe.
This is my final project which is due next week, I really don't know how to explain this to my professor.
Appreciate any help!
Thanks a lot!
below is my code that creates objects:
function init() {
container = document.createElement('div');
document.body.appendChild(container);
renderer = new THREE.WebGLRenderer({
antialias : true, alpha: true
});
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
renderer.shadowMapEnabled = true;
container.appendChild(renderer.domElement);
scene = new THREE.Scene();
scene.updateMatrixWorld(true);
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.01, 1000 );
camera.position.set(5,5,5);
controls = new THREE.TrackballControls( camera );
controls.rotateSpeed = 1.0;
controls.zoomSpeed = 1.2;
controls.panSpeed = 0.8;
controls.noZoom = false;
controls.staticMoving = false;
controls.dynamicDampingFactor = 0.2;
var light = new THREE.AmbientLight( 0x222222 );
scene.add( light ); // this is the light I tried to close
var light = new THREE.DirectionalLight( 0xffffff, 0 );
light.position.set(0,0,5);
scene.add( light ); // this is the light I tried to close
light.castShadow = true;
light.shadowCameraNear = 0.01;
light.shadowCameraFar = 15;
light.shadowCameraFov = 45;
light.shadowCameraLeft = -1;
light.shadowCameraRight = 1;
light.shadowCameraTop = 1;
light.shadowCameraBottom= -1;
//light.shadowCameraVisible = true
light.shadowBias = 0.001;
light.shadowDarkness = 0.2;
light.shadowMapWidth = 1024;
light.shadowMapHeight = 1024;
//////////////////////////////////////////////////////////////////////////////////
// render the scene //
//////////////////////////////////////////////////////////////////////////////////
onRenderFcts.push(function(){
controls.update();
renderer.render( scene, camera );
});
window.addEventListener('keydown', onKeyDown, false);
renderer.domElement.addEventListener( 'mousemove', onMouseMove, false );
renderer.domElement.addEventListener( 'click', onMouseClick, false );
}
function createSun (){
var geometry = new THREE.SphereGeometry(0.5, 32, 32)
var texture = THREE.ImageUtils.loadTexture(THREEx.Planets.baseURL+'images/sunmap.jpg')
var material = new THREE.MeshPhongMaterial({
map : texture,
bumpMap : texture,
bumpScale: 0.05,
emissive: new THREE.Color('#ff9933'),
specular: new THREE.Color('#ffff66'),
shininess: 800,
wireframeLinewidth: 500
})
var mesh = new THREE.Mesh(geometry, material)
mesh.receiveShadow = true;
mesh.castShadow = true;
mesh.matrixWorldNeedsUpdate = true;
return mesh
}
function createMoon (){
var geometry = new THREE.SphereGeometry(0.5, 32, 32)
var material = new THREE.MeshPhongMaterial({
map : THREE.ImageUtils.loadTexture(THREEx.Planets.baseURL+'images/moonmap1k.jpg'),
bumpMap : THREE.ImageUtils.loadTexture(THREEx.Planets.baseURL+'images/moonbump1k.jpg'),
bumpScale: 0.002,
})
var mesh = new THREE.Mesh(geometry, material)
return mesh
}
function add_objects() {
// star field
var geometry = new THREE.SphereGeometry(900, 32, 32);
var material = new THREE.MeshBasicMaterial({
map : THREE.ImageUtils.loadTexture('images/earthcloudmap.jpg'),
side : THREE.BackSide
});
var starSphere = new THREE.Mesh(geometry, material);
scene.add(starSphere);
// reference points
originPoint = new THREE.Object3D();
scene.add(originPoint);
onRenderFcts.push(function (delta, now) {
originPoint.rotation.x += rotateFactor * delta;
originPoint.rotation.z += rotateFactor * delta;
});
sunsBasePoint = new THREE.Object3D();
originPoint.add(sunsBasePoint);
onRenderFcts.push(function (delta, now) {
sunsBasePoint.rotation.y += rotateFactor * delta;
sunsBasePoint.rotation.z += rotateFactor * delta;
});
// stars
sun1 = createSun();
sun1.name = 'sun1';
sun1.position.set(0,0,-1.5);
sunsBasePoint.add(sun1);
onRenderFcts.push(function (delta, now) {
sun1.rotation.y -= 1/2 * delta;
sun1.rotation.z += 1/4 * delta;
});
objects.push(sun1);
sun2 = createSun();
sun2.name = 'sun2';
sun2.position.set(1,-1.5,0);
sun2.scale.multiplyScalar(0.8)
sunsBasePoint.add(sun2);
onRenderFcts.push(function (delta, now) {
sun2.rotation.x -= 1/4 * delta;
sun2.rotation.y += 1/8 * delta;
});
objects.push(sun2);
sun3 = createSun();
sun3.name = 'sun3';
sun3.position.set(-1,1,1.5);
sun3.scale.multiplyScalar(1.5);
sunsBasePoint.add(sun3);
onRenderFcts.push(function (delta, now) {
sun3.rotation.y -= 1/8 * delta;
sun3.rotation.x += 1/4 * delta;
});
objects.push(sun3);
threeBodyPlanet = createMoon();
threeBodyPlanet.name = "Three Body Planet";
threeBodyPlanet.position.set(0.5,-0.5,0.5);
threeBodyPlanet.scale.multiplyScalar(1/5);
threeBodyPlanet.receiveShadow = true;
threeBodyPlanet.castShadow = true;
originPoint.add(threeBodyPlanet);
objects.push(threeBodyPlanet);
}
function debug() {
var debugaxis = function(axisLength){
//Shorten the vertex function
function v(x,y,z){
return new THREE.Vertex(new THREE.Vector3(x,y,z));
}
//Create axis (point1, point2, colour)
function createAxis(p1, p2, color){
var line, lineGeometry = new THREE.Geometry(),
lineMat = new THREE.LineBasicMaterial({color: color, lineWidth: 1});
lineGeometry.vertices.push(p1, p2);
line = new THREE.Line(lineGeometry, lineMat);
scene.add(line);
}
createAxis(v(-axisLength/25, 0, 0), v(axisLength, 0, 0), 0xFF0000);
createAxis(v(0, -axisLength/25, 0), v(0, axisLength, 0), 0x00FF00);
createAxis(v(0, 0, -axisLength/25), v(0, 0, axisLength), 0x0000FF);
};
//To use enter the axis length
debugaxis(100);
// lens flares
var textureFlare0 = THREE.ImageUtils.loadTexture( "lensflare0.png" );
var textureFlare2 = THREE.ImageUtils.loadTexture( "lensflare2.png" );
var textureFlare3 = THREE.ImageUtils.loadTexture( "lensflare3.png" );
addLight( 0.55, 0.9, 0.5, 0, 0, 100 );
//addLight( 0.08, 0.8, 0.5, 0, 0, -10 );
//addLight( 0.995, 0.5, 0.9, 50, 50, -10 );
function addLight( h, s, l, x, y, z ) {
var light = new THREE.PointLight( 0xffffff, 1.5, 4500 );
light.color.setHSL( h, s, l );
light.position.set( x, y, z );
scene.add( light );
var flareColor = new THREE.Color( 0xffffff );
flareColor.setHSL( h, s, l + 0.5 );
var lensFlare = new THREE.LensFlare( textureFlare0, 700, -0.1, THREE.AdditiveBlending, flareColor );
lensFlare.add( textureFlare2, 512, 0.0, THREE.AdditiveBlending );
lensFlare.add( textureFlare2, 512, 0.0, THREE.AdditiveBlending );
lensFlare.add( textureFlare2, 512, 0.0, THREE.AdditiveBlending );
lensFlare.add( textureFlare3, 60, 0.6, THREE.AdditiveBlending );
lensFlare.add( textureFlare3, 70, 0.7, THREE.AdditiveBlending );
lensFlare.add( textureFlare3, 120, 0.9, THREE.AdditiveBlending );
lensFlare.add( textureFlare3, 70, 1.0, THREE.AdditiveBlending );
lensFlare.customUpdateCallback = lensFlareUpdateCallback;
lensFlare.position = light.position;
lensFlare.size = 70;
scene.add( lensFlare );
}
function lensFlareUpdateCallback( object ) {
var f, fl = object.lensFlares.length;
var flare;
var vecX = -object.positionScreen.x * 2;
var vecY = -object.positionScreen.y * 2;
//var size = object.size ? object.size : 1000;
for( f = 0; f < fl; f++ ) {
flare = object.lensFlares[ f ];
flare.x = object.positionScreen.x + vecX * flare.distance;
flare.y = object.positionScreen.y + vecY * flare.distance;
//flare.scale = size / camera.distance;
flare.rotation = 0;
}
object.lensFlares[ 2 ].y += 0.025;
object.lensFlares[ 3 ].rotation = object.positionScreen.x * 0.5 + THREE.Math.degToRad( 45 );
};
}
-------------updating-------------
Thanks for yaku's help, I found that the weird square is indeed because of the camera shadow,like in the pics below:
After I increased the shadow parameters, the square shadow seems to be gone, but the remaining shadows on the back of the spheres are still kind of weird in its texture, like this:
It looks like very low resolution shadow made of small squares, why?
Thanks a lot!
------one more question------
All yaku said works!
But I found out there's no shadows of the spheres themselves.
I called
mesh.castShadow = mesh.receiveShadow = true;
every time I create the spheres.
I remember there were these shadows now they are gone...
What might the reason of it?
Thanks!
Not sure, but have you checked the shadow camera dimensions? Looks like the frustum of the shadow camera could be too small, and what you are seeing could be everything inside the frustum is in shadow and the rest unaffected. The light square could be some weird remnant of the shadow camera, shadow maps can be unwieldy..
Set light.shadowCameraVisible = true; and adjust the other shadow parameters so that the box encapsulates the whole scene.
I'm trying to have multiple materials on a single plane to make a simple terrain editor. So I create a couple of materials, and try to assign a material index to each vertex in my plane:
var materials = [];
materials.push(new THREE.MeshFaceMaterial( { color: 0xff0000 }));
materials.push(new THREE.MeshFaceMaterial( { color: 0x00ff00 }));
materials.push(new THREE.MeshFaceMaterial( { color: 0x0000ff }));
// Plane
var planegeo = new THREE.PlaneGeometry( 500, 500, 10, 10 );
planegeo.materials = materials;
for(var i = 0; i < planegeo.faces.length; i++)
{
planegeo.faces[i].materialIndex = (i%3);
}
planegeo.dynamic = true;
this.plane = THREE.SceneUtils.createMultiMaterialObject(planegeo, materials);
But I always get either a whole bunch of errors in the shader, or only a single all-red plane if I use MeshBasicMaterial instead of FaceMaterial. What am I doing wrong?
To get a checkerboard pattern with three colors do this:
// geometry
var geometry = new THREE.PlaneGeometry( 500, 500, 10, 10 );
// materials
var materials = [];
materials.push( new THREE.MeshBasicMaterial( { color: 0xff0000 }) );
materials.push( new THREE.MeshBasicMaterial( { color: 0x00ff00 }) );
materials.push( new THREE.MeshBasicMaterial( { color: 0x0000ff }) );
// assign a material to each face (each face is 2 triangles)
var l = geometry.faces.length / 2;
for( var i = 0; i < l; i ++ ) {
var j = 2 * i;
geometry.faces[ j ].materialIndex = i % 3;
geometry.faces[ j + 1 ].materialIndex = i % 3;
}
// mesh
mesh = new THREE.Mesh( geometry, new THREE.MeshFaceMaterial( materials ) );
scene.add( mesh );
EDIT: Updated for three.js r.60