-
distance algorythm help
ok ive been try8ing to work this out for a while now, say if we have an x,y 2d position, and a "3d" view is required how could i turn the x,y co-ordinates into a point of view co-ordinate like a side on view that gives a false definition of depth, i ve got sprite scaling to work fine for it but im having trouble getting the correct blit coordinates to make it look like its going towards the horizon (center of view) its not a good explanation of my prob, if u need more of my dogey explanations of the problem just say so, but if u can help out with the problem it would be great, thanx
-
Another explanation of your problem would be helpful :D I think I understand what you're trying to say, and my thought is to try leaving the your sprite at the desired final coordinate and letting the sprite scaling to do the job of animation for you.
-
ok below is a dogey image to help explain, i think that ID software used a simular algorythm to make doom appear 3d, although it is actualy 2d but uses a blitting algorythm (which i want) to make it appear 3d
http://members.lycos.co.uk/csoft/eg.JPG
-
I think I understand better now. Something that should give more feel of depth is to have the objects move across the screen with the speed depending on the depth. If you have any good ol' Super Nintendo or Genesis games you can look at, study those for even more ideas.
-
ive thought of that idea also, thanx for ur hep.. i guess tho for now itl have to stay 2d..
-
You're welcome. The technical name for the doom engine's effect if I remember right is called raycasting, there should be a lot of easily findable information about it.
-
Yes DOOM used raycasting and what you are referring to has little or nothing to do with raycasting.
To determine the x,y screen coords of any object from the 3D coords, here is a simplified version of the projection transformation:
Let's assume your 3D coords for your object are in camera space.
screen_x=camera.x*view_plane_dist/camera.z+halfscreen_x;
screen_y=camera.y*view_plane_dist/camera.z+halfscreen_y;
For info on DOOM-like raycasting consult Peroxide tutorials 7 and 8 or PXDTUT7 and PXDTUT8 (I think it's 8, maybe 9). Google it and you will find em.
-
Actually bubba, if I am not mistaken, what you are doing IS raycasting. Don't those equations simply find the 2D screen coordinates where the ray that was casted from the camera to a transformed vertex intersects the viewing plane?
edit
the way I am used to seeing it (for DirectX coordinate system) is:
1) transform the vertex (using inverse translation and angles, effectively leaving camera position at origin, but transforming vertex around camera pos to simulate movement/rotation)
2) screen coord pos = vertexpos * (planedist/vertex.z)
-
No a raycast is much different than that.
Raycast will divide the ray into itx x and y components.
Essentially in ortho ray casting if you know the size of each cell then you can find out the stepsize for each component via tangent instead of sin cos.
cos(theta)=adj/hyp
sin(theta)=opp/hyp
tan(theta)=opp/adj
if you know adj or opp which we do...its the cellsize, then you can find the other.
This is essentially a projection transform...you are finding the height of the wall by dividing by the distance from the camera, but to equate raycasting with an actual projection transform is not a good habit. They are two fundamentally different approaches. One is fake 3D and one is true 3D.
Actually in DX there is more going on than that. The clip matrix transforms from camera space to clip space to get the correct value in W.
Direct3D clip matrix:
0<=z<=w
Mclip=
[zoomx 0 0 0]
[0 zoomy 0 0]
[0 0 (f/(f-n) 0]
[0 0 (nf/(n-f)) 0]
then:
screenx=(clipx*resx/2*clipw)+screencenterx;
screeny=(clipy*resy/2*clipw)+screencentery;
zclip and wclip can be used for zbuffering and perspective correction.
But I think we are straying off topic.
Here is a crappy slow raycast using sin cos:
Code:
void Slow2DRaycast(Player &thePlayer)
{
//Compute casting angle for 60 degree FOV
float angle=thePlayer.angle-30f;
if (angle<0.0f) angle+=360.0f;
//Compute angle increment for screen res x
float angleinc=60.0f/horiz_res_x;
//Ray position
float rayx=0.0f,rayy=0.0f;
//Ray steps
float ix=0.0f,iy=0.0f;
//Height of hit wall
float heightofslice=0.0f;
//Map position intersected by ray
int mapx=0,mapy=0;
//Color of slice
int wallcolor=0;
//Floor and ceiling screen y locations
int floor=0;
int ceiling=0;
//Cast from 0 to horizontal screen res
for (int screenx=0;screenx<horiz_res_x;screenx++)
{
//Set ray origin at player location
rayx=thePlayer.x;
rayy=thePlayer.y;
//Compute increments
ix=cos(DEGTORAD(angle));
iy=sin(DEGTORAD(angle));
do
{
//Advance ray
rayx+=ix;
rayy+=iy;
//Compute ray map coords from ray world coords
int mapx= rayx/CELLSIZE;
int mapy=rayy/CELLSIZE;
//keep ray on map - only works on maps that are a power of 2
mapx&=(mapwidth-1);
mapy&=(mapheight-1);
//Retrieve value from map at ray intersection
wallcolor=map(mapy*mapwidth+mapx);
//Check to see if we hit a wall
if (wallcolor)
{
float dx=rayx-thePlayer.x;
float dy=rayy-thePlayer.y;
//Compute actual distance from player
//extremely slow - could use cos for distance
heightofslice=sqrt((dx*dx)+(dy*dy));
//Compute ceiling and floor
ceiling=centerscreeny-(heightofslice/2.0f);
floor=ceiling+heightofslice;
//Draw the slice
VerticalLine(screenx,ceiling,floor,wallcolor);
}
} while (wallcolor==0);
//Increment angle and check for angle>360.0f
angle+=angleinc;
if (angle>360.0f) angle-=360.0f;
}
}
-
Okay, after reading that post, I can see a fundamental difference.
I'm glad you cleared that up for me :)