I'm just starting with threejs, and I'm building a basic first person shooter. I use pointer lock controls.

When the user clicks ("shoots") an object, I remove it and place it at another random position in the 3D world.

When creating the object, I want to position the object randomly, but always inside the current field of view of the user. So the object must be visible in the current view of the user when it's created.

I've tried things like h = tan(fov/2)*dist trying to get the height, but the problem is I don't have the distance between the object and the camera, since the object still needs to be created...

Any help would be much appreciated. I've found similar questions online, but they're usually about changing the camera view based on an object, but that's not what I want since the camera view is determined by the mouse of the user.

Why not simulate another click? since you already have mouse-click ray-casting (I assume), apply some random length to the ray. Any click will be in view, so your problem is already solved.

  • Interesting suggestion. But how would I simulate a random click, without moving the camera position? – binoculars Jul 19 '16 at 7:26
  • That's a terribly inefficient way to solve this – Bálint Jan 30 '17 at 14:57

You need the camera's properties for the following formula, mainly the angles of the camera, the position of the camera, vertical FOV, the aspect ratio (width / height), the near and the far clipping plane's distance.

Getting an angle that's inside the camera's view is very simple, you just use the vertical FOV, get a random value between 0 and it (I refer to this as yAngle), then calculate the horizontal FOV (vertical FOV * aspect ratio), create a random value between 0 and that too (this'll be xAngle), then you add the camera's rotation around the y axis (yaw) to the horizontal angle, and the camera's rotation around the x axis (pitch) to the vertical angle (these are xTotal and yTotal respectively).

Now you have the angles. You need to get the distance between the object and the camera. This should be a random value between the near and far value. Lastly, you need to create a vector out of this. There are multiple ways this can be done. You can either use this formula, or you can create a vector pointing in the negative z direction, then create a rotation matrix (the 2 methods do the same, the first one is just the algorithm version of the latter one).

After you got the vector, you can add it to the position of the camera and done, you get a position in the field of view of the camera.

Pseudo-code:

func getPosition(float FOV, float aspect, float cameraXAngle, float cameraYAngle, float near, float far, vec3 cameraPos) {
    xTotal := rand(0, FOV * aspect) + cameraXAngle
    yTotal := rand(0, FOV) + cameraYAngle

    distance := rand(near, far)

    vec3 direction = vec3(
        distance * cos(xTotal) * sin(yTotal),
        distance * cos(xTotal) * cos(yTotal),
        distance * sin(xTotal)
    )
    return cameraPos + direction
}

I've tried things like h = tan(fov/2)*dist trying to get the height, but the problem is I don't have the distance between the object and the camera, since the object still needs to be created

Well, you need to first randomly choose a dist value then. There's N^3 more space as you go N times further away, so picking something like dist = pow(1 - rand()/RANDMAX, 3) * max_dist should result in a believable distribution.

  • 1
    You'll want a cube root in the formula (pushing more values toward the far end where there's more space), rather than a cube (which would push more values to the narrow end). The 1 - might not be necessary, since either way the input is a random value between 0 and 1. – DMGregory Dec 6 at 13:03

I'm not familiar with three.js, but from my experience with 3D graphics, there's a simple trick you can try.

When you create a new object, move it to the camera's position, and copy the camera's rotation, this way the new object will "look" towards the same place as the camera.

Now translate the object on the +Z axis (or -Z, depending what three.js considers forward), and it will move forward inside the field of view. All 3D engines I've used have a translate function that does the math for you.

A quick search on StackOverflow, shows this solution:

object.translateZ( 10 );

Replace 10 with any value you want, this shows how far away the object will move from the camera. This will successfully place an object in front of the player, wherever they are looking at.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.