Fast CSG

Blitz3D Forums/Blitz3D Programming/Fast CSG

39,600-poly sphere split in half, with caps, in 68 millisecs:
http://www.leadwerks.com/post/splitmesh.exe

thats great ,are you going to release the source?

Dude, you need a wireframe mode :D

you liar! You just one sphere mesh (b3d) and stuck them together as one!!!

Hehehe, no seriously, it's cool.

Let us see it on a abstract piece of geo.

The shape shouldn't matter. It isn't like he can special case a sphere or something. Triangles are triangles.

I'm just interested to see how well it copes with true Csg(I.e carving one mesh into another etc) rather than splitting a round mesh. The csg funcs in the archives for example work great in some cases, and are totally 'messed' up in other circumstances. I'm guessing this is a part of a commercial lib, and if it does what it says fast across any geo then even I'd buy it. And I don't buy things apperantly..;)

And obviously real world siturations... I mean would you guys demo unreal 3 with a sphere? :)

this would make geo-mod possible ,if halo is kind enough to release the source

if halo is kind enough to release the source

That's the best joke I've heard all year. ;)

But I'm sure he'll be releasing it as a lib..which is cool if reasonably priced.

It's likely a part of Cartography Shop.

Carving is just splitting with one plane, delete one side, split the result with another plane, delete one side, etc.

I'm using a little different method for CShop.

This creates a lot of extra triangles and vertices on the capped face. It can only cap convex objects. The code is rather complicated, especially when ordering the cap surface vertices. I tested it out on some of our WWII weapon models, and it worked perfectly:

Graphics3D 800,600,0,2
SetBuffer BackBuffer()

nx#=0.5
ny#=-1
nz#=0.5
d#=2

cam=CreateCamera()
MoveEntity cam,0,0,-40

FlushKeys

TurnEntity CreateLight(),45,45,0

;m=CreateCube()
m=CreateSphere(50)
;EntityFX m,16
ScaleMesh m,10,10,10
;m=LoadMesh("carbine.3ds")

;WireFrame 1
RenderWorld
Text 0,0,"Press a key to split the sphere."
Flip
WaitKey

time=MilliSecs()
splitmesh m,nx,ny,nz,d,1
time=MilliSecs()-time

;UpdateNormals operanda()
;UpdateNormals operandb()

p=CreatePivot()

EntityParent operanda(),p
EntityParent operandb(),p
;EntityFX operanda(),16
;EntityFX operandb(),16

FreeEntity m

;

speed#=0.01

;MoveEntity OPERANDA(),nx*speed,ny*speed,nz*speed
;MoveEntity OPERANDB(),nx*-speed,ny*-speed,nz*-speed

;FreeEntity OPERANDB()

;TurnEntity p,0,90,0

;FreeEntity operandb()

While Not KeyHit(1)
	MoveEntity OPERANDA(),nx*speed,ny*speed,nz*speed
	MoveEntity OPERANDB(),nx*-speed,ny*-speed,nz*-speed

	TurnEntity p,.5,.5,0
	RenderWorld
	Text 0,0,"Split in "+time+" milliseconds."
	Flip
	Wend
End

Global OPERANDA
Global OPERANDB

Global VectorX#
Global VectorY#
Global VectorZ#

Function OperandA()
Return OPERANDA
End Function

Function OperandB()
Return OPERANDB
End Function

Function VectorX#()
Return VectorX#
End Function

Function VectorY#()
Return VectorY#
End Function

Function VectorZ#()
Return VectorZ#
End Function

Function PointOnPlane#(x#,y#,z#,nx#,ny#,nz#,d#)
Return d+nx*x+ny*y+nz*z
End Function

Function RayIntersectsPlane(Ax#,Ay#,Az#,Bx#,By#,Bz#,nx#,ny#,nz#,d#)
u#=(nx*Ax+ny*Ay+nz*Az+d)/(nx*(Ax-Bx)+ny*(Ay-By)+nz*(Az-Bz))
VectorX=Ax+(Bx-Ax)*u
VectorY=Ay+(By-Ay)*u
VectorZ=Az+(Bz-Az)*u
If u>=0.0 And u<=1.0 Return True
End Function

Function Normalize(nx#,ny#,nz#)
m#=Sqr(nx*nx+ny*ny+nz*nz)
VectorX=nx/m
VectorY=ny/m
VectorZ=nz/m
End Function

Function SplitMesh(m,nx#,ny#,nz#,d#,cap=False)
Normalize nx,ny,nz
nx=VectorX()
ny=VectorY()
nz=VectorZ()

OPERANDA=CreateMesh()
OPERANDB=CreateMesh()
PositionEntity OPERANDA,EntityX(m,1),EntityY(m,1),EntityZ(m,1),1
PositionEntity OPERANDB,EntityX(m,1),EntityY(m,1),EntityZ(m,1),1
EntityFX OPERANDA,2
EntityFX OPERANDB,2
If cap
	capa=CreateBank()
	capb=CreateBank()
	temp=CreatePivot()
	AlignToVector temp,nx,ny,nz,3
	MoveEntity temp,0,0,-d
	EndIf
For s=1 To CountSurfaces(m)
	surf=GetSurface(m,s) 
	surfa=CreateSurface(OPERANDA)
	surfb=CreateSurface(OPERANDB)
	If cap
		lista=CreateBank()
		listb=CreateBank()
		EndIf
	SplitSurface(surf,surfa,surfb,nx,ny,nz,d,lista,listb)
	If cap
		For n=0 To BankSize(lista)/20-1
			v=PeekInt(lista,n*20)
			TFormPoint VertexX(surfa,v),VertexY(surfa,v),VertexZ(surfa,v),operanda,temp
			exists=False
			epsilon#=0.0000001
			;For n2=0 To BankSize(capa)/16-1
			;	If Abs(TFormedX()-PeekFloat(capa,n2*16))<epsilon
			;		If Abs(TFormedY()-PeekFloat(capa,n2*16+4))<epsilon
			;			exists=True
			;			Exit
			;			EndIf
			;		EndIf
			;	Next
			If Not exists
				size=BankSize(capa)
				ResizeBank capa,size+16
				PokeFloat capa,size,TFormedX()
				PokeFloat capa,size+4,TFormedY()
				EndIf
			Next
			
			
		For n=0 To BankSize(listb)/20-1
			v=PeekInt(listb,n*20)
			TFormPoint VertexX(surfb,v),VertexY(surfb,v),VertexZ(surfb,v),operandb,temp
			exists=False
			epsilon#=0.0000001
			;For n2=0 To BankSize(capa)/16-1
			;	If Abs(TFormedX()-PeekFloat(capa,n2*16))<epsilon
			;		If Abs(TFormedY()-PeekFloat(capa,n2*16+4))<epsilon
			;			exists=True
			;			Exit
			;			EndIf
			;		EndIf
			;	Next
			If Not exists
				size=BankSize(capb)
				ResizeBank capb,size+16
				PokeFloat capb,size,TFormedX()
				PokeFloat capb,size+4,TFormedY()
				EndIf
			Next
		EndIf
	;ClearSurface surfa
	Next
UpdateNormals operanda
UpdateNormals operandb
If cap
	For n=0 To BankSize(capa)/16-1
		x#=PeekFloat(capa,n*16)
		y#=PeekFloat(capa,n*16+4)
		If x>maxx# Or n=0 maxx=x
		If y>maxy# Or n=0 maxy=y
		If x<minx# Or n=0 minx=x
		If y<miny# Or n=0 miny=y		
		Next
	cx#=(maxx-minx)/2.0+minx
	cy#=(maxy-miny)/2.0+miny
	For n=0 To BankSize(capa)/16-1
		x#=PeekFloat(capa,n*16)
		y#=PeekFloat(capa,n*16+4)
		x=x-cx#
		y=y-cy#
		a#=ATan2(y,x)
		PokeFloat capa,n*16+8,a
		Next
	bank=CreateBank()
	Repeat
		stillgoing=False
		index=0
		For n=0 To BankSize(capa)/16-1
			If PeekInt(lista,n*16+12)=0
				index=index+1
				stillgoing=True
				a#=PeekFloat(capa,n*16+8)
				If index=1 Or a<lowesta#
					lowesta#=a
					lowestslot=n
					EndIf
				EndIf
			Next
		If Not stillgoing Exit
		size=BankSize(bank)
		ResizeBank bank,size+4
		PokeInt bank,size,lowestslot
		PokeInt lista,lowestslot*16+12,1
		Forever
	capsurf=CreateSurface(OPERANDA)
	For n=0 To BankSize(bank)/4-1
		slot=PeekInt(bank,n*4)
		x#=PeekFloat(capa,slot*16)
		y#=PeekFloat(capa,slot*16+4)
		TFormPoint x,y,0,temp,0
		v=AddVertex(capsurf,TFormedX(),TFormedY(),TFormedZ())
		VertexNormal capsurf,v,-nx,-ny,-nz
		Next
	For n=1 To BankSize(bank)/4-2
		AddTriangle capsurf,0,n+1,n
		Next
	AddTriangle capsurf,BankSize(bank)/4-1,0,0
	FreeBank bank



	;Cap B======================================
	
	
		For n=0 To BankSize(capb)/16-1
		x#=PeekFloat(capb,n*16)
		y#=PeekFloat(capb,n*16+4)
		If x>maxx# Or n=0 maxx=x
		If y>maxy# Or n=0 maxy=y
		If x<minx# Or n=0 minx=x
		If y<miny# Or n=0 miny=y		
		Next
	cx#=(maxx-minx)/2.0+minx
	cy#=(maxy-miny)/2.0+miny
	For n=0 To BankSize(capb)/16-1
		x#=PeekFloat(capb,n*16)
		y#=PeekFloat(capb,n*16+4)
		x=x-cx#
		y=y-cy#
		a#=ATan2(y,x)
		PokeFloat capb,n*16+8,a
		Next
	bank=CreateBank()
	Repeat
		stillgoing=False
		index=0
		For n=0 To BankSize(capb)/16-1
			If PeekInt(listb,n*16+12)=0
				index=index+1
				stillgoing=True
				a#=PeekFloat(capb,n*16+8)
				If index=1 Or a<lowesta#
					lowesta#=a
					lowestslot=n
					EndIf
				EndIf
			Next
		If Not stillgoing Exit
		size=BankSize(bank)
		ResizeBank bank,size+4
		PokeInt bank,size,lowestslot
		PokeInt listb,lowestslot*16+12,1
		Forever
	capsurf=CreateSurface(operandb)
	For n=0 To BankSize(bank)/4-1
		slot=PeekInt(bank,n*4)
		x#=PeekFloat(capb,slot*16)
		y#=PeekFloat(capb,slot*16+4)
		TFormPoint x,y,0,temp,0
		v=AddVertex(capsurf,TFormedX(),TFormedY(),TFormedZ())
		VertexNormal capsurf,v,nx,ny,nz
		Next
	For n=1 To BankSize(bank)/4-2
		AddTriangle capsurf,0,n,n+1
		Next
	AddTriangle capsurf,BankSize(bank)/4-1,0,0
	
	;===========================================






	FreeBank lista
	FreeBank listb
	FreeBank capa
	FreeBank capb
	FreeEntity temp
	EndIf
	EntityFX operanda,16
End Function

Function SplitSurface(surf,surfa,surfb,nx#,ny#,nz#,d#,lista=0,listb=0) 
For t=0 To CountTriangles(surf)-1 
	A=TriangleVertex(surf,t,0) 
	B=TriangleVertex(surf,t,1) 
	C=TriangleVertex(surf,t,2) 
	SplitTriangle(surfa,surfb,VertexX(surf,A),VertexY(surf,A),VertexZ(surf,A),VertexX(surf,B),VertexY(surf,B),VertexZ(surf,B),VertexX(surf,C),VertexY(surf,C),VertexZ(surf,C),nx,ny,nz,d,lista,listb) 
	Next 
End Function 

Function SplitTriangle(surfa,surfb,Ax#,Ay#,Az#,Bx#,By#,Bz#,Cx#,Cy#,Cz#,nx#,ny#,nz#,d#,lista=0,listb=0) 
pa#=PointOnPlane(ax,ay,az,nx,ny,nz,d)
pb#=PointOnPlane(bx,by,bz,nx,ny,nz,d)
pc#=PointOnPlane(cx,cy,cz,nx,ny,nz,d)
If pa=0.0 And pb=0 And pc=0 Return
If (Sgn(pa)=Sgn(pb) And Sgn(pb)=Sgn(pc)) Or (Sgn(pb)=Sgn(pc) And pa=0) Or (Sgn(pb)=Sgn(pa) And pc=0) Or (Sgn(pa)=Sgn(pc) And pb=0)
	If pa>0.0 
		A=AddVertex(surfa,ax,ay,az) 
		B=AddVertex(surfa,bx,by,bz) 
		C=AddVertex(surfa,cx,cy,cz) 
		AddTriangle surfa,a,b,c 
		Else
		A=AddVertex(surfb,ax,ay,az) 
		B=AddVertex(surfb,bx,by,bz) 
		C=AddVertex(surfb,cx,cy,cz) 
		AddTriangle surfb,a,b,c 
		EndIf
	Return False 
	EndIf
If Sgn(pa)=Sgn(pb);AB|C 
	If pa<0.0 
		surf=surfa 
		surfa=surfb 
		surfb=surf
		list=lista
		lista=listb
		listb=list
		EndIf 
	RayIntersectsPlane(ax,ay,az,cx,cy,cz,nx,ny,nz,d) 
	dx#=VectorX() 
	dy#=VectorY() 
	dz#=VectorZ() 
	RayIntersectsPlane(bx,by,bz,cx,cy,cz,nx,ny,nz,d) 
	ex#=VectorX() 
	ey#=VectorY() 
	ez#=VectorZ()
	A=AddVertex(surfa,ax,ay,az) 
	B=AddVertex(surfa,bx,by,bz) 
	C=AddVertex(surfb,cx,cy,cz) 
	D=AddVertex(surfa,Dx,Dy,Dz) 
	E=AddVertex(surfa,Ex,Ey,Ez) 
	AddTriangle surfa,D,A,B 
	AddTriangle surfa,D,B,E 

	;VertexColor surfa,D,255,0,0
	;VertexColor surfa,E,255,0,0

	If lista
		size=BankSize(lista)
		ResizeBank lista,size+40
		PokeInt lista,size,D
		PokeInt lista,size+20,E
		EndIf	

	D=AddVertex(surfb,Dx,Dy,Dz) 
	E=AddVertex(surfb,Ex,Ey,Ez) 
	AddTriangle surfb,C,D,E

	
	;VertexColor surfb,D,255,0,0
	;VertexColor surfb,E,255,0,0

	If listb
		size=BankSize(listb)
		ResizeBank listb,size+40
		PokeInt listb,size,D
		PokeInt listb,size+20,E
		EndIf	
	
ElseIf Sgn(pa)=Sgn(pc);AC|B 
	If pa<0.0
		surf=surfa 
		surfa=surfb 
		surfb=surf 
		list=lista
		lista=listb
		listb=list
		EndIf 
	RayIntersectsPlane(ax,ay,az,bx,by,bz,nx,ny,nz,d) 
	dx#=VectorX() 
	dy#=VectorY() 
	dz#=VectorZ() 
	RayIntersectsPlane(bx,by,bz,cx,cy,cz,nx,ny,nz,d) 
	ex#=VectorX() 
	ey#=VectorY() 
	ez#=VectorZ() 
	A=AddVertex(surfa,ax,ay,az) 
	B=AddVertex(surfb,bx,by,bz) 
	C=AddVertex(surfa,cx,cy,cz) 
	D=AddVertex(surfa,Dx,Dy,Dz) 
	E=AddVertex(surfa,Ex,Ey,Ez) 
	
	;VertexColor surfa,D,255,0,0
	;VertexColor surfa,E,255,0,0

	If lista
		size=BankSize(lista)
		ResizeBank lista,size+40
		PokeInt lista,size,D
		PokeInt lista,size+20,E
		EndIf
	
	AddTriangle surfa,A,D,C 
	AddTriangle surfa,D,E,C 
	D=AddVertex(surfb,Dx,Dy,Dz) 
	E=AddVertex(surfb,Ex,Ey,Ez) 

	;VertexColor surfb,D,255,0,0
	;VertexColor surfb,E,255,0,0

	If listb
		size=BankSize(listb)
		ResizeBank listb,size+40
		PokeInt listb,size,D
		PokeInt listb,size+20,E
		EndIf	

	AddTriangle surfb,B,E,D
ElseIf Sgn(pb)=Sgn(pc);BC|A 
	If pa>0.0 
		surf=surfa 
		surfa=surfb 
		surfb=surf 
		list=lista
		lista=listb
		listb=list
		EndIf 
	RayIntersectsPlane(ax,ay,az,cx,cy,cz,nx,ny,nz,d) 
	dx#=VectorX() 
	dy#=VectorY() 
	dz#=VectorZ() 
	RayIntersectsPlane(bx,by,bz,ax,ay,az,nx,ny,nz,d) 
	ex#=VectorX() 
	ey#=VectorY() 
	ez#=VectorZ() 
	A=AddVertex(surfb,ax,ay,az) 
	B=AddVertex(surfa,bx,by,bz) 
	C=AddVertex(surfa,cx,cy,cz) 
	D=AddVertex(surfa,Dx,Dy,Dz) 
	E=AddVertex(surfa,Ex,Ey,Ez) 

	;VertexColor surfa,D,255,0,0
	;VertexColor surfa,E,255,0,0

	If lista
		size=BankSize(lista)
		ResizeBank lista,size+40
		PokeInt lista,size,D
		PokeInt lista,size+20,E
		EndIf

	AddTriangle surfa,B,C,D 
	AddTriangle surfa,B,D,E
	D=AddVertex(surfb,Dx,Dy,Dz) 
	E=AddVertex(surfb,Ex,Ey,Ez) 
	AddTriangle surfb,A,E,D 

	;VertexColor surfb,D,255,0,0
	;VertexColor surfb,E,255,0,0

	If listb
		size=BankSize(listb)
		ResizeBank listb,size+40
		PokeInt listb,size,D
		PokeInt listb,size+20,E
		EndIf

	EndIf 
Return True 
End Function

Function appendint(buffer,value)
ResizeBank buffer,BankSize(buffer)+4
PokeInt buffer,BankSize(buffer)-4,value
End Function


Simply amazing. Thanks Halo.

really fast stuff.

what made me wonder was the fact, that its going mad when it comes to cones, which shouldn't be any problem compared to the problems a sphere creates ...

I think what I am using in CShop is properly called "convex hulls". The objects are wireframes, where the lines are made out of triangles between only two vertices. It's a million times easier to split, because there is only one way to split a line, and there are three ways to split a triangle.

I AM A ****ING GENIUS!

I wrote a routine that will "cap" the faces of any object made out of wireframe lines (triangles between two vertices).

Nobody
 #16
Oh don't pat yourself on the back to hard there halo. There is always somebody else out there that can also accomplish great things as well... Not just you! I've seen some other peoples work too, And there is alot of ****ING GENIUS'S out there! Rob, Rob Farley, FredBorg, Skitchy, to name just a few!! I respect & appreciate these people and others on here because they don't go around Glorifying themselves as you so often do! If you know you create excellent work. Then let other people praise you for it! Don't brag & glorify yourself as this makes you look bad towards others! But hey! This is just my opinion though!
Halo you seem to have talent in this area but looking at the code archives you dont seem to make this available to people - except if they are lucky enough to spot your post on the forums.

Why dont you be a good chap and put all your functions (that you have posted) in the code archives.

You will gain lasting respect and admiration.
I only see 2 entries from you in the 3D sections.

As for the routine to cap any surface, WIngs3D (free app) has been doing that for a few years now,

Nobody, your screen name is appropriate.

That's pretty fast. Thanks, I think I'll be using that at some point for something...

Very impressive... I should send you some muscle pain reliever from patting yourself on the back ;)

Well organized and readable even for my poor addled brain.

Major Kudos halo
-RZ

[quote]halo (Posted 2004-06-19 21:18:53)
Nobody, your screen name is appropriate. [\quote]

I think that "Nobody" is displayed when the user is banned.

"Well organized and readable even for my poor addled brain.”

So true, all too many pieces of code that hit the forums don’t follow even the most basic indentation and variable naming rules. It's a big waist when some on has all the logic but writes out puke code; your pretty print is very much appreciated halo.

halo


Nobody, your screen name is appropriate.

Hmmmmm... Sound's like "Nobody" didn't like your reply to you being a ****ing GENIUS there halo.

;)

Who knew that God couldn't spell?

Here is a demo of a 32-sided cylinder set at a 45 degree angle carving a chunk out of a cube. The process takes 7 milliseconds(!). Hit any key to start:
http://www.leadwerks.com/post/fastcarve.zip

If I can do a complex boolean like this in basically no time, real-time processing for shadow volumes, BSP cuts, occlusion, etc., should be no problem.

For the CShop 5 lightmapper, I am going to attempt to use a shadow volume method rather than a raytracer. It's project the edges of brushes onto other brushes and trim away the overlaps. At this speed, it might be possible to perform lighting in a few seconds. Maybe even real-time. I don't know yet.

Very impressive carve demo halo. I was scoring from 7-8 milliseconds with a few apps open in the background.

Halo: so you aren't planing to use any GI like stuff in CS5 again?

thats class again, nice halo

What is GI?

Halo, your alot of things, but you aren't a genious ;). Talanted and smart yeah. But arrogance never gets anyone **** out of life. It gets them a kick in the arse m8.

Good work with the CSG though, especially if it's as fast as was said. I havn't had time to look myself, or keep up with this post.

All you Euros are so sensitive.

what about us damn brits. we never get any compliments!

(feel free to flame, stab, mutilate, burn, mail, brand, cook, demoralize, steal from, or kick me in the nuts with reference to this post)

Halo, You link returns an invalid web page. Could you please fix this so I can check this out?

ShatteredReality (Posted 2004-06-20 17:41:34)

Halo, your alot of things, but you aren't a genious ;). Talanted and smart yeah. But arrogance never gets anyone **** out of life. It gets them a kick in the arse m8.
match halo's skill or STFU.

Spoon?

match halo's skill or STFU.

Many of us can match his skill. His ego, well, that's another matter...

You can't match. Unless "Bubble Blocks" is it.

Otacon: "Spoon?"

agreed.

i find it amazing how you people find the smallest things to argue about. and this is just pointless arguing, not a "discussion" of any kind.

halo - you may well be a genius. Was it a FLASH of insight that hit you out of the blue? Your post was a prime example of WHY coding and designing software is so much freakin fun!

I understand where you were coming from. Keep up the good work.

It was the alien beings that tell me to do bad things.