Code archives/3D Graphics - Mesh/CSG Functions another edition
This code has been declared by its author to be Public Domain code.
Download source code
| |||||
Rewritten Code Example from David Dawkins(Starfox) Big thanks to him !!! Now it don't loose UV coords and calculate new UVs !!! And the output Mesh have multiple Surfaces :-) 02.11.2003 Repaint the new target Mesh with use of GetSurfaceBrush BB =>V1.85 Only you need a test texture , look in CSGExample Function ![]() | |||||
; 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 Entity 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 ;----------------------- Type CSGVectorType Field x# Field y# Field z# Field u# ;Texture Coords ! Field v# Field w# End Type ;----------------------- Type CSGTriangleTYPE 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=EntityX(mesh1,1) ey=EntityY(mesh1,1) ez=EntityZ(mesh1,1) Local epitch#,eyaw#,eroll# epitch=EntityPitch(mesh1,1) eyaw =EntityYaw (mesh1,1) eroll =EntityRoll (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 CountSurfaces(curmesh) ;DebugLog "sindex "+sindex surf = GetSurface(curmesh,sindex) For tindex = 0 To CountTriangles(surf)-1 ;--------------------------------------- vi1 = TriangleVertex(surf,tindex,0) vi2 = TriangleVertex(surf,tindex,1) vi3 = TriangleVertex(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] = CreateMesh() surf = CreateSurface(csgmesh[0]) vi1 = AddVertex(surf,-1,0,1) vi2 = AddVertex(surf,1,0,1) vi3 = AddVertex(surf,1,0,-1) AddTriangle(surf,vi1,vi2,vi3) ;---------------------------------------- csgmesh[1] = CreateMesh() surf = CreateSurface(csgmesh[1]) vi1 = AddVertex(surf,-1,0,1) vi2 = AddVertex(surf,1,0,1) vi3 = AddVertex(surf,1,0,-1) AddTriangle(surf,vi1,vi2,vi3) ;---------------------------------------- csgmesh[2] = CreateCube() ScaleMesh csgmesh[2],100000*csgscale,0,100000*csgscale ;<--- mesh vertices must be in range of float ! ;---------------------------------------- ;Time to split the a polys For t1.CSGTriangleTYPE = Each CSGTriangleTYPE If t1\mindex = 2 For t2.CSGTriangleTYPE = Each CSGTriangleTYPE 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 = Each CSGTriangleTYPE If t1\mindex = 3 For t2.CSGTriangleTYPE = Each CSGTriangleTYPE 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 = GetSurface(csgmesh[0],1) AddTriangle(surf,2,1,0) FreeEntity csgmesh[1] FreeEntity csgmesh[2] csgpiv = CreatePivot() ;---------------------------------------- ;Setting a flag to delete all the triangles without normals For t1.CSGTriangleTYPE = Each CSGTriangleTYPE 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 Delete t1 EndIf Next ;---------------------------------------- Local epsilon#=0.000001 ;MeshA For t1.CSGTriangleTYPE = Each CSGTriangleTYPE 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 = Each CSGTriangleTYPE If t2\mindex = 4 res = CSGRayIntersect(t2,t1) If res = 1 intx# = PickedX() inty# = PickedY() intz# = PickedZ() 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 Delete t1 EndIf ;Mesh A Next ;Tri ;---------------------------------------- ;MeshB For t.CSGTriangleTYPE = Each CSGTriangleTYPE 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 = Each CSGTriangleTYPE If tr\mindex = 3 res = CSGRayIntersect(tr,t) If res = 1 intx# = PickedX() inty# = PickedY() intz# = PickedZ() 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 Delete t EndIf Next ;---------------------------------------- FreeEntity csgpiv FreeEntity 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 PositionMesh mesh,-ex,-ey,-ez PositionEntity mesh, ex, ey, ez RotateMesh mesh, 0,-eyaw,0 RotateMesh mesh,-epitch, 0,0 RotateMesh mesh, 0, 0,-eroll RotateEntity mesh,epitch,eyaw,eroll ;----------------------------------------------- Delete Each CSGTriangleTYPE ;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 = Last CSGTriangleTYPE 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 = GetSurface(csgmesh[0],1) ;Dummy Mesh with one triangle :-) VertexCoords(surf,0,t1\v1x,t1\v1y,t1\v1z) VertexCoords(surf,1,t1\v2x,t1\v2y,t1\v2z) VertexCoords(surf,2,t1\v3x,t1\v3y,t1\v3z) surf = GetSurface(csgmesh[1],1) VertexCoords(surf,0,t2\v1x,t2\v1y,t2\v1z) VertexCoords(surf,1,t2\v2x,t2\v2y,t2\v2z) VertexCoords(surf,2,t2\v3x,t2\v3y,t2\v3z) Return MeshesIntersect(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 = GetSurface(csgmesh[0],1) ;Dummy Mesh with one triangle :-) VertexCoords(surf,0,t1\v1x,t1\v1y,t1\v1z) VertexCoords(surf,1,t1\v2x,t1\v2y,t1\v2z) VertexCoords(surf,2,t1\v3x,t1\v3y,t1\v3z) Local piv = csgpiv RotateEntity piv,0,0,0 ;!? PositionEntity(piv,t2\mix ,t2\miy ,t2\miz) AlignToVector (piv,t2\normx,t2\normy,t2\normz,3) MoveEntity piv,0,0,100000.0*csgscale ;<--- ! EntityPickMode csgmesh[0],2 Local distx# = EntityX(piv)-t2\mix Local disty# = EntityY(piv)-t2\miy Local distz# = EntityZ(piv)-t2\miz Local picked = LinePick(t2\mix,t2\miy,t2\miz,distx,disty,distz) EntityPickMode 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] EntityPickMode cube,2 PositionEntity cube,t1\mix,t1\miy,t1\miz RotateEntity cube,0,0,0 AlignToVector(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 = LinePick(t2\v2x,t2\v2y,t2\v2z,distx,disty,distz) If picked = cube newvx[1] = PickedX() newvy[1] = PickedY() newvz[1] = PickedZ() 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 = LinePick(t2\v3x,t2\v3y,t2\v3z,distx,disty,distz) If picked = cube newvx[2] = PickedX() newvy[2] = PickedY() newvz[2] = PickedZ() 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 = LinePick(t2\v1x,t2\v1y,t2\v1z,distx,disty,distz) If picked = cube newvx[3] = PickedX() newvy[3] = PickedY() newvz[3] = PickedZ() 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 ;------------------------------------------------------------ EntityPickMode 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 Delete t2 End Function ;############################################################################################### Function CSGTriRemoveDel() ;MR 19.01.2003 ;----------------------------------------------- For t.CSGTriangleTYPE = Each CSGTriangleTYPE If t\del=1 Then Delete t Next End Function ;############################################################################################### Function CSGMakeNewMesh() ;MR 26.01.2003 ;----------------------------------------------- New Mesh Local m=CreateMesh() ;----------------------------------------------- Find Max Surfaces for Mesh 1 Local smax1=0 For t.CSGTriangleTYPE = Each CSGTriangleTYPE 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 = Each CSGTriangleTYPE 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 = Each CSGTriangleTYPE 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=CreateSurface(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 CountSurfaces(m) For t.CSGTriangleTYPE = Each CSGTriangleTYPE If t\del=0 And t\mindex=mindex And t\sindex=si Then surf=GetSurface(m,si) v1=AddVertex(surf,t\v1x,t\v1y,t\v1z) v2=AddVertex(surf,t\v2x,t\v2y,t\v2z) v3=AddVertex(surf,t\v3x,t\v3y,t\v3z) VertexNormal surf,v1,t\normx,t\normy,t\normz VertexNormal surf,v2,t\normx,t\normy,t\normz VertexNormal surf,v3,t\normx,t\normy,t\normz VertexTexCoords surf,v1,t\u1,t\v1,t\w1 ;Set UV Coords ! VertexTexCoords surf,v2,t\u2,t\v2,t\w2 VertexTexCoords surf,v3,t\u3,t\v3,t\w3 If FlipTriangles=0 Then AddTriangle surf,v1,v2,v3 Else AddTriangle surf,v3,v2,v1 EndIf Delete t ;Remove the Triangle from Collection ! EndIf Next Next ;All Surfaces ;----------------------------------------------- UpdateNormals 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 CountSurfaces (mesh1)=>1 Then For c1=1 To CountSurfaces(mesh1) cc1=cc1+1 If CountSurfaces(meshnew)=>cc1 Then PaintSurface GetSurface(meshnew,cc1),GetSurfaceBrush(GetSurface(mesh1,c1)) EndIf Next EndIf ;CountSurfaces=>1 ;---------------------------------------------------------------------------------------------- ;Paint New Surfaces from Mesh B If CountSurfaces(mesh2)=>1 Then For c1=1 To CountSurfaces(mesh2) cc1=cc1+1 If CountSurfaces(meshnew)=>cc1 Then PaintSurface GetSurface(meshnew,cc1),GetSurfaceBrush(GetSurface(mesh2,c1)) EndIf Next EndIf ;CountSurfaces=>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 = Each CSGTriangleTYPE 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 = Each CSGTriangleTYPE 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 Next Next If count < 3 Delete t EndIf EndIf Next End Function ;############################################################################################################ Function CSGGetVertexRealPosition.CSGVectorType(entity,surf,vindex) Local pivot1=CreatePivot() Local pivot2=CreatePivot(pivot1) Local vreal.CSGVectorType =New CSGVectorType PositionEntity pivot1,0,0,0 PositionEntity pivot2,VertexX(surf,vindex),VertexY(surf,vindex),VertexZ(surf,vindex) RotateEntity pivot1,EntityPitch(entity,True),EntityYaw(entity,True),EntityRoll(entity,True) vreal\x=EntityX(pivot2,True)+EntityX(entity,True) vreal\y=EntityY(pivot2,True)+EntityY(entity,True) vreal\z=EntityZ(pivot2,True)+EntityZ(entity,True) vreal\u=VertexU(surf,vindex) vreal\v=VertexV(surf,vindex) vreal\w=VertexW(surf,vindex) FreeEntity pivot2 FreeEntity pivot1 Return vreal End Function ;#################################################################################################### UVW Function CSGPickedUVW.CSGVectorType(t2.CSGTriangleTYPE) ;MR 25.01.2003 Local ve.CSGVectorType = New CSGVectorType Local px#=PickedX() Local py#=PickedY() Local pz#=PickedZ() 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 = CreateCube() ScaleMesh cube,10,2,10 For s=1 To CountSurfaces(cube) PaintSurface GetSurface(cube,s),brush Next EntityFX cube,16 ;TurnEntity cube,90,0,0 ;MoveEntity 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 = CreateCube() cube2 = CreateCylinder(16) ScaleMesh cube2,6,6,6 For s=1 To CountSurfaces(cube2) PaintSurface GetSurface(cube2,s),br2 Next ;--------------------------------------------------------------------------------------- cam = CreateCamera() MoveEntity cam,0,10,-20 PointEntity cam,cube2 CameraClsColor cam,0,0,80 CameraRange cam,1,2000 ;--------------------------------------------------------------------------------------- Local light=CreateLight() TurnEntity light,45,1,0 LightRange light,50 PositionEntity light,0,50,-50 ;--------------------------------------------------------------------------------------- UpdateNormals cube UpdateNormals cube2 EntityAlpha 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 TranslateEntity cube2,.1,0,0 If KeyDown(203) Then TranslateEntity cube2,-.1,0,0 If KeyDown(30) Then TranslateEntity cube2,0,0,.1 If KeyDown(44) Then TranslateEntity cube2,0,0,-.1 ;Y German If KeyDown(200) Then TranslateEntity cube2,0,.1,0 If KeyDown(208) Then TranslateEntity cube2,0,-.1,0 If KeyDown(37) Then ;K ;ClearSurface GetSurface(cube,7),True,True ;TEST EndIf If KeyDown(18) Then ;E TurnEntity cube,-1,0,0 EndIf If KeyDown(19) Then ;R TurnEntity cube,0,-1,0 EndIf If KeyDown(20) Then ;T TurnEntity cube,0,0,-1 EndIf If KeyHit(21) Then ;Z German TurnEntity 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 FreeEntity cube cube = man ;PaintEntity cube,brush EntityFX 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 : " +CountSurfaces(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 entitys Local si If mesh=0 Then Return 0 Local c=0 For si=1 To CountSurfaces(mesh) c=c+CountTriangles(GetSurface(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 =Entity 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=CreateMesh() EndIf ;----------------------------- ;top face If o_top=1 Then s=CreateSurface( m , Br_Top) AddVertex s,x1,y2,z2,0,1:AddVertex s,x2,y2,z2,0,0 AddVertex s,x2,y2,z1,1,0:AddVertex s,x1,y2,z1,1,1 AddTriangle s,0,1,2:AddTriangle s,0,2,3 EndIf ;bottom face If o_bottom=1 Then s=CreateSurface( m , Br_Bottom) AddVertex s,x1,y1,z1,1,0:AddVertex s,x2,y1,z1,1,1 AddVertex s,x2,y1,z2,0,1:AddVertex s,x1,y1,z2,0,0 AddTriangle s,0,1,2:AddTriangle s,0,2,3 EndIf ;left face If o_left=1 Then s=CreateSurface( m , Br_Left) AddVertex s,x1,y2,z2,0,0:AddVertex s,x1,y2,z1,1,0 AddVertex s,x1,y1,z1,1,1:AddVertex s,x1,y1,z2,0,1 AddTriangle s,0,1,2:AddTriangle s,0,2,3 EndIf ;right face If o_right=1 Then s=CreateSurface( m , Br_Right) AddVertex s,x2,y2,z1,0,0:AddVertex s,x2,y2,z2,1,0 AddVertex s,x2,y1,z2,1,1:AddVertex s,x2,y1,z1,0,1 AddTriangle s,0,1,2:AddTriangle s,0,2,3 EndIf ;front face If o_front=1 Then s=CreateSurface( m , Br_Front) AddVertex s,x1,y2,z1,0,0:AddVertex s,x2,y2,z1,1,0 AddVertex s,x2,y1,z1,1,1:AddVertex s,x1,y1,z1,0,1 AddTriangle s,0,1,2:AddTriangle s,0,2,3 EndIf ;back face If o_back=1 Then s=CreateSurface( m , Br_Back) AddVertex s,x2,y2,z2,0,0:AddVertex s,x1,y2,z2,1,0 AddVertex s,x1,y1,z2,1,1:AddVertex s,x2,y1,z2,0,1 AddTriangle s,0,1,2:AddTriangle s,0,2,3 EndIf UpdateNormals m ;EntityPickMode m,2 ;Poly Return m End Function ;#################################################################################################### |
Comments
| ||
Wow. Thank you. You are David's Co-god. |
| ||
Good god man... This is great!!!! |
| ||
This is brilliant! Such an obvious way to work. Just wish I had time to build an editor around this code, but my guess is that someone's already working on it :-) Thanks for sharing. |
Code Archives Forum