Author Topic: [B2D] Source for Touching Cloth  (Read 3803 times)

0 Members and 1 Guest are viewing this topic.

Offline Jim

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 5301
  • Karma: 402
    • View Profile
[B2D] Source for Touching Cloth
« on: April 11, 2011 »
Here's the source code for my entry to the Destruction competition 'Touching Cloth'.
It's all in BlitzBasic because I was on holiday with only my netbook.  I very often make a prototype of my demos in b2d and then port to C to get the release and to use some hardware acceleration.  In this case everything is pixel pushed the hard way.  In total the coding time was about 15 hours, but I hoiked in the 3d/triangles from an old engine of mine, and spent a lot of time reading up about spring mass models and, in particular, cracking which is what makes this demo hard and interesting.  I have some more plans for this engine.

Apologies again for the crap scroller, I forgot at the last minute to put the fractional scroll position in the equation so it jumps a whole letter at a time.  The faster your PC the crappier the scroll would have been.

Also, for some reason, I think the 3d wasn't working in the release.  This is a shame, as a lot of the cpu is eaten by zbuffering and it could have been avoided.

Here it is in all its glory,

Cheers!

Jim

Code: [Select]

Const screen_x%=800
Const screen_y%=600
Const screen_x4% = screen_x*4

AppTitle "Touching Cloth"
Graphics screen_x, screen_y,32,0

msg$="                                                                              "
msg=msg+"Welcome everyone to Touching Cloth, a demo by Jim for the March 2011 Destruction Competition on DBF. "
msg=msg+"Once again, as you'd expect from me, this is a sim.  My first go at cloth, just touching upon the possibilities :). "
msg=msg+"The music is Rubikon.mod, I think it's from the Amiga game of the same name, but I could be wrong. "
msg=msg+"Anyway, it's a top tune and I appreciate the effort of the original author. "
msg=msg+"I stole the bunnies and puddies from google. Sue me. "
msg=msg+"I thought I had another day to work on this, hence the fact this scroll text is in the default font "
msg=msg+"and probably takes about 50% of the total frame time to draw. "
msg=msg+"Also, I was rudely separated from my C compiler, so you lot get to see a chunk of "
msg=msg+"painful pixel pushing in BlitzBasic.  It's about as quick as I can make it.  I coded "
msg=msg+"it on my 1.6GHz Atom netbook running on batteries so if it sucks for you then you really need "
msg=msg+"to upgrade that PIII you are running on..."
msg=msg+"If your PC runs this faster than 60Hz or less than 20Hz you will be clamped and the sim will "
msg=msg+"run too slow or too fast.  Even with the clamping sometimes it goes fucking nuts and "
msg=msg+"the sim runs out of control. I don't care. "
msg=msg+"As usual, source code will follow this demo and be posted on the DBF forum. "
msg=msg+"Press F6 to switch to wireframe mode with no rotations. F5 to reset.  Space to add another split.  "
msg=msg+"Greets to Kez, Shockwave, Rbz, Benny!, CK0, Dr.Death, Hellfire, Kirl, LittleWhite, "
msg=msg+"Moroboshisan, Ninogenio, Padman, rdc, Hotshot, Clyde, Yaloopy, Slinks, relsoft, Pixel Outlaw, Taj, "
msg=msg+"StoneMonkey, Va!n, rain_storm, Optimus. Sorry, there are so many of you who post on DBF I can't "
msg=msg+"work out how to find a list of you - you guys rock! "
msg=msg+"Fuckings to Puki - mate, does this happen to you a lot?  Have you ever wondered why?"
msg=msg+"                                                                              "
msglen=Len(msg)

Const origin_x% = screen_x%/2
Const origin_y% = screen_y%/2

Const cx%=20
Const cy%=10
Const y_off%=-100

Const grid%=20
Const stiffness#=1
Const mass#=1

Const use_diags%=True

Const n_springs%=(cx-1)*(cy-1)*4+cx-1+cy-1
Const init_n_points%=cx*cy
Const n_faces%=(cx-1)*(cy-1)

Type POINT
Field x#,y#,z#
Field mass#
Field ax#,ay#,az#
Field vx#,vy#,vz#
Field sx%,sy%,sz#
Field u#,v#
End Type

Type SPRING
Field p0%,p1%
Field length#
Field stiffness#
End Type

Type FACE
Field p0%,p1%,p2%,p3%
End Type

Global n_points%=init_n_points
Dim points.POINT(n_points*10)

Dim springs.SPRING(n_springs)

Dim faces.FACE(n_faces)

Dim matrix#(9)

PlayMusic("music/rubikon.mod")

initMesh()

t%=MilliSecs()
SeedRnd t

framecount%=1
starttime%=t
walltime%=t

wireframe%=False
Delay 33

;------------
Type EDGE
Field x#,z#
Field r#,g#,b#,a#
Field u#,v#
Field wx#,wy#,wz#
Field nx#,ny#,nz#
End Type

;Type POINT
; Field sx%,sy%
; Field x#,y#,z#
; Field r#,g#,b#,a#
; Field u#,v#
; Field wx#,wy#,wz#
; Field nx#,ny#,nz#
;End Type

Type VIEWP
;Field camera.CAMERA
;Field origin_x%
;Field origin_y%
;Field window_w%
;Field window_h%
;Field view_width%
;Field view_height%
Field rect_left%
Field rect_right%
Field rect_top%
Field rect_bottom%
;Field near_clip#
End Type

Type TEXTURE
Field width%
Field height%
Field width_shift%
Field width_mask%
Field height_mask%
Field bank%
End Type


Global L.EDGE = New EDGE
Global R.EDGE = New EDGE

Global TP0.POINT = New POINT
Global TP1.POINT = New POINT
Global TP2.POINT = New POINT
Global TP3.POINT = New POINT

Global current_view.VIEWP = New VIEWP
Global current_texture.TEXTURE

current_view\rect_left = 0
current_view\rect_top = 0
current_view\rect_right = GraphicsWidth()
current_view\rect_bottom = GraphicsHeight()

Dim textures.TEXTURE(3)
load_texture_from_file(0,"tex1.jpg")
load_texture_from_file(1,"tex2.jpg")
load_texture_from_file(2,"tex3.jpg")
current_texture=textures(0)

; ZBuffer
;--------------------------------------------------------------------------------
Global zbuffer=CreateBank(screen_x*screen_y*4)
Global zbufferempty=CreateBank(screen_x*screen_y*4)
For i=0 To (screen_x * screen_y)-1
PokeFloat(zbufferempty,i*4,65536.0)
Next

;--------------------------------------------------------------------------------
; Screen
;--------------------------------------------------------------------------------
Global screen = CreateBank(screen_x*screen_y*4)
Global screencls = CreateBank(screen_x*screen_y*4)
For i=0 To (screen_x * screen_y)-1
PokeInt(screen,i*4,0)
Next

;------------

SetBuffer BackBuffer()
splittimer%=50
resettimerlen%=30000
resettimer%=resettimerlen

msg_start%=0
rt%=0
gt%=0
bt%=0
Repeat
Cls

If Not wireframe Then
;clear zbuffer and screen
clearzbuffer()
clearscreen()
End If

ums%=MilliSecs()
dt%=ums-t
If dt<1 dt=1
t=ums

avedt%=(ums-starttime) / framecount
framecount=framecount+1

walltime=walltime+avedt
movePoints(Max(1000/20,Min((1000/60),avedt)),walltime)

If wireframe Then
renderWireMesh()
Else
renderMesh(walltime)
End If

If Not wireframe
copyscreen()
End If

Color 255,255,255
Text 0,0, ""+ 1000/dt+"fps" + " "+1000/avedt+"fps"

rt = (rt + dt) Mod 128
gt = (gt + dt * 3) Mod 128
bt = (bt + dt * 5) Mod 128
Color 127+rt,127+gt,127+bt
Text 0,450,Mid$(msg,1+msg_start/100,200)
msg_start = msg_start + dt

Flip False

splittimer = splittimer-dt
If KeyDown(57) Or splittimer < 0 Then

splittimer=200

hv%=Rand(0,32)
If hv<24 Then
s=Rand(0,cy*(cx-1))
Else
s=(cy*(cx-1))+Rand(0,cx*(cy-1))
End If
k0%=springs(s)\p0
k1%=springs(s)\p1
If k0<>-1 And k1<>-1 And k0<>0 And k1<>0 And k0<>cx-1 And k1<>cx-1 Then
nx#=points(k1)\x-points(k0)\x
ny#=points(k1)\y-points(k0)\y
nz#=points(k1)\z-points(k0)\z
ln#=Sqr(nx*nx+ny*ny+nz*nz)
If ln>0 Then
ln=1.0/ln
nx=nx*ln
ny=ny*ln
nz=nz*ln

If Rand(2)=1
q%=clone(points(k0))
k%=k0
Else
q%=clone(points(k1))
k%=k1
nx=-nx
ny=-ny
nz=-nz
End If

For f=0 To n_faces-1
fnd%=0
If faces(f)\p0 = k Then
dx#=points(faces(f)\p2)\x-points(k)\x
dy#=points(faces(f)\p2)\y-points(k)\y
dz#=points(faces(f)\p2)\z-points(k)\z
fnd=1
Else If faces(f)\p1 = k Then
dx#=points(faces(f)\p3)\x-points(k)\x
dy#=points(faces(f)\p3)\y-points(k)\y
dz#=points(faces(f)\p3)\z-points(k)\z
fnd=2
Else If faces(f)\p2 = k Then
dx#=points(faces(f)\p0)\x-points(k)\x
dy#=points(faces(f)\p0)\y-points(k)\y
dz#=points(faces(f)\p0)\z-points(k)\z
fnd=3
Else If faces(f)\p3 = k Then
dx#=points(faces(f)\p1)\x-points(k)\x
dy#=points(faces(f)\p1)\y-points(k)\y
dz#=points(faces(f)\p1)\z-points(k)\z
fnd=4
End If
If fnd<>0 Then
dot#=dx*nx + dy*ny + dz*nz
If dot<0 Then
;find the springs which form this face and end at k, point them to q
For s%=0 To n_springs-1
If springs(s)\p0 = k Then
If faces(f)\p0 = springs(s)\p1 Or faces(f)\p1 = springs(s)\p1 Or faces(f)\p2=springs(s)\p1 Or faces(f)\p3=springs(s)\p1 Then
springs(s)\p0=q
End If
Else If springs(s)\p1 = k
If faces(f)\p0 = springs(s)\p0 Or faces(f)\p1 = springs(s)\p0 Or faces(f)\p2=springs(s)\p0 Or faces(f)\p3=springs(s)\p0 Then
springs(s)\p1=q
End If
End If
Next
;fix the face to point at q
If fnd=1 Then
faces(f)\p0=q
Else If fnd=2 Then
faces(f)\p1=q
Else If fnd=3 Then
faces(f)\p2=q
Else
faces(f)\p3=q
End If
End If
End If
Next
End If
End If
End If

resettimer = resettimer - dt
If KeyDown(63) Or resettimer < 0 Then
resettimer=resettimerlen
current_texture = textures(Rand(0,2))
initMesh()
End If
If KeyDown(64) wireframe=Not wireframe

Until KeyDown(1)
End

Function clone(p.POINT)
q.POINT = New POINT
q\x=p\x
q\y=p\y
q\z=p\z
q\vx=p\vx
q\vy=p\vy
q\vz=p\vz
q\mass=p\mass
q\u=p\u
q\v=p\v
points(n_points)=q
n_points=n_points+1
Return n_points-1
End Function

Function Max(a%,b%)
If a%>=b% Return a%
Return b%
End Function
Function Min(a%,b%)
If a%>=b% Return b%
Return a%
End Function


Function movePoints(dt#,walltime%)

kv#=0.01*(dt/33)

For p%=0 To n_points-1
points(p)\ax=0
points(p)\ay=0
points(p)\az=0
If points(p)\vx<0 s0%=-1 Else s0%=1
If points(p)\vy<0 s1%=-1 Else s1%=1
If points(p)\vz<0 s2%=-1 Else s2%=1
points(p)\vx=points(p)\vx-points(p)\vx*kv
points(p)\vy=points(p)\vy-points(p)\vy*kv
points(p)\vz=points(p)\vz-points(p)\vz*kv
If points(p)\vx<0 And s0=1 points(p)\vx=0
If points(p)\vx>0 And s0=-1 points(p)\vx=0
If points(p)\vy<0 And s1=1 points(p)\vy=0
If points(p)\vy>0 And s1=-1 points(p)\vy=0
If points(p)\vz<0 And s2=1 points(p)\vz=0
If points(p)\vz>0 And s2=-1 points(p)\vz=0
Next

For p%=0 To n_springs-1

p0% = springs(p)\p0
p1% = springs(p)\p1

If p0 <> -1 And p1 <> -1 Then

x0# = points(p0)\x
y0# = points(p0)\y
z0# = points(p0)\z
x1# = points(p1)\x
y1# = points(p1)\y
z1# = points(p1)\z

dx# = x1-x0
dy# = y1-y0
dz# = z1-z0

le# = dx*dx + dy*dy + dz*dz
If le > 0.00001 Then
le# = Sqr(le)
ool# = springs(p)\length / le
nx# = ool * dx
ny# = ool * dy
nz# = ool * dz

fx# = (dx - nx) * springs(p)\stiffness
fy# = (dy - ny) * springs(p)\stiffness
fz# = (dz - nz) * springs(p)\stiffness

points(p0)\ax = points(p0)\ax + fx
points(p0)\ay = points(p0)\ay + fy
points(p0)\az = points(p0)\az + fz

points(p1)\ax = points(p1)\ax - fx
points(p1)\ay = points(p1)\ay - fy
points(p1)\az = points(p1)\az - fz
End If

End If
Next

Goto noLimits

kt#=(1.2)^2
For p%=0 To n_points-1
m# = points(p)\ax*points(p)\ax + points(p)\ay*points(p)\ay + points(p)\az*points(p)\az
If m# > kt Then
oom# = kt/Sqr(m)
points(p)\ax = points(p)\ax * oom
points(p)\ay = points(p)\ay * oom
points(p)\az = points(p)\az * oom
End If
Next

.noLimits

ka#= 0.05*dt/33
g# = 0.03*dt/33
kv#= dt/33
For p%=0 To n_points-1
;v = u + at
af# = ka / points(p)\mass
points(p)\vx = points(p)\vx + af * (points(p)\ax - Sin(walltime/100) * 0.1)
points(p)\vy = points(p)\vy + af * (points(p)\ay)-g
points(p)\vz = points(p)\vz + af * (points(p)\az - Sin(walltime/100) * 0.001 + 0.001)

;s = s + tv
points(p)\x = points(p)\x + kv * points(p)\vx
points(p)\y = points(p)\y + kv * points(p)\vy
points(p)\z = points(p)\z + kv * points(p)\vz
Next

points(0)\x=-(cx/2)*grid
points(0)\y=(cy/2)*grid-y_off
points(0)\z=0
points(cx-1)\x=(cx-1-cx/2)*grid
points(cx-1)\y=-(-cy/2)*grid-y_off
points(cx-1)\z=0

points(0)\vx=0
points(0)\vy=0
points(0)\vz=0
points(cx-1)\vx=0
points(cx-1)\vy=0
points(cx-1)\vz=0

End Function

Function initMesh()

du#=1.0/cx
dv#=1.0/cy
v#=0
For y%=0 To cy-1
u#=0
For x%=0 To cx-1
points(x+cx*y)=New POINT
points(x+cx*y)\x=(x-cx/2)*grid
points(x+cx*y)\y=-(y-cy/2)*grid-y_off
points(x+cx*y)\z=0
points(x+cx*y)\mass=mass
points(x+cx*y)\u=u
points(x+cx*y)\v=v
u=u+du
Next
v=v+dv
Next

f%=0
For y%=0 To cy-2
For x%=0 To cx-2
faces(f)=New FACE
faces(f)\p0=x+y*cx
faces(f)\p1=x+1+y*cx
faces(f)\p2=x+1+(y+1)*cx
faces(f)\p3=x+(y+1)*cx
f=f+1
Next
Next

i%=0
For y%=0 To cy-1
For x%=0 To cx-2
springs(i)=New Spring
springs(i)\p0=x+y*cx
springs(i)\p1=x+1+y*cx
springs(i)\length=grid
springs(i)\stiffness=stiffness
i=i+1
Next
Next
For x%=0 To cx-1
For y%=0 To cy-2
springs(i)=New Spring
springs(i)\p0=x+y*cx
springs(i)\p1=x+(y+1)*cx
springs(i)\length=grid
springs(i)\stiffness=stiffness
i=i+1
Next
Next

If use_diags<> True Goto diags

For y%=0 To cy-2
For x%=0 To cx-2
springs(i)=New Spring
springs(i)\p0=x+y*cx
springs(i)\p1=x+1+(y+1)*cx
springs(i)\length=grid*1.41
springs(i)\stiffness=stiffness
i=i+1
Next
Next

For y%=0 To cy-2
For x%=1 To cx-1
springs(i)=New Spring
springs(i)\p0=x+y*cx
springs(i)\p1=x-1+(y+1)*cx
springs(i)\length=grid*1.41
springs(i)\stiffness=stiffness
i=i+1
Next
Next

.diags

End Function

Function renderWireMesh()
Color 255,0,0
renderWireMesh1()
Color 0,255,0
renderWireMesh2()
End Function

Function renderWireMesh1()
For p%=0 To n_springs-1

p0% = springs(p)\p0
p1% = springs(p)\p1

If p0 <> -1 And p1 <> -1 Then
Line origin_x+points(p0)\x,origin_y-points(p0)\y , origin_x+points(p1)\x,origin_y-points(p1)\y
End If
Next
End Function

Function renderWireMesh2()

For p%=0 To n_points-1
points(p)\sx = origin_x + points(p)\x
points(p)\sy = origin_y - points(p)\y
points(p)\z = 1000
Next

For f%=0 To n_faces-1
p0=faces(f)\p0
p1=faces(f)\p1
p2=faces(f)\p2
p3=faces(f)\p3

Line points(p0)\sx,points(p0)\sy , points(p1)\sx,points(p1)\sy
Line points(p1)\sx,points(p1)\sy , points(p2)\sx,points(p2)\sy
Line points(p2)\sx,points(p2)\sy , points(p3)\sx,points(p3)\sy
Line points(p3)\sx,points(p3)\sy , points(p0)\sx,points(p0)\sy
Next

End Function

Function buildcameramatrix(tilt#, turn#, roll#)
Local A#,B#,C#,D#,E#,F#
Local AD#,BD#
A=Cos(tilt):B=Sin(tilt)
C=Cos(turn):D=Sin(turn)
E=Cos(roll):F=Sin(roll)
AD=A*D
BD=B*D
matrix(0)=C*E
matrix(1)=-C*F
matrix(2)=D
matrix(3)=BD*E+A*F
matrix(4)=-BD*F+A*E
matrix(5)=-B*C
matrix(6)=-AD*E+B*F
matrix(7)=AD*F+B*E
matrix(8)=A*C
End Function

Function renderMesh(wallclock%)

buildcameramatrix(Sin(wallclock/200)*10,Sin(wallclock/100)*25,Sin(wallclock/300)*5)

For p%=0 To n_points-1

xx# = points(p)\x * matrix(0) + points(p)\y * matrix(3) + points(p)\z*matrix(6)
yy# = points(p)\x * matrix(1) + points(p)\y * matrix(4) + points(p)\z*matrix(7)
zz# = points(p)\x * matrix(2) + points(p)\y * matrix(5) + points(p)\z*matrix(8)

points(p)\sx = origin_x + xx
points(p)\sy = origin_y - yy
points(p)\sz = zz*10+1000
Next

; For y=0 To cy-2
; For x=0 To cx-2
; texztriangle(points(x+y*cx),points(x+1+y*cx),points(x+(y+1)*cx))
; texztriangle(points(x+1+y*cx),points(x+1+(y+1)*cx),points(x+(y+1)*cx))
; Next
; Next

For f%=0 To n_faces-1
p0=faces(f)\p0
p1=faces(f)\p1
p2=faces(f)\p2
p3=faces(f)\p3
texztriangle(points(p0),points(p1),points(p3))
texztriangle(points(p1),points(p2),points(p3))
Next

End Function

;--------------------------------------------------------------------------------
; Z-Buffered Textured triangle
;--------------------------------------------------------------------------------
Function texzscan(y,EL.EDGE,ER.EDGE)
Local xl%,xr%
Local lz#,lu#,lv#
Local dz#,du#,dv#
Local tx%,ty%
Local zoff%

;offscreen in Y?
If y<current_view\rect_top Return
If y>=current_view\rect_bottom Return

If EL\x > ER\x Then
tmp.EDGE = EL
EL = ER
ER = tmp
End If

xl% = Floor(EL\x)
xr% = Floor(ER\x)

;offscreen in X?
If xl >= current_view\rect_right Return
If xr < current_view\rect_left Return

lz# = EL\z
lu# = EL\u
lv# = EL\v

        If xl=xr Then
If xl < current_view\rect_left Return
dz# = 0
du# = 0
dv# = 0
Else
dx# = 1.0/(xr-xl)
dz# = (ER\z-lz)*dx
du# = (ER\u-lu)*dx
dv# = (ER\v-lv)*dx

;left clip?
If xl < current_view\rect_left Then
xd% = current_view\rect_left-xl
lz = lz + xd * dz
lu = lu + xd * du
lv = lv + xd * dv
xl = current_view\rect_left
End If
End If

;right clip?
If xr >= current_view\rect_right xr = current_view\rect_right-1

zoff% = Y*screen_x4+(xl Shl 2)

For x = xl To xr
If lz < PeekFloat(zbuffer,zoff) Then
PokeFloat(zbuffer,zoff,lz)
tx% = Int(lu * current_texture\width) And current_texture\width_mask
ty% = Int(lv * current_texture\height) And current_texture\height_mask
; WritePixelFast x,y,PeekInt(current_texture\bank,((ty Shl current_texture\width_shift) + tx) Shl 2)
PokeInt(screen,zoff,PeekInt(current_texture\bank,((ty Shl current_texture\width_shift) + tx) Shl 2))
End If
lz = lz + dz
lu = lu + du
lv = lv + dv
zoff = zoff + 4
Next

End Function

Function texztriangle(p0.POINT, p1.POINT, p2.POINT)
If p0\sy<=p1\sy And p0\sy<=p2\sy Then
If p1\sy>p2\sy Then
tmp.POINT = p1
p1 = p2
p2 = tmp
End If
Else If p1\sy<=p0\sy And p1\sy<=p2\sy Then
tmp.POINT = p0
If p0\sy < p2\sy Then
p0 = p1
p1 = tmp
Else
p0 = p1
p1 = p2
p2 = tmp
End If
Else
tmp.POINT = p0
If p1\sy < p0\sy Then
p0 = p2
p2 = tmp
Else
p0 = p2
p2 = p1
p1 = tmp
End If
End If

;offscreen
If p2\sy < current_view\rect_top Return
If p0\sy >= current_view\rect_bottom Return

        dyL# = p2\sy-p0\sy
        If dyL=0 Return
               
        Y% = p0\sy
        dyT# = p1\sy-Y

        L\x = p0\sx
L\z = p0\sz
L\u = p0\u
L\v = p0\v
dyL = 1.0/dyL
        dxL# = (p2\sx-L\x)*dyL
dzL# = (p2\sz-L\z)*dyL
        duL# = (p2\u-L\u)*dyL
        dvL# = (p2\v-L\v)*dyL

        If dyT = 0 Goto bottom

        R\x = L\x
R\z = L\z
R\u = L\u
R\v = L\v
dyT = 1.0/dyT
        dxT# = (p1\sx-L\x)*dyT
dzT# = (p1\sz-L\z)*dyT
        duT# = (p1\u-L\u)*dyT
        dvT# = (p1\v-L\v)*dyT

Ye%=p1\sy
If Ye >= current_view\rect_bottom Then
Ye = current_view\rect_bottom-1
End If

        While (Y < Ye)
                texzscan(Y,L,R)
                Y = Y + 1
                L\x = L\x + dxL
L\z = L\z + dzL
L\u = L\u + duL
L\v = L\v + dvL
                R\x = R\x + dxT
R\z = R\z + dzT
R\u = R\u + duT
R\v = R\v + dvT
        Wend
.bottom

If Y>=current_view\rect_bottom Return

        dyB# = p2\sy-p1\sy
        If dyB=0 Goto done

        R\x = p1\sx
R\z = p1\sz
R\u = p1\u
R\v = p1\v
dyB = 1.0/dyB
        dxB# = (p2\sx-R\x)*dyB
dzB# = (p2\sz-R\z)*dyB
        duB# = (p2\u-R\u)*dyB
        dvB# = (p2\v-R\v)*dyB

Ye%=p2\sy
If Ye >= current_view\rect_bottom Then
Ye = current_view\rect_bottom-1
End If

        While (Y < Ye)
                texzscan(Y,L,R)
                Y = Y + 1
                L\x = L\x + dxL
L\z = L\z + dzL
L\u = L\u + duL
L\v = L\v + dvL
                R\x = R\x + dxB
R\z = R\z + dzB
R\u = R\u + duB
R\v = R\v + dvB
        Wend
.done
End Function

Function load_texture_from_file(index%,file$)
Local x%,y%,bank%,image%,pix%

textures(index) = New TEXTURE
tex.TEXTURE = textures(index)

image = LoadImage("images\"+file$)

If image=0 Then
;create a default checkerboard texture
;if file is missing
tex\width = 4
tex\height = 4
tex\width_shift = 2
tex\width_mask = tex\width-1
tex\height_mask = tex\height-1
tex\bank = CreateBank(4*4*4)
bank%=0
pix%=0
For y%=0 To 3
For x%= 0 To 3
PokeInt(tex\bank,bank, pix)
bank = bank+4
pix = pix Xor $ffffff
Next
pix = pix Xor $ffffff
Next
Return
End If

w% = ImageWidth(image)
h% = ImageHeight(image)

;make sure texture is a power of 2 wide/high
tex\width = pow2up(w)
tex\height = pow2up(h)
tex\width_mask = tex\width-1
tex\height_mask = tex\height-1

If tex\width <> w Or tex\height <> h Then
ResizeImage(image, tex\width, tex\height)
End If

;work out the shift amount for this texture size
tex\width_shift = 0
While (1 Shl tex\width_shift < tex\width)
tex\width_shift = tex\width_shift + 1
Wend

tex\bank = CreateBank(tex\width * tex\height * 4)
bank% = 0

LockBuffer(ImageBuffer(image))
For y% = 0 To tex\height-1
For x% = 0 To tex\width-1
pix% = ReadPixelFast(x,y,ImageBuffer(image)) And $ffffff
PokeInt(tex\bank,bank, pix)
bank = bank+4
Next
Next
UnlockBuffer(ImageBuffer(image))

FreeImage(image)

End Function

;--------------------------------------------------------------------------------
; Return the next power of 2 >= n
;--------------------------------------------------------------------------------
Function pow2up(n%)
If n<=1 Return 1
If n<=2 Return 2
If n<=4 Return 4
If n<=8 Return 8
If n<=16 Return 16
If n<=32 Return 32
If n<=64 Return 64
If n<=128 Return 128
If n<=256 Return 256
If n<=512 Return 512
Return 1024
End Function


;--------------------------------------------------------------------------------
; Copy screen bank to real screen
;--------------------------------------------------------------------------------
Function copyscreen()
Local sx%,sy%,off%
sy = screen_y-1
sx = screen_x-1
off% = 0

LockBuffer()
For y=0 To sy
For x=0 To sx
; If PeekFloat(zbuffer,off)<>65536.0 Then
If PeekInt(zbuffer,off)<>1199570944 Then
WritePixelFast(x,y,PeekInt(screen,off))
End If
off = off+4
Next
Next
UnlockBuffer()
End Function

;--------------------------------------------------------------------------------
; Clear screen
;--------------------------------------------------------------------------------
Function clearscreen()
CopyBank(screencls,0,screen,0,screen_x4*screen_y)
End Function

;--------------------------------------------------------------------------------
; Clear Z Buffer
;--------------------------------------------------------------------------------
Function clearzbuffer()
; If enable_zbuffer Then
CopyBank(zbufferempty,0,zbuffer,0,screen_x4*screen_y)
; End If
End Function
Challenge Trophies Won:

Offline padman

  • Senior Member
  • Pentium
  • ********
  • Posts: 990
  • Karma: 260
    • View Profile
Re: [B2D] Source for Touching Cloth
« Reply #1 on: April 11, 2011 »
Thanks for sharing!  :cheers:
Challenge Trophies Won:

Offline Shockwave

  • good/evil
  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 17407
  • Karma: 498
  • evil/good
    • View Profile
    • My Homepage
Re: [B2D] Source for Touching Cloth
« Reply #2 on: April 11, 2011 »
Really nice chunk of pixel pushing there Jim!

I like the triangle rasteriser.
Shockwave ^ Codigos
Challenge Trophies Won: