Texture Map Correction for spherical mapping

Blitz3D Forums/Blitz3D Programming/Texture Map Correction for spherical mapping

Krischan(Posted 2006) [#1]
Hi,

I have a generated texture map (planet surface) in mercator-style projection applied to a sphere. The problem is that the texture distorts at the poles. I have seen textures of planets/moons of our solar system where the texture has been modified and there is no more distortion at the poles (like here: http://www.mmedia.is/bjj/planetary_maps.html ).

Any Idea how to do this modification in blitzbasic? The idea behind is a procedural universe with random planets / no file-based heightmaps, everything is being generated on the fly.

Here is a example planet texture:


The algorithm should produce a map like this:


The examples are generated with a DOS tool by Torben Mogensen (grab it here: http://www.diku.dk/~torbenm/ ), which can generate a "square projection" map (Example 2) which fits my needs, but unfortunately the planet.exe must be in a path only with DOS compatible 8.3 parent directories :-( But i won't use this tool, I have my own perlin-based algorithm for planet surface generation which is way faster.

Can anybody read/transform the square projection C-Code from this planet generator into Blitz code? I really don't understand Torbens code and need help. Thanks.


Mustang(Posted 2006) [#2]
If you have Photoshop here's a plug-in that does the same thing:


Spherical Mapping Corrector

This filter produces texture map correction for spherical texture mapping. Special thanks to Paul Bourke for allowing his algorithm to be ported to this plugin. For more information, please visit Mr. Bourke's site at Mr. Bourke'sCurrent Version v1.2



http://www.richardrosenman.com/software/downloads/


It stretches the top and bottom of an image horizontally more than the center of the image so that the top and bottom don't create a "pinched" look at the poles. The results are not necessarily mathematically accurate.




Krischan(Posted 2006) [#3]
I know this tool, but I won't preprocess the heightmaps, I want to calculate the new maps in BB (imagine 100 stars with approx. 5 planets each = 500 heightmaps, doh!). And if you try to stretch the upper map with this tool and put the new map on a sphere it won't fit anymore at the sides.

Torbens planet generator has the solution but I don't understand his source code (the squarep() function).


Morbius(Posted 2006) [#4]
Here's some pseudocode from: http://local.wasp.uwa.edu.au/~pbourke/texture/polargrid/

   double theta,phi,phi2;
   int i,i2,j;
   BITMAP *imagein,*imageout;

   Form the input and output image arrays
   Read an input image from a file

   for (j=0;j<image.height;j++) {
      theta = PI * (j - (image.height-1)/2.0) / (double)(image.height-1);
      for (i=0;i<image.width;i++) {
         phi  = TWOPI * (i - image.width/2.0) / (double)image.width;
         phi2 = phi * cos(theta);
         i2  = phi2 * image.width / TWOPI + image.width/2;
         if (i2 < 0 || i2 > image.width-1) {
            newpixel = red;                         /* Should not happen */
         } else {
            newpixel = imagein[j*image.width+i2];
         }
         imageout[j*image.width+i] = image.newpixel;
      }
   }

   Do something with the output image
Share your code when you're done!

Also, you could combine your map generation and polar correction in the same loop to speed things up. In other words calculate each map pixel and polar-correct it as you go.

Mike


Krischan(Posted 2006) [#5]
Morbius, sorry I forgot to mention that I know this site and tried to write the code in Blitzbasic. But there is something wrong, running my code gives an exact copy of the original image, and I dont know why LOL!

On the other hand, if I take an image from this site and put it on a sphere, the X axis sides doesn't match anymore.

Here's my code attempt:

Graphics 512,513,32,2 

width=512
height=256
twopi#=2*Pi


;read image to array
Dim col(width,height) 


;load source image
raster=LoadImage("raster.png") 


;get color data from source image
SetBuffer ImageBuffer(raster) 
LockBuffer ImageBuffer(raster) 
For x=0 To width-1 
	For y=0 To height-1 
		col(x,y)=ReadPixelFast(x,y)
	Next 
Next 
UnlockBuffer ImageBuffer(raster) 


;create a new image
test=CreateImage(width,height)


;algorithm
SetBuffer ImageBuffer(test) 
LockBuffer ImageBuffer(test) 
For j=0 To height-1 
	theta#=Pi*(j-(height-1)/2.0)/(height-1) 
	For i=0 To width-1 
		phi#=twopi#*(i-width/2.0)/width 
		phi2#=phi#*Cos(theta#) 
		i2#=phi2#*width/twopi#+width/2 
		rgb=col(i,j) 
		WritePixelFast i2#,j,rgb 
	Next 
Next 
UnlockBuffer ImageBuffer(test) 
SetBuffer FrontBuffer() 


;draw results
DrawImage raster,0,0 
DrawImage test,0,height+1 


;red divider line
Color 255,0,0 
Line 0,256,512,256 


WaitKey 


End


The raster image i used is here:




b32(Posted 2006) [#6]
I think the problem itself is the difference between blitz' cos/sin and c++ cos/sin.
In Blitz, cos/sin use degrees and in C++, radians.
The conversion between them is * pi / 180, but I don't remeber which way around, so you might need to invert it.
And I would make all variables float, so that when you use them in a division, the outcome will not become an integer.


Jeppe Nielsen(Posted 2006) [#7]
You switched two variables, and forgot to convert from radians to degrees.

Anyway, here you go:
Graphics 512,513,32,2 

imagefile$="raster.png"

;load source image
raster=LoadImage(imagefile$) 

width=ImageWidth(raster)
height=ImageHeight(raster)
twopi#=2*Pi

;read image to array
Dim col(width,height) 

;get color data from source image
SetBuffer ImageBuffer(raster) 
LockBuffer ImageBuffer(raster) 
For x=0 To width-1 
	For y=0 To height-1 
		col(x,y)=ReadPixelFast(x,y)
	Next 
Next 
UnlockBuffer ImageBuffer(raster) 


;create a new image
test=CreateImage(width,height)


;algorithm
SetBuffer ImageBuffer(test) 
LockBuffer ImageBuffer(test) 
For j=0 To height-1 
	theta#=Pi*(j-(height-1)/2.0)/(height-1) 
	For i=0 To width-1 
		phi#=twopi#*(i-width/2.0)/width 
		phi2#=phi#*Cos(theta#*(180.0/Float(Pi))) 
		i2#=phi2#*width/twopi#+width/2 
		rgb=col(i2,j)
		WritePixelFast i,j,rgb 
	Next 
Next 
UnlockBuffer ImageBuffer(test) 
SetBuffer FrontBuffer() 


;draw results
DrawImage raster,0,0 
DrawImage test,0,height+1 


;red divider line
Color 255,0,0 
Line 0,256,512,256 


WaitKey 


End



Krischan(Posted 2006) [#8]
Jeppe, nice one :-) There is still one issue i mentioned before: the X axis sides doesn't match, here is a 3D test for it:

Graphics3D 512,513,32,2 

imagefile$="planet1.png"

;load source image
raster=LoadImage(imagefile$) 

width=ImageWidth(raster)
height=ImageHeight(raster)
twopi#=2*Pi

;read image to array
Dim col(width,height) 

;get color data from source image
SetBuffer ImageBuffer(raster) 
LockBuffer ImageBuffer(raster) 
For x=0 To width-1 
	For y=0 To height-1 
		col(x,y)=ReadPixelFast(x,y)
	Next 
Next 
UnlockBuffer ImageBuffer(raster) 


;create a new image
test=CreateImage(width,height)


;algorithm
SetBuffer ImageBuffer(test) 
LockBuffer ImageBuffer(test) 
For j=0 To height-1 
	theta#=Pi*(j-(height-1)/2.0)/(height-1) 
	For i=0 To width-1 
		phi#=twopi#*(i-width/2.0)/width 
		phi2#=phi#*Cos(theta#*(180.0/Float(Pi))) 
		i2#=phi2#*width/twopi#+width/2 
		rgb=col(i2,j)
		WritePixelFast i,j,rgb 
	Next 
Next 
UnlockBuffer ImageBuffer(test) 
SetBuffer FrontBuffer() 


;draw results
;DrawImage raster,0,0
;DrawImage test,0,height+1 


;red divider line
;Color 255,0,0 
;Line 0,256,512,256 

SaveImage test,"planet.bmp"

planet=CreateSphere(32)
tex=LoadTexture("planet.bmp")
;test it with this line
;tex=LoadTexture("planet2.png")
EntityTexture planet,tex

cam=CreateCamera()
PositionEntity cam,0,0,2
MoveMouse 256,256
PointEntity cam,planet

While Not KeyHit(1)

TurnEntity planet,0.5,0.25,0.5

RenderWorld

Flip

Wend


End


to see how it should look just remove the comment before entitytexture (you need planet1.png / planet2.png, the two examples from the beginning)


Morbius(Posted 2006) [#9]
I'll have a look tonight. I'm sure you're on the right track.


Morbius(Posted 2006) [#10]
Ah, which projection are you using to make the original map? And the "corrected" map?

Give me the commandline arguments you are using if you can.

The original flat map you posted appears to be truncated at the top and bottom. Entire sections of map are missing that do not appear in the spherical version. This is what is leading you to conclude that your code is wrong when in fact it is fine.

Thanks

Mike


markcw(Posted 2006) [#11]
this is what i got. it basically lowers the amount of distortion, but results in problems at the poles.




Krischan(Posted 2006) [#12]
Morbius, the commandline for this planet is exactly

planet.exe -pq -M terra.rgb -i -0.01 -s 0.1 -w 512 -h 256 -o planet.bmp

the switch -pq calculates the square projection (example 2), changing this to -pm you'll get mercator projection (example 1), oh and terra.rgb is a simple text file:

#333399
#6666cc
#009900
#E8A45A
#F8B45C
#A5806C
#FFFFFF
#000000
#000000

EDIT: here is an animation of the two maps - Morbius you're right, it seems that the map is cut off slightly at the poles in mercator projection mode. The distortion looks like if it increases from equator to poles in an exponential?!? curve:



But even if I take another map it doesn't gets seamless. I've made a small GIF animation to see the difference:



markcw, if I take your code and use the same image we can see the difference, the distortion is not strong enough:



I think we should extract the wisdom from Torbens C code because he knew how to do the trick :-|

My final pseudorandom generated world could look like this (needs more finetuning, first attempt of atmosphere):




markcw(Posted 2006) [#13]
hi Krischan, yes with that algorithm it seems to "push" the data off the map, as can be seen in your gifs. so i guess you're right, it needs the squarep algorithm. i'll have a go at it. what is that algorithm by the way?

edit: sorry missed the link to that article.


Krischan(Posted 2006) [#14]
Hi markcw,

the algorithm is this C code (include in Torbens planet generator, see the link in my first post):

void squarep()
{
double y,scale1,theta1,cos2, log_2();
int k,i,j, planet0();

k = (int)(lat*Width*scale/PI);
for (j = 0; j < Height; j++) {
if (debug && ((j % (Height/25)) == 0)) {fprintf (stderr, "%c", view); fflush(stderr);}
y = (2.0*(j-k)-Height)/Width/scale*PI;
if (fabs(y)>=0.5*PI) for (i = 0; i < Width ; i++) {
col[i][j] = BACK;
if (doshade) shades[i][j] = 255;
} else {
cos2 = cos(y);
if (cos2>0.0) {
scale1 = scale*Width/Height/cos2/PI;
Depth = 3*((int)(log_2(scale1*Height)))+3;
for (i = 0; i < Width ; i++) {
theta1 = longi-0.5*PI+PI*(2.0*i-Width)/Width/scale;
col[i][j] = planet0(cos(theta1)*cos2,sin(y),-sin(theta1)*cos2);
if (doshade) shades[i][j] = shade;
}
}
}
}
if (hgrid != 0.0) { /* draw horisontal gridlines */
for (theta1 = 0.0; theta1>-90.0; theta1-=hgrid);
for (theta1 = theta1; theta1<90.0; theta1+=hgrid) {
y = DEG2RAD*theta1;
j = Height/2+(int)(0.5*y*Width*scale/PI)+k;
if (j>=0 && j<Height) for (i = 0; i < Width ; i++) col[i][j] = BLACK;
}
}
if (vgrid != 0.0) { /* draw vertical gridlines */
for (theta1 = 0.0; theta1>-360.0; theta1-=vgrid);
for (theta1 = theta1; theta1<360.0; theta1+=vgrid) {
i = (int)(0.5*Width*(1.0+scale*(DEG2RAD*theta1-longi)/PI));
if (i>=0 && i<Width)
for (j = max(0,Height/2-(int)(0.25*PI*Width*scale/PI)+k);
j < min(Height,Height/2+(int)(0.25*PI*Width*scale/PI)+k); j++)
col[i][j] = BLACK;
}
}
}

Notes on this code I found out:

- lat/longi is 0.0 (I guess)
- scale is 1.0
- log_2 is log(x)/log(2.0)
- the "Depth" isn't used and makes no sense
- col[x][y] contains the final map data (is being calculated by squarep)
- we don't need shades
- we don't need grids

So we can shorten the code to:

void squarep()
{
double y,scale1,theta1,cos2, log_2();
int k,i,j, planet0();

k = (int)(lat*Width*scale/PI);
for (j = 0; j < Height; j++) {
y = (2.0*(j-k)-Height)/Width/scale*PI;
if (fabs(y)>=0.5*PI) for (i = 0; i < Width ; i++) {
col[i][j] = BACK;
cos2 = cos(y);
if (cos2>0.0) {
scale1 = scale*Width/Height/cos2/PI;
for (i = 0; i < Width ; i++) {
theta1 = longi-0.5*PI+PI*(2.0*i-Width)/Width/scale;
col[i][j] = planet0(cos(theta1)*cos2,sin(y),-sin(theta1)*cos2);
}
}
}
}

What I don't understand is the call of planet0(x,y,z), I think the code calculates somehow the planet surface color for a given x,y,z coordinate and distorts the value from this position to the final image. But this function is very confusing to me.


Morbius(Posted 2006) [#15]
Thanks for posting. I'll have a look tonight. Judging by the animated gif, (very helpful!) it appears that it is just squeezing the lattitude as a proportion of the circumference of the circle at some lattitude to the circumference of the equator.

To find the circumference at a given lattitude: C = E * Cos(L)

Where:

E is the circumference at the equator
L is the lattitude (O at the equator, 1 at the poles)

It's hard to tell exactly what is going on at the poles since they are truncated in the original map. I'll check out the algorithm above and see if I can get a clue. It looks like it's squeezing (vertical) as described above, then doing a little stretching (horizontal) (near poles?)

Thanks

Mike


markcw(Posted 2006) [#16]
hi Krischan, yeah i looked at the planet.c code but i couldn't understand the planet functions either. but i went back to the other algorithm and ended up rewriting it. the theory is you distort according to an arc, but a standard sin arc isn't enough, you need a steep arc. the result of some further tweaking is enough to get what you need i think.

i have two codes, one for the planet sphere and one for the image to show how the custom sin curve is obtained.






Ross C(Posted 2006) [#17]
Hmmmm, seems like a lot of bother... Why not just use a geosphere? That would solve your problems :)


Krischan(Posted 2006) [#18]
markcw, thanks for your nice demonstration, the result is here:



I used a different map (perlin noise with a shaded relief) with more land mass at the north pole, and you can clearly see that the distortion looks strange there. A simple solution would be to have an ocean at the poles, so that the distortion seems to disappear in a single color, but this is only useful for creating Class M planets (think about a pluto-style planet or even jupiter with its clouds).

Ross C, I already thought about it but the result looks like on a sphere, or do you have another solution or example code/mesh for it? Here is a screenshot with a 32 segment Icosaeder geosphere:



For both examples I used this new colormap:



I think the only useful solution is to translate the *complete* source from Torbens planet generator to Blitzbasic and see if it is working there (without knowing *why* it's working LOL). But I'm afraid that Blitzbasic is not fast enough to calculate the planet in an appropriate time but we'll see (the DOS program is not that fast already).

Any suggestions / hints concerning known traps if I translate C code to Blitzbasic? Never did that, beside Basic I know PHP and a little bit Java... never coded in C but it looks a little bit like Java syntax.


Ross C(Posted 2006) [#19]
Well, the problem using sphereical mapping, is the mesh's UV co-ords are always going to be squeezed at the top. Have you tried using a cubemap? I'm not sure how you would go about creating a cubemap from this...


markcw(Posted 2006) [#20]
hi Krischan, i have been translating the planet.c code. thought you might like to see what i have so far. it is now functioning.

edit: just an update on what i have now.
edit2: ok, another update, it now prints the heightmap, i think.
edit3: added the mercator function.
edit4: added 5 more of the projection functions.
edit5: added the last 4 projections.
edit6: fixed sinusoid map projection, added ppm output.

code is now here:
http://www.blitzbasic.com/codearcs/codearcs.php?code=1831


Morbius(Posted 2006) [#21]
Amazing! It would take me a week to get that far. I've done a little further research and found that what we're looking for is called a geographic lat-lon projection. It really isn't a projection at all, and the cartographers don't recognize it as such.

The trick, as I understand it so far, is to treat lats and lons directly as if they were x and y coordinates with lat -90 to 90 and lon -180 to 180. If I get anywhere, I'll share it.

Good luck to you both!

Mike


Krischan(Posted 2006) [#22]
markcw, I'm deeply impressed how far you got, I didn't even start my own code! I would love to see the final result and hope that we'll get it to work in BB!

Ross, I've hade some experiments with geospheres but I don't get it how to put a texture on it. Only a premade UV-mapped geosphere worked, but none of the codes here which create a geosphere in BB. The sphere gets some color from the texture but that's all.

Morbius, I think the correct name for this is "equidistant cylindrical projection", read this:

The simplest of all map graticules belongs to the equatorial aspect of the equirrectangular projection, referred to by many names like equidistant cylindrical, plane chart, plain chart and rectangular. It is a cylindrical projection with standard meridians: all have constant scale, equal to the standard parallels's, therefore all parallels are equally spaced. It was credited to Erathostenes (ca. 200 b.c.) and to Marinus of Tyre (ca. 100). Its trivial construction made it widely used, even for navigation, until the Modern Age.

A special case of the equirrectangular projection is called Plate Carrée, or simple cylindrical: the Equator is a standard parallel, so it is twice as long as all meridians, making the map a 2 : 1 rectangle and the graticule's grid square.

Fast, trivial equations led to its resurgence in rough computer-drawn maps, with early machines or real-time graphics. It is still commonly used in digitized textures ("skins") of earthly and planetary features.

From http://www.progonos.com/furuti/MapProj/Normal/ProjCyl/projCyl.html

There is a nice overview of projection techniques, too:
http://www.progonos.com/furuti/MapProj/Normal/TOC/cartTOC.html


Morbius(Posted 2006) [#23]
We're learning more about cartography than we ever imagined, aren't we!


markcw(Posted 2006) [#24]
i'm having problems. i have the mercator function translated and the "commandline" is set to do that function, but i think there is a problem with converting from radians to degrees, as the output is just blank.

it draws the vertical gridlines ok but not the horizontal ones, there's a commented line on what it was, and then my attempt at converting radians to degrees, but i don't know how to do that, maybe you could fix it Krischan/anyone?

i'll move on a translate the other ones now.


Morbius(Posted 2006) [#25]
Degrees = Radians * (Pi / 180) ?

You're conveting theta1 to radians then back to degrees?

y = Sin(DEG2RAD*theta1 * Rad2Deg) ;y = Sin(DEG2RAD*theta1)



Morbius(Posted 2006) [#26]
Back to cartography for a moment - There's a nice illustration of the geographic projection here:

http://www.3dsoftware.com/Cartography/USGS/MapProjections/Cylindrical/PlateCarree/

And here's some fantastic info:

http://www.lepp.cornell.edu/~seb/celestia/textures.html#2.1




markcw(Posted 2006) [#27]
hi Morbius,

well, while translating the sinusoid projection i found the gridline projections worked when i did sin or cos(value*Rad2Deg) where Rad2Deg = 180/Pi. And when i went back to the mercator function i found i could do:
Sin(theta1) or Sin(DEG2RAD*theta1*Rad2Deg)
but i still had to edit the original code before it worked.

i still can't get anything working for the actual map projections though, but i'm thinking it must be something wrong in the planet functions, but it's confusing because they don't have any sin/cos commands.

i will just ignore it for now and get the rest of the projections translated.


markcw(Posted 2006) [#28]
hi Krischan,

that's all the important stuff translated now. the only stuff left is the output to ppm or xpm formats, which i'll do later.

i have tested all the projections and compared them to identical commandlines in planet.exe, and all the gridlines match now that i converted sin/cos to rad2deg.

the last 5 projections don't have any lat/longi specifications so they are at 0,0 always. strange how it isn't finished.

also there's something funny going on in the conical projection one, most of it comes out black. so i've edited it to force blue to see the gridlines.

so that's the gridlines working but still no actual map data. :/

edit: ok, found the problem, it was the initial altitude -i or M in the code which needs to be around 0.3 for some reason. it works now, yippee!


Morbius(Posted 2006) [#29]
Wow! I'm blown away. Really amazing work there!


Krischan(Posted 2006) [#30]
markcw, that are really good news today. I would love to see it running in Blitzbasic, by the way: how fast is it calculating a 1024x512 map in square projection? And did you notice, that when you apply lat/lon data and a magnification level of 10 or 100, the details get finer and finer, shores and small islands appear :-)


markcw(Posted 2006) [#31]
Hi Krischan,
i have moved the code to here: http://www.blitzbasic.com/codearcs/codearcs.php?code=1831
i had to remove a bit so it would fit. i will edit it some more.

can you not run the code? i haven't tried 1024x512 but it is slow, especially when you increase the -m (magnification) option.


Krischan(Posted 2006) [#32]
Hi markcw,

sorry I didn't see that you've posted the code to the code archive. Huh, you really translated the complete source, respect! It works very good, I played a little bit around but still don't get it how the square projection works, I'm even more confused now. The "planet1" function returns incredible small numbers (smaller than 0.0000xxx) and I think I'm just too stupid to understand the technique behind it. Unfortunately, the planet generation in higher dimensions (1024x512) is way too slow for nearly realtime calculation (for ex. when entering a solar system, screen message: "Scanning system..." for ~ 3-5 seconds)

Calculating a perlin noise cloud is ~ 100 times faster than Torben's algorithm (ok, Torbens planet looks nicer, so it should take longer). But I don't know how to distort such a perlin noise image with torbens squarep algorithm, because we have X/Y/Z coordinates, and Torbens code calculates the height (=alt) out of these coordinates, but my perlin cloud is only 2D. Huh? Why does it need a Y coordinate?

So "my" holy grail of planet generation would be a mixture of a fast perlin cloud and its distortion with squarep.


b32(Posted 2006) [#33]
When you found a method that works, but is to slow, maybe you could precalculate a table. Say, two arrays, containing the projected coordinates ie. newx(x, y) and newy(x, y)


markcw(Posted 2006) [#34]
hi Krischan,

well knowing a bit about calculating stuff i can say there is a rule that usually works, which is: quality is relative to time. so if you want quality AND speed then you'd need to precalculate the maps ie. save out the maps to be loaded into the project later.

looking at the planet functions i can't see anything you could do to speed them up, they are already optimized.


Morbius(Posted 2006) [#35]
Krischan: Here's a link to a very complete projection system with source http://www.users.globalnet.co.uk/~arcus/mmps/

markcw: There's an interesting projection in this code called a perspective projection, which basically maps the texture around an imaginary sphere, complete with shadow casting. You could use this to render a small quick billboard imposter of the planet and save the heavy calculation for close ranges.


Krischan(Posted 2006) [#36]
I have another idea how to distort the texture, maybe it is working. The idea is to convert the cylindrical map into a sinusoid projection, so that the poles get pinched to a singularity and remap this sinusoid back to a cylindrical projection.

Here is my example code using the planet1.png (first image in this post) which converts the image into a sinusoid-like one. But now there is a problem: I dunno how to convert this image back to a flat image :-(



source:


output:



ShadowTurtle(Posted 2006) [#37]
If you want more details, do re-calculate the uv coords instead edit the image from texture.


Krischan(Posted 2006) [#38]
ok, here is my "solution" but I'm not very happy with it, still pinching at the poles and the code looks messy:





This tech demo shows all three maps in a row


Krischan(Posted 2008) [#39]
Well folks, after two years I found the solution to this, but unfortunately it is written in Dark Basic Pro. It is a custom Perlin3D noise function which produces a smooth and spherecompatible texture. I tried to translate this to BB but wasn't successfully. Is anybody able to locate the error or rewrite my attempt that we get the same results in BB?

Dark Basic Pro output:


My BB attempt output:


The Dark Basic Code


My BB attempt Code



mtnhome3d(Posted 2008) [#40]
couldn't you use a sphere with pre-done uv coords and then generate the map and then place it on the spherein the game?
also how did you get that atmosphere?? its awesome looking


Krischan(Posted 2008) [#41]
This one is seamless and easy to use. The Atmosphere - dunno - i have to look in my archives. But I worked further and got a different pic now, still not working correct. Looks like something has turned upside down with Sinus and Cosinus coordinates. The main problem was that you can declare in Dark Basic variables twice so I renamed them all that they can't collide in BB. At least I can see some parts of a shoreline now :-)

But I still need help here:






Floyd(Posted 2008) [#42]
I think the remaining problem is Int(), which is misnamed in Blitz3D. It should be called Round() since it rounds to the nearest integer. Every other language I know uses Int() to mean "integer part of", i.e. discard the fractional part.

So here is a quick fix. I did a search and replace to change every Int( to DBInt(, which chops off everything after the decimal point.




big10p(Posted 2008) [#43]
Int() also has this strange behaviour:

Int converts floating point numbers by rounding to the nearest integer.
NOTE: This is not the traditional meaning of Int in Basic.

What about numbers exactly halfway between integers?
The rounding is to the nearest even integer:

Int( 2.5 ) ... produces 2
Int( 3.5 ) ... produces 4




Kryzon(Posted 2008) [#44]
Just use Int( Left( Number,1) ).


big10p(Posted 2008) [#45]
Kryzon, that wont work for numbers with more than 1 digit or negative numbers.


Kryzon(Posted 2008) [#46]
True. Nevermind that.

To bypass Blitz's rounding system, use strings (since blitz doesn't round strings, it just returns the number until the "."):
Print Int( 2.9 )  ;result is 3
Print Int( Str(2.9) ) ;result is 2, which is what it should be in the first place.



Krischan(Posted 2008) [#47]
Thanks to all, that is the solution! I wonder if I could speed up the whole code since it is a little bit slow for on-the-fly generating a planet. Perhaps pre-calculated sin/cos tables?


Stevie G(Posted 2008) [#48]
For a decent speed up, lock the buffer and use writepixelfast, instead of plot.

Also, just use the native float command rather than this ..

Function flo#(a)
	
	b# = a*1.0
	
	Return b#
	
End Function



Ross C(Posted 2008) [#49]
Just an alternate idea. Have you tried a geosphere, with a cubemapped planet texture?


Krischan(Posted 2008) [#50]
Stevie G - yeah "Plot" was used just for test purposes, sure "Writepixelfast" is faster for output. I was talking about speed up the calculation and my tests results showed that Float is slower than x*1.0.

Ross C - I only read about this but I am too dumb to realise it, are you talking about a "smoothed cube"? At the moment I am using a geosphere mesh instead of a sphere, but the texture only mapped to it the standard way. My goal is a planet generated by a seed which looks like the planets in "Freelancer" - they were simple but looked fine from a certain distance. And do you remember the game "Starflight"? There were nice but low resolution planets where you could land and drive over the surface (in 2D). I dunno how they did it (both the Freelancer planets and these in Starflight).

Another thing I was thinking about is creating and coloring a geosphere direct from the 3D Perlin cloud:

- generate a 3D Perlin Noise cloud
- calc the X/Y/Z Coordinates of Geosphere vertices
- Vertexcolor these vertices with the "color" from the same position in this cloud
- or even apply a texture depending on the "height" of the vertex, e.g. sea/grass/mountain
- realtime subdivide the visible patches if you get closer and modify the geosphere by the Perlin cloud data to get more detail

A very advanced engine using this technique (as far as I understood) is "Infinity":

http://www.infinity-universe.com/Infinity/index.php?option=com_zoom&Itemid=90&catid=4&PageNo=2
http://www.youtube.com/watch?v=DCzDKj3hjOE&feature=related

In Darkbasic there is a simple example how they did it, and even untextured it looks awesome!
http://forumfiles.thegamecreators.com/download/1527504


Ross C(Posted 2008) [#51]
Ah i see what you mean now.