Recalculate normals if vertexlit after deform

Falagard

24-03-2006 16:51:25

Hey Tuan,

I have a feature request. Can you recalculate normals after a deform if vertex lighting is enabled?

I haven't yet tested it, but looking at the code it doesn't appear that the deform code does it, so I anticipate it being a problem.

Thanks

Clay

tuan kuranes

24-03-2006 16:58:28

Well, now normals are computed on the fly.
heightmap normal was intended for this at start, but finally it doesn't really need to be precomputed (unless used for normal mapping)

Falagard

24-03-2006 17:23:43

What do you mean vertex normals are calculated on the fly? Do you mean in a vertex shader? What if it's not using a shader but instead is using fixed function?

tuan kuranes

24-03-2006 17:39:02

vertex lighting was meaning fixed function lighting and/or per-vertex shader lighting (normals are uploaded inside vertex buffer, and updated on the fly along with deformation)
(but that gives ugly lights, because of LOD making vertex normal very worng)

Updating normal texture is indeed useful for shaders using per-pixel lighting, and is indeed missing.

That can be done.

Falagard

24-03-2006 18:03:58

Nope, that's fine as long as the vertex normals are updated at the same time as deformation. I couldn't find where the code was recalculating normals, but now I see it, when deformHeight is called it tells the renderable to reload and then load() is called which gets the height data again from the Data2D class. Sorry I missed it earlier.

What I'm planning is to just turn on vertex lighting when editing the terrain. Then when the user wants to see the final terrain they'll hit a button which will export it and do things such as calculate shadowmaps, calculate normal maps, or whatever I end up doing. That process could a minute, or a few hours in the case of calculating shadows if I'm including meshes casting shadows on terrain and themselves ;-)

So, everything should be fine as-is.

Thanks

nindim

28-03-2007 18:06:58

I hate to bring up an old topic, but I'm having some problems with the normals generated when I deform the terrain.



The image above shows two of the same exact deformations applied to the terrain. The one on the left has been applied to the terrain, the app was then closed and re-opened, at this time another deformationw was applied to its right.

As you can see, if the app isnt closed and reopened the shading on the terrain is incorrect, I assume this is because the normals get recalculated when the terrain gets loaded up again.

Here is my .cfg file in case theres anything in their that may cause this:


GroupName=PLSM2

Width=2
Height=2

Data2DFormat=HeightField
LandScapeFileName=testMap
FileSystem=testMap

TextureStretchFactor=2

NumTextureFormatSupported=1
TextureFormatSupported0=PLSplattingShaderLit
TextureFormat=PLSplattingShaderLit

ScaleX=10260
ScaleY=5100
ScaleZ=10260

VisibleRenderables=75
NumRenderablesLoading=10
RenderableLoadInterval=3
MaxAdjacentPages=1
MaxPreloadedPages=2
PageLoadInterval=5
MaxNumRenderables=256
IncrementRenderables=256
MaxNumTiles=256
IncrementTiles=256
#SaveDeformation=no

Deformable=yes
VertexCompression=no
VertexProgramMorph=no
VertexNormals=yes
VertexLit = yes
TextureModifiable=yes
MaterialDistanceLod=8000
HorizonVisibilityComputing=yes
PageSize=513
RoughnessLod=yes
DistanceLOD=1
#MaxRenderLevel=100
#MaxPixelError=8

NumMatHeightSplat=4

SplatFilename0=Terrain_Dirt1.jpg
SplatFilename1=Terrain_Rock1.jpg
SplatFilename2=Terrain_Grass1.jpg
SplatFilename3=Terrain_Cobble1.jpg


What I'm really wondering is if anyone has encountered this before and knows how to fix it? I tok a look at the deformheight function falagard mentioned and the only lines I could see that may deal with the relaoding of the deformed terrain is here:


if (t && t->isLoaded ())
{
mImpactInfo = t->getInfo ();
// check page boundaries to modify any page, tile neighbour
// tells any tile modified to update at next frame
assert (curr_indx < mBrushArrayWidth*mBrushArrayHeight);
if (mData2DManager->deformHeight (currpoint, h, mImpactInfo))
mTextureManager->deformHeight (currpoint, mImpactInfo);
} // if (t && t->isLoaded ())


I assume this is what Falagard meant when he said "when deformHeight is called it tells the renderable to reload and then load() is called which gets the height data again from the Data2D class"?

Edit: I have noticed that if the tile is unloaded due to the camera not being able to see it, when it comes back into view the correct normals have been calculated, again, i assume this is due to the load/unload. Can this be called manually say at the end of my deformation?

nindim

03-04-2007 13:50:28

I've tried quite a few different things now, seems like there is an UpdateTerain() method which doesnt ever seem to get called. I added that to the deformheight function, It works to a certain degree....
If I deform an area it initially looks the same as the deformation to the right in my previous picture. If i then deform over that area again then it will update the normals correctly.

I have also tried manually calling unload and load but that usually just results in assertion errors :(

I'm a bit stumped to be honest, could anyone with a bit more knowledge of the inner working of the PLSM2 perhaps explain to me what needs to be done? Possibly Tuan if he happens to read this?

nindim

03-04-2007 14:39:19

Ok, well I've figured out a workaround for this.

It looks as though the PLSM2 is in fact recalculating the normals, just its not doing all of the ones required. If you apply a 10 x 10 brush to the ground, then there will be 10 x 10 vertices pulled out of the ground. Because of the nature of how the terrain is made though (triangle strips) this reuslts in the triangles surrounding the deformation to be streched up. As the other vertices in these surrounding triangles are not actually part of the deformation, their normals are not recualculated.

The workaround is pretty simple, if I apply a 10 x 10 brush to the ground, i simply apply another brush 2 pixels in width and heigth larger. This means those vertices are now being recualculated. The trick is to negate the effect of this larger brush which is simply done by multiplyign the scale by minus one and applying he same brush again.

Effectively this method does mean you're applyign 3 brushes per deform, but at least it works and it looks nice.