mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 02:15:43 -04:00
commit ambient occlusion for terrain
This commit is contained in:
parent
58124af9f5
commit
feaac60df4
@ -1,7 +1,5 @@
|
||||
// Filename: geoMipTerrain.I
|
||||
// Created by: pro-rsoft (29jun07)
|
||||
// Modified by: CMU ETC Summer 2010 team (03aug10) (added getters
|
||||
// for _auto_flatten, _near, _far).
|
||||
// Created by: rdb (29Jun07)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
@ -52,7 +50,7 @@ GeoMipTerrain(const string &name) {
|
||||
// call remove_node() prior to destruction.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE GeoMipTerrain::
|
||||
~GeoMipTerrain() {
|
||||
~GeoMipTerrain() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -364,7 +362,7 @@ get_near() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GeoMipTerrain::get_flatten_mode
|
||||
// Access: Published
|
||||
// Description: Returns the automatic-flatten mode (e.g., off,
|
||||
// Description: Returns the automatic-flatten mode (e.g., off,
|
||||
// flatten_light, flatten_medium, or flatten_strong)
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int GeoMipTerrain::
|
||||
@ -420,7 +418,7 @@ get_block_from_pos(double x, double y) {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE unsigned short GeoMipTerrain::
|
||||
lod_decide(unsigned short mx, unsigned short my) {
|
||||
float cx = mx;
|
||||
float cx = mx;
|
||||
float cy = my;
|
||||
cx = (cx * _block_size + _block_size / 2) * _root.get_sx();
|
||||
cy = (cy * _block_size + _block_size / 2) * _root.get_sy();
|
||||
@ -520,7 +518,7 @@ set_color_map(const string &path) {
|
||||
// Description: Returns whether a color map has been set.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool GeoMipTerrain::
|
||||
has_color_map() {
|
||||
has_color_map() const {
|
||||
return _has_color_map;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Filename: geoMipTerrain.cxx
|
||||
// Created by: pro-rsoft (29jun07)
|
||||
// Created by: rdb (29Jun07)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
@ -45,13 +45,13 @@ PT(GeomNode) GeoMipTerrain::
|
||||
generate_block(unsigned short mx,
|
||||
unsigned short my,
|
||||
unsigned short level) {
|
||||
|
||||
|
||||
nassertr(mx < (_xsize - 1) / _block_size, NULL);
|
||||
nassertr(my < (_ysize - 1) / _block_size, NULL);
|
||||
|
||||
unsigned short center = _block_size / 2;
|
||||
unsigned int vcounter = 0;
|
||||
|
||||
|
||||
// Create the format
|
||||
PT(GeomVertexArrayFormat) array = new GeomVertexArrayFormat();
|
||||
if (_has_color_map) {
|
||||
@ -73,7 +73,7 @@ generate_block(unsigned short mx,
|
||||
vdata->unclean_set_num_rows((_block_size + 1) * (_block_size + 1));
|
||||
GeomVertexWriter cwriter;
|
||||
if (_has_color_map) {
|
||||
cwriter=GeomVertexWriter(vdata, "color" );
|
||||
cwriter = GeomVertexWriter(vdata, "color");
|
||||
}
|
||||
GeomVertexWriter vwriter (vdata, "vertex" );
|
||||
GeomVertexWriter twriter (vdata, "texcoord");
|
||||
@ -90,7 +90,7 @@ generate_block(unsigned short mx,
|
||||
level = min(max(_min_level, level), _max_level);
|
||||
unsigned short reallevel = level;
|
||||
level = int(pow(2.0, int(level)));
|
||||
|
||||
|
||||
// Neighbor levels and junctions
|
||||
unsigned short lnlevel = get_neighbor_level(mx, my, -1, 0);
|
||||
unsigned short rnlevel = get_neighbor_level(mx, my, 1, 0);
|
||||
@ -100,7 +100,7 @@ generate_block(unsigned short mx,
|
||||
bool rjunction = (rnlevel != reallevel);
|
||||
bool bjunction = (bnlevel != reallevel);
|
||||
bool tjunction = (tnlevel != reallevel);
|
||||
|
||||
|
||||
// Confusing note:
|
||||
// the variable level contains not the actual level as described
|
||||
// in the GeoMipMapping paper. That is stored in reallevel,
|
||||
@ -108,7 +108,7 @@ generate_block(unsigned short mx,
|
||||
|
||||
// This is the number of vertices at the certain level.
|
||||
unsigned short lowblocksize = _block_size / level + 1;
|
||||
|
||||
|
||||
for (int x = 0; x <= _block_size; x++) {
|
||||
for (int y = 0; y <= _block_size; y++) {
|
||||
if ((x % level) == 0 && (y % level) == 0) {
|
||||
@ -245,14 +245,14 @@ generate_block(unsigned short mx,
|
||||
PT(Geom) geom = new Geom(vdata);
|
||||
geom->add_primitive(prim);
|
||||
geom->set_bounds_type(BoundingVolume::BT_box);
|
||||
|
||||
|
||||
ostringstream sname;
|
||||
sname << "gmm" << mx << "x" << my;
|
||||
PT(GeomNode) node = new GeomNode(sname.str());
|
||||
node->add_geom(geom);
|
||||
node->set_bounds_type(BoundingVolume::BT_box);
|
||||
_old_levels.at(mx).at(my) = reallevel;
|
||||
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
@ -262,7 +262,7 @@ generate_block(unsigned short mx,
|
||||
// Description: Fetches the elevation at (x, y), where the input
|
||||
// coordinate is specified in pixels. This ignores
|
||||
// the current LOD level and instead provides an
|
||||
// accurate number. Linear blending is used for
|
||||
// accurate number. Linear blending is used for
|
||||
// non-integral coordinates.
|
||||
// Terrain scale is NOT taken into account! To get
|
||||
// accurate normals, please multiply this with the
|
||||
@ -355,12 +355,46 @@ make_slope_image() {
|
||||
normal.get_y() / _root.get_sy(),
|
||||
normal.get_z() / _root.get_sz());
|
||||
normal.normalize();
|
||||
result.set_gray(x, y, normal.angle_deg(LVector3f::up()) / 90.0);
|
||||
result.set_xel(x, y, normal.angle_deg(LVector3f::up()) / 90.0);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GeoMipTerrain::calc_ambient_occlusion
|
||||
// Access: Published
|
||||
// Description: Calculates an approximate for the ambient occlusion
|
||||
// and stores it in the color map, so that it will be
|
||||
// written to the vertex colors. Any existing color
|
||||
// map will be discarded.
|
||||
// You need to call this before generating the geometry.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GeoMipTerrain::
|
||||
calc_ambient_occlusion(float radius, float contrast, float brightness) {
|
||||
_color_map = PNMImage(_xsize, _ysize);
|
||||
_color_map.make_grayscale();
|
||||
_color_map.set_maxval(_heightfield.get_maxval());
|
||||
|
||||
for (unsigned int x = 0; x < _xsize; ++x) {
|
||||
for (unsigned int y = 0; y < _ysize; ++y) {
|
||||
_color_map.set_xel(x, _ysize - y - 1, get_pixel_value(x, y));
|
||||
}
|
||||
}
|
||||
|
||||
// We use the cheap old method of subtracting a blurred version
|
||||
// of the heightmap from the heightmap, and using that as lightmap.
|
||||
_color_map.gaussian_filter(radius);
|
||||
|
||||
for (unsigned int x = 0; x < _xsize; ++x) {
|
||||
for (unsigned int y = 0; y < _ysize; ++y) {
|
||||
_color_map.set_xel(x, y, (get_pixel_value(x, _ysize - y - 1) - _color_map.get_gray(x, y)) * contrast + brightness);
|
||||
}
|
||||
}
|
||||
|
||||
_has_color_map = true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GeoMipTerrain::generate
|
||||
// Access: Published
|
||||
@ -480,7 +514,7 @@ update() {
|
||||
// However, if we call flatten_strong on the root,
|
||||
// then the root will contain unpredictable stuff.
|
||||
// This function returns true if the root has been
|
||||
// flattened, and therefore, does not contain the
|
||||
// flattened, and therefore, does not contain the
|
||||
// terrain blocks.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool GeoMipTerrain::
|
||||
@ -488,12 +522,12 @@ root_flattened() {
|
||||
if (_root_flattened) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// The following code is error-checking code. It actually verifies
|
||||
// that the terrain blocks are underneath the root, and that nothing
|
||||
// else is underneath the root. It is not very efficient, and should
|
||||
// eventually be removed once we're sure everything works.
|
||||
|
||||
|
||||
int total = 0;
|
||||
unsigned int xsize = _blocks.size();
|
||||
for (unsigned int tx = 0; tx < xsize; tx++) {
|
||||
@ -510,7 +544,7 @@ root_flattened() {
|
||||
grutil_cat.error() << "GeoMipTerrain: root node unexpectedly mangled: " << total << " vs " << (_root.node()->get_num_children()) << "\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// The default.
|
||||
return false;
|
||||
}
|
||||
@ -525,21 +559,21 @@ auto_flatten() {
|
||||
if (_auto_flatten == AFM_off) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Creating a backup node causes the SceneGraphReducer
|
||||
// to operate in a nondestructive manner. This protects
|
||||
// the terrain blocks themselves from the flattener.
|
||||
|
||||
NodePath np("Backup Node");
|
||||
np.node()->copy_children(_root.node());
|
||||
|
||||
|
||||
// Check if the root's children have changed unexpectedly.
|
||||
switch(_auto_flatten) {
|
||||
case AFM_light: _root.flatten_light(); break;
|
||||
case AFM_medium: _root.flatten_medium(); break;
|
||||
case AFM_strong: _root.flatten_strong(); break;
|
||||
}
|
||||
|
||||
|
||||
_root_flattened = true;
|
||||
}
|
||||
|
||||
@ -619,13 +653,13 @@ set_heightfield(const Filename &filename, PNMFileType *ftype) {
|
||||
if (imgheader.read_header(filename, ftype)) {
|
||||
// Copy over the header to the heightfield image.
|
||||
_heightfield.copy_header_from(imgheader);
|
||||
|
||||
|
||||
if(!is_power_of_two(imgheader.get_x_size() - 1) || !is_power_of_two(imgheader.get_y_size() - 1)) {
|
||||
// Calculate the nearest power-of-two-plus-one size.
|
||||
unsigned int reqx, reqy;
|
||||
reqx = max(3, (int) pow(2.0, ceil(log((double) max(2, imgheader.get_x_size() - 1)) / log(2.0))) + 1);
|
||||
reqy = max(3, (int) pow(2.0, ceil(log((double) max(2, imgheader.get_y_size() - 1)) / log(2.0))) + 1);
|
||||
|
||||
|
||||
// If it's not a valid size, tell PNMImage to resize it.
|
||||
if (reqx != (unsigned int)imgheader.get_x_size() || reqy != (unsigned int)imgheader.get_y_size()) {
|
||||
grutil_cat.warning()
|
||||
@ -635,14 +669,14 @@ set_heightfield(const Filename &filename, PNMFileType *ftype) {
|
||||
_heightfield.set_read_size(reqx, reqy);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Read the real image now
|
||||
if (!_heightfield.read(filename, ftype)) {
|
||||
_heightfield.clear_read_size();
|
||||
grutil_cat.error() << "Failed to read heightfield image " << filename << "!\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
_is_dirty = true;
|
||||
_xsize = _heightfield.get_x_size();
|
||||
_ysize = _heightfield.get_y_size();
|
||||
|
@ -1,7 +1,5 @@
|
||||
// Filename: geoMipTerrain.h
|
||||
// Created by: pro-rsoft (29jun07)
|
||||
// Modified by: CMU ETC Summer 2010 team (03aug10) (added
|
||||
// get_flatten_mode(), get_near(), get_far() ).
|
||||
// Created by: rdb (29Jun07)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
@ -43,7 +41,7 @@ class EXPCL_PANDA_GRUTIL GeoMipTerrain : public TypedObject {
|
||||
PUBLISHED:
|
||||
INLINE GeoMipTerrain(const string &name);
|
||||
INLINE ~GeoMipTerrain();
|
||||
|
||||
|
||||
INLINE PNMImage &heightfield();
|
||||
bool set_heightfield(const Filename &filename, PNMFileType *type = NULL);
|
||||
INLINE bool set_heightfield(const PNMImage &image);
|
||||
@ -54,15 +52,16 @@ PUBLISHED:
|
||||
INLINE bool set_color_map(const PNMImage &image);
|
||||
INLINE bool set_color_map(const Texture *image);
|
||||
INLINE bool set_color_map(const string &path);
|
||||
INLINE bool has_color_map();
|
||||
INLINE bool has_color_map() const;
|
||||
INLINE void clear_color_map();
|
||||
void calc_ambient_occlusion(float radius = 32, float contrast = 2.0f, float brightness = 0.75f);
|
||||
double get_elevation(double x, double y);
|
||||
LVector3f get_normal(int x, int y);
|
||||
INLINE LVector3f get_normal(unsigned short mx, unsigned short my,
|
||||
INLINE LVector3f get_normal(unsigned short mx, unsigned short my,
|
||||
int x,int y);
|
||||
INLINE void set_bruteforce(bool bf);
|
||||
INLINE bool get_bruteforce();
|
||||
|
||||
|
||||
// The flatten mode specifies whether the terrain nodes are flattened
|
||||
// together after each terrain update.
|
||||
enum AutoFlattenMode {
|
||||
@ -75,9 +74,9 @@ PUBLISHED:
|
||||
// FM_strong: the terrain is flattened using flatten_strong.
|
||||
AFM_strong = 3,
|
||||
};
|
||||
|
||||
|
||||
INLINE void set_auto_flatten(int mode);
|
||||
|
||||
|
||||
// The focal point is the point at which the terrain will have the
|
||||
// highest quality (lowest level of detail). Parts farther away from
|
||||
// the focal point will have a lower quality (higher level of detail).
|
||||
@ -90,7 +89,7 @@ PUBLISHED:
|
||||
INLINE void set_focal_point(NodePath fnp);
|
||||
INLINE NodePath get_focal_point() const;
|
||||
INLINE NodePath get_root() const;
|
||||
|
||||
|
||||
INLINE void set_block_size(unsigned short newbs);
|
||||
INLINE unsigned short get_block_size();
|
||||
INLINE unsigned short get_max_level();
|
||||
@ -113,16 +112,16 @@ PUBLISHED:
|
||||
PNMImage make_slope_image();
|
||||
void generate();
|
||||
bool update();
|
||||
|
||||
|
||||
private:
|
||||
|
||||
|
||||
PT(GeomNode) generate_block(unsigned short mx, unsigned short my, unsigned short level);
|
||||
bool update_block(unsigned short mx, unsigned short my,
|
||||
signed short level = -1, bool forced = false);
|
||||
void calc_levels();
|
||||
void auto_flatten();
|
||||
bool root_flattened();
|
||||
|
||||
|
||||
INLINE bool is_power_of_two(unsigned int i);
|
||||
INLINE float f_part(float i);
|
||||
INLINE double f_part(double i);
|
||||
@ -131,7 +130,7 @@ private:
|
||||
INLINE double get_pixel_value(unsigned short mx, unsigned short my, int x, int y);
|
||||
INLINE unsigned short lod_decide(unsigned short mx, unsigned short my);
|
||||
unsigned short get_neighbor_level(unsigned short mx, unsigned short my, short dmx, short dmy);
|
||||
|
||||
|
||||
NodePath _root;
|
||||
int _auto_flatten;
|
||||
bool _root_flattened;
|
||||
@ -155,7 +154,7 @@ private:
|
||||
pvector<pvector<NodePath> > _blocks;
|
||||
pvector<pvector<unsigned short> > _levels;
|
||||
pvector<pvector<unsigned short> > _old_levels;
|
||||
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
|
Loading…
x
Reference in New Issue
Block a user