so I want to be able to draw a circle like you may do in Word or Powerpoint. from the users point of view they will click once to set the centre, and then a second time to set the radius.
I know the screen point that the mouse is on
I will know the centrepoint x,y,z.
My plan was to then create a plane at the centrepoint whose normal I will also eventually know, this will more than likely not face the camera, for now i am using a basic vector.
I then thought I should be able to get the point at which the mouse intersects this plane, and the raidus will be the distance between that intersect point and the centrepoint, then i can easily just draw a circle. so heres my code
screenPoint.unproject( camera );
let raycaster = new THREE.Raycaster();
raycaster.setFromCamera(screenPoint, camera);
//eventually will be worked out elsewhere this is just temp`
let normal = new THREE.Vector3(0, 0, 1);
let plane = new THREE.Plane();
plane.setFromNormalAndCoplanarPoint(normal,centrePoint);
let intersectPoint = new THREE.Vector3();
raycaster.ray.intersectPlane(plane, intersectPoint);
let radius = centrePoint.distanceTo(intersectPoint);
let geometry = new THREE.CircleGeometry(radius, 60);
// Remove center vertex
geometry.vertices.shift();
let material = new THREE.LineBasicMaterial({color: red});
//To get a closed circle use LineLoop instead
let mesh = new THREE.LineLoop(geometry, material);
mesh.position.set(centrePoint.x, centrePoint.y, centrePoint.z);
scene.add(mesh);
Im clearly doing something utterly wrong, i get a circle but the radius is miles out. I found a few stack overflow answers which didnt help me (more than likely more lack of understanding) alot of the answers I found seems to not really work in 3d, more assume a plane is facing the camera. ANy pointers would be very much appriciated
When you have a big problem, and the whole thing isn’t coming together, break it into parts and make the parts work individually before bringing them together.
If this were my project, I would break it into three pieces:
Creating the Plane
Raycasting against the plane
Creating a circle based on two vectors
For item one, make sure you understand how the plane is created, and how it will react to your raycaster. I’m not sure what centrePoint you’re using, but this should be somewhere along the -z axis in camera space. (The camera looks down along its own -z axis, so anything with a z value below 0 will be “in front of” the camera.)
It looks like you’re already raycasting correctly, but it can’t hurt to drop a simple Mesh (like a box or a sphere) at the intersect point to verify you’re getting the correct coordinates.
Finally, again, it looks like you’re using the correct methods to create the circle, but you’ll need to ensure that not only the positioning is correct, but also the rotation orientation as projected from camera space.
Thanks for the replies. I will take some time to digest your codepen example and see where I am going wrong.
I like the way you chaange the scale of the circle. For future knowledge, is there a reason you set the scale of the circle, rather than just recreating the radius?
I just don’t want to use the technique of dynamic geometries for no reason, as it’s computationally expensive Scaling is fast and easy to implement
To expand on this, consider that you have a circle with even a small number of vertices (say, 32).
When the geometry is initialized, that buffer of vertices is sent to the GPU (32 * 3 = 96 float values).
If you updated the vertices individually for perform a scale, not only would you be performing at least two operations per vertex (computation and assignment), but then the entire buffer would need to be sent to the GPU again (all 96 float values).
On the other hand, if you change the scale, then you really only update the transformation matrix (16 float values). Yes, those 16 float values are sent to the GPU every time you update them, but it’s only ever 16 values. I’m sure you can now see why this would be the preferred way of scaling a mesh, especially as the meshes become larger and more complex.