Code archives/3D Graphics - Misc/Portable Lightmapper
This code has been declared by its author to be Public Domain code.
Download source code
| |||||
| Here is the lightmapper that I planned to release sooner or later. It isn't perfect, but good enough for my needs since it was only a test, to see I was capable of creating a lightmapper. The only requirement for using this lightmapper is to give me credit in any of the used programs. ReUpdated! Some Thanks to Olive and Peter! This now includes different sized lightmaps! Features Are: Lightmap Compression(Saves on one texture) Automatic Lightmap lumel size choser(Based on surface area) Eight very conveniant Lightmap Related functions! Very Cool Lightmap Sharing(Similar lightmaps share vertices) Suppports three types of light(Direct,Point,Spot) Open Source And Easy To Use! Example of Lightmap Sharing: Unshared lightmapped cube looks like this: But a shared lightmapped cube looks like this: Which takes up a lot less space, and is quicker to write! | |||||
;Simple Lightmap Package
;Open Source, by David Dawkins(Starfox)
;Some thanks go to Elias for his lightmapper!
;All meshes must be unwelded!
;Built in 9/07/02 - 11/29/02
;Added Lightmap Compression!
;Added Optimization, thanks to Olive!
;Added Automatic lightmap size choser
;Sped up lightmap placement
;Lightmap Sharing is now in!
;This now includes light types(1-Direct,2-Point,3-Spot)
;LightmapMesh(mesh,saveuvfilename,detail,lightmapsize,scale-true|false,AmR,G,B,Luminance,Share)
;CreatelmLight(x,y,z,red,green,blue,range,ltype)
;CreateLUVs(mesh,savefilename,coordset)
;LoadLUVs(mesh,openfilename,coordset)
;Unweld(mesh)
;LightmapTerrain(terrain,Amr,G,B,size,luminance)
Function example()
Graphics3D 640,480,0,2
cube = CreateCube() ;Create a object to lightmap
unweld(cube) ;try it without this line:)
EntityPickMode cube,2 ;Make sure that anything you want in the way is pickable
sha = CreateCube() ;Create a cube shadow
ScaleEntity sha,.25,.25,.25
MoveEntity sha,-3,0,0
EntityPickMode sha,2
CreateLight()
UpdateNormals cube
ScaleEntity cube,10,3,3
FlipMesh(cube) ;Make sure you are able to see inside out
cam = CreateCamera()
UpdateNormals cube
MoveEntity cam,0,0,-15
PointEntity cam,cube
EntityPickMode cube,2
;Create generic lights to do the lightmapping
createlmlight(0,0,0,0,0,255,25) ;Position the lights
createlmlight(-5,0,0,255,0,0,15) ;light 2 is at -5,0,0 and color is 255,0,0 and range is 20
While Not KeyHit(1)
If MouseHit(1)
CameraPick(cam,MouseX(),MouseY())
If PickedEntity()
en = PickedEntity()
food = MilliSecs()
tex = lightmapmesh(en,"",0,128,1,0,0,0,1,share) ;Lightmapper
EntityFX cube,1
time = MilliSecs() - food
EntityTexture en,tex
im = CreateImage(256,256)
CopyRect(0,0,256,256,0,0,TextureBuffer(tex),ImageBuffer(im))
FreeTexture tex
EndIf
EndIf
UpdateWorld
RenderWorld
Color 255,255,255
If im > 0
DrawImage im,0,0
EndIf
Text 0,30,"Time To Lightmap: "+time
Text 0,40,"Hit Space To Toggle Lightmap Sharing: "+share
Text 0,50,"Click On Object"
If KeyHit(57)
share = 1-share
EndIf
Flip
Wend
End
End Function
example() ;The example
Type tris
Field x#[3],y#[3],z#[3]
Field surf,index,mesh
Field ver[3],u#[3],v#[3]
Field tex,size#
Field xpos#,ypos#,hosttex
End Type
Type lmlight
Field x#,y#,z#,range#
Field r#,g#,b#,lmtype
Field inner,outer
Field pitch,yaw,roll
End Type
Type lightmapnode
Field x,y,size
End Type
Function LightmapMesh(mesh,luvsave$="",detail=16,bound=256,scaletex=1,ambr=0,ambg=0,ambb=0,lum#=1,share=0)
Local nx#,ny#,nz#,normlen#
Local imagepivot = CreatePivot()
EntityPickMode imagepivot,1:EntityRadius imagepivot,.625
Local lightpivot = CreatePivot()
For surfcount = 1 To CountSurfaces(mesh) ;Surface count
surf = GetSurface(mesh,surfcount)
For tricount = 0 To CountTriangles(surf)-1 ;Triangle count
;Prestuff
t.tris = New tris
t\surf = surf : t\mesh = mesh
t\index = tricount
in = TriangleVertex(t\surf,t\index,0)
t\x[1] = VertexX(surf,in) : t\y[1] = VertexY(surf,in)
t\z[1] = VertexZ(surf,in) : t\ver[1] = in
t\u[1] = VertexU(surf,in) : t\v[1] = VertexV(surf,in)
TFormPoint(t\x[1],t\y[1],t\z[1],t\mesh,0)
t\x[1] = TFormedX() : t\y[1] = TFormedY() : t\z[1] = TFormedZ()
in = TriangleVertex(t\surf,t\index,1)
t\x[2] = VertexX(surf,in) : t\y[2] = VertexY(surf,in)
t\z[2] = VertexZ(surf,in) : t\ver[2] = in
t\u[2] = VertexU(surf,in) : t\v[2] = VertexV(surf,in)
TFormPoint(t\x[2],t\y[2],t\z[2],t\mesh,0)
t\x[2] = TFormedX() : t\y[2] = TFormedY() : t\z[2] = TFormedZ()
in = TriangleVertex(t\surf,t\index,2)
t\x[3] = VertexX(surf,in) : t\y[3] = VertexY(surf,in)
t\z[3] = VertexZ(surf,in) : t\ver[3] = in
t\u[3] = VertexU(surf,in) : t\v[3] = VertexV(surf,in)
TFormPoint(t\x[3],t\y[3],t\z[3],t\mesh,0)
t\x[3] = TFormedX() : t\y[3] = TFormedY() : t\z[3] = TFormedZ()
VertexTexCoords t\surf,t\ver[1],t\u[1],t\v[1]
VertexTexCoords t\surf,t\ver[2],t\u[2],t\v[2]
VertexTexCoords t\surf,t\ver[3],t\u[3],t\v[3]
;Get the normals
nx = getnorm(t\x[1],t\y[1],t\z[1],t\x[2],t\y[2],t\z[2],t\x[3],t\y[3],t\z[3],1)
ny = getnorm(t\x[1],t\y[1],t\z[1],t\x[2],t\y[2],t\z[2],t\x[3],t\y[3],t\z[3],2)
nz = getnorm(t\x[1],t\y[1],t\z[1],t\x[2],t\y[2],t\z[2],t\x[3],t\y[3],t\z[3],3)
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
;End Pre
Local plane
Local uvmin#[2],uvmax#[2]
Local uvdelta#[2]
;Figure out the plane its on
uvxnorm# = nx : uvynorm# = ny : uvznorm# = nz
nx = Abs(nx) : ny = Abs(ny) : nz = Abs(nz)
plane = 3
If nx > ny And nx > nz Then plane = 1 ;YZ Right
If ny > nx And ny > nz Then plane = 2 ;XZ Top
If nz > nx And nz > ny Then plane = 3 ;XY Front
If nx = ny And nx = nz Then plane = 1
If nz = ny And nz = nx Then plane = 2
If nz = nx And nz = ny Then plane = 3
If plane = 2
t\u[1] = t\x[1] : t\v[1] = t\z[1] ;1st
t\u[2] = t\x[2] : t\v[2] = t\z[2] ;2nd
t\u[3] = t\x[3] : t\v[3] = t\z[3] ;3rd
ElseIf plane = 1
t\u[1] = t\y[1] : t\v[1] = t\z[1] ;1st
t\u[2] = t\y[2] : t\v[2] = t\z[2] ;2nd
t\u[3] = t\y[3] : t\v[3] = t\z[3] ;3rd
ElseIf plane = 3
t\u[1] = t\x[1] : t\v[1] = t\y[1] ;1st
t\u[2] = t\x[2] : t\v[2] = t\y[2] ;2nd
t\u[3] = t\x[3] : t\v[3] = t\y[3] ;3rd
EndIf
;Get the bounding box for the uv coords
uvmin[1] = t\u[1] : uvmin[2] = t\v[1]
uvmax[1] = t\u[1] : uvmax[2] = t\v[1]
For co = 1 To 3
If t\u[co] < uvmin[1] Then uvmin[1] = t\u[co];If U is < uv minimun u then uvmin u = U
If t\v[co] < uvmin[2] Then uvmin[2] = t\v[co];If V is < uv minimun v then uvmin v = V
If t\u[co] > uvmax[1] Then uvmax[1] = t\u[co];If U is > uv maximum u then uvmax u = U
If t\v[co] > uvmax[2] Then uvmax[2] = t\v[co];If V is > uv maximum v then uvmax v = V
Next
uvdelta[1] = uvmax[1] - uvmin[1] ;U Delta = U Max - U Min
uvdelta[2] = uvmax[2] - uvmin[2] ;V Delta = V Max - V Min
;Now make it a range from 0.0 to 1.0
For co = 1 To 3
t\u[co] = t\u[co] - uvmin[1] ;Subtract to make the min at the origin
t\v[co] = t\v[co] - uvmin[2]
t\u[co] = t\u[co] / uvdelta[1] ;Then Divide to make it range from 0 to 1
t\v[co] = t\v[co] / uvdelta[2]
Next
;Convert Lumels(Lightmap Pixels) to global space using vectors
Local uvor,dist#,uvvector#[3]
Local vec1#[3], vec2#[3] ;X,Y,Z
Local edge1#[3], edge2#[3]
Local lumelpos#[3]
Local nedge1#[3],nedge2#[3]
Local lightvector#[3]
For co = 1 To 3 ;Find the origin
If t\u[co] = 0 And t\v[co] = 0 Then uvor = co
Next
uvor = 1
;Distance on a plane Formula by Elias
nx = uvxnorm : ny = uvynorm : nz = uvznorm
dist = -(uvxnorm * t\x[uvor] + uvynorm * t\y[uvor] + uvznorm * t\z[uvor])
;Confusing vector work
If plane = 1 ;YZ
tempx# = - (ny * uvmin[1] + nz * uvmin[2] + dist) / nx
uvvector[1] = tempx
uvvector[2] = uvmin[1] : uvvector[3] = uvmin[2]
tempx# = - (ny * uvmax[1] + nz * uvmin[2] + dist) / nx
vec1[1] = tempx
vec1[2] = uvmax[1] : vec1[3] = uvmin[2]
tempx# = - (ny * uvmin[1] + nz * uvmax[2] + dist) / nx
vec2[1] = tempx
vec2[2] = uvmin[1] : vec2[3] = uvmax[2]
ElseIf plane = 2 ;XZ
tempy# = - (nx * uvmin[1] + nz * uvmin[2] + dist) / ny
uvvector[2] = tempy
uvvector[1] = uvmin[1] : uvvector[3] = uvmin[2]
tempy# = - (nx * uvmax[1] + nz * uvmin[2] + dist) / ny
vec1[2] = tempy
vec1[1] = uvmax[1] : vec1[3] = uvmin[2]
tempy# = - (nx * uvmin[1] + nz * uvmax[2] + dist) / ny
vec2[2] = tempy
vec2[1] = uvmin[1] : vec2[3] = uvmax[2]
ElseIf plane = 3 ;XY
tempz# = - (nx * uvmin[1] + ny * uvmin[2] + dist) / nz
uvvector[3] = tempz
uvvector[1] = uvmin[1] : uvvector[2] = uvmin[2]
tempz# = - (nx * uvmax[1] + ny * uvmin[2] + dist) / nz
vec1[3] = tempz
vec1[1] = uvmax[1] : vec1[2] = uvmin[2]
tempz# = - (nx * uvmin[1] + ny * uvmax[2] + dist) / nz
vec2[3] = tempz
vec2[1] = uvmin[1] : vec2[2] = uvmax[2]
EndIf
edge1[1] = vec1[1] - uvvector[1] ;X
edge1[2] = vec1[2] - uvvector[2] ;Y
edge1[3] = vec1[3] - uvvector[3] ;Z
edge2[1] = vec2[1] - uvvector[1] ;X
edge2[2] = vec2[2] - uvvector[2] ;Y
edge2[3] = vec2[3] - uvvector[3] ;Z
;Done with vectors, now onto the image
Local lightmapsize = 0 ;Size of lightmap ^2 or whatever
If detail > 0 Then lightmapsize = detail
If detail = 0
mydist# = Abs(uvdelta[1] + uvdelta[2])
If mydist < 1 Then lightmapsize = 1
If mydist >= 1 And mydist < 4 Then lightmapsize = 2
If mydist >= 4 And mydist < 10 Then lightmapsize = 4
If mydist >= 10 And mydist < 26 Then lightmapsize = 8
If mydist >= 26 And mydist < 50 Then lightmapsize = 16
If mydist >= 50 And mydist < 100 Then lightmapsize = 32
If mydist >= 100 And mydist < 200 Then lightmapsize = 64
If mydist >= 200 And mydist < 400 Then lightmapsize = 128
If mydist >= 400 Then lightmapsize = 256
EndIf
Local uf#,vf#
Local lx#,ly#,lz#,lrange#
Local lightmapim = CreateTexture(lightmapsize,lightmapsize)
SetBuffer TextureBuffer(lightmapim)
ClsColor ambr,ambg,ambb : Cls : ClsColor 0,0,0
LockBuffer()
For l.lmlight = Each lmlight ;Incorperate lights
If l\lmtype = 3
piv = CreateCone(8,0)
RotateMesh piv,-90,0,0
PositionEntity piv,l\x,l\y,l\z
FlipMesh piv:RotateEntity piv,l\pitch,l\yaw,l\roll
ScaleMesh piv,l\outer,l\outer,l\inner
EntityPickMode piv,2
EndIf
PositionEntity lightpivot,l\x,l\y,l\z
lrange = l\range
falloffr# = l\r#/lrange#
falloffg# = l\g#/lrange#
falloffb# = l\b#/lrange#
For y = 0 To lightmapsize-1
For x = 0 To lightmapsize-1
uf = Float(x) / Float(lightmapsize)
vf = Float(y) / Float(lightmapsize)
nedge1[1] = edge1[1] * uf ;X
nedge1[2] = edge1[2] * uf ;Y
nedge1[3] = edge1[3] * uf ;Z
nedge2[1] = edge2[1] * vf
nedge2[2] = edge2[2] * vf
nedge2[3] = edge2[3] * vf
;Get image pos in 3d space
lumelpos[1] = uvvector[1] + nedge2[1] + nedge1[1]
lumelpos[2] = uvvector[2] + nedge2[2] + nedge1[2]
lumelpos[3] = uvvector[3] + nedge2[3] + nedge1[3]
lightvector[1] = lx - lumelpos[1]
lightvector[2] = ly - lumelpos[2]
lightvector[3] = lz - lumelpos[3]
PositionEntity imagepivot,lumelpos[1],lumelpos[2],lumelpos[3]
xi# = EntityX(imagepivot) : yi# = EntityY(imagepivot) : zi# = EntityZ(imagepivot)
;Check for visibility
distx# = xi-l\x
disty# = yi-l\y
distz# = zi-l\z
endist# = EntityDistance(imagepivot,lightpivot)
If endist <= lrange Or l\lmtype = 1
If LinePick(l\x,l\y,l\z,distx,disty,distz,0)=imagepivot
;If endist < 1 Then endist = 1
normx# = xi - l\x : normy# = yi - l\y : normz# = zi - l\z
normx = normx/endist : normy = normy/endist : normz = normz/endist
cosangle# = (nx*normx)+(ny*normy)+(nz*normz)
If cosangle > 0
intense# = Abs(cosangle)
If intense > 1 Then intense = 1
If intense < 0 Then intense = 0
minusr# = falloffr*endist
minusg# = falloffg*endist
minusb# = falloffb*endist
colr# = l\r - minusr+falloffr
colg# = l\g - minusg+falloffg
colb# = l\b - minusb+falloffb
If l\lmtype = 1 Then colr = l\r:colg=l\g:colb=l\b;Direct
colr = colr*intense*lum : colg = colg*intense*lum
colb = colb*intense*lum
argb = ReadPixelFast(x,y) And $FFFFFF
colr = colr + (argb Shr 16 And %11111111)
colg = colg + (argb Shr 8 And %11111111)
colb = colb + (argb And %11111111)
If colr < 0 Then colr = 0
If colr > 255 Then colr = 255
If colg < 0 Then colg = 0
If colg > 255 Then colg = 255
If colb < 0 Then colb = 0
If colb > 255 Then colb = 255
rgb = colb Or (colg Shl 8) Or (colr Shl 16)
;Color colr,colg,colb
;Rect x,y,1,1
WritePixelFast x,y,rgb
EndIf
EndIf
EndIf
Next
Next
If l\lmtype = 3 Then FreeEntity piv
Next
UnlockBuffer()
SetBuffer BackBuffer()
t\tex = lightmapim : t\size = lightmapsize
;Do all the transformations here
;blur(t\tex) or whatever
Next
Next
;Do lightmap sharing
If share = 1
For t.tris = Each tris
For tr.tris = Each tris
If tr <> t And tr\hosttex = 0
alike = texturealike(tr\tex,t\tex)
If alike = 1
t\hosttex = tr\tex:Exit
EndIf
EndIf
Next
Next
;Second Wave
For t.tris = Each tris
If t\hosttex > 0
For tr.tris = Each tris
If tr\hosttex = 0
alike = texturealike(tr\tex,t\tex)
If alike = 1
t\hosttex = tr\tex:Exit
EndIf
EndIf
Next
EndIf
Next
EndIf
;Pack on one big bitmap
Local lightmapbound# = lightmapsize^2;Maximum size for lightmap ^2
Local lightbound =bound
Local xpos#,ypos#
Local xsmall#,ysmall#
Local move#
Local bigtex = CreateTexture(lightbound,lightbound,512)
scale# = lightbound/lightmapbound
move# = lightmapsize/lightmapbound
If detail = 0
;tbcount = 0
;tbcurrent=0
;tbbank = CreateBank(tbcount*3*4)
For t.tris = Each tris
If t\hosttex = 0
scale# = lightbound/(t\size*t\size)
lightmapbound = t\size*t\size
For ypos = 0 To lightbound-1
For xpos = 0 To lightbound-1
overlap = 0
;For cmk = 0 To tbcurrent
;off = cmk*3*4
; nlx = PeekInt(tbbank,off)
; nly = PeekInt(tbbank,off+4)
; nlsize = PeekInt(tbbank,off+8)
; If RectsOverlap(nlx,nly,nlsize,nlsize,xpos,ypos,t\size,t\size) = 1
; overlap=1:xpos=xpos+nlsize-1
; Exit
; EndIf
;Next
For nl.lightmapnode = Each lightmapnode
If RectsOverlap(nl\x,nl\y,nl\size,nl\size,xpos,ypos,t\size,t\size) = 1
overlap=1:xpos=xpos+nl\size-1
Exit
EndIf
Next
If xpos + t\size > lightbound Then overlap = 1:dot1=1:ypos=ypos+1:xpos=-1
If ypos + t\size > lightbound Then overlap = 1:dot2=1:ypos=lightbound:xpos=lightbound
If overlap = 0
;off = tbcurrent*3*4
;tbcurrent = tbcurrent + 1
t\xpos = xpos : t\ypos = ypos
n.lightmapnode = New lightmapnode
n\x = xpos : n\y = ypos : n\size = t\size
; PokeInt(tbbank,off,xpos):PokeInt(tbbank,off+4,ypos):PokeInt(tbbank,off+8,t\size)
CopyRect(0,0,t\size,t\size,xpos,ypos,TextureBuffer(t\tex),TextureBuffer(bigtex))
xsmall# = xpos/Float(lightmapbound) : ysmall# = ypos/Float(lightmapbound)
For co = 1 To 3
;Get rid of the black lines by scaling up and down
If scaletex = 1
If t\u[co] > .5 Then t\u[co] = t\u[co]-.1
If t\v[co] > .5 Then t\v[co] = t\v[co]-.1
If t\u[co] < .5 Then t\u[co] = t\u[co]+.1
If t\v[co] < .5 Then t\v[co] = t\v[co]+.1
EndIf
t\u[co] = (t\u[co]/t\size) + xsmall
t\v[co] = (t\v[co]/t\size) + ysmall
t\u[co] = t\u[co]/scale : t\v[co] = t\v[co] / scale
VertexTexCoords t\surf,t\ver[co],t\u[co],t\v[co],0,1
Next
Exit
EndIf
Next
If overlap = 0 Then Exit
Next
If dot1=1 And dot2=1 Then RuntimeError "Too Many Polys or too high detail, Increase Bound"
EndIf
Next
FreeBank tbbank
ElseIf detail > 0
For t.tris = Each tris
If t\hosttex = 0
t\xpos = xpos : t\ypos = ypos
CopyRect(0,0,t\size,t\size,xpos,ypos,TextureBuffer(t\tex),TextureBuffer(bigtex))
For co = 1 To 3
;Get rid of the black lines by scaling up and down
If scaletex = 1
If t\u[co] > .5 Then t\u[co] = t\u[co]-.1
If t\v[co] > .5 Then t\v[co] = t\v[co]-.1
If t\u[co] < .5 Then t\u[co] = t\u[co]+.1
If t\v[co] < .5 Then t\v[co] = t\v[co]+.1
EndIf
uvm# = t\u[co]
uvn# = t\v[co]
t\u[co] = (t\u[co]/t\size) + xsmall
t\v[co] = (t\v[co]/t\size) + ysmall
t\u[co] = t\u[co]/scale : t\v[co] = t\v[co] / scale
uvm = t\u[co]
uvn = t\v[co]
VertexTexCoords t\surf,t\ver[co],t\u[co],t\v[co],0,1
Next
xpos = xpos + t\size
xsmall = xsmall + move
If xpos >= lightbound Then xpos = 0 : ypos = ypos + t\size:xsmall = 0:ysmall = ysmall +move
If ypos>lightbound Then RuntimeError "Too Many Polys, or too high detail, Increase Lightmap bound"
EndIf
Next
EndIf
;Finally share the lightmap
For t.tris = Each tris
If t\hosttex > 0
For tr.tris = Each tris
If tr\tex = t\hosttex
scale# = lightbound/(t\size*t\size)
lightmapbound = t\size*t\size
xsmall# = tr\xpos/Float(lightmapbound) : ysmall# = tr\ypos/Float(lightmapbound)
For co = 1 To 3
;Get rid of the black lines by scaling up and down
If scaletex = 1
If t\u[co] > .5 Then t\u[co] = t\u[co]-.1
If t\v[co] > .5 Then t\v[co] = t\v[co]-.1
If t\u[co] < .5 Then t\u[co] = t\u[co]+.1
If t\v[co] < .5 Then t\v[co] = t\v[co]+.1
EndIf
t\u[co] = (t\u[co]/t\size) + xsmall
t\v[co] = (t\v[co]/t\size) + ysmall
uvm = t\u[co]
uvn = t\v[co]
t\u[co] = t\u[co]/scale : t\v[co] = t\v[co] / scale
uvm = t\u[co]
uvn = t\v[co]
VertexTexCoords t\surf,t\ver[co],t\u[co],t\v[co],0,1
Next
Exit
EndIf
Next
EndIf
If t\tex > 0 Then FreeTexture t\tex
Delete t
Next
Delete Each lightmapnode
TextureCoords bigtex,1
If luvsave <> ""
createluvs(mesh,luvsave,1)
EndIf
;FreeEntity copy
FreeEntity lightpivot : FreeEntity imagepivot
Return bigtex
End Function
Function getNorm#(x1#,y1#,z1#,x2#,y2#,z2#,x3#,y3#,z3#,axis)
;Once again, thanks to elias and sswift
ux#= x1#- x2#
uy#= y1#- y2#
uz#= z1#- z2#
vx#= x3#- x2#
vy#= y3#- y2#
vz#= z3#- z2#
If axis = 1
Return (uy#*vz#)-(vy#*uz#)
ElseIf axis = 2
Return (uz#*vx#)-(vz#*ux#)
ElseIf axis = 3
Return (ux#*vy#)-(vx#*uy#)
EndIf
End Function
Function CreateLMLight.lmlight(x#,y#,z#,r#,g#,b#,range#,ltype=2)
l.lmlight = New lmlight
l\x = x : l\y = y : l\z = z
l\r =r : l\g = g : l\b =b
l\outer = 1:l\inner =1
l\range = range:l\lmtype = ltype
Return l
End Function
Function CreateLUVs(mesh,filename$,coordset=1)
file = WriteFile(filename+".luv")
For surfcount = 1 To CountSurfaces(mesh)
surf = GetSurface(mesh,surfcount)
For vercount = 0 To CountVertices(surf)-1
WriteFloat(file,VertexU(surf,vercount,coordset))
WriteFloat(file,VertexV(surf,vercount,coordset))
Next
Next
CloseFile file
End Function
Function LoadLUVs(mesh,filename$,coordset=1)
file = ReadFile(filename)
For surfcount = 1 To CountSurfaces(mesh)
surf = GetSurface(mesh,surfcount)
For vercount = 0 To CountVertices(surf)-1
u# = ReadFloat(file)
v# = ReadFloat(file)
VertexTexCoords surf,vercount,u,v,0,coordset
Next
Next
CloseFile file
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 LightmapTerrain(terr,r=0,g=0,b=0,detail=0,lum#=1)
width = TerrainSize(terr)
If detail = 0 Then detail = width
If detail < width Then detail = width
tex = CreateTexture(detail,detail,512)
vx# = GetMatElement(terr,0,0)
vy# = GetMatElement(terr,0,1)
vz# = GetMatElement(terr,0,2)
xscale# = Sqr(vx*vx+vy*vy+vz*vz)
vx# = GetMatElement(terr,1,0)
vy# = GetMatElement(terr,1,1)
vz# = GetMatElement(terr,1,2)
yscale# = Sqr(vx*vx+vy*vy+vz*vz)
vx# = GetMatElement(terr,2,0)
vy# = GetMatElement(terr,2,1)
vz# = GetMatElement(terr,2,2)
zscale# = Sqr(vx*vx+vy*vy+vz*vz)
scale# = 1
If detail < width
scale# = Float(detail)/Float(width)
EndIf
piv = CreatePivot():EntityPickMode piv,1
EntityRadius piv,5
light = CreatePivot()
SetBuffer TextureBuffer(tex)
ClsColor r,g,b : Cls : Color 0,0,0
LockBuffer()
For l.lmlight = Each lmlight
PositionEntity light,l\x,l\y,l\z
lrange# = l\range
falloffr# = l\r#/lrange#
falloffg# = l\g#/lrange#
falloffb# = l\b#/lrange#
For z = 0 To detail-1
For x = 0 To detail-1
xpos# = EntityX(terr) : ypos# = EntityY(terr) : zpos# = EntityZ(terr)
movx# = (xpos+x*xscale)/scale
movy# = (ypos+(TerrainHeight(terr,x,width-z)*yscale))/scale
movz# = ((zpos+(width*zscale))-(z*zscale))/scale
PositionEntity piv,movx,movy,movz
xi# = EntityX(piv) : zi# = EntityZ(piv) : yi# = EntityY(piv)
distx# = xi-l\x : disty# = yi-l\y : distz# = zi-l\z
If LinePick(l\x,l\y,l\z,distx,disty,distz)=piv
endist# = EntityDistance(piv,light)
If endist <= lrange
minusr# = falloffr*endist
minusg# = falloffg*endist
minusb# = falloffb*endist
colr# = l\r - minusr
colg# = l\g - minusg
colb# = l\b - minusb
colr = colr*lum : colg = colg*lum : colb = colb*lum
argb = ReadPixelFast(x,z) And $FFFFFF
colr = colr + (argb Shr 16 And %11111111)
colg = colg + (argb Shr 8 And %11111111)
colb = colb + (argb And %11111111)
If colr < 0 Then colr = 0
If colr > 255 Then colr = 255
If colg < 0 Then colg = 0
If colg > 255 Then colg = 255
If colb < 0 Then colb = 0
If colb > 255 Then colb = 255
rgb = colb Or (colg Shl 8) Or (colr Shl 16)
WritePixelFast(x,z,rgb)
;Color colr,colg,colb
;Rect x,z,1,1
EndIf
EndIf
Next
Next
Next
UnlockBuffer()
SetBuffer BackBuffer()
ScaleTexture tex,detail,detail
FreeEntity piv : FreeEntity light
Return tex
End Function
Function TextureAlike(tex1,tex2)
;Check if textures are congruent
width1 = TextureWidth(tex1) : width2 = TextureWidth(tex2)
If width1 <> width2 Then Return 0
height1 = TextureHeight(tex1) : height2 = TextureHeight(tex2)
If height1 <> height2 Then Return 0
LockBuffer(TextureBuffer(tex1))
LockBuffer(TextureBuffer(tex2))
For y = 0 To height1-1
For x = 0 To width1-1
rgb1 = ReadPixelFast(x,y,TextureBuffer(tex1))
rgb2 = ReadPixelFast(x,y,TextureBuffer(tex2))
If rgb1 <> rgb2
UnlockBuffer(TextureBuffer(tex1))
UnlockBuffer(TextureBuffer(tex2))
Return 0
EndIf
Next
Next
UnlockBuffer(TextureBuffer(tex1))
UnlockBuffer(TextureBuffer(tex2))
Return 1
End Function |
Comments
None.
Code Archives Forum