Dark Bit Factory & Gravity

PROGRAMMING => General coding questions => Topic started by: Tetra on July 01, 2006

Title: 3D Software Engine - Clipping Polygons
Post by: Tetra on July 01, 2006
As some of you know there are a few 3d software engines about. I have also made one, which I have never used for anything.

Revisiting my old code I have decided to try again, but this time it will be for speed and not functionality.
The last hurdle of my engine was polygon clipping. I never understood how to do it, and from what I can gather there are a number of ways to do it.
But I have no Idea how to implement it correctly.

This is what I have:

The vertices of a polygon: Xa,Ya,Za,  Xb,Yb,Yz,  Xc,Yc,Zc
The TopLeft and BottomRight, Clipping Rect,  TLX,TLY, BRX,BRY

(http://www.tetrahedron.me.uk/polyclip.png)

What I think happens next is that each point is determined to be either inside or outside of each edge, then clipped or not clipped accordingly.
The first case, (Xa,Ya,Za)->(Xb,Yb,Zb) the line needs to be clipped twice, once against the right hand side (BRX,TLY)->(BRX,BRY), and the next against the bottom (TLX,BRY)->(BRX,BRY).
Secondly (Xb,Yb,Zb)->(Xc,Yc,Zc) gets clipped against (TLX,BRY)->(BRX,BRY).
Finally (Xc,Yc,Zc)->(Xa,Ya,Za) gets clipped against (TLX,TLY)->(BRX,TLY).

What I have found so far is just an equation for finding the point that two lines cross each other if they are not parallel. These lines are also infinate in length.

In code I have

Function Clip( x1,y1, x2,y2, x3,y3, x4,y4 )
   div = (x1-x2) * (y3-y4) - (y1-y2) * (x3-x4)
   If ( div < 0 ) Then
      xI = ( (x2-x1) * (x3 * y4 - x4 * y3) - (x4-x3) * (x1 * y2-x2 * y1) ) / ( div )
      yI = ( (y3-y4) * (x1 * y2 - x2 * y1) - (y1-y2) * (x3 * y4-x4 * y3) ) / ( div )
   endif
End Function

(xI,yI) is the intersection point of the two lines (x1,y1)->(x2,y2) and (x3,y3)->(x4,y4)

e.g the Third case where  (Xc,Yc,Zc)->(Xa,Ya,Za) gets clipped against (TLX,TLY)->(BRX,TLY) we would call

Clip(  Xc,Yc,  Xa,Ya, TLX,TLY,  BRX,TLY )

then xI,yI would be the point these lines intersect. But the problem with this is that there is too much overhead because its only the polygon edges that are moving, so for the line (TLX,TLY)->(BRX-TLY) there is no need to calulate yI because we know that this is a constant. Not only that but because the equation assumes infinate line length then the equation will return points that are beyond the boundries of the clip rect.

So then how do I implement a polyclip into my engine based on the above diagran and its information so that I can safely call my pollyfill function without causing problems with writing pixels outside of the screen buffer range?

Finally to expand on this, how do I then Clip it in the Z axis, i.e into the screen?

I would be most greatfull for any knid of information that can help me solve this problem.
 :cheers:
Title: Re: 3D Software Engine - Clipping Polygons
Post by: Jim on July 02, 2006
Sticking to 2d just for a second.

First work out which points are inside or outside the box.  Usually I do this by setting a 1 bit for each plane.
eg. bit 0 - set if point off to the left, bit1 - set if point off to the right etc
Then by examining pairs of points (edges) in your triangle you can see if it needs clipping or not.
If both sets of bits are 0 then both points are inside the box.
If both points have one of the bits set in the same position then the line is totally outside the box.
eg. if both have bit0 set then both points are off the the left.  You can do this using AND.

Once you've determined you have one point to one side of the box and one to the other (treat each side of the box in a different step, lets start with left edge).
You have A(xa,ya) and B(xb,yb) and the left edge of the box TLX.
The point where that line crosses the left edge is

x = tlx
y = ya + (yb-ya)*(xb-tlx)/(xb-xa)

You never have to worry about xb-xa being 0 because by testing if the points are in or out of the box you guarantee it as a non-zero value.
Once you've created the new point, you need to re-evaluate its clip bit flags.  Repeat this for all the planes.

Jim
Title: Re: 3D Software Engine - Clipping Polygons
Post by: Tetra on July 02, 2006
Hey Jim :)

Thanx for your reply.
I happened to be looking at your bb engine before I read you reply strangely enough. I only just realised the way you find the ratio value for the line equation was really simple.
I dont really understand the math but it works a treat.

And again thanx for eplaining the order to do things in. It actually makes sense to me now ;D

So to summarize, and make sure I got this right

Every point of the polygon needs to be checked if its inside or outside of the bounding box.
i.e. against every edge of the bounding box. Probably should note here that none of the bounding box sides are sloped, so each side can be described as a single value specific to the axis it is on.

From that you can determine whether an Edge needs to be clipped against a particular side or sides

e.g. point(Xa,Ya,Za) is above TLY. point(Xc,Yc,Zc) is inside the bounding box.
so Edge(Xc,Yc,Zc)->(Xa,Ya,Za) needs to be clipped along the top of the bounding box TLY.

Next you need to know the line equation, which is xy = xy1 + ( Ratio * ( xy2 - xy1 ) )
That returns to you a point along the line xy1->xy2 where a Ratio of 0.0 will return xy1, a Ratio of 0.5 will be half way and a Ratio of 1.0 will return xy2

Understanding that, in order to find the intersection point where an edge of the polygon crosses the side of the bounding box we need to determin what value Ratio is.
Back to the running example we need to find a new X position as Y = TLY.

so
Ratio = (TLY - Ya) / (Yc - Ya)Â  Â - I dont understand how that works but it does.

Finally
X = Xa + ( Ratio * ( Xc - Xa ) )

So now we got X and Y of the intersection.

This is good, because the Ratio value will come in handy to clip the UV texture values and even the gourad values.

e.g.
the texture cord for the Intersection point would be
U = Ua + ( Ratio * ( Uc - Ua ) )
V = Va + ( Ratio * ( Vc - Va ) )

I think thats it.

p.s. the Z of the intersection is also Z = Za + ( Ratio * ( Zc - Za ) )

p.p.s. what happens when everypoint is outside of the bounding box, and not only that but none of the edges intersect the sides of the bounding box?


  Â  Â  Â  /\
  Â  Â  /  Â  \
  Â  /  [ ]  Â \
  /_______\

[ ] - Bounding box

and

I dunno if i'm implementing it wrong, but it seems I need to do different checks for polygons that mite simply be rotated: -
(http://www.tetrahedron.me.uk/triop.png)
is that right? in which case that would mean that there is atleast 48 combinations to check  ???

 :cheers:
Title: Re: 3D Software Engine - Clipping Polygons
Post by: Jim on July 02, 2006
Quote
I only just realised the way you find the ratio value for the line equation was really simple.
I dont really understand the math but it works a treat.
If you make 2 right angled triangles out of the edge that crosses the plane, you will see it's just similar triangles - the ratio of the horizontal edges is the same as the ratio of the sloping edge you want to clip.
The entire width of the triangles is x2-x1 and the widths of the two are x2-tlx and tlx-x1, keeping the signs all the same.  The ratio is just the bit that's inside divided by the whole thing.  Â (Or the bit that's outside, it doesn't matter which end you start at).

Quote
p.p.s. what happens when everypoint is outside of the bounding box, and not only that but none of the edges intersect the sides of the bounding box?

  Â  Â  Â  A
  Â  Â  Â  /\
  Â  Â  /  Â  \
  Â  /  [ ]  Â \
  /_______\
BÂ  Â  Â  Â  Â  Â  Â  Â C
[ ] - Bounding box
It comes out in the wash.  First AB and CA will get clipped against the top, then the bottom till you have a trapezium shape, then what's left will get clipped against the left and right hand sides.  Exactly the order it gets cropped depends on which order you clip the planes, but the end result is always the same.

Quote
I dunno if i'm implementing it wrong, but it seems I need to do different checks for polygons that mite simply be rotated: -
This is why I keep my vertices in arrays.  In my code, I work my way round the edge of the triangle.  I have 2 buffers of vertices, the source polygon and the dest polygon (not triangles any more).
Start with the triangle and go round the edges clipping all those that need clipping against the first side of the box.  Then, using the output of that, clip all the new edges against the top of the box, and repeat, just swapping between the two arrays.  That's one way of doing it.  Alterntively you can do it recursively which is what I did in that blitz engine - every time you clip, create new triangles from what's left (a fan) and present each of them back to the triangle routine.  Only draw a triangle if there's no clipping.  This creates a lot of extra intermediate triangles, but it's easier to do in a language like blitz that doesn't have any pointers to speak of.

Jim
Title: Re: 3D Software Engine - Clipping Polygons
Post by: Tetra on July 02, 2006
Amazing ;D

Very much appreciate the help, I completely understand it now :) Its not as hard as I expected either.

:cheers: Jim
Title: Re: 3D Software Engine - Clipping Polygons
Post by: Shockwave on July 02, 2006
Nice one Jim, great explanation! :) Maybe Tetra will finish his 3D engine so we can all see it in action now :P
Title: Re: 3D Software Engine - Clipping Polygons
Post by: Tetra on July 02, 2006
;)
Title: Re: 3D Software Engine - Clipping Polygons
Post by: Tetra on July 17, 2006
Well I tried very hard to get the clipping to work and failed. I did manage to clip the polygons in some cases, but I failed to clip all cases or even come up with a method that didnt check each individual case.

But I have managed to clip the polygons a different way, on the polygon fill level. As far as I can tell I wont lose much, in terms of cpu cycles doing it this way. However this will be bad for polygons that are not partly inside the clipping rect, wasting some cycles. To counter that I do a lot of testing, This is where this method will probably cost more cycles, although its not too bad. The way I do it is to first test if all the points are within the clipping rectangle. Then, if that fails, I test each point of the clipping rect to see whether they are inside the polygon, if so then the polygon can be rendered.

Code: [Select]
Function clipPolygonCheck( polygonIndex% )

Local xA : Local yA : Local zA
Local xB : Local yB : Local zB
Local xC : Local yC : Local zC

Local x1 : Local y1 : Local z1
Local x2 : Local y2 : Local z2

Local ta1 : Local ta2 : Local ta3 : Local ta4

Local colA : Local colB : Local colC

Local rA : Local gA : Local bA
Local rB : Local gB : Local bB
Local rC : Local gC : Local bC

Local pA = PeekInt( PolygonsA, polygonIndex% )
Local pB = PeekInt( PolygonsB, polygonIndex% )
Local pC = PeekInt( PolygonsC, polygonIndex% )


Local Ap%
Local Bp%
Local Cp%

zA = PeekFloat( RotatedVerticesZ, pA )
zB = PeekFloat( RotatedVerticesZ, pB )
zC = PeekFloat( RotatedVerticesZ, pC )

  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  ; this is adequate for my purpose
If ( zA > gfx_clip_zMin )Or( zB > gfx_clip_zMin )Or( zC > gfx_clip_zMin ) Then Return False

xA = PeekFloat( RotatedVerticesX, pA )
yA = PeekFloat( RotatedVerticesY, pA )

xB = PeekFloat( RotatedVerticesX, pB )
yB = PeekFloat( RotatedVerticesY, pB )

xC = PeekFloat( RotatedVerticesX, pC )
yC = PeekFloat( RotatedVerticesY, pC )

; for the purpose of the zbuffer
zA = (zA * 256.0) + 90000000
zB = (zB * 256.0) + 90000000
zC = (zC * 256.0) + 90000000

colA = VertexLight#( pA )
colB = VertexLight#( pB )
colC = VertexLight#( pC )

rA = colA
gA = colA
bA = colA

rB = colB
gB = colB
bB = colB

rC = colC
gC = colC
bC = colC

ta1 = TriangleArea( xA,yA, xB,yB, xC,yC )

; does the polygon face the camera?
If ( ta1 < 0 )

If ( xA < gfx_clip_xMin ) Then Ap% = Ap% + $01
If ( yA < gfx_clip_yMin ) Then Ap% = Ap% + $02

If ( xA > gfx_clip_xMax ) Then Ap% = Ap% + $04
If ( yA > gfx_clip_yMax ) Then Ap% = Ap% + $08

If ( xB < gfx_clip_xMin ) Then Bp% = Bp% + $01
If ( yB < gfx_clip_yMin ) Then Bp% = Bp% + $02

If ( xB > gfx_clip_xMax ) Then Bp% = Bp% + $04
If ( yB > gfx_clip_yMax ) Then Bp% = Bp% + $08

If ( xC < gfx_clip_xMin ) Then Cp% = Cp% + $01
If ( yC < gfx_clip_yMin ) Then Cp% = Cp% + $02

If ( xC > gfx_clip_xMax ) Then Cp% = Cp% + $04
If ( yC > gfx_clip_yMax ) Then Cp% = Cp% + $08


If (( Ap% + Bp% + Cp% ) = 0 )
polyFillGourad( xA,yA,zA, xB,yB,zB, xC,yC,zC, rA,gA,bA, rB,gB,bB, rC,gC,bC )
Return True
EndIf

If PointInTriangle( xA,yA, xB,yB, xC,yC ,gfx_clip_xMin,gfx_clip_yMin, ta1 )

polyFillGourad( xA,yA,zA, xB,yB,zB, xC,yC,zC, rA,gA,bA, rB,gB,bB, rC,gC,bC )
Return True

ElseIf PointInTriangle( xA,yA, xB,yB, xC,yC ,gfx_clip_xMax,gfx_clip_yMin, ta1 )

polyFillGourad( xA,yA,zA, xB,yB,zB, xC,yC,zC, rA,gA,bA, rB,gB,bB, rC,gC,bC )
Return True

ElseIf PointInTriangle( xA,yA, xB,yB, xC,yC ,gfx_clip_xMax,gfx_clip_yMax, ta1 )

polyFillGourad( xA,yA,zA, xB,yB,zB, xC,yC,zC, rA,gA,bA, rB,gB,bB, rC,gC,bC )
Return True

ElseIf PointInTriangle( xA,yA, xB,yB, xC,yC ,gfx_clip_xMin,gfx_clip_yMax, ta1 )

polyFillGourad( xA,yA,zA, xB,yB,zB, xC,yC,zC, rA,gA,bA, rB,gB,bB, rC,gC,bC )
Return True

EndIf
EndIf

Return False
End Function

Function TriangleArea( xA,yA, xB,yB, xC,yC )
Return ((xA - xB)*(yC - yB)) - ((yA - yB)*(xC - xB))
End Function

Function PointInTriangle( xA,yA, xB,yB, xC,yC ,xP,yP, a1 )

Local a2
Local a3
Local a4

a2 = TriangleArea( xA,yA, xB,yB, xP,yP )
a3 = TriangleArea( xB,yB, xC,yC, xP,yP )
a4 = TriangleArea( xC,yC, xA,yA, xP,yP )

If ( a2 + a3 + a4 ) > a1 Then
Return False
Else
Return True
EndIf
End Function




;-----------------------------------------------------------
;Â  Â  Â  Â  Â  -==<Â  No Texture, just Color with Z-Buffer >==-
;-----------------------------------------------------------
Function polyFillGourad( vAx,vAy,vAz, vBx,vBy,vBz, vCx,vCy,vCz, rA,gA,bA, rB,gB,bB, rC,gC,bCÂ  )

Local yMin
Local yMax

Local xMin
Local xMax

Local zMin
Local zMax

Local xLen

Local r
Local g
Local b

Local rRat#
Local gRat#
Local bRat#

Local x
Local y
Local yOffset

Local zRat#
Local zBufferOffset
Local gfx_width4y
Local xDiff

polyFillEdgeGourad( vAx,vAy,vAz, vBx,vBy,vBz,  rA,gA,bA, rB,gB,bB )
polyFillEdgeGourad( vBx,vBy,vBz, vCx,vCy,vCz,  rB,gB,bB, rC,gC,bC )
polyFillEdgeGourad( vCx,vCy,vCz, vAx,vAy,vAz,  rC,gC,bC, rA,gA,bA )

yMin = vAy
If (vBy < yMin) Then yMin = vBy
If (vCy < yMin) Then yMin = vCy
If ( yMin < gfx_clip_yMin ) Then yMin = gfx_clip_yMin

yMax = vAy
If (vBy > yMax) Then yMax = vBy
If (vCy > yMax) Then yMax = vCy
If ( yMax >= gfx_clip_yMax ) Then yMax = gfx_clip_yMax - 1

For y = yMin To yMax

xMin = xPos(y, 0)
xMax = xPos(y, 1)


If ( xMin < xMax ) ; Stop divide by zero

xLen = xMax - xMin

zMin = zPos(y, 0)
zMax = zPos(y, 1)
zRat = ( zMax - zMin ) / xLen

r = rCol( y, 0 )
g = gCol( y, 0 )
b = bCol( y, 0 )

rRat = ( rCol( y, 1 ) - r ) / xLen
gRat = ( gCol( y, 1 ) - g ) / xLen
bRat = ( bCol( y, 1 ) - b ) / xLen

; Clip left side if needed
If ( xMin < gfx_clip_xMin )

xDiff = gfx_clip_xMin - xMin
xMin = gfx_clip_xMin

r = r + ( rRat * xDiff )
g = g + ( gRat * xDiff )
b = b + ( bRat * xDiff )

zMin = zMin + ( zRat * xDiff )
EndIf

; Clip right side if needed
If ( xMax >= gfx_clip_xMax )
xMax = gfx_clip_xMax - 1
EndIf

gfx_width4y = gfx_width4 * y

For x = xMin To xMax

zBufferOffset = gfx_width4y + ( x Shl 2 )

If ( zMin > PeekInt( z_Buffer, zBufferOffset ) )
PokeInt( z_Buffer, zBufferOffset, zMin )
WritePixelFast x ,y, (r Shl 8 And $FF0000) + (g And $00FF00) + ((b Shr 8) And $0000FF)
EndIf

r = r + rRat
g = g + gRat
b = b + bRat

zMin = zMin + zRat
Next
EndIf
Next

End Function

Function polyFillEdgeGourad( vAx,vAy,vAz, vBx,vBy,vBz, rAc,gAc,bAc, rBc,gBc,bBc )

Local xA
Local yA
Local zA

Local xB
Local yB
Local zB

Local xRat
Local zRat

Local rRat
Local gRat
Local bRat

Local rA
Local gA
Local bA

Local rB
Local gB
Local bB

Local swap

Local yLen

Local yDiff

If ( vAy < vBy )
xA = vAx Shl 8
yA = vAy
zA = vAz

xB = vBx Shl 8
yB = vBy
zB = vBz

rA = rAc Shl 8
gA = gAc Shl 8
bA = bAc Shl 8

rB = rBc Shl 8
gB = gBc Shl 8
bB = bBc Shl 8

swap = True
Else
xA = vBx Shl 8
yA = vBy
zA = vBz

xB = vAx Shl 8
yB = vAy
zB = vAz

rA = rBc Shl 8
gA = gBc Shl 8
bA = bBc Shl 8

rB = rAc Shl 8
gB = gAc Shl 8
bB = bAc Shl 8

swap = False
EndIf


If (yA < yB) Then
yLen = (yB-yA)

xRat = (xB-xA) / yLen
rRat = (rB-rA) / yLen
gRat = (gB-gA) / yLen
bRat = (bB-bA) / yLen
zRat = (zB-zA) / yLen

; Clip top side if needed
If ( yA < gfx_clip_yMin )
yDiff = gfx_clip_yMin - yA
yA = gfx_clip_yMin

xA = xA + ( xRat * yDiff )
zA = zA + ( zRat * yDiff )

rA = rA + ( rRat * yDiff )
gA = gA + ( gRat * yDiff )
bA = bA + ( bRat * yDiff )
EndIf

;clip bottom side if needed
If ( yB >= gfx_clip_yMax )
yB = gfx_clip_yMax - 1
EndIf

For y = yA To yB

xPos(y, swap) = xA Sar 8
zPos(y, swap) = zA

rCol(y, swap) = rA
gCol(y, swap) = gA
bCol(y, swap) = bA

xA = xA + xRat
zA = zA + zRat

rA = rA + rRat
gA = gA + gRat
bA = bA + bRat
Next

EndIf

End Function
Title: Re: 3D Software Engine - Clipping Polygons
Post by: Jim on July 17, 2006
Quote
Well I tried very hard to get the clipping to work and failed. I did manage to clip the polygons in some cases, but I failed to clip all cases or even come up with a method that didnt check each individual case.
That's a real shame. :(  Are you still keen on fixing it up?  Those clip-checks inside the triangle loops are far more expensive than you think.

One thing I do when I'm writing a clipper is to shrink the clip window to be far smaller than the screen, say 160x100, then enable the clipping for one plane only at a time, making sure that first one plane, then pairs/threes of planes are working.  Then it doesn't matter too much if it splatters off over the sides and you can see where the errors are.  I also deliberately constuct triangles that clip one 1,2,3,4 planes and watch them as they go through - it's a bit tricky without a debugger though.  You really want to work out the results on paper and then check that the code does the same thing.

Jim
Title: Re: 3D Software Engine - Clipping Polygons
Post by: Tetra on July 18, 2006
Yes I am, i would like to do it properly :)

Problem is, I know what I need to do, but i'm not sure how to make it. Every attempt so far has ended up with hundreds of lines of code, which I know there is a more finite way of writing.
This was my most recent attempt, but I could see that it was becoming quite a lot.

I will try what you said by attacking one side at a time, maybe I will have better luck that way.

Code: [Select]
Function clipPolygonCheck( polygonIndex% )

Local xA
Local yA
Local zA

Local xB
Local yB
Local zB

Local xC
Local yC
Local zC

Local x1
Local y1
Local z1

Local x2
Local y2
Local z2

Local x3
Local y3
Local z3

Local colA
Local colB
Local colC

Local rA
Local gA
Local bA

Local rB
Local gB
Local bB

Local rC
Local gC
Local bC



Local pA = PeekInt( PolygonsA, polygonIndex% )
Local pB = PeekInt( PolygonsB, polygonIndex% )
Local pC = PeekInt( PolygonsC, polygonIndex% )

Local Ratio#

Local Ap%
Local Bp%
Local Cp%

Local FlagA

xA = PeekFloat( RotatedVerticesX, pA )
yA = PeekFloat( RotatedVerticesY, pA )
zA = PeekFloat( RotatedVerticesZ, pA )

xB = PeekFloat( RotatedVerticesX, pB )
yB = PeekFloat( RotatedVerticesY, pB )
zB = PeekFloat( RotatedVerticesZ, pB )

xC = PeekFloat( RotatedVerticesX, pC )
yC = PeekFloat( RotatedVerticesY, pC )
zC = PeekFloat( RotatedVerticesZ, pC )

If ( zA > 0 )And( zB > 0 )And( zC > 0 ) Then Return False



;Â  Â  Â  Â  Â  Â  |Â  Â  Â  Â  Â |
;Â  Â  Â  Â  $03 |Â  Â $02Â  Â | $06
;Â  Â  Â  Â -----|---------|-----
;Â  Â  Â  Â  Â  Â  |Â  Â  Â  Â  Â |
;Â  Â  Â  Â  $01 |Â  Screen | $04
;  Â  Â  Â  Â  Â  |  Â Area  |
;Â  Â  Â  Â -----|---------|-----
;Â  Â  Â  Â  $09 |Â  Â $08Â  Â | $0C
;Â  Â  Â  Â  Â  Â  |Â  Â  Â  Â  Â |

If ( xA < gfx_clip_xMin ) Then Ap% = Ap% + $01
If ( yA < gfx_clip_yMin ) Then Ap% = Ap% + $02

If ( xA > gfx_clip_xMax ) Then Ap% = Ap% + $04
If ( yA > gfx_clip_yMax ) Then Ap% = Ap% + $08

If ( xB < gfx_clip_xMin ) Then Bp% = Bp% + $01
If ( yB < gfx_clip_yMin ) Then Bp% = Bp% + $02

If ( xB > gfx_clip_xMax ) Then Bp% = Bp% + $04
If ( yB > gfx_clip_yMax ) Then Bp% = Bp% + $08

If ( xC < gfx_clip_xMin ) Then Cp% = Cp% + $01
If ( yC < gfx_clip_yMin ) Then Cp% = Cp% + $02

If ( xC > gfx_clip_xMax ) Then Cp% = Cp% + $04
If ( yC > gfx_clip_yMax ) Then Cp% = Cp% + $08

zA = (zA * 256.0) + 50000000
zB = (zB * 256.0) + 50000000
zC = (zC * 256.0) + 50000000

rA = 255
gB = 255
bC = 255



; Polygon does not need clipping
If ( Ap = 0 )And( Bp = 0 )And( Cp = 0 )
polyFillGourad( xA,yA,zA, xB,yB,zB, xC,yC,zC, rA,gA,bA, rB,gB,bB, rC,gC,bC )
Return True
EndIf

; Left Clip
If ( Ap = $01 )

If ( Bp = $00 )And( Cp = $00 ) Then FlagA = 1
If ( Bp = $01 )And( Cp = $00 ) Then FlagA = 3
If ( FlagA > 0 ) Return clipPolygonRender( xA,yA,zA, xB,yB,zB, xC,yC,zC, rA,gA,bA, rB,gB,bB, rC,gC,bC, FlagA,1 )
EndIf

If ( Bp = $01 )
If ( Cp = $00 )And( Ap = $00 ) Then FlagA = 1
If ( Cp = $01 )And( Ap = $00 ) Then FlagA = 3
If ( FlagA > 0 ) Return clipPolygonRender( xB,yB,zB, xC,yC,zC, xA,yA,zA, rB,gB,bB, rC,gC,bC, rA,gA,bA, FlagA,1 )
EndIf

If ( Cp = $01 )
If KeyDown(57) Then Stop
If ( Ap = $00 )And( Bp = $00 ) Then FlagA = 1
If ( Ap = $01 )And( Bp = $00 ) Then FlagA = 3
If ( FlagA > 0 ) Return clipPolygonRender( xC,yC,zC, xA,yA,zA, xB,yB,zB, rC,gC,bC, rA,gA,bA, rB,gB,bB, FlagA,1 )
EndIf


;Right Clip
If ( Ap = $04 )Or( Bp = $04 )Or( Cp = $04 )

If ( Bp = 0 )And( Cp = 0 ) Return clipPolygonRender( xA,yA,zA, xB,yB,zB, xC,yC,zC, rA,gA,bA, rB,gB,bB, rC,gC,bC, 1,2 )
If ( Ap = 0 )And( Cp = 0 ) Return clipPolygonRender( xB,yB,zB, xC,yC,zC, xA,yA,zA, rB,gB,bB, rC,gC,bC, rA,gA,bA, 1,2 )
If ( Ap = 0 )And( Bp = 0 ) Return clipPolygonRender( xC,yC,zC, xA,yA,zA, xB,yB,zB, rC,gC,bC, rA,gA,bA, rB,gB,bB, 1,2 )

;Top Clip
ElseIf ( Ap = $02 )Or( Bp = $02 )Or( Cp = $02 )

If ( Bp = 0 )And( Cp = 0 ) Return clipPolygonRender( xA,yA,zA, xB,yB,zB, xC,yC,zC, rA,gA,bA, rB,gB,bB, rC,gC,bC, 2,1 )
If ( Ap = 0 )And( Cp = 0 ) Return clipPolygonRender( xB,yB,zB, xC,yC,zC, xA,yA,zA, rB,gB,bB, rC,gC,bC, rA,gA,bA, 2,1 )
If ( Ap = 0 )And( Bp = 0 ) Return clipPolygonRender( xC,yC,zC, xA,yA,zA, xB,yB,zB, rC,gC,bC, rA,gA,bA, rB,gB,bB, 2,1 )

;Bottom Clip
ElseIf ( Ap = $08 )Or( Bp = $08 )Or( Cp = $08 )

If ( Bp = 0 )And( Cp = 0 ) Return clipPolygonRender( xA,yA,zA, xB,yB,zB, xC,yC,zC, rA,gA,bA, rB,gB,bB, rC,gC,bC, 2,2 )
If ( Ap = 0 )And( Cp = 0 ) Return clipPolygonRender( xB,yB,zB, xC,yC,zC, xA,yA,zA, rB,gB,bB, rC,gC,bC, rA,gA,bA, 2,2 )
If ( Ap = 0 )And( Bp = 0 ) Return clipPolygonRender( xC,yC,zC, xA,yA,zA, xB,yB,zB, rC,gC,bC, rA,gA,bA, rB,gB,bB, 2,2 )
EndIf

;if the prog gets this far then a polygon has not been rendered
Return False

End Function


Function clipPolygonRender( xA,yA,zA, xB,yB,zB, xC,yC,zC, rA,gA,bA, rB,gB,bB, rC,gC,bC, FlagA, FlagBÂ  )
Local ratio#

Local xR
Local yR
Local zR

Local x1
Local y1
Local z1

Local x2
Local y2
Local z2

Local x3
Local y3
Local z3

Local r1
Local g1
Local b1

Local r2
Local g2
Local b2

Select FlagA
Case 1
Select FlagB
Case 1 xR = gfx_clip_xMin
Case 2 xR = gfx_clip_xMax
End Select

Ratio# = ClipRatio( xR, xA, xB )
y1 = yA + ( Ratio# * (yB - yA) )
z1 = zA + ( Ratio# * (zB - zA) )

r1 = rA + ( Ratio# * (rB - rA) )
g1 = gA + ( Ratio# * (gB - gA) )
b1 = bA + ( Ratio# * (bB - bA) )

Ratio# = ClipRatio( xR, xC, xA )
y2 = yC + ( Ratio# * (yA - yC) )
z2 = zC + ( Ratio# * (zA - zC) )
r2 = rC + ( Ratio# * (rA - rC) )

g2 = gC + ( Ratio# * (gA - gC) )
b2 = bC + ( Ratio# * (bA - bC) )

polyFillGourad( xR,y1,z1, xB,yB,zB, xC,yC,zC, r1,g1,b1, rB,gB,bB, rC,gC,bC )
polyFillGourad( xR,y1,z1, xC,yC,zC, xR,y2,z2, r1,g1,b1, rC,gC,bC, r2,g2,b2 )
Return True

Case 3
Select FlagB
Case 1 xR = gfx_clip_xMin
Case 2 xR = gfx_clip_xMax
End Select

Ratio# = ClipRatio( xR, xA, xC )
y1 = yA + ( Ratio# * (yC - yA) )
z1 = zA + ( Ratio# * (zC - zA) )

r1 = rA + ( Ratio# * (rC - rA) )
g1 = gA + ( Ratio# * (gC - gA) )
b1 = bA + ( Ratio# * (bC - bA) )

Ratio# = ClipRatio( xR, xB, xC )
y2 = yB + ( Ratio# * (yC - yB) )
z2 = zB + ( Ratio# * (zC - zB) )
r2 = rB + ( Ratio# * (rC - rB) )

g2 = gB + ( Ratio# * (gC - gB) )
b2 = bB + ( Ratio# * (bC - bB) )

polyFillGourad( xR,y1,z1, xR,y2,z2, xC,yC,zC, r1,g1,b1, r2,g2,b2, rC,gC,bC )
Return True

Case 2
Select FlagB
Case 1 yR = gfx_clip_yMin
Case 2 yR = gfx_clip_yMax
End Select

Ratio# = ClipRatio( yR, yA, yB )
x1 = xA + ( Ratio# * (xB - xA) )
z1 = zA + ( Ratio# * (zB - zA) )

r1 = rA + ( Ratio# * (rB - rA) )
g1 = gA + ( Ratio# * (gB - gA) )
b1 = bA + ( Ratio# * (bB - bA) )

Ratio# = ClipRatio( yR, yC, yA )
x2 = xC + ( Ratio# * (xA - xC) )
z2 = zC + ( Ratio# * (zA - zC) )

r2 = rC + ( Ratio# * (rA - rC) )
g2 = gC + ( Ratio# * (gA - gC) )
b2 = bC + ( Ratio# * (bA - bC) )

polyFillGourad( x1,yR,z1, xB,yB,zB, xC,yC,zC, r1,g1,b1, rB,gB,bB, rC,gC,bC )
polyFillGourad( x1,yR,z1, xC,yC,zC, x2,yR,z2, r1,g1,b1, rC,gC,bC, r2,g2,b2 )
Return True


End Select

End Function
Title: Re: 3D Software Engine - Clipping Polygons
Post by: Jim on July 18, 2006
I think that's really close.  Really, really close.  Your code at the moment looks like it should clip against one plane at a time.  All you need to change is in clipPolygonRender, instead of calling polyFillGourad, you need to call back in to clipPolygonCheck (a recursive call) to get it to clip against the remaining planes.  All that needs is a bit of work to get around the parameters being different.  Once all the planes are clipped it will eventually drop out through the "; Polygon does not need clipping" case, or it'll drop off the end as being totally clipped off.

Jim
Title: Re: 3D Software Engine - Clipping Polygons
Post by: relsoft on July 18, 2006
You use te sutherland-cohen clip to fix you probs and add triangles if there are more than 2 intersections.
Title: Re: 3D Software Engine - Clipping Polygons
Post by: Tetra on July 19, 2006
 :|| :|| :|| :|| :|| :|| :|| :||

Yey I done it.

Thanx very much Jim, I never actually realized that you could simply pass the polygon through the same function. It makes far more sense now, and I dont need to make a case for special cases.

What I failed to realize is that basically each side of the clip rect is infact infinate in length. In addition to that, there is only two posible position for the polygons vertices that actually need clipping. One vertice one side and the other two on the oppersite side, or visaversa, ignoring the polygons orientation that is.

(http://www.tetrahedron.me.uk/clipping.png)

Then its just a simple case of clipping those two cases, After re-orientating the polygon to account for it to be rotated.

Code: [Select]
Function clipPolygonCheck( xA,yA,zA, xB,yB,zB, xC,yC,zC, rA,gA,bA, rB,gB,bB, rC,gC,bC )


;Â  Â  Â |Â  Â  Â  Â  Â |
; $03 |Â  Â $02Â  Â | $06
;-----|---------|-----
;Â  Â  Â |Â  Â  Â  Â  Â |
; $01 |Â  Screen | $04
;  Â  Â |  Â Area  |
;-----|---------|-----
; $09 |Â  Â $08Â  Â | $0C
;Â  Â  Â |Â  Â  Â  Â  Â |

If ( xA < gfx_clip_xMin ) Then Ap% = Ap% + $01
If ( yA < gfx_clip_yMin ) Then Ap% = Ap% + $02

If ( xA > gfx_clip_xMax ) Then Ap% = Ap% + $04
If ( yA > gfx_clip_yMax ) Then Ap% = Ap% + $08

If ( xB < gfx_clip_xMin ) Then Bp% = Bp% + $01
If ( yB < gfx_clip_yMin ) Then Bp% = Bp% + $02

If ( xB > gfx_clip_xMax ) Then Bp% = Bp% + $04
If ( yB > gfx_clip_yMax ) Then Bp% = Bp% + $08

If ( xC < gfx_clip_xMin ) Then Cp% = Cp% + $01
If ( yC < gfx_clip_yMin ) Then Cp% = Cp% + $02

If ( xC > gfx_clip_xMax ) Then Cp% = Cp% + $04
If ( yC > gfx_clip_yMax ) Then Cp% = Cp% + $08


; Polygon does not need clipping
If ( Ap = 0 )And( Bp = 0 )And( Cp = 0 )

zA = (zA * 256.0) + 50000000
zB = (zB * 256.0) + 50000000
zC = (zC * 256.0) + 50000000

polyFillGourad( xA,yA,zA, xB,yB,zB, xC,yC,zC, rA,gA,bA, rB,gB,bB, rC,gC,bC )
EndIf

;Â  Â  Â |
; $03 |
;-----|
;Â  Â  Â |
; $01 |
;Â  Â  Â |
;-----|
; $09 |
;Â  Â  Â |
; Left Clip
If ( Ap = $03 )Or( Ap = $01 )Or( Ap = $09 )

If ( Bp <> $03 )And( Bp <> $01 )And( Bp <> $09 )
If ( Cp = $03 )Or( Cp = $01 )Or( Cp = $09 )
clipPolygonRender( xA,yA,zA, xB,yB,zB, xC,yC,zC, rA,gA,bA, rB,gB,bB, rC,gC,bC, 3,1 ) : Return True
ElseIf ( Cp <> $03 )And( Cp <> $01 )And( Cp <> $09 )
clipPolygonRender( xA,yA,zA, xB,yB,zB, xC,yC,zC, rA,gA,bA, rB,gB,bB, rC,gC,bC, 1,1 ) : Return True
EndIf
EndIf
EndIf

If ( Cp = $03 )Or( Cp = $01 )Or( Cp = $09 )

If ( Ap <> $03 )And( Ap <> $01 )And( Ap <> $09 )
If ( Bp = $03 )Or( Bp = $01 )Or( Bp = $09 )
clipPolygonRender( xC,yC,zC, xA,yA,zA, xB,yB,zB, rC,gC,bC, rA,gA,bA, rB,gB,bB, 3,1 ) : Return True
ElseIf ( Bp <> $03 )And( Bp <> $01 )And( Bp <> $09 )
clipPolygonRender( xC,yC,zC, xA,yA,zA, xB,yB,zB, rC,gC,bC, rA,gA,bA, rB,gB,bB, 1,1 ) : Return True
EndIf
EndIf
EndIf

If ( Bp = $03 )Or( Bp = $01 )Or( Bp = $09 )

If ( Cp <> $03 )And( Cp <> $01 )And( Cp <> $09 )
If ( Ap = $03 )Or( Ap = $01 )Or( Ap = $09 )
clipPolygonRender( xB,yB,zB, xC,yC,zC, xA,yA,zA, rB,gB,bB, rC,gC,bC, rA,gA,bA, 3,1 ) : Return True
ElseIf ( Ap <> $03 )And( Ap <> $01 )And( Ap <> $09 )
clipPolygonRender( xB,yB,zB, xC,yC,zC, xA,yA,zA, rB,gB,bB, rC,gC,bC, rA,gA,bA, 1,1 ) : Return True
EndIf
EndIf

EndIf


;Â  Â  Â |Â  Â  Â  Â  Â |
; $03 |Â  Â $02Â  Â | $06
;-----|---------|-----
;Top Clip
If ( Ap = $03 )Or( Ap = $02 )Or( Ap = $06 )

If ( Cp <> $03 )And( Cp <> $02 )And( Cp <> $06 )
If ( Bp = $03 )Or( Bp = $02 )Or( Bp = $06 )
clipPolygonRender( xA,yA,zA, xB,yB,zB, xC,yC,zC, rA,gA,bA, rB,gB,bB, rC,gC,bC, 4,1 ) : Return True
ElseIf ( Bp <> $03 )And( Bp <> $02 )And( Bp <> $06 )
clipPolygonRender( xA,yA,zA, xB,yB,zB, xC,yC,zC, rA,gA,bA, rB,gB,bB, rC,gC,bC, 2,1 ) : Return True
EndIf
EndIf
EndIf

If ( Bp = $03 )Or( Bp = $02 )Or( Bp = $06 )

If ( Ap <> $03 )And( Ap <> $02 )And( Ap <> $06 )
If ( Cp = $03 )Or( Cp = $02 )Or( Cp = $06 )
clipPolygonRender( xB,yB,zB, xC,yC,zC, xA,yA,zA, rB,gB,bB, rC,gC,bC, rA,gA,bA, 4,1 ) : Return True
ElseIf ( Cp <> $03 )And( Cp <> $02 )And( Cp <> $06 )
clipPolygonRender( xB,yB,zB, xC,yC,zC, xA,yA,zA, rB,gB,bB, rC,gC,bC, rA,gA,bA, 2,1 ) : Return True
EndIf
EndIf

EndIf

If ( Cp = $03 )Or( Cp = $02 )Or( Cp = $06 )

If ( Bp <> $03 )And( Bp <> $02 )And( Bp <> $06 )
If ( Ap = $03 )Or( Ap = $02 )Or( Ap = $06 )
clipPolygonRender( xC,yC,zC, xA,yA,zA, xB,yB,zB, rC,gC,bC, rA,gA,bA, rB,gB,bB, 4,1 ) : Return True
ElseIf ( Ap <> $03 )And( Ap <> $02 )And( Ap <> $06 )
clipPolygonRender( xC,yC,zC, xA,yA,zA, xB,yB,zB, rC,gC,bC, rA,gA,bA, rB,gB,bB, 2,1 ) : Return True
EndIf
EndIf
EndIf


;|
;| $06
;|-----
;|
;| $04
;|
;|-----
;| $0C
;|
;Right Clip
If ( Ap = $06 )Or( Ap = $04 )Or( Ap = $0C )

If ( Bp <> $06 )And( Bp <> $04 )And( Bp <> $0C )
If ( Cp = $06 )Or( Cp = $04 )Or( Cp = $0C )
clipPolygonRender( xA,yA,zA, xB,yB,zB, xC,yC,zC, rA,gA,bA, rB,gB,bB, rC,gC,bC, 3,2 ) : Return True
ElseIf ( Cp <> $06 )And( Cp <> $04 )And( Cp <> $0C )
clipPolygonRender( xA,yA,zA, xB,yB,zB, xC,yC,zC, rA,gA,bA, rB,gB,bB, rC,gC,bC, 1,2 ) : Return True
EndIf
EndIf
EndIf

If ( Cp = $06 )Or( Cp = $04 )Or( Cp = $0C )

If ( Ap <> $06 )And( Ap <> $04 )And( Ap <> $0C )
If ( Bp = $06 )Or( Bp = $04 )Or( Bp = $0C )
clipPolygonRender( xC,yC,zC, xA,yA,zA, xB,yB,zB, rC,gC,bC, rA,gA,bA, rB,gB,bB, 3,2 ) : Return True
ElseIf ( Bp <> $06 )And( Bp <> $04 )And( Bp <> $0C )
clipPolygonRender( xC,yC,zC, xA,yA,zA, xB,yB,zB, rC,gC,bC, rA,gA,bA, rB,gB,bB, 1,2 ) : Return True
EndIf
EndIf
EndIf

If ( Bp = $06 )Or( Bp = $04 )Or( Bp = $0C )

If ( Cp <> $06 )And( Cp <> $04 )And( Cp <> $0C )
If ( Ap = $06 )Or( Ap = $04 )Or( Ap = $0C )
clipPolygonRender( xB,yB,zB, xC,yC,zC, xA,yA,zA, rB,gB,bB, rC,gC,bC, rA,gA,bA, 3,2 ) : Return True
ElseIf ( Ap <> $06 )And( Ap <> $04 )And( Ap <> $0C )
clipPolygonRender( xB,yB,zB, xC,yC,zC, xA,yA,zA, rB,gB,bB, rC,gC,bC, rA,gA,bA, 1,2 ) : Return True
EndIf
EndIf

EndIf



;-----|---------|-----
; $09 |Â  Â $08Â  Â | $0C
;Â  Â  Â |Â  Â  Â  Â  Â |
;Bottom Clip
If ( Ap = $09 )Or( Ap = $08 )Or( Ap = $0C )

If ( Cp <> $09 )And( Cp <> $08 )And( Cp <> $0C )
If ( Bp = $09 )Or( Bp = $08 )Or( Bp = $0C )
clipPolygonRender( xA,yA,zA, xB,yB,zB, xC,yC,zC, rA,gA,bA, rB,gB,bB, rC,gC,bC, 4,2 ) : Return True
ElseIf ( Bp <> $09 )And( Bp <> $08 )And( Bp <> $0C )
clipPolygonRender( xA,yA,zA, xB,yB,zB, xC,yC,zC, rA,gA,bA, rB,gB,bB, rC,gC,bC, 2,2 ) : Return True
EndIf
EndIf
EndIf

If ( Bp = $09 )Or( Bp = $08 )Or( Bp = $0C )

If ( Ap <> $09 )And( Ap <> $08 )And( Ap <> $0C )
If ( Cp = $09 )Or( Cp = $08 )Or( Cp = $0C )
clipPolygonRender( xB,yB,zB, xC,yC,zC, xA,yA,zA, rB,gB,bB, rC,gC,bC, rA,gA,bA, 4,2 ) : Return True
ElseIf ( Cp <> $09 )And( Cp <> $08 )And( Cp <> $0C )
clipPolygonRender( xB,yB,zB, xC,yC,zC, xA,yA,zA, rB,gB,bB, rC,gC,bC, rA,gA,bA, 2,2 ) : Return True
EndIf
EndIf

EndIf

If ( Cp = $09 )Or( Cp = $08 )Or( Cp = $0C )

If ( Bp <> $09 )And( Bp <> $08 )And( Bp <> $0C )
If ( Ap = $09 )Or( Ap = $08 )Or( Ap = $0C )
clipPolygonRender( xC,yC,zC, xA,yA,zA, xB,yB,zB, rC,gC,bC, rA,gA,bA, rB,gB,bB, 4,2 ) : Return True
ElseIf ( Ap <> $09 )And( Ap <> $08 )And( Ap <> $0C )
clipPolygonRender( xC,yC,zC, xA,yA,zA, xB,yB,zB, rC,gC,bC, rA,gA,bA, rB,gB,bB, 2,2 ) : Return True
EndIf
EndIf
EndIf

End Function


Function clipPolygonRender( xA,yA,zA, xB,yB,zB, xC,yC,zC, rA,gA,bA, rB,gB,bB, rC,gC,bC, FlagA, FlagBÂ  )

Local ratio#

Local xR : Local yR : Local zR
Local x1 : Local y1 : Local z1
Local x2 : Local y2 : Local z2
Local x3 : Local y3 : Local z3
Local r1 : Local g1 : Local b1
Local r2 : Local g2 : Local b2

Select FlagA
Case 1
Select FlagB
Case 1 xR = gfx_clip_xMin
Case 2 xR = gfx_clip_xMax
End Select

Ratio# = ClipRatio( xR, xA, xB )
y1 = yA + ( Ratio# * (yB - yA) )
z1 = zA + ( Ratio# * (zB - zA) )

r1 = rA + ( Ratio# * (rB - rA) )
g1 = gA + ( Ratio# * (gB - gA) )
b1 = bA + ( Ratio# * (bB - bA) )

Ratio# = ClipRatio( xR, xC, xA )
y2 = yC + ( Ratio# * (yA - yC) )
z2 = zC + ( Ratio# * (zA - zC) )
r2 = rC + ( Ratio# * (rA - rC) )

g2 = gC + ( Ratio# * (gA - gC) )
b2 = bC + ( Ratio# * (bA - bC) )

clipPolygonCheck( xR,y1,z1, xB,yB,zB, xC,yC,zC, r1,g1,b1, rB,gB,bB, rC,gC,bC )
clipPolygonCheck( xR,y1,z1, xC,yC,zC, xR,y2,z2, r1,g1,b1, rC,gC,bC, r2,g2,b2 )

Case 3
Select FlagB
Case 1 xR = gfx_clip_xMin
Case 2 xR = gfx_clip_xMax
End Select

Ratio# = ClipRatio( xR, xA, xB )
y1 = yA + ( Ratio# * (yB - yA) )
z1 = zA + ( Ratio# * (zB - zA) )

r1 = rA + ( Ratio# * (rB - rA) )
g1 = gA + ( Ratio# * (gB - gA) )
b1 = bA + ( Ratio# * (bB - bA) )

Ratio# = ClipRatio( xR, xB, xC )
y2 = yB + ( Ratio# * (yC - yB) )
z2 = zB + ( Ratio# * (zC - zB) )
r2 = rB + ( Ratio# * (rC - rB) )

g2 = gB + ( Ratio# * (gC - gB) )
b2 = bB + ( Ratio# * (bC - bB) )

clipPolygonCheck( xR,y1,z1, xB,yB,zB, xR,y2,z2, r1,g1,b1, rB,gB,bB, r2,g2,b2 )

Case 2
Select FlagB
Case 1 yR = gfx_clip_yMin
Case 2 yR = gfx_clip_yMax
End Select

Ratio# = ClipRatio( yR, yA, yB )
x1 = xA + ( Ratio# * (xB - xA) )
z1 = zA + ( Ratio# * (zB - zA) )

r1 = rA + ( Ratio# * (rB - rA) )
g1 = gA + ( Ratio# * (gB - gA) )
b1 = bA + ( Ratio# * (bB - bA) )

Ratio# = ClipRatio( yR, yC, yA )
x2 = xC + ( Ratio# * (xA - xC) )
z2 = zC + ( Ratio# * (zA - zC) )

r2 = rC + ( Ratio# * (rA - rC) )
g2 = gC + ( Ratio# * (gA - gC) )
b2 = bC + ( Ratio# * (bA - bC) )

clipPolygonCheck( x1,yR,z1, xB,yB,zB, xC,yC,zC, r1,g1,b1, rB,gB,bB, rC,gC,bC )
clipPolygonCheck( x1,yR,z1, xC,yC,zC, x2,yR,z2, r1,g1,b1, rC,gC,bC, r2,g2,b2 )

Case 4
Select FlagB
Case 1 yR = gfx_clip_yMin
Case 2 yR = gfx_clip_yMax
End Select

Ratio# = ClipRatio( yR, yA, yC )
x1 = xA + ( Ratio# * (xC - xA) )
z1 = zA + ( Ratio# * (zC - zA) )

r1 = rA + ( Ratio# * (rC - rA) )
g1 = gA + ( Ratio# * (gC - gA) )
b1 = bA + ( Ratio# * (bC - bA) )

Ratio# = ClipRatio( yR, yB, yC )
x2 = xB + ( Ratio# * (xC - xB) )
z2 = zB + ( Ratio# * (zC - zB) )
r2 = rB + ( Ratio# * (rC - rB) )

g2 = gB + ( Ratio# * (gC - gB) )
b2 = bB + ( Ratio# * (bC - bB) )

clipPolygonCheck( x1,yR,z1, x2,yR,z2, xC,yC,zC, r1,g1,b1, r2,g2,b2, rC,gC,bC )

End Select

End Function


 :cheers:
Title: Re: 3D Software Engine - Clipping Polygons
Post by: Stonemonkey on July 19, 2006
Very interesting stuff, I've been meaning to get round to this as up till now I've only ever clipped in 3d against the near z plane and done the rest of the clipping in 2d in the poly renderer. Looking at this has given me a thought, instead of sending the flag through would it be possible to swap the axis of the vertex coordinates in some way as it's sent through so that only one piece of clipping code is needed?
Title: Re: 3D Software Engine - Clipping Polygons
Post by: Jim on July 19, 2006
Sod it.  I wrote a long reply to this and the board lost it.  This is me writing it again.

Good stuff Tetra!

It might be worth trying to simplify it a bit now.

I suspect you've realised that left clipping is the same as right clipping with a different x plane, same thing with top and bottom.
That should let you make 2 suborutines for clipx and clipy.

Then you can take advantage of bitwise And and Or to simplify all those if/and/else checks.
If A,B,C are the 3 sets of clip flags
A Or B Or C = 0 implies there are no clip flags and there's no clipping required

Also
c1 = A And B
c2 = A And C
c3 = B And C
if c1 or c2 or c3 has any bit set, then that edge needs clipping against those planes, so

if (c1 And $1) clipx(a->b,left)
if (c1 And $2) clipy(a->b,top)
if (c1 And $4) clipx(a->b,right)
if (c1 And $8) clipy(a->b,bottom)
same for c2 and c3.
Only clip one line per iteration.  Clipping a line changes all the clip flags.

Sorry, that's a fair bit shorter but more concise than I first posted.

Jim
Title: Re: 3D Software Engine - Clipping Polygons
Post by: Tetra on August 05, 2006
I quickly realized that this clipping method could potentially create a load more polys that actually needed.
With that in mind, plus the very interesting info you gave in your last post Jim, I have come up with this.

I've spent many hours working this out, I can only hope it is infact as efficient as I would like it to be. Either way I beleive it is better that the recursive method.

Code and Exe is also attached.

Code: [Select]
;-----------------------------------------------
;
; Polygon clipping test bed / Working Clipper
;
; by Tetra, with many thanx to Jim
;
;-----------------------------------------------


Global keystop = 0


Global gfx_clip_xMin = 160
Global gfx_clip_xMax = 640 - 160
Global gfx_clip_yMin = 120
Global gfx_clip_yMax = 480 - 120

Global gfx_clip_zMin = -1500


; clipping buffers needed for clipPolygonCheck
Dim vBuff#( 15, 8 )



Global NoDrawnPols
Global goMouse = False

Graphics 640,480,32,2

SetBuffer( BackBuffer() )

Global v1x,v1y,v1z, v2x,v2y,v2z, v3x,v3y,v3z



Function SaveVertices()
fout = WriteFile( "data.dat" )

WriteInt( fout, v1x )
WriteInt( fout, v1y )
WriteInt( fout, v1z )

WriteInt( fout, v2x )
WriteInt( fout, v2y )
WriteInt( fout, v2z )

WriteInt( fout, v3x )
WriteInt( fout, v3y )
WriteInt( fout, v3z )

CloseFile( fout )
End Function

Function LoadVertices()

fin = ReadFile( "data.dat" )
If fin
v1x = ReadInt( fin )
v1y = ReadInt( fin )
v1z = ReadInt( fin )

v2x = ReadInt( fin )
v2y = ReadInt( fin )
v2z = ReadInt( fin )

v3x = ReadInt( fin )
v3y = ReadInt( fin )
v3z = ReadInt( fin )

CloseFile( fin )

Return True
EndIf

Return False
End Function


Function Main()

If KeyDown(57)
If keystop
setPoly()
keystop = False
EndIf
ElseIf KeyDown(3)
If keystop
rotatePoints()
keystop = False
EndIf
Else
keystop = True
EndIf

If KeyDown(203) Then v1x = v1x - 4
If KeyDown(205) Then v1x = v1x + 4
If KeyDown(200) Then v1y = v1y - 4
If KeyDown(208) Then v1y = v1y + 4

Select goMouse
Case 1
v1x = MouseX()
v1y = MouseY()
Case 2
v2x = MouseX()
v2y = MouseY()
Case 3
v3x = MouseX()
v3y = MouseY()
End Select


Color 0,255,0
Rect gfx_clip_xMin,gfx_clip_yMin, (gfx_clip_xMax - gfx_clip_xMin ) + 1, ( gfx_clip_yMax - gfx_clip_yMin ) + 1, 0



If inRange( MouseX(), MouseY(), v1x,v1y, 10 )
If MouseDown(1) Then goMouse = 1
Color 255,0,0
Oval v1x-9,v1y-9,19,19
Color 255,255,255
Oval v1x-9,v1y-9,19,19,0
Color 0,255,0
Text v1x-4,v1y-6,"A"
Else
Color 0,0,0
Oval v1x-9,v1y-9,19,19
Color 255,255,255
Oval v1x-9,v1y-9,19,19,0
Color 0,255,0
Text v1x-4,v1y-6,"A"
EndIf

If inRange( MouseX(), MouseY(), v2x,v2y, 10 )
If MouseDown(1) Then goMouse = 2
Color 255,0,0
Oval v2x-9,v2y-9,19,19
Color 255,255,255
Oval v2x-9,v2y-9,19,19,0
Color 0,255,0
Text v2x-4,v2y-6,"B"
Else
Color 0,0,0
Oval v2x-9,v2y-9,19,19
Color 255,255,255
Oval v2x-9,v2y-9,19,19,0
Color 0,255,0
Text v2x-4,v2y-6,"B"
EndIf

If inRange( MouseX(), MouseY(), v3x,v3y, 10 )
If MouseDown(1) Then goMouse = 3
Color 255,0,0
Oval v3x-9,v3y-9,19,19
Color 255,255,255
Oval v3x-9,v3y-9,19,19,0
Color 0,255,0
Text v3x-4,v3y-6,"C"
Else
Color 0,0,0
Oval v3x-9,v3y-9,19,19
Color 255,255,255
Oval v3x-9,v3y-9,19,19,0
Color 0,255,0
Text v3x-4,v3y-6,"C"
EndIf


NoDrawnPols = 0

If ( TriangleArea( v1x,v1y, v2x,v2y, v3x,v3y ) < 0 )



Color 255,0,0
Line v1x,v1y, v2x,v2y

Color 0,255,0
Line v2x,v2y, v3x,v3y

Color 0,0,255
Line v3x,v3y, v1x,v1y

clipPolygonCheck( v1x,v1y,v1z, v2x,v2y,v2z, v3x,v3y,v3z, 255,0,0, 0,255,0, 0,0,255 )

For x = 0 To 14
tx = x

If (vBuff( x, 6 ) <> 0 )

Color 255,255,0
Oval vBuff( x, 0 ) - 2, vBuff( x, 1 ) - 2, 5,5

Color 0,0,0
Rect vBuff( x, 0 ) + 4, vBuff( x, 1 ) - 14, 18, 14
Color vBuff( x, 3 ),vBuff( x, 4 ),vBuff( x, 5 )
Text vBuff( x, 0 ) + 4, vBuff( x, 1 ) - 14, "i"+tx;+":"+Int(cXT( x, 6 ))



EndIf



vBuff( x, 0 ) = 0
vBuff( x, 1 ) = 0
vBuff( x, 6 ) = 0


Next
EndIf




If Not MouseDown(1) Then goMouse = 0



Color 255,255,255
Text 10,10,"Drawn Polygons: "+NoDrawnPols
Text 10,25,"Spacebar for random Polygon, arrow keys move A"
Text 10,40, "Left click to move verticies, 2 to rotate"
Flip
Cls

End Function


Function inRange( x1,y1, x2,y2, dist )

If ( Abs( x2 - x1 ) < dist )And( Abs( y2 - y1 ) < dist )
Return True
Else
Return False
EndIf

End Function

Function setPoly()
SeedRnd MilliSecs()

Local go = 1

While go > 0
v1x = 320 + (Rand( 640 )-320)
v1y = 240 + (Rand( 480 )-240)
v1z = -2000

v2x = 320 + (Rand( 640 )-320)
v2y = 240 + (Rand( 480 )-240)
v2z = -2000

v3x = 320 + (Rand( 640 )-320)
v3y = 240 + (Rand( 480 )-240)
v3z = -2000
go = TriangleArea( v1x,v1y, v2x,v2y, v3x,v3y )
Wend
End Function


Function rotatePoints()

Local tx,ty,tz
tx = v1x
ty = v1y
tz = v1z


v1x = v2x
v1y = v2y
v1z = v2z

v2x = v3x
v2y = v3y
v2z = v3z

v3x = tx
v3y = ty
v3z = tz

End Function

;any polygon passing through here does not need clipping
Function renderPoly( xA#,yA#,zA#, xB#,yB#,zB#, xC#,yC#,zC#, rA,gA,bA, rB,gB,bB, rC,gC,bC )

NoDrawnPols = NoDrawnPols + 1

If TriangleArea( xA,yA, xB,yB, xC,yC ) < 0
Color 255,255,255

Line xA,yA, xB,yB
Line xB,yB, xC,yC
Line xC,yC, xA,yA
Else
Color 255,0,0

Line xA,yA, xB,yB
Line xB,yB, xC,yC
Line xC,yC, xA,yA
EndIf

;Color rA,gA,bA
;Line xA,yA, xB,yB
;Color rB,gB,bB
;Line xB,yB, xC,yC
;Color rC,gC,bC
;Line xC,yC, xA,yA

End Function



;---------------------------------------------------------------------------------------------------------
; Clipping stuff

Function TriangleArea( xA,yA, xB,yB, xC,yC )
Return ((xA - xB)*(yC - yB)) - ((yA - yB)*(xC - xB))
End Function



;Â  Â  Â |Â  Â  Â  Â  Â |
;Â  $5 |Â  Â $4Â  Â  | $6
;-----|---------|-----
;Â  Â  Â |Â  Â  Â  Â  Â |
;Â  $1 |Â  Screen | $2
;  Â  Â |  Â Area  |
;-----|---------|-----
;Â  $9 |Â  Â $8Â  Â  | $A
;Â  Â  Â |Â  Â  Â  Â  Â |

;---------------------------------------
;
;
Function ClipPos( xA#,yA# )

Local clip% = 0

If ( xA < gfx_clip_xMin ) Then clip% = clip% Or $1
If ( xA > gfx_clip_xMax ) Then clip% = clip% Or $2

If ( yA < gfx_clip_yMin ) Then clip% = clip% Or $4
If ( yA > gfx_clip_yMax ) Then clip% = clip% Or $8

Return clip

End Function

;---------------------------------------
;
;
Function ClipPosX( xA# )

Local clip% = 0

If ( xA < gfx_clip_xMin ) Then clip% = clip% Or $1
If ( xA > gfx_clip_xMax ) Then clip% = clip% Or $2

Return clip

End Function

;---------------------------------------
;
;
Function ClipPosY( yA# )

Local clip% = 0

If ( yA < gfx_clip_yMin ) Then clip% = clip% Or $4
If ( yA > gfx_clip_yMax ) Then clip% = clip% Or $8

Return clip

End Function







;---------------------------------------
;
;
Function clipPolygonCheck( xA#,yA#,zA#, xB#,yB#,zB#, xC#,yC#,zC#, rA,gA,bA, rB,gB,bB, rC,gC,bC )

Local edgeAB
Local edgeBC
Local edgeCA

Local edgeABx
Local edgeABy

Local edgeBCx
Local edgeBCy

Local edgeCAx
Local edgeCAy


vertexA% = ClipPos( xA, yA )
vertexB% = ClipPos( xB, yB )
vertexC% = ClipPos( xC, yC )

; Polygon does not need clipping
If ( vertexA + vertexB + vertexC = 0 )
renderPoly( xA,yA,zA, xB,yB,zB, xC,yC,zC, rA,gA,bA, rB,gB,bB, rC,gC,bC )
Return
EndIf

edgeAB = vertexA Xor vertexB
edgeBC = vertexB Xor vertexC
edgeCA = vertexC Xor vertexA

edgeABx = ( edgeAB And $3 )
edgeABy = ( edgeAB And $C )

edgeBCx = ( edgeBC And $3 )
edgeBCy = ( edgeBC And $C )

edgeCAx = ( edgeCA And $3 )
edgeCAy = ( edgeCA And $C )





; Clip A -> B
Select edgeABx
Case $1
ClipX( xA,yA,zA, xB,yB,zB, rA,gA,bA, rB,gB,bB, gfx_clip_xMin, 0 )
Case $2
ClipX( xA,yA,zA, xB,yB,zB, rA,gA,bA, rB,gB,bB, gfx_clip_xMax, 1 )
Case $3
ClipX( xA,yA,zA, xB,yB,zB, rA,gA,bA, rB,gB,bB, gfx_clip_xMin, 0 )
ClipX( xA,yA,zA, xB,yB,zB, rA,gA,bA, rB,gB,bB, gfx_clip_xMax, 1 )
End Select

Select edgeABy
Case $4
ClipY( xA,yA,zA, xB,yB,zB, rA,gA,bA, rB,gB,bB, gfx_clip_yMin, 2 )
Case $8
ClipY( xA,yA,zA, xB,yB,zB, rA,gA,bA, rB,gB,bB, gfx_clip_yMax, 3 )
Case $C
ClipY( xA,yA,zA, xB,yB,zB, rA,gA,bA, rB,gB,bB, gfx_clip_yMin, 2 )
ClipY( xA,yA,zA, xB,yB,zB, rA,gA,bA, rB,gB,bB, gfx_clip_yMax, 3 )
End Select

; Clip B -> C
Select edgeBCx
Case $1
ClipX( xB,yB,zB, xC,yC,zC, rB,gB,bB, rC,gC,bC, gfx_clip_xMin, 4 )
Case $2
ClipX( xB,yB,zB, xC,yC,zC, rB,gB,bB, rC,gC,bC, gfx_clip_xMax, 5 )
Case $3
ClipX( xB,yB,zB, xC,yC,zC, rB,gB,bB, rC,gC,bC, gfx_clip_xMin, 4 )
ClipX( xB,yB,zB, xC,yC,zC, rB,gB,bB, rC,gC,bC, gfx_clip_xMax, 5 )
End Select

Select edgeBCy
Case $4
ClipY( xB,yB,zB, xC,yC,zC, rB,gB,bB, rC,gC,bC, gfx_clip_yMin, 6 )
Case $8
ClipY( xB,yB,zB, xC,yC,zC, rB,gB,bB, rC,gC,bC, gfx_clip_yMax, 7 )
Case $C
ClipY( xB,yB,zB, xC,yC,zC, rB,gB,bB, rC,gC,bC, gfx_clip_yMin, 6 )
ClipY( xB,yB,zB, xC,yC,zC, rB,gB,bB, rC,gC,bC, gfx_clip_yMax, 7 )
End Select

; Clip C -> A
Select edgeCAx
Case $1
ClipX( xC,yC,zC, xA,yA,zA, rC,gC,bC, rA,gA,bA, gfx_clip_xMin, 8 )
Case $2
ClipX( xC,yC,zC, xA,yA,zA, rC,gC,bC, rA,gA,bA, gfx_clip_xMax, 9 )
Case $3
ClipX( xC,yC,zC, xA,yA,zA, rC,gC,bC, rA,gA,bA, gfx_clip_xMin, 8 )
ClipX( xC,yC,zC, xA,yA,zA, rC,gC,bC, rA,gA,bA, gfx_clip_xMax, 9 )
End Select

Select edgeCAy
Case $4
ClipY( xC,yC,zC, xA,yA,zA, rC,gC,bC, rA,gA,bA, gfx_clip_yMin, 10 )
Case $8
ClipY( xC,yC,zC, xA,yA,zA, rC,gC,bC, rA,gA,bA, gfx_clip_yMax, 11 )
Case $C
ClipY( xC,yC,zC, xA,yA,zA, rC,gC,bC, rA,gA,bA, gfx_clip_yMin, 10 )
ClipY( xC,yC,zC, xA,yA,zA, rC,gC,bC, rA,gA,bA, gfx_clip_yMax, 11 )
End Select



Local  selLeft = ( vBuff( 0, 6 ) Shl 8 ) Or ( vBuff( 4, 6 ) Shl 4 ) Or vBuff( 8, 6 )

Select selLeft

;top left
Case 1840
ClipInternal( 0, 4, gfx_clip_yMin )
Case 775
ClipInternal( 8, 0, gfx_clip_yMin )
Case 115
ClipInternal( 4, 8, gfx_clip_yMin )

Case 1795
ClipInternal( 0, 8, gfx_clip_yMin )
Case 55
ClipInternal( 8, 4, gfx_clip_yMin )
Case 880
ClipInternal( 4, 0, gfx_clip_yMin )

;bottom left
Case 944
ClipInternal( 4, 0, gfx_clip_yMax )
Case 2819
ClipInternal( 0, 8, gfx_clip_yMax )
Case 59
ClipInternal( 8, 4, gfx_clip_yMax )

Case 779
ClipInternal( 8, 0, gfx_clip_yMax )
Case 179
ClipInternal( 4, 8, gfx_clip_yMax )
Case 2864
ClipInternal( 0, 4, gfx_clip_yMax )

;top & bottom left
Case 1803
ClipInternal( 0, 8, gfx_clip_yMin )
ClipInternal( 8, 0, gfx_clip_yMax )
Case 183
ClipInternal( 8, 4, gfx_clip_yMin )
ClipInternal( 4, 8, gfx_clip_yMax )
Case 2928
ClipInternal( 4, 0, gfx_clip_yMin )
ClipInternal( 0, 4, gfx_clip_yMax )

Case 1968
ClipInternal( 0, 4, gfx_clip_yMin )
ClipInternal( 4, 0, gfx_clip_yMax )
Case 2823
ClipInternal( 8, 0, gfx_clip_yMin )
ClipInternal( 0, 8, gfx_clip_yMax )
Case 123
ClipInternal( 4, 8, gfx_clip_yMin )
ClipInternal( 8, 4, gfx_clip_yMax )


;remove unwanted vertices
Case 2992
vBuff( 0, 6 ) = 0
vBuff( 4, 6 ) = 0
Case 1904
vBuff( 0, 6 ) = 0
vBuff( 4, 6 ) = 0

Case 2827
vBuff( 8, 6 ) = 0
vBuff( 0, 6 ) = 0
Case 1799
vBuff( 8, 6 ) = 0
vBuff( 0, 6 ) = 0

Case 187
vBuff( 4, 6 ) = 0
vBuff( 8, 6 ) = 0
Case 119
vBuff( 4, 6 ) = 0
vBuff( 8, 6 ) = 0
End Select

Local selRight = ( vBuff( 1, 6 ) Shl 8 ) Or ( vBuff( 5, 6 ) Shl 4 ) Or vBuff( 9, 6 )

Select selRight

;top right
Case 1840
ClipInternal( 1, 5, gfx_clip_yMin )
Case 775
ClipInternal( 9, 1, gfx_clip_yMin )
Case 115
ClipInternal( 5, 9, gfx_clip_yMin )

Case 1795
ClipInternal( 1, 9, gfx_clip_yMin )
Case 55
ClipInternal( 9, 5, gfx_clip_yMin )
Case 880
ClipInternal( 5, 1, gfx_clip_yMin )

;bottom right
Case 944
ClipInternal( 5, 1, gfx_clip_yMax )
Case 2819
ClipInternal( 1, 9, gfx_clip_yMax )
Case 59
ClipInternal( 9, 5, gfx_clip_yMax )

Case 779
ClipInternal( 9, 1, gfx_clip_yMax )
Case 179
ClipInternal( 5, 9, gfx_clip_yMax )
Case 2864
ClipInternal( 1, 5, gfx_clip_yMax )

;top & bottom right
Case 1803
ClipInternal( 1, 9, gfx_clip_yMin )
ClipInternal( 9, 1, gfx_clip_yMax )
Case 183
ClipInternal( 9, 5, gfx_clip_yMin )
ClipInternal( 5, 9, gfx_clip_yMax )
Case 2928
ClipInternal( 5, 1, gfx_clip_yMin )
ClipInternal( 1, 5, gfx_clip_yMax )

Case 1968
ClipInternal( 1, 5, gfx_clip_yMin )
ClipInternal( 5, 1, gfx_clip_yMax )
Case 2823
ClipInternal( 9, 1, gfx_clip_yMin )
ClipInternal( 1, 9, gfx_clip_yMax )
Case 123
ClipInternal( 5, 9, gfx_clip_yMin )
ClipInternal( 9, 5, gfx_clip_yMax )

;remove unwanted vertices
Case 2992
vBuff( 1, 6 ) = 0
vBuff( 5, 6 ) = 0
Case 1904
vBuff( 1, 6 ) = 0
vBuff( 5, 6 ) = 0

Case 2827
vBuff( 9, 6 ) = 0
vBuff( 1, 6 ) = 0
Case 1799
vBuff( 9, 6 ) = 0
vBuff( 1, 6 ) = 0

Case 187
vBuff( 5, 6 ) = 0
vBuff( 9, 6 ) = 0
Case 119
vBuff( 5, 6 ) = 0
vBuff( 9, 6 ) = 0
End Select


Local PBuff[8]
Local NumberOfVertices = 0
Local LastV = 0


If KeyDown(7) Stop

; Edge A -> B
If ( vertexA = 0 )
vBuff( 12, 0 ) = xA#
vBuff( 12, 1 ) = yA#
vBuff( 12, 2 ) = zA#
vBuff( 12, 3 ) = rA
vBuff( 12, 4 ) = gA
vBuff( 12, 5 ) = bA
vBuff( 12, 6 ) = 0

PBuff[ NumberOfVertices ] = 12
NumberOfVertices = NumberOfVertices + 1
EndIf

LastV = NumberOfVertices
For i = 0 To 3
If ( vBuff( i, 6 ) > 0 ) Then
If ( LastV <> NumberOfVertices )
If ( vBuff( i, 7 ) > vBuff( PBuff[ NumberOfVertices - 1 ], 7 ) )
PBuff[ NumberOfVertices ] = i
NumberOfVertices = NumberOfVertices + 1
Else
PBuff[ NumberOfVertices ] = PBuff[ NumberOfVertices - 1 ]
PBuff[ NumberOfVertices - 1 ] = i
NumberOfVertices = NumberOfVertices + 1
EndIf
Else
PBuff[ NumberOfVertices ] = i
NumberOfVertices = NumberOfVertices + 1
EndIf
EndIf
Next

; Edge B -> C
If ( vertexB = 0 )
vBuff( 13, 0 ) = xB#
vBuff( 13, 1 ) = yB#
vBuff( 13, 2 ) = zB#
vBuff( 13, 3 ) = rB
vBuff( 13, 4 ) = gB
vBuff( 13, 5 ) = bB
vBuff( 13, 6 ) = 0

PBuff[ NumberOfVertices ] = 13
NumberOfVertices = NumberOfVertices + 1
EndIf

LastV = NumberOfVertices
For i = 4 To 7
If ( vBuff( i, 6 ) > 0 ) Then
If ( LastV <> NumberOfVertices )
If ( vBuff( i, 7 ) > vBuff( PBuff[ NumberOfVertices - 1 ], 7 ) )
PBuff[ NumberOfVertices ] = i
NumberOfVertices = NumberOfVertices + 1
Else
PBuff[ NumberOfVertices ] = PBuff[ NumberOfVertices - 1 ]
PBuff[ NumberOfVertices - 1 ] = i
NumberOfVertices = NumberOfVertices + 1
EndIf
Else
PBuff[ NumberOfVertices ] = i
NumberOfVertices = NumberOfVertices + 1
EndIf
EndIf
Next

; Edge C -> A
If ( vertexC = 0 )
vBuff( 14, 0 ) = xC#
vBuff( 14, 1 ) = yC#
vBuff( 14, 2 ) = zC#
vBuff( 14, 3 ) = rC
vBuff( 14, 4 ) = gC
vBuff( 14, 5 ) = bC
vBuff( 14, 6 ) = 0

PBuff[ NumberOfVertices ] = 14
NumberOfVertices = NumberOfVertices + 1
EndIf

LastV = NumberOfVertices
For i = 8 To 11
If ( vBuff( i, 6 ) > 0 ) Then
If ( LastV <> NumberOfVertices )
If ( vBuff( i, 7 ) > vBuff( PBuff[ NumberOfVertices - 1 ], 7 ) )
PBuff[ NumberOfVertices ] = i
NumberOfVertices = NumberOfVertices + 1
Else
PBuff[ NumberOfVertices ] = PBuff[ NumberOfVertices - 1 ]
PBuff[ NumberOfVertices - 1 ] = i
NumberOfVertices = NumberOfVertices + 1
EndIf
Else
PBuff[ NumberOfVertices ] = i
NumberOfVertices = NumberOfVertices + 1
EndIf
EndIf
Next



Select NumberOfVertices
Case 3
renderPoly( vBuff( PBuff[0], 0 ),vBuff( PBuff[0], 1 ),vBuff( PBuff[0], 2 ), vBuff( PBuff[1], 0 ),vBuff( PBuff[1], 1 ),vBuff( PBuff[1], 2 ), vBuff( PBuff[2], 0 ),vBuff( PBuff[2], 1 ),vBuff( PBuff[2], 2 ), vBuff( PBuff[0], 4 ),vBuff( PBuff[0], 5 ),vBuff( PBuff[0], 6 ), vBuff( PBuff[1], 4 ),vBuff( PBuff[1], 5 ),vBuff( PBuff[1], 6 ), vBuff( PBuff[2], 4 ),vBuff( PBuff[2], 5 ),vBuff( PBuff[2], 6 ) )
Case 4
renderPoly( vBuff( PBuff[0], 0 ),vBuff( PBuff[0], 1 ),vBuff( PBuff[0], 2 ), vBuff( PBuff[1], 0 ),vBuff( PBuff[1], 1 ),vBuff( PBuff[1], 2 ), vBuff( PBuff[2], 0 ),vBuff( PBuff[2], 1 ),vBuff( PBuff[2], 2 ), vBuff( PBuff[0], 4 ),vBuff( PBuff[0], 5 ),vBuff( PBuff[0], 6 ), vBuff( PBuff[1], 4 ),vBuff( PBuff[1], 5 ),vBuff( PBuff[1], 6 ), vBuff( PBuff[2], 4 ),vBuff( PBuff[2], 5 ),vBuff( PBuff[2], 6 ) )
renderPoly( vBuff( PBuff[0], 0 ),vBuff( PBuff[0], 1 ),vBuff( PBuff[0], 2 ), vBuff( PBuff[2], 0 ),vBuff( PBuff[2], 1 ),vBuff( PBuff[2], 2 ), vBuff( PBuff[3], 0 ),vBuff( PBuff[3], 1 ),vBuff( PBuff[3], 2 ), vBuff( PBuff[0], 4 ),vBuff( PBuff[0], 5 ),vBuff( PBuff[0], 6 ), vBuff( PBuff[2], 4 ),vBuff( PBuff[2], 5 ),vBuff( PBuff[2], 6 ), vBuff( PBuff[3], 4 ),vBuff( PBuff[3], 5 ),vBuff( PBuff[3], 6 ) )
Case 5
renderPoly( vBuff( PBuff[0], 0 ),vBuff( PBuff[0], 1 ),vBuff( PBuff[0], 2 ), vBuff( PBuff[1], 0 ),vBuff( PBuff[1], 1 ),vBuff( PBuff[1], 2 ), vBuff( PBuff[2], 0 ),vBuff( PBuff[2], 1 ),vBuff( PBuff[2], 2 ), vBuff( PBuff[0], 4 ),vBuff( PBuff[0], 5 ),vBuff( PBuff[0], 6 ), vBuff( PBuff[1], 4 ),vBuff( PBuff[1], 5 ),vBuff( PBuff[1], 6 ), vBuff( PBuff[2], 4 ),vBuff( PBuff[2], 5 ),vBuff( PBuff[2], 6 ) )
renderPoly( vBuff( PBuff[0], 0 ),vBuff( PBuff[0], 1 ),vBuff( PBuff[0], 2 ), vBuff( PBuff[2], 0 ),vBuff( PBuff[2], 1 ),vBuff( PBuff[2], 2 ), vBuff( PBuff[3], 0 ),vBuff( PBuff[3], 1 ),vBuff( PBuff[3], 2 ), vBuff( PBuff[0], 4 ),vBuff( PBuff[0], 5 ),vBuff( PBuff[0], 6 ), vBuff( PBuff[2], 4 ),vBuff( PBuff[2], 5 ),vBuff( PBuff[2], 6 ), vBuff( PBuff[3], 4 ),vBuff( PBuff[3], 5 ),vBuff( PBuff[3], 6 ) )
renderPoly( vBuff( PBuff[0], 0 ),vBuff( PBuff[0], 1 ),vBuff( PBuff[0], 2 ), vBuff( PBuff[3], 0 ),vBuff( PBuff[3], 1 ),vBuff( PBuff[3], 2 ), vBuff( PBuff[4], 0 ),vBuff( PBuff[4], 1 ),vBuff( PBuff[4], 2 ), vBuff( PBuff[0], 4 ),vBuff( PBuff[0], 5 ),vBuff( PBuff[0], 6 ), vBuff( PBuff[3], 4 ),vBuff( PBuff[3], 5 ),vBuff( PBuff[3], 6 ), vBuff( PBuff[4], 4 ),vBuff( PBuff[4], 5 ),vBuff( PBuff[4], 6 ) )
Case 6
renderPoly( vBuff( PBuff[0], 0 ),vBuff( PBuff[0], 1 ),vBuff( PBuff[0], 2 ), vBuff( PBuff[1], 0 ),vBuff( PBuff[1], 1 ),vBuff( PBuff[1], 2 ), vBuff( PBuff[2], 0 ),vBuff( PBuff[2], 1 ),vBuff( PBuff[2], 2 ), vBuff( PBuff[0], 4 ),vBuff( PBuff[0], 5 ),vBuff( PBuff[0], 6 ), vBuff( PBuff[1], 4 ),vBuff( PBuff[1], 5 ),vBuff( PBuff[1], 6 ), vBuff( PBuff[2], 4 ),vBuff( PBuff[2], 5 ),vBuff( PBuff[2], 6 ) )
renderPoly( vBuff( PBuff[0], 0 ),vBuff( PBuff[0], 1 ),vBuff( PBuff[0], 2 ), vBuff( PBuff[2], 0 ),vBuff( PBuff[2], 1 ),vBuff( PBuff[2], 2 ), vBuff( PBuff[3], 0 ),vBuff( PBuff[3], 1 ),vBuff( PBuff[3], 2 ), vBuff( PBuff[0], 4 ),vBuff( PBuff[0], 5 ),vBuff( PBuff[0], 6 ), vBuff( PBuff[2], 4 ),vBuff( PBuff[2], 5 ),vBuff( PBuff[2], 6 ), vBuff( PBuff[3], 4 ),vBuff( PBuff[3], 5 ),vBuff( PBuff[3], 6 ) )
renderPoly( vBuff( PBuff[0], 0 ),vBuff( PBuff[0], 1 ),vBuff( PBuff[0], 2 ), vBuff( PBuff[3], 0 ),vBuff( PBuff[3], 1 ),vBuff( PBuff[3], 2 ), vBuff( PBuff[5], 0 ),vBuff( PBuff[5], 1 ),vBuff( PBuff[5], 2 ), vBuff( PBuff[0], 4 ),vBuff( PBuff[0], 5 ),vBuff( PBuff[0], 6 ), vBuff( PBuff[3], 4 ),vBuff( PBuff[3], 5 ),vBuff( PBuff[3], 6 ), vBuff( PBuff[5], 4 ),vBuff( PBuff[5], 5 ),vBuff( PBuff[5], 6 ) )
renderPoly( vBuff( PBuff[3], 0 ),vBuff( PBuff[3], 1 ),vBuff( PBuff[3], 2 ), vBuff( PBuff[4], 0 ),vBuff( PBuff[4], 1 ),vBuff( PBuff[4], 2 ), vBuff( PBuff[5], 0 ),vBuff( PBuff[5], 1 ),vBuff( PBuff[5], 2 ), vBuff( PBuff[3], 4 ),vBuff( PBuff[3], 5 ),vBuff( PBuff[3], 6 ), vBuff( PBuff[4], 4 ),vBuff( PBuff[4], 5 ),vBuff( PBuff[4], 6 ), vBuff( PBuff[5], 4 ),vBuff( PBuff[5], 5 ),vBuff( PBuff[5], 6 ) )
Case 7
renderPoly( vBuff( PBuff[0], 0 ),vBuff( PBuff[0], 1 ),vBuff( PBuff[0], 2 ), vBuff( PBuff[1], 0 ),vBuff( PBuff[1], 1 ),vBuff( PBuff[1], 2 ), vBuff( PBuff[2], 0 ),vBuff( PBuff[2], 1 ),vBuff( PBuff[2], 2 ), vBuff( PBuff[0], 4 ),vBuff( PBuff[0], 5 ),vBuff( PBuff[0], 6 ), vBuff( PBuff[1], 4 ),vBuff( PBuff[1], 5 ),vBuff( PBuff[1], 6 ), vBuff( PBuff[2], 4 ),vBuff( PBuff[2], 5 ),vBuff( PBuff[2], 6 ) )
renderPoly( vBuff( PBuff[0], 0 ),vBuff( PBuff[0], 1 ),vBuff( PBuff[0], 2 ), vBuff( PBuff[2], 0 ),vBuff( PBuff[2], 1 ),vBuff( PBuff[2], 2 ), vBuff( PBuff[3], 0 ),vBuff( PBuff[3], 1 ),vBuff( PBuff[3], 2 ), vBuff( PBuff[0], 4 ),vBuff( PBuff[0], 5 ),vBuff( PBuff[0], 6 ), vBuff( PBuff[2], 4 ),vBuff( PBuff[2], 5 ),vBuff( PBuff[2], 6 ), vBuff( PBuff[3], 4 ),vBuff( PBuff[3], 5 ),vBuff( PBuff[3], 6 ) )
renderPoly( vBuff( PBuff[0], 0 ),vBuff( PBuff[0], 1 ),vBuff( PBuff[0], 2 ), vBuff( PBuff[3], 0 ),vBuff( PBuff[3], 1 ),vBuff( PBuff[3], 2 ), vBuff( PBuff[5], 0 ),vBuff( PBuff[5], 1 ),vBuff( PBuff[5], 2 ), vBuff( PBuff[0], 4 ),vBuff( PBuff[0], 5 ),vBuff( PBuff[0], 6 ), vBuff( PBuff[3], 4 ),vBuff( PBuff[3], 5 ),vBuff( PBuff[3], 6 ), vBuff( PBuff[5], 4 ),vBuff( PBuff[5], 5 ),vBuff( PBuff[5], 6 ) )
renderPoly( vBuff( PBuff[3], 0 ),vBuff( PBuff[3], 1 ),vBuff( PBuff[3], 2 ), vBuff( PBuff[4], 0 ),vBuff( PBuff[4], 1 ),vBuff( PBuff[4], 2 ), vBuff( PBuff[5], 0 ),vBuff( PBuff[5], 1 ),vBuff( PBuff[5], 2 ), vBuff( PBuff[3], 4 ),vBuff( PBuff[3], 5 ),vBuff( PBuff[3], 6 ), vBuff( PBuff[4], 4 ),vBuff( PBuff[4], 5 ),vBuff( PBuff[4], 6 ), vBuff( PBuff[5], 4 ),vBuff( PBuff[5], 5 ),vBuff( PBuff[5], 6 ) )
renderPoly( vBuff( PBuff[0], 0 ),vBuff( PBuff[0], 1 ),vBuff( PBuff[0], 2 ), vBuff( PBuff[5], 0 ),vBuff( PBuff[5], 1 ),vBuff( PBuff[5], 2 ), vBuff( PBuff[6], 0 ),vBuff( PBuff[6], 1 ),vBuff( PBuff[6], 2 ), vBuff( PBuff[0], 4 ),vBuff( PBuff[0], 5 ),vBuff( PBuff[0], 6 ), vBuff( PBuff[5], 4 ),vBuff( PBuff[5], 5 ),vBuff( PBuff[5], 6 ), vBuff( PBuff[6], 4 ),vBuff( PBuff[6], 5 ),vBuff( PBuff[6], 6 ) )
End Select

End Function

;---------------------------------------
;
;
Function ClipInternal( a, b, gfx_clip# )

Local Ratio#

Ratio# = Float( gfx_clip - vBuff( a, 1 ) ) / Float(vBuff( b, 1 ) - vBuff( a, 1 ))

vBuff( a, 1 ) = vBuff( a, 1 ) + ( Ratio# * (vBuff( b, 1 ) - vBuff( a, 1 )) )
vBuff( a, 2 ) = vBuff( a, 2 ) + ( Ratio# * (vBuff( b, 2 ) - vBuff( a, 2 )) )

vBuff( a, 3 ) = vBuff( a, 3 ) + ( Ratio# * (vBuff( b, 3 ) - vBuff( a, 3 )) )
vBuff( a, 4 ) = vBuff( a, 4 ) + ( Ratio# * (vBuff( b, 4 ) - vBuff( a, 4 )) )
vBuff( a, 5 ) = vBuff( a, 5 ) + ( Ratio# * (vBuff( b, 5 ) - vBuff( a, 5 )) )
vBuff( a, 6 ) = $5

End Function

;---------------------------------------
;
;
Function ClipX( xA#,yA#,zA#, xB#,yB#,zB#, rA,gA,bA, rB,gB,bB, gfx_clip#, tmpIndex )

Local Ratio#

Ratio# = Float( gfx_clip - xA ) / Float(xB - xA)

vBuff( tmpIndex, 0 ) = gfx_clip#
vBuff( tmpIndex, 1 ) = yA + ( Ratio# * (yB - yA) )
vBuff( tmpIndex, 2 ) = zA + ( Ratio# * (zB - zA) )

vBuff( tmpIndex, 3 ) = rA + ( Ratio# * (rB - rA) )
vBuff( tmpIndex, 4 ) = gA + ( Ratio# * (gB - gA) )
vBuff( tmpIndex, 5 ) = bA + ( Ratio# * (bB - bA) )

vBuff( tmpIndex, 6 ) = ClipPosY( vBuff( tmpIndex, 1 ) ) Xor $3

vBuff( tmpIndex, 7 ) = Ratio#
End Function

;---------------------------------------
;
;
Function ClipY( xA#,yA#,zA#, xB#,yB#,zB#, rA,gA,bA, rB,gB,bB, gfx_clip#, tmpIndex )

Local Ratio#

Ratio# = Float( gfx_clip - yA ) / Float(yB - yA)

vBuff( tmpIndex, 0 ) = xA + ( Ratio# * (xB - xA) )

vBuff( tmpIndex, 6 ) = ClipPosX( vBuff( tmpIndex, 0 ) ) Xor $C

; dont bother if its not used
If ( vBuff( tmpIndex, 6 ) = $C )

vBuff( tmpIndex, 1 ) = gfx_clip#
vBuff( tmpIndex, 2 ) = zA + ( Ratio# * (zB - zA) )

vBuff( tmpIndex, 3 ) = rA + ( Ratio# * (rB - rA) )
vBuff( tmpIndex, 4 ) = gA + ( Ratio# * (gB - gA) )
vBuff( tmpIndex, 5 ) = bA + ( Ratio# * (bB - bA) )

vBuff( tmpIndex, 7 ) = Ratio#
Else

vBuff( tmpIndex, 6 ) = 0

EndIf

End Function

;------------------------------------------------- END CLIPPING STUFF -----------------------------

;---------------------------------------
; Main Program
;

If Not LoadVertices() Then setPoly()

While Not KeyDown(1)
Main()
Wend

SaveVertices()

End
Title: Re: 3D Software Engine - Clipping Polygons
Post by: Shockwave on August 05, 2006
Respect :)
Title: Re: 3D Software Engine - Clipping Polygons
Post by: Jim on August 06, 2006
Wow!  And that works?  Fantastic!

Jim
Title: Re: 3D Software Engine - Clipping Polygons
Post by: Rbz on August 06, 2006
Really neat, welldone dude  :)
Title: Re: 3D Software Engine - Clipping Polygons
Post by: Tetra on August 06, 2006
tnx guys, Hope some people will find this thread usefull :)

I forgot to mention the above code is a test bed for making a clipper. It lets you create any shape triangle, tells you which way the rendered triangle is facing by a white triangle facing the camera and a red triangle facing away. It also saves the last triangle to a file so when you run it again the last triangle you were working on will be loaded letting you see if the changes you made work for that triangle.