PDA

View Full Version : Project: Miniverse



vgo
14-04-2006, 04:02 PM
My project is called "Project Miniverse" and yes, it's another game engine... It's a cross platform project and hopefully it will compile and run at least on various versions of Windows, Linux and Mac OS X.

It's the fourth game engine, I've coded one before (about 5-6 years ago) using OpenGL for Windows and couple more before that for good old DOS. The last one used a commercial game engine, but I got tired of the limitations and I like to know what happens "under the hood", besides I wanted to have a shot on cross-platform coding... 8)

Basically I'm doing this for the fun of it and I'll probably never finish it, let alone create a game with it. But that doesn't matter as long as it's fun and I learn new things... :)

I'll probably ask some more stupid questions on the forums regarding OpenGL and stuff as I have forgotten too much of it since I last time used it for anything... ;)

Anyway, big part of the game engine logic is already done and now I'm porting it to use OpenGL and other cross-platform libraries. I'll probably rewrite whole lot of it along the way, but that's how software gets better and better... :)

cragwolf
14-04-2006, 08:55 PM
Basically I'm doing this for the fun of it and I'll probably never finish it, let alone create a game with it. But that doesn't matter as long as it's fun and I learn new things... :)

You are made from the same cloth as me. Fun and learning are the only reasons I do this sort of thing. The journey is more important than the goal (what goal?) Good luck with it.

vgo
27-08-2007, 02:40 PM
Looks like it's been a while since I started this thread... :)

Thought that I might write a bit more about my project. My PGD 2007 entry was part of this, but it went badly. I just didn't have time to work on it so I had to pull out from the competition.

I'm still working on the actual game engine and I've written whole lot of prototypes that I've used to experiment with various things, but the space sim genre seems to be the one I always come back to.

I've started working on a planet rendering system, nothing fancy yet, but hopefully it'll lead to some cool things... :)

The theory behind my planet renderer is pretty simple:
Take a cube and normalize it, then subdivide and subdivide and subdivide...
Store the results in a quadtree and calculate normals and bounding spheres, links to neighbours etc. for each node. Process the quadtree nodes based on the distance and visibility and subdivide more when needed, then generate the actual vertex data based on current node LOD render it and store for later use, when the distance is big enough discard the generated data to save memory.

Here's my test planet that I call "The Sphereworld", yes it's a perfect sphere that started it's life as a cube, I've extended the sides and then subdivided the hell out of it. :)
Also visible the normals of the nodes from the quadtree.
http://www.projectminiverse.com/images/gallery/tn_Planets07_20070827160431.jpg (http://www.projectminiverse.com/images/gallery/Planets07_20070827160431.jpg)

Here's the surface just 2.6 meters away, the radius of the "planet" is just 100 meters, but it's good for some initial testing, I've also experimented with Earth-sized planets and there the biggest problem is the crappy precision of 32bit floating point numbers, also the Z-fighting is very bad indeed.
http://www.projectminiverse.com/images/gallery/tn_Planets08_20070827160447.jpg (http://www.projectminiverse.com/images/gallery/Planets08_20070827160447.jpg)

Here's another with visible node normals and vertices. These are not from the actual geometry that will be rendered, which doesn't exist yet.
http://www.projectminiverse.com/images/gallery/tn_Planets09_20070827160501.jpg (http://www.projectminiverse.com/images/gallery/Planets09_20070827160501.jpg)

Here's some normals beyod the horizon, I've been tweaking my horizontal culling method so that as few extra nodes are visible as possible but still the high points like mountains would be.
http://www.projectminiverse.com/images/gallery/tn_Planets10_20070827160513.jpg (http://www.projectminiverse.com/images/gallery/Planets10_20070827160513.jpg)

I've already experimented with some random heightmap based vertex patches, but more on that later. ;)

NecroDOME
27-08-2007, 07:45 PM
Try adding a earth or moon surface (texture) + heightmap.

vgo
28-08-2007, 06:58 AM
I found some Mars textures with bump maps and they are arranged into sets that can be wrapped around a cube, I'm gonna try those and use the bump maps to calculate heights for the vertex patches. Should be quite easy to do, I just have to interpolate the texture coordinates for texture and height information.

If someone has planet textures arranged so that they can be used on the 6 sides of a cube I'd be interested to get my hands on those. :)

Firlefanz
28-08-2007, 07:21 AM
Perhaps try this for planet textures, it is great and free, used it for my game "Commando Xenidis":

http://www.gharat.net/pages/planetgen.html

vgo
28-08-2007, 08:54 AM
Thanks for the tip.

I've installed the program and it seems to generate textures only to use with spherical mapping. My program uses the six sides of a cube, assigns texture coordinates for those and then interpolates them as the cube is subdivided into a sphere. Either I have to calculate spherical mapping coordinates or make a tool that takes textures like that and converts them to separate front/back, left/right and top/bottom textures...

NecroDOME
28-08-2007, 09:28 AM
I guess you are looking for something like this?:
http://www.humus.ca/Textures/Earth.jpg

Download link: http://www.humus.ca/index.php?page=Textures&&start=8

vgo
28-08-2007, 10:01 AM
Yes! That's exactly what I was looking for. :)

But I can easily calculate the texture coordinates for spherical mapping too as I interpolate the vertex normals.

vgo
28-08-2007, 03:14 PM
Wrapped some textures around my planet:
http://www.projectminiverse.com/images/gallery/tn_Planets12_20070828165348.jpg (http://www.projectminiverse.com/images/gallery/Planets12_20070828165348.jpg)

http://www.projectminiverse.com/images/gallery/tn_Planets13_20070828165405.jpg (http://www.projectminiverse.com/images/gallery/Planets13_20070828165405.jpg)

There's some ugly seams between the sphere segments, but I fixed them by using texture coordinates like 0.001 and 0.999, this way the edges are filtered perfectly, I can't see the seams anywhere anymore.

Next step: surface geometry using height maps. Should be fun. :)

vgo
30-08-2007, 07:30 PM
First experiments with the height maps:
http://www.projectminiverse.com/images/screenshots/Planets15.jpg
http://www.projectminiverse.com/images/screenshots/Planets16.jpg
http://www.projectminiverse.com/images/screenshots/Planets17.jpg

Looking good so far, but I had to disable texturing because I get so bad Z-buffer artifacts on real sized planets... :(

NecroDOME
30-08-2007, 11:37 PM
Z-buffer artifacts.... try to set your near-view value higher. If you have it 1.0, try make it 10.0!

vgo
31-08-2007, 05:04 AM
I have to adjust it more, because I need to have all the little things visible infront of the camera too. The radius of the planet is 3,400,000 units (ie. 3400km), I think that when I'm rendering I move the Z-near to 1000-10000 units and render stuff, then move it a bit closer and render more, again a bit closer and render the rest, I need to clear the buffer before each "pass" too. I think this might work... So I need my Z-near value to range from 0.001 to 10000 or so...

paul_nicholls
31-08-2007, 06:59 AM
Hi vgo,
perhaps these links on the gamasutra site can help (all about planetary rendering) by Sean O'Neil:

"A Real-Time Procedural Universe" parts 1-4

http://www.gamasutra.com/features/20010302/oneil_01.htm
http://www.gamasutra.com/features/20010810/oneil_01.htm
http://www.gamasutra.com/features/20020712/oneil_01.htm
http://www.gamasutra.com/features/20060112/oneil_01.shtml

They "may" require a login, but if one is needed, it is completely free to join...
cheers,
Paul

vgo
31-08-2007, 07:17 AM
I've read those articles before I started working on my planet rendering code, actually I've read pretty much all the articles ever written on the subject. :)

Besides, O'Neil's original approach is quite a bit different than mine, he used spherical ROAM algorithm, I use chunked (or whatever :) ) quad tree, but the later version of his engine used some sort of quad trees too, I think.

Changing the Z-near according to the rendering distance is probably the only way to get it working. Guess I'll know that for sure in a couple of days.

I can't wait to do some walking on the surface! ;)

Robert Kosek
31-08-2007, 11:09 AM
Looks like you're getting some good results. Keep up the good work. :)

vgo
01-09-2007, 07:30 AM
I decided to post links to the current build to get some feedback on the performance etc.

You can get the data (textures, heightmaps and an older build with more bugs :) ) here (http://www.projectminiverse.com/ol/QuadSphere06.7z).
The latest build is here (http://www.projectminiverse.com/ol/QuadSphere08.7z).

Both files are compressed with 7zip (http://www.7-zip.org/). Just uncompress them to the same folder and you're ready to go. Both executables are for Windows.

There's a whole lot of bugs, no need to report them and yes there's canals on Mars! :D

Those should go away soon when I implement a proper height map edge filtering, now I just clamp the edges to 0 and that makes the funny ditches run all over the planet.

In textured mode there's a lot of visible cracks between the surface patches, I'm working on that too. The edges between patches will be split further to fix them.

Don't be alarmed by the VERY long loading times when starting the program, my JPEG loader code sucks... Gonna try Vampyre lib for that.

EDIT: Just realized that this build has compiler optimization turned off and I bet the range check is on too, so it's not exactly blazing fast. :)
To get rid off the z-buffer artifacts you can try to reduce that radius of the planet... To improve performance you can try turning the automatic subdivision off, or reducing the number of subdividions/frame.

EDIT2: Controls for the test program: right mouse button yaw/pitch, middle mouse button roll/pitch, arrow keys to move around. You have to click on the rendering surface to activate the controls if you click on the GUI elements on the right.
Try turning of texturing and then turning on node rendering to see the actual quadtree getting rendered. Clicking the "Reset" button resets the camera orientation and places it some way from the planet facing it, just in case you get lost if you resize the planet :)

technomage
01-09-2007, 09:35 AM
nice work, worked no problems here :)

Galfar
01-09-2007, 11:42 AM
Works great, 450fps on Radeon X1950Pro with default planet and settings.

vgo
01-09-2007, 03:54 PM
Nice to hear that it actually works. :)

Here's a new version, now the height map edges are perfectly aligned with each other. Well, they would be IF the original height maps were perfect too, but they are not... The top and bottom bump maps are slightly rotated compared to their color maps and this makes it impossible to make them align perfectlywith the others. You can see this if you browse the images with a image viewer, they are off just a few degrees, but it's enough in this case. As bump maps they work just fine...

There was also a silly bug in one of the bump maps, which was driving me crazy until I looked at the size of the image, it was 1023x1024 and not 1024x1024 like the rest. Doh.

The new package includes a new resized version of this bump map too, you can get it here (http://www.projectminiverse.com/ol/QuadSphere09.7z).

I think it looks pretty nice already, there's only cracks between surface patches of different detail level, but hopefully I'll get those fixed soon enough.

Now I need to get my hands on some new cubemaps to play with. Earth and the Moon in real life size orbiting it would be nice. :)

Reiter
01-09-2007, 11:31 PM
Hi vgo!

You remeber me? - You do, don't you :).

Nice to hear you are advancing sucessfully! Some really great screenshots you got, so keep the good work going :)!

vgo
02-09-2007, 01:40 PM
Sure I remember you Reiter! :)

Another update, let's start with some screenshots.

http://www.projectminiverse.com/images/gallery/tn_Planets20_20070902144821.jpg (http://www.projectminiverse.com/images/gallery/Planets20_20070902144821.jpg)
A volcano.

http://www.projectminiverse.com/images/gallery/tn_Planets21_20070902144837.jpg (http://www.projectminiverse.com/images/gallery/Planets21_20070902144837.jpg)
A (small) meteor impact crater.

http://www.projectminiverse.com/images/gallery/tn_Planets22_20070902144850.jpg (http://www.projectminiverse.com/images/gallery/Planets22_20070902144850.jpg)
Another volcano, you can actually see a bit of the "mouth" of that thing.

As you can see I've cranked up the surface detail level. ;)
Now, at any given time, there's about ~100k tris rendered on the screen, rendering pretty is slow because it's all still done in immediate mode and there's many unnecessary state changed etc.

I think it already looks quite nice and I already sort of realize at times that I've been just flying around the planet looking for stuff and not coding the renderer! :)

There's two detail levels for the surface geometry, 8x8 produces about ~8000 tris and 16x16 ~100k tris, I had 32x32 patch too, but... Well, let's just say that my development PC didn't like that much so I dropped it for now. :)

I'm aiming for ~100k average tris count with full detail, the actual LOD system still needs a lot of tweaking and I need to get rid off the rest of the seams between nodes that are rendered in different detail level.

You can get the new version here (http://www.projectminiverse.com/ol/QuadSphere10.7z).

EDIT: Just noticed something very strange when I tried the current version in my game PC, the performance is at least 10x worse than on my development PC! My development PC is a AMD Sempron 3000+ 2GB ATI X800XT PE and my game PC is AMD Athlon 64 X2 4400+ 2GB ATI 1950XT Pro. What's going on? :shock:

EDIT2: On my game PC I get ~25 fps in wireframe mode and ~8 in textured mode, on the development rig I get ~45 in textured mode and ~120 in wireframe mode... Still no idea what's causing the low fps... :(

EDIT3: I managed to double the frame rate on my game PC with this (http://www.projectminiverse.com/ol/QuadSphere11.7z) version, but it's still ~20 at best when near the surface. My work PC has 3-4 times better fps...

EDIT4: Once more with feeling! I managed to fix most of the Z-buffer artifacts. New version for download here (http://www.projectminiverse.com/ol/QuadSphere12.7z). Guess this is enough for one day, time to get some sleep. :)

vgo
08-09-2007, 12:32 PM
A quick update...

I've been working on the renderer and the spatial subdivision and other things seem to be pretty close to final.

Here's some screenshots from the planet surface:

http://www.projectminiverse.com/images/gallery/tn_Planets23_20070908140725.jpg (http://www.projectminiverse.com/images/gallery/Planets23_20070908140725.jpg)
Running out of height map resolution...

http://www.projectminiverse.com/images/gallery/tn_Planets24_20070908140738.jpg (http://www.projectminiverse.com/images/gallery/Planets24_20070908140738.jpg)
Those big Lego blocks are single pixels from the 1024x1024 height maps.

http://www.projectminiverse.com/images/gallery/tn_Planets25_20070908140756.jpg (http://www.projectminiverse.com/images/gallery/Planets25_20070908140756.jpg)
Here's a screenshot from 0.25 meters(!) above the surface of the planet. The radius of the planet in this image is 3400 kilometers. No height maps were in use in this detail level, they just won't work anymore... The grey blob in that shot is a sphere with a diameter of 1m which I placed on the planet surface to get some kind of idea of the scale...

Next stop: procedural height maps and textures using fractal noise...

technomage
08-09-2007, 08:49 PM
looking good :D

vgo
09-09-2007, 04:04 PM
Been busy again! :D

Here's my first attempt at fractal planets.

http://www.projectminiverse.com/images/gallery/tn_Planets27_20070909174036.jpg (http://www.projectminiverse.com/images/gallery/Planets27_20070909174036.jpg)

The whole surface geometry was generated using a fBm fractal routine.

http://www.projectminiverse.com/images/gallery/tn_Planets28_20070909174050.jpg (http://www.projectminiverse.com/images/gallery/Planets28_20070909174050.jpg)

With the height maps I ran out of detail prettu soon, but here I can zoom in and get more and more detailed surface. :)

You can get the current build HERE (http://www.projectminiverse.com/ol/QuadSphere13.7z). There's no textures yet, so only wireframe mode is available. You don't need any of the data files either, everything you see is generated as you move around and see the stuff for the first time.

technomage
09-09-2007, 04:39 PM
nice work :)

I got about 130 FPS when at the planet surface. My system spec is

AMD 3800+ 2.4 GHz
1 Gig Ram
NVidia GeForce 7800 GT.

Well done.

vgo
09-09-2007, 04:54 PM
Nice to hear that it works on your rig too. :)

Here's some interesting screenshots from a planet I created.

http://www.projectminiverse.com/images/gallery/tn_Planets29_20070909182216.jpg (http://www.projectminiverse.com/images/gallery/Planets29_20070909182216.jpg)

This one looks a lot more like a real planet.

http://www.projectminiverse.com/images/gallery/tn_Planets30_20070909182717.jpg (http://www.projectminiverse.com/images/gallery/Planets30_20070909182717.jpg)

It even has a huge sea on it!

Try using the same parameters as in the screenshots and you should get EXACTLY the same planet on your screen. :)

technomage
09-09-2007, 05:20 PM
very nice, got the same results on the machine here. :D

vgo
11-09-2007, 05:55 PM
Here's some pretty colors:
http://www.projectminiverse.com/images/gallery/tn_Planets46_20070911193458.jpg (http://www.projectminiverse.com/images/gallery/Planets46_20070911193458.jpg)

http://www.projectminiverse.com/images/gallery/tn_Planets47_20070911193510.jpg (http://www.projectminiverse.com/images/gallery/Planets47_20070911193510.jpg)

http://www.projectminiverse.com/images/gallery/tn_Planets48_20070911193523.jpg (http://www.projectminiverse.com/images/gallery/Planets48_20070911193523.jpg)

Putting some color on the planets make them look so much more interesting, I've also implemented more fractal routines etc. Climate zones are probably my next big addition.

You can download the new version HERE (http://www.projectminiverse.com/ol/QuadSphere17.7z).

technomage
11-09-2007, 09:05 PM
cool :)

vgo
15-09-2007, 09:26 AM
I've improved the quality of my noise routines a lot and this means better surface features on the planets. However, it has also made the renderer a lot slower, I need to find a way to speed up the noise routines.

http://www.projectminiverse.com/images/gallery/tn_Planets53_20070915110317.jpg (http://www.projectminiverse.com/images/gallery/Planets53_20070915110317.jpg)

http://www.projectminiverse.com/images/gallery/tn_Planets52_20070915110328.jpg (http://www.projectminiverse.com/images/gallery/Planets52_20070915110328.jpg)

http://www.projectminiverse.com/images/gallery/tn_Planets54_20070915110338.jpg (http://www.projectminiverse.com/images/gallery/Planets54_20070915110338.jpg)

You can get the new version HERE (http://www.projectminiverse.com/ol/QuadSphere18.7z).

Now I'm gonna do a complete rewrite for the renderer to make it better, then start adding all kinds of nifty detail on the surface...

NecroDOME
15-09-2007, 09:57 AM
I can see my house from here :P !!

Nice work man! Have you any textured screenshots?

vgo
15-09-2007, 10:48 AM
There's no support for textures yet, I need to figure out how to implement climate zones, terrain type on different slopes etc. before I can start texturing the planets.

I've just started rewriting the procedural planet class and hopefully I can fix the cracks between nodes with different LOD and maybe then I could try some textures on it (maybe 4-8 different textures with variation based on altitude only). I need to add the cube map rendering too, so that I can create the textures that are used to render the planet from far away.

vgo
15-09-2007, 04:06 PM
Well, I thought that at this point I'd be coding the new version of the renderer, but I was not very happy with my noise routines, so I decided to do something about it.

First I implemented "Improved Perlin Noise" based on the Java reference implementation by Ken Perlin, it was slightly faster than the original, but still not fast enough.

Then I started working on a even faster version and I finally cracked it. I already had an earlier version based on code that I got from the guy who codes the Infinity MMO project, but I couldn't get it to tile properly so I scrapped that one. I took a few bits from this and the rest from the improved noise, implemented a couple of FPU tricks and voila! New very fast noise routine! :)

I compared this to the fast Perlin noise code by IA and it's even faster than that! Noise quality is also very good, only slightly worse than the original Perlin noise and completely unnoticeable on my planet renderer.

Here's some test results from 3 different noise routines that are all based on the Perlin noise:


Perlin Noise: 1,10200 seconds
Improved Perlin Noise: 0,90000 seconds
Fast Perlin Noise IA: 0,52000 seconds
Fast Perlin Noise: 0,39000 seconds


The first two are based on original code by Ken Perlin and the last one is my own modification of the second version. The Fast Perlin Noise IA is the "reference implementation" by IA (aka Ysaneya at gamedev.net).
My test program took 1000000 samples from each noise generator and calculated the elapsed time.

The first one is the noise routine that I've used so far, so speed improvement is quite dramatic.

I updated my planet renderer to use the new noise routine and there's hardly any stuttering on the low altitudes anymore unless you're moving too fast. You can get the new version HERE (http://www.projectminiverse.com/ol/QuadSphere19.7z). This is hopefully the last release using the old procedural planet class.

paul_nicholls
16-09-2007, 11:20 PM
Well, I thought that at this point I'd be coding the new version of the renderer, but I was not very happy with my noise routines, so I decided to do something about it.

First I implemented "Improved Perlin Noise" based on the Java reference implementation by Ken Perlin, it was slightly faster than the original, but still not fast enough.

Then I started working on a even faster version and I finally cracked it. I already had an earlier version based on code that I got from the guy who codes the Infinity MMO project, but I couldn't get it to tile properly so I scrapped that one. I took a few bits from this and the rest from the improved noise, implemented a couple of FPU tricks and voila! New very fast noise routine! :)

I compared this to the fast Perlin noise code by IA and it's even faster than that! Noise quality is also very good, only slightly worse than the original Perlin noise and completely unnoticeable on my planet renderer.

Here's some test results from 3 different noise routines that are all based on the Perlin noise:


Perlin Noise: 1,10200 seconds
Improved Perlin Noise: 0,90000 seconds
Fast Perlin Noise IA: 0,52000 seconds
Fast Perlin Noise: 0,39000 seconds


The first two are based on original code by Ken Perlin and the last one is my own modification of the second version. The Fast Perlin Noise IA is the "reference implementation" by IA (aka Ysaneya at gamedev.net).
My test program took 1000000 samples from each noise generator and calculated the elapsed time.

The first one is the noise routine that I've used so far, so speed improvement is quite dramatic.

I updated my planet renderer to use the new noise routine and there's hardly any stuttering on the low altitudes anymore unless you're moving too fast. You can get the new version HERE (http://www.projectminiverse.com/ol/QuadSphere19.7z). This is hopefully the last release using the old procedural planet class.

Hi vgo,
Well done! :-)

Even your original perlin noise routine is over twice as fast as my Pascal perlin noise translation I did a while ago.

Mine takes around 2.8 seconds to do the 1000000 iterations!!

Is there any chance I can get your fast perlin noise routine off you?

EDIT:
my function:

Function TPerlinNoise.PerlinNoise3d(x,y,z: Double;
Persistence: Single = 0.25;
Frequency: Single = 1;
Octaves: Integer = 4): Double;

I was using the above defaults for persistence, frequency and octaves...
cheers,
Paul.

paul_nicholls
17-09-2007, 01:17 AM
PS. if anyone is intersted in my slower (but working) perlin noise class, here is the unit:


Unit PerlinNoiseUnit;

Interface

{$R-}
{$Q-}

Const
_B = $100;
BM = $ff;

N = $1000;

Type
TPerlinNoise = Class
Private
P : Array[0..(_B+_B+2)-1] Of Integer;
G1: Array[0..(_B+_B+2)-1] Of Double;
Public
Constructor Create(Seed: Integer);

Procedure InitNoise(Seed: Integer);
Function Noise1d(x: Double): Double;
Function Noise2d(x,y: Double): Double;
Function Noise3d(x,y,z: Double): Double;

Function PerlinNoise1d(x: Double;
Persistence: Single = 0.25;
Frequency: Single = 1;
Octaves: Integer = 4): Double;
Function PerlinNoise2d(x,y: Double;
Persistence: Single = 0.25;
Frequency: Single = 1;
Octaves: Integer = 4): Double;
Function PerlinNoise3d(x,y,z: Double;
Persistence: Single = 0.25;
Frequency: Single = 1;
Octaves: Integer = 4): Double;
End;

Implementation

Uses
SysUtils;

Function TPerlinNoise.Noise1d(x: Double): Double;
Var
bx0,bx1: Integer;
rx0,sx,t,u,v: Double;
Begin
t := x+N;
bx0 := Trunc(t) And BM;
bx1 := (bx0+1) And BM;
rx0 := t-Trunc(t);

sx := (rx0*rx0*(3.0-2.0*rx0));

u := G1[P[bx0]];
v := G1[P[bx1]];

Result := u+sx*(v-u);
End;

Function TPerlinNoise.Noise2d(x,y: Double): Double;
Var
bx0,bx1,by0,by1: Integer;
i,j: Integer;
rx0,ry0: Double;
sx,sy: Double;
a,b,t,u,v: Double;
Begin
t := x+N;
bx0 := Trunc(t) And BM;
bx1 := (bx0+1) And BM;
rx0 := t-Trunc(t);

t := y+N;
by0 := Trunc(t) And BM;
by1 := (by0+1) And BM;
ry0 := t-Trunc(t);

i := P[bx0];
j := P[bx1];

sx := (rx0*rx0*(3.0-2.0*rx0));
sy := (ry0*ry0*(3.0-2.0*ry0));

u := G1[P[i+by0]];
v := G1[P[j+by0]];
a := u+sx*(v-u);

u := G1[P[i+by1]];
v := G1[P[j+by1]];
b := u+sx*(v-u);

Result := a+sy*(b-a);
End;

Function TPerlinNoise.Noise3d(x,y,z: Double): Double;
Var
bx0,bx1,by0,by1,bz0,bz1: Integer;
i,j,k,l: Integer;
rx0,ry0,rz0: Double;
sx,sy,sz: Double;
a,b,c,d,t,u,v: Double;
Begin
t := x+N;
bx0 := Trunc(t) And BM;
bx1 := (bx0+1) And BM;
rx0 := t-Trunc(t);

t := y+N;
by0 := Trunc(t) And BM;
by1 := (by0+1) And BM;
ry0 := t-Trunc(t);

t := z+N;
bz0 := Trunc(t) And BM;
bz1 := (bz0+1) And BM;
rz0 := t-Trunc(t);

i := P[bx0];
j := P[bx1];

k := P[i+by0];
l := P[j+by0];
i := P[i+by1];
j := P[j+by1];

sx := (rx0*rx0*(3.0-2.0*rx0));
sy := (ry0*ry0*(3.0-2.0*ry0));
sz := (rz0*rz0*(3.0-2.0*rz0));

u := G1[P[k+bz0]];
v := G1[P[l+bz0]];
a := u+sx*(v-u);

u := G1[P[i+bz0]];
v := G1[P[j+bz0]];
b := u+sx*(v-u);

c := a+sy*(b-a);

u := G1[P[k+bz1]];
v := G1[P[l+bz1]];
a := u+sx*(v-u);

u := G1[P[i+bz1]];
v := G1[P[j+bz1]];
b := u+sx*(v-u);

d := a+sy*(b-a);

Result := c+sz*(d-c);
End;

constructor TPerlinNoise.Create(Seed: Integer);
Begin
inherited Create;

InitNoise(Seed);
End;

procedure TPerlinNoise.InitNoise(Seed: Integer);
Var
i,j: Integer;
Begin
RandSeed := Seed;

For i := 0 to _B - 1 Do
Begin
P[i] := i;
G1[i] := 2*Random-1;
End;

For i := 0 to _B - 1 Do
Begin
j := Random(_B);
P[i] := P[i] xor P[j];
P[j] := P[j] xor P[i];
P[i] := P[i] xor P[j];
End;

For i := 0 to _B+2 - 1 Do
Begin
P[_B+i] := P[i];
G1[_B+i] := G1[i];
End
End;

Function TPerlinNoise.PerlinNoise1d(x: Double;
Persistence: Single = 0.25;
Frequency: Single = 1;
Octaves: Integer = 4): Double;
Var
i: Integer;
p,s: Double;
Begin
Result := 0;
s := Frequency;
p := 1;
For i := 0 to Octaves - 1 Do
Begin
Result := Result + p * Noise1d(x * s);
s := s * 2;
p := p * Persistence;
End;
End;

Function TPerlinNoise.PerlinNoise2d(x,y: Double;
Persistence: Single = 0.25;
Frequency: Single = 1;
Octaves: Integer = 4): Double;
Var
i: Integer;
p,s: Double;
Begin
Result := 0;
s := Frequency;
p := 1;
For i := 0 to Octaves - 1 Do
Begin
Result := Result + p * Noise2d(x * s,y * s);
s := s * 2;
p := p * Persistence;
End;
End;

Function TPerlinNoise.PerlinNoise3d(x,y,z: Double;
Persistence: Single = 0.25;
Frequency: Single = 1;
Octaves: Integer = 4): Double;
Var
i: Integer;
p,s: Double;
Begin
Result := 0;
s := Frequency;
p := 1;
For i := 0 to Octaves - 1 Do
Begin
Result := Result + p * Noise3d(x * s,y * s,z * s);
s := s * 2;
p := p * Persistence;
End;
End;

End.

cheers,
Paul.

vgo
17-09-2007, 09:30 AM
I might clean up my code a bit and then post it here. But there's a catch in it (there always is :) ), it MAY NOT work as expected if you use Trunc/Floor/Round/etc. in your code, this is because of the fpu tricks that I use. The VCL code in Delphi may alter the fpu registers which will stop the noise routine from working properly... So, it's pretty much "use only if you really know what you're doing". :)

This could be easily fixed by checking/resetting the fpu registers, but this would also nullify the speed increase, making it just as slow as it was before... It's fast because the code expects to find the fpu always in a certain state.

The best approach would be to code the whole noise routine in MMX assembly, but I don't have time for that.

Anyway, the noise code is not directly comparable to yours, because I don't handle the octaves/frequency in the actual noise generator, instead I use fractal and other routines to control this.

But I could try another similar test with 16 octaves etc. to see what's what. :)

I also noticed a bit of a problem in your implementation: You can't use Trunc instead of Floor when calculating the gradient indices. The results may look similar, but especially on higher octaves you get artifacts and the noise output won't tile properly in 3D.

By default my planet renderer uses 16 octaves fBm and when combined with ridged multifractal that's 16 + 8 octaves for each point generated on the planet and if I use Trunc instead of Floor the results are BAD...

paul_nicholls
17-09-2007, 10:20 PM
Thanks for the reply and interesting information vgo :-)
I am still interested in seeing your noise generation code anyway when you are ready to post it, regardless of catches and tricks <G>

Keep up the excellent work :)

cheers,
Paul

Chavez_US
18-10-2007, 07:28 AM
Nice work vgo!...Are you still experimenting with project miniverse?


This could be easily fixed by checking/resetting the fpu registers, but this would also nullify the speed increase, making it just as slow as it was before... It's fast because the code expects to find the fpu always in a certain state...The best approach would be to code the whole noise routine in MMX assembly,...


Because the MMX registers overlay the FPU registers, you cannot mix FPU and MMX instructions in the same computation sequence. You can begin executing an MMX instruction sequence at any time; however, once you execute an MMX instruction you cannot execute another FPU instruction until you execute a special MMX instruction, EMMS (Exit MMX Machine State). This instruction resets the FPU so you may begin a new sequence of FPU calculations. The CPU does not save the FPU state across the execution of the MMX instructions; executing EMMS clears all the FPU registers. Because saving FPU state is very expensive, and the EMMS instruction is quite slow, it's not a good idea to frequently switch between MMX and FPU calculations. Instead, you should attempt to execute the MMX and FPU instructions at different times during your program's execution. http://webster.cs.ucr.edu/AoA/Windows/HTML/TheMMXInstructionSet.html

Can speed be increased by buffering (flushing) and caching? I think more data can be transferred with less procedural calls, which in turn reduces system call overhead...and items in a cache are not limited to a specific type, form, or size...

Rick (Chavez_US)