Author |
Topic: Fractal landscape with D3D (Read 820 times) |
|
DDRM
Administrator
member is offline


Gender: 
Posts: 321
|
 |
Fractal landscape with D3D
« Thread started on: Aug 11th, 2015, 4:40pm » |
|
As promised, here is a proof-of-principle demonstration of a fractal landscape rendered using D3DLIBA.
When you run it, a fractal landscape will be generated, and rendered very crudely to see if it is interesting. If you don't like it, press "n", and a new one will appear. When You've got one you like, press "y", and it will be converted to a D3D view which you can fly around.
Controls: Arrow keys: bank left and right (causes you to turn in horizontal plane), "Dive" or "Climb" A and Z: accelerate forwards or backwards R: Reset position, heading and speed to the initial one (stationary above the (0,0) corner) Q: quit
You can change the setting of s% in line 6 to alter the size of the map. 128 will generate fairly fast, and is big enough to get an idea of flying round it. 256 is my favourite. By 512 it all gets a bit ponderous, both creating and running.
Lots of other bits you can play with if you want to: change the position and/or colour of the lights for different times of day, change the colours (and fractions of the landscape) for the different regions.
I've tried to include reasonably clear annotation of what's going on.
Hope that's interesting to someone!
D
Code:
HIMEM=PAGE +1E8
INSTALL @lib$+"D3DLIBA"
MODE 21
xres%=800
yres%=600
s%=128 :REM must be a power of 2. Size of the map in squares (each way)
vscale=yres%/s%
hscale=xres%/s%
DIM l%(s%,s%) :REM This will hold the height data
REPEAT
REM Set up a map and see if we like it!
minh%=1000
maxh%=0
PROCfillland(0,0,s%) :REM Recursive fractal generation of the landscape
PROCMeasureLand :REM Look for the highest and lowest points
wlevel%=minh%+(maxh%-minh%)/2 :REM everything below this level will be sea
l%()-=wlevel%
maxh%-=wlevel%
snowlevel%=maxh%*3/4 :REM Snowy mountains above this level
REM Fill in the sea
FOR y%=0 TO s%-1
FOR x%=0 TO s%-1
IF l%(x%,y%)<0 THEN l%(x%,y%)=0
NEXT x%
NEXT y%
PROCPlot :REM Quick and dirty view of the generated world, before we make the big vertex buffer
PRINT "Fly this world (y/n/q)?"
q$=GET$
CLS
IF q$="q" OR q$="Q" THEN QUIT
UNTIL q$="y" OR q$="Y"
PRINT "Creating the world: please wait a moment."
REM OK, We've made our world, let's set up D3D and fly round it
mapscaleh=5 :REM This determines how big the x,y squares are, relative to the vertical coordinates
DIM l2%(1), b%(1), n%(1), f%(1), s%(1), m%(1), t%(1), y(1), p(1), r(1), X(1), Y(1), Z(1), e(2), a(2)
ON CLOSE PROCcleanup:QUIT
ON ERROR PROCcleanup:PRINT REPORT$:END
PROCSetUpLights
d% = FN_initd3d(@hwnd%, 1, 1)
IF d% = 0 ERROR 100, "Can't initialise Direct3D"
b%(0) = FN_MakeVBuf(d%, n%(0), f%(0), s%(0))
IF b%(0) = 0 ERROR 100, "Failed to make buffer"
PROCSetStartPos
REPEAT
REM Use arrow keys to bank left or right, or raise or lower nose
REM Use keys A and Z to accelerate forward or backward, respectively.
IF INKEY(-66) THEN v+=0.01
IF INKEY(-98) THEN v-=0.01
IF INKEY(-26) THEN ra+=0.01
IF INKEY(-122) THEN ra-=0.01
IF INKEY(-58) THEN va-=0.01
IF INKEY(-42) THEN va+=0.01
ha+=SIN(ra)/100
px+=v*COS(ha)*COS(va)
py+=v*SIN(ha)*COS(va)
pz+=v*SIN(va)
e() = px,pz,py
a()=px+COS(ha),pz+SIN(va),py+SIN(ha)
PROC_render(d%, &FF8080FF, 2, l2%(), 1, m%(), t%(), b%(), n%(), f%(), s%(), y(), p(), r(), X(), Y(), Z(), e(), a(), PI/4, 5/4, 1, 5000,ra)
q$=INKEY$(1)
IF q$="r" OR q$="R" THEN PROCSetStartPos:REM Reset position and speed
UNTIL q$="q" OR q$="Q"
QUIT
:
DEFPROCfillland(l%,b%,side%)
LOCAL mx%,my%,r%,t%,hs%,localscale
localscale=2*(RND(1))
hs%=side% DIV 2
mx%=l%+hs%
my%=b%+hs%
r%=l%+side%
t%=b%+side%
l%(r%,my%)=(l%(r%,b%)+l%(r%,t%))/2+(RND(side%)-hs%)*localscale
l%(mx%,t%)=(l%(l%,t%)+l%(r%,t%))/2+(RND(side%)-hs%)*localscale
l%(mx%,my%)=(l%(l%,my%)+l%(r%,my%)+l%(mx%,b%)+l%(mx%,t%))/4+(RND(side%)-hs%)*localscale
IF side%>1 THEN
PROCfillland(l%,b%,hs%)
PROCfillland(l%,my%,hs%)
PROCfillland(mx%,b%,hs%)
PROCfillland(mx%,my%,hs%)
ENDIF
ENDPROC
:
DEFPROCMeasureLand
LOCAL x%,y%
FOR y%=0 TO s%-1
FOR x%=0 TO s%-1
IF l%(x%,y%)>maxh% THEN maxh%=l%(x%,y%)
IF l%(x%,y%)<minh% THEN minh%=l%(x%,y%)
NEXT x%
NEXT y%
ENDPROC
:
DEFPROCPlot
LOCAL x%,y%
FOR y%=0 TO s%-1
MOVE xres%-hscale*y%,vscale*y%+l%(0,y%)*vscale
FOR x%=0 TO s%-1
IF l%(x%,y%)<=0 THEN GCOL 4 ELSE GCOL 2
IF l%(x%,y%)>snowlevel% THEN GCOL 7
DRAW xres%-hscale*y%+hscale*x%,vscale*y%+vscale*x%+l%(x%,y%)*vscale
NEXT x%
NEXT y%
ENDPROC
:
DEFFN_MakeVBuf(D%,RETURN N%,RETURN V%,RETURN L%)
LOCAL B%,P%,R%
N%=s%*s%*6 :REM Number of vertices
V%=&52 :REM Format for each vertex
L%=28 :REM Size of each vertex
SYS!(!D%+92),D%,N%*L%,0,V%,0,^B% TO R%:REM CreateVertexBuffer
IF R% THEN=0
SYS!(!B%+44),B%,0,N%*L%,^P%,0:REM Lock
FOR x%=0 TO s%-1
FOR y%=0 TO s%-1
PROCDoVBpoint(P%,x%,y%,n())
PROCDoVBpoint(P%,(x%+1),y%,n())
PROCDoVBpoint(P%,(x%+1),(y%+1),n())
PROCDoVBpoint(P%,x%,y%,n())
PROCDoVBpoint(P%,(x%+1),(y%+1),n())
PROCDoVBpoint(P%,(x%),(y%+1),n())
NEXT y%
NEXT x%
SYS!(!B%+48),B%:REM Unlock
=B%
:
DEF PROC4(A%):BPUT#F%,A%:BPUT#F%,A%>>8:BPUT#F%,A%>>16:BPUT#F%,A%>>24:ENDPROC
:
DEFPROCDoVBpoint(RETURN p%,x%,y%,n())
LOCAL c%,n(),u(),v()
DIM n(2),u(2),v(2)
REM XYZ data
!p%=FN_f4(mapscaleh*x%)
p%!4=FN_f4(l%(x%,y%))
p%!8=FN_f4(mapscaleh*y%)
p%+=12
REM Sort out the surface normal, looking at points either side of this one
IF x%=0 OR x%=s% OR y%=0 OR y%=s% THEN
n()=0,0,1
ELSE
u(0)=2:u(1)=0:u(2)=l%(x%+1,y%)-l%(x%-1,y%)
v(0)=0:v(1)=2:v(2)=l%(x%,y%+1)-l%(x%,y%-1)
n(0)=u(1)*v(2)-u(2)*v(1)
n(1)=u(2)*v(0)-u(0)*v(2)
n(2)=u(0)*v(1)-u(1)*v(0)
ENDIF
REM Add surface normals
!p%=FN_f4(n(0))
p%!4=FN_f4(n(2))
p%!8=FN_f4(n(1))
p%+=12
REM Now work out colour
CASE TRUE OF
WHEN l%(x%,y%)=0: c%=&FF0000F0 :REM water
WHEN l%(x%,y%)<3:c%=&FFF0F000 :REM Sand
WHEN l%(x%,y%)<snowlevel%*3/4:c%=&FF00F000 :REM Grass
WHEN l%(x%,y%)<snowlevel%:c%=&FFF08050 :REM dirt
OTHERWISE:c%=&FFF0F0F0 :REM Snow
ENDCASE
!p%=c% :REM Colour data
p%+=4
ENDPROC
:
DEF PROCcleanup
REM Stolen unchanged from one of Richard's demos: probably needs beefing up
t%(1) += 0:IF t%(1) PROC_release(t%(1))
b%(0) += 0:IF b%(0) PROC_release(b%(0))
b%(1) += 0:IF b%(1) PROC_release(b%(1))
d% += 0 :IF d% PROC_release(d%)
ENDPROC
:
DEFPROCSetUpLights
REM Set up a couple of light sources: the first is "like the sun",
REM while the second gives a bit of backlighting from directly above
DIM D3Dlight8{Type%, Diffuse{r%,g%,b%,a%}, Specular{r%,g%,b%,a%}, \
\ Ambient{r%,g%,b%,a%}, Position{x%,y%,z%}, Direction{x%,y%,z%}, \
\ Range%, Falloff%, Attenuation0%, Attenuation1%, Attenuation2%, \
\ Theta%, Phi% }
D3Dlight8.Type% = 3 : REM directional source
D3Dlight8.Diffuse.r% = FN_f4(0.2)
D3Dlight8.Diffuse.g% = FN_f4(0.2)
D3Dlight8.Diffuse.b% = FN_f4(0.2)
D3Dlight8.Direction.x% = FN_f4(1)
D3Dlight8.Direction.y% = FN_f4(-1)
D3Dlight8.Direction.z% = FN_f4(1)
l2%(0) = D3Dlight8{}
DIM D3Dlight2{}=D3Dlight8{}
D3Dlight2.Type% = 3 : REM directional source
D3Dlight2.Diffuse.r% = FN_f4(0.1)
D3Dlight2.Diffuse.g% = FN_f4(0.1)
D3Dlight2.Diffuse.b% = FN_f4(0.1)
D3Dlight2.Direction.x% = FN_f4(0)
D3Dlight2.Direction.y% = FN_f4(-1)
D3Dlight2.Direction.z% = FN_f4(0)
l2%(1) = D3Dlight2{}
ENDPROC
:
DEFPROCSetStartPos
px=0
py=0
pz=maxh%*2
v=0
va=-PI/8
ha=PI/4
ra=0
e()= px,pz,py
a()=0,0,0
ENDPROC
|
|
Logged
|
|
|
|
David Williams
Developer
member is offline

meh

Gender: 
Posts: 452
|
 |
Re: Fractal landscape with D3D
« Reply #1 on: Aug 11th, 2015, 6:01pm » |
|
Wow! Good work, David. It runs nicely. It was definitely worth signing back up to the BB4W Yahoo! Group just to obtain D3DLIBA so I could run it. 
I'll probably experiment a bit with larger landscape sizes.
David. --
|
|
Logged
|
|
|
|
David Williams
Developer
member is offline

meh

Gender: 
Posts: 452
|
 |
Re: Fractal landscape with D3D
« Reply #2 on: Aug 12th, 2015, 6:16pm » |
|
Suppose a 'Chocks Away!'-style game where you fire bullets at enemy planes and ground objects, what might be your strategy for accurate (or reasonably accurate) collision detection? For instance, an enemy craft might comprise a few dozen polygons, and there may be dozens of enemy craft flying around. So perhaps an initial, easy, efficient bullet-in-bounding-sphere test followed by (in the case of collision with sphere) a more computationally intensive (but more accurate) check to see if the projectile lies within an angled rectangular prism surrounding each polygon/face of the object?
I haven't yet checked if Direct3D 8, 9 or 11 offers any collision detection functions, so I'll have a look now...
David. --
|
|
Logged
|
|
|
|
DDRM
Administrator
member is offline


Gender: 
Posts: 321
|
 |
Re: Fractal landscape with D3D
« Reply #3 on: Aug 12th, 2015, 10:26pm » |
|
Yes, something like that - "could I have hit?", refined to "did I hit?". Depends a bit on how fast things will run - you could just cheat, use a slightly smaller bounding sphere, and rely on proximity fuses... 
Not sure D3D does collision detection, though it may be in the extension DLL that is causing all the trouble with D3D9, and/or may be in later versions. Anyway, I thought that was what GFXLIB(2) was for? 
D
|
|
Logged
|
|
|
|
David Williams
Developer
member is offline

meh

Gender: 
Posts: 452
|
 |
Re: Fractal landscape with D3D
« Reply #5 on: Aug 13th, 2015, 07:46am » |
|
on Aug 12th, 2015, 10:26pm, DDRM wrote:Not sure D3D does collision detection, though it may be in the extension DLL that is causing all the trouble with D3D9, and/or may be in later versions. Anyway, I thought that was what GFXLIB(2) was for?  |
|
GFXLIB is oriented towards 2D games; essentially it's an overly-extensive collection of sprite plotters!
Perhaps a new library - 3DLIB.BBC - could include a bunch of subs & functions for doing collision detection, 3D object creation (for creating e.g. Platonic solids, (ir-)regular polyhedra, cones, spheres, etc.), and object loaders for importing 3D objects from Blender, 3DS Max, etc., as well as other useful functions to facilitate game/app creation.
(Just daydreaming. Not volunteering to undertake such a project myself!)
David. --
|
|
Logged
|
|
|
|
David Williams
Developer
member is offline

meh

Gender: 
Posts: 452
|
 |
Re: Fractal landscape with D3D
« Reply #7 on: Aug 15th, 2015, 11:48am » |
|
on Aug 15th, 2015, 09:06am, Torro wrote:
We can all dream. 
I'd give greater priority to a 3D utilities library (perhaps a 3DTOOLSLIB.BBC) I outlined earlier to DDRM, as a companion library to D3DLIB/D3D9LIB, etc.
Just a reminder of some of the functionality that a hypothetical 3DTOOLSLIB could offer:
- Collision detection - Object loaders (to import from Blender, 3DS, etc.) - Scene loaders - Object and mesh manipulation - 3D primitive object creation - Procedural texture generators - Object texturing functions - Various 3D maths functions - Various other utility functions
Sadly, the great effort involved in creating such a library, however, may just end up being largely a waste of time and energy. Sorry to be so negative about this.
Torro, have you seen DDRM's germinal/proof-of-concept, fractal landscape-based flight sim he posted to this board a few days ago? Check it out if you haven't already.
David. --
|
|
|
|
Torro
New Member
member is offline


Posts: 25
|
 |
Re: Fractal landscape with D3D
« Reply #8 on: Aug 15th, 2015, 3:54pm » |
|
David respect for what you did previously just don't end up a troll.
|
|
Logged
|
|
|
|
DDRM
Administrator
member is offline


Gender: 
Posts: 321
|
 |
Re: Fractal landscape with D3D
« Reply #9 on: Aug 15th, 2015, 10:09pm » |
|
Hi Guys,
I have made some progress. I have a model plane, but I am struggling to render the propeller disk semi-transparent. Simply setting the alpha value doesn't seem to hack it. I've played with various things in SetRenderState (such as alpha enable!), but some web sources suggest I need to play with SetTextureStageState as well. Anyone managed to make this work in D3D8 or 9 (I'm currently working with 9, to get Richard's declarations, and so the MSDN pages relate to what I'm doing).
I've managed to get ambient light working: you need to turn it on with SetRenderState, but also tell it to use the vertex colours. That gives a bit of "fill in" light, so the shadows aren't so harsh.
I'm also thinking about the map. It seems obvious that I can't render the whole world at full detail or everything will grind to a halt. I'm planning a low-res, large scale map, which will probable be hand-designed to include interesting places (including flat bits for airfields), and then a modified version of the fractal generator to generate the detailed landscape. Obviously I'll need to pass a seed and reset the RND function each time, so it comes up the same... I thought I could have 4, or maybe 9, buffers containing the local patches of territory around your position.
I haven't quite worked out how to implement that, though...
D
|
|
Logged
|
|
|
|
David Williams
Developer
member is offline

meh

Gender: 
Posts: 452
|
 |
Re: Fractal landscape with D3D
« Reply #10 on: Aug 16th, 2015, 12:12pm » |
|
Glad you've made some more progress, David.
I'm keeping tabs on this project of yours!
Admittedly, my own tinkerings with D3DLIB some years back never ventured into semi-transparent polygons (most likely because I didn't have the know-how).
David. --
http://www.proggies.uk/ https://www.youtube.com/channel/UC1E2sxhlc9h9C82q6RFvAWQ
|
|
Logged
|
|
|
|
David Williams
Developer
member is offline

meh

Gender: 
Posts: 452
|
 |
Re: Fractal landscape with D3D
« Reply #12 on: Aug 17th, 2015, 5:38pm » |
|
Splendid.
|
|
Logged
|
|
|
|
|