SyntaxBomb - Indie Coders

Languages & Coding => Blitz Code Archives => 3D Graphics - Effects => Topic started by: BlitzBot on June 29, 2017, 00:28:42

Title: [bb] Omni Light/Normal Mapper by AntonyWells [ 1+ years ago ]
Post by: BlitzBot on June 29, 2017, 00:28:42
Title : Omni Light/Normal Mapper
Author : AntonyWells
Posted : 1+ years ago

Description : 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.


Code :
Code (blitzbasic) Select
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 horn ex5.bmp")

rock=LoadTexture("units horn ex2.jpg")
tock=LoadTexture("units horn ex2.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("unitshovermain.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)
lMapsw =width
lMapsh =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
recvid =mesh
recvcw=cw
recvch=ch
recvhull=hull
;EntityFX mesh,2
End Function

Function addCaster(mesh)
cast.cast =New cast
castid =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
lightx =x
lighty =y
lightz =z
light =r
lightg =g
light =b
lightfallOff=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 recvid,2,True
HideEntity recvid
Next
For cast.cast =Each cast
HideEntity castid
Next
CameraViewport cam,0,0,shadeWidth,shadeHeight
CameraZoom cam,1.8
mapWidth =GraphicsWidth()
mapHeight =GraphicsHeight()

For light.light =Each light
PositionEntity cam,lightx,lighty,lightz
For cast.cast =Each cast
lightshade[lightsc] =New shadeMap
shademap.shademap =lightshade[lightsc]
lightsc=lightsc+1
shadeMapcast =cast
PointEntity cam,castid
ShowEntity castid
Cls
RenderWorld
HideEntity castid
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 shadeMapx[px]=Null shadeMapx[px] =New yl
shadeMapx[px]y[py] =True
EndIf
Next
Next
UnlockBuffer
Next

Next



For cast.cast =Each cast
ShowEntity castid
Next


Goto skipnew
For light.light =Each light ;create shadow segs'
PositionEntity cam,lightx,lighty,lightz
For cast.cast =Each cast
PointEntity cam,castid
For sc =1 To CountSurfaces( castid)
srf =GetSurface( castid,sc)
For t=1 To CountTriangles( srf)
shade.shade =New shade
shademsh =castid
shadelight =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)
shadesx[vt] =ProjectedX()
shadesy[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(recvid)
cy#=EntityY(recvid)
cz#=EntityZ(recvid)
;recvcx=cx
; recvcy=cy
; recvcz=cz

unweld(recvid)
HideEntity recvid
EntityTexture recvid,lMap exMap,0,0
; EntityFX recvid,1
sC =CountSurfaces( recvid)
;UpdateNormals recvid
If sc
For s=1 To sc
srf =GetSurface( recvid,s)
tris =CountTriangles( srf)

For tri=0 To tris
chunk.chunk =New chunk
chunkcx=cx
chunkcy=cy
chunkcz=cz
chunk ri=tri
chunkent=recvid
chunksrf=srf
chunkentX=EntityY(recvid)
chunkentY=EntityX(recvid)
chunkentZ=EntityZ(recvid)
chunkhull=recvhull

chunkcw =recvcw
chunkmesh =recvid
chunkch =recvch
chunksrf =srf
chunklit =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)
chunkx[vt] =x[vt]
chunky[vt] =y[vt]
chunkz[vt] =z[vt]
chunkvi[vt] =vi
Else
Delete chunk
Goto skipChunk
EndIf
Next
triNorm( chunkx[0],chunky[0],chunkz[0],chunkx[1],chunky[1],chunkz[1],chunkx[2],chunky[2],chunkz[2])
nx#=tnormX()
ny#=tnormY()
nz#=tnormZ()




If Abs(nx)>Abs(ny) And Abs(nx)>Abs(nz)
chunkpTex =1
;map onto yz-plane
Else
If Abs(ny)>Abs(nx) And Abs(ny)>Abs(nz)
chunkpTex =2
Else
chunkpTex =3
EndIf
EndIf
.skipChunk
Next
Next
EndIf

Next
If mode=1 tr =normalChunks()
If mode=2 tr =lightChunks()
For recv.recv =Each recv
;UpdateNormals recvid
ShowEntity recvid
Next
CameraViewport cam,0,0,GraphicsWidth(),GraphicsHeight()
CameraZoom cam,1
For cast.cast =Each cast
ShowEntity castid
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 exMap =CreateTexture(lMapWidth,lMapHeight,8)
lmap exBuf =TextureBuffer(lMap exMap)
TextureCoords lmap exMap,1 ;set to the second u,v set.
imap=lmap exmap

TextureBlend lmap exMap,3
End Function
Function setLightCam(cam)
lmapscam =cam
CameraClsMode lmapscam,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 ree =Null ;first image
lMap ree =New leaf
lMap reew =lMapWidth
lMap reeh =lMapHeight
EndIf
For leaf.leaf =Each leaf
out.leaf =insertLeaf( leaf,texture)
If out<>Null Return out
Next
;Return addLeaf( lMap ree,texture)
End Function


Function insertLeaf.leaf( leaf.leaf,texture)
width =TextureWidth(texture)
height =TextureHeight(texture)

If leafon Return

If width<=leafw And height<=leafh ;fits
leafon =True

leafleaf[0] =New leaf
leafleaf[1] =New leaf
leafleaf[0]x =leafx+width
leafleaf[0]y =leafy
leafleaf[0]w =leafw-width-1
leafleaf[0]h =height

leafleaf[1]x =leafx
leafleaf[1]y =leafy+height
leafleaf[1]w =leafw
leafleaf[1]h =leafh-height

leafw =width
leafh =height
CopyRect 0,0,width,height,leafx,leafy,TextureBuffer(texture),lMap exBuf
Return leaf
EndIf
End Function


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

If leafon

    nleaf =insertLeaf( leafleaf[0],texture)
If nleaf<>Null Return nleaf
nleaf =insertLeaf( leafleaf[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 ((leafx+1)+((leafw-2)*u))/lMapWidth
End Function

Function leafV#(leaf.leaf,v#)
Return ((leafy+1)+((leafh-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 chunklit
;-fx

;----
For vt=0 To 2
chunkshim[vt] =Rnd(360)
Select chunkpTex
Case 1 ;yz
u[vt] =chunky[vt]
v[vt] =chunkz[vt]
Case 2 ;xz
u[vt] =chunkx[vt]
v[vt] =chunkz[vt]
Case 3 ;xy
u[vt] =chunkx[vt]
v[vt] =chunky[vt]
Default
RuntimeError "Illegal projection plane"
End Select
Next
triNorm( chunkx[0],chunky[0],chunkz[0],chunkx[1],chunky[1],chunkz[1],chunkx[2],chunky[2],chunkz[2])

;TriNorm( x[0],y[0],z[0],x[1],y[1],z[1],x[2],y[2],z[2])
chunk
X# =tNormX()
chunk
y =tNormY()
chunk
z =tNormZ()





;tnx#=chunk
x
;tny#=chunk
y
;tnz#=chunk
z


;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 =chunkcw
mapHeight =chunkch

tempMap =CreateTexture( mapWidth,mapHeight,256)
If Not tempMap Return
For vt=0 To 2
chunku[vt] =(u[vt]-miU) /rU
chunkv[vt] =(v[vt]-miV) /rV
Next


    dist# = -(chunk
x * chunkx[0]+chunk
y*chunky[1]+chunk
z*chunkz[2])
Select chunkpTex
Case 3

Z# = -(chunk
x*miU + chunk
y * miV + Dist) / chunk
z
uvx# = miu : UVY# = miV : UVZ# = Z
Z# = -(chunkNX * maU + chunkNY * miV + Dist) / chunkNZ
V1X# = maU : V1Y# = miV : V1Z# = Z
Z# = -(chunkNX * miu + chunkNY * maV + Dist) / chunkNZ
V2X# = miu : V2Y# = maV : V2Z# = Z
Case 2
Y# = -(chunkNX * miu + chunkNZ * miV + Dist) / chunkNY
UVX# = miu : UVY# = Y : UVZ# = miV
Y# = -(chunkNX * maU + chunkNZ * miV + Dist) / chunkNY
V1X# = maU : V1Y# = Y : V1Z# = miV
Y# = -(chunkNX * miu + chunkNZ * maV + Dist) / chunkNY
V2X# = miu : V2Y# = Y : V2Z# = maV
Case 1
X# = -(chunkNY * miu + chunkNZ * miV + Dist) / chunkNX
UVX# = X : UVY# = miu : UVZ# = miV
X# = -(chunkNY * maU + chunkNZ * miV + Dist) / chunkNX
V1X# = X : V1Y# = maU : V1Z# = miV
X# = -(chunkNY * miu + chunkNZ * maV + Dist) / chunkNX
V2X# = X : V2Y# = miu : V2Z# = maV
End Select
chunkeux = V1X - UVX : chunkeuy = V1Y - UVY : chunkeuz = V1Z - UVZ
chunkevx = V2X - UVX : chunkevy = V2Y - UVY : chunkevz = V2Z - UVZ
chunkox = UVX# : chunkoy = UVY# : chunkoz = UVZ#

;dx# =chunkox

ox#=md( chunkx[0],chunkx[1],chunkx[2])
oy#=md( chunky[0],chunky[1],chunky[2])
oz#=md( chunkz[0],chunkz[1],chunkz[2])
; ox=ox+chunkcx

;DebugLog chunkcx+" Oy>"+chunkcy+" oz>"+chunkcz
If chunkhull
ox=-ox
oy=-oy
oz=-oz
; dx#=ox-chunkcx
; dy#=oy-chunkcy
; dz#=oz-chunkcz
Else
; dx =chunkcx-ox
; dy =chunkcy-oy
; dz =chunkcz-oz

EndIf
; ox=ox-chunkcx
; oy=oy-chunkcy
; oz=oz-chunkcz

;nl# =Sqr(ox*ox+oy*oy+oz*oz)
; tnx#=(ox)/nl
; tny#=(oy)/nl
; tnz#=(oz)/nl
; ox=chunkcx+ox
; oy=chunkcy+oy
; oz=chunkcz+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,chunkcx,chunkcy,chunkcz

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#=chunkentX
entY#=chunkentY
entZ#=chunkentZ
If chunkhull dir#=1 Else dir=-1
PositionEntity spiv,chunkcx,chunkcy,chunkcz
tw#=TextureWidth(vest)
th#=TextureHeight(vest)

For x#=0 To mapWidth-1
au# = x/mapwidth
N_UEdgeX# = chunkEuX * au#  :  N_UEdgeY# = chunkeuY * au#  :  N_UEdgeZ# = chunkeuZ * au#
For y#=0 To mapHeight-1
av# = y/mapHeight
N_VEdgeX# = chunkevX * av#  :  N_VEdgeY# = chunkevY * av#  :  N_VEdgeZ# = chunkevZ * av#
lx# = (chunkox + N_UEdgeX + N_VEdgeX)
ly# = (chunkoy + N_UEdgeY + N_VEdgeY)
lz# = (chunkoz + 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 lmapscam,lightx,lighty,lightz
; shaded=False
; If lightsc
; For j=0 To lightsc-1
; shade.shadeMap =lightshade[j]
; PointEntity lmapscam,shadecastid
; If shadecastid =chunkmesh Goto skips
; CameraProject lmapscam,lx,ly,lz
; px =ProjectedX()
; If px>0 And px<shadeWidth
; If shadex[px]<>Null
; py =ProjectedY()
; If py>0 And py<shadeHeight
; shaded =shadex[px]y[py]
; If shaded Exit
; EndIf
; EndIf
; EndIf
; .skips
; Next
; EndIf
; If Not shaded

; PositionEntity spiv,lightx,lighty,lightz
; ed# =(EntityDistance(spiv,lpiv1)*lightfallOff)
;
; r1=(light-ed)
; g1=(lightg-ed)
; b1=(light-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-chunkcx)
; yd#=(ly-chunkcy)
; zd#=(lz-chunkcz)
;I;f chunkhull=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(chunkent,chunksrf,chunk ri,lx,ly,lz,chunk
x,chunk
y,chunk
z)
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)
chunkleaf =leaf
FreeTexture tempMap
For vt=0 To 2 ;map lightmap onto mesh
chunku[vt] =leafU(leaf,chunku[vt])
chunkv[vt] =leafV(leaf,chunkv[vt])
VertexTexCoords chunksrf,chunkvi[vt],chunku[vt],chunkv[vt],0,1
Next
EndIf
Next

For recv.recv =Each recv
ShowEntity recvid
Next
CameraZoom lmapscam,1
SetBuffer BackBuffer()
CameraViewport lmapscam,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 chunklit
;-fx

;----
For vt=0 To 2
chunkshim[vt] =Rnd(360)
Select chunkpTex
Case 1 ;yz
u[vt] =chunky[vt]
v[vt] =chunkz[vt]
Case 2 ;xz
u[vt] =chunkx[vt]
v[vt] =chunkz[vt]
Case 3 ;xy
u[vt] =chunkx[vt]
v[vt] =chunky[vt]
Default
RuntimeError "Illegal projection plane"
End Select
Next
triNorm( chunkx[0],chunky[0],chunkz[0],chunkx[1],chunky[1],chunkz[1],chunkx[2],chunky[2],chunkz[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 =chunkcw
mapHeight =chunkch

tempMap =CreateTexture( mapWidth,mapHeight,256)
If Not tempMap Return
For vt=0 To 2
chunku[vt] =(u[vt]-miU) /rU
chunkv[vt] =(v[vt]-miV) /rV
Next


    dist# = -(chunk
x * chunkx[0]+chunk
y*chunky[1]+chunk
z*chunkz[2])
Select chunkpTex
Case 3

Z# = -(chunk
x*miU + chunk
y * miV + Dist) / chunk
z
uvx# = miu : UVY# = miV : UVZ# = Z
Z# = -(chunkNX * maU + chunkNY * miV + Dist) / chunkNZ
V1X# = maU : V1Y# = miV : V1Z# = Z
Z# = -(chunkNX * miu + chunkNY * maV + Dist) / chunkNZ
V2X# = miu : V2Y# = maV : V2Z# = Z
Case 2
Y# = -(chunkNX * miu + chunkNZ * miV + Dist) / chunkNY
UVX# = miu : UVY# = Y : UVZ# = miV
Y# = -(chunkNX * maU + chunkNZ * miV + Dist) / chunkNY
V1X# = maU : V1Y# = Y : V1Z# = miV
Y# = -(chunkNX * miu + chunkNZ * maV + Dist) / chunkNY
V2X# = miu : V2Y# = Y : V2Z# = maV
Case 1
X# = -(chunkNY * miu + chunkNZ * miV + Dist) / chunkNX
UVX# = X : UVY# = miu : UVZ# = miV
X# = -(chunkNY * maU + chunkNZ * miV + Dist) / chunkNX
V1X# = X : V1Y# = maU : V1Z# = miV
X# = -(chunkNY * miu + chunkNZ * maV + Dist) / chunkNX
V2X# = X : V2Y# = miu : V2Z# = maV
End Select
chunkeux = V1X - UVX : chunkeuy = V1Y - UVY : chunkeuz = V1Z - UVZ
chunkevx = V2X - UVX : chunkevy = V2Y - UVY : chunkevz = V2Z - UVZ
chunkox = UVX# : chunkoy = UVY# : chunkoz = 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# = chunkEuX * au#  :  N_UEdgeY# = chunkeuY * au#  :  N_UEdgeZ# = chunkeuZ * au#
For y#=0 To mapHeight-1
av# = y/mapHeight
N_VEdgeX# = chunkevX * av#  :  N_VEdgeY# = chunkevY * av#  :  N_VEdgeZ# = chunkevZ * av#
lx# = (chunkox + N_UEdgeX + N_VEdgeX)
ly# = (chunkoy + N_UEdgeY + N_VEdgeY)
lz# = (chunkoz + N_UEdgeZ + N_VEdgeZ)

shaded =False
lcast.cast=Null
r1=0
g1=0
b1=0

For light.light =Each light
PositionEntity lmapscam,lightx,lighty,lightz
shaded=False
If lightsc
For j=0 To lightsc-1
shade.shadeMap =lightshade[j]
PointEntity lmapscam,shadecastid
If shadecastid =chunkmesh Goto skips
CameraProject lmapscam,lx,ly,lz
px =ProjectedX()
If px>0 And px<shadeWidth
If shadex[px]<>Null
py =ProjectedY()
If py>0 And py<shadeHeight
shaded =shadex[px]y[py]
If shaded Exit
EndIf
EndIf
EndIf
.skips
Next
EndIf
If Not shaded
PositionEntity lpiv1,lx,ly,lz
PositionEntity spiv,lightx,lighty,lightz
ed# =(EntityDistance(spiv,lpiv1)*lightfallOff)

r1=(light-ed)
g1=(lightg-ed)
b1=(light-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)
chunkleaf =leaf
FreeTexture tempMap
For vt=0 To 2 ;map lightmap onto mesh
chunku[vt] =leafU(leaf,chunku[vt])
chunkv[vt] =leafV(leaf,chunkv[vt])
VertexTexCoords chunksrf,chunkvi[vt],chunku[vt],chunkv[vt],0,1
Next
EndIf
Next

For recv.recv =Each recv
ShowEntity recvid
Next
CameraZoom lmapscam,1
SetBuffer BackBuffer()
CameraViewport lmapscam,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
 
vqx0# = VertexX(su,txv(0))
vqy0# = VertexY(su,txv(0))
vqz0# = VertexZ(su,txv(0))
vqu0# = VertexU(su,txv(0),0)
vqv0# = VertexV(su,txv(0),0)
vqu20# = VertexU(su,txv(0),1)
vqv20# = VertexV(su,txv(0),1)

vqx1# = VertexX(su,txv(1))
vqy1# = VertexY(su,txv(1))
vqz1# = VertexZ(su,txv(1))
vqu1# = VertexU(su,txv(1),0)
vqv1# = VertexV(su,txv(1),0)
vqu21# = VertexU(su,txv(1),1)
vqv21# = VertexV(su,txv(1),1)

vqx2# = VertexX(su,txv(2))
vqy2# = VertexY(su,txv(2))
vqz2# = VertexZ(su,txv(2))
vqu2# = VertexU(su,txv(2),0)
vqv2# = VertexV(su,txv(2),0)
vqu22# = VertexU(su,txv(2),1)
vqv22# = VertexV(su,txv(2),1)
Next

ClearSurface su

For vq.tris = Each tris

vt1=findvert(su,vqx0#,vqy0#,vqz0#,vqu0#,vqv0#,vqu20#,vqv20#)

If vt1=-1 Then
vt1=AddVertex(su,vqx0#,vqy0#,vqz0#,vqu0#,vqv0#)
VertexTexCoords su,mycount,vqu20#,vqv20#,0,1
vt1 = mycount
mycount = mycount +1
EndIf

vt2=findvert(su,vqx1#,vqy1#,vqz1#,vqu1#,vqv1#,vqu21#,vqv21#)
If Vt2=-1 Then
vt2=AddVertex( su,vqx1#,vqy1#,vqz1#,vqu1#,vqv1#)
VertexTexCoords su,mycount,vqu21#,vqv21#,0,1
vt2 = mycount
mycount = mycount +1
EndIf

vt3=findvert(su,vqx2#,vqy2#,vqz2#,vqu2#,vqv2#,vqu22#,vqv22#)

If vt3=-1 Then
vt3=AddVertex(su,vqx2#,vqy2#,vqz2#,vqu2#,vqv2#)
VertexTexCoords su,mycount,vqu22#,vqv22#,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 leafon
DebugLog "Active leaf"
EndIf
DebugLog "X:"+leafx+" Y:"+leafy+" W:"+leafw+" H:"+leafh
Next
EndIf
;Return
If Not MouseDown(1) Return
For leaf.leaf =Each leaf
Color 128,128,128
Rect leafx,leafy,leafw,leafh
Color 255,255,255
Rect leafx,leafy,leafw,leafh,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 ptripu[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 ptripv[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 ptripw[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
ptrient  = ent
ptrisurf = surf
ptri ri  = tri


ptripx = x
ptripy = y
ptripz = z

For i = 0 To 2
TFormPoint VertexX(ptrisurf,TriangleVertex(ptrisurf,ptri ri,i)),VertexY(ptrisurf,TriangleVertex(ptrisurf,ptri ri,i)),VertexZ(ptrisurf,TriangleVertex(ptrisurf,ptri ri,i)),ptrient,0

ptrivx[i] = TFormedX()
ptrivy[i] = TFormedY()
ptrivz[i] = TFormedZ()

ptrivnx[i] = VertexNX(ptrisurf,TriangleVertex(ptrisurf,ptri ri,i))
ptrivny[i] = VertexNY(ptrisurf,TriangleVertex(ptrisurf,ptri ri,i))
ptrivnz[i] = VertexNZ(ptrisurf,TriangleVertex(ptrisurf,ptri ri,i))

ptrivu[i+0] = VertexU(ptrisurf,TriangleVertex(ptrisurf,ptri ri,i),0)
ptrivv[i+0] = VertexV(ptrisurf,TriangleVertex(ptrisurf,ptri ri,i),0)
ptrivw[i+0] = VertexW(ptrisurf,TriangleVertex(ptrisurf,ptri ri,i),0)

ptrivu[i+3] = VertexU(ptrisurf,TriangleVertex(ptrisurf,ptri ri,i),1)
ptrivv[i+3] = VertexV(ptrisurf,TriangleVertex(ptrisurf,ptri ri,i),1)
ptrivw[i+3] = VertexW(ptrisurf,TriangleVertex(ptrisurf,ptri ri,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# = ptrivx[1] - ptrivx[0]
a1# = ptrivy[1] - ptrivy[0]

; edge 1
b0# = ptrivx[2] - ptrivx[0]
b1# = ptrivy[2] - ptrivy[0]

; picked offset from triangle vertex 0
c0# =ptripx - ptrivx[0]
c1# = ptripy - ptrivy[0]
Else
; xz components
If (coords = 2)
; edge 0
a0# = ptrivx[1] - ptrivx[0]
a1# = ptrivz[1] - ptrivz[0]

; edge 1
b0# = ptrivx[2] - ptrivx[0]
b1# = ptrivz[2] - ptrivz[0]

; picked offset from triangle vertex 0
c0# = ptripx - ptrivx[0]
c1# = ptripz - ptrivz[0]
Else
; yz components

; edge 0
a0# = ptrivy[1] - ptrivy[0]
a1# = ptrivz[1] - ptrivz[0]

; edge 1
b0# = ptrivy[2] - ptrivy[0]
b1# = ptrivz[2] - ptrivz[0]

; picked offset from triangle vertex 0
c0# = ptripy - ptrivy[0]
c1# = ptripz - ptrivz[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)
ptripu[0] = (ptrivu[0] + ((ptrivu[1] - ptrivu[0]) * u) + ((ptrivu[2] - ptrivu[0]) * v)) Mod 1
ptripv[0] = (ptrivv[0] + ((ptrivv[1] - ptrivv[0]) * u) + ((ptrivv[2] - ptrivv[0]) * v)) Mod 1
ptripw[0] = (ptrivw[0] + ((ptrivw[1] - ptrivw[0]) * u) + ((ptrivw[2] - ptrivw[0]) * v)) Mod 1

; If any of the coords are negative
If ptripu[0]<0.0 Then ptripu[0] = 1.0 + ptripu[0]
If ptripv[0]<0.0 Then ptripv[0] = 1.0 + ptripv[0]
If ptripw[0]<0.0 Then ptripw[0] = 1.0 + ptripw[0]

; Calculate picked uvw's for coordset 1 (and modulate them to be in the range of 0-1 nescessary)
ptripu[1] = (ptrivu[3] + ((ptrivu[4] - ptrivu[3]) * u) + ((ptrivu[5] - ptrivu[3]) * v)) Mod 1
ptripv[1] = (ptrivv[3] + ((ptrivv[4] - ptrivv[3]) * u) + ((ptrivv[5] - ptrivv[3]) * v)) Mod 1
ptripw[1] = (ptrivw[3] + ((ptrivw[4] - ptrivw[3]) * u) + ((ptrivw[5] - ptrivw[3]) * v)) Mod 1

; If any of the coords are negative
If ptripu[1]<0.0 Then ptripu[1] = 1.0 + ptripu[1]
If ptripv[1]<0.0 Then ptripv[1] = 1.0 + ptripv[1]
If ptripw[1]<0.0 Then ptripw[1] = 1.0 + ptripw[1]
End If

End Function




;


Comments :


Olive(Posted 1+ years ago)

 Impressive work !I'll try it asap, thanks for sharing.


Damien Sturdy(Posted 1+ years ago)

 get rid of the read only attribs ;)otherwise this is cool :D


AntonyWells(Posted 1+ years ago)

 <div class="quote"> get rid of the read only attribs ;) </div>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. ;pHelp me to help you. :)


AntonyWells(Posted 1+ years ago)

 dp


jfk EO-11110(Posted 1+ years ago)

 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.


AntonyWells(Posted 1+ years ago)

 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 Sturdy(Posted 1+ years ago)

 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.. :)


Megalomanic(Posted 1+ years ago)

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