|
|
I've mentioned my problem with height-field smoothing before, but now I
actually have a very good idea of how to fix it. I created a little
snippet of code (more would need to be added) to allow the "smooth"
keyword in a height field to supply a number, and that number would be
used to control the amount of smoothing--a grave necessity, I think. My
pseudocode deals with the smoothing itself, not with the parsing, but it
shows how my idea could be implmented.
(I also posted this in povray.text.scene-files, but Bob suggested I post
here; so I have.)
Aside from changes in hfield.c and hfield.h, changes are required in
parse.c to allow the smooth keyword to accept a numeric value (or to use
1.0 as a default if the keyword is found). The change would go something
like this:
height_field {
...
smooth [float value]
}
The float value is smooth_exponent, a value used in the normal
calculation process. If this is just 1.0, then linear interpolation of
the corner vectors (the current default) is still used, and the
original code is called for the sake of speed. If it's not 1.0, the
exponent is applied and used to warp the u, v, x, and z values.
----------------------------------------------------------------------
Segment of original HField_Normal() code (for smoothed normals):
x = stretch(x);
z = stretch(z);
u = (1.0 - x);
v = (1.0 - z);
Result[X] = v*(u*n[0][X] + x*n[1][X]) + z*(u*n[2][X] + x*n[3][X]);
Result[Y] = v*(u*n[0][Y] + x*n[1][Y]) + z*(u*n[2][Y] + x*n[3][Y]);
Result[Z] = v*(u*n[0][Z] + x*n[1][Z]) + z*(u*n[2][Z] + x*n[3][Z]);
Segment of proposed new code:
x = stretch(x);
z = stretch(z);
u = (1.0 - x);
v = (1.0 - z);
/*
smooth_exponent is a part of the height field structure itself,
and div should be declared in the beginning of this function.
Some error checking may be required when calling the pow()
function, since it could cause numerical underflow or overflow.
*/
if(smooth_exponent==1.0) {
Result[X] = v*(u*n[0][X] + x*n[1][X]) + z*(u*n[2][X] +
x*n[3][X]);
Result[Y] = v*(u*n[0][Y] + x*n[1][Y]) + z*(u*n[2][Y] +
x*n[3][Y]);
Result[Z] = v*(u*n[0][Z] + x*n[1][Z]) + z*(u*n[2][Z] +
x*n[3][Z]);
}
else {
x=pow(x,smooth_exponent);
z=pow(z,smooth_exponent);
u=pow(u,smooth_exponent);
v=pow(v,smooth_exponent);
div=(x+u)*(z+v);
Result[X] = (v*(u*n[0][X] + x*n[1][X]) + z*(u*n[2][X] +
x*n[3][X]))/div;
Result[Y] = (v*(u*n[0][Y] + x*n[1][Y]) + z*(u*n[2][Y] +
x*n[3][Y]))/div;
Result[Z] = (v*(u*n[0][Z] + x*n[1][Z]) + z*(u*n[2][Z] +
x*n[3][Z]))/div;
}
----------------------------------------------------------------------
A higher exponent causes the x and u values, and z and v, to diverge
farther from each other, thus biasing the result to favor the corners
more heavily. Since the normal will now be seen as if it was further
toward the edge, the triangle will have a much more rounded appearance.
Naturally, a lower exponent will have the opposite effect, converging
the values toward each other, and thus away from the corners. A low
smoothing value should cause a semi-faceted look, with smooth edges
but a flat center.
Zero should produce a very flat surface--but interestingly, it will
remove the two-triangle appearance caused by no smoothing at all.
Bizarre effects could come of using negative values, because the
normals for all the corners will be effectively swapped.
Lummox JR
Post a reply to this message
|
|