I am trying to:
Draw a THREE.PointCloud object with approx. 150k points where points are sent from a web application.
Scale the points in the THREE.PointCloud object to achieve a result similar to this (rendered using MayaVi):
The problem is that:
Data passed to the THREE.PointCloud object seems to be inaccurate
When rendered in three.js, points are arranged into eight cubes, for unknown reasons (I'm not applying any scaling, or transformations to the points)
Example server response (I have included sample data at the bottom of this post):
{'geometry': [[-156, 65, 89],
[268, 84, 337],
[-205, 68, 170],
[-87, 69, 52],
...
[289, 81, 143],
[141, 78, 280],
[403, 75, 351]],
'metadata': {'max': {'x': 421, 'y': 105, 'z': 458},
'min': {'x': -335, 'y': 63, 'z': 39}}}
The three.js code used to create the point cloud:
var container;
var scene, camera, renderer, controls;
var geometry, material, mesh;
init();
animate();
function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(27, window.innerWidth / window.innerHeight, 5, 5000);
camera.position.z = 2750;
//Add a buffer geometry for particle system
var geometry = new THREE.BufferGeometry();
var particles = {{ len(topology['geometry']) }};
var geometry = new THREE.BufferGeometry();
var positions = new Float32Array(particles * 3);
var colors = new Float32Array(particles * 3);
var color = new THREE.Color();
var i = 0;
{% for point in topology['geometry'] %}
var x = {{ point[0] }};
var y = {{ point[1] }};
var z = {{ point[2] }};
//Store the position of the point
positions[i] = x;
positions[i + 1] = y;
positions[i + 2] = z;
//Assign a colour to the point
color.setRGB(0.42, 0.42, 0.42);
colors[i] = color.r;
colors[i + 1] = color.g;
colors[i + 2] = color.b;
i+=1;
{% end %}
geometry.addAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.addAttribute('color', new THREE.BufferAttribute(colors, 3));
geometry.computeBoundingSphere();
var material = new THREE.PointCloudMaterial({ size: 15, vertexColors: THREE.VertexColors });
particleSystem = new THREE.PointCloud(geometry, material);
scene.add(particleSystem);
//Lights
light = new THREE.DirectionalLight(0xffffff);
light.position.set(1, 1, 1);
scene.add(light);
//Set up renderer
renderer = new THREE.WebGLRenderer({ antialias:false });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
//Attach renderer to #container DOM element
container = document.getElementById('container');
container.appendChild(renderer.domElement);
//Add window listener for resize events
window.addEventListener('resize', onWindowResize, false);
//Call render loop
animate();
}
function onWindowResize(){
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
render();
}
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
function render(){
renderer.render(scene, camera);
}
The scene ends up looking like this:
Any suggestions? I've used the following example code, but I'm having difficulty properly implementing scaling for the points in my dataset: http://threejs.org/examples/#webgl_buffergeometry_particles
Link to a sample of data that I am working with (2MB, 180k lines): https://gist.githubusercontent.com/TylerJFisher/659e3e233f8aa458feee/raw/889c0dd0093fd0476094af48488aab62c8666271/topology.asc
I used your sample data. Put it in an array, like this:
var data = [
"-156 65 89",
"268 84 337",
"-205 68 170",
"-87 69 52",
...
];
and used THREE.Geometry() for PointCloud:
var geometry = new THREE.Geometry();
var colors = [];
for ( var x = 0; x < data.length; x++){
var pointCoord = data[ x ].split(" ");
if ( pointCoord.length != 3 ) continue;
var currentColor = new THREE.Color( 0.5, 1, 0.5 );
colors.push( currentColor );
geometry.vertices.push(
new THREE.Vector3(
pointCoord[2],
pointCoord[1],
pointCoord[0]
)
);
};
//
console.log( geometry.vertices.length );
geometry.colors = colors;
var material = new THREE.PointCloudMaterial( { size: 1, vertexColors: THREE.VertexColors } );
particleSystem = new THREE.PointCloud( geometry, material );
scene.add( particleSystem );
Also, in geodata, coordinates x and y are always swapped (in this case, there are x and z). If you won't do it, you'll get mirrored object then. That's why I put it as
new THREE.Vector3(
pointCoord[2],
pointCoord[1],
pointCoord[0]
)
instead of
new THREE.Vector3(
pointCoord[0],
pointCoord[1],
pointCoord[2]
)
The result is here: geodata
And yes, some lines in your sample data seem incorrect. Means they have 1 or 2 values instead of 3.
Related
My project uses geometry where each face is its own mesh. I need to clip the geometry to cut away a portion of it and have a stenciled cap face cover the clipped edges. I examined and tinkered with the Three.js clipping stencil example and I understand how to use a stencil to cap trimmed solid geometry, but when I try it on collections of face geometries it doesn't work. Here is some code I have been tinkering with, based on the example:
body { margin: 0; }
canvas { display: block; }
<script type="module">
import * as THREE from 'https://unpkg.com/three#0.120.1/build/three.module.js';
import { OrbitControls } from 'https://unpkg.com/three#0.120.1/examples/jsm/controls/OrbitControls.js';
import { BufferGeometryUtils } from 'https://unpkg.com/three#0.120.1/examples/jsm/utils/BufferGeometryUtils.js';
var camera, scene, renderer;
var planes, planeObjects;
init();
animate();
function createPlaneStencilGroup( geometry, plane, renderOrder )
{
var group = new THREE.Group();
var baseMat = new THREE.MeshBasicMaterial();
baseMat.depthWrite = false;
baseMat.depthTest = false;
baseMat.colorWrite = false;
baseMat.stencilWrite = true;
baseMat.stencilFunc = THREE.AlwaysStencilFunc;
// back faces
var mat0 = baseMat.clone();
mat0.side = THREE.BackSide;
mat0.clippingPlanes = [ plane ];
mat0.stencilFail = THREE.IncrementWrapStencilOp;
mat0.stencilZFail = THREE.IncrementWrapStencilOp;
mat0.stencilZPass = THREE.IncrementWrapStencilOp;
var mesh0 = new THREE.Mesh( geometry, mat0 );
mesh0.renderOrder = renderOrder;
group.add( mesh0 );
// front faces
var mat1 = baseMat.clone();
mat1.side = THREE.FrontSide;
mat1.clippingPlanes = [ plane ];
mat1.stencilFail = THREE.DecrementWrapStencilOp;
mat1.stencilZFail = THREE.DecrementWrapStencilOp;
mat1.stencilZPass = THREE.DecrementWrapStencilOp;
var mesh1 = new THREE.Mesh( geometry, mat1 );
mesh1.renderOrder = renderOrder;
group.add( mesh1 );
return group;
}
function init()
{
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 36, window.innerWidth / window.innerHeight, 1, 100 );
camera.position.set( 2, 2, 2 );
initLights();
planes = [
new THREE.Plane( new THREE.Vector3( 0, - 1, 0 ), 0.42 ),
new THREE.Plane( new THREE.Vector3( 0, 0, - 1 ), 0.25 )
];
var material = new THREE.MeshStandardMaterial( {
color: 0x00ff00,
metalness: 0.1,
roughness: 0.75,
side: THREE.DoubleSide,
clippingPlanes: planes,
clipShadows: true,
shadowSide: THREE.DoubleSide,
} );
// Simple sphere geometry. Something I know works, for comparison.
var sphereGeom = new THREE.SphereBufferGeometry( 0.5, 32, 32 );
sphereGeom.translate( -1.1, 0, 0 );
// Make a cube out of 6 planes and merge them together
var planeGeoms = [];
for(var i = 0; i < 6; i++)
{
planeGeoms.push( new THREE.PlaneBufferGeometry( 1, 1 ) );
}
var mergedBufferGeom = BufferGeometryUtils.mergeBufferGeometries( planeGeoms );
// Set up clip plane rendering
planeObjects = [];
var planeGeom = new THREE.PlaneBufferGeometry( 4, 4 );
for ( var i = 0; i < 2; i ++ )
{
var poGroup = new THREE.Group();
var plane = planes[ i ];
var stencilGroup_sphere = createPlaneStencilGroup( sphereGeom, plane, i + 1 );
var stencilGroup_Box = createPlaneStencilGroup( mergedBufferGeom, plane, i + 1 )
// plane is clipped by the other clipping planes
var planeMat = new THREE.MeshStandardMaterial( {
color: 0x0000ff,
metalness: 0.1,
roughness: 0.75,
clippingPlanes: planes.filter( p => p !== plane ),
stencilWrite: true,
stencilRef: 0,
stencilFunc: THREE.NotEqualStencilFunc,
stencilFail: THREE.ReplaceStencilOp,
stencilZFail: THREE.ReplaceStencilOp,
stencilZPass: THREE.ReplaceStencilOp,
} );
var po = new THREE.Mesh( planeGeom, planeMat );
po.onAfterRender = function ( renderer ) {
renderer.clearStencil();
};
po.renderOrder = i + 1.1;
plane.coplanarPoint( po.position );
po.lookAt(
po.position.x - plane.normal.x,
po.position.y - plane.normal.y,
po.position.z - plane.normal.z,
);
scene.add( stencilGroup_sphere );
scene.add( stencilGroup_Box );
poGroup.add( po );
planeObjects.push( po );
scene.add( poGroup );
}
var sphereMesh = new THREE.Mesh( sphereGeom, material );
sphereMesh.renderOrder = 6;
scene.add( sphereMesh );
var planeMeshes = [];
for(var i = 0; i < 6; i++)
{
planeMeshes.push( new THREE.Mesh(planeGeoms[i], material) );
}
planeMeshes[0].position.copy(new THREE.Vector3(.5, 0, 0));
planeMeshes[1].position.copy(new THREE.Vector3(0, .5, 0));
planeMeshes[2].position.copy(new THREE.Vector3(0, 0, .5));
planeMeshes[3].position.copy(new THREE.Vector3(-.5, 0, 0));
planeMeshes[4].position.copy(new THREE.Vector3(0, -.5, 0));
planeMeshes[5].position.copy(new THREE.Vector3(0, 0, -.5));
planeMeshes[0].lookAt(new THREE.Vector3(2, 0, 0));
planeMeshes[1].lookAt(new THREE.Vector3(0, 2, 0));
planeMeshes[2].lookAt(new THREE.Vector3(0, 0, 2));
planeMeshes[3].lookAt(new THREE.Vector3(-2, 0, 0));
planeMeshes[4].lookAt(new THREE.Vector3(0, -2, 0));
planeMeshes[5].lookAt(new THREE.Vector3(0, 0, -2));
for(var i = 0; i < 6; i++)
scene.add( planeMeshes[i] );
// Renderer
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.shadowMap.enabled = true;
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( 0x263238 );
renderer.localClippingEnabled = true;
window.addEventListener( 'resize', onWindowResize, false );
document.body.appendChild( renderer.domElement );
// Controls
var controls = new OrbitControls( camera, renderer.domElement );
controls.minDistance = 2;
controls.maxDistance = 20;
controls.update();
}
function initLights()
{
scene.add( new THREE.AmbientLight( 0xffffff, 0.5 ) );
var dirLight = new THREE.DirectionalLight( 0xffffff, 1 );
dirLight.position.set( 5, 10, 7.5 );
dirLight.castShadow = true;
dirLight.shadow.camera.right = 2;
dirLight.shadow.camera.left = - 2;
dirLight.shadow.camera.top = 2;
dirLight.shadow.camera.bottom = - 2;
dirLight.shadow.mapSize.width = 1024;
dirLight.shadow.mapSize.height = 1024;
scene.add( dirLight );
}
function onWindowResize()
{
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function animate()
{
requestAnimationFrame( animate );
renderer.render( scene, camera );
}
</script>
It contains 2 clipping planes, a cube made from 6 separate PlaneGeometries, and a solid sphere for comparison. I made the stencil for the cube using an additional BufferGeometry made from merging the planes together into a single geometry object. The stencil for the cube appears to be the right shape and size, but only one cap face is drawn and it is not at the location of either of the clipping planes. Is there anything else I'm supposed to do with the stencil or the clipping plane beyond what the example already does to make it work on geometry of this type?
Turns out the PlaneBufferGeometries that were getting merged for the stencil were not in the same positions as the plane meshes that used those geometries. That is why the cap face wasn't being drawn properly. I had not considered the fact that if you apply a transform to a Mesh, then get the Mesh's geometry to use elsewhere, that geometry won't reflect the transform applied to the Mesh. I got it to work by applying the transform matrices from the plane meshes to the PlaneBufferGeometries that needed to be merged.
I used this cool codepen to have my camera follow a spline :
https://codepen.io/wiledal/pen/WvNvEq
This works great but I want to have a uniform speed during my camera movement.
I played with all the parameters of the CatmullRomCurve3() function but to no avail.
In the following example you can see that it slows down at once when it reaches the curves.
Should I try to have the same intensity of points everywhere all along my spline ? If so how can I do that ?
Thank you very much.
var renderer, scene, camera, spline, camPos, camPosIndex;
function init(){
renderer = new THREE.WebGLRenderer();
scene = new THREE.Scene();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
const W = window.innerWidth;
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, .1, 2000 );
spline = new THREE.CatmullRomCurve3([
new THREE.Vector3( -70, 9 ),
new THREE.Vector3( -20, 9 ),
new THREE.Vector3( -13, 9 ),
new THREE.Vector3( 13, -9 ),
new THREE.Vector3( 20, -9 ),
new THREE.Vector3( 70, -9 ),
]);
var points = spline.getPoints(500);
var geometry = new THREE.BufferGeometry().setFromPoints( points );
var material = new THREE.LineBasicMaterial( { color : 0xffffff } );
// Create the final object to add to the scene
var splineObject = new THREE.Line( geometry, material );
scene.add(splineObject);
camPosIndex = 0;
}
let speed = 1000;
function update() {
renderer.render(scene, camera);
requestAnimationFrame(update);
camPosIndex++;
if (camPosIndex > speed) {
camPosIndex = 0;
}
var camPos = spline.getPoint(camPosIndex / speed);
var camRot = spline.getTangent(camPosIndex / speed);
camera.position.x = camPos.x;
camera.position.y = camPos.y;
camera.position.z = camPos.z + 40; // so I can watch my spline
camera.rotation.x = camRot.x;
camera.rotation.y = camRot.y;
camera.rotation.z = camRot.z;
camera.lookAt(spline.getPoint((camPosIndex+1) / speed));
}
init();
update();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/110/three.min.js"></script>
I have a simple 3d cube (BoxGeometry of 100, 100, 100) and I am trying to rotate it. If we call all 100x100x100 a tile - when I rotate it I can see it's overlapping the below tile.
(by changing color, now I totally understand the behaviour).
tl.to(this.cube4.rotation, 0.5, {z: -45* Math.PI/180});
[
What if I want to rotate it based on an anchor point of right bottom? So instead of overflowing inside the below tile, it will overflow that portion to above tile.
So it will look like the green example and not the red example:
The red example here is achieved by
tl.to(this.cube4.rotation, 0.5, {z: -45* Math.PI/180});
tl.to(this.cube4.position, 0.5, {x: 50 }, 0.5);
I am very new to three.js so if any terminology is wrong, please warn me
Add the ("red") cube to a THREE.Group, in that way that the rotation axis (the edge) is in the origin of the group. This means the cube has to be shifted by the half side length.
If you rotate the group object, then the cube (which is inside the group) will rotate around the edge and not around its center.
e.g.
var bbox = new THREE.Box3().setFromObject(cube);
cube.position.set(bbox.min.x, bbox.max.y, 0);
var pivot = new THREE.Group();
pivot.add(cube);
scene.add(pivot);
See also the answer to How to center a group of objects?, which uses this solution to rotate a group of objects.
(function onLoad() {
var camera, scene, renderer, orbitControls, pivot;
var rot = 0.02;
init();
animate();
function init() {
container = document.getElementById('container');
renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
container.appendChild(renderer.domElement);
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 100);
camera.position.set(4, 1, 2);
//camera.lookAt( -1, 0, 0 );
loader = new THREE.TextureLoader();
loader.setCrossOrigin("");
scene = new THREE.Scene();
scene.background = new THREE.Color(0xffffff);
scene.add(camera);
window.onresize = function() {
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
}
orbitControls = new THREE.OrbitControls(camera, container);
var ambientLight = new THREE.AmbientLight(0x404040);
scene.add(ambientLight);
var directionalLight = new THREE.DirectionalLight( 0xffffff, 0.5 );
directionalLight.position.set(1,2,-1.5);
scene.add( directionalLight );
addGridHelper();
createModel();
}
function createModel() {
var material = new THREE.MeshPhongMaterial({color:'#80f080'});
var geometry = new THREE.BoxGeometry( 1, 1, 1 );
var cube1 = new THREE.Mesh(geometry, material);
cube1.position.set(0,-0.5,-0.5);
var cube2 = new THREE.Mesh(geometry, material);
cube2.position.set(0,0.5,-0.5);
var cube3 = new THREE.Mesh(geometry, material);
cube3.position.set(0,-0.5,0.5);
var material2 = new THREE.MeshPhongMaterial({color:'#f08080'});
var cube4 = new THREE.Mesh(geometry, material2);
var bbox = new THREE.Box3().setFromObject(cube4);
cube4.position.set(bbox.min.x, bbox.max.y, 0);
pivot = new THREE.Group();
pivot.add(cube4);
pivot.position.set(-bbox.min.x, 0.5-bbox.max.y, 0.5);
scene.add(cube1);
scene.add(cube2);
scene.add(cube3);
scene.add(pivot);
}
function addGridHelper() {
var helper = new THREE.GridHelper(100, 100);
helper.material.opacity = 0.25;
helper.material.transparent = true;
scene.add(helper);
var axis = new THREE.AxesHelper(1000);
scene.add(axis);
}
function animate() {
requestAnimationFrame(animate);
orbitControls.update();
pivot.rotation.z += rot;
if (pivot.rotation.z > 0.0 || pivot.rotation.z < -Math.PI/2) rot *= -1;
render();
}
function render() {
renderer.render(scene, camera);
}
})();
<!--script src="https://threejs.org/build/three.js"></!--script-->
<script src="https://rawcdn.githack.com/mrdoob/three.js/r124/build/three.js"></script>
<script src="https://rawcdn.githack.com/mrdoob/three.js/r124/examples/js/controls/OrbitControls.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tween.js/17.2.0/Tween.js"></script>
<div id="container"></div>
From the first image, it appears that the pivot of your red tile is at its center.
For the rotation you want, you would ideally change the pivot to the lower right of the cube. This is impossible without modifying the geometry of the cube.
BUT a simple trick is to create an empty node at that pivot point, parent your cube to that empty, and apply your rotation to the empty. (Don't forget to remove your translation, you don't need it anymore)
Here is some pseudo code, assuming your red box is centered at (0,0,0) and has a width and height of 100:
// create an empty node at desired rotation pivot
var empty = new Object3D or group
empty.position = (50, -50, 0)
// parent your cube to the empty
var cube = your box
empty.add(cube)
// you may need to change the local position of your cube to bring it back to its global position of (0,0,0)
cube.position = (-50, 50, 0)
rotate empty by 45°
I think you can get the bounds of the rotated object like this:
bounds = new THREE.Box3().setFromObject( theRedObject )
Then reposition the object.y based on its bounds.min.y
let scene, camera, controls, ambient, point, loader, renderer, container, stats;
const targetRotation = 0;
const targetRotationOnMouseDown = 0;
const mouseX = 0;
const mouseXOnMouseDown = 0;
const windowHalfX = window.innerWidth / 2;
const windowHalfY = window.innerHeight / 2;
init();
animate();
var box, b1, b2, b3;
function init() {
// Create a scene which will hold all our meshes to be rendered
scene = new THREE.Scene();
// Create and position a camera
camera = new THREE.PerspectiveCamera(
60, // Field of view
window.innerWidth / window.innerHeight, // Aspect ratio
/*window.innerWidth / -8,
window.innerWidth / 8,
window.innerHeight / 8,
window.innerHeight / -8,
*/
0.1, // Near clipping pane
1000 // Far clipping pane
);
scene.add(camera)
// Reposition the camera
camera.position.set(0, 5, 10);
// Point the camera at a given coordinate
camera.lookAt(new THREE.Vector3(0, 0, 0));
// Add orbit control
controls = new THREE.OrbitControls(camera);
controls.target.set(0, -0.5, 0);
controls.update();
// Add an ambient lights
ambient = new THREE.AmbientLight(0xffffff, 0.2);
scene.add(ambient);
// Add a point light that will cast shadows
point = new THREE.PointLight(0xffffff, 1);
point.position.set(25, 50, 25);
point.castShadow = true;
point.shadow.mapSize.width = 1024;
point.shadow.mapSize.height = 1024;
scene.add(point);
group = new THREE.Group();
group.position.y = 0;
scene.add(group);
rotationAnchor = new THREE.Object3D()
group.add(rotationAnchor);
box = new THREE.Mesh(new THREE.BoxGeometry(), new THREE.MeshStandardMaterial({
color: 'grey'
}))
b1 = box.clone();
b2 = box.clone();
b3 = box.clone();
b3.material = b3.material.clone()
b3.material.color.set('red')
group.add(box);
group.add(b1);
b1.position.y += 1
group.add(b2);
b2.position.z += 1
rotationAnchor.add(b3);
rotationAnchor.position.set(0.5, 0.5, 1.5)
b3.position.set(-.5, -.5, -.5)
// Create a renderer
renderer = new THREE.WebGLRenderer({
antialias: true
});
// Set size
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
// Set color
renderer.setClearColor(0xf8a5c2);
renderer.gammaOutput = true;
// Enable shadow mapping
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
// Append to the document
container = document.createElement("div");
document.body.appendChild(container);
document.body.appendChild(renderer.domElement);
// Add resize listener
window.addEventListener("resize", onWindowResize, false);
// Enable FPS stats
stats = new Stats();
container.appendChild(stats.dom);
var gui = new dat.GUI({
height: 5 * 32 - 1
});
let params = {
'test': 4,
'bevelThickness': 1,
'bevelSize': 1.5,
'bevelSegments': 3
}
gui.add(params, 'test', 0, 10).onChange(val => {
test = val
})
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function animate() {
rotationAnchor.rotation.z = (Math.cos(performance.now() * 0.001) * Math.PI * 0.25) + (Math.PI * 1.25)
requestAnimationFrame(animate);
// Re-render scene
renderer.render(scene, camera);
// Update stats
stats.update();
}
body {
overflow: hidden;
margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/96/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<script src="https://threejs.org/examples/js/libs/stats.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.2/dat.gui.min.js"></script>
I have added sphere and planegeometry to the scene, I have used X and Y values to place the planegeometry in
the scene, some planegeometry are overlapping with eachother I need to detect the overlapped planegeometry
and place it to a new position in order to avoid the overlapping of those planegeometry without changing the
X and Y values. can someone please help me how to solve this problem. I have just added this code in jsfiddle
I don't know exactly how to display result in jsfiddle. I have added the image of the result which might give
an idea what the problem is. https://jsfiddle.net/lakers1234/ek7fcx9L/
window.onload = createsphere();
function createsphere()
{
var controls,scene,camera,renderer;
function init()
{
var spriteResponse = [];
spriteResponse[0] = {ID:1, x: 0, y: 0, name:'Hello'};
spriteResponse[1] = {ID:2, x: 0, y: 0.01, name:'Hello world'};
spriteResponse[2] = {ID:3, x: 0, y: 0.5, name:'los Angles united states of america'};
spriteResponse[3] = {ID:4, x: 0.5, y: 0, name:'Canada'};
spriteResponse[4] = {ID:5, x: 0.25, y: 0.5, name:'London united kingdom' };
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);
//camera.position.y = 1;
camera.position.z = 1 ;
var width = window.innerWidth;
var height = window.innerHeight;
renderer = new THREE.WebGLRenderer( {antialias:true} );
renderer.setSize(width, height);
document.body.appendChild(renderer.domElement);
/* ------------------------ creating the geometry of sphere------------------------------*/
var radius = 2.5;
var spheregeometry = new THREE.SphereGeometry(radius, 20, 20, 0, -6.283, 1, 1);
var texture = THREE.ImageUtils.loadTexture ('rbi00000083.jpg');
texture.minFilter = THREE.NearestFilter;
//var spherematerial = new THREE.MeshBasicMaterial({map: texture});
var spherematerial = new THREE.MeshBasicMaterial({color: '#A9A9A9'});
var sphere = new THREE.Mesh(spheregeometry, spherematerial);
scene.add(sphere);
scene.add(camera);
scene.autoUpdate = true;
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.minPolarAngle = Math.PI/4;
controls.maxPolarAngle = 3*Math.PI/4;
}
Based on this SO answer.
When you know quaternion of your camera, you can apply it to your planes.
Put your planes in an array:
var planes = [];
and then in the animation loop we'll do this:
planes.forEach(function(p){
p.quaternion.copy(camera.quaternion);
})
jsfiddle example.
I've been testing some ideas on how to get a circle to have a different color for the part of the circle that has positive Z values. I tried one approach, creating two separate line segments and using different materials. It works if the circle has segments that don't jump across Z=0. The problem I'm working on is more complicated as the line segments will jump across the Z=0 boundary so I end up with gaps if I try to do it in two segments. Is there a way to just use one line Geom and then change the color of the part of the line that falls into negative Z values? I'm not sure this is the right approach. Thanks!
Here is what I have so far for a test (using X,Y):
<html>
<head>
<title>Cirle Color</title>
<style>
body { margin: 0; }
canvas { width: 100%; height: 100% }
</style>
</head>
<body>
<script src="three.min.js"></script>
<script>
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 500, window.innerWidth/window.innerHeight, 0.1, 100000 );
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
var segmentCount = 100,
radius = 10,
geometry = new THREE.Geometry();
geometry2 = new THREE.Geometry();
material = new THREE.LineBasicMaterial({ color: "#5fd119" }); // light green
material2 = new THREE.LineBasicMaterial({ color: "#3d8710" }); // darker green
//PUSH THE ORIGIN VERTICY IN
geometry2.vertices.push(new THREE.Vector3(-10,0,0));
for (var i = 0; i <= segmentCount; i++) {
var theta = (i / segmentCount) * Math.PI * 2;
x = Math.cos(theta) * radius;
y = Math.sin(theta) * radius;
z = 0;
if (y >=0 ){
geometry.vertices.push(new THREE.Vector3(x, y, z));
} else {
geometry2.vertices.push(new THREE.Vector3(x, y, z));
}
}
scene.add(new THREE.Line(geometry, material));
scene.add(new THREE.Line(geometry2, material2));
camera.position.z = 5;
var render = function () {
requestAnimationFrame( render );
renderer.render(scene, camera);
};
render();
</script>
</body>
</html>
Update using the answer below. Works great:
I hope I get you correctly. You can set colours of vertices of a geometry and then use vertexColors parameter of a material.
var radius = 5;
var shape = new THREE.Shape();
shape.moveTo(radius, 0);
shape.absarc(0, 0, radius, 0, 2 * Math.PI, false);
var spacedPoints = shape.createSpacedPointsGeometry(360);
var vertexColors = []; // array for our vertex colours
spacedPoints.vertices.forEach( function( vertex ){ // fill the array
if( vertex.y < 0 )
vertexColors.push( new THREE.Color( 0xff0000 ))
else
vertexColors.push( new THREE.Color( 0x0000ff ));
});
spacedPoints.colors = vertexColors; // assign the array
var orbit = new THREE.Line(spacedPoints, new THREE.LineBasicMaterial({
vertexColors: THREE.VertexColors // set this parameter like it shown here
}));
scene.add(orbit);
jsfiddle example