Âûïîëíèë:
ñòóäåíò ãðóïïû
ÏÎ94á Áîòåâ Ì.Â.
Ïðîâåðèë:
Ãóáåíêî Í.Å.
Äîíåöê-1997
> Can someone explain the details of how to
make game graphics like
> in commanche over kill ?
It's called Voxel.
Don't ask me why. Below is a text that explains it.
---------------------------------------------------------------
From:
pleung@cs.buffalo.edu (Patrick Leung)
Newsgroups:
rec.games.programmer
Subject: How To: Mars
Landscape (Repost)
Well, since I posted
something about the: 'Voxel landscapes and
How I did it' post by
Tim Clarke, a coupla people have asked about it. So, here it is, Tim Clarke's :
Voxel landscapes and How I did it with some corrections and modifications he
added in later postings. Hope I dont infringe on any of his rights in doing
this...
The 'I' s in the following
represent Tim Clarke, not me :)
Voxel landscapes and How
I did it
This document
describes the method I used in my demo of a Martian terrain, which can be found
at garbo.uwasa.fi:/pc/demo/mars10.zip.
It's similar to a floating horizon hidden line removal algorithm, so
you'll find discussion of the salient points in many computer graphics books.
The difference is the vertical line interpolation.
First, some general
points:
The map is a 256x256 grid of points, each having an 8-bit integer
height and a colour. The map wraps round such that, calling w(u,v) the height
at (u,v), then w(0,0)=w(256,0)=w(0,256)=w(256,256). w(1,1)=w(257,257), etc.
Map
co-ords: (u,v) co-ordinates that describe a position on the map. The map can be
thought of as a height function h=w(u,v) sampled discretely.
Screen co-ords: (x,y)
co-ordinates for a pixel on the screen.
To generate the map:
This is a recursive
subdivision, or plasma, fractal. You start of with
a random height at (0,0)
and therefore also at (256,0), (0,256), (256,256).
Call a routine that takes
as input the size and position of a square, in the first case the entire map.
This routine get the
heights from the corners of the square it gets given. Across each edge (if the
map has not been written to at the point halfway along that edge), it takes the
average of the heights of the 2 corners on that edge, applies some noise
proportional to the length of the edge, and writes the result into the map at a
position halfway along the edge. The centre of the square is the average of the
four corners+noise.
The routine then calls itself recursively, splitting each square into
four quadrants, calling itself for each quadrant until the length of the side
is 2 pixels.
This is probably old-hat to many people, but the map is made more
realistic by blurring:
w(u,v)=k1*w(u,v)+k2*w(u+3,v-2)+k3*w(u-2,v+4)
or something.
Choose k1,k2,k3 such that k1+k2+k3=1. The points at which the map is
sampled for the blurring filter do not really matter - they give different
effects, and you don't need any theoretical reason to choose one lot as long as
it looks good. Of course do everything in fixed point integer arithmetic.
The colours are done so that the sun is on
the horizon to the East:
Colour=A*[ w(u+1,v)-w(u,v) ]+B
with A and B chosen so
that the full range of the palette is used.
The sky is a similar fractal but without
the colour transformation.
How to draw each frame
First, draw the sky, and blank off about 50 or so scan lines below the
horizon since the routine may not write to all of them (eg. if you are on top
of a high mountain looking onto a flat plane, the plane will not go to the
horizon).
Now, down to business. The screen is as
follows:
---------------------------
| |
| |
| Sky |
| |
| |
|a------------------------|
Horizon
| |
| | Point (a)=screen co-ords (0,0)
| Ground | x increases horizontally
| | y increases downwards
| |
Imagine the viewpoint
is at a position (p,q,r) where (p,q) are the (u,v)
map co-ordinates and r
is the altitude. Now, for each horizontal (constant v)
line of map from v=q+100 (say) down to
v=q, do this:
1. Calculate the y co-ordinate of map
co-ord (p,v,0) (perspective transform)
you:->------------------------
Horizontal view
:
r :
:
:
-----------------------------P
Ground
.........................
(q-v)
q v
You have to find where
the line between P and you intersects with the
screen (vertical, just in
front of 'you'). This is the perspective transform:
y=r/(q-v).
2. Calculate scale
factor f which is how many screen pixels high a mountain of constant height
would be if at distance v from q. Therefore, f is small for map co-ords far
away (v>>q) and gets bigger as v comes down towards q.
So, f is a number such that if you multiply a height from the map by f,
you get the number of pixels on the screen high that height would be. For
example, take a spot height of 250 on the map. If this was very close, it could
occupy 500 pixels on the screen (before clipping)->f=2.
3. Work out the map u co-ord corresponding to (0,y). v is constant
along each line.
4. Starting at the calculated (u,v), traverse the screen, incrementing
the x co-ordinate and adding on a constant, c, to u such that (u+c,v) are the
map co-ords corresponding to the screen co-ords (1,y). You then have 256 map
co-ords along a line of constant v. Get the height, w, at each map co-ord and
draw a spot at (x,y-w*f) for all x.
I.e. the further away
the scan line is, the more to the "left" u will start, and the larger
c will be (possibly skipping some u columns if c > 1); the closer the scan
line, the lesser u will start on the "left", and c will be smaller.
Sorry, but that
probably doesn't make much sense. Here's an example:
Imagine sometime in the middle of drawing
the frame, everything behind a point (say v=q+50) will have been drawn:
---------------------------
| |
| |
| |
| **** |
| ********* | <- A mountain
half-drawn.
|-----**************------|
|*************************|
|********* *********|
|****** ******|
|.........................|
<- The row of dots is at screen co-ord y
| | corresponding to an altitude of 0 for that
--------------------------- particular distance v.
Now the screen-scanning routine will get called for v=q+50. It draws in
a point for every x corresponding to heights at map positions (u,v) where u
goes from p-something to p+something, v constant. The routine would put points
at these positions: (ignoring what was there before) *** *** ******* ******* .........................
So,
you can see that the screen gets drawn from the back, one vertical section
after another. In fact, there's more to it than drawing one pixel at every x
during the scan - you need to draw a vertical line between (x,y old) to (x,y
new), so you have to have a buffer containing the y values for every x that
were calculated in the previous pass. You interpolate along this line (Gouraud
style) from the old colour to the new colour also, so you have to keep a buffer
of the colours done in the last pass.
Only draw the vertical
lines if they are visible (ie. going down,
y new>y old). The screen
is drawn from the back so that objects can be drawn
inbetween drawing each
vertical section at the appropriate time.
If you need further
information or details, mail me or post here... Posting will allow others to
benefit from your points and my replies, though.
_
Ôðàêòàëû
è îáëàñòü èõ
ïðèìåíåíèÿ
Òåðìèí
"ôðàêòàë" (îò
ëàòèíñêîãî
"fractus" - äðîáü) áûë
ââåäåí
áåëüãèéñêèì
ìàòåìàòèêîì
Áåíóà
Ìàíäåëüáðîòîì
è îáîçíà÷àåò
ìíîæåñòâî,
èìåþùåå
äðîáíóþ
ôðàêòàëüíóþ
ðàçìåðíîñòü.
Ðàññìîòðèì
êëàññè÷åñêèé
ïðèìåð
ôðàêòàëà -
òðèàäíóþ
êðèâóþ Êîõ à
òàêæå øàãè
åãî ïîñòðîåíèÿ.
1.
Ïîñòðîåíèå
êðèâîé
íà÷èíàåòñÿ
ñ åäèíè÷íîãî
îòðåçêà,
êîòîðûé
íàçûâàåòñÿ
èíèöèàòîðîì
è ÿâëÿåòñÿ
ïðåäôðàêòàëîì
0-ãî ïîðÿäêà
2.
Äàëåå
èíèöèàòîð
çàìåíÿåòñÿ
íà îáðàçóþùèé
ýëåìåíò -
êðèâóþ èõ
÷åòûðåõ
çâåíüåâ, êàæäîå
èõ êîòîðûõ
èìååò äëèíó
1/3, òàê îáðàçóåòñÿ
ïðåäôðàêòàë
1-ãî ïîðÿäêà
Äëèíà
ïîëó÷åííîãî
ôðàêòàëà
ðàâíà 4/3 îò èñõîäíîé
3.
Êàæäûé èç
îòðåçêîâ
îïÿòü
äåëèòñÿ íà
÷åòûðå
çâåíà
Î÷åâèäíî,
÷òî ïðè n,
ñòðåìÿùåìñÿ
ê áåñêîíå÷íîñòè
äëèíà
ôðàêòàëà
òàêæå
ñòðåìèòñÿ ê
áåñêîíå÷íîñòè.
Â
äàííîå âðåìÿ
ôðàêòàëû
èñïîëüçóþòñÿ
âî ìíîãèõ
îáëàñòÿõ
ïðîãðàììèðîâàíèÿ.
Íàèáîëåå
èçâåñòíûå
îáëàñòè
ïðèìåíåíèÿ -
ôðàêòàëüíîå
ñæàòèå
èçîáðàæåíèé
è ãåíåðàöèÿ
ôðàêòàëüíûõ
ðåëüåôîâ,
ðàññìîòðåííàÿ
â äàííîé
ðàáîòå
Òðåáîâàíèÿ
ê
àïïàðàòíûì
è ïðîãðàììíûì
ñðåäñòâàì
1.
Òðåáîâàíèÿ
ê
àïïàðàòíûì
ñðåäñòâàì
Äëÿ
íîðìàëüíîé
ðàáîòû
ïðîãðàììû
äîñòàòî÷íî IBM
ñîâìåñòèìîãî
êîìïüþòåðà
êëàññà IBM PC/AT 286 c 2Ìá
ÎÇÓ. Òàêæå
íåîáõîäèì VGA
äèñïëåé. Ó
ïðîãðàììû
èìååòñÿ
âîçìîæíîñòü
âûâîäà
ïîëó÷åííûõ
èçîáðàæåíèé
íà
ïðèíòåð(íàëè÷èå
íåîáÿçàòåëüíî).
Äëÿ
ïîëó÷åíèÿ
êà÷åñòâåííîé
àíèìàöèè (áåç
ðûâêîâ) ïðè
ïîñòðîåíèè
ðåëüåôîâ
VOXEL-ìåòîäîì
òðåáóåòñÿ
êîìïüþòåð
êëàññà IBM PC/AT 386.
2. Òðåáîâàíèÿ
ê
ïðîãðàììíûì
ñðåäñòâàì
Äëÿ
ðàáîòû
ïðîãðàììû
äîñòàòî÷íî MS
DOS 3.30. Òàêæå íå
áûëî
çàìå÷åíî
íèêàêèõ
îùèáîê è
ñáîåâ
ïðîãðàììû
ïðè ðàáîòå â
ñðåäå MS Windows è OS/2
3.
Òðåáîâàíèÿ
ê ïðîãðàììå
Ïðîãðàììà
äîëæíà
îáðàáàòûâàòü
âõîäíûå äàííûå
è â
çàâèñèìîñòè
îò ïàëèòðû è
ïîëó÷åííîãî
ôðàêòàëà
ñòðîèòü
ôðàêòàëüíûé
ðåëüåô è
ïîçâîëÿòü
ïîëüçîâàòåëþ
äèíàìè÷åñêè
ïî íåìó ïåðåìåùàòüñÿ(ïðîãðàììà
VOXEL) èëè
ñòîðîèòü
ãðóïïó
óçëîâûõ
òî÷åê è ïîçâîëÿòü
ïåðåìåùàòüñÿ
ïî
ïîñòðîåííîé
ïîâðõíîñòè â
ïðåäåëàõ
îáëàñòè
çàäàíèÿ
ôðàêòàëà(ïðîãðàììà
LANDSCAPE).
Âõîäíûå
è âûõîäíûå
äàííûå
1.
Ïðîãðàììà VOXEL
1.1
Âõîäíûå
äàííûå
Âõîäíûìè
äàííûìè äëÿ
äàííîé
ïðîãðàììû
ÿâëÿþòñÿ:
-
ïàëèòðà
öâåòîâ,
êîòîðàÿ
áóäåò
èñïîëüçîâàíà
ïðè
ïîñòðîåíèè
ðåëüåôà. Âàðüèðóÿ
çíà÷åíèÿ
ïàëèòðû(èñïîëüçóåòñÿ
256 öâåòîâ),
ìîæíî
äîáèâàòüñÿ ðàçëè÷íûõ
ýôôåêòîâ.
Ïàëèòðà ïî
óìîë÷àíèþ
ïîäîáðàíà
òàêèì
îáðàçîì, ÷òî
áîëåå
íèçêèå ÷àñòè
ðåëüåôà(âîäîåìû)
èìåþò
îòòåíêè
ãîëóáîãî öâåòà.
Áîëåå
âûñîêèå(äîëèíû
è ïðåäãîðüÿ)
èìåþò
îòòåíêè
çåëåíîãî è æåëòîãî
öâåòîâ. È,
íàêîíåö, ñàìûå
âûñîêèå(ãîðû
ñî ñíåæíûìè
øàïêàìè) èìåþò
îòòåíêè
ñåðîãî è
áåëîãî
öâåòîâ.
-
äàííûå,
ïîñòóïàþùèå
ñ
êëàâèàòóðû.
Íàæèìàÿ íà
êëàâèøè
óïðàâëåíèÿ êóðñîðîì,
ïîëüçîâàòåëü
ìîæåò
äèíàìè÷åñêè
ïåðåìåùàòüñÿ
ïî ñîçäàííîìó
ôðàêòàëüíîìó
ðåëüåôó.
-
äàííûå,
ïîñòóïàþùèå
èç
ãåíåðàòîðà
ñëó÷àéíûõ
÷èñåë,
êîòîðûå èñïîëüçóþòñÿ
ïðè
ïîñòðîåíèè
ôðàêòàëà.
1.2
Âûõîäíûå
äàííûå
Âûõîäíûìè
äàííûìè
ïðîãðàììû
ÿâëÿåòñÿ
ôðàêòàëüíûé
ðåëüåô, âûâîäèìûé
íà ýêðàí
êîìïüþòåðà
2.
Ïðîãðàììà LANDSCAPE
2.1
Âõîäíûå
äàííûå
-
äàííûå, ïîñòóïàþùèå
ñ
ìàíèïóëÿòîðà
"ìûøü", ïðè ïîìîùè
êîòîðîãî ìîæíî
ïåðåìåùàòüñÿ
ïî ïîñòðîåííîé
ïîâåðõíîñòè
-
äàííûå,
ïîñòóïàþùèå
èç
ãåíåðàòîðà
ñëó÷àéíûõ
÷èñåë, êîòîðûå
èñïîëüçóþòñÿ
ïðè
ïîñòðîåíèè
ôðàêòàëà.
2.2
Âûõîäíûå
äàííûå
Âûõîäíûìè
äàííûìè
ïðîãðàììû
ÿâëÿåòñÿ
ïîâåðõíîñòü,
ïðåäñòàâëåííàÿ
â âèäå
íàáîðà
óçëâûõ
òî÷åê