Code archives/3D Graphics - Mesh/CSG Functions

This code has been declared by its author to be Public Domain code.

Download source code

CSG Functions by starfox2003
Here are my csg functions, it might go slow if you make too many vertices for it to split. It is relatively easy once you get the idea of it. Tutorial to do csg is www.flipcode.com Please give me credit in any thing you use this in.
;Csg Engine
;By David Dawkins(Starfox)
;Started 1-10-03
;Finished(without optimizing)1-13-03
;Optimized(1-15-03)
;Licensing: None! Except to give me credit in anything you use it in:)
;Features: Union, Subtraction, Intersect, Fast enough, Removes bad triangles
;Call the csg(mesha,meshb,booltype) to do the actual functions
;Limits: Not to fast with many tris, no uvmapping
;Use PositionEntity, RotateMesh, ScaleMesh to modify pos/orient of mesh
;What csg() returns is the result mesh, not the actual meshes you send to it
;so you might want to delete those.

;Here are the globals
Global csgscale#=1,csgpiv ;The world scale (1- Normal, 2-2x Normal)
Global csgmesh[2] ;Different surface holders for different opereations

Type triangle
Field x#,y#,z#,vz#[2]
Field nx#,ny#,nz#
Field surf,index
Field ver[2],mesh
Field vx#[2],vy#[2]
Field id,tarid,del
End Type

Function FindNorm#(t.triangle,axis)
;Thanks to Simon Harris
x1# = t\vx[0]
y1# = t\vy[0]
z1# = t\vz[0]
x2# = t\vx[1]
y2# = t\vy[1]
z2# = t\vz[1]
x3# = t\vx[2]
y3# = t\vy[2]
z3# = t\vz[2]
ax#=x2-x1
ay#=y2-y1
az#=z2-z1
	
bx#=x3-x2
by#=y3-y2
bz#=z3-z2
	
If axis = 1 Then Return (ay#*bz#)-(az#*by#)
If axis = 2 Then Return (az#*bx#)-(ax#*bz#)
If axis = 3 Then Return (ax#*by#)-(ay#*bx#)
End Function
	
Function Trisintersect(t.triangle,tr.triangle)
Local x#[2],y#[2],z#[2]
surf = GetSurface(csgmesh[0],1)

x[0] = t\vx[0]
y[0] = t\vy[0]
z[0] = t\vz[0]
x[1] = t\vx[1]
y[1] = t\vy[1]
z[1] = t\vz[1]
x[2] = t\vx[2]
y[2] = t\vy[2]
z[2] = t\vz[2]

VertexCoords(surf,0,x[0],y[0],z[0])
VertexCoords(surf,1,x[1],y[1],z[1])
VertexCoords(surf,2,x[2],y[2],z[2])

surf1 = GetSurface(csgmesh[1],1)

x[0] = tr\vx[0]
y[0] = tr\vy[0]
z[0] = tr\vz[0]
x[1] = tr\vx[1]
y[1] = tr\vy[1]
z[1] = tr\vz[1]
x[2] = tr\vx[2]
y[2] = tr\vy[2]
z[2] = tr\vz[2]

VertexCoords(surf1,0,x[0],y[0],z[0])
VertexCoords(surf1,1,x[1],y[1],z[1])
VertexCoords(surf1,2,x[2],y[2],z[2])

inter = MeshesIntersect(csgmesh[0],csgmesh[1])

Return inter
End Function

Function RayIntersect(t.triangle,tr.triangle)
Local x#[2],y#[2],z#[2]
x[0] = t\vx[0]
y[0] = t\vy[0]
z[0] = t\vz[0]
x[1] = t\vx[1]
y[1] = t\vy[1]
z[1] = t\vz[1]
x[2] = t\vx[2]
y[2] = t\vy[2]
z[2] = t\vz[2]
surf = GetSurface(csgmesh[0],1)

VertexCoords(surf,0,x[0],y[0],z[0])
VertexCoords(surf,1,x[1],y[1],z[1])
VertexCoords(surf,2,x[2],y[2],z[2])

piv = csgpiv
PositionEntity(piv,tr\x,tr\y,tr\z)
AlignToVector(piv,tr\nx,tr\ny,tr\nz,3)
MoveEntity piv,0,0,100000*csgscale

EntityPickMode csgmesh[0],2

distx# = EntityX(piv)-tr\x
disty# = EntityY(piv)-tr\y
distz# = EntityZ(piv)-tr\z
picked = LinePick(tr\x,tr\y,tr\z,distx,disty,distz)

If picked > 0
Return 1
Else
Return 0
EndIf
End Function

Function Split(t.triangle,tr.triangle)
If t = Null Then Return
If tr = Null Then Return
mesh = tr\mesh
Local newvx#[2],newvy#[2],newvz#[2]
Local edge1,edge2,edge3,count=0
Local cx#[2],cy#[2],cz#[2]
Local epsilon#=.00001
cube = csgmesh[2]
EntityPickMode cube,2;Position the plane
PositionEntity cube,t\x,t\y,t\z
RotateEntity cube,0,0,0
AlignToVector(cube,t\nx,t\ny,t\nz,2)
;Edge1
x# = tr\vx[0]
y# = tr\vy[0]
z# = tr\vz[0]
x1# = tr\vx[1]
y1# = tr\vy[1]
z1# = tr\vz[1]
distx# = x-x1:disty#=y-y1:distz#=z-z1
picked = LinePick(x1,y1,z1,distx,disty,distz)
If picked = cube
edge1 = True
newvx[count] = PickedX():newvy[count]=PickedY():newvz[count]=PickedZ()

distx# = newvx[count] - x1
disty# = newvy[count] - y1
distz# = newvz[count] - z1
cdist# = Sqr(distx*distx + disty*disty + distz*distz)
If cdist <= epsilon
edge1 = False
Else
count = count + 1
EndIf

EndIf
;Edge2
x# = tr\vx[1]
y# = tr\vy[1]
z# = tr\vz[1]
x1# = tr\vx[2]
y1# = tr\vy[2]
z1# = tr\vz[2]
distx# = x-x1:disty#=y-y1:distz#=z-z1
picked = LinePick(x1,y1,z1,distx,disty,distz)
If picked = cube
edge2 = True
newvx[count] = PickedX():newvy[count]=PickedY():newvz[count]=PickedZ()

distx# = newvx[count] - x1
disty# = newvy[count] - y1
distz# = newvz[count] - z1
cdist# = Sqr(distx*distx + disty*disty + distz*distz)
If cdist <= epsilon
edge2 = False
Else
count = count + 1
EndIf

EndIf
;Edge3
x# = tr\vx[2]
y# = tr\vy[2]
z# = tr\vz[2]
x1# = tr\vx[0]
y1# = tr\vy[0]
z1# = tr\vz[0]
distx# = x-x1:disty#=y-y1:distz#=z-z1
picked = LinePick(x1,y1,z1,distx,disty,distz)
If picked = cube
edge3 = True
newvx[count] = PickedX():newvy[count]=PickedY():newvz[count]=PickedZ()

distx# = newvx[count] - x1
disty# = newvy[count] - y1
distz# = newvz[count] - z1
cdist# = Sqr(distx*distx + disty*disty + distz*distz)
If cdist <= epsilon
edge3 = False
Else
count = count + 1
EndIf

EndIf
If count = 0 Then Return 0
If edge1 And edge2
cx[0] = tr\vx[0]
cy[0] = tr\vy[0]
cz[0] = tr\vz[0]
cx[1] = tr\vx[1]
cy[1] = tr\vy[1]
cz[1] = tr\vz[1]
cx[2] = tr\vx[2]
cy[2] = tr\vy[2]
cz[2] = tr\vz[2]
surf = tr\surf
mesh = tr\mesh
tr\del = 1
;deletetri(tr)
v1 = AddVertex(surf,cx[0],cy[0],cz[0])
v2 = AddVertex(surf,newvx[0],newvy[0],newvz[0])
v3 = AddVertex(surf,cx[1],cy[1],cz[1])
v4 = AddVertex(surf,newvx[1],newvy[1],newvz[1])
v5 = AddVertex(surf,cx[2],cy[2],cz[2])

index = AddTriangle(surf,v1,v2,v5)
tm.triangle = createtri(surf,index,mesh)
tm\tarid = t\id
index = AddTriangle(surf,v2,v4,v5)
tm.triangle = createtri(surf,index,mesh)
tm\tarid = t\id
index = AddTriangle(surf,v2,v3,v4)
tm.triangle = createtri(surf,index,mesh)
tm\tarid = t\id

ElseIf edge1 And edge3
cx[0] = tr\vx[0]
cy[0] = tr\vy[0]
cz[0] = tr\vz[0]
cx[1] = tr\vx[1]
cy[1] = tr\vy[1]
cz[1] = tr\vz[1]
cx[2] = tr\vx[2]
cy[2] = tr\vy[2]
cz[2] = tr\vz[2]
surf = tr\surf
mesh = tr\mesh
tr\del = 1
;deletetri(tr)
v1 = AddVertex(surf,cx[0],cy[0],cz[0])
v2 = AddVertex(surf,newvx[0],newvy[0],newvz[0])
v3 = AddVertex(surf,cx[1],cy[1],cz[1])
v4 = AddVertex(surf,cx[2],cy[2],cz[2])
v5 = AddVertex(surf,newvx[1],newvy[1],newvz[1])

index = AddTriangle(surf,v1,v2,v5)
tm.triangle = createtri(surf,index,mesh)
tm\tarid = t\id
index = AddTriangle(surf,v2,v4,v5)
tm.triangle = createtri(surf,index,mesh)
tm\tarid = t\id
index = AddTriangle(surf,v2,v3,v4)
tm.triangle = createtri(surf,index,mesh)
tm\tarid = t\id
ElseIf edge2 And edge3
cx[0] = tr\vx[0]
cy[0] = tr\vy[0]
cz[0] = tr\vz[0]
cx[1] = tr\vx[1]
cy[1] = tr\vy[1]
cz[1] = tr\vz[1]
cx[2] = tr\vx[2]
cy[2] = tr\vy[2]
cz[2] = tr\vz[2]
surf = tr\surf
mesh = tr\mesh
tr\del = 1
;deletetri(tr)
v1 = AddVertex(surf,cx[0],cy[0],cz[0])
v2 = AddVertex(surf,cx[1],cy[1],cz[1])
v3 = AddVertex(surf,newvx[0],newvy[0],newvz[0])
v4 = AddVertex(surf,cx[2],cy[2],cz[2])
v5 = AddVertex(surf,newvx[1],newvy[1],newvz[1])

index = AddTriangle(surf,v1,v2,v5)
tm.triangle = createtri(surf,index,mesh)
tm\tarid = t\id
index = AddTriangle(surf,v2,v3,v5)
tm.triangle = createtri(surf,index,mesh)
tm\tarid = t\id
index = AddTriangle(surf,v3,v4,v5)
tm.triangle = createtri(surf,index,mesh)
tm\tarid = t\id
ElseIf edge2
cx[0] = tr\vx[0]
cy[0] = tr\vy[0]
cz[0] = tr\vz[0]
cx[1] = tr\vx[1]
cy[1] = tr\vy[1]
cz[1] = tr\vz[1]
cx[2] = tr\vx[2]
cy[2] = tr\vy[2]
cz[2] = tr\vz[2]
surf = tr\surf
mesh = tr\mesh
tr\del = 1
;deletetri(tr)
v1 = AddVertex(surf,cx[0],cy[0],cz[0])
v2 = AddVertex(surf,cx[1],cy[1],cz[1])
v3 = AddVertex(surf,newvx[0],newvy[0],newvz[0])
v4 = AddVertex(surf,cx[2],cy[2],cz[2])
index = AddTriangle(surf,v1,v2,v3)
tm.triangle = createtri(surf,index,mesh)
tm\tarid = t\id
index = AddTriangle(surf,v1,v3,v4)
tm.triangle = createtri(surf,index,mesh)
tm\tarid = t\id
ElseIf edge1
cx[0] = tr\vx[0]
cy[0] = tr\vy[0]
cz[0] = tr\vz[0]
cx[1] = tr\vx[1]
cy[1] = tr\vy[1]
cz[1] = tr\vz[1]
cx[2] = tr\vx[2]
cy[2] = tr\vy[2]
cz[2] = tr\vz[2]
surf = tr\surf
mesh = tr\mesh
tr\del = 1
;deletetri(tr)
v1 = AddVertex(surf,cx[0],cy[0],cz[0])
v2 = AddVertex(surf,newvx[0],newvy[0],newvz[0])
v3 = AddVertex(surf,cx[1],cy[1],cz[1])
v4 = AddVertex(surf,cx[2],cy[2],cz[2])
index = AddTriangle(surf,v1,v2,v4)
tm.triangle = createtri(surf,index,mesh)
tm\tarid = t\id
index = AddTriangle(surf,v2,v3,v4)
tm.triangle = createtri(surf,index,mesh)
tm\tarid = t\id
ElseIf edge3
cx[0] = tr\vx[0]
cy[0] = tr\vy[0]
cz[0] = tr\vz[0]
cx[1] = tr\vx[1]
cy[1] = tr\vy[1]
cz[1] = tr\vz[1]
cx[2] = tr\vx[2]
cy[2] = tr\vy[2]
cz[2] = tr\vz[2]
surf = tr\surf
mesh = tr\mesh
tr\del = 1
;deletetri(tr)

v1 = AddVertex(surf,cx[0],cy[0],cz[0])
v2 = AddVertex(surf,cx[1],cy[1],cz[1])
v3 = AddVertex(surf,cx[2],cy[2],cz[2])
v4 = AddVertex(surf,newvx[0],newvy[0],newvz[0])

index = AddTriangle(surf,v1,v2,v4)
tm.triangle = createtri(surf,index,mesh)
tm\tarid = t\id
index = AddTriangle(surf,v2,v3,v4)
tm.triangle = createtri(surf,index,mesh)
tm\tarid = t\id
EndIf

;UpdateNormals mesh
End Function

Function CreateTri.triangle(surf,index,mesh)
Local x1#,y1#,z1#
Local x2#,y2#,z2#
Local x3#,y3#,z3#
tr.triangle = Last triangle
newid = tr\id + 1
t.triangle = New triangle
t\surf = surf : t\index = index : t\mesh = mesh
t\ver[0] = TriangleVertex(surf,t\index,0)
x1=VertexX(surf,t\ver[0]):y1=VertexY(surf,t\ver[0]):z1=VertexZ(surf,t\ver[0])
TFormPoint(x1,y1,z1,t\mesh,0)
x1 = TFormedX():y1 = TFormedY():z1 = TFormedZ()
t\vx[0] = x1:t\vy[0]=y1:t\vz[0]=z1
t\ver[1] = TriangleVertex(surf,t\index,1)
x2=VertexX(surf,t\ver[1]):y2=VertexY(surf,t\ver[1]):z2=VertexZ(surf,t\ver[1])
TFormPoint(x2,y2,z2,t\mesh,0)
x2 = TFormedX():y2 = TFormedY():z2 = TFormedZ()
t\vx[1] = x2:t\vy[1]=y2:t\vz[1]=z2
t\ver[2] = TriangleVertex(surf,t\index,2)
x3=VertexX(surf,t\ver[2]):y3=VertexY(surf,t\ver[2]):z3=VertexZ(surf,t\ver[2])
TFormPoint(x3,y3,z3,t\mesh,0)
x3 = TFormedX():y3 = TFormedY():z3 = TFormedZ()
t\vx[2] = x3:t\vy[2]=y3:t\vz[2]=z3
t\nx = findnorm(t,1)
t\ny = findnorm(t,2)
t\nz = findnorm(t,3)
normlen# = Sqr#((t\nx*t\nx)+(t\ny*t\ny)+(t\nz*t\nz))
If normlen > 0
t\nx = t\nx/normlen : t\ny = t\ny/normlen : t\nz = t\nz/normlen
Else
t\del = 1
EndIf
t\x = (x1 + x2 + x3)/3.0:t\y = (y1 + y2 + y3)/3.0:t\z = (z1 + z2 + z3)/3.0
t\id = newid
Return t
End Function

Function DeleteTris()
;Deletes all the triangles that should be deleted
Local surface[1000]
Local counter=0
For t.triangle = Each triangle
If t\del = 1

For doit = 1 To counter
If t\surf = surface[doit]
counter = doit:Exit
EndIf
Next

If t\surf <> surface[counter]
counter = counter + 1
surface[counter] = t\surf
EndIf

EndIf
Next

For doit = 1 To counter
surf = surface[doit]

	count = CountTriangles(surf)
	bank = CreateBank((15*count)*4)
	For tricount = 0 To count-1
	off = (tricount*15)*4
	in = TriangleVertex(surf,tricount,0)
	x# = VertexX(surf,in):y#=VertexY(surf,in):z#=VertexZ(surf,in)
	u# = VertexU(surf,in):v#=VertexV(surf,in)
	TFormPoint(x,y,z,mesh,0)
	x = TFormedX():y=TFormedY():z=TFormedZ()
	PokeFloat(bank,off,x)
	PokeFloat(bank,off+4,y)
	PokeFloat(bank,off+8,z)
	PokeFloat(bank,off+12,u)
	PokeFloat(bank,off+16,v)

	in = TriangleVertex(surf,tricount,1)
	x# = VertexX(surf,in):y#=VertexY(surf,in):z#=VertexZ(surf,in)
	u# = VertexU(surf,in):v#=VertexV(surf,in)
	TFormPoint(x,y,z,mesh,0)
	x = TFormedX():y=TFormedY():z=TFormedZ()
	PokeFloat(bank,off+20,x)
	PokeFloat(bank,off+24,y)
	PokeFloat(bank,off+28,z)
	PokeFloat(bank,off+32,u)
	PokeFloat(bank,off+36,v)

	in = TriangleVertex(surf,tricount,2)
	x# = VertexX(surf,in):y#=VertexY(surf,in):z#=VertexZ(surf,in)
	u# = VertexU(surf,in):v#=VertexV(surf,in)
	TFormPoint(x,y,z,mesh,0)
	x = TFormedX():y=TFormedY():z=TFormedZ()
	PokeFloat(bank,off+40,x)
	PokeFloat(bank,off+44,y)
	PokeFloat(bank,off+48,z)
	PokeFloat(bank,off+52,u)
	PokeFloat(bank,off+56,v)

	Next
	
	ClearSurface(surf,True,True)
	
	For tricount = 0 To count-1
	skipthis = 0
	For t.triangle = Each triangle
	If t\del = 1
		If t\index = tricount And t\surf = surf
		skipthis = 1:Exit
		EndIf
	EndIf
	Next
	;If (t\index <> tricount Or t\surf <> surf)
	If skipthis = 0
	off = (tricount*15)*4
	x# = PeekFloat(bank,off)
	y# = PeekFloat(bank,off+4)
	z# = PeekFloat(bank,off+8)
	u# = PeekFloat(bank,off+12)
	v# = PeekFloat(bank,off+16)
	TFormPoint(x,y,z,0,mesh)
	x = TFormedX():y=TFormedY():z=TFormedZ()
	a = AddVertex(surf,x,y,z,u,v)
	x# = PeekFloat(bank,off+20)
	y# = PeekFloat(bank,off+24)
	z# = PeekFloat(bank,off+28)
	u# = PeekFloat(bank,off+32)
	v# = PeekFloat(bank,off+36)
	TFormPoint(x,y,z,0,mesh)
	x = TFormedX():y=TFormedY():z=TFormedZ()
	b = AddVertex(surf,x,y,z,u,v)
	x# = PeekFloat(bank,off+40)
	y# = PeekFloat(bank,off+44)
	z# = PeekFloat(bank,off+48)
	u# = PeekFloat(bank,off+52)
	v# = PeekFloat(bank,off+56)
	TFormPoint(x,y,z,0,mesh)
	x = TFormedX():y=TFormedY():z=TFormedZ()
	c = AddVertex(surf,x,y,z,u,v)
	AddTriangle(surf,a,b,c)
	EndIf
	Next
	FreeBank bank
	
	
Next

For t.triangle = Each triangle
If t\del = 1
	For tom.triangle = Each triangle
	If tom\index > t\index And tom\surf = t\surf
	tom\index = tom\index - 1
	EndIf
	Next
Delete t
EndIf
Next
	
;index = t\index
;surf = t\surf
;id = t\id
;tar = t\tarid
;Delete t
;UpdateNormals mesh
;For tom.triangle = Each triangle
;If tom\index > index And tom\surf = surf
;tom\index = tom\index - 1
;EndIf
;Next
;EndIf
;Next

;Return mesh
End Function

Function CSG(mesha,meshb,mode=2)
;mode 1 - Union, mode 2 - Subtraction, mode 3 - Intersection
Local x1#,y1#,z1#
Local x2#,y2#,z2#
Local x3#,y3#,z3#
Local idstate=0

;Do prestuff
xpos# = EntityX(mesha,1):ypos# = EntityY(mesha,1):zpos#=EntityZ(mesha,1)
xpos1# = EntityX(meshb,1):ypos1# = EntityY(meshb,1):zpos1#=EntityZ(meshb,1)
mesha = CopyMesh(mesha) : meshb = CopyMesh(meshb)
meshc = CopyMesh(mesha) : meshd = CopyMesh(meshb)
PositionMesh mesha,xpos,ypos,zpos
PositionMesh meshb,xpos1,ypos1,zpos1
PositionMesh meshc,xpos,ypos,zpos
PositionMesh meshd,xpos1,ypos1,zpos1

For cat = 1 To 4
If cat = 1 Then curmesh = mesha
If cat = 2 Then curmesh = meshb
If cat = 3 Then curmesh = meshc
If cat = 4 Then curmesh = meshd
For surfcount = 1 To CountSurfaces(curmesh)
	surf = GetSurface(curmesh,surfcount)
	For tricount = 0 To CountTriangles(surf)-1
	t.triangle = New triangle
	t\surf = surf : t\index = tricount : t\mesh = curmesh
	t\ver[0] = TriangleVertex(surf,t\index,0)
	x1=VertexX(surf,t\ver[0]):y1=VertexY(surf,t\ver[0]):z1=VertexZ(surf,t\ver[0])
	TFormPoint(x1,y1,z1,t\mesh,0)
	x1 = TFormedX():y1 = TFormedY():z1 = TFormedZ()
	t\vx[0] = x1:t\vy[0]=y1:t\vz[0]=z1
	t\ver[1] = TriangleVertex(surf,t\index,1)
	x2=VertexX(surf,t\ver[1]):y2=VertexY(surf,t\ver[1]):z2=VertexZ(surf,t\ver[1])
	TFormPoint(x2,y2,z2,t\mesh,0)
	x2 = TFormedX():y2 = TFormedY():z2 = TFormedZ()
	t\vx[1] = x2:t\vy[1]=y2:t\vz[1]=z2
	t\ver[2] = TriangleVertex(surf,t\index,2)
	x3=VertexX(surf,t\ver[2]):y3=VertexY(surf,t\ver[2]):z3=VertexZ(surf,t\ver[2])
	TFormPoint(x3,y3,z3,t\mesh,0)
	x3 = TFormedX():y3 = TFormedY():z3 = TFormedZ()
	t\vx[2] = x3:t\vy[2]=y3:t\vz[2]=z3
	t\nx = findnorm(t,1)
	t\ny = findnorm(t,2)
	t\nz = findnorm(t,3)
	normlen# = Sqr#((t\nx*t\nx)+(t\ny*t\ny)+(t\nz*t\nz))
	If normlen > 0
	t\nx = t\nx/normlen : t\ny = t\ny/normlen : t\nz = t\nz/normlen
	Else
	t\del = 1
	EndIf
	t\x = (x1 + x2 + x3)/3.0:t\y = (y1 + y2 + y3)/3.0:t\z = (z1 + z2 + z3)/3.0
	t\id = idstate:t\tarid = -1
	idstate = idstate + 1
	Next
Next
Next

;Create the reuse objects
csgmesh[0] = CreateMesh()
surf = CreateSurface(csgmesh[0])
v1 = AddVertex(surf,-1,0,1)
v2 = AddVertex(surf,1,0,1)
v3 = AddVertex(surf,1,0,-1)
AddTriangle(surf,v1,v2,v3)

csgmesh[1] = CreateMesh()
surf = CreateSurface(csgmesh[1])
v1 = AddVertex(surf,-1,0,1)
v2 = AddVertex(surf,1,0,1)
v3 = AddVertex(surf,1,0,-1)
AddTriangle(surf,v1,v2,v3)

csgmesh[2] = CreateCube()
ScaleMesh csgmesh[2],10000*csgscale,0,10000*csgscale

;Time to split the a polys
For t.triangle = Each triangle
If t\mesh = meshb
hit = 0
	For tr.triangle = Each triangle
	If tr\mesh = mesha And tr\tarid <> t\id
	If tr\del = 0
	inter = 0
	inter = trisintersect(t,tr)
	If inter = 1
		split(t,tr)
	EndIf
	EndIf
	EndIf
	Next
EndIf
Next

;Now split the b poly's
For t.triangle = Each triangle
If t\mesh = meshc
	For tr.triangle = Each triangle
	If tr\mesh = meshb And tr\tarid <> t\id
	If tr\del = 0
	inter = 0
	inter = trisintersect(t,tr)
	If inter = 1
		split(t,tr)
	EndIf
	EndIf
	EndIf
	Next
EndIf
Next

;Step 2 of reuse
surf = GetSurface(csgmesh[0],1)
AddTriangle(surf,2,1,0)
FreeEntity csgmesh[1]
FreeEntity csgmesh[2]
csgpiv = CreatePivot()

;Delete all the triangles without normals
For t.triangle = Each triangle
If t\nx = 0 And t\ny = 0 And t\nz = 0 And t\del = 0
t\del = 1
EndIf
Next

Local epsilon#=.00001

;MeshA
For t.triangle = Each triangle
If t\mesh = mesha And t\del = 0
cosangle# = -1
inter = 0
intermode = 0;1 - inside, 2 - shared, 3 - Not inside
quickdist# = 100000
	For tr.triangle = Each triangle
	If tr\mesh = meshd
	res = rayintersect(tr,t)
	If res = 1
	intx# = PickedX()
	inty# = PickedY()
	intz# = PickedZ()
	dist# = Sqr((intx-t\x)*(intx-t\x)+(inty-t\y)*(inty-t\y)+(intz-t\z)*(intz-t\z))
	If dist < quickdist
	quickdist = dist
	inter = 1
	cosangle# = (t\nx*tr\nx)+(t\ny*tr\ny)+(t\nz*tr\nz)
	EndIf
	EndIf
	EndIf
	Next
	
	If inter = 1
	If cosangle > 0 Then intermode = 1
	If cosangle < 0 Then intermode = 3
	If quickdist < epsilon ;If the triangle is shared
	intermode = 2
	EndIf
	Else
	intermode = 3
	EndIf
	
If mode = 2
	If intermode = 1 Or intermode = 2
	t\del = 1
	;deletetri(t)
	EndIf
ElseIf mode = 1
	If intermode = 1 Or intermode = 2
	t\del = 1
	;deletetri(t)
	EndIf
ElseIf mode = 3
	If intermode = 3 Or intermode = 2
	t\del = 1
	;deletetri(t)
	EndIf
EndIf
EndIf
Next

;MeshB
For t.triangle = Each triangle
If t\mesh = meshb And t\del = 0
cosangle = -1
inter = 0
intermode = 0;1 - inside, 2 - shared, 3 - not inside
quickdist# = 100000
	For tr.triangle = Each triangle
	If tr\mesh = meshc
	res = rayintersect(tr,t)
	If res = 1
	intx# = PickedX()
	inty# = PickedY()
	intz# = PickedZ()
	dist# = Sqr((intx-t\x)*(intx-t\x)+(inty-t\y)*(inty-t\y)+(intz-t\z)*(intz-t\z))
	If dist < quickdist
	quickdist = dist
	inter = 1
	cosangle# = (t\nx*tr\nx)+(t\ny*tr\ny)+(t\nz*tr\nz)
	EndIf
	EndIf
	EndIf
	Next
	
	If inter = 1
	If cosangle > 0 Then intermode = 1
	If cosangle < 0 Then intermode = 3
	If quickdist < epsilon
	intermode = 2
	EndIf
	Else
	intermode = 3
	EndIf
	
If mode = 2
	If intermode = 3 Or intermode = 2
	t\del = 1
	;deletetri(t)
	EndIf
ElseIf mode = 1
	If intermode = 1
	t\del = 1
	;deletetri(t)
	EndIf
ElseIf mode = 3
	If intermode = 3
	t\del = 1
	;deletetri(t)
	EndIf
EndIf
EndIf
Next

;Now delete the polys that don't belong(loose polys)

clearltris(mesha)
clearltris(meshb)

deletetris()

If mode = 2
FlipMesh(meshb)
EndIf

FreeEntity csgpiv
FreeEntity csgmesh[0]
FreeEntity meshd
FreeEntity meshc
AddMesh(meshb,mesha)
FreeEntity meshb

Delete Each triangle
UpdateNormals mesha

Return mesha
End Function

Function ClearLTris(mesh)
;Clears the triangles that have no partners
Local epsilon#=.00001,cdist#
Local count=0, dist#[2]
For t.triangle = Each triangle
If t\mesh = mesh And t\del = 0
count=0
For full = 0 To 2
	For tom.triangle = Each triangle
	If tom\del = 0 And tom\mesh = mesh
	cdist = 0
		For car = 0 To 2
		dist[0] = tom\vx[car] - t\vx[full]
		dist[1] = tom\vy[car] - t\vy[full]
		dist[2] = tom\vz[car] - t\vz[full] 
		cdist# = Sqr(dist[0]*dist[0] + dist[1]*dist[1] + dist[2]*dist[2])
		If cdist <= epsilon Then Exit
		Next
	If cdist >= 0 Then count = count + 1:Exit
	EndIf
	Next
Next

If count < 3
t\del = 1
EndIf
EndIf
Next
End Function

example()
Function example()
Local wire=0
AppTitle "Starfox's CSG (David Dawkins)"
Graphics3D 640,480
cube = CreateCube()
ScaleMesh cube,10,2,10
cube2 = CreateCube()
ScaleMesh cube2,5,5,5
cam = CreateCamera()
MoveEntity cam,0,10,-20
PointEntity cam,cube2
TurnEntity CreateLight(),45,45,0
UpdateNormals cube:UpdateNormals cube2
EntityAlpha cube2,.5

While Not KeyHit(1)
If KeyDown(205) Then MoveEntity cube2,.1,0,0
If KeyDown(203) Then MoveEntity cube2,-.1,0,0
If KeyDown(30) Then MoveEntity cube2,0,0,.1
If KeyDown(44) Then MoveEntity cube2,0,0,-.1
If KeyDown(200) Then MoveEntity cube2,0,.1,0
If KeyDown(208) Then MoveEntity cube2,0,-.1,0
If KeyHit(17)
wire = 1 - wire
WireFrame wire
EndIf
If KeyHit(57)
e = MilliSecs()
man = csg(cube,cube2)
e = MilliSecs() -e
FreeEntity cube
cube = man
EndIf

UpdateWorld
RenderWorld
Text 0,0,"Time: "+e+" m"
Text 0,15,"Arrows to Move Left/Right/Up/Down"
Text 0,30,"A/Z to move Forward and Back"
Text 0,45,"Tris: "+TrisRendered()/2
Flip
Wend
End
End Function

Comments

None.

Code Archives Forum