I thought the list might be interested in some notes on this subject. We will be attempting the implement the scheme described below in the near future, and if there is interest I would be happy to share the results.
Dave Yazel Cosm Development Team http://www.cosm-game.com TREES ---------- I have been toying with these ideas for a while and wanted to get them jotted down so we don't lose them. There are some wierd things that make 3d worlds come alive. Trees, shrubs, flowers, weeds, ferns, grass, sticks, rocks, pebbles, worms,birds, etc. Cosm is right now a very barren place, despite the illusion. There are many problems with displaying all that in a way which looks good but does not crush your frame rate. These things very much differ from POI ("points of interest"). Cosm's POI manager is pretty efficient. It will bring a tower into being and place it in the right place when it needs to and not before. It will even manage duplicate objects, like boulders, and constantly move them around to conserve memory. So as you walk through the world rocks are being removed from behind you, then scaled and rotated and placed in front of you... and you never see it happening. We are currently managing trees in this manner. A pool of trees is created and they are moved around as you walk through the world. On my geforce II I can push the distance out pretty far and see a lot of trees. The problem is that it starts to really soak up the frame rate, and these trees arn't even very good. They are low poly and ugly. When we put nice trees in the scene then we might start to lose a lot of frame rate, or be forced to bring in the clip. So I would like to experiment with something called imposters. An imposter is a picture of something that is placed in the scene to fool you into thinking that it is really there. Its like if someone painted a big picture on a billboard and went and placed it in a field and when you looked at it you thought there really was a tree there. An imposter is usually a flat plane oriented to face the camera. So as you move, the billboard rotates to be parallel to your viewport. This gives the illusion that the imposter is really 3-dimensional. If the billboard did not rotate then it would become thinner and thinner as you approached it from an oblique angle, until your were looking at it edge-on, whereupon it would be invisible. Imposters can usually be pretty small, depending on how close you want the imposter to get before you replace it with the real thing. Now I should pause here and discuss some technical constraints: 1. There are two ways of doing transparency, blended or boolean. With boolean transparency each pixel in the image is either off or on. If it is off then whatever is behind that pixel shows through. With blended transparency you can have a pixel which is translucent. This is very good for edges of things, and especially good for vegetation and trees. The issue is that for something to be blended with stuff behind it, then that stuff has to already be drawn. Translucent items therefore have to be drawn after all opaque objects, and the translucent obejcts themselves need to be sorted to make sure they are drawn back to front. 2. The basic thing that is drawn in Java3d is a "shape3d". A Shape3d consists of a bunch of triangles and directions on how to draw them. The directions are called the Appearance. The appearance controls the texture, the materials, transparency options, coloring, zbuffering, etc. Basically the appearance controls everything about the shape except its geometry. There is a fixed overhead in drawing Shaped3D's. A long time ago I created tree imposters in Cosm, each one in a shape3d. 1000 trees reduced my frame rates to a crawl. The reason was the overhead of all those shapes. The other reason is that each of those shapes had to be transformed to be moved into the scene, and that each of those shapes needed a behavior which handled the rotations per frame. So basically 1000 transforms, 1000 behaviors, 1000 shapes with 1000 appearances and 1000 geometries. All to draw 1000 identical trees. Now I did use link nodes for the Shape3d, so it was using the memory of 1 shaped3d, but it was rendering 1000 shapes. 3. There is something called a GeometryUpdater. This is basically a method to change the geometry dynamically. We use this for skin and bone animations, particles, sky system and lots of other things. With geometry updaters I can adjust the each vertex's color, texture coordinates, normal and position. We can also add and remove new vertices. The disadvantage is that all this information has to be sent over every frame and therefore cannot use display lists stored on the 3d card. The other disadvantage is that all that geometry in a single updater has to share the same Appearance, which namely means it is sharing the same texture. Ok onto the imposters. If we use a geometry updater, with every 4 vertices being a single vertex, we could draw 1000 trees with 4000 vertices, one shape and one texture. This would be very fast. For every frame we would re-sort the trees by distance to viewer, then loop through them and build up the buffer. For each tree we would check to see if it was within view. If it was not then we would exlcude it. I am confident this would work very well and run very fast. Well, it would work very good if all we were showing was pine trees. But what about a mixture of trees? I mean a forest has more than one type of tree generally. If we had two of these updaters, one for each tree then each tree would be rendered in a different shape3d, which means their order would be all one types of tree, then all the other type of tree, etc. But these trees need translucent (anti-aliased) edges to look good, so they need to be rendered in order. So we would be forced back into having a single shape3D for each tree, back into our basic problem. But how big does a tree texture need to be, especially if it is a far away tree? Well a far away tree could be 20 pixels high or less, but a tree half the distance away could be 200 pixels high. So we can probably assume that a picture of a tree could be 100 x 100 pixels and still scale reasonably to 20x20 or 200x200. We would have to play with the numbers. Let us say then that we made a composite texture, sized 256x256. On this texture we could place four 128x128 images on it. I am not being precise here, since we will need a bleed border between the images, but we are doing estimates here. This would mean that we could show 4 different types of trees all with the same shaped3d! Ah but there are a few problems. The first is that four different tree types in the scene is not very many, and what do we do about transitionary borders when we change from one area to another, each of which might have different tree types. Well one solution might be to move to a 256x512 texture, which would double the tree count to 8, or to a 512x512 texture which would move us to 16. I dare say that 16 different types of trees in view at one time would be sufficient. Remenber that each tree can be scaled slightly differently or orientated slightly differently. The next problem is that a single picture of each tree is not sufficient. To do it correctly you would need to take snapshots of the trees from different angles and then pick the right picture based on the orientation of the tree and your relationship to the tree while viewing it. So while there might be 100 pine trees which are all really the same, they are each placed into the world with a slightly different scale and roatation. The less we respect that in our imposters, the more obvious it will be when we swap out the imposter and swap in the model. So we could take the 128x128 space and divide that into 4 peices, each one representing the tree from a different angle. This would work really well for far away trees, but those 64x64 trees might start to scale badly when they are taking up 200 pixels of screen space. We won't know until we try it. Now as you get closer to a tree there comes a time when we will replace the imposter with the model itself. This is usually pretty obvious if you are looking for it, especially if the "real rendered trees" radius is pretty small. I don't think this is a particularly high proce to pay however. I know Asheron's Call does this and it has never bothered me at all. Another nice technique would be to make far away trees more and more transparent until they just fade away. PLANTS ------------ The next category is all the other stuff which you would expect to see in the world around you. This could be flowers, weeds, grass, small pebbles,etc. basically anything which falls into the category of "mentally dimensionless". I use this phrase to describe those things that exist on the periphery of our conciousness. We don't really look closely enough at them to notice they are 2 dimensional. If you see a field of grass and dandylions you never look at each dandylion individually, instead you see the "effect" of lots of little yellow flowers. So the dandylion could be drawn as a very small texture of a yellow flower with no stalk. If this was mixed into ground cover then this would appear to be legitimate dandylions. So the idea is that we assign a bunch of "ground cover" objects to an area, build a composite texture which includes all the little images and render them using the same technique as we are using for trees. Except this time the radius extends from the view outward. We should not go out further than the the break between real and imposter trees, since they are being rendered in two different shapes we don't want them to collide, but in practice we will render the ground cover after we render the imposter trees. Thats the basic idea. I will publish more detailed information after we do some of the implemtation so we can get a feel for how this will work in practice. =========================================================================== To unsubscribe, send email to [EMAIL PROTECTED] and include in the body of the message "signoff JAVA3D-INTEREST". For general help, send email to [EMAIL PROTECTED] and include in the body of the message "help".