I am trying to map lat/long data to a sphere. I am able to get vectors with different positions and set the position of the cube mesh to those. After I merge and display it appears that there is only one cube. I am assuming that all the cubes are in the same position. Wondering where I am going wrong here. (latLongToSphere returns a vector);
// simple function that converts the data to the markers on screen
function renderData() {
// the geometry that will contain all the cubes
var geom = new THREE.Geometry();
// add non reflective material to cube
var cubeMat = new THREE.MeshLambertMaterial({color: 0xffffff,opacity:0.6, emissive:0xffffff});
for (var i = quakes.length - 1; i >= 0; i--) {
var objectCache = quakes[i]["geometry"]["coordinates"];
// calculate the position where we need to start the cube
var position = latLongToSphere(objectCache[0], objectCache[1], 600);
// create the cube
var cubeGeom = new THREE.BoxGeometry(2,2,2000,1,1,1),
cube = new THREE.Mesh(cubeGeom, cubeMat);
// position the cube correctly
cube.position.set(position.x, position.y, position.z);
cube.lookAt( new THREE.Vector3(0,0,0) );
// merge with main model
geom.merge(cube.geometry, cube.matrix);
}
// create a new mesh, containing all the other meshes.
var combined = new THREE.Mesh(geom, cubeMat);
// and add the total mesh to the scene
scene.add(combined);
}
You have to update the mesh matrix before merging its geometry:
cube.updateMatrix();
geom.merge(cube.geometry, cube.matrix);
jsfiddle: http://jsfiddle.net/L0rdzbej/222/
Related
I make a game where you can add objects to a world without using a grid. Now I want to make a footpath. When you click on "Create footpath", then you can add a point to on the world at the raycaster position. After you add a first point you can add a second point to the world. When these 2 objects where placed. A line/footpath is visible from the first point to the second one.
I can do this really simple with THREE.Line. See the code:
var lineGeometry = new THREE.Geometry();
lineGeometry.vertices.push( new THREE.Vector3(x1,0,z1), new THREE.Vector3(x2,0,z2) );
lineGeometry.computeLineDistances();
var lineMaterial = new THREE.LineBasicMaterial( { color: 0xFF0000 } );
var line = new THREE.Line( lineGeometry, lineMaterial );
scene.add(line);
But I can't add a texture on a simple line. Now I want to do something the same with a Mesh. I have the position of the first point and the raycaster position of the second point. I also have the lenght between the two objects for the lenght of the footpath. But I don't know how I can get the rotation what is needed.
Note. I saw something about LookAt, is this maybe a good idea, how can I use this with a mesh?
Can anyone help me to get the correct rotation for the footpath object?
I use this code for the foodpath mesh:
var loader = new THREE.TextureLoader();
loader.load('images/floor.jpg', function ( texture ) {
var geometry = new THREE.BoxGeometry(10, 0, 2);
var material = new THREE.MeshBasicMaterial({ map: texture, overdraw: 0.5 });
var footpath = new THREE.Mesh(geometry, material);
footpath.position.copy(point2);
var direction = // What can I do here?
footpath.rotation.y = direction;
scene.add(footpath);
});
I want to get the correct rotation for direction.
[UPDATE]
The code of WestLangley helps a lot. But it works not in all directions. I used this code for the lenght:
var lenght = footpaths[i].position.z - point2.position.z;
What can I do that the lenght works in all directions?
You want to align a box between two 3D points. You can do that like so:
var geometry = new THREE.BoxGeometry( width, height, length ); // align length with z-axis
geometry.translate( 0, 0, length / 2 ); // so one end is at the origin
...
var footpath = new THREE.Mesh( geometry, material );
footpath.position.copy( point1 );
footpath.lookAt( point2 );
three.js r.84
I am trying to draw a least squares plane through a set of points in Three.js. I have a plane defined as follows:
var plane = new THREE.Plane();
plane.setFromNormalAndCoplanarPoint(normal, point).normalize();
My understanding is that I need to take that plane and use it to come up with a Geometry in order to create a mesh to add to the scene for display:
var dispPlane = new THREE.Mesh(planeGeometry, planeMaterial);
scene.add(dispPlane);
I've been trying to apply this answer to get the geometry. This is what I came up with:
plane.setFromNormalAndCoplanarPoint(dir, centroid).normalize();
planeGeometry.vertices.push(plane.normal);
planeGeometry.vertices.push(plane.orthoPoint(plane.normal));
planeGeometry.vertices.push(plane.orthoPoint(planeGeometry.vertices[1]));
planeGeometry.faces.push(new THREE.Face3(0, 1, 2));
planeGeometry.computeFaceNormals();
planeGeometry.computeVertexNormals();
But the plane is not displayed at all, and there are no errors to indicate where I may have gone wrong.
So my question is, how can I take my Math.Plane object and use that as a geometry for a mesh?
This approach should create a mesh visualization of the plane. I'm not sure how applicable this would be towards the least-squares fitting however.
// Create plane
var dir = new THREE.Vector3(0,1,0);
var centroid = new THREE.Vector3(0,200,0);
var plane = new THREE.Plane();
plane.setFromNormalAndCoplanarPoint(dir, centroid).normalize();
// Create a basic rectangle geometry
var planeGeometry = new THREE.PlaneGeometry(100, 100);
// Align the geometry to the plane
var coplanarPoint = plane.coplanarPoint();
var focalPoint = new THREE.Vector3().copy(coplanarPoint).add(plane.normal);
planeGeometry.lookAt(focalPoint);
planeGeometry.translate(coplanarPoint.x, coplanarPoint.y, coplanarPoint.z);
// Create mesh with the geometry
var planeMaterial = new THREE.MeshLambertMaterial({color: 0xffff00, side: THREE.DoubleSide});
var dispPlane = new THREE.Mesh(planeGeometry, planeMaterial);
scene.add(dispPlane);
var material = ...;
var plane = new THREE.Plane(...);
// Align to plane
var geometry = new THREE.PlaneGeometry(100, 100);
var mesh = new THREE.Mesh(geometry, material);
mesh.translate(plane.coplanarPoint());
mesh.quaternion.setFromUnitVectors(new THREE.Vector3(0,0,1), plane.normal);
Note that Plane.coplanarPoint() simply returns -normal*constant, so it might be a better option to use Plane.projectPoint() to determine a center that is "close to" an arbitrary point.
I am trying to create a terrain from a heightmap with a "closed" bottom see the example here:
http://demos.playfuljs.com/terrain/
My terrain generation function is as so:
var img = document.getElementById("landscape-image");
var numSegments = img.width - 1; // We have one less vertex than pixel
var geometry = new THREE.PlaneGeometry(2400, 2400, numSegments, numSegments);
var material = new THREE.MeshLambertMaterial({
color: 0xccccff,
wireframe: false
});
plane = new THREE.Mesh(geometry, material);
plane.name = 'Terrain';
// set height of vertices
for (var i = 0; i < plane.geometry.vertices.length; i++) {
plane.geometry.vertices[i].z = (terrain[i]/255) * height;
}
geometry.computeFaceNormals();
geometry.computeVertexNormals();
plane.position.x = 0;
plane.rotation.x = 0;
plane.position.y = -10;
The problem I am having is how do I create that connected bottom part of the terrain with a THREE.PlaneGeometry. I can't extrude as:
The bottom must be flat if I extrude it will be bumpy like the
terrain.
Extrude takes a Shape object, not a Geometry object.
Really scratching my head here anyone done this before.
Edit: Maybe I could use two planes and merge them but how would I merge the side faces into a single piece of Geometery ?
P.S. The example draws straight to the canvas
create a plane for each side which has your amount of Segments in width and 1 in height. them set the top Vertices according to your heightmap
something like this
var geometry_l = new THREE.PlaneGeometry(2400, 0, numSegments, 1);
plane_l = new THREE.Mesh(geometry_l, material);
for (var i = 0; i < numSegments; i++) {
plane_l.geometry_l.vertices[i].z = (Terrain[0][i]/255) * height;
}
//Offset to the edge of your main plane
you might want to Change your Terrain Array to be two-dimensional for this. so you can always read the row you want.
I have an IcosahedronGeometry defined like this (with all the code about colors and non-position stuff omitted):
var radius = 200;
geometry = new THREE.IcosahedronGeometry(radius, 2);
var materials = [
new THREE.MeshPhongMaterial({}),
new THREE.MeshBasicMaterial({})
];
group1 = THREE.SceneUtils.createMultiMaterialObject(geometry, materials);
group1.position.x = 0;
// rotate a bit just so it spins off-axis
group1.rotation.x = -1.87;
Which creates an almost spherical, many-sided shape.
I want to place little spheres at just a few of the vertices of this shape. Let's say 10 spheres. I do this by copying 10 vertices into an array, like this:
var vertexArray = [];
for (var i = 0; i < 10; i++) {
vertexArray.push(geometry4.vertices[i])
}
then, I use the Vectors copied into vertexArray to set the positions off Sprites:
for (var i = 0; i < vertexArray.length; i++) {
var loader = new THREE.TextureLoader()
var spriteMaterial = new THREE.SpriteMaterial(
{
map: loader.load('/glow.png'),
blending: THREE.AdditiveBlending,
side: THREE.BackSide
})
var sprite = new THREE.Sprite(spriteMaterial)
sprite.position.set(vertexArray[i].x, vertexArray[i].y, vertexArray[i].z)
// do i need rotate these by the same amount?
sprite.rotation.x = -1.87
scene.add(sprite)
}
This all works fine, except that the Sprites don't line up with the actual vertices on the Icosahedron, they just sit randomly (seemingly) somewhere on the faces. Occasionally a Sprite will sit exactly on a vertex.
Am I copying the vertices wrong, or missing a step in here?
Add an object as a child of a parent object, and the child object will rotate with the parent.
Use this pattern, instead:
var sprite = new THREE.Sprite( spriteMaterial );
sprite.position.copy( vertexArray[i] );
group1.add( sprite );
three.js r.76
I want to keep the position of an object in scene and want to change the parent of that object from scene to any other mesh.here is a sample code
http://plnkr.co/edit/fpjsUkOA0rH6FvG4DL6Z?p=preview
in this example when am trying to add the sphere to box it's position is changing.i want to keep the original position .try to remove comment in line 35 ,the spehere is moving towards box.i want to keep its position and make sphere box's child
http://plnkr.co/edit/fpjsUkOA0rH6FvG4DL6Z?p=preview
If question relies only to position then the answer of Brakebein may be correct. But if you need also to revert scale and rotation, then you should make something like this, I think:
var inversionMatrix = new THREE.Matrix4();
inversionMatrix.getInverse( parentObject.matrix );
childObject.applyMatrix(inversionMatrix);
If you add the sphere to the group, you just need to substract the group's position from the sphere's position to keep it in its original world position.
var material = new THREE.MeshLambertMaterial({color: 0x00ff00});
var boxGeometry = new THREE.BoxGeometry(5, 15, 5);
var box = new THREE.Mesh(boxGeometry, material);
var sphereGeometry = new THREE.SphereGeometry( 5, 32, 32 );
var sphere = new THREE.Mesh(sphereGeometry, material);
sphere.position.set(0, 10, 0);
sphere.updateMatrix();
var group = new THREE.Object3D();
group.translateX(6);
group.updateMatrix();
// if you add sphere to group object
group.add(box);
group.add(sphere);
scene.add(group);
var m = new THREE.Matrix4().getInverse(group.matrixWorld);
sphere.applyMatrix(m);
// if you add sphere to box
group.add(box);
box.add(sphere);
scene.add(group);
var m = new THREE.Matrix4().getInverse(box.matrixWorld);
sphere.applyMatrix(m);
console.log(group.position, sphere.position);