Code archives/3D Graphics - Mesh/CSG Bmax + B3d Edition

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

Download source code

CSG Bmax + B3d Edition by Leon Drake2007
Just a Port from Blitz3d to Bmax + B3dsdk for Markus Rauch + Starfox's CSG operations.
' MR 02.11.2003 

'####################################################################################################

'Csg Engine 

'Thanks To David Dawkins(Starfox) For the bb code example '-)

'MR 19.01.2003
'tuned And optimized , now by cube subtract sphere 2 seconds + :-)
'MR 25.01.2003
'add uvmapping :-) slow down but works
'MR 26.01.2003
'Multiple Surfaces :-)
'MR 02.11.2003
'Repaint target Surfaces , need BB 3D => V 1.85 !

'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
'It works only If all bbEntity have no Pickmode !

'What CSG() returns is the result mesh, Not the actual meshes you send To it
'so you might want To Delete those.

'NOTE:AddMesh add no surfaces :-( , And with CopyMesh you became only 1 surface :-(

'####################################################################################################

'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
Global CSGVectorType_list:TList = CreateList()
Global CSGTriangleTYPE_list:TList = CreateList()
'-----------------------

Type CSGVectorType Extends TBBType

	Method New()
		Add(CSGVectorType_list)
	End Method
	Method After:CSGVectorType()
		Local t:TLink
		t=_link.NextLink()
		If t Return CSGVectorType(t.Value())
	End Method

	Method Before:CSGVectorType()
		Local t:TLink
		t=_link.PrevLink()
		If t Return CSGVectorType(t.Value())
	End Method


 Field x#
 Field y#
 Field z#

 Field u# 'Texture Coords !
 Field v#
 Field w#
End Type

'-----------------------

Type CSGTriangleTYPE Extends TBBType

	Method New()
		Add(CSGTriangleTYPE_list)
	End Method
	Method After:CSGTriangleTYPE()
		Local t:TLink
		t=_link.NextLink()
		If t Return CSGTriangleTYPE(t.Value())
	End Method

	Method Before:CSGTriangleTYPE()
		Local t:TLink
		t=_link.PrevLink()
		If t Return CSGTriangleTYPE(t.Value())
	End Method




 Field id
 Field tarid            'See Split
 Field del              'Can be deleted
 Field mindex           'Mesh Index (Not a Handle)
 Field sindex						'Surface Index			
 Field tindex 					'Triangle Index

 Field v1x#           'Edge Vertex 1
 Field v1y#
 Field v1z#
 Field u1#
 Field v1#
 Field w1#

 Field v2x#           'Edge Vertex 2
 Field v2y#
 Field v2z#
 Field u2#
 Field v2#
 Field w2#

 Field v3x#           'Edge Vertex 3
 Field v3y#
 Field v3z#
 Field u3#
 Field v3#
 Field w3#

 Field mix#   'Middle Vector from all Edge Vertices
 Field miy# 
 Field miz#

 Field normx# 'Normal of Triangle
 Field normy# 
 Field normz# 

End Type

'###############################################################################################

'.CSGTestIt

'Commend the two lines If you Include this CSG file !

'CSGExample()
'End

'###############################################################################################

Function CSG(mesh1,mesh2,mode=2)

 'MR 02.11.2003

 'mode 1 - Union, mode 2 - Subtraction, mode 3 - Intersection

 Local x1#,y1#,z1#
 Local x2#,y2#,z2#
 Local x3#,y3#,z3#

 Local vi1,vi2,vi3    'Only VertexIndex

 '-------------------------------------------------------------------------------------- Memory Position And Angles

 Local ex#,ey#,ez#

 ex=bbEntityX(mesh1,1)
 ey=bbEntityY(mesh1,1)
 ez=bbEntityZ(mesh1,1)

 Local epitch#,eyaw#,eroll#

 epitch=bbEntityPitch(mesh1,1)
 eyaw  =bbEntityYaw  (mesh1,1)
 eroll =bbEntityRoll (mesh1,1)

 '--------------------------------------------------------------------------------------

 Local curmesh
 Local mindex
 Local surf,sindex
 Local SurfaceBrush
 Local tindex
 Local idstate=0
 Local t:CSGTriangleTYPE
 Local t1:CSGTriangleTYPE
 Local t2:CSGTriangleTYPE

 Local ve1:CSGVectorType
 Local ve2:CSGVectorType
 Local ve3:CSGVectorType

 For mindex = 1 To 4

 If mindex = 1 Then curmesh = mesh1
 If mindex = 2 Then curmesh = mesh2
 If mindex = 3 Then curmesh = mesh1
 If mindex = 4 Then curmesh = mesh2

 'Now copy all 4 Meshes To Buffer

 For sindex = 1 To bbCountSurfaces(curmesh)

  'DebugLog "sindex "+sindex

	surf = bbGetSurface(curmesh,sindex)
	For tindex = 0 To bbCountTriangles(surf)-1
   
   '---------------------------------------
  
	 vi1 = bbTriangleVertex(surf,tindex,0)
	 vi2 = bbTriangleVertex(surf,tindex,1)
	 vi3 = bbTriangleVertex(surf,tindex,2)

   ve1=CSGGetVertexRealPosition(curmesh,surf,vi1)
   ve2=CSGGetVertexRealPosition(curmesh,surf,vi2)
   ve3=CSGGetVertexRealPosition(curmesh,surf,vi3)

   t=CSGTriAdd(ve1,ve2,ve3)

	 t.mindex = mindex
	 t.sindex = sindex 
	 t.tindex = tindex
	 t.tarid = -1

   '---------------------------------------

	Next 'Triangles
 Next 'Surfaces
 Next '1-4

 CSGTriRemoveDel

 '--------------------------------------------------------------------------------------

 'Create the reuse objects
 csgmesh[0] = bbCreateMesh()
 surf = bbCreateSurface(csgmesh[0])
 vi1 = bbAddVertex(surf,-1,0,1)
 vi2 = bbAddVertex(surf,1,0,1)
 vi3 = bbAddVertex(surf,1,0,-1)
 bbAddTriangle(surf,vi1,vi2,vi3)

 '----------------------------------------

 csgmesh[1] = bbCreateMesh()
 surf = bbCreateSurface(csgmesh[1])
 vi1 = bbAddVertex(surf,-1,0,1)
 vi2 = bbAddVertex(surf,1,0,1)
 vi3 = bbAddVertex(surf,1,0,-1)
 bbAddTriangle(surf,vi1,vi2,vi3)

 '----------------------------------------

 csgmesh[2] = bbCreateCube()
 bbScaleMesh csgmesh[2],100000*csgscale,0,100000*csgscale '<--- mesh vertices must be in range of Float !

 '----------------------------------------

 'Time To split the a polys
 For t1:CSGTriangleTYPE = EachIn CSGTriangleTYPE_list
 If t1.mindex = 2
	For t2:CSGTriangleTYPE = EachIn CSGTriangleTYPE_list
	If t2.mindex = 1 And t2.tarid <> t1.id
	 If t2.del = 0
	  If CSGTrisIntersect(t1,t2) = 1
	 	 CSGSplit t1,t2
	  EndIf
	 EndIf
	EndIf
	Next
 EndIf
 Next

 '----------------------------------------

 'Now split the b poly's
 For t1:CSGTriangleTYPE = EachIn CSGTriangleTYPE_list
 If t1.mindex = 3
	For t2:CSGTriangleTYPE = EachIn CSGTriangleTYPE_list
	If t2.mindex = 2 And t2.tarid <> t1.id
	 If t2.del = 0
	  If CSGTrisIntersect(t1,t2) = 1
		 CSGSplit t1,t2
	  EndIf
	 EndIf
	EndIf
	Next
 EndIf
 Next

 '----------------------------------------

 'Step 2 of reuse
 surf = bbGetSurface(csgmesh[0],1)
 bbAddTriangle(surf,2,1,0)

 bbFreeEntity csgmesh[1]
 bbFreeEntity csgmesh[2]

 csgpiv = bbCreatePivot()

 '----------------------------------------

 'Setting a flag To Delete all the triangles without normals
 For t1:CSGTriangleTYPE = EachIn CSGTriangleTYPE_list
  If t1.normx = 0.0 And t1.normy = 0.0 And t1.normz = 0.0 'And t1.del = 0
   'DebugLog "NORM=0 : "+t1.normx+" "+t1.normy+" "+t1.normz+" MIndex="+t1.mindex
  CSGTriangleTYPE_list.remove t1 
  t1.Remove()
  EndIf
 Next

 '----------------------------------------

 Local epsilon#=0.000001

 'MeshA
 For t1:CSGTriangleTYPE = EachIn CSGTriangleTYPE_list
 If t1.mindex = 1 And t1.del = 0
  cosangle# = -1
  inter = 0
  intermode = 0 '1 - inside, 2 - shared, 3 - Not inside
  quickdist# = 100000

	For t2:CSGTriangleTYPE = EachIn CSGTriangleTYPE_list
	 If t2.mindex = 4
	  res = CSGRayIntersect(t2,t1)
	  If res = 1
	   intx# = bbPickedX()
	   inty# = bbPickedY()
	   intz# = bbPickedZ()
	   dist# = Sqr((intx-t1.mix)*(intx-t1.mix)+(inty-t1.miy)*(inty-t1.miy)+(intz-t1.miz)*(intz-t1.miz))
	   If dist < quickdist
	    quickdist = dist
	    inter = 1
	    cosangle# = (t1.normx*t2.normx)+(t1.normy*t2.normy)+(t1.normz*t2.normz)
	   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

  Select mode
  Case  2
	 If intermode = 1 Or intermode = 2
	  t1.del = 1
	 EndIf
  Case 1
	 If intermode = 1 Or intermode = 2
	  t1.del = 1
	 EndIf
  Case  3
	 If intermode = 3 Or intermode = 2
	  t1.del = 1
	 EndIf
  End Select

  If t1.del=1 Then 
  CSGTriangleTYPE_list.remove t1 
  t1.Remove()
  EndIf
 EndIf 'Mesh A
 Next 'Tri

 '----------------------------------------

 'MeshB
 For t:CSGTriangleTYPE = EachIn CSGTriangleTYPE_list
 If t.mindex = 2 And t.del = 0
  cosangle = -1
  inter = 0
  intermode = 0'1 - inside, 2 - shared, 3 - Not inside
  quickdist# = 100000
	For tr:CSGTriangleTYPE = EachIn CSGTriangleTYPE_list
	 If tr.mindex = 3
	  res = CSGRayIntersect(tr,t)
	  If res = 1
	   intx# = bbPickedX()
	   inty# = bbPickedY()
	   intz# = bbPickedZ()
	   dist# = Sqr((intx-t.mix)*(intx-t.mix)+(inty-t.miy)*(inty-t.miy)+(intz-t.miz)*(intz-t.miz))
	   If dist < quickdist
	    quickdist = dist
	    inter = 1
	    cosangle# = (t.normx*tr.normx)+(t.normy*tr.normy)+(t.normz*tr.normz)
	   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
	 EndIf
  ElseIf mode = 1
	 If intermode = 1
	  t.del = 1
	 EndIf
  ElseIf mode = 3
	 If intermode = 3
	  t.del = 1
	 EndIf
  EndIf

  If t.del=1 Then 
  CSGTriangleTYPE_list.remove t1 
  t1.Remove()
	EndIf
 EndIf
 Next

 '----------------------------------------

 bbFreeEntity csgpiv
 bbFreeEntity csgmesh[0]

 '----------------------------------------

 'Now Delete the polys that don't belong(loose polys)

 CSGClearlTris 1 
 CSGClearlTris 2

 '----------------------------------------------- New Mesh

 Local mesh=CSGMakeNewMesh()
 
 CSGAddTheTriangles mesh,1

 'Now add Mesh 2 To Mesh 1
 If mode = 2
  CSGAddTheTriangles mesh,2,True 'Flips all the triangles in a mesh
 Else
  CSGAddTheTriangles mesh,2,False
 EndIf

 '----------------------------------------------- Repaint !

 CSGRepaint mesh,mesh1,mesh2

 '----------------------------------------------- Reposition Mesh

 bbPositionMesh   mesh,-ex,-ey,-ez
 bbPositionEntity mesh, ex, ey, ez

 bbRotateMesh mesh,      0,-eyaw,0
 bbRotateMesh mesh,-epitch,    0,0
 bbRotateMesh mesh,      0,    0,-eroll

 bbRotateEntity mesh,epitch,eyaw,eroll

 '-----------------------------------------------

 For t1:CSGTriangleTYPE = EachIn CSGTriangleTYPE_list
CSGTriangleTYPE_list.remove t1
t1.Remove()
Next
 'Free the whole Triangle Collection

 Return mesh

End Function

'###############################################################################################

Function CSGVec:CSGVectorType(x#,y#,z#,u#,v#,w#) 

 'MR 25.01.2003 

 'Simple Return a Vector as Type :-)

 Local ve:CSGVectorType = New CSGVectorType

 ve.x=x#
 ve.y=y#
 ve.z=z#

 ve.u=u#
 ve.v=v#
 ve.w=w#

 Return ve

End Function

'###############################################################################################

Function CSGTriAdd:CSGTriangleTYPE(v1:CSGVectorType,v2:CSGVectorType,v3:CSGVectorType)

 'MR 02.11.2003

 Local newid=0
 Local tr:CSGTriangleTYPE = CSGTriangleTYPE(CSGTriangleTYPE_list.Last())
 If tr<>Null Then newid = tr.id + 1

 '------------------------------------------

  t:CSGTriangleTYPE = New CSGTriangleTYPE

  t.id = newid

 '------------------------------------------ Copy Parameters V1,V2,V3

	t.v1x = v1.x
	t.v1y = v1.y
	t.v1z = v1.z

	t.v2x = v2.x
	t.v2y = v2.y
	t.v2z = v2.z

	t.v3x = v3.x
	t.v3y = v3.y
	t.v3z = v3.z

 '------------------------------------------ Memory UVW For Vertex V1,V2,V3

	t.u1 = v1.u
	t.v1 = v1.v
	t.w1 = v1.w

	t.u2 = v2.u
	t.v2 = v2.v
	t.w2 = v2.w

	t.u3 = v3.u
	t.v3 = v3.v
	t.w3 = v3.w

 '------------------------------------------ Middle

  t.mix = (t.v1x + t.v2x + t.v3x) / 3.0
  t.miy = (t.v1y + t.v2y + t.v3y) / 3.0
  t.miz = (t.v1z + t.v2z + t.v3z) / 3.0

 '------------------------------------------ Normal

  Local ax#,ay#,az#
  Local bx#,by#,bz#

  ax#=t.v2x-t.v1x
  ay#=t.v2y-t.v1y
  az#=t.v2z-t.v1z
	
  bx#=t.v3x-t.v2x
  by#=t.v3y-t.v2y
  bz#=t.v3z-t.v2z

  t.normx=(ay#*bz#)-(az#*by#)
  t.normy=(az#*bx#)-(ax#*bz#)
  t.normz=(ax#*by#)-(ay#*bx#)

  Local normlen# = Sqr((t.normx*t.normx)+(t.normy*t.normy)+(t.normz*t.normz))
  If normlen# > 0.0
   t.normx = t.normx/normlen 
   t.normy = t.normy/normlen 
   t.normz = t.normz/normlen
  Else
   t.del = 1
  EndIf

 '------------------------------------------

 Return t

End Function

'###############################################################################################
	
Function CSGTrisIntersect(t1:CSGTriangleTYPE,t2:CSGTriangleTYPE)

 'MR 19.01.2003

 'If one triangle in another triangle

 Local surf

 surf = bbGetSurface(csgmesh[0],1) 'Dummy Mesh with one triangle :-)

 bbVertexCoords(surf,0,t1.v1x,t1.v1y,t1.v1z)
 bbVertexCoords(surf,1,t1.v2x,t1.v2y,t1.v2z)
 bbVertexCoords(surf,2,t1.v3x,t1.v3y,t1.v3z)

 surf = bbGetSurface(csgmesh[1],1)

 bbVertexCoords(surf,0,t2.v1x,t2.v1y,t2.v1z)
 bbVertexCoords(surf,1,t2.v2x,t2.v2y,t2.v2z)
 bbVertexCoords(surf,2,t2.v3x,t2.v3y,t2.v3z)

 Return bbMeshesIntersect(csgmesh[0],csgmesh[1])

End Function

'###############################################################################################

Function CSGRayIntersect(t1:CSGTriangleTYPE,t2:CSGTriangleTYPE)

 'MR 02.11.2003

 'i think it used To find the triangles that can be deleted

 Local surf = bbGetSurface(csgmesh[0],1) 'Dummy Mesh with one triangle :-)

 bbVertexCoords(surf,0,t1.v1x,t1.v1y,t1.v1z)
 bbVertexCoords(surf,1,t1.v2x,t1.v2y,t1.v2z)
 bbVertexCoords(surf,2,t1.v3x,t1.v3y,t1.v3z)

 Local piv = csgpiv
 bbRotateEntity piv,0,0,0 '!?
 bbPositionEntity(piv,t2.mix  ,t2.miy  ,t2.miz)
 bbAlignToVector (piv,t2.normx,t2.normy,t2.normz,3)
 bbMoveEntity piv,0,0,100000.0*csgscale '<--- !

 bbEntityPickMode csgmesh[0],2

 Local distx# = bbEntityX(piv)-t2.mix
 Local disty# = bbEntityY(piv)-t2.miy
 Local distz# = bbEntityZ(piv)-t2.miz
 Local picked = bbLinePick(t2.mix,t2.miy,t2.miz,distx,disty,distz)

 bbEntityPickMode csgmesh[0],0

 If picked Then
  Return 1
 Else
  Return 0
 EndIf

End Function

'###############################################################################################

Function CSGSplit(t1:CSGTriangleTYPE,t2:CSGTriangleTYPE)

 'MR 02.11.2003

 'If CSGTrisIntersect = True than split it To New triangles

 'now the New triangles are in menory triangle Type collection !

 If t1 = Null Or t2 = Null Then Return 0

'------------------------------------------------------------

 Local newvx#[3]
 Local newvy#[3]
 Local newvz#[3]

 Local newu#[3]
 Local newv#[3]
 Local neww#[3]

 Local v:CSGVectorType 

 Local edge1,edge2,edge3

 Local epsilon#=0.000001 

'------------------------------------------------------------

 Local cube = csgmesh[2]
 bbEntityPickMode cube,2
 bbPositionEntity cube,t1.mix,t1.miy,t1.miz
 bbRotateEntity cube,0,0,0
 bbAlignToVector(cube,t1.normx,t1.normy,t1.normz,2)

'------------------------------------------------------------

 'Edge1 To 2

 distx# = t2.v1x-t2.v2x
 disty# = t2.v1y-t2.v2y
 distz# = t2.v1z-t2.v2z

 picked = bbLinePick(t2.v2x,t2.v2y,t2.v2z,distx,disty,distz)
 If picked = cube
  newvx[1] = bbPickedX()
  newvy[1] = bbPickedY()
  newvz[1] = bbPickedZ()

  v=CSGPickedUVW(t2)

  newu[1]=v.u
  newv[1]=v.v
  neww[1]=v.w
 
  distx# = newvx[1] - t2.v2x
  disty# = newvy[1] - t2.v2y
  distz# = newvz[1] - t2.v2z
  cdist# = Sqr(distx*distx + disty*disty + distz*distz)
  If cdist <= epsilon
   edge1 = False
  Else
   edge1 = True
  EndIf

 EndIf

'------------------------------------------------------------

 'Edge2 To 3

 distx# = t2.v2x-t2.v3x
 disty# = t2.v2y-t2.v3y
 distz# = t2.v2z-t2.v3z

 picked = bbLinePick(t2.v3x,t2.v3y,t2.v3z,distx,disty,distz)
 If picked = cube
  newvx[2] = bbPickedX()
  newvy[2] = bbPickedY()
  newvz[2] = bbPickedZ()

  v=CSGPickedUVW(t2)

  newu[2]=v.u
  newv[2]=v.v
  neww[2]=v.w

  distx# = newvx[2] - t2.v3x
  disty# = newvy[2] - t2.v3y
  distz# = newvz[2] - t2.v3z
  cdist# = Sqr(distx*distx + disty*disty + distz*distz)
  If cdist <= epsilon
   edge2 = False
  Else
   edge2 = True
  EndIf

 EndIf

'------------------------------------------------------------

 'Edge3 To 1

 distx# = t2.v3x-t2.v1x
 disty# = t2.v3y-t2.v1y
 distz# = t2.v3z-t2.v1z

 picked = bbLinePick(t2.v1x,t2.v1y,t2.v1z,distx,disty,distz)
 If picked = cube
  newvx[3] = bbPickedX()
  newvy[3] = bbPickedY()
  newvz[3] = bbPickedZ()

  v=CSGPickedUVW(t2)

  newu[3]=v.u
  newv[3]=v.v
  neww[3]=v.w

  distx# = newvx[3] - t2.v1x
  disty# = newvy[3] - t2.v1y
  distz# = newvz[3] - t2.v1z
  cdist# = Sqr(distx*distx + disty*disty + distz*distz)
  If cdist <= epsilon
   edge3 = False
  Else
   edge3 = True
  EndIf

 EndIf

'------------------------------------------------------------

 bbEntityPickMode cube,0

 If edge1=0 And edge2=0 And edge3=0 Then Return 0

'------------------------------------------------------------

 Local v1:CSGVectorType = New CSGVectorType
 Local v2:CSGVectorType = New CSGVectorType
 Local v3:CSGVectorType = New CSGVectorType
 Local v4:CSGVectorType = New CSGVectorType
 Local v5:CSGVectorType = New CSGVectorType

 Local mindex = t2.mindex
 Local sindex = t2.sindex
 Local tm:CSGTriangleTYPE

'------------------------------------------------------------

 If edge1 And edge2

  t2.del = 1

  v1 = CSGVec(t2.v1x,t2.v1y,t2.v1z,t2.u1,t2.v1,t2.w1)
  v2 = CSGVec(newvx[1],newvy[1],newvz[1],newu[1],newv[1],neww[1])
  v3 = CSGVec(t2.v2x,t2.v2y,t2.v2z,t2.u2,t2.v2,t2.w2)
  v4 = CSGVec(newvx[2],newvy[2],newvz[2],newu[2],newv[2],neww[2])
  v5 = CSGVec(t2.v3x,t2.v3y,t2.v3z,t2.u3,t2.v3,t2.w3)

  tm = CSGTriAdd(v1,v2,v5)
  tm.mindex= mindex
  tm.sindex= sindex
  tm.tarid = t1.id

  tm = CSGTriAdd(v2,v4,v5)
  tm.mindex= mindex
  tm.sindex= sindex
  tm.tarid = t1.id

  tm = CSGTriAdd(v2,v3,v4)
  tm.mindex= mindex
  tm.sindex= sindex
  tm.tarid = t1.id

 ElseIf edge1 And edge3

  t2.del = 1

  v1 = CSGVec(t2.v1x,t2.v1y,t2.v1z,t2.u1,t2.v1,t2.w1)
  v2 = CSGVec(newvx[1],newvy[1],newvz[1],newu[1],newv[1],neww[1])
  v3 = CSGVec(t2.v2x,t2.v2y,t2.v2z,t2.u2,t2.v2,t2.w2)
  v4 = CSGVec(t2.v3x,t2.v3y,t2.v3z,t2.u3,t2.v3,t2.w3)
  v5 = CSGVec(newvx[3],newvy[3],newvz[3],newu[3],newv[3],neww[3])

  tm = CSGTriAdd(v1,v2,v5) '1,2,5
  tm.mindex= mindex
  tm.sindex= sindex
  tm.tarid = t1.id

  tm = CSGTriAdd(v2,v4,v5)
  tm.mindex= mindex
  tm.sindex= sindex
  tm.tarid = t1.id

  tm = CSGTriAdd(v2,v3,v4)
  tm.mindex= mindex
  tm.sindex= sindex
  tm.tarid = t1.id

 ElseIf edge2 And edge3

  t2.del = 1

  v1 = CSGVec(t2.v1x,t2.v1y,t2.v1z,t2.u1,t2.v1,t2.w1)
  v2 = CSGVec(t2.v2x,t2.v2y,t2.v2z,t2.u2,t2.v2,t2.w2)
  v3 = CSGVec(newvx[2],newvy[2],newvz[2],newu[2],newv[2],neww[2])
  v4 = CSGVec(t2.v3x,t2.v3y,t2.v3z,t2.u3,t2.v3,t2.w3)
  v5 = CSGVec(newvx[3],newvy[3],newvz[3],newu[3],newv[3],neww[3])

  tm = CSGTriAdd(v1,v2,v5)
  tm.mindex= mindex
  tm.sindex= sindex
  tm.tarid = t1.id

  tm = CSGTriAdd(v2,v3,v5)
  tm.mindex= mindex
  tm.sindex= sindex
  tm.tarid = t1.id

  tm = CSGTriAdd(v3,v4,v5)
  tm.mindex= mindex
  tm.sindex= sindex
  tm.tarid = t1.id

 ElseIf edge2

  t2.del = 1

  v1 = CSGVec(t2.v1x,t2.v1y,t2.v1z,t2.u1,t2.v1,t2.w1)
  v2 = CSGVec(t2.v2x,t2.v2y,t2.v2z,t2.u2,t2.v2,t2.w2)
  v3 = CSGVec(newvx[2],newvy[2],newvz[2],newu[2],newv[2],neww[2])
  v4 = CSGVec(t2.v3x,t2.v3y,t2.v3z,t2.u3,t2.v3,t2.w3)

  tm = CSGTriAdd(v1,v2,v3)
  tm.mindex= mindex
  tm.sindex= sindex
  tm.tarid = t1.id

  tm = CSGTriAdd(v1,v3,v4)
  tm.mindex= mindex
  tm.sindex= sindex
  tm.tarid = t1.id

 ElseIf edge1

  t2.del = 1

  v1 = CSGVec(t2.v1x,t2.v1y,t2.v1z,t2.u1,t2.v1,t2.w1)
  v2 = CSGVec(newvx[1],newvy[1],newvz[1],newu[1],newv[1],neww[1]) 
  v3 = CSGVec(t2.v2x,t2.v2y,t2.v2z,t2.u2,t2.v2,t2.w2)
  v4 = CSGVec(t2.v3x,t2.v3y,t2.v3z,t2.u3,t2.v3,t2.w3)

  tm = CSGTriAdd(v1,v2,v4)
  tm.mindex= mindex
  tm.sindex= sindex
  tm.tarid = t1.id

  tm = CSGTriAdd(v2,v3,v4)
  tm.mindex= mindex
  tm.sindex= sindex
  tm.tarid = t1.id

 ElseIf edge3

  t2.del = 1

  v1 = CSGVec(t2.v1x,t2.v1y,t2.v1z,t2.u1,t2.v1,t2.w1)
  v2 = CSGVec(t2.v2x,t2.v2y,t2.v2z,t2.u2,t2.v2,t2.w2)
  v3 = CSGVec(t2.v3x,t2.v3y,t2.v3z,t2.u3,t2.v3,t2.w3)
  v4 = CSGVec(newvx[3],newvy[3],newvz[3],newu[3],newv[3],neww[3])

  tm = CSGTriAdd(v1,v2,v4)
  tm.mindex= mindex
  tm.sindex= sindex
  tm.tarid = t1.id

  tm = CSGTriAdd(v2,v3,v4)
  tm.mindex= mindex
  tm.sindex= sindex
  tm.tarid = t1.id

 EndIf

 If t2.del=1 Then
CSGTriangleTYPE_list.remove t2
t2.Remove()
EndIf

End Function

'###############################################################################################

Function CSGTriRemoveDel()

 'MR 19.01.2003

 '-----------------------------------------------

 For t:CSGTriangleTYPE = EachIn CSGTriangleTYPE_list
  If t.del=1 Then 
CSGTriangleTYPE_list.remove t
t.Remove()
  
EndIf
 Next

End Function

'###############################################################################################

Function CSGMakeNewMesh()

 'MR 26.01.2003

 '----------------------------------------------- New Mesh

 Local m=bbCreateMesh()

 '----------------------------------------------- Find Max Surfaces For Mesh 1

 Local smax1=0

 For t:CSGTriangleTYPE = EachIn CSGTriangleTYPE_list
  If t.mindex=1 Then
   If t.sindex>smax1 Then smax1=t.sindex  
  EndIf
 Next

 '----------------------------------------------- Find Max Surfaces For Mesh 2

 Local smax2=0

 For t:CSGTriangleTYPE = EachIn CSGTriangleTYPE_list
  If t.mindex=2 Then
   If t.sindex>smax2 Then smax2=t.sindex  
  EndIf
 Next

 '----------------------------------------------- Add Max Surface Index from Mesh 1 To Mesh 2

 For t:CSGTriangleTYPE = EachIn CSGTriangleTYPE_list
  If t.mindex=2 Then
   t.sindex=t.sindex+smax1
  EndIf
 Next

 '----------------------------------------------- Create all Surfaces

 Local smax=smax1+smax2 'all needed surfaces

 Local si

 Local surf

 For si=1 To smax

  surf=bbCreateSurface(m)
 
 Next

 '-----------------------------------------------

 Return m

End Function

'###############################################################################################

Function CSGAddTheTriangles(m,mindex,FlipTriangles=0)

 'MR 02.11.2003

 '----------------------------------------------- Bring Triangle To Surface

 Local v1,v2,v3 'VertexIndex

 Local surf=0

 Local si

 '-----------------------------------------------

 For si=1 To bbCountSurfaces(m)

  For t:CSGTriangleTYPE = EachIn CSGTriangleTYPE_list
   If t.del=0 And t.mindex=mindex And t.sindex=si Then

    surf=bbGetSurface(m,si)  

    v1=bbAddVertex(surf,t.v1x,t.v1y,t.v1z)
    v2=bbAddVertex(surf,t.v2x,t.v2y,t.v2z)
    v3=bbAddVertex(surf,t.v3x,t.v3y,t.v3z)

    bbVertexNormal surf,v1,t.normx,t.normy,t.normz 
    bbVertexNormal surf,v2,t.normx,t.normy,t.normz 
    bbVertexNormal surf,v3,t.normx,t.normy,t.normz 

    bbVertexTexCoords surf,v1,t.u1,t.v1,t.w1 'Set UV Coords !
    bbVertexTexCoords surf,v2,t.u2,t.v2,t.w2 
    bbVertexTexCoords surf,v3,t.u3,t.v3,t.w3 

    If FlipTriangles=0 Then
     bbAddTriangle surf,v1,v2,v3
    Else
     bbAddTriangle surf,v3,v2,v1
    EndIf

    CSGTriangleTYPE_list.remove t
    t.Remove()
 'Remove the Triangle from Collection !

   EndIf  
  Next

 Next 'All Surfaces

 '-----------------------------------------------

 bbUpdateNormals m

End Function

'###############################################################################################

Function CSGRepaint(meshnew,mesh1,mesh2)

 'MR 02.11.2003

 'Repaint all Surfaces :-)

 '----------------------------------------------------------------------------------------------

  Local cc1=0 'New SurfaceCount !

  Local c1

  'Paint New Surfaces from Mesh A  

  If bbCountSurfaces (mesh1)=>1 Then 
   For c1=1 To bbCountSurfaces(mesh1)
    cc1=cc1+1
   
    If bbCountSurfaces(meshnew)=>cc1 Then 
     bbPaintSurface bbGetSurface(meshnew,cc1),bbGetSurfaceBrush(bbGetSurface(mesh1,c1))
    EndIf 

   Next
  EndIf 'bbCountSurfaces=>1

 '----------------------------------------------------------------------------------------------

  'Paint New Surfaces from Mesh B  

  If bbCountSurfaces(mesh2)=>1 Then 
   For c1=1 To bbCountSurfaces(mesh2)
    cc1=cc1+1
   
    If bbCountSurfaces(meshnew)=>cc1 Then 
     bbPaintSurface bbGetSurface(meshnew,cc1),bbGetSurfaceBrush(bbGetSurface(mesh2,c1))
    EndIf 

   Next
  EndIf 'bbCountSurfaces=>1

 '----------------------------------------------------------------------------------------------

End Function

'###############################################################################################

Function CSGClearLTris(mindex)

 'MR 26.01.2003

 'Clears the triangles that have no partners
 Local epsilon#=0.000001 

 Local count=0
 Local full
 Local car

 Local distx#
 Local disty#
 Local distz#
 Local cdist#

 Local vax#
 Local vay#
 Local vaz#

 Local vbx#
 Local vby#
 Local vbz#

 For t:CSGTriangleTYPE = EachIn CSGTriangleTYPE_list
  If t.mindex = mindex And t.del = 0
   count=0
   For full = 0 To 2
    Select full
    Case 0
     vax#=t.v1x
     vay#=t.v1y
     vaz#=t.v1z
    Case 1
     vax#=t.v2x
     vay#=t.v2y
     vaz#=t.v2z
    Case 2
     vax#=t.v3x
     vay#=t.v3y
     vaz#=t.v3z
    End Select

 	  For tom:CSGTriangleTYPE = EachIn CSGTriangleTYPE_list
 	   If t.id<>tom.id And tom.del = 0 And tom.mindex = mindex
	    cdist = 0
	    For car = 0 To 2
       Select car
       Case 0
        vbx#=tom.v1x
        vby#=tom.v1y
        vbz#=tom.v1z
       Case 1
        vbx#=tom.v2x
        vby#=tom.v2y
        vbz#=tom.v2z
       Case 2
        vbx#=tom.v3x
        vby#=tom.v3y
        vbz#=tom.v3z
       End Select
		   distx# = vbx - vax
		   disty# = vby - vay
		   distz# = vbz - vaz 
		   cdist# = Sqr(distx*distx + disty*disty + distz*distz)
		   If cdist <= epsilon Then Exit
	    Next
 	    If cdist >= 0.0 Then 
		count = count + 1
		Exit
	    EndIf
	   EndIf
	  Next
   Next

   If count < 3
    CSGTriangleTYPE_list.remove t
	t.Remove()
   EndIf
  EndIf
 Next

End Function

'############################################################################################################

Function CSGGetVertexRealPosition:CSGVectorType(bbEntity,surf,vindex)

 Local pivot1=bbCreatePivot()
 Local pivot2=bbCreatePivot(pivot1)

 Local vreal:CSGVectorType =New CSGVectorType

 bbPositionEntity pivot1,0,0,0
 bbPositionEntity pivot2,bbVertexX(surf,vindex),bbVertexY(surf,vindex),bbVertexZ(surf,vindex)
 bbRotateEntity pivot1,bbEntityPitch(bbEntity,True),bbEntityYaw(bbEntity,True),bbEntityRoll(bbEntity,True)
 
 vreal.x=bbEntityX(pivot2,True)+bbEntityX(bbEntity,True)
 vreal.y=bbEntityY(pivot2,True)+bbEntityY(bbEntity,True)
 vreal.z=bbEntityZ(pivot2,True)+bbEntityZ(bbEntity,True)

 vreal.u=bbVertexU(surf,vindex)
 vreal.v=bbVertexV(surf,vindex)
 vreal.w=bbVertexW(surf,vindex)

 bbFreeEntity pivot2
 bbFreeEntity pivot1

 Return vreal

End Function

'#################################################################################################### UVW

Function CSGPickedUVW:CSGVectorType(t2:CSGTriangleTYPE)

  'MR 25.01.2003

  Local ve:CSGVectorType = New CSGVectorType

  Local px#=bbPickedX()
  Local py#=bbPickedY()
  Local pz#=bbPickedZ() 

  Local pnx#=t2.normx
  Local pny#=t2.normy
  Local pnz#=t2.normz

  'DebugLog "Picked XYZ "+px+" "+py+" "+pz
		
		' Select which component of xyz coordinates To ignore
		Local coords = 3

		If Abs(PNX) > Abs(PNY)
			If Abs(PNX)>Abs(PNZ) Then coords = 1
		Else
			If Abs(PNY)>Abs(PNZ) Then coords = 2
		EndIf

    'DebugLog "coords "+coords
		
		Local a0#,a1#,b0#,b1#,c0#,c1#
		
		If (coords = 3)

 		  'xy components

			' edge 1
			a0# = t2.v2x - t2.v1x
			a1# = t2.v2y - t2.v1y
		
			' edge 2
			b0# = t2.v3x - t2.v1x
			b1# = t2.v3y - t2.v1y

			' picked offset from triangle vertex 1
			c0# = px - t2.v1x
			c1# = py - t2.v1y
		Else		
			If (coords = 2)
				' xz components

				' edge 1
				a0# = t2.v2x - t2.v1x
				a1# = t2.v2z - t2.v1z
		
				' edge 2
				b0# = t2.v3x - t2.v1x
				b1# = t2.v3z - t2.v1z

				' picked offset from triangle vertex 1
				c0# = px - t2.v1x
				c1# = pz - t2.v1z
			Else
				' yz components

				' edge 1
				a0# = t2.v2y - t2.v1y
				a1# = t2.v2z - t2.v1z
		
				' edge 2
				b0# = t2.v3y - t2.v1y
				b1# = t2.v3z - t2.v1z

				' picked offset from triangle vertex 1
				c0# = py - t2.v1y
				c1# = pz - t2.v1z
			End If
		End If
						
		'
		' u And v are offsets from vertex 0 along edge 0 And edge 1
		' using these it is possible To calculate the Texture UVW coordinates
		' of the picked XYZ location
		'
		' a0*u + b0*v = c0
		' a1*u + b1*v = c1
		'
		' solve equation (standard equation with 2 unknown quantities)
		' check a math book To see why the following is True
		'
		Local u# = (c0*b1 - b0*c1) / (a0*b1 - b0*a1)
		Local v# = (a0*c1 - c0*a1) / (a0*b1 - b0*a1)

    'DebugLog "U "+u+" V "+v
				
		' Calculate picked uvw's 
		ve.u = (t2.u1 + ((t2.u2 - t2.u1) * u) + ((t2.u3 - t2.u1) * v))
		ve.v = (t2.v1 + ((t2.v2 - t2.v1) * u) + ((t2.v3 - t2.v1) * v))
		ve.w = (t2.w1 + ((t2.w2 - t2.w1) * u) + ((t2.w3 - t2.w1) * v))
		
    'DebugLog "U "+ve.u+" V "+ve.v

 Return ve
		
End Function

'###############################################################################################

'Function CSGExample()

 'MR 02.11.2003

' AppTitle "CSG Test"

' Graphics3D 640,480

 '---------------------------------------------------------------------------------------

' Local texture=LoadTexture("ch1.bmp")
' Local brush=CreateBrush(255,255,255)

' BrushTexture brush,texture

 'cube =CSGAddMyMeshCubeX(   0,0,0,0,20, 4,20,1,1,1,brush,brush,brush,brush,brush,brush)
 'cube =CSGAddMyMeshCubeX(cube,0,0,0,10,10,10,1,1,1,brush,brush,brush,brush,brush,brush)

' cube = bbCreateCube()
' bbScaleMesh cube,10,2,10
' For s=1 To bbCountSurfaces(cube)
'  bbPaintSurface bbGetSurface(cube,s),brush
' Next 
' bbEntityFX cube,16

 'TurnbbEntity cube,90,0,0
 'bbMoveEntity cube,0,5,0

 '---------------------------------------------------------------------------------------

' Local tex2=CreateTexture(64,64)
' SetBuffer TextureBuffer(tex2) 
' Color 128,0,0
' Rect 0,0,64,64 
' Color 255,0,0
' Rect 0,0,32,32
' Rect 32,32,32,32
' SetBuffer BackBuffer()
' Local br2=CreateBrush()
' BrushTexture br2,tex2
' ScaleTexture tex2,.25,.25

 'cube2 = CreateSphere(8)
 'cube2 = bbCreateCube()
' cube2 = CreateCylinder(16)
 
' bbScaleMesh cube2,6,6,6
' For s=1 To bbCountSurfaces(cube2)
'  bbPaintSurface bbGetSurface(cube2,s),br2
' Next 

 '---------------------------------------------------------------------------------------

' cam = CreateCamera()
' bbMoveEntity cam,0,10,-20
' PointbbEntity cam,cube2
' CameraClsColor cam,0,0,80 
' CameraRange cam,1,2000
'
 '---------------------------------------------------------------------------------------

' Local light=CreateLight()
' TurnbbEntity light,45,1,0
' LightRange light,50
' bbPositionEntity light,0,50,-50

 '---------------------------------------------------------------------------------------

' bbUpdateNormals cube
' bbUpdateNormals cube2
' bbEntityAlpha cube2,.5

 '---------------------------------------------------------------------------------------

' Local wire=0
' Local Mode=2

' Color 255,255,255
' While Not KeyHit(1) 'ESC

'  If KeyHit(2) Then Mode=1 '1
'  If KeyHit(3) Then Mode=2 '2
'  If KeyHit(4) Then Mode=3 '3

'  If KeyDown(205) Then TranslatebbEntity cube2,.1,0,0
'  If KeyDown(203) Then TranslatebbEntity cube2,-.1,0,0

'  If KeyDown(30)  Then TranslatebbEntity cube2,0,0,.1
'  If KeyDown(44)  Then TranslatebbEntity cube2,0,0,-.1 'Y German

'  If KeyDown(200) Then TranslatebbEntity cube2,0,.1,0
'  If KeyDown(208) Then TranslatebbEntity cube2,0,-.1,0

'  If KeyDown(37) Then 'K
'   'ClearSurface bbGetSurface(cube,7),True,True 'TEST
'  EndIf

'  If KeyDown(18) Then 'E
'   TurnbbEntity cube,-1,0,0   
'  EndIf

'  If KeyDown(19) Then 'R
'   TurnbbEntity cube,0,-1,0   
'  EndIf

'  If KeyDown(20) Then 'T
'   TurnbbEntity cube,0,0,-1   
'  EndIf

'  If KeyHit(21) Then 'Z    German
'   TurnbbEntity cube2,-45,0,0   
'  EndIf

'  If KeyHit(31) Then 'S = Screenshot
'   SaveBuffer FrontBuffer(),"screenshot.bmp"
'  EndIf

'  If KeyHit(17) 'W
'   wire = 1 - wire
'   WireFrame wire
'  EndIf
 
'  If KeyHit(57) 'Space
'   Cls
'   RenderWorld
'   Text 0,0,"Wait ..."
'   Flip 
'   e = MilliSecs()
'   man = csg(cube,cube2,Mode) '1 Add , 2 Sub , 3 Diff
'   e = MilliSecs() -e
'   bbFreeEntity cube
'   cube = man
'   'PaintbbEntity cube,brush
'   bbEntityFX cube,16
'   FlushKeys
'  EndIf

'  UpdateWorld
'  RenderWorld
'  Text 0,0,"Time: "+e+" ms"
'  Text 0,15*1,"Arrows to Move Left/Right/Up/Down"
'  Text 0,15*2,"A/Z to move Forward and Back"
'  Text 0,15*3,"Tris All : "+TrisRendered()
'  Text 0,15*4,"Tris 1 : "+CSGCountAllTriangles(cube )+" Surfaces : " +bbCountSurfaces(cube)
'  Text 0,15*5,"Tris 2 : "+CSGCountAllTriangles(cube2)
'  Text 0,15*6,"Mode: "+Mode
'  Text 0,15*7,"E,R,T Rotate Obj. 1"
'  Text 0,15*8,"Y Rotate Obj. 2"
'  Text 0,15*9,"S Screenshot"
'  Flip
' Wend

'End Function

'#################################################################################################### 

Function CSGCountAllTriangles(mesh) 'only For example

 'without child bbEntitys

 Local si

 If mesh=0 Then Return 0

 Local c=0

 For si=1 To bbCountSurfaces(mesh)
  c=c+bbCountTriangles(bbGetSurface(mesh,si))
 Next 

 Return c

End Function

'#################################################################################################### 

Function CSGAddMyMeshCubeX(m,x1#,y1#,z1#,x2#,y2#,z2#,cx,cy,cz,br_top,br_bottom,br_left,br_right,br_front,br_back,o_top=1,o_bottom=1,o_left=1,o_right=1,o_front=1,o_back=1)

 'MR 31.10.2002

 'Create a Cube centered

 'm       =bbEntity Handle 0=Create a New one :-)
 'x1,x2   =From X1 To X2
 'cx,cy,cy=Center  
 'br_     =Brush  Handle
 'o_      =Optional 1=Create 0=No Create  
 
  Local w#,h#,d#

 'w#=witdh  (X)
 'h#=height (Y)
 'd#=depth  (Z)

  w#=x2#-x1#
  h#=y2#-y1#
  d#=z2#-z1#

  '--------------------- Center ?

  If cx=1 Then 
   x1=x1-w/2.0
   x2=x2-w/2.0
  EndIf

  If cy=1 Then 
   y1=y1-h/2.0
   y2=y2-h/2.0
  EndIf

  If cz=1 Then 
   z1=z1-d/2.0
   z2=z2-d/2.0
  EndIf

  '-----------------------------

  If m=0 Then
	 m=bbCreateMesh()
  EndIf

  '-----------------------------

	'top face
	If o_top=1 Then 
	 s=bbCreateSurface( m , Br_Top)
	 bbAddVertex s,x1,y2,z2,0,1
	 bbAddVertex s,x2,y2,z2,0,0
	 bbAddVertex s,x2,y2,z1,1,0
	 bbAddVertex s,x1,y2,z1,1,1
	 bbAddTriangle s,0,1,2
	 bbAddTriangle s,0,2,3
  EndIf

	'bottom face	
  If o_bottom=1 Then
	 s=bbCreateSurface( m , Br_Bottom)
	 bbAddVertex s,x1,y1,z1,1,0
	 bbAddVertex s,x2,y1,z1,1,1
	 bbAddVertex s,x2,y1,z2,0,1
	 bbAddVertex s,x1,y1,z2,0,0
	 bbAddTriangle s,0,1,2
	 bbAddTriangle s,0,2,3
  EndIf

	'Left face
  If o_left=1 Then
	 s=bbCreateSurface( m , Br_Left)
	 bbAddVertex s,x1,y2,z2,0,0
	 bbAddVertex s,x1,y2,z1,1,0
	 bbAddVertex s,x1,y1,z1,1,1
	 bbAddVertex s,x1,y1,z2,0,1
	 bbAddTriangle s,0,1,2
	 bbAddTriangle s,0,2,3
  EndIf 

	'Right face
  If o_right=1 Then
	 s=bbCreateSurface( m , Br_Right)
	 bbAddVertex s,x2,y2,z1,0,0
	 bbAddVertex s,x2,y2,z2,1,0
	 bbAddVertex s,x2,y1,z2,1,1
	 bbAddVertex s,x2,y1,z1,0,1
	 bbAddTriangle s,0,1,2
	 bbAddTriangle s,0,2,3
  EndIf

	'front face
  If o_front=1 Then
	 s=bbCreateSurface( m , Br_Front)
	 bbAddVertex s,x1,y2,z1,0,0
	 bbAddVertex s,x2,y2,z1,1,0
	 bbAddVertex s,x2,y1,z1,1,1
	 bbAddVertex s,x1,y1,z1,0,1
 	 bbAddTriangle s,0,1,2
     bbAddTriangle s,0,2,3
  EndIf

	'back face
  If o_back=1 Then
	 s=bbCreateSurface( m , Br_Back)
	 bbAddVertex s,x2,y2,z2,0,0
	 bbAddVertex s,x1,y2,z2,1,0
	 bbAddVertex s,x1,y1,z2,1,1
	 bbAddVertex s,x2,y1,z2,0,1
	 bbAddTriangle s,0,1,2
	 bbAddTriangle s,0,2,3
  EndIf

  bbUpdateNormals m
	  
  'bbEntityPickMode m,2 'Poly

  Return m  

End Function

'####################################################################################################

Comments

None.

Code Archives Forum