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 |

