A quick 3d World...

Thought this might help some. It’s nothing special… but, basically, I have been a coder for years but never a 3d modeller. Common problem? Dunno.

Anyway, I didn’t want a stock terrain, I wanted something unique. So I did this:

  1. Grab L3DT from bundysoft.com/L3DT/ …in my case, got it running under Linux using Wine.

  2. Generate terrain using it’s nice interactive designer.

  3. Save out the height map and the texture map as images.

  4. Bit of Python:

from panda3d.core import GeoMipTerrain

terrain = GeoMipTerrain("worldTerrain")
terrain.setHeightfield("heightmap.jpg")
terrain.setColorMap("colourmap.jpg")
# terrain.setBlockSize(512)
terrain.setBruteforce(True)

root = terrain.getRoot()
# root.reparentTo(render)
# root.setScale(0.5,0.5,0.5)
# root.setPos(0,0,0)
root.setSz(60) # max height

terrain.generate()
root.writeBamFile('gworld.bam')
  1. Run it…out pops your BAM file. bam2egg if you want the egg file etc.

I realise I could just leave the GeoMipTerrain code in place and use in whatever app is being developed. But load times became a problem for me (especially as I was brute-forcing the terrain).

In short, I figure a nice speedy BAM file is much better than generating the terrain on every app execution.

Oh, last thing: for reasons unknown, I found I had to vertically flip the texture map else the GeoMipTerrain was wrong! Anyone else seen this?

Cheers,
~G

Confirmed. I started over with a height/terrain map. I put a white circle on the height map to create a column. A red dot on the terrain map in the exact same position - you’d expect a red top to the column right?

…nope. Not how it comes out. Flip the terrain map vertically and it is correct. A bug?

Tried this on Linux and Windows with same result.

Cheers,
~G

It doesn’t sound like a bug to me; it just sounds like a disagreement between L3DT and GeoMipTerrain as to which is the correct orientation to apply the map.

There are clearly at least two different common conventions. One tool chose one convention, the other tool chose the other one. It just means you need to adapt when you convert from one tool to the other.

David

Exactly. And it’s easy to apply a setTexScale, or just put a minus sign in front of the Y texcoord if you use a shader.

Convention? I guess that could be the case, but the exports from L3DT are aligned and oriented correctly with relation to each other. i.e., like this:

So you wouldn’t expect to have to flip the terrain… cept you do.

Perhaps it is convention and not a bug, it just seemed somewhat illogical to me. :slight_smile:

Cheers,
Gary

That’s a good point, but unfortunately I can’t change that at this point any more. In any case, it’s an easy workaround.

I completely agree. It would cause havoc to change it now. Is it possible, then, to have a small note in the Panda3D manual on the GeoMip page?

I’m sure others have done a bit of head scratching over it, as I did. :slight_smile:

All that said - it’s an awesome feature, saved me tons of time!

Cheers,
Gary

I’ve been playing with l3dt/panda3d and I’m a bit confused by this thread.

I have not seen where I need to flip anything??? I just tried putting a while circle on the heightmap and a red dot on the texture map in the same place and ended up with a red column.

If you write it out as a bam file, then later use that bam, don’t you lose the geomipterrain functionality? No more LOD, etc?

Right.

Yup, that’s why I setBruteForce(True). Generate the full terrain in the highest LOD then write that out as a model.

The bam generation simply avoids the need to generate the terrain which, in my case, led to long load times.

I suppose I’m a little confused myself! If you follow the Panda3D manual when starting out, it has you using models for the world - not any terrain generator. Ditto with the examples (Roaming Ralph etc.).

I guess (and I’m sure I’ll be corrected if wrong!) that using a GeoMipTerrain with varying LOD is best suited to very large terrains. But if your world/game area isn’t that large - a model is better suited.

The point of the exercise/thread was a quick and easy way to get going with a 3D world for those who do not have 3D modelling experience (i.e., using GeoMipTerrain instead of sitting in Blender or similar creating the landscape).

Sorry if it’s confusing!

Cheers,
Gary

Where on the height map did you put the dot? I can assure you - because I’ve done it several times now - that if you put a white dot, say, bottom right on the height map image… then red dot bottom right on the texture… they won’t come close to lining up until you flip one of the images. I’ve had other people try too with the same result using both the current stable release of Panda and the CVS version on both Linux and Windows.

As noted before, if it’s ‘convention’ that height/colour map be opposite vertically then so be it. If not - it’s a bug or an ‘undocumented feature’, hence I suggested a note in the manual.

Cheers,
Gary

Interesting, I put the white dot in the bottom right corner of the heightmap, the red dot in the bottom right corner of the texture map, and they line up. Purely coincidence that I chose bottom right…

Panda 1.7.0 on linux (Linux Mint - variant of Ubuntu 10.04)

Code - stripped out everything unrelated:

import direct.directbase.DirectStart


from pandac.PandaModules import *

render.setShaderAuto()



def blendtex(texture, stage, SORT):
    ts = TextureStage(stage)
    ts.setSort(SORT)
    ts.setCombineRgb(TextureStage.CMModulate, TextureStage.CSPrevious, TextureStage.COSrcColor,
                                                  TextureStage.CSTexture, TextureStage.COSrcColor)
    ts.setRgbScale(2)
    root.setTexture(ts, texture)
    ts.setSavedResult(True)
    
    
# add ambient light
ambient = Vec4(0.34, 0.3, 0.3, 1)
alight = AmbientLight('alight')
alight.setColor(ambient)
alnp = render.attachNewNode(alight)

dlight = DirectionalLight('dlight')
dlight.setColor(VBase4(0.8, 0.8, 0.5, 1))
dlnp = render.attachNewNode(dlight)
dlnp.setHpr(0, -60, 0)


# Set up the GeoMipTerrain
terrain = GeoMipTerrain("genTerrain")
terrain.setHeightfield("simpleheight.png")
terrain.setBlockSize(64)
terrain.setBruteforce(1)         
        
# Store the root NodePath for convenience
root = terrain.getRoot()
root.reparentTo(render)
root.setScale(4)
root.setSz(200)
terrain.generate()

######  Load textures and alpha maps
tex0 = loader.loadTexture('simpleheight_TX.jpg')


render.setLight(alnp)
render.setLight(dlnp)


blendtex(tex0, "finalstage", 200)

run()

the heightmap

scaled down version of texture

output - I eyeballed the white/red dots so they are not perfect, but close enough to show I don’t need to flip anything.

Not saying you don’t need to flip anything, it sounds pretty clear that you do. Maybe I don’t understand what you are doing and I’m doing it differently??? Is this something specific to using BAM files that I’m not seeing by using geomipterrain directly?

lol, awesome!

Ok, I see the difference. You’re using setTexture, I’m using setColourMap. If I use setTexture, it’s correct. So I still think you’d expect the same with using setColorMap right?

…and… what’s the difference? I might be being a bit thick, but both basically do the same job.

Every day is a school day, thanks for the help!

Cheers,
Gary

1 Like

They don’t do the same job, as setColorMap assigns vertex colours, so it’ll be lower quality (although when you’re using bruteforce rendering and if your colour map is the same size as the height map, there is indeed little difference in the result.)

Hi.

I’m new here and i just got started on the whole 3D game development thing.

This thread was very helpful to me, but now that i’ve got the .bam file generated, how can i use it?

Thanks.

This is the way to load a .bam file (same as .egg)

from direct.showbase.ShowBase import ShowBase
 
class MyApp(ShowBase):
 
    def __init__(self):
        ShowBase.__init__(self)
        self.world = self.loader.loadModel("world.bam")
        self.world.reparentTo(self.render)
 
app = MyApp()
app.run()

This is coming from an example on http://www.mygamefast.com, has excelent tutorials for Panda3D.

Never ever pass “anything.bam” to loadModel()!!!

Use the file name without extension instead. Panda will automatically look for such a file with bam or egg ending respectively.

Bam files are automatically generated and of binary form, that loads fast, but is not editable and constrained to a version of panda.

Please read about that on the manual. It’s all there.

That’s not true. Panda will only append .egg automatically in the SDK build. If you want to load .bam files in the SDK build, you do need to append the .bam extension.

Ok, i’ve managed to load the .bam file, but the game takes a lot of time to start and when it does, it’s really slow!

Maybe it’s because my .bam file has 270MB, i don’t know.

Oh and it’s showing up almost flat, while the terrain i made with L3DT is very high.

Ok, I apologize. I thought the loader would automatically search for bam first. (It certainly would make sense, I think)

I probably have mistaken it with something else… >_>

sry.