Hi,
for a contest in the German DarkBasic Forum (www.darkbasic.de) I made this small (media-less) candle:
`Start Coding 03.10.2007 | 14:15 Uhr
set display mode 1024,768,32
color backdrop 1
set camera range 1,100000
autocam off
hide mouse
`Texturen machen
gosub texturen
`------------------------------------------------------------------------------------------------->
` Flamme Vorbereitung
make object sphere 1,150,12,24
texture object 1,1
set object transparency 1,2
set object light 1,0
offset as float
height as float
radius as float
softness as float
`------------------------------------------------------------------------------------------------->
` Kerze machen
`Aus der Sphere lässt sich relativ einfach ein
`Zylinder MIT Deckflächen erstellen.
`Der Docht wird parallel gemacht, dann brauch man
`den ganzen Scheiß nur einmal machen.
make object sphere 3,100,12,24
texture object 3,2
lock vertexdata for limb 3,0
durchmesser=100
hoehe=1000
vertind=0
`Deckfläche Oben
for i=0 to 3
durch=(durchmesser/3)*i
for j=0 to 24
`In der Mitte muss oben eine kleine Mulde sein,
`außen hingegen soll ein etwas knittriger Rand enstehen.
select i
case 0 : rf=-durchmesser/4 : endcase
case 1 : rf=-durchmesser/5 : endcase
case 2 : rf=-durchmesser/6 : endcase
case 3 : rf=rnd(durchmesser/6) : endcase
endselect
`Winkel der Vertex zum Mittelpunkt ausrechnen
winkel=(360/24)*j
set vertexdata position vertind,sin(winkel)*durch,hoehe+rf,cos(winkel)*durch
inc vertind
next j
next i
`Seitenteile
for i=4 to 8
h=hoehe-((i-4)*hoehe/4)
for j=0 to 24
`Kleiner Zufallsfaktor, damit es wie "Wachs" aussieht.
`Moderne Kerzen sind zwar kerzengrade, früher gabs sowas
`aber nicht. ^^
rf=(2-abs(i-6))*5
`Winkel der Vertex zum Mittelpunkt ausrechnen
winkel=(360/24)*j
set vertexdata position vertind,sin(winkel)*durchmesser+rnd(rf),h,cos(winkel)*durchmesser+rnd(rf)
inc vertind
next j
next i
`Deckfläche Unten
for i=9 to 12
durch=(durchmesser/3)*(abs(i-12))
for j=0 to 24
`Winkel der Vertex zum Mittelpunkt ausrechnen
winkel=(360/24)*j
set vertexdata position vertind,sin(winkel)*durch,0,cos(winkel)*durch
inc vertind
next j
next i
unlock vertexdata
calculate object bounds 3
`------------------------------------------------------------------------------------------------->
` Docht
`Der Docht ist fast identisch mit der Kerze, also kann man fast den gleichen
`Code wie bei der Kerze benutzen. Warum keine Funktion? Die beiden Sachen sind so
`spezifisch, dass sich eine Funktion nicht lohnen würde. Also nicht meckern ich
`würde keine Funktionen benutzen.. Außerdem braucht der nicht so viele Polygone.
make object sphere 4,100,6,8
texture object 4,3
lock vertexdata for limb 4,0
durchmesser=5
hoehe=100
vertind=0
schiefheit=20
`Deckfläche Oben
for i=0 to 1
durch=durchmesser*i
for j=0 to 8
`Winkel der Vertex zum Mittelpunkt ausrechnen
winkel=(360/8)*j
set vertexdata position vertind,sin(winkel)*durch+schiefheit,hoehe,cos(winkel)*durch
inc vertind
next j
next i
`Seitenteile
for i=2 to 6
h=hoehe-((i-2)*hoehe/5)
s=sin(abs((i-6))*(90./4.))*schiefheit
for j=0 to 8
`Winkel der Vertex zum Mittelpunkt ausrechnen
winkel=(360/8)*j
set vertexdata position vertind,sin(winkel)*durchmesser+s,h,cos(winkel)*durchmesser+rnd(rf)
inc vertind
next j
next i
`Deckfläche Unten
for i=7 to 8
durch=durchmesser*abs(i-8)
for j=0 to 8
`Winkel der Vertex zum Mittelpunkt ausrechnen
winkel=(360/8)*j
set vertexdata position vertind,sin(winkel)*durch,0,cos(winkel)*durch
inc vertind
next j
next i
unlock vertexdata
calculate object bounds 4
`------------------------------------------------------------------------------------------------->
` Boden
`Ja, auch der Boden besteht aus einer Sphere. ^^ Die wird diesmal zu einer
`Platte gemacht (wie eine CD).
make object sphere 5,100,12,40
texture object 5,4
set object light 5,0
lock vertexdata for limb 5,0
durchmesser=1500
vertind=0
`Sphere "aufklappen".
for i=0 to 12
durch=(durchmesser/12)*i
for j=0 to 40
`Winkel der Vertex zum Mittelpunkt ausrechnen
winkell as float
winkell=(360./40.)*j
set vertexdata position vertind,sin(winkell)*durch,0,cos(winkell)*durch
inc vertind
next j
next i
unlock vertexdata
calculate object bounds 5
camh=1200
camd=1700
camang=0
`------------------------------------------------------------------------------------------------->
` Loop
`------------------------------------------------------------------------------------------------->
sync on : sync rate 60
while returnkey()=0
ani=wrapvalue(ani+4)
`------------------------------------------------------------------------------------------------->
` Flamme Animation
`Flammenbewegung animieren
restore Flamme
lock vertexdata for limb 1,0
vertind=0
for i=0 to 12
read height
read radius
read softness
offset=sin(wrapvalue(ani+i*20.))*20.
for j=0 to 24
`Winkel der Vertex zum Mittelpunkt ausrechnen
winkel=(360/24)*j
set vertexdata position vertind,sin(winkel)*radius+(offset*softness/100),height+offset*softness/100/10,cos(winkel)*radius-(offset*softness/100)
inc vertind
next j
next i
unlock vertexdata
calculate object bounds 1
`Flamme positionieren und etwas runterskalieren
position object 1,schiefheit,1010,0
scale object 1,75,75,75
`Zweite Flamme erstellen und ghosten (sieht realer aus)
if object exist(2)=1 then delete object 2
instance object 2,1
scale object 2,85,85,85
ghost object on 2
position object 2,schiefheit,1010,0
`Docht positionieren
position object 4,0,955,0
`Boden positionieren (Passend zur Kerze macht der kleine Bewegungen.)
position object 5,-sin(ani)*10,0,-cos(ani)*10
`------------------------------------------------------------------------------------------------->
` Szene
`Kamerasteuerung
if cammode=0
position camera sin(camang)*camd,camh,cos(camang)*camd
point camera 0,1300-camd/2,0
camang=wrapvalue(camang+mousemovex())
camd=camd+mousemovey()
else
rotate camera camera angle x()+mousemovey(),camera angle y()+mousemovex(),0
move camera ((mouseclick()=1)-(mouseclick()=2))*10
endif
`WireFrame Ansicht
if keystate(17)=1
if d=0
wire=abs(wire-1)
set object wireframe 1,wire
set object wireframe 2,wire
set object wireframe 3,wire
set object wireframe 4,wire
set object wireframe 5,wire
d=1
endif
else
d=0
endif
`Kamerasteuerung ändern
if controlkey()=1
if d_con=0
cammode=abs(cammode-1)
if cammode=0
`Wenn von FreeFlight Modus in den anderen gewechselt
`wird, muss eben die Kameraposition in die Variablen
`eingerechnet werden damit es schön ist.
camang=atanfull(camera position x(),camera position z())
camh=1200
camd=sqrt(camera position x()^2+camera position z()^2)
endif
d_con=1
endif
else
d_con=0
endif
center text 512,10,"Candle - by Alsan - 2007"
line 0,30,1024,30
if cammode=0
center text 512,748,"[W] Toggle Wireframe [CTRL] Toggle Camera Movement (Free Flight)"
else
center text 512,748,"[W] Toggle Wireframe [CTRL] Toggle Camera Movement (Center View)"
endif
line 0,744,1024,744
sync
endwhile
`------------------------------------------------------------------------------------------------->
` Texturen
texturen:
type _textur
r as float
g as float
b as float
a as float
pos as float
endtype
`Dat Ganze machen wir vier Mal, einmal für Flamme, einmal für Kerze,
`einmal für Docht und einmal für den Boden.
for j=1 to 4
if j=1 then restore Textur_Flamme
if j=2 then restore Textur_Kerze
if j=3 then restore Textur_Docht
if j=4 then restore Textur_Boden
read points
dim col(points+1) as _textur
for i=1 to points
read col(i).pos
read col(i).r
read col(i).g
read col(i).b
read col(i).a
next i
`Erstmal einen Memblock dafür machen.
make_image_memblock(1,512,512)
curmark=1
`Deklarationen (einfach alles als Float, das passt
`immer ;) )
rr as float
gg as float
bb as float
aa as float
rstep as float
gstep as float
bstep as float
astep as float
`Bild mit RGB Informationen fluten
for y=0 to 511
if y=col(curmark).pos
rr=col(curmark).r
gg=col(curmark).g
bb=col(curmark).b
aa=col(curmark).a
rstep = (col(curmark+1).r-col(curmark).r)/(col(curmark+1).pos-col(curmark).pos)
gstep = (col(curmark+1).g-col(curmark).g)/(col(curmark+1).pos-col(curmark).pos)
bstep = (col(curmark+1).b-col(curmark).b)/(col(curmark+1).pos-col(curmark).pos)
astep = (col(curmark+1).a-col(curmark).a)/(col(curmark+1).pos-col(curmark).pos)
inc curmark
endif
`Farben
inc rr,rstep
inc gg,gstep
inc bb,bstep
inc aa,astep
`Kleine Sicherheitsvorkehrungen
if rr>255 then rr=255
if gg>255 then gg=255
if bb>255 then bb=255
if aa>255 then aa=255
if rr<0 then rr=0
if gg<0 then gg=0
if bb<0 then bb=0
if aa<0 then aa=0
`Pixelzeile schreiben
for x=0 to 511
mdot(1,x,y,rr,gg,bb,aa)
next x
next y
`Textur erstellen und Memblock löschen
make image from memblock j,1
delete memblock 1
next j
return
`------------------------------------------------------------------------------------------------->
` Make Image Memblock
function make_image_memblock(mem,dimx,dimy)
`Diese Funktion erstellt einen Memblock zur späteren
`Benutzung als Bild.
`Mache Memblock
make memblock mem,12+dimx*dimy*4
`Schreibe Daten
write memblock dword mem,0,dimx
write memblock dword mem,4,dimy
write memblock byte mem,8,32
endfunction
`------------------------------------------------------------------------------------------------->
` Make Dot
function mdot(mem,posx,posy,red,green,blue,alpha)
`Diese Funktion macht einen Punkt an die
`angegebene Stelle im Memblock.
`Dimensionen des Bildes herausfinden..
dimx=memblock dword(mem,0)
base=12+posx*4+posy*dimx*4
`Daten schreiben
write memblock byte mem,base ,blue
write memblock byte mem,base+1,green
write memblock byte mem,base+2,red
write memblock byte mem,base+3,alpha
endfunction
`------------------------------------------------------------------------------------------------->
` Data
`data Anzahl der "Farbpunkte"
`data Position,Rot,Grün,Blau,Alpha
`Eine Flamme ist unten Blau, geht dann langsam über Orange
`in grelles Gelb über. Das Blau ist sehr durchsichtig, das Orange
`mittelmäßig und das Gelb praktisch nicht durchsichtig.
Textur_Flamme:
data 4
data 0,255,255, 0,150
data 300,255,175, 0,100
data 400, 0,150,255, 70
data 511, 0,200,255, 90
`Die Kerze ist oben eher hell, da das Licht der Flamme "durch"
`sie hindurchscheint. Nennt man Subsurface Scattering. Nach unten
`wird sie dunkler, durchsichtig ist sie nie.
Textur_Kerze:
data 4
data 0,255,128,128,255
data 300,200, 50, 50,255
data 400,180, 0, 0,255
data 511,255, 0, 0,255
`Der Docht glüht oben, daher ist er dort Orange. Außerdem ist er
`da schon etwas weggebrannt, daher der etwas niedrigere Alpha Wert.
`Dann geht er über schwarz (angebrannt) zu weiß über (mit Wachs
`überzogen.) Durchsichtig ist das nicht mehr.
Textur_Docht:
data 5
data 0,255,255, 0,255
data 250,255,128, 0,255
data 350, 0, 0, 0,255
data 400,255,255,255,255
data 511,255,255,255,255
`Der Boden ist in der Mitte eher dunkel, da die Kerze einen
`Schatten wirft. Dann wird er schlagartig heller und wird dann
`langsam schwarz. Das alles hat noch einen gelblichen Stich.
Textur_Boden:
data 5
data 0, 40, 40, 10,255
data 200,100,100, 60,255
data 210,200,200,150,255
data 500, 0, 0, 0,255
data 511, 0, 0, 0,255
Flamme:
data 385, 0,100
data 321,21,100
data 278,37,100
data 229,57,100
data 182,73,100
data 152,82,100
data 121,83,100
data 90,82,100
data 61,73, 80
data 35,61, 60
data 16,42, 20
data 4,22, 0
data 0, 0, 0
I think it looks quite cool so I thought I could post it here. Please excuse the German comments and variable names.
You'll need at least Upgrade 5.8 to run it because of the Vertexdata Commands.
Hope you like it.
Visit my Forum [German]: www.jaf-entertainment.de