Not an easy task. I wrote some code that did this about a year ago, and heres the approach I used. . .
(1) Define your paintable objects. Store them as a collection of 3-dimensional points. (ie. a cube is a collection of eight Point3Ds in space.)
(2) Define your perspective using a plane. Eventually, you'll be projecting points on to this plane. To make the projection easy, the plane needs to be represented as two orthonormal vectors. (To understand whats going on, think of this plane as the surface of your monitor. Vector one is an imaginary line across the bottom of the screen, and Vector 2 is a line up the left side.)
(3) Project the objects on to the plane. Before painting an object on the screen, first project each of its 3d points on to the perspective plane. The projection can be done by computing the scalar product of your point with each of the orthonormal vectors in step 2. The result of the first product is your X coordinate, the second is your Y coordinate.
(4) Draw it on the screen. After you've done the projections, scale the results to the size of your image, and draw them using Graphics 2D.
(5) Filling planes. If all you want to do is draw wireframe models, you're done. Filling in regions is a bit trickier, since each region is probably opaque. You can use the Graphics2D fillPolygon method, but first you need to implement your own solution to a classic problem in imaging called the Visibility Problem. Basically, you need to decide which regions get filled in, and in what order. I'd recommend using Painters Algorithm: http://en.wikipedia.org/wiki/Painters_algorithm
You're done!. . .by the way, did I mention that a background in linear algebra makes this a lot easier. . .
Anyway, this is a lot of work, but the results are pretty cool. And if you're like me, you get to run around bragging to all your friends that you wrote your own 3d imaging software, lol.
Yes, I thought about projection, too but looking for example code. My aim is to do some 3D mapping of images (e.g. wrap a 2D image around a sphere) and plot single pixels in a 3D coordinate system (X,Y,Z diagrams). Would be helpful to get some example code how to do the projection/transformation of the x/y/z points to the x/y panel.
Before going on, you may want to revisit your decision to even engage this problem. You're basically building your own 3d library, which is not a straightforward task. If you do not have a background in Advanced Calculus, Physics, or Linear Algebra, you will be seeing some new mathematics. You'll also be writing a LOT of code, that even when completed, will be difficult to use. Now assuming you want to continue. . .
You actually have two problems.
The first problem is mapping the pixels of an image to the surface of a sphere, which is not something I've worked on before. You'll need a mapping transformation to define how the wrapping will be done (since the surface of a sphere is not rectangular). Heres the first one that popped into my mind: map each line of latitude to a horizontal strip on the image. In other words, as you trace a line of latitude around the sphere, moving from longitude 0 to 360, get your color information from 0 to image.getWidth(), at a fixed Y value. Note that this solution will cause your image to look bloated near the equator. Also note that any efficient mapping transformation is going to require directly interacting with the image pixel data.
The second problem is projecting your 3d pixels to a 2d plane (the screen). As noted in my previous response, you'll need to define the plane in terms of two orthonormal basis vectors, and compute the dot product of your 3d point with each vector.
/* This code assumes the existence of a Point3D class with public
* x, y, and z coordinates. It also assumes the existence of a Plane3D
* with two Vector3D basisVectors. Each Vector3D also has an x, y and z.
*/
public static Point project(Point3D point, Plane3D ontoThis){
//compute the scalar product of the 3d point with the
//planes first basis vector
int x = (point.x * ontoThis.basisVector1.x) +
(point.y * ontoThis.basisVector1.y) +
(point.z * ontoThis.basisVector1.z);
//compute the scalar product of the 3d point with the
//planes 2nd basis vector
int y = (point.x * ontoThis.basisVector2.x) +
(point.y * ontoThis.basisVector2.y) +
(point.z * ontoThis.basisVector2.z);
//return the data
return new Point(x,y);
}
Notice that to control the perspective, you have to change your plane's basis vectors. This can make your scene difficult to control. Also, if you pick vectors that are not orthonormal, you will get crazy results. (This is comparable to telling the computer that the X and Y axis's do not intersect at a right angle, or that one axis is longer than another.)
I do not yet have a solution that provides an intuitive way of controlling perspective.
Message was edited by:
BillC