Code archives/3D Graphics - Effects/Omni Light/Normal Mapper

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

Download source code

Omni Light/Normal Mapper by AntonyWells2004
This is an engine, not an app. It's very easy to use, you just define light sources, caster meshes and reciever meshes. for lightmapping.

the lightmapping uses a custom leaf texture packer to pack the lightmap into one big texture.
You can define how many pixels(I.e 16x16) each poly in the scene gets.
The lightmapper uses a custom projected 2d volume technique to determine which lumels are shadowed, rather than using linepicks.

The normal mapper generates a per-pixel normal map for the scene, again using the leaf texture packer.
This allows you to do per-pixel lighting. Best suited to characters/props, rather than whole levels.(That's what the lightmapper is for.)
Although it does work pretty nicely on most small rooms(And terrains).
Included is EntityLight, this function transposes a light into object space and sets it's normal vector(I.e entityColor) to point towards the light source. (I.e map your mesh, setup the textures, and then simply use entityLight once per frame for per pixel lighting)




Lemme know if you have any probs getting it to work..wrote this a year back.
Global imap
Global ptri.pickedtri = New pickedtri

;Omni V0.9 Beta 5 - 3D Lighting and normal mapping Engine.
;
;Public Domain.
;
;Feel free to upload improved versions.
;
;Originally wrote by Antony Wells 2003
;-----

;-{Engine Globals. There are functions to change these, use 'em]
Global lMapWidth#=2048,lMapHeight#=2048
Global chunkWidth#=32,chunkHeight#=256
Const shadeWidth =128,shadeHeight=128
Global lMap.lightMap 



;---Test code]
Graphics3D 640,480,32,2
SetBuffer BackBuffer()

room=CreateCube()
FlipMesh room
ScaleMesh room,30,30,30

vcam=CreateCamera()

;-

Global vest=LoadTexture("units\thorn\tex5.bmp")

rock=LoadTexture("units\thorn\tex2.jpg")
tock=LoadTexture("units\thorn\tex2.jpg")
TextureBlend rock,1
TextureBlend tock,5

;EntityTexture room,rock,0,1
;ScaleTexture rock,0.2,0.2

;EntityTexture room,rock,0,1



AmbientLight 128,128,128


;-

;-

;AddReciever(room,16,16,1)


lv=CreateSphere()
cube=CreateCube();LoadMesh("units\hover\main.3ds")

If Not cube End
EntityColor room,128,0,0
;EntityTexture cube,tock,0,1




;FitMesh cube,-2,-2,-2,4,4,4
ScaleMesh cube,4,4,4
RotateMesh cube,90,0,0

;EntityTexture cube,rock,0,1

EntityTexture room,rock
Local cd[100]
cd[0]=cube


addreciever(cd[0],256,256,1)
	renderMap(vcam)



Repeat
If KeyDown(57) TextureBlend imap,1 Else TextureBlend imap,4
	TurnEntity vcam,MouseYSpeed(),-MouseXSpeed(),0
	PositionEntity lv,Cos(aaa#)*35,0,Sin(aaa)*35
	aaa#=aaa+1
	If MouseDown(2)
		PositionEntity lv,EntityX(vcam),EntityY(vcam),EntityZ(vcam)
	EndIf
	
	
	If KeyDown(17) MoveEntity vcam,0,0,0.1
	If KeyDown(31) MoveEntity vcam,0,0,-0.1
	If KeyDown(30) MoveEntity vcam,-0.1,0,0
	If KeyDown(32) MoveEntity vcam,0.1,0,0
	;-
	UpdateWorld
	RenderWorld
	;-
	Text 1,1,MouseZ()*0.1
	Flip
		;VectorLight(room,lv,MouseZ()*0.1,0)
		entityLight(cd[0],lv,MouseZ()*0.1,0)
		For j=0 To 0
	;		VectorLight(cd[j],lv,MouseZ()*0.1,0)
		Next
		
Until KeyDown(1)


Global lMapBlend=3
;-End of test]

;-[Types]
Type recv ;reciever meshes(Are lit)
	Field id
	Field cW,cH
	Field hull
End Type

Type cast ;caster meshes (Cast shadows)
	Field id
End Type

Type light ;3d lights
	Field x#,y#,z#
	Field cpiv,r,g,b
	Field fallOff#
	Field typ
	Field shade.shademap[100],sc
End Type

;-Chunks are 'reciever' tris, processed for rendering.
Type chunk 
	Field x#[3],y#[3],z#[3]
	Field u#[3],v#[3] ;u,v coords for the lightmap
	Field vi[3],hull
	Field nx#,ny#,nz# ;x,y,z normal of the triangle.
	Field pTex ;which texture plane to map to. (1-3)
	Field lTex ;lightMap texture
	Field srf,mesh,tri,ent
	Field eux#,evx#
	Field euy#,evy#
	Field euz#,evz#,leaf.leaf
	Field ox#,oy#,oz#
	Field tBank
	Field lit,shade
	Field cw,ch
	Field mx#,my#,mz#
	;real time fx 
	Field shim#[3]
	Field cx#,cy#,cz#,entX#,entY#,entZ#
End Type

Type shade
	Field x#[2],y#[2],z#[2]
	Field sx#[2],sy#[2]
	Field msh,light.light
End Type

Type yl
	Field y[shadeHeight]
End Type
Type shadeMap
	Field img,buf
	Field x.yl[shadeWidth]
	Field light.light,cast.cast
End Type


Type leaf
	Field leaf.leaf[2]
	Field x#,y#,w#,h#
	Field on
End Type

Type lightMap
	Field texMap,texBuf
	Field sW,sH
	Field tree.leaf,scam
End Type

;shadow maps

;--- [ Engine control ]
Function lightMapSize( width#,height#)
	lMapWidth =width
	lMapHeight =height
End Function

Function chunkSize( width#,height#)
	chunkWidth =width
	chunkHeight =height
End Function
Function shadeMapSize( width,height)
	lMap\sw =width
	lMap\sh =height
End Function


Function ligtMapBlend( mode=2)
	lMapBlend =mode
End Function

;--- [ Special Fx ] ;you must retain chunks for fx to work.
Global aa=0
Function shadowShimmer() ;disabled for now.

End Function


;--- [ Scene Building ]
Function addReciever(mesh,cw=128,ch=128,hull=False)
	recv.recv =New recv
	recv\id =mesh
	recv\cw=cw
	recv\ch=ch
	recv\hull=hull
	;EntityFX mesh,2
End Function

Function addCaster(mesh)
	cast.cast =New cast
	cast\id =mesh
End Function


Const cOmni=1,cDirectional=2
Function addOmniLight.light(x#,y#,z#,r#=128,g#=128,b#=128,fallOff#=10)
	light.light =New light
	light\x =x
	light\y =y
	light\z =z
	light\r =r
	light\g =g
	light\b =b
	light\fallOff=fallOff
	Return light
End Function

Function renderMap(cam=0,mode=1)
Local x#[5],y#[5],z#[5],v#[5]
	For recv.recv =Each recv
		EntityPickMode recv\id,2,True
		HideEntity recv\id
	Next
	For cast.cast =Each cast
		HideEntity cast\id
	Next
	CameraViewport cam,0,0,shadeWidth,shadeHeight
	CameraZoom cam,1.8
	mapWidth =GraphicsWidth()
	mapHeight =GraphicsHeight()

	For light.light =Each light
		PositionEntity cam,light\x,light\y,light\z
		For cast.cast =Each cast
			light\shade[light\sc] =New shadeMap
			shademap.shademap =light\shade[light\sc]
			light\sc=light\sc+1
			shadeMap\cast =cast
			PointEntity cam,cast\id
			ShowEntity cast\id
			Cls
			RenderWorld
			HideEntity cast\id
			LockBuffer
			For px=0 To shadeWidth-1
				For py=0 To shadeHeight-1
					;pix =ReadPixelFast(px,py) 
					If ((ReadPixelFast(px,py) Shr 16) And 255)
						If shadeMap\x[px]=Null shadeMap\x[px] =New yl
						shadeMap\x[px]\y[py] =True
					EndIf
				Next
			Next
			UnlockBuffer
		Next
		
	Next
	
	
	
	For cast.cast =Each cast
		ShowEntity cast\id
	Next
	
	
	Goto skipnew
	For light.light =Each light ;create shadow segs'
	PositionEntity cam,light\x,light\y,light\z
	For cast.cast =Each cast
		PointEntity cam,cast\id
		For sc =1 To CountSurfaces( cast\id)
			srf =GetSurface( cast\id,sc)
			For t=1 To CountTriangles( srf)
				shade.shade =New shade
				shade\msh =cast\id
				shade\light =light
				sa=sa+1
				For vt=0 To 2
					v1 =TriangleVertex(srf,t,vt)
					If v1=<CountVertices(srf)
						CameraProject cam,VertexX(srf,v1),VertexY(srf,v1),VertexZ(srf,v1)
						shade\sx[vt] =ProjectedX()
						shade\sy[vt] =ProjectedY() 
					Else
						Delete shade
						Goto skipS
					EndIf
					
					Next
				Next
			.skipS
			Next
		
		Next
		
	Next
	.skipnew
	
	createLightMap()
	If cam setLightCam(cam)
	For recv.recv =Each recv
		cx#=EntityX(recv\id)
		cy#=EntityY(recv\id)
		cz#=EntityZ(recv\id)
		;recv\cx=cx
	;	recv\cy=cy
	;	recv\cz=cz
		
		unweld(recv\id)
		HideEntity recv\id
		EntityTexture recv\id,lMap\texMap,0,0
	;	EntityFX recv\id,1
		sC =CountSurfaces( recv\id)
		;UpdateNormals recv\id
		If sc
			For s=1 To sc
				srf =GetSurface( recv\id,s)
				tris =CountTriangles( srf)
			
				For tri=0 To tris
					chunk.chunk =New chunk
					chunk\cx=cx
					chunk\cy=cy
					chunk\cz=cz
					chunk\tri=tri
					chunk\ent=recv\id
					chunk\srf=srf
					chunk\entX=EntityY(recv\id)
					chunk\entY=EntityX(recv\id)
					chunk\entZ=EntityZ(recv\id)
					chunk\hull=recv\hull
					
					chunk\cw =recv\cw
					chunk\mesh =recv\id
					chunk\ch =recv\ch
					chunk\srf =srf
					chunk\lit =True	
					For vt=0 To 2
						vi =TriangleVertex(srf,tri,vt)
						If vi<CountVertices(srf)
							x[vt] =VertexX( srf,vi)
							y[vt] =VertexY( srf,vi)
							z[vt] =VertexZ( srf,vi)
							chunk\x[vt] =x[vt]
							chunk\y[vt] =y[vt]
							chunk\z[vt] =z[vt]
							chunk\vi[vt] =vi
						Else
							Delete chunk
							Goto skipChunk
						EndIf
					Next
					triNorm( chunk\x[0],chunk\y[0],chunk\z[0],chunk\x[1],chunk\y[1],chunk\z[1],chunk\x[2],chunk\y[2],chunk\z[2])
					nx#=tnormX()
					ny#=tnormY()
					nz#=tnormZ()
					
				
					
								
					If Abs(nx)>Abs(ny) And Abs(nx)>Abs(nz)
						chunk\pTex =1
						;map onto yz-plane
					Else
						If Abs(ny)>Abs(nx) And Abs(ny)>Abs(nz)
							chunk\pTex =2
						Else
							chunk\pTex =3
						EndIf
					EndIf
					.skipChunk								
				Next
			Next
		EndIf
		
	Next
	If mode=1 tr =normalChunks()
	If mode=2 tr =lightChunks()
	For recv.recv =Each recv
		;UpdateNormals recv\id
		ShowEntity recv\id
	Next
	CameraViewport cam,0,0,GraphicsWidth(),GraphicsHeight()
	CameraZoom cam,1
	For cast.cast =Each cast
		ShowEntity cast\id
	Next
	SetBuffer BackBuffer()
	Return sa
End Function

Function big#(v0#,v1#,v2#)
	If v0>v1 
		If v0>v2 
			Return v0
		Else 
			Return v2
		EndIf
	Else 
		If v1>v2
			Return v1
		Else	
			Return v2
		EndIf
	EndIf
End Function

Function small#(v0#,v1#,v2#)
	If v0<v1 
		If v0<v2 
			Return v0
		Else 
			Return v2
		EndIf
	Else 
		If v1<v2
			Return v1
		Else	
			Return v2
		EndIf
	EndIf
End Function


Function vectorLight(entity,light,inten#=0.5,hull)
	ox#=EntityX(light)
	oy#=EntityY(light)
	
	oz#=EntityZ(light)
	;If Not hull inten=-inten
	tp=CreatePivot()
	PositionEntity tp,EntityX(light),EntityY(light),EntityZ(light)
	TFormPoint ox,oy,oz,tp,entity
	;FreeEntity tp
	light=tp
	
	PositionEntity light,TFormedX(),TFormedY(),TFormedZ() ;Transpose light into 
	srf=CountSurfaces(Entity)
	lx#=EntityX(light)
	ly#=EntityY(light)
	lz#=EntityZ(light)

	cs=CountSurfaces(entity)
	For s=1 To cs
		srf=GetSurface(entity,s)
		For v=0 To CountVertices(srf)-1
			vx#=VertexX(srf,v)
			vy#=VertexY(Srf,v)
			vz#=VertexZ(srf,v)
			dx# =(lx-vx)
			dy# =(ly-vy)
			dz# =(lz-vz)
			tdx#=vx-lx
			tdy#=vy-ly
			tdz#=vz-lz
		;	tl#=Sqr(tdx*tdx+tdy*tdy*+tdz*tdz)
		;	dx=(dx/tl)*inten
		;	dy=(dy/tl)*inten
			;dz=(dz/tl)*inten
			nl#=Sqr(tdx*tdx+tdy*tdy+tdz*tdz)
			nx#=dx/nl
			ny#=dy/nl
			nz#=dz/nl
			nl#=(nl*10.-255.)/255.
	
			nl=1-nl
	
	If nl>1 nl=1
	If nl<0 nl=0
	nl=in

	nx=nx*inten
	ny=ny*inten
	nz=nz*inten

			
			VertexColor srf,v,128+(128*nx),128+(128*nz),128+(128*ny)
		Next

	Next
	FreeEntity tp
End Function


Function old()
For v=0 To CountVertices(srf)-1
			vx#=VertexX(srf,v)
			vy#=VertexY(Srf,v)
			vz#=VertexZ(srf,v)
			dx# =(lx-vx)
			dy# =(ly-vy)
			dz# =(lz-vz)
			tdx#=vx-lx
			tdy#=vy-ly
			tdz#=vz-lz
		;	tl#=Sqr(tdx*tdx+tdy*tdy*+tdz*tdz)
		;	dx=(dx/tl)*inten
		;	dy=(dy/tl)*inten
			;dz=(dz/tl)*inten
			nl#=Sqr(tdx*tdx+tdy*tdy+tdz*tdz)
			nx#=dx/nl
			ny#=dy/nl
			nz#=dz/nl
			nl#=(nl*10.-255.)/255.
	
			nl=1-nl
	
	If nl>1 nl=1
	If nl<0 nl=0
	nl=in

	nx=nx*inten
	ny=ny*inten
	nz=nz*inten

			
			VertexColor srf,v,128+(128*nx),128+(128*nz),128+(128*ny)
		Next
End Function


Function entityLight(entity,light,inten#=0.5,hull=False)
	ox#=EntityX(light)
	oy#=EntityY(light)
	oz#=EntityZ(light)
	inten =0.5
;	If Not hull inten=1.-inten
	tp=CreatePivot()
	PositionEntity tp,EntityX(light),EntityY(light),EntityZ(light)
	TFormPoint ox,oy,oz,tp,entity
	;FreeEntity tp
	light=tp
	
	PositionEntity light,TFormedX(),TFormedY(),TFormedZ() ;Transpose light into 
	dx# =(EntityX(light)-EntityX( entity));*inten
	dy# =(EntityY(light)-EntityY( entity));*inten
	dz# =(EntityZ(light)-EntityZ( entity));*inten
	
	nl#=Sqr(dx*dx+dy*dy+dz*dz)
	nx#=dx/nl
	ny#=dy/nl
	nz#=dz/nl
	nl#=(nl*10.-255.)/255.
	
	nl=1.-nl
	
	If nl>1. nl=1
	If nl<0. nl=0
	nl=in

	nx=nx;*inten
	ny=ny;*inten
	nz=nz;*inten
	
	;nz=(Sgn(nz))+nz
	;nx=(Sgn(nx))+nx
	;ny=(Sgn(ny))+ny
	
;	If nx<0 nx
		
		
	FreeEntity tp
	EntityColor entity,128.+(128.*nx),128.+(128.*nz),128.+(128.*ny)
	

	;EntityColor entity,256+(256*nx),256.0+(256*ny),256.0+(256*nt)
	
;	PositionEntity light,ox,oy,oz ;return light.
End Function
 

Function createLightMap()
	lMap.lightMap =New lightMap
	lmap\texMap =CreateTexture(lMapWidth,lMapHeight,8)
	lmap\texBuf =TextureBuffer(lMap\texMap)
	TextureCoords lmap\texMap,1 ;set to the second u,v set.
	 imap=lmap\texmap
	
	TextureBlend lmap\texMap,3
End Function
Function setLightCam(cam)
	lmap\scam =cam
	CameraClsMode lmap\scam,False,True
End Function

;-- [ Leaf Engine] ;packs multiple textures into 1 'larger' texture
Function newLeaf.leaf(texture) ;returns leaf object that holds the tex.
	width =TextureWidth(texture)
	height =TextureHeight(texture)
	If width<1 Or height<1 Return
	If lMap\tree =Null ;first image
		lMap\tree =New leaf
		lMap\tree\w =lMapWidth
		lMap\tree\h =lMapHeight
	EndIf
	For leaf.leaf =Each leaf
		out.leaf =insertLeaf( leaf,texture)
		If out<>Null Return out
	Next
	;Return addLeaf( lMap\tree,texture)
End Function


Function insertLeaf.leaf( leaf.leaf,texture)
width =TextureWidth(texture)
height =TextureHeight(texture)	
	
If leaf\on Return 
	
	If width<=leaf\w And height<=leaf\h ;fits
		leaf\on =True

		leaf\leaf[0] =New leaf
		leaf\leaf[1] =New leaf
		leaf\leaf[0]\x =leaf\x+width
		leaf\leaf[0]\y =leaf\y
		leaf\leaf[0]\w =leaf\w-width-1
		leaf\leaf[0]\h =height
				
		leaf\leaf[1]\x =leaf\x
		leaf\leaf[1]\y =leaf\y+height
		leaf\leaf[1]\w =leaf\w
		leaf\leaf[1]\h =leaf\h-height
		
		leaf\w =width
		leaf\h =height
		CopyRect 0,0,width,height,leaf\x,leaf\y,TextureBuffer(texture),lMap\texBuf
		Return leaf
	EndIf
End Function


Function addLeaf.leaf( leaf.leaf,texture) ;internal function
Local nleaf.leaf
	width =TextureWidth(texture)
	height =TextureHeight(texture)

If leaf\on

    nleaf =insertLeaf( leaf\leaf[0],texture)
	If nleaf<>Null Return nleaf
	nleaf =insertLeaf( leaf\leaf[1],texture)
	If nleaf<>Null Return nleaf
Else
	nleaf =insertLeaf( leaf,texture)
	If nleaf<>Null Return nleaf
EndIf
	
End Function

Function leafU#(leaf.leaf,u#) ;converts a normal u coord into a lightmap u coord
	Return ((leaf\x+1)+((leaf\w-2)*u))/lMapWidth 
End Function

Function leafV#(leaf.leaf,v#)
	Return ((leaf\y+1)+((leaf\h-2)*v))/lMapHeight
End Function

Function textureNorm(tex)
	SetBuffer TextureBuffer(Tex)
	tw#=TextureWidth(Tex)
	th#=TextureHeight(tex)
	LockBuffer
	For x=0 To tw-1
	For y=0 To th-1
		cv=ReadPixelFast(x,y)
		r=(cv Shr 16) And 255
		g=(cv Shr 8) And 255
		b=(cv And 255)
		cv=(r+g+b)/3.
		nx#=128
		ny#=128
		nz#=cv
		rgb = nz Or (ny Shl 8) Or (nx Shl 16)
		WritePixelFast x,y,rgb
	Next
	Next
	UnlockBuffer
	SetBuffer BackBuffer()
End Function


Function NormalChunks() ;final chunk 'prep' before rendering
Local miU#,miV#
Local maU#,maV#,rU#,rV#
Local u#[3],v#[3]
Local spiv =CreatePivot(),lpiv1=CreatePivot()
Local lpiv2 =CreatePivot(),lpiv3 =CreatePivot()

For chunk.chunk =Each chunk
If chunk\lit
		;-fx
		
		;----
		For vt=0 To 2
			chunk\shim[vt] =Rnd(360)
			Select chunk\pTex
				Case 1 ;yz
					u[vt] =chunk\y[vt]
					v[vt] =chunk\z[vt]
				Case 2 ;xz
					u[vt] =chunk\x[vt]
					v[vt] =chunk\z[vt]
				Case 3 ;xy
					u[vt] =chunk\x[vt]
					v[vt] =chunk\y[vt]
				Default
					RuntimeError "Illegal projection plane"
			End Select
		Next
		triNorm( chunk\x[0],chunk\y[0],chunk\z[0],chunk\x[1],chunk\y[1],chunk\z[1],chunk\x[2],chunk\y[2],chunk\z[2])
		
		;TriNorm( x[0],y[0],z[0],x[1],y[1],z[1],x[2],y[2],z[2])
		chunk\nX# =tNormX()
		chunk\ny =tNormY()
		chunk\nz =tNormZ()
					
				
		
					
		
		;tnx#=chunk\nx
		;tny#=chunk\ny
		;tnz#=chunk\nz
		
		
		;map u,v into valid 0,1 range.
		miU = 9999
		miV = 9999
		maU = -9999
		maV = -9999
		For i=0 To 2
			If u[i]<miU
				miU =u[i]
			EndIf
			If u[i]>maU
				maU =u[i]
			EndIf
			If v[i]<miV
				miV =v[i]
			EndIf
			If v[i]>maV
				maV =v[i]
			EndIf
		Next
		
	
		rU =maU -miU
		rV =maV -miV
		
	
		mapWidth =chunk\cw
		mapHeight =chunk\ch
	
		tempMap =CreateTexture( mapWidth,mapHeight,256)
		If Not tempMap Return
		For vt=0 To 2
			chunk\u[vt] =(u[vt]-miU) /rU
			chunk\v[vt] =(v[vt]-miV) /rV
		Next
		
	
    	dist# = -(chunk\nx * chunk\x[0]+chunk\ny*chunk\y[1]+chunk\nz*chunk\z[2])
		Select chunk\pTex
			Case 3
			
				Z# = -(chunk\nx*miU + chunk\ny * miV + Dist) / chunk\nz
				uvx# = miu : UVY# = miV : UVZ# = Z
				Z# = -(chunk\NX * maU + chunk\NY * miV + Dist) / chunk\NZ
				V1X# = maU : V1Y# = miV : V1Z# = Z
				Z# = -(chunk\NX * miu + chunk\NY * maV + Dist) / chunk\NZ
				V2X# = miu : V2Y# = maV : V2Z# = Z
			Case 2
				Y# = -(chunk\NX * miu + chunk\NZ * miV + Dist) / chunk\NY
				UVX# = miu : UVY# = Y : UVZ# = miV
				Y# = -(chunk\NX * maU + chunk\NZ * miV + Dist) / chunk\NY
				V1X# = maU : V1Y# = Y : V1Z# = miV
				Y# = -(chunk\NX * miu + chunk\NZ * maV + Dist) / chunk\NY
				V2X# = miu : V2Y# = Y : V2Z# = maV
			Case 1		
				X# = -(chunk\NY * miu + chunk\NZ * miV + Dist) / chunk\NX
				UVX# = X : UVY# = miu : UVZ# = miV
				X# = -(chunk\NY * maU + chunk\NZ * miV + Dist) / chunk\NX	
				V1X# = X : V1Y# = maU : V1Z# = miV	
				X# = -(chunk\NY * miu + chunk\NZ * maV + Dist) / chunk\NX
				V2X# = X : V2Y# = miu : V2Z# = maV
		End Select
		chunk\eux = V1X - UVX : chunk\euy = V1Y - UVY : chunk\euz = V1Z - UVZ
		chunk\evx = V2X - UVX : chunk\evy = V2Y - UVY : chunk\evz = V2Z - UVZ
		chunk\ox = UVX# : chunk\oy = UVY# : chunk\oz = UVZ#

		;dx# =chunk\ox
		
		ox#=md( chunk\x[0],chunk\x[1],chunk\x[2])
		oy#=md( chunk\y[0],chunk\y[1],chunk\y[2])
		oz#=md( chunk\z[0],chunk\z[1],chunk\z[2])
	;	ox=ox+chunk\cx
		
		;DebugLog chunk\cx+" Oy>"+chunk\cy+" oz>"+chunk\cz
		If chunk\hull
	ox=-ox
			oy=-oy
			oz=-oz
		;	dx#=ox-chunk\cx
		;	dy#=oy-chunk\cy
		;	dz#=oz-chunk\cz	
		Else
		;	dx =chunk\cx-ox
		;	dy =chunk\cy-oy
		;	dz =chunk\cz-oz
			
		EndIf	
	;	ox=ox-chunk\cx
	;	oy=oy-chunk\cy
	;	oz=oz-chunk\cz
		
		;nl# =Sqr(ox*ox+oy*oy+oz*oz)
	;	tnx#=(ox)/nl
	;	tny#=(oy)/nl
	;	tnz#=(oz)/nl
	;	ox=chunk\cx+ox
	;	oy=chunk\cy+oy
	;	oz=chunk\cz+oz
		
	;	cc=CreateCube()
	;	FitMesh cc, -0.2,-0.2,-0.2,0.4,0.4,0.4
	;	PositionEntity cc,ox,oy,oz
		
	;	vp=CreateCube()
	;	FitMesh vp,-0.2,-0.2,-.2,0.4,0.4,0.4
	;	PositionEntity vp,chunk\cx,chunk\cy,chunk\cz
	
		If mapWidth<>laW Or mapHeight<>laH
			laW =mapWidth
			laH =mapHeight
			If tmpImg FreeImage tmpImg
			tmpImg =CreateImage(mapWidth,mapHeight)
			tmpBuf =ImageBuffer(tmpImg)
			SetBuffer tmpBuf
		EndIf
		LockBuffer tmpBuf
		LockBuffer TextureBuffer(vest)
		rv#=128.+(128.*tnx)
		bv#=128.+(128.*tny)
		gv#=128.+(128.*tnz)
		;rv=Rnd(255)
		;EntityColor cc,255,255,255
		vb=TextureBuffer(vest)
		entX#=chunk\entX
		entY#=chunk\entY
		entZ#=chunk\entZ
		If chunk\hull dir#=1 Else dir=-1
		PositionEntity spiv,chunk\cx,chunk\cy,chunk\cz
		tw#=TextureWidth(vest)
		th#=TextureHeight(vest)
		
		For x#=0 To mapWidth-1 
			au# = x/mapwidth
			N_UEdgeX# = chunk\EuX * au#  :  N_UEdgeY# = chunk\euY * au#  :  N_UEdgeZ# = chunk\euZ * au#
		For y#=0 To mapHeight-1 
			av# = y/mapHeight		
			N_VEdgeX# = chunk\evX * av#  :  N_VEdgeY# = chunk\evY * av#  :  N_VEdgeZ# = chunk\evZ * av#
			lx# = (chunk\ox + N_UEdgeX + N_VEdgeX)
			ly# = (chunk\oy + N_UEdgeY + N_VEdgeY)
			lz# = (chunk\oz + N_UEdgeZ + N_VEdgeZ)
		
			
			td#=Sqr(lx*lx+ly*ly+lz*lz)
			nox#=lx/td ;*Rnd(0.75,1.25)
			noz#=ly/td ;'*Rnd(0.75,1.25)
			noy#=lz/td
			
			
			
		;	shaded =False
		;	lcast.cast=Null
		;	r1=0
			;g1=0
		;	b1=0
	
		;	For light.light =Each light
		;		PositionEntity lmap\scam,light\x,light\y,light\z
		;		shaded=False
		;		If light\sc
		;		For j=0 To light\sc-1
		;			shade.shadeMap =light\shade[j]
		;			PointEntity lmap\scam,shade\cast\id
		;			If shade\cast\id =chunk\mesh Goto skips 
		;			CameraProject lmap\scam,lx,ly,lz
		;			px =ProjectedX()
		;			If px>0 And px<shadeWidth
		;			If shade\x[px]<>Null
		;				py =ProjectedY()
		;				If py>0 And py<shadeHeight
		;					shaded =shade\x[px]\y[py]
		;					If shaded Exit
		;				EndIf
		;			EndIf
		;			EndIf
		;			.skips
		;		Next
		;		EndIf
		;		If Not shaded
				
		;			PositionEntity spiv,light\x,light\y,light\z
		;			ed# =(EntityDistance(spiv,lpiv1)*light\fallOff)
		;			
		;			r1=(light\r-ed)
		;			g1=(light\g-ed)
		;			b1=(light\b-ed)
		;			If r1<0 r1=0
		;			If g1<0 g1=0
		;			If b1<0 b1=0
		;			rv=rv+r1
		;			gv=gv+g1
		;			bv=bv+b1
		;		Else
				
		;		EndIf
		;	Next
		;	If rv>255 rv=255
		;	If gv>255 gv=255
		;	If bv>255 bv=255
			;If r1<0 rv=0
			;If g1<0 gv=0
			;If b1<0 bv=0	
				
		;	xd#=(lx-chunk\cx)
		;	yd#=(ly-chunk\cy)
		;	zd#=(lz-chunk\cz)
			;I;f chunk\hull=False
			;	xd=0
			;	yd=0
			;	zd=0			
			;EndIf
			
			
		;	ld#=Sqr(xd*Xd+Yd*Yd+zd*zd)
		;	PositionEntity lpiv1,lx,ly,lz
		;	ld#=EntityDistance(lpiv1,spiv)
			;ld=-dist
			
		;	anx#=xd/ld
		;	any#=yd/ld
		;Function PickedUVW(ent,surf,tri,x#,y#,z#,nx#,ny#,nz#)
		pickedUVW(chunk\ent,chunk\srf,chunk\tri,lx,ly,lz,chunk\nx,chunk\ny,chunk\nz)
		ssu#=pickedU()
		ssv#=pickedV()
		ax#=tw*ssu
		ay#=th*ssv
		;If ax>tw-1 ax=tw-1
		;If ay>th-1 ay=th-1
		;If ax<0 ax=0
		;If ay<0 ay=0
			ab=ReadPixelFast(ax,ay,vb)
			ar=(ab Shr 16) And 255
			ag=(ab Shr 8) And 255
			ab=(ab And 255)
		;	anz#=zd/ld  ;+((ag/255)-1)
		;	any=any+ag
			
			;anx=ar
			;any=ag
			
			;anz=ab
		;	anx#=tnx#+Rnd(-0.001,0.001)
		;	any#=tny#+Rnd(-0.001,0.001)
		;	anz#=tnz#+Rnd(-0.001,0.001)
		;	anx=tnx+Cos(x)
		;	any=tny+Sin(y)
		;	anz=tnz
		
		vx#=((ar)/255.0)
		vz#=((ag)/255.0)
		vy#=((ab)/255.0)
		vx#=-1.+vx*2.
		vy#=-1.+vy*2. ;bring vector into valid -1,1 range
		vz#=-1.+vz*2.
		
	;	If vx>1 End
		;PointEntity lpiv1,spiv
		;PointEntity spiv,lpiv1
		
	
		;AlignToVector spiv,nox,noy,noz,0
		
		;AlignToVector spiv,nox,noy,noz,2
		
		
	
		TFormVector2(vx,vy,vz,nox,noy,noz)
		ar=128.0+(128.0*TFormedX())
		ag=128.0+(128.0*TFormedY())
		ab=128.0+(128.0*TFormedZ())
		
		;ar=128
		;ag=128
		;ab=128
		
		
		
		;ar=vx*anx
		
	;;	ag=vy*any
	;	ab=vz*anz
		;ar=128.+(128.*vx)
		;ag=128.+(128.*vy)
		;ab=128.+(128.*vz)	
	;	anx=anx*vx
	;	any=any*vy
	;	anz=anz*vz
	;	rv#=128.+(128.*anx)
	;	bv#=128.+(128.*any)
	;	gv#=128.+(128.*anz)
	;	ar=(ar-128)*2
	;	ag=(ag-128)*2
	;	ab=(ab-128)*2
	;	rv=rv+ar
	;	gv=gv+ag
	;	bv=bv+ab
		
		
	;	rv#=(0.5+(nox/2.0))*255.
	;	gv#=(0.5+(noy/2.0))*255.
	;	bv#=(0.5+(noz/2.0))*255.
			
		rv=ar
		gv=ag
		bv=ab	
		If rv<0 rv=0
		If gv<0 gv=0
		If bv<0 bv=0
		If rv>255 rv=255
		If gv>255 gv=255
		If bv>255 bv=255
		;	bv=ar
		;	rv=ag
			
		;	gv=ab;+Rnd(-20,20)
			arg = bv Or (gv Shl 8) Or (rv Shl 16)	
			WritePixelFast x,y,arg
		Next
		Next
		UnlockBuffer tmpBuf
		UnlockBuffer TextureBuffer(vest)
		SetBuffer TextureBuffer(tempMap)
		DrawBlock tmpImg,0,0
		SetBuffer tmpBuf 	
	;CopyRect 0,0,mapWidth,mapHeight,0,0,tmpBuf,TextureBuffer(tempMap)
		

	
		

		
		;-
		leaf.leaf =newLeaf(tempMap) 
		chunk\leaf =leaf
		FreeTexture tempMap
		For vt=0 To 2 ;map lightmap onto mesh
			chunk\u[vt] =leafU(leaf,chunk\u[vt])
			chunk\v[vt] =leafV(leaf,chunk\v[vt])
			VertexTexCoords chunk\srf,chunk\vi[vt],chunk\u[vt],chunk\v[vt],0,1
		Next
EndIf
	Next

	For recv.recv =Each recv
		ShowEntity recv\id
	Next
	CameraZoom lmap\scam,1
	SetBuffer BackBuffer()
	CameraViewport lmap\scam,0,0,GraphicsWidth(),GraphicsHeight()
	FreeImage tmpImg
End Function
Function md#(v1#,v2#,v3#)
	v1=v1+2000
	v2=v2+2000
	v3=v3+2000
	s#=sm(v1,v2,v3)
	b#=bg(v1,v2,v3)
	v#=s+((b-s)/2.)
	v=v-2000
	Return v
End Function

Function bg#(v1#,v2#,v3#)
	If v1=v2
		If v3<v2 Return v2
	EndIf
	If v1=v3
		If v2<v1 Return v1
	EndIf
	If v2=v3
		If v1<v2 Return v2
	EndIf
		
	
	If v1>v2 And v1>v3 Return v1
	If v2>v1 And v2>v3 Return v2
	Return v3
End Function

Function sm#(v1#,v2#,v3#)
	If v1=v2
		If v3>v2 Return v1
	EndIf
	If v1=v3
		If v2>v3 Return v1
	EndIf
	If v2=v3 
		If v1>v2 Return v2
	EndIf
	
	
	If v1<v2 And v1<v3 Return v1
	If v2<v1 And v2<v3 Return v2
	Return v3
End Function


Function LightChunks() ;final chunk 'prep' before rendering
Local miU#,miV#
Local maU#,maV#,rU#,rV#
Local u#[3],v#[3]
Local spiv =CreatePivot(),lpiv1=CreatePivot()
Local lpiv2 =CreatePivot(),lpiv3 =CreatePivot()

For chunk.chunk =Each chunk
If chunk\lit
		;-fx
		
		;----
		For vt=0 To 2
			chunk\shim[vt] =Rnd(360)
			Select chunk\pTex
				Case 1 ;yz
					u[vt] =chunk\y[vt]
					v[vt] =chunk\z[vt]
				Case 2 ;xz
					u[vt] =chunk\x[vt]
					v[vt] =chunk\z[vt]
				Case 3 ;xy
					u[vt] =chunk\x[vt]
					v[vt] =chunk\y[vt]
				Default
					RuntimeError "Illegal projection plane"
			End Select
		Next
		triNorm( chunk\x[0],chunk\y[0],chunk\z[0],chunk\x[1],chunk\y[1],chunk\z[1],chunk\x[2],chunk\y[2],chunk\z[2])
		
		tnx#=tNormX()
		tny#=tnormY()
		tnz#=tnormz()
		
		;map u,v into valid 0,1 range.
		miU = 9999
		miV = 9999
		maU = -9999
		maV = -9999
		For i=0 To 2
			If u[i]<miU
				miU =u[i]
			EndIf
			If u[i]>maU
				maU =u[i]
			EndIf
			If v[i]<miV
				miV =v[i]
			EndIf
			If v[i]>maV
				maV =v[i]
			EndIf
		Next
		
	
		rU =maU -miU
		rV =maV -miV
		
	
		mapWidth =chunk\cw
		mapHeight =chunk\ch
	
		tempMap =CreateTexture( mapWidth,mapHeight,256)
		If Not tempMap Return
		For vt=0 To 2
			chunk\u[vt] =(u[vt]-miU) /rU
			chunk\v[vt] =(v[vt]-miV) /rV
		Next
		
	
    	dist# = -(chunk\nx * chunk\x[0]+chunk\ny*chunk\y[1]+chunk\nz*chunk\z[2])
		Select chunk\pTex
			Case 3
			
				Z# = -(chunk\nx*miU + chunk\ny * miV + Dist) / chunk\nz
				uvx# = miu : UVY# = miV : UVZ# = Z
				Z# = -(chunk\NX * maU + chunk\NY * miV + Dist) / chunk\NZ
				V1X# = maU : V1Y# = miV : V1Z# = Z
				Z# = -(chunk\NX * miu + chunk\NY * maV + Dist) / chunk\NZ
				V2X# = miu : V2Y# = maV : V2Z# = Z
			Case 2
				Y# = -(chunk\NX * miu + chunk\NZ * miV + Dist) / chunk\NY
				UVX# = miu : UVY# = Y : UVZ# = miV
				Y# = -(chunk\NX * maU + chunk\NZ * miV + Dist) / chunk\NY
				V1X# = maU : V1Y# = Y : V1Z# = miV
				Y# = -(chunk\NX * miu + chunk\NZ * maV + Dist) / chunk\NY
				V2X# = miu : V2Y# = Y : V2Z# = maV
			Case 1		
				X# = -(chunk\NY * miu + chunk\NZ * miV + Dist) / chunk\NX
				UVX# = X : UVY# = miu : UVZ# = miV
				X# = -(chunk\NY * maU + chunk\NZ * miV + Dist) / chunk\NX	
				V1X# = X : V1Y# = maU : V1Z# = miV	
				X# = -(chunk\NY * miu + chunk\NZ * maV + Dist) / chunk\NX
				V2X# = X : V2Y# = miu : V2Z# = maV
		End Select
		chunk\eux = V1X - UVX : chunk\euy = V1Y - UVY : chunk\euz = V1Z - UVZ
		chunk\evx = V2X - UVX : chunk\evy = V2Y - UVY : chunk\evz = V2Z - UVZ
		chunk\ox = UVX# : chunk\oy = UVY# : chunk\oz = UVZ#

	
			
	
	
		If mapWidth<>laW Or mapHeight<>laH
			laW =mapWidth
			laH =mapHeight
			If tmpImg FreeImage tmpImg
			tmpImg =CreateImage(mapWidth,mapHeight)
			tmpBuf =ImageBuffer(tmpImg)
			SetBuffer tmpBuf
		EndIf
		LockBuffer
		LockBuffer TextureBuffer(vest)
		vb=TextureBuffer(vest)
		For x#=0 To mapWidth-1 
			au# = x/mapwidth
			N_UEdgeX# = chunk\EuX * au#  :  N_UEdgeY# = chunk\euY * au#  :  N_UEdgeZ# = chunk\euZ * au#
		For y#=0 To mapHeight-1 
			av# = y/mapHeight		
			N_VEdgeX# = chunk\evX * av#  :  N_VEdgeY# = chunk\evY * av#  :  N_VEdgeZ# = chunk\evZ * av#
			lx# = (chunk\ox + N_UEdgeX + N_VEdgeX)
			ly# = (chunk\oy + N_UEdgeY + N_VEdgeY)
			lz# = (chunk\oz + N_UEdgeZ + N_VEdgeZ)
			
			shaded =False
			lcast.cast=Null
			r1=0
			g1=0
			b1=0
	
			For light.light =Each light
				PositionEntity lmap\scam,light\x,light\y,light\z
				shaded=False
				If light\sc
				For j=0 To light\sc-1
					shade.shadeMap =light\shade[j]
					PointEntity lmap\scam,shade\cast\id
					If shade\cast\id =chunk\mesh Goto skips 
					CameraProject lmap\scam,lx,ly,lz
					px =ProjectedX()
					If px>0 And px<shadeWidth
					If shade\x[px]<>Null
						py =ProjectedY()
						If py>0 And py<shadeHeight
							shaded =shade\x[px]\y[py]
							If shaded Exit
						EndIf
					EndIf
					EndIf
					.skips
				Next
				EndIf
				If Not shaded
					PositionEntity lpiv1,lx,ly,lz
					PositionEntity spiv,light\x,light\y,light\z
					ed# =(EntityDistance(spiv,lpiv1)*light\fallOff)
					
					r1=(light\r-ed)
					g1=(light\g-ed)
					b1=(light\b-ed)
					If r1<0 r1=0
					If g1<0 g1=0
					If b1<0 b1=0
					rv=rv+r1
					gv=gv+g1
					bv=bv+b1
				Else
				
				EndIf
			Next
			If rv>255 rv=255
			If gv>255 gv=255
			If bv>255 bv=255
			;If r1<0 rv=0
			;If g1<0 gv=0
			;If b1<0 bv=0		
			
			rv=128+(128*tnx)
			gv=128+(128*tny)
			bv=128+(128*tnz)
			
			WritePixelFast x,y,bv Or (gv Shl 8) Or (rv Shl 16)
			rv=0
			gv=0
			bv=0
		Next
		Next
		UnlockBuffer TextureBuffer(vest)
		UnlockBuffer
		SetBuffer TextureBuffer(tempMap)
		DrawBlock tmpImg,0,0
		SetBuffer tmpBuf 	
	;CopyRect 0,0,mapWidth,mapHeight,0,0,tmpBuf,TextureBuffer(tempMap)
		

	
		

		
		;-
		leaf.leaf =newLeaf(tempMap) 
		chunk\leaf =leaf
		FreeTexture tempMap
		For vt=0 To 2 ;map lightmap onto mesh
			chunk\u[vt] =leafU(leaf,chunk\u[vt])
			chunk\v[vt] =leafV(leaf,chunk\v[vt])
			VertexTexCoords chunk\srf,chunk\vi[vt],chunk\u[vt],chunk\v[vt],0,1
		Next
EndIf
	Next

	For recv.recv =Each recv
		ShowEntity recv\id
	Next
	CameraZoom lmap\scam,1
	SetBuffer BackBuffer()
	CameraViewport lmap\scam,0,0,GraphicsWidth(),GraphicsHeight()
	FreeImage tmpImg
End Function

Function TFormVector2(Ax#,Ay#,Az#,Bx#,By#,Bz#)
temp=CreatePivot()
AlignToVector temp,bx,0,0,1
AlignToVector temp,0,by,0,2
AlignToVector temp,0,0,bz,3
TFormVector ax,ay,az,0,temp
FreeEntity temp
End Function

Function max3#(a#,b#,c#)
	If a>b 
		If a>c Return a
		Return c
	EndIf
	If b>c Return b
	Return c
End Function
Function min3#(a#,b#,c#)
	If a<b 
		If a<c Return a
		Return c
	EndIf
	If b<c Return b
	Return c
End Function


Function texToImage(texture) ;converts a texture to an image
	out =CreateImage(TextureWidth(texture),TextureHeight(texture))
	CopyRect 0,0,TextureWidth(texture),TextureHeight(texture),0,0,TextureBuffer(texture),ImageBuffer(out)
	Return out
End Function


;-- 3rd party functions. 

Function dot(x0#,y0#,x1#,y1#,x2#,y2#)

Return (x1#-x0#)*(y2#-y1#)-(x2#-x1#)*(y1#-y0#)

End Function

Function inTri(px#,py#,x0#,y0#,x1#,y1#,x2#,y2#)

If dot(x0,y0,x1,y1,px,py)>=0

If dot(x1,y1,x2,y2,px,py)>=0

If dot(x2,y2,x0,y0,px,py)>=0

Return True

EndIf

EndIf

EndIf

End Function


Global g_TriNormalX#, g_TriNormalY#, g_TriNormalZ#

Function TriNorm(x1#, y1#, z1#, x2#, y2#, z2#, x3#, y3#, z3#)
    ux# = x1# - x2#
    uy# = y1# - y2#
    uz# = z1# - z2#
    vx# = x3# - x2#
    vy# = y3# - y2#
    vz# = z3# - z2#	
	nx# = (uy# * vz#) - (vy# * uz#)
    ny# = (uz# * vx#) - (vz# * ux#)  
    nz# = (ux# * vy#) - (vx# * uy#)
; Normalize it
    NormLen# = Sqr((nx*nx) + (ny*ny) + (nz*nz))  
    If NormLen > 0
		nx = nx/NormLen : ny = ny/NormLen: nz = nz/NormLen
	Else
		nx = 0 : ny = 0 : nz = 1
	EndIf
	g_TriNormalX = nx
	g_TriNormalY = ny
	g_TriNormalZ = nz
End Function
Dim txv#(3) 
Type TRIS
Field x0#
Field y0#
Field z0#
Field u0#
Field v0#
Field U20#
Field V20#

Field x1#
Field y1#
Field z1#
Field u1#
Field v1#
Field U21#
Field V21#

Field x2#
Field y2#
Field z2#
Field u2#
Field v2#
Field U22#
Field V22#

Field surface
End Type

Function Weld(mish)
Dim txv(3)


For nsurf = 1 To CountSurfaces(mish)
su=GetSurface(mish,nsurf)
For tq = 0 To CountTriangles(su)-1
txv(0) = TriangleVertex(su,tq,0)
txv(1) = TriangleVertex(su,tq,1)
txv(2) = TriangleVertex(su,tq,2)
vq.TRIS = New TRIS
 
vq\x0# = VertexX(su,txv(0))
vq\y0# = VertexY(su,txv(0))
vq\z0# = VertexZ(su,txv(0))
vq\u0# = VertexU(su,txv(0),0)
vq\v0# = VertexV(su,txv(0),0)
vq\u20# = VertexU(su,txv(0),1)
vq\v20# = VertexV(su,txv(0),1)

vq\x1# = VertexX(su,txv(1))
vq\y1# = VertexY(su,txv(1))
vq\z1# = VertexZ(su,txv(1))
vq\u1# = VertexU(su,txv(1),0)
vq\v1# = VertexV(su,txv(1),0)
vq\u21# = VertexU(su,txv(1),1)
vq\v21# = VertexV(su,txv(1),1)

vq\x2# = VertexX(su,txv(2))
vq\y2# = VertexY(su,txv(2))
vq\z2# = VertexZ(su,txv(2))
vq\u2# = VertexU(su,txv(2),0)
vq\v2# = VertexV(su,txv(2),0)
vq\u22# = VertexU(su,txv(2),1)
vq\v22# = VertexV(su,txv(2),1)
Next

ClearSurface su

For vq.tris = Each tris

vt1=findvert(su,vq\x0#,vq\y0#,vq\z0#,vq\u0#,vq\v0#,vq\u20#,vq\v20#)

If vt1=-1 Then
vt1=AddVertex(su,vq\x0#,vq\y0#,vq\z0#,vq\u0#,vq\v0#)
VertexTexCoords su,mycount,vq\u20#,vq\v20#,0,1
vt1 = mycount
mycount = mycount +1
EndIf

vt2=findvert(su,vq\x1#,vq\y1#,vq\z1#,vq\u1#,vq\v1#,vq\u21#,vq\v21#)
If Vt2=-1 Then
vt2=AddVertex( su,vq\x1#,vq\y1#,vq\z1#,vq\u1#,vq\v1#)
VertexTexCoords su,mycount,vq\u21#,vq\v21#,0,1
vt2 = mycount
mycount = mycount +1
EndIf

vt3=findvert(su,vq\x2#,vq\y2#,vq\z2#,vq\u2#,vq\v2#,vq\u22#,vq\v22#)

If vt3=-1 Then 
vt3=AddVertex(su,vq\x2#,vq\y2#,vq\z2#,vq\u2#,vq\v2#)
VertexTexCoords su,mycount,vq\u22#,vq\v22#,0,1
vt3 = mycount
mycount = mycount +1
EndIf

AddTriangle su,vt1,vt2,vt3

Next

Delete Each tris
mycount=0
Next
End Function

Function findvert(su,x2#,y2#,z2#,u2#,v2#,u22#,v22#)
Local thresh# =0.001

For t=0 To CountVertices(su)-1
If Abs(VertexX(su,t)-x2#)<thresh# Then 
If Abs(VertexY(su,t)-y2#)<thresh# Then 
If Abs(VertexZ(su,t)-z2#)<thresh# Then 
If Abs(VertexU(su,t,0)-u2#)<thresh# Then 
If Abs(VertexV(su,t,0)-v2#)<thresh# Then 
If Abs(VertexU(su,t,1)-u22#)<thresh# Then 
If Abs(VertexV(su,t,1)-v22#)<thresh# Then
Return t
EndIf
EndIf
EndIf
EndIf
EndIf
EndIf
EndIf
Next
Return -1
End Function

Function debugMeshUV( mesh)
	srf =GetSurface(mesh,1)

		For v=0 To CountVertices(srf)-2
			DebugLog "U1>"+VertexU(srf,v,0)
			DebugLog "U2>"+VertexU(srf,v,0)
			DebugLog "V1>"+VertexV(srf,v,0)
			DebugLog "V2>"+VertexV(srf,v,0)
			VertexTexCoords srf,v,Rnd(0.3),Rnd(0.3)
		Next


	
End Function


Function debugLeafs(doLog=True)
If doLog=4
	For leaf.leaf =Each leaf
		DebugLog "=-=-=-=-=-=-=-=-=-=-"
		If leaf\on
			DebugLog "Active leaf"
		EndIf
		DebugLog "X:"+leaf\x+" Y:"+leaf\y+" W:"+leaf\w+" H:"+leaf\h
	Next
EndIf
	;Return
	If Not MouseDown(1) Return
	For leaf.leaf =Each leaf
		Color 128,128,128
		Rect leaf\x,leaf\y,leaf\w,leaf\h
		Color 255,255,255
		Rect leaf\x,leaf\y,leaf\w,leaf\h,0
	Next
End Function


Function Unweld(mesh)
;Unweld a mesh, retaining all of its textures coords and textures
For surfcount = 1 To CountSurfaces(mesh)
surf = GetSurface(mesh,surfcount)

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)
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)
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)
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
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)
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)
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)
c = AddVertex(surf,x,y,z,u,v)
AddTriangle(surf,a,b,c)
Next
FreeBank bank

Next
;UpdateNormals mesh


Return mesh
End Function

Function TNormX#()
	Return g_TriNormalX
End Function
Function TNormY#()
	Return g_TriNormalY
End Function
Function TNormZ#()
	Return g_TriNormalZ
End Function

; Load in animation sequences
;Idle=ExtractAnimSeq(gsg9,100,159)
;Run=ExtractAnimSeq(gsg9,2,37)
;Jump=ExtractAnimSeq(gsg9,38,99)
;Crouch=ExtractAnimSeq(gsg9,161,190)
;CrouchWalk=ExtractAnimSeq(gsg9,192,220)




; PickedU(), PickedV(), PickedW() commands 
;
; Created by Mikkel Fredborg
; 
; Use as you please, but please include a thank you :)
;

;
; PickedTri type
; Necessary for the PickedU(), PickedV(), and PickedW() commands
Type PickedTri
Field ent,surf,tri;picked entity, surface and triangle
Field px#,py#,pz#    ;picked xyz
Field pu#[1],  pv#[1]  ,pw#[1]  ;picked uvw x 2

Field vx#[2],  vy#[2]  ,vz#[2]  ;vertex xyz
Field vnx#[2], vny#[2] ,vnz#[2] ;vertex normals
Field vu#[5],  vv#[5]  ,vw#[5]  ;vertex uvw x 2
End Type



;
; Returns the Texture U coordinate of the last successful pick command
; coordset may be set to either 0 or 1
Function PickedU#(coordset = 0)

; if something new has been picked then calculate the new uvw coordinates


Return ptri\pu[coordset]

End Function

;
; Returns the Texture U coordinate of the last successful pick command
; coordset may be set to either 0 or 1
Function PickedV#(coordset = 0)

; if something new has been picked then calculate the new uvw coordinates

Return ptri\pv[coordset]

End Function

;
; Returns the Texture U coordinate of the last successful pick command
; coordset may be set to either 0 or 1
Function PickedW#(coordset = 0)

; if something new has been picked then calculate the new uvw coordinates


Return ptri\pw[coordset]

End Function

;
; Calculates the UVW coordinates of a pick
; Do not call this by yourself, as PickedU(), PickedV(), and PickedW()
; takes care of calling it when nescessary
Function PickedUVW(ent,surf,tri,x#,y#,z#,nx#,ny#,nz#)

If surf
ptri\ent  = ent
ptri\surf = surf
ptri\tri  = tri


ptri\px = x
ptri\py = y
ptri\pz = z

For i = 0 To 2
TFormPoint VertexX(ptri\surf,TriangleVertex(ptri\surf,ptri\tri,i)),VertexY(ptri\surf,TriangleVertex(ptri\surf,ptri\tri,i)),VertexZ(ptri\surf,TriangleVertex(ptri\surf,ptri\tri,i)),ptri\ent,0

ptri\vx[i] = TFormedX()
ptri\vy[i] = TFormedY()
ptri\vz[i] = TFormedZ()

ptri\vnx[i] = VertexNX(ptri\surf,TriangleVertex(ptri\surf,ptri\tri,i))
ptri\vny[i] = VertexNY(ptri\surf,TriangleVertex(ptri\surf,ptri\tri,i))
ptri\vnz[i] = VertexNZ(ptri\surf,TriangleVertex(ptri\surf,ptri\tri,i))

ptri\vu[i+0] = VertexU(ptri\surf,TriangleVertex(ptri\surf,ptri\tri,i),0)
ptri\vv[i+0] = VertexV(ptri\surf,TriangleVertex(ptri\surf,ptri\tri,i),0)
ptri\vw[i+0] = VertexW(ptri\surf,TriangleVertex(ptri\surf,ptri\tri,i),0)

ptri\vu[i+3] = VertexU(ptri\surf,TriangleVertex(ptri\surf,ptri\tri,i),1)
ptri\vv[i+3] = VertexV(ptri\surf,TriangleVertex(ptri\surf,ptri\tri,i),1)
ptri\vw[i+3] = VertexW(ptri\surf,TriangleVertex(ptri\surf,ptri\tri,i),1)
Next

; Select which component of xyz coordinates to ignore
Local coords = 3

If Abs(NX) > Abs(NY)
If Abs(NX)>Abs(NZ) Then coords = 1
Else
If Abs(NY)>Abs(NZ) Then coords = 2
EndIf

Local a0#,a1#,b0#,b1#,c0#,c1#

; xy components
If (coords = 3)
; edge 0
a0# = ptri\vx[1] - ptri\vx[0]
a1# = ptri\vy[1] - ptri\vy[0]

; edge 1
b0# = ptri\vx[2] - ptri\vx[0]
b1# = ptri\vy[2] - ptri\vy[0]

; picked offset from triangle vertex 0
c0# =ptri\px - ptri\vx[0]
c1# = ptri\py - ptri\vy[0]
Else
; xz components
If (coords = 2)
; edge 0
a0# = ptri\vx[1] - ptri\vx[0]
a1# = ptri\vz[1] - ptri\vz[0]

; edge 1
b0# = ptri\vx[2] - ptri\vx[0]
b1# = ptri\vz[2] - ptri\vz[0]

; picked offset from triangle vertex 0
c0# = ptri\px - ptri\vx[0]
c1# = ptri\pz - ptri\vz[0]
Else
; yz components

; edge 0
a0# = ptri\vy[1] - ptri\vy[0]
a1# = ptri\vz[1] - ptri\vz[0]

; edge 1
b0# = ptri\vy[2] - ptri\vy[0]
b1# = ptri\vz[2] - ptri\vz[0]

; picked offset from triangle vertex 0
c0# = ptri\py - ptri\vy[0]
c1# = ptri\pz - ptri\vz[0]
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)

; If either u or v is out of range then the
; picked entity was not a mesh, and therefore
; the uvw coordinates cannot be calculated
If (u<0.0 Or u>1.0) Or (v<0.0 Or v>1.0)
Return 
End If

; Calculate picked uvw's for coordset 0 (and modulate them to be in the range of 0-1 nescessary)
ptri\pu[0] = (ptri\vu[0] + ((ptri\vu[1] - ptri\vu[0]) * u) + ((ptri\vu[2] - ptri\vu[0]) * v)) Mod 1
ptri\pv[0] = (ptri\vv[0] + ((ptri\vv[1] - ptri\vv[0]) * u) + ((ptri\vv[2] - ptri\vv[0]) * v)) Mod 1
ptri\pw[0] = (ptri\vw[0] + ((ptri\vw[1] - ptri\vw[0]) * u) + ((ptri\vw[2] - ptri\vw[0]) * v)) Mod 1

; If any of the coords are negative
If ptri\pu[0]<0.0 Then ptri\pu[0] = 1.0 + ptri\pu[0]
If ptri\pv[0]<0.0 Then ptri\pv[0] = 1.0 + ptri\pv[0]
If ptri\pw[0]<0.0 Then ptri\pw[0] = 1.0 + ptri\pw[0]

; Calculate picked uvw's for coordset 1 (and modulate them to be in the range of 0-1 nescessary)
ptri\pu[1] = (ptri\vu[3] + ((ptri\vu[4] - ptri\vu[3]) * u) + ((ptri\vu[5] - ptri\vu[3]) * v)) Mod 1
ptri\pv[1] = (ptri\vv[3] + ((ptri\vv[4] - ptri\vv[3]) * u) + ((ptri\vv[5] - ptri\vv[3]) * v)) Mod 1
ptri\pw[1] = (ptri\vw[3] + ((ptri\vw[4] - ptri\vw[3]) * u) + ((ptri\vw[5] - ptri\vw[3]) * v)) Mod 1

; If any of the coords are negative
If ptri\pu[1]<0.0 Then ptri\pu[1] = 1.0 + ptri\pu[1]
If ptri\pv[1]<0.0 Then ptri\pv[1] = 1.0 + ptri\pv[1]
If ptri\pw[1]<0.0 Then ptri\pw[1] = 1.0 + ptri\pw[1]
End If

End Function




;

Comments

Olive2004
Impressive work !

I'll try it asap, thanks for sharing.


Damien Sturdy2004
get rid of the read only attribs ;)


otherwise this is cool :D


AntonyWells2004
get rid of the read only attribs ;)


Now, you're either implying I only read replies without actually replying myself, or you're telling me the source can't be altered in your editor, or you're joking 'cos you can't edit the html display. ;p

Help me to help you. :)


AntonyWells2004
dp


jfk EO-111102004
I say too: impressive work. No idea about that read-only thing. Anyway. This may be a true alternative to all shadowing and lightmapping stuff we've seen so far.


AntonyWells2004
Thanks Jfk. I plan on doing a uber new version for vivid at some point, so it's nice to know it's not unadulterated crap in everyone elses eyes ;)(My first lightmapper is all)


Damien Sturdy2005
Heh, sorry, reading my above post i have no idea what i was going on about, though it might have been a problem with the contents of the ZIP file.. :)


Megalomanic2007
Where is the ZIP file? Does anyone have the resources?


Code Archives Forum