#22108 - ProblemBaby - Sun Jun 13, 2004 3:06 pm
Hi
Iam trying to place some objects in my mode7 environment but it won't work! and I cant understand why.
I've started to just get the right position (no scaling) and my code goes something like this.
d = viewdistance;
obj_x, obj_y, obj_z = object position in world space
cam_x, cam_y, cam_z = camera position in world space
spr_x, spr_y, spr_width, spr_height = sprite pos and size
Code: |
x = obj_x - cam_x;
y = obj_y - cam_y;
z = obj_z - cam_z;
spr_x = (120+((x * d) / z)) - (spr_width/2);
spr_y = (80-((y * d) / z)) - (spr_height/2);
|
yes it is many divisions but i'll get rid of it when it works...
then I wonder how to achieve the correct scale.
plz help!
#22120 - keldon - Sun Jun 13, 2004 6:00 pm
what's your input data, if you mind me asking?
hold on .. I'm about to edit this post to just give you a correct formula
Last edited by keldon on Sun Jun 13, 2004 6:04 pm; edited 1 time in total
#22121 - ProblemBaby - Sun Jun 13, 2004 6:02 pm
um input that should work.. if its done in a correct way but
I think it is one thing that is missed.. but I dont know what=((
#22122 - keldon - Sun Jun 13, 2004 6:11 pm
spr_x = 120 + ( x / ( z + d )) * d
spr_y = 80 + ( y / ( z + d )) * d
spr_width = ( spr_width / ( z + d )) * d
spr_height = ( spr_height / ( z + d )) * d
---
it's basically trigonometry, the same used in 3d perspective conversion. And by changing d, you get the effect of zooming in and not just getting closer - there is a big difference. Just watch out for divide by 0. And to test that it works, set z to 0 and it should come out in roughly the correct places - but if you want them exact the rewrite the formula so that it multiplies x then divides.
#22124 - ProblemBaby - Sun Jun 13, 2004 6:30 pm
when I try this the sprite appears in the middle of the screen all the time
even if I change the pos of the object or the camera
x, y, z is the relative coordinates between cam and obj right?
#22143 - keldon - Sun Jun 13, 2004 9:15 pm
spr_x = 120 + (x * d) / (z + d)
spr_y = 80 + (y * d) / (z + d)
it's a precision thing, if you divide and make 0 all the time, then it will all be in the middle.
#22187 - Cearn - Mon Jun 14, 2004 12:28 pm
keldon wrote: |
spr_x = 120 + (x * d) / (z + d)
spr_y = 80 + (y * d) / (z + d)
it's a precision thing, if you divide and make 0 all the time, then it will all be in the middle. |
You mean a fixed point thing, right? But that shouldn't matter much in this case since the endresult is supposed to be a pure integer anyway. (or was that the point of your post?)
You may want to lose the extra addition by d, though, since the top of the viewing pyramid is at z=0, not z=-d. Also, remember that the screen y-axis points down, while your world y-zxis probably points up, which would mean that the you need to subtract the projected y coord, not add.
Code: |
spr_x = 120 + (x * d) / (z)
spr_y = 80 - (y * d) / (z)
|
You can cut down on one of the divisions if you out something like (d<<16)/z in a temporary first; though you might have to play with the exact shift a bit.
For proper scaling, you'd have to use something like pa=pc=z/d, though there are reasons for doubling this number. Of course, you still to alter a few things when you rotate (either yaw or pitch), and there's still clipping
to take care of.
#22188 - keldon - Mon Jun 14, 2004 1:16 pm
It's a trigonometry thing, so we need ( z + d ) for the scaling, which is weighted by the value of d.
Code: |
^ |-----/ obj_x - cam_x
|$ | /
v | /
^ |--/ spr_x
|? | /
v |/
|
? represents d, $ represents obj_z - cam_z (z)
So what this does is scale obj_x - cam_x to calculate spr_x. I rewrote the order because (z + d) is likely to be greater than x, so x / (z + d) would most likely result in 0. I just forgot that problem completely when writing the formula, because I'd usually work in floats.
#22192 - Cearn - Mon Jun 14, 2004 2:47 pm
keldon wrote: |
It's a trigonometry thing, so we need ( z + d ) for the scaling, which is weighted by the value of d.
Code: |
^ |-----/ obj_x - cam_x
|$ | /
v | /
^ |--/ spr_x
|? | /
v |/
|
? represents d, $ represents obj_z - cam_z (z)
|
This really depends on the relationship between the camera and the projection plane. In your case you have the projection plane at z=0 and the camera at z=-d; usually you'll take the camera at the origin and z=d (or z=-d in a righthanded system).
Code: |
spr_x
| obj_x
| |
^ |-----/ - obj_z
|$ | /
v | /
^ |--/ - spr_z
|? | /
v |/ - cam_z
|
In camera space (which has the camera position as its origin), then
x = x_obj-x_cam (vector!) and the projection plane is d in front of the camera, so spr_z=d. In that case, x_spr = x_obj *d / z. For example, if an object is located d units in front of the camera (that is, z=d), it's scale should be 1, which indeed would happen with d/z, but not with d/(d+z).
EDIT: now I remember what the deal was here. What is casually called " the camera position" can be either the back of the camera,in which case you'd use d/z; or the front of the camera, which uses d/(d+z). Which of these you use is a matter of taste, though I think most of the time it means the back of the camera, though.
#22200 - keldon - Mon Jun 14, 2004 5:04 pm
oh, I get your formula now; camera at 0,0,0. I usually have the screen at 0,0,0; but I think your way is much better as it means you don't have the additional add
#22216 - ProblemBaby - Mon Jun 14, 2004 11:11 pm
Today i changed my mind I dont want a mode7 environment
just a background that doesn't move something like this
Code: |
___
/ \
/ \
/________\
|
its just a picture
well i found out that I could do this to find out the x-coordinate
for an object in this picture
slope of the outer line (in y) = x/y
and then build a table
like
zTable[z] = FAR_X2 + (z * slope)
and then if I had a x-world coordinate between -1 and 1 just multiply it
with tzTable[obj_scr_y] i found out the correct x coordinate.
and i can use it to scale it so it looks good
but the question is how do I found the correct y??
if I just have a picture to look at is itsome lines that tells how much the object should move in y-direction (screen) according to the world_z???
or is it impossible to find out?[/code]
Last edited by ProblemBaby on Mon Jun 14, 2004 11:49 pm; edited 1 time in total
#22217 - keldon - Mon Jun 14, 2004 11:49 pm
I gather that the z values are finite, right? And this is the picture you meant to draw??
Code: |
_____
/ \
/ \
/ \
/___________\ |
Movement in the X and Y direction is straight forward, just make sure that your camera position is in line with your background picture. I would do this with a sheet of paper, and a calculator to plot coordinates of the background so that it perfectly matches the camera position.
The correct Y will be found by using the z value, as moving away from the camera will now also raise the sprites on screen position. And the Y value is scaled however you see fit - - although you may wish for it to be precise, so get your calculator out.
I assume you know and understand the trigonometry involved ?!?
#22221 - ProblemBaby - Tue Jun 15, 2004 12:33 am
Yes it was:D
but I have try and i cant find out the connection between z-world and
y-screen.
I know how I should scale and the x position if I get the correct y-screen coordinate, Iam quite sure about it had exact as the x value something
with the slope of the outer lines to do but I cant find out the actual formula.=(
#22235 - keldon - Tue Jun 15, 2004 11:05 am
Code: |
a1_____ a2
/ \
/ \
/ \
a3/___________\a4
|
Code: |
<| (camera)
a3,4__________a1,2 (ground)
|
now the camera has a position; which should be at about (120,80,-400) for its (X,Y,Z), [b]d[/d] should be about 200. Now set a1-a2 at (Z=400,Y=0) and a3-a4 at (Z=0, Y=0) and a1-a3 at (Y=0, X=0) and a2-a4 at (Y=0, x=240) for now. And just calculate the screen x position using our formulas we gave you; and experiment until you are satisfied with its arrangement on the screen. Also jig about with the camera etc.
#22241 - ProblemBaby - Tue Jun 15, 2004 4:12 pm
Thanks alot!
now I know how to do (almost) everything!
my very last problem is:
Ive started do draw dots at the edges of my square (board)-picture
to find out which values I should use for everything.
but when I look at it the camera isnt just like this:
|_|<
________________
more like this:
\
\
/_
/ |
_____________________
I do my transformation like this:
Code: |
// COS, SIN is a table 0-255 with fixed values for sin and cos
theta = 256 - 64;
x = IntToFixed((BOARD_LEFT - CAMERAX));
y = IntToFixed((0 - CAMERAY));
z = IntToFixed((BOARD_FAR - CAMERAZ));
//I thought that the 'rotate around pitch' transformation looked like this
y = FixedMul(y, COS[theta]) + FixedMul(z, SIN[theta]);
z = FixedMul(y, -SIN[theta]) + FixedMul(z, COS[theta]);
|
#22243 - ProblemBaby - Tue Jun 15, 2004 4:40 pm
omg it should be minus of course!
#22310 - ProblemBaby - Thu Jun 17, 2004 12:38 pm
Now Ive only two problems left!
my sprite is 8x8x8 size in the world
In the cameratransformation should i do like this?? to later find the correct x1, y1 in screen coords?
Code: |
x = (x_obj - 4) - x_cam; // 4 is the half of the size of the object in world
y = (y_obj - 4) - y_cam; // 4 is the half of the size of the object in world
z = (z_obj - 4) - z_cam; // 4 is the half of the size of the object in world
// here goes the rotation
// and here the perspective transform
// and screen transform
|
Is this how it should be done? it doesnt feel correct=/
then how do I find the scalefactor??
like this?
Code: |
x1 = (x_obj - 4) - x_cam; // 4 is the half of the size of the object in world
y1 = (y_obj - 4) - y_cam; // 4 is the half of the size of the object in world
z1= (z_obj - 4) - z_cam; // 4 is the half of the size of the object in world
x2 = (x_obj + 4) - x_cam; // 4 is the half of the size of the object in world
y2 = (y_obj + 4) - y_cam; // 4 is the half of the size of the object in world
z2 = (z_obj + 4) - z_cam; // 4 is the half of the size of the object in world
// here goes the rotation
// and here the perspective transform
// and screen transform
|
x2-x1 = size in pixels, but that isn't true=/
I know that I dont just can use X but how should i do?
and last which should i do first translation or rotation?
help would be great or a link to a tutorial that talks about billboarding
(with software), cant find any=/
#22369 - Cearn - Sat Jun 19, 2004 3:45 pm
Remember that sprites aren't 3d objects. Almost everytime you have a sprite in a 3d world it will use one 3d coordinate, which corresponds to one screen coordinate, which is where the sprite will be placed. The whole sprite will use one scale, based on this transformation.
The problem with this is that when you rotate, the sprite will seem to rotate with you in such a way that you're always facing it (see Doom for example, or any old 3d or mode 7 game). To be sure it seems to rotate around the right point, you'll have to define an anchor point on the sprite, which corresponds to `the' sprite's position in world space and the compensate for this anchor's position (as well the scaling) when you write the screen location to OAM.
I have this on code on my site (the mode7d demo) and had hoped to have a document explaining it all by the end of this week, but didn't quite make it, though you can see a draft here
#22380 - ProblemBaby - Sat Jun 19, 2004 7:58 pm
Yeah I read it but I found out almost myself how should be done
with some own touch though;D
but it looks good at works well and thats the most important thing for the moment.
And since Ive a view that doesnt rotate the rotation problem
is no problem.
Thanks for all support!
especially Keldon
and Cearn for your tutorials
#22389 - dagamer34 - Sun Jun 20, 2004 12:21 am
ProblemBaby wrote: |
Yeah I read it but I found out almost myself how should be done
with some own touch though;D
but it looks good at works well and thats the most important thing for the moment.
And since Ive a view that doesnt rotate the rotation problem
is no problem.
Thanks for all support!
especially Keldon
and Cearn for your tutorials |
Feel like sharing the code? :)
_________________
Little kids and Playstation 2's don't mix. :(