3D projection question(s)!

Started by
5 comments, last by staticVoid2 15 years, 11 months ago
First off, what im trying to do is create a basic 3d cord to 2d cord system in Actionscript3(Flash), but Iv got some questions, using the "Perspective projection" code found here http://en.wikipedia.org/wiki/3D_projection description of your image description of your image Main questions are, The rotation of the camera, degrees/radians? the viewer position in camera space. Huh? anyone care to explain that, would it be just 0,0,0 or The Cam.x,Cam.y,Cam.z im sure ill have more as they come....oh and if I want my world to be setup as X/Y =left/forward and z=up/down what rotation would I change by 90 Degrees to get this?(on the camara) Currently the setup is acting very odd, cant seem to get it to work right(but zero errors!)

function ScreenCordX(ax,ay,az) {
	var dx, dy, dz,bx,by,cx,cy,cz,crx,cry,crz;
	cx=Cam.x;
	cy=Cam.y;
	cz=Cam.z;
	crx=0;
	cry=0;
	crz=Cam.rotation/360;

	dx=cos(cry)*(sin(crz)*(ay-cy)+cos(crz)*(ax-cx))-sin(cry)*(ax-cx);
	dy=sin(crx)*(cos(cry)*(az-cz)+sin(cry)*(sin(crz)*(ay-cy)+cos(crz)*(ax-cx)))+cos(crx)*(cos(crz)*(ay-cy)-sin(crz)*(ax-cx));
	dz=cos(crx)*(cos(cry)*(az-cz)+sin(cry)*(sin(crz)*(ay-cy)+cos(crz)*(ax-cx)))-sin(crx)*(cos(crz)*(ay-cy)-sin(crz)*(ax-cx));
	bx=(dx-0)*(Cam.z/dz);
	by=(dy-0)*(Cam.z/dz);
	return bx;
}
I know the above is a very bad as far as scripting goes, but ill worry about formating later. Also, iv made functions sin(a)=Math.sin(a) simply to save some space and make it so they all line up
Advertisement
okay! iv got it all working, expect one thing, I still cant figure out what this "the viewer position in camera space" is, it works if I keep it at 0,0,0 but then I cant raise the cams Z value without it going crazy :S
is Cam.x and Cam.y the camera position in world space or is it the viewer position in camera space?

If it is the first then you need to define a separate location in camera space. this is just another translation vector. so take for example:

(0, 0, 1000) this means the viewer will be positioned 1000 units behind(or infront) the camera. so your code will now look like:


bx=(dx-0)*(1000/dz);
by=(dy-0)*(1000/dz);

note: you will probaly see points that are behind the camera because eg.
(10, 10) / -5 = (-2, -2) which will still be a valid point on screen if your x and y axis intersect at for instance the center of the screen.
Quote:Original post by staticVoid2
is Cam.x and Cam.y the camera position in world space or is it the viewer position in camera space?

If it is the first then you need to define a separate location in camera space. this is just another translation vector. so take for example:

(0, 0, 1000) this means the viewer will be positioned 1000 units behind(or infront) the camera. so your code will now look like:


bx=(dx-0)*(1000/dz);
by=(dy-0)*(1000/dz);

note: you will probaly see points that are behind the camera because eg.
(10, 10) / -5 = (-2, -2) which will still be a valid point on screen if your x and y axis intersect at for instance the center of the screen.


Cam.x and Cam.y are the camera position in world space, this whole "Viewer position" and camera space is what is throwing me off :S

is the Viewer how a Field of view effect would be applyed? I noticed theres a major fish eye effect going on as is

you are probaly not translating the screen coordinates so that they are fixed around the center instead of the top left corner.

try:
function ScreenCordX(ax,ay,az) {	var dx, dy, dz,bx,by,cx,cy,cz,crx,cry,crz;	cx=Cam.x;	cy=Cam.y;	cz=Cam.z;	crx=0;	cry=0;	crz=Cam.rotation/360;	dx=cos(cry)*(sin(crz)*(ay-cy)+cos(crz)*(ax-cx))-sin(cry)*(ax-cx);	dy=sin(crx)*(cos(cry)*(az-cz)+sin(cry)*(sin(crz)*(ay-cy)+cos(crz)*(ax-cx)))+cos(crx)*(cos(crz)*(ay-cy)-sin(crz)*(ax-cx));	dz=cos(crx)*(cos(cry)*(az-cz)+sin(cry)*(sin(crz)*(ay-cy)+cos(crz)*(ax-cx)))-sin(crx)*(cos(crz)*(ay-cy)-sin(crz)*(ax-cx));	bx = (dx - <center x>) * (<field of view>/dz);	by = (dy - <center y>) * (<field of view>/dz);	return bx;}


the field of view (in this case) is just the distance the projection plane is in front of the camera. the smaller this value is the more you will be able to see around you so you can set this value to whatever you prefer, say 800 for now. then center x and center y is the position on your window/screen etc. so say you had a 800 by 600 window, you would set these as (800/2) = 400 and (600/2) = 300 respectfully. try these values and see what happens.

Quote:
is the Viewer how a Field of view effect would be applyed? I noticed theres a major fish eye effect going on as is


yes. the viewer position in this case is just the same as applying a 3d projection to 2d screen space, its just put in a different syntax from usual.

[Edited by - staticVoid2 on May 13, 2008 3:44:24 PM]
Okay, so just to make sure iv got this right, the Viewer position is essentially the "Cone" you see on cameras(for example, in most 3d rendering programs) while the X,Y control the plane Height/Length and the Z is the distance from the camera pos? I tried using Height/2 and Width/2 for the X,Y values and it seems to make an odd effect(Seemingly random, the object is there, and you can see it, but its like...warped like crazy)

Edit: this seems to create a good looking effect,

bx=(dx-0)*(80/dz);
by=(dy-0)*(80/dz);

and then in the setup part,

Draw.x =width/2;
Draw.y =height/2;

(Draw is the object that everything is rendered to)

800 creates a rather huge zoomed effect, assuming it works that the "800" means 800 from the camera, that would be nearly across the map haha but I shall keep tweaking it, ill post an example in a sec
why do you set crx and cry to 0 and why Cam.rotation/360 for z? here's a working version in C:

struct Point3D{	Point3D(float x, float y, float z) : x(x), y(y), z(z) {}	float x, y, z;};struct Camera{	Camera(void) : rotation(0, 0, 0), location(0, 0, 0) {}	Point3D rotation;	Point3D location;};Point3D transform(float ax, float ay, float az, Point3D center, Camera Cam){	float bx, by;	float crx = Cam.rotation.x,			cry = Cam.rotation.y,			crz = Cam.rotation.z;	float cx = Cam.location.x,			cy = Cam.location.y,			cz = Cam.location.z;	float dx=cos(cry)*(sin(crz)*(ay-cy)+cos(crz)*(ax-cx))-sin(cry)*(ax-cx);	float dy=sin(crx)*(cos(cry)*(az-cz)+sin(cry)*(sin(crz)*(ay-cy)+cos(crz)*(ax-cx)))+cos(crx)*(cos(crz)*(ay-cy)-sin(crz)*(ax-cx));	float dz=cos(crx)*(cos(cry)*(az-cz)+sin(cry)*(sin(crz)*(ay-cy)+cos(crz)*(ax-cx)))-sin(crx)*(cos(crz)*(ay-cy)-sin(crz)*(ax-cx));	bx = dx * 800 /dz;	by = dy * 800 /dz;	bx += center.x;	by = center.y - by;	return Point3D(bx, by, dz);}


this is highly inefficient, you would be better just storing transformation and projection in one matrix. (and most parameters are passed by value) but for now it will do. It's basically the same as your code, I've pased the center as a 3d point but you only use the x and y off of it. note: when you are rotatating your camera make sure the rotation is in radians not degrees because most math libraries cos and sin func. parameters are radians. I've tested this code and it seems to work.

[Edited by - staticVoid2 on May 14, 2008 5:50:06 AM]

This topic is closed to new replies.

Advertisement