My simple 3D Z issue
BlitzMax Forums/BlitzMax Programming/My simple 3D Z issue
| ||
Ok so I made a simple pseudo 3d plotting engine. This is not true human eye 3D but is based on the "one vanishing point" method of projection. If you draw a cube in this perspective the face is compleatly visable but the sides skew to point towards the vanashing point. My engine calculates the x and y coordinate based on the x,y,z point. It then plots it. Any z point with a value greater than 0 is plotted. I thought I had it working 100% but then I noticed that points with a z value lower than the camera get plotted in reverse and the z value gets multiplied by -1. This is a huge problem because nothing can be higher than the camera. I'll include some quick shots and the source. A cylindar with a positive z value( works GREAT!) ^The very same rings with a z of -2 (above the projection plane) Now for the source. (Just copy and paste into the editor of your choice.) Strict graphics 640,480 SeedRnd(MilliSecs()) 'now we make a some objects to demonsrtate the data Type spiral Global spiral_list:TList = New TList Field x#,y#,z#,direction# Function Create(x#,y#,z#) Local temp:spiral= New spiral temp.x =x temp.y =y temp.z = z temp.direction = Rand(360) ' make the first rotation ListAddLast(spiral_list,temp) End Function Method Update() ' draw each point For Local j=0 To 35 'now we find the x and y of the point in question 'first circle of points Local x1#=plot_3D_x(x+Cos(j*10)*128,y+Sin(j*10)*128,z) Local x2#=plot_3D_x(x+Cos(j*10+10)*128,y+Sin(j*10+10)*128,z) Local y1#=plot_3D_Y(x+Cos(j*10)*128,y+Sin(j*10)*128,z) Local y2#=plot_3D_Y(x+Cos(j*10+10)*128,y+Sin(j*10+10)*128,z) SetColor 255,255,0 DrawLine(x1,y1,x2,y2) ' second circle Local x3#=plot_3D_x(x+Cos(j*10)*128,y+Sin(j*10)*128,z+.5) Local x4#=plot_3D_x(x+Cos(j*10+10)*128,y+Sin(j*10+10)*128,z+.5) Local y3#=plot_3D_Y(x+Cos(j*10)*128,y+Sin(j*10)*128,z+.5) Local y4#=plot_3D_Y(x+Cos(j*10+10)*128,y+Sin(j*10+10)*128,z+.5) SetColor 255,0,0 DrawLine(x3,y3,x4,y4) ' use the points of both circles together to make virtual sides SetColor 255,128,0 DrawLine(x1,y1,x3,y3) DrawLine(x2,y2,x3,y3) SetBlend LIGHTBLEND SetAlpha .5 Local points:Float[]=[x1,y1,x2,y2,x4,y4,x3,y3] DrawPoly(points) SetBlend SOLIDBLEND SetAlpha 1 Next End Method Method Destroy() ListRemove(spiral_list,Self) End Method EndType Type point Field x#,y#,z# EndType Function point_distance(x1#,y1#,x2#,y2#) ' get the x difference Local x_distance#= x1-x2 ' get the y difference Local y_distance#= y1-y2 ' find the difference using pythagroin therom Local distance#=sqr((x_distance*x_distance)+(y_distance*y_distance)) Return distance EndFunction Function point_direction#(x1#,y1#,x2#,y2#) Local Angle# = ATan2(y2-y1,x2-x1) If angle<0 angle:+ 360 End If Return angle EndFunction ' this plots one point Function plot_3D(x3#,y3#,z3#) Local direction#=point_direction(x3,y3,320,240) Local distance#= point_distance(x3,y3,320,240) Local new_x#=320+Cos(direction+180)*((distance/z3)) Local new_y#=240+Sin(direction+180)*((distance/z3)) Plot new_x,new_y End Function 'like the previous function except it finds the y coordinate Function plot_3D_Y#(x3#,y3#,z3#) Local direction#=point_direction(x3,y3,320,240) Local distance#= point_distance(x3,y3,320,240) Local new_y#=240+Sin(direction+180)*((distance/z3)) Return new_y End Function 'like the previous function except it finds the x coordinate Function plot_3D_x#(x3#,y3#,z3#) Local direction#=point_direction(x3,y3,320,240) Local distance#= point_distance(x3,y3,320,240) Local new_x#=320+Cos(direction+180)*((distance/z3)) Return new_x End Function Local angle=0 ' make a neat circle of varying z values For Local i=0 To 9 spiral.Create(320+Sin(i*36)*128,240+Cos(i*36)*128,Rand(3)) Next While not KeyDown(KEY_ESCAPE) Cls Plot 320,240 ' update our spirals For Local f:spiral =EachIn(spiral.spiral_list) f.Update() Next Flip Wend |
| ||
You need to implement z clipping of your polygons. Basically, when you start getting negative Z values, the maths you're using generates what's called a singularity right in the middle of the screen. As you move through your tubes, you would find a reflection of them converging to the center of the screen. There's no simple fix with your code. An approach I tried some time ago was to not draw any polygon with a negative z ordinate, and this solved the problem. It introduced other visual problems as polygons simply winked out of existance. My ultimate solution was to buy Andre LaMonth's Secrets of the 3D Game Programming Guru's and work through his polygon clipping code. Be warned: this is a massive book, and will take you some time to work through. If you're looking for an answer right now, have a look at the MiniB3D things that's floating around. I haven't tried it myself, but there's plenty of good things being said. Neil |