Getting points on a sphere [Solved]

Greetings JGO. This is sort of a general math question that ties into lwjgl/opengl please correct me if this is not the right board.

My problem is I’m trying to place a shape at a certain distance away from the camera in a spherical radius. Right now it works correctly for the x,z coords but the y is what I’m having trouble with.

What I’m trying to do is trying to create a point/cube 10m from the cameras current position in in any direction based on where i click. right now the code I’m using only works for the x,z axis no the y.

Above should hopefully show what I’m talking about

I know that i have to subtract the x,z coords by some amount, based on the pitch of the camera (as the y increases the z,x should be brought back) but i have no idea how to go about this.


float xr = RANGE * (float) Math.sin(Math.toRadians(-yaw));
float zr = RANGE * (float) Math.cos(Math.toRadians(-yaw));
float yr = RANGE * (float) Math.tan(Math.toRadians(pitch));
				
CubeGame.addCube(new Vector3f(pos.x - xr, pos.y - yr, pos.z- zr), 1);

here’s a pastebin of the full class for full context: http://pastebin.com/rApm19G6

Thanks for the help :slight_smile:

not sure what you exactly want to achieve … but if it’s a circle in front of the camera at a specific distance you want, i would probably …

make an axis aligned unit circle, scale by radius and multiply it by camera-inverse-projection (or was it modelview?) or something into that direction.

for points-on-unitsphere-distribution i use this :


/**
 * @param sphereFactor float : 0.0 = all vectors pointing to (0,0,1), 1.0 = hemisphere, 2.0 = full sphere
 */
public static vec3[] distributeSurface(final int numPoints, double sphereFactor)
{
  if(sphereFactor < 1.0) sphereFactor *= Math.sqrt(sphereFactor);
  else
  {
    final double d = 2.0 - sphereFactor;
    sphereFactor = ( 2.0 - ( d*Math.sqrt(d) ) );
  }

  final vec3[] points = new vec3[numPoints];

  final double off = sphereFactor/points.length;
  final double inc = Math.PI * ( 3.0 - sqrt(5.0);

  for(int k = 0; k < points.length; k++)
  {
    final double z   = k*off - 1 + ( off/2 );
    final double r   = Math.sqrt(1.0 - z*z);
    final double phi = k*inc;

    points[k] = new vec3( StrictMath.cos(phi)*r, StrictMath.sin(phi)*r, -z);
  }

  return points;
}


known as golden spiral or fibonacci sphere distribution.

@basil_ sorry for not being so clear. what I’m trying to do is trying to create a point/cube 10m from the cameras current position in in any direction based on where i click. right now the code I’m using only works for the x,z axis no the y.

This is called “unprojecting.” What you generally have to do here is to take the transformation which brings you from view-space to clip-space, and then just do the opposite transformation. That “transformation” is usually a 4x4 matrix.
And in OpenGL this transformation is the “projection” matrix (without any view or model transformations).
And in matrix-speak the “opposite” transformation of a matrix is the inverse of that matrix. So do a matrix inversion of that projection matrix.
After that, you can multiply any clip-space position/vector by that matrix and end up with the homogeneous view-space position.
Also you don’t need any sine/cosine functions to do that.
Now the next problem is how to get a vector in clip-space from your mouse coordinates.
First thing, we take your mouse coordinates, which are in window coordinates and transform them to normalized device coordinates (NDC) by normalizing them between (-1, -1) and (+1, +1), so that the center pixel coordinate of your window yields (0, 0).
Then I’d build a NDC/clip-space coordinate (NDC.x, NDC.y, 0, 1), where NDC.x and NDC.y are your previously computed mouse coordinates in NDC space and the ‘Z’ coordinate is 0 which means the near frustum plane.
You can then matrix-vector multiply that vector by the previously computed inverted projection matrix, which will yield a position in homoegenous view-space.
Then, do a perspective divide (dividing your vector by its own ‘w’ component) to get from homogeneous coordinates to real 3D coordinates.
Next thing is to make sure that the vector is exactly 10 units of length away from your camera. An easy solution is to normalize that vector and multiply by 10.
Since we are in view/camera space, the vector is still pointing into the same direction when viewed from the camera.
Now if desired, we just need to do another transformation from view-space to world-space. This can be done using the inverse view matrix in OpenGL.
There you have your world-space coordinate.

Note that this is a general algorithm that works with any projection (orthographic or perspective) and with any camera/view position/rotation etc…
If your setup is simpler and you restrict your camera to certain properties, then a simpler solution might be possible.

Here is a nice overview of all the spaces involved in OpenGL: http://www.songho.ca/opengl/gl_transform.html (view-space is called “eye coordinates” there).

And here for the corresponding “JOML code” (using latest 1.6.6-SNAPSHOT):


int[] viewport = {0, 0, 800, 800};
Vector3f mouseWinCoordinates = new Vector3f(400, 400, 0);
Vector3f viewCoords = new Vector3f();
Vector3f worldCoords = new Vector3f();

// Build projection matrix (if not already done)
Matrix4f proj = new Matrix4f();
proj.perspective((float) Math.toRadians(90.0f), 1.0f, 0.01f, 100.0f)
// unproject window coordinates to view-space
.unproject(mouseWinCoordinates, viewport, viewCoords)
// make them 10 units of length away from the camera
.normalize().mul(10);

// Build view matrix (if not already done)
Matrix4f view = new Matrix4f();
view.lookAt(0, 0, 5,
            0, 0, 0,
            0, 1, 0)
.invert() // <- invert to get from view-space to world-space
// Transform view-space coordinates to world-space
.transformPoint(viewCoords, worldCoords);

// Your world-space coordinates are now in 'worldCoords'

Thanks a bunch KaiHH, in the end i managed to get it working by doing most of what you said but with a few modifications, i also found this great tutorial on that helped me bunch http://www.antongerdelan.net/opengl/raycasting.html


	Vector4f clipCoords = new Vector4f(0,0,-1.0f,1.0f);
	Vector4f eye = Matrix4f.transform(Matrix4f.invert(projMat, null), clipCoords, null);
	Vector4f eyeCoords = new Vector4f(eye.x,eye.y,-1f,0f);
	// calculate world ray:
	Matrix4f invertedView = Matrix4f.invert(viewMat, null);
	Vector4f rayWorld = Matrix4f.transform(invertedView, eyeCoords, null);
	Vector3f worldRay = new Vector3f(rayWorld.x,rayWorld.y,rayWorld.z);
	worldRay.normalise();
	worldRay.scale(RANGE);
		
	CubeGame.addCube(new Vector3f(pos.x +worldRay.x, pos.y + worldRay.y, pos.z
			+ worldRay.z), 1);

Great! :slight_smile:
It looks to me that your “viewMat” then does not contain the camera translations.
In this case, scaling the “worldRay” vector does work, since the origin of both view-space and world-space coincide. If your camera (i.e. your “viewMat,” that is) is translated to anywhere else than the world-origin, scaling the world vector does not work anymore. Just keep that in mind.
And assuming that “pos” is your camera position, you can omit offsetting your computed world vector by that if you just include that translation into the camera’s “viewMat.”